# HG changeset patch # User chegar # Date 1336729322 -3600 # Node ID a1985f14b03009e376e5b8341f8b097112be8b0f Initial load diff -r 000000000000 -r a1985f14b030 ASSEMBLY_EXCEPTION --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ASSEMBLY_EXCEPTION Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,27 @@ + +OPENJDK ASSEMBLY EXCEPTION + +The OpenJDK source code made available by Sun at openjdk.java.net and +openjdk.dev.java.net ("OpenJDK Code") is distributed under the terms of the +GNU General Public License version 2 +only ("GPL2"), with the following clarification and special exception. + + Linking this OpenJDK Code statically or dynamically with other code + is making a combined work based on this library. Thus, the terms + and conditions of GPL2 cover the whole combination. + + As a special exception, Sun gives you permission to link this + OpenJDK Code with certain code licensed by Sun as indicated at + http://openjdk.java.net/legal/exception-modules-2007-05-08.html + ("Designated Exception Modules") to produce an executable, + regardless of the license terms of the Designated Exception Modules, + and to copy and distribute the resulting executable under GPL2, + provided that the Designated Exception Modules continue to be + governed by the licenses under which they were offered by Sun. + +As such, it allows licensees and sublicensees of Sun's GPL2 OpenJDK Code to +build an executable that includes those portions of necessary code that Sun +could not provide under GPL2 (or that Sun has provided under GPL2 with the +Classpath exception). If you modify or add to the OpenJDK code, that new +GPL2 code may still be combined with Designated Exception Modules if the +new code is made subject to this exception by its copyright holder. diff -r 000000000000 -r a1985f14b030 LICENSE --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/LICENSE Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,347 @@ +The GNU General Public License (GPL) + +Version 2, June 1991 + +Copyright (C) 1989, 1991 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. + +Preamble + +The licenses for most software are designed to take away your freedom to share +and change it. By contrast, the GNU General Public License is intended to +guarantee your freedom to share and change free software--to make sure the +software is free for all its users. This General Public License applies to +most of the Free Software Foundation's software and to any other program whose +authors commit to using it. (Some other Free Software Foundation software is +covered by the GNU Library General Public License instead.) You can apply it to +your programs, too. + +When we speak of free software, we are referring to freedom, 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 or use pieces of it in new free programs; and that you know you +can do these things. + +To protect your rights, we need to make restrictions that forbid anyone to deny +you these rights or to ask you to surrender the rights. These restrictions +translate to certain responsibilities for you if you distribute copies of the +software, or if you modify it. + +For example, if you distribute copies of such a program, whether gratis or for +a fee, you must give the recipients all the rights that you have. You must +make sure that they, too, receive or can get the source code. And you must +show them these terms so they know their rights. + +We protect your rights with two steps: (1) copyright the software, and (2) +offer you this license which gives you legal permission to copy, distribute +and/or modify the software. + +Also, for each author's protection and ours, we want to make certain that +everyone understands that there is no warranty for this free software. If the +software is modified by someone else and passed on, we want its recipients to +know that what they have is not the original, so that any problems introduced +by others will not reflect on the original authors' reputations. + +Finally, any free program is threatened constantly by software patents. We +wish to avoid the danger that redistributors of a free program will +individually obtain patent licenses, in effect making the program proprietary. +To prevent this, we have made it clear that any patent must be licensed for +everyone's free use or not licensed at all. + +The precise terms and conditions for copying, distribution and modification +follow. + +TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + +0. This License applies to any program or other work which contains a notice +placed by the copyright holder saying it may be distributed under the terms of +this General Public License. The "Program", below, refers to any such program +or work, and a "work based on the Program" means either the Program or any +derivative work under copyright law: that is to say, a work containing the +Program or a portion of it, either verbatim or with modifications and/or +translated into another language. (Hereinafter, translation is included +without limitation in the term "modification".) Each licensee is addressed as +"you". + +Activities other than copying, distribution and modification are not covered by +this License; they are outside its scope. The act of running the Program is +not restricted, and the output from the Program is covered only if its contents +constitute a work based on the Program (independent of having been made by +running the Program). Whether that is true depends on what the Program does. + +1. You may copy and distribute verbatim copies of the Program's 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 give any other recipients of the +Program a copy of this License along with the Program. + +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. + +2. You may modify your copy or copies of the Program or any portion of it, thus +forming a work based on the Program, 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) You must cause the modified files to carry prominent notices stating + that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in whole or + in part contains or is derived from the Program or any part thereof, to be + licensed as a whole at no charge to all third parties under the terms of + this License. + + c) If the modified program normally reads commands interactively when run, + you must cause it, when started running for such interactive use in the + most ordinary way, to print or display an announcement including an + appropriate copyright notice and a notice that there is no warranty (or + else, saying that you provide a warranty) and that users may redistribute + the program under these conditions, and telling the user how to view a copy + of this License. (Exception: if the Program itself is interactive but does + not normally print such an announcement, your work based on the Program is + not required to print an announcement.) + +These requirements apply to the modified work as a whole. If identifiable +sections of that work are not derived from the Program, 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 Program, 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 Program. + +In addition, mere aggregation of another work not based on the Program with the +Program (or with a work based on the Program) on a volume of a storage or +distribution medium does not bring the other work under the scope of this +License. + +3. You may copy and distribute the Program (or a work based on it, under +Section 2) in object code or executable form under the terms of Sections 1 and +2 above provided that you also do one of the following: + + a) 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; or, + + b) Accompany it with a written offer, valid for at least three years, to + give any third party, for a charge no more than your cost of physically + performing source distribution, a complete machine-readable copy of the + corresponding source code, to be distributed under the terms of Sections 1 + and 2 above on a medium customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer to + distribute corresponding source code. (This alternative is allowed only + for noncommercial distribution and only if you received the program in + object code or executable form with such an offer, in accord with + Subsection b above.) + +The source code for a work means the preferred form of the work for making +modifications to it. For an executable work, 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 executable. However, as a special exception, the source code +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. + +If distribution of executable or 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 counts as distribution of the source code, even though +third parties are not compelled to copy the source along with the object code. + +4. You may not copy, modify, sublicense, or distribute the Program except as +expressly provided under this License. Any attempt otherwise to copy, modify, +sublicense or distribute the Program 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. + +5. 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 Program +or its derivative works. These actions are prohibited by law if you do not +accept this License. Therefore, by modifying or distributing the Program (or +any work based on the Program), you indicate your acceptance of this License to +do so, and all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + +6. Each time you redistribute the Program (or any work based on the Program), +the recipient automatically receives a license from the original licensor to +copy, distribute or modify the Program 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 to this License. + +7. 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 Program at all. +For example, if a patent license would not permit royalty-free redistribution +of the Program 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 Program. + +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. + +8. If the distribution and/or use of the Program is restricted in certain +countries either by patents or by copyrighted interfaces, the original +copyright holder who places the Program 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. + +9. The Free Software Foundation may publish revised and/or new versions of the +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 Program +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 Program does not specify a version number of this License, you may +choose any version ever published by the Free Software Foundation. + +10. If you wish to incorporate parts of the Program into other free programs +whose distribution conditions are different, 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 + +11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR +THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE +STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE +PROGRAM "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 PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, +YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + +12. 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 +PROGRAM 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 PROGRAM (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 PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER +OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + +END OF TERMS AND CONDITIONS + +How to Apply These Terms to Your New Programs + +If you develop a new program, and you want it to be of the greatest possible +use to the public, the best way to achieve this is to make it free software +which everyone can redistribute and change under these terms. + +To do so, attach the following notices to the program. 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 program's name and a brief idea of what it does. + + Copyright (C) + + This program is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by the Free + Software Foundation; either version 2 of the License, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, Inc., 59 + Temple Place, Suite 330, Boston, MA 02111-1307 USA + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this when it +starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author Gnomovision comes + with ABSOLUTELY NO WARRANTY; for details type 'show w'. This is free + software, and you are welcome to redistribute it under certain conditions; + type 'show c' for details. + +The hypothetical commands 'show w' and 'show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may be +called something other than 'show w' and 'show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your school, +if any, to sign a "copyright disclaimer" for the program, if necessary. Here +is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + 'Gnomovision' (which makes passes at compilers) written by James Hacker. + + signature of Ty Coon, 1 April 1989 + + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General Public +License instead of this License. + + +"CLASSPATH" EXCEPTION TO THE GPL + +Certain source files distributed by Oracle America and/or its affiliates are +subject to the following clarification and special exception to the GPL, but +only where Oracle has expressly included in the particular source file's header +the words "Oracle designates this particular file as subject to the "Classpath" +exception as provided by Oracle in the LICENSE file that accompanied this code." + + Linking this library statically or dynamically with other modules is making + a combined work based on this library. Thus, the terms and conditions of + the GNU General Public License cover the whole combination. + + As a special exception, the copyright holders of this library give you + permission to link this library with independent modules to produce an + executable, regardless of the license terms of these independent modules, + and to copy and distribute the resulting executable under terms of your + choice, provided that you also meet, for each linked independent module, + the terms and conditions of the license of that module. An independent + module is a module which is not derived from or based on this library. If + you modify this library, you may extend this exception to your version of + the library, but you are not obligated to do so. If you do not wish to do + so, delete this exception statement from your version. diff -r 000000000000 -r a1985f14b030 README --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/README Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,16 @@ +Berkeley DB 11g Release 2, library version 11.2.5.4.0: (May 7, 2012) + +This file should be located at the top of the bdb Mercurial repository. + +See http://openjdk.java.net/ for more information about the OpenJDK. + +See ../README-builds.html for complete details on build machine requirements. + +Simple Build Instructions: + + cd make && gnumake + +The files that will be imported into the jdk build will be in the "import" +directory. + + diff -r 000000000000 -r a1985f14b030 THIRD_PARTY_README --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/THIRD_PARTY_README Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,3385 @@ +DO NOT TRANSLATE OR LOCALIZE. +----------------------------- + +%% This notice is provided with respect to ASM Bytecode Manipulation +Framework v3.1, which is included with JRE 7, JDK 7, and OpenJDK 7. + +--- begin of LICENSE --- + +Copyright (c) 2000-2005 INRIA, France Telecom +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + +3. Neither the name of the copyright holders nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF +THE POSSIBILITY OF SUCH DAMAGE. + +--- end of LICENSE --- + +-------------------------------------------------------------------------------- + +%% This notice is provided with respect to CodeViewer 1.0, which is included +with JDK 7. + +--- begin of LICENSE --- + +Copyright 1999 by CoolServlets.com. + +Any errors or suggested improvements to this class can be reported as +instructed on CoolServlets.com. We hope you enjoy this program... your +comments will encourage further development! This software is distributed +under the terms of the BSD License. Redistribution and use in source and +binary forms, with or without modification, are permitted provided that the +following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +Neither name of CoolServlets.com nor the names of its contributors may be +used to endorse or promote products derived from this software without +specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY COOLSERVLETS.COM AND CONTRIBUTORS ``AS IS'' AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." + + +--- end of LICENSE --- + +------------------------------------------------------------------------------- + +%% This notice is provided with respect to Cryptix AES 3.2.0, which is +included with JRE 7, JDK 7, and OpenJDK 7. + +--- begin of LICENSE --- + +Cryptix General License + +Copyright (c) 1995-2005 The Cryptix Foundation Limited. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + 1. Redistributions of source code must retain the copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + +THIS SOFTWARE IS PROVIDED BY THE CRYPTIX FOUNDATION LIMITED AND +CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE CRYPTIX FOUNDATION LIMITED OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE +OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN +IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +--- end of LICENSE --- + +------------------------------------------------------------------------------- + +%% This notice is provided with respect to CUP Parser Generator for +Java 0.10k, which is included with JRE 7, JDK 7, and OpenJDK 7. + +--- begin of LICENSE --- + +Copyright 1996-1999 by Scott Hudson, Frank Flannery, C. Scott Ananian + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, provided +that the above copyright notice appear in all copies and that both the +copyright notice and this permission notice and warranty disclaimer appear in +supporting documentation, and that the names of the authors or their +employers not be used in advertising or publicity pertaining to distribution of +the software without specific, written prior permission. + +The authors and their employers disclaim all warranties with regard to +this software, including all implied warranties of merchantability and fitness. +In no event shall the authors or their employers be liable for any special, +indirect or consequential damages or any damages whatsoever resulting from +loss of use, data or profits, whether in an action of contract, negligence or +other tortious action, arising out of or in connection with the use or +performance of this software. + +--- end of LICENSE --- + +------------------------------------------------------------------------------- + +%% This notice is provided with respect to Document Object Model (DOM) Level 2 +& 3, which is included with JRE 7, JDK 7, and OpenJDK 7. + +--- begin of LICENSE --- + +W3C SOFTWARE NOTICE AND LICENSE + +http://www.w3.org/Consortium/Legal/2002/copyright-software-20021231 + +This work (and included software, documentation such as READMEs, or other +related items) is being provided by the copyright holders under the following +license. By obtaining, using and/or copying this work, you (the licensee) +agree that you have read, understood, and will comply with the following terms +and conditions. + +Permission to copy, modify, and distribute this software and its +documentation, with or without modification, for any purpose and without fee +or royalty is hereby granted, provided that you include the following on ALL +copies of the software and documentation or portions thereof, including +modifications: + + 1.The full text of this NOTICE in a location viewable to users of the + redistributed or derivative work. + + 2.Any pre-existing intellectual property disclaimers, notices, or terms and + conditions. If none exist, the W3C Software Short Notice should be included + (hypertext is preferred, text is permitted) within the body of any + redistributed or derivative code. + + 3.Notice of any changes or modifications to the files, including the date + changes were made. (We recommend you provide URIs to the location from + which the code is derived.) + +THIS SOFTWARE AND DOCUMENTATION IS PROVIDED "AS IS," AND COPYRIGHT HOLDERS +MAKE NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT +LIMITED TO, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR +PURPOSE OR THAT THE USE OF THE SOFTWARE OR DOCUMENTATION WILL NOT INFRINGE ANY +THIRD PARTY PATENTS,COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS. + +COPYRIGHT HOLDERS WILL NOT BE LIABLE FOR ANY DIRECT, INDIRECT, SPECIAL +OR CONSEQUENTIAL DAMAGES ARISING OUT OF ANY USE OF THE SOFTWARE OR +DOCUMENTATION. The name and trademarks of copyright holders may NOT be used +in advertising or publicity pertaining to the software without specific, +written prior permission. Title to copyright in this software and any +associated documentation will at all times remain with copyright holders. + +____________________________________ + +This formulation of W3C's notice and license became active on December 31 +2002. This version removes the copyright ownership notice such that this +license can be used with materials other than those owned by the W3C, reflects +that ERCIM is now a host of the W3C, includes references to this specific +dated version of the license, and removes the ambiguous grant of "use". +Otherwise, this version is the same as the previous version and is written so +as to preserve the Free Software Foundation's assessment of GPL compatibility +and OSI's certification under the Open Source Definition. Please see our +Copyright FAQ for common questions about using materials from our site, +including specific terms and conditions for packages like libwww, Amaya, and +Jigsaw. Other questions about this notice can be directed to +site-policy@w3.org. + +--- end of LICENSE --- + +------------------------------------------------------------------------------- + +%% This notice is provided with respect to Elliptic Curve Cryptography, which +is included with JRE 7, JDK 7, and OpenJDK 7. + +You are receiving a copy of the Elliptic Curve Cryptography library in source +form with the JDK 7 source distribution and object code in the JRE 7 & JDK 7 +runtime. + +The terms of the Oracle license do NOT apply to the Elliptic Curve +Cryptography library program; it is licensed under the following license, +separately from the Oracle programs you receive. If you do not wish to install +this program, you may delete the library named libsunec.so (on Solaris and +Linux systems) or sunec.dll (on Windows systems) from the JRE bin directory +reserved for native libraries. + +--- begin of LICENSE --- + + GNU LESSER GENERAL PUBLIC LICENSE + Version 2.1, February 1999 + + Copyright (C) 1991, 1999 Free Software Foundation, Inc. + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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. + + 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. + + 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. + + 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. + + 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. + + 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. + + 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. + + 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. + + 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 + + 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. + + + Copyright (C) + + 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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. + + , 1 April 1990 + Ty Coon, President of Vice + +That's all there is to it! + +--- end of LICENSE --- + +------------------------------------------------------------------------------- + +%% This notice is provided with respect to FontConfig 2.5, which is +included with JRE 7, JDK 7, and OpenJDK 7 source distributions on +Linux and Solaris. + +--- begin of LICENSE --- + +Copyright ¬© 2001,2003 Keith Packard + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that the +above copyright notice appear in all copies and that both that copyright +notice and this permission notice appear in supporting documentation, and that +the name of Keith Packard not be used in advertising or publicity pertaining +to distribution of the software without specific, written prior permission. +Keith Packard makes no representations about the suitability of this software +for any purpose. It is provided "as is" without express or implied warranty. + +KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING +ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL KEITH +PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY +DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN +CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + + +--- end of LICENSE --- + +------------------------------------------------------------------------------- + +%% This notice is provided with respect to IAIK PKCS#11 Wrapper, +which is included with JRE 7, JDK 7, and OpenJDK 7. + +--- begin of LICENSE --- + +IAIK PKCS#11 Wrapper License + +Copyright (c) 2002 Graz University of Technology. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +3. The end-user documentation included with the redistribution, if any, must + include the following acknowledgment: + + "This product includes software developed by IAIK of Graz University of + Technology." + + Alternately, this acknowledgment may appear in the software itself, if and + wherever such third-party acknowledgments normally appear. + +4. The names "Graz University of Technology" and "IAIK of Graz University of + Technology" must not be used to endorse or promote products derived from this + software without prior written permission. + +5. Products derived from this software may not be called "IAIK PKCS Wrapper", + nor may "IAIK" appear in their name, without prior written permission of + Graz University of Technology. + +THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE +LICENSOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, +OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. + +--- end of LICENSE --- + +------------------------------------------------------------------------------- + +%% This notice is provided with respect to ICU4C 4.0.1 and ICU4J 4.4, which +is included with JRE 7, JDK 7, and OpenJDK 7. + +--- begin of LICENSE --- + +Copyright (c) 1995-2010 International Business Machines Corporation and others + +All rights reserved. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, and/or sell copies of the +Software, and to permit persons to whom the Software is furnished to do so, +provided that the above copyright notice(s) and this permission notice appear +in all copies of the Software and that both the above copyright notice(s) and +this permission notice appear in supporting documentation. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. IN +NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN THIS NOTICE BE +LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY +DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN +CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +Except as contained in this notice, the name of a copyright holder shall not +be used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization of the copyright holder. +All trademarks and registered trademarks mentioned herein are the property of +their respective owners. + +--- end of LICENSE --- + +------------------------------------------------------------------------------- + +%% This notice is provided with respect to IJG JPEG 6b, which is +included with JRE 7, JDK 7, and OpenJDK 7. + +--- begin of LICENSE --- + +This software is copyright (C) 1991-1998, Thomas G. Lane. +All Rights Reserved except as specified below. + +Permission is hereby granted to use, copy, modify, and distribute this +software (or portions thereof) for any purpose, without fee, subject to these +conditions: +(1) If any part of the source code for this software is distributed, then this +README file must be included, with this copyright and no-warranty notice +unaltered; and any additions, deletions, or changes to the original files +must be clearly indicated in accompanying documentation. +(2) If only executable code is distributed, then the accompanying +documentation must state that "this software is based in part on the work of +the Independent JPEG Group". +(3) Permission for use of this software is granted only if the user accepts +full responsibility for any undesirable consequences; the authors accept +NO LIABILITY for damages of any kind. + +These conditions apply to any software derived from or based on the IJG code, +not just to the unmodified library. If you use our work, you ought to +acknowledge us. + +Permission is NOT granted for the use of any IJG author's name or company name +in advertising or publicity relating to this software or products derived from +it. This software may be referred to only as "the Independent JPEG Group's +software". + +We specifically permit and encourage the use of this software as the basis of +commercial products, provided that all warranty or liability claims are +assumed by the product vendor. + +--- end of LICENSE --- + +-------------------------------------------------------------------------------- + +%% This notice is provided with respect to JOpt-Simple v3.0, which is +included with JRE 7, JDK 7, and OpenJDK 7. + +--- begin of LICENSE --- + + Copyright (c) 2004-2009 Paul R. Holser, Jr. + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--- end of LICENSE --- + +-------------------------------------------------------------------------------- + +%% This notice is provided with respect to Kerberos functionality, which +which is included with JRE 7, JDK 7, and OpenJDK 7. + +--- begin of LICENSE --- + + (C) Copyright IBM Corp. 1999 All Rights Reserved. + Copyright 1997 The Open Group Research Institute. All rights reserved. + +--- end of LICENSE --- + +------------------------------------------------------------------------------- + +%% This notice is provided with respect to Kerberos functionality from +FundsXpress, INC., which is included with JRE 7, JDK 7, and OpenJDK 7. + +--- begin of LICENSE --- + + Copyright (C) 1998 by the FundsXpress, INC. + + All rights reserved. + + Export of this software from the United States of America may require + a specific license from the United States Government. It is the + responsibility of any person or organization contemplating export to + obtain such a license before exporting. + + WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + distribute this software and its documentation for any purpose and + without fee is hereby granted, provided that the above copyright + notice appear in all copies and that both that copyright notice and + this permission notice appear in supporting documentation, and that + the name of FundsXpress. not be used in advertising or publicity pertaining + to distribution of the software without specific, written prior + permission. FundsXpress makes no representations about the suitability of + this software for any purpose. It is provided "as is" without express + or implied warranty. + + THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR + IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED + WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. + + +--- end of LICENSE --- + +------------------------------------------------------------------------------- + +%% This notice is provided with respect to Kronos OpenGL headers, which is +included with JDK 7 and OpenJDK 7 source distributions. + +--- begin of LICENSE --- + + Copyright (c) 2007 The Khronos Group Inc. + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and/or associated documentation files (the "Materials"), to + deal in the Materials without restriction, including without limitation the + rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + sell copies of the Materials, and to permit persons to whom the Materials are + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Materials. + + THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE USE OR OTHER DEALINGS IN THE + MATERIALS. + +--- end of LICENSE --- + +------------------------------------------------------------------------------- + +%% Portions Copyright Eastman Kodak Company 1992 + +------------------------------------------------------------------------------- + +%% This notice is provided with respect to libpng 1.2.18, which is +included with JRE 7, JDK 7, and OpenJDK 7. + +--- begin of LICENSE --- + +This copy of the libpng notices is provided for your convenience. In case of +any discrepancy between this copy and the notices in the file png.h that is +included in the libpng distribution, the latter shall prevail. + +COPYRIGHT NOTICE, DISCLAIMER, and LICENSE: + +If you modify libpng you may insert additional notices immediately following +this sentence. + +libpng versions 1.2.6, August 15, 2004, through 1.2.18, May 15, 2007, are +Copyright (c) 2004, 2006-2007 Glenn Randers-Pehrson, and are +distributed according to the same disclaimer and license as libpng-1.2.5 +with the following individual added to the list of Contributing Authors + + Cosmin Truta + +libpng versions 1.0.7, July 1, 2000, through 1.2.5 - October 3, 2002, are +Copyright (c) 2000-2002 Glenn Randers-Pehrson, and are +distributed according to the same disclaimer and license as libpng-1.0.6 +with the following individuals added to the list of Contributing Authors + + Simon-Pierre Cadieux + Eric S. Raymond + Gilles Vollant + +and with the following additions to the disclaimer: + + There is no warranty against interference with your enjoyment of the + library or against infringement. There is no warranty that our + efforts or the library will fulfill any of your particular purposes + or needs. This library is provided with all faults, and the entire + risk of satisfactory quality, performance, accuracy, and effort is with + the user. + +libpng versions 0.97, January 1998, through 1.0.6, March 20, 2000, are +Copyright (c) 1998, 1999 Glenn Randers-Pehrson, and are +distributed according to the same disclaimer and license as libpng-0.96, +with the following individuals added to the list of Contributing Authors: + + Tom Lane + Glenn Randers-Pehrson + Willem van Schaik + +libpng versions 0.89, June 1996, through 0.96, May 1997, are +Copyright (c) 1996, 1997 Andreas Dilger +Distributed according to the same disclaimer and license as libpng-0.88, +with the following individuals added to the list of Contributing Authors: + + John Bowler + Kevin Bracey + Sam Bushell + Magnus Holmgren + Greg Roelofs + Tom Tanner + +libpng versions 0.5, May 1995, through 0.88, January 1996, are +Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc. + +For the purposes of this copyright and license, "Contributing Authors" +is defined as the following set of individuals: + + Andreas Dilger + Dave Martindale + Guy Eric Schalnat + Paul Schmidt + Tim Wegner + +The PNG Reference Library is supplied "AS IS". The Contributing Authors +and Group 42, Inc. disclaim all warranties, expressed or implied, +including, without limitation, the warranties of merchantability and of +fitness for any purpose. The Contributing Authors and Group 42, Inc. +assume no liability for direct, indirect, incidental, special, exemplary, +or consequential damages, which may result from the use of the PNG +Reference Library, even if advised of the possibility of such damage. + +Permission is hereby granted to use, copy, modify, and distribute this +source code, or portions hereof, for any purpose, without fee, subject +to the following restrictions: + +1. The origin of this source code must not be misrepresented. + +2. Altered versions must be plainly marked as such and must not + be misrepresented as being the original source. + +3. This Copyright notice may not be removed or altered from any + source or altered source distribution. + +The Contributing Authors and Group 42, Inc. specifically permit, without +fee, and encourage the use of this source code as a component to +supporting the PNG file format in commercial products. If you use this +source code in a product, acknowledgment is not required but would be +appreciated. + + +A "png_get_copyright" function is available, for convenient use in "about" +boxes and the like: + + printf("%s",png_get_copyright(NULL)); + +Also, the PNG logo (in PNG format, of course) is supplied in the +files "pngbar.png" and "pngbar.jpg (88x31) and "pngnow.png" (98x31). + +Libpng is OSI Certified Open Source Software. OSI Certified Open Source is a +certification mark of the Open Source Initiative. + +Glenn Randers-Pehrson +glennrp at users.sourceforge.net +May 15, 2007 + +--- end of LICENSE --- + +------------------------------------------------------------------------------- + +%% This notice is provided with respect to libungif 4.1.3, which is +included with JRE 7, JDK 7, and OpenJDK 7. + +--- begin of LICENSE --- + +The GIFLIB distribution is Copyright (c) 1997 Eric S. Raymond + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +--- end of LICENSE --- + +------------------------------------------------------------------------------- + +%% This notice is provided with respect to Little CMS 2.0, which is +included with OpenJDK 7. + +--- begin of LICENSE --- + +Little CMS +Copyright (c) 1998-2010 Marti Maria Saguer + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +--- end of LICENSE --- + +------------------------------------------------------------------------------- + +%% Lucida is a registered trademark or trademark of Bigelow & Holmes in the +U.S. and other countries. + +------------------------------------------------------------------------------- + +%% This notice is provided with respect to Mesa 3D Graphics Library v4.1, +which is included with JRE 7, JDK 7, and OpenJDK 7 source distributions. + +--- begin of LICENSE --- + + Mesa 3-D graphics library + Version: 4.1 + + Copyright (C) 1999-2002 Brian Paul All Rights Reserved. + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included + in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +--- end of LICENSE --- + +------------------------------------------------------------------------------- + +%% This notice is provided with respect to PC/SC Lite for Suse Linux v.1.1.1, +which is included with JRE 7, JDK 7, and OpenJDK 7 on Linux and Solaris. + +--- begin of LICENSE --- + +Copyright (c) 1999-2004 David Corcoran +Copyright (c) 1999-2004 Ludovic Rousseau +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. +3. All advertising materials mentioning features or use of this software + must display the following acknowledgement: + This product includes software developed by: + David Corcoran + http://www.linuxnet.com (MUSCLE) +4. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + +Changes to this license can be made only by the copyright author with +explicit written consent. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +--- end of LICENSE --- + +------------------------------------------------------------------------------- + +%% This notice is provided with respect to Relax NG Object/Parser v.20050510, +which is included with JRE 7, JDK 7, and OpenJDK 7. + +--- begin of LICENSE --- + +Copyright (c) Kohsuke Kawaguchi + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: The above copyright +notice and this permission notice shall be included in all copies or +substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +--- end of LICENSE --- + +------------------------------------------------------------------------------- + +%% This notice is provided with respect to RelaxNGCC v1.12, which is +included with JRE 7, JDK 7, and OpenJDK 7. + +--- begin of LICENSE --- + +Copyright (c) 2000-2003 Daisuke Okajima and Kohsuke Kawaguchi. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +3. The end-user documentation included with the redistribution, if any, must + include the following acknowledgment: + + "This product includes software developed by Daisuke Okajima + and Kohsuke Kawaguchi (http://relaxngcc.sf.net/)." + +Alternately, this acknowledgment may appear in the software itself, if and +wherever such third-party acknowledgments normally appear. + +4. The names of the copyright holders must not be used to endorse or promote + products derived from this software without prior written permission. For + written permission, please contact the copyright holders. + +5. Products derived from this software may not be called "RELAXNGCC", nor may + "RELAXNGCC" appear in their name, without prior written permission of the + copyright holders. + +THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.IN NO EVENT SHALL THE APACHE +SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING +NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, +EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +--- end of LICENSE --- + +------------------------------------------------------------------------------- + +%% This notice is provided with respect to Mozilla Rhino v1.7R3, which +is included with JRE 7, JDK 7, and OpenJDK 7 + +--- begin of LICENSE --- + + MOZILLA PUBLIC LICENSE + Version 1.1 + + --------------- + +1. Definitions. + + 1.0.1. "Commercial Use" means distribution or otherwise making the + Covered Code available to a third party. + + 1.1. "Contributor" means each entity that creates or contributes to + the creation of Modifications. + + 1.2. "Contributor Version" means the combination of the Original + Code, prior Modifications used by a Contributor, and the Modifications + made by that particular Contributor. + + 1.3. "Covered Code" means the Original Code or Modifications or the + combination of the Original Code and Modifications, in each case + including portions thereof. + + 1.4. "Electronic Distribution Mechanism" means a mechanism generally + accepted in the software development community for the electronic + transfer of data. + + 1.5. "Executable" means Covered Code in any form other than Source + Code. + + 1.6. "Initial Developer" means the individual or entity identified + as the Initial Developer in the Source Code notice required by Exhibit + A. + + 1.7. "Larger Work" means a work which combines Covered Code or + portions thereof with code not governed by the terms of this License. + + 1.8. "License" means this document. + + 1.8.1. "Licensable" means having the right to grant, to the maximum + extent possible, whether at the time of the initial grant or + subsequently acquired, any and all of the rights conveyed herein. + + 1.9. "Modifications" means any addition to or deletion from the + substance or structure of either the Original Code or any previous + Modifications. When Covered Code is released as a series of files, a + Modification is: + A. Any addition to or deletion from the contents of a file + containing Original Code or previous Modifications. + + B. Any new file that contains any part of the Original Code or + previous Modifications. + + 1.10. "Original Code" means Source Code of computer software code + which is described in the Source Code notice required by Exhibit A as + Original Code, and which, at the time of its release under this + License is not already Covered Code governed by this License. + + 1.10.1. "Patent Claims" means any patent claim(s), now owned or + hereafter acquired, including without limitation, method, process, + and apparatus claims, in any patent Licensable by grantor. + + 1.11. "Source Code" means the preferred form of the Covered Code for + making modifications to it, including all modules it contains, plus + any associated interface definition files, scripts used to control + compilation and installation of an Executable, or source code + differential comparisons against either the Original Code or another + well known, available Covered Code of the Contributor's choice. The + Source Code can be in a compressed or archival form, provided the + appropriate decompression or de-archiving software is widely available + for no charge. + + 1.12. "You" (or "Your") means an individual or a legal entity + exercising rights under, and complying with all of the terms of, this + License or a future version of this License issued under Section 6.1. + For legal entities, "You" includes any entity which controls, is + controlled by, or is under common control with You. For purposes of + this definition, "control" means (a) the power, direct or indirect, + to cause the direction or management of such entity, whether by + contract or otherwise, or (b) ownership of more than fifty percent + (50%) of the outstanding shares or beneficial ownership of such + entity. + +2. Source Code License. + + 2.1. The Initial Developer Grant. + The Initial Developer hereby grants You a world-wide, royalty-free, + non-exclusive license, subject to third party intellectual property + claims: + (a) under intellectual property rights (other than patent or + trademark) Licensable by Initial Developer to use, reproduce, + modify, display, perform, sublicense and distribute the Original + Code (or portions thereof) with or without Modifications, and/or + as part of a Larger Work; and + + (b) under Patents Claims infringed by the making, using or + selling of Original Code, to make, have made, use, practice, + sell, and offer for sale, and/or otherwise dispose of the + Original Code (or portions thereof). + + (c) the licenses granted in this Section 2.1(a) and (b) are + effective on the date Initial Developer first distributes + Original Code under the terms of this License. + + (d) Notwithstanding Section 2.1(b) above, no patent license is + granted: 1) for code that You delete from the Original Code; 2) + separate from the Original Code; or 3) for infringements caused + by: i) the modification of the Original Code or ii) the + combination of the Original Code with other software or devices. + + 2.2. Contributor Grant. + Subject to third party intellectual property claims, each Contributor + hereby grants You a world-wide, royalty-free, non-exclusive license + + (a) under intellectual property rights (other than patent or + trademark) Licensable by Contributor, to use, reproduce, modify, + display, perform, sublicense and distribute the Modifications + created by such Contributor (or portions thereof) either on an + unmodified basis, with other Modifications, as Covered Code + and/or as part of a Larger Work; and + + (b) under Patent Claims infringed by the making, using, or + selling of Modifications made by that Contributor either alone + and/or in combination with its Contributor Version (or portions + of such combination), to make, use, sell, offer for sale, have + made, and/or otherwise dispose of: 1) Modifications made by that + Contributor (or portions thereof); and 2) the combination of + Modifications made by that Contributor with its Contributor + Version (or portions of such combination). + + (c) the licenses granted in Sections 2.2(a) and 2.2(b) are + effective on the date Contributor first makes Commercial Use of + the Covered Code. + + (d) Notwithstanding Section 2.2(b) above, no patent license is + granted: 1) for any code that Contributor has deleted from the + Contributor Version; 2) separate from the Contributor Version; + 3) for infringements caused by: i) third party modifications of + Contributor Version or ii) the combination of Modifications made + by that Contributor with other software (except as part of the + Contributor Version) or other devices; or 4) under Patent Claims + infringed by Covered Code in the absence of Modifications made by + that Contributor. + +3. Distribution Obligations. + + 3.1. Application of License. + The Modifications which You create or to which You contribute are + governed by the terms of this License, including without limitation + Section 2.2. The Source Code version of Covered Code may be + distributed only under the terms of this License or a future version + of this License released under Section 6.1, and You must include a + copy of this License with every copy of the Source Code You + distribute. You may not offer or impose any terms on any Source Code + version that alters or restricts the applicable version of this + License or the recipients' rights hereunder. However, You may include + an additional document offering the additional rights described in + Section 3.5. + + 3.2. Availability of Source Code. + Any Modification which You create or to which You contribute must be + made available in Source Code form under the terms of this License + either on the same media as an Executable version or via an accepted + Electronic Distribution Mechanism to anyone to whom you made an + Executable version available; and if made available via Electronic + Distribution Mechanism, must remain available for at least twelve (12) + months after the date it initially became available, or at least six + (6) months after a subsequent version of that particular Modification + has been made available to such recipients. You are responsible for + ensuring that the Source Code version remains available even if the + Electronic Distribution Mechanism is maintained by a third party. + + 3.3. Description of Modifications. + You must cause all Covered Code to which You contribute to contain a + file documenting the changes You made to create that Covered Code and + the date of any change. You must include a prominent statement that + the Modification is derived, directly or indirectly, from Original + Code provided by the Initial Developer and including the name of the + Initial Developer in (a) the Source Code, and (b) in any notice in an + Executable version or related documentation in which You describe the + origin or ownership of the Covered Code. + + 3.4. Intellectual Property Matters + (a) Third Party Claims. + If Contributor has knowledge that a license under a third party's + intellectual property rights is required to exercise the rights + granted by such Contributor under Sections 2.1 or 2.2, + Contributor must include a text file with the Source Code + distribution titled "LEGAL" which describes the claim and the + party making the claim in sufficient detail that a recipient will + know whom to contact. If Contributor obtains such knowledge after + the Modification is made available as described in Section 3.2, + Contributor shall promptly modify the LEGAL file in all copies + Contributor makes available thereafter and shall take other steps + (such as notifying appropriate mailing lists or newsgroups) + reasonably calculated to inform those who received the Covered + Code that new knowledge has been obtained. + + (b) Contributor APIs. + If Contributor's Modifications include an application programming + interface and Contributor has knowledge of patent licenses which + are reasonably necessary to implement that API, Contributor must + also include this information in the LEGAL file. + + (c) Representations. + Contributor represents that, except as disclosed pursuant to + Section 3.4(a) above, Contributor believes that Contributor's + Modifications are Contributor's original creation(s) and/or + Contributor has sufficient rights to grant the rights conveyed by + this License. + + 3.5. Required Notices. + You must duplicate the notice in Exhibit A in each file of the Source + Code. If it is not possible to put such notice in a particular Source + Code file due to its structure, then You must include such notice in a + location (such as a relevant directory) where a user would be likely + to look for such a notice. If You created one or more Modification(s) + You may add your name as a Contributor to the notice described in + Exhibit A. You must also duplicate this License in any documentation + for the Source Code where You describe recipients' rights or ownership + rights relating to Covered Code. You may choose to offer, and to + charge a fee for, warranty, support, indemnity or liability + obligations to one or more recipients of Covered Code. However, You + may do so only on Your own behalf, and not on behalf of the Initial + Developer or any Contributor. You must make it absolutely clear than + any such warranty, support, indemnity or liability obligation is + offered by You alone, and You hereby agree to indemnify the Initial + Developer and every Contributor for any liability incurred by the + Initial Developer or such Contributor as a result of warranty, + support, indemnity or liability terms You offer. + + 3.6. Distribution of Executable Versions. + You may distribute Covered Code in Executable form only if the + requirements of Section 3.1-3.5 have been met for that Covered Code, + and if You include a notice stating that the Source Code version of + the Covered Code is available under the terms of this License, + including a description of how and where You have fulfilled the + obligations of Section 3.2. The notice must be conspicuously included + in any notice in an Executable version, related documentation or + collateral in which You describe recipients' rights relating to the + Covered Code. You may distribute the Executable version of Covered + Code or ownership rights under a license of Your choice, which may + contain terms different from this License, provided that You are in + compliance with the terms of this License and that the license for the + Executable version does not attempt to limit or alter the recipient's + rights in the Source Code version from the rights set forth in this + License. If You distribute the Executable version under a different + license You must make it absolutely clear that any terms which differ + from this License are offered by You alone, not by the Initial + Developer or any Contributor. You hereby agree to indemnify the + Initial Developer and every Contributor for any liability incurred by + the Initial Developer or such Contributor as a result of any such + terms You offer. + + 3.7. Larger Works. + You may create a Larger Work by combining Covered Code with other code + not governed by the terms of this License and distribute the Larger + Work as a single product. In such a case, You must make sure the + requirements of this License are fulfilled for the Covered Code. + +4. Inability to Comply Due to Statute or Regulation. + + If it is impossible for You to comply with any of the terms of this + License with respect to some or all of the Covered Code due to + statute, judicial order, or regulation then You must: (a) comply with + the terms of this License to the maximum extent possible; and (b) + describe the limitations and the code they affect. Such description + must be included in the LEGAL file described in Section 3.4 and must + be included with all distributions of the Source Code. Except to the + extent prohibited by statute or regulation, such description must be + sufficiently detailed for a recipient of ordinary skill to be able to + understand it. + +5. Application of this License. + + This License applies to code to which the Initial Developer has + attached the notice in Exhibit A and to related Covered Code. + +6. Versions of the License. + + 6.1. New Versions. + Netscape Communications Corporation ("Netscape") may publish revised + and/or new versions of the License from time to time. Each version + will be given a distinguishing version number. + + 6.2. Effect of New Versions. + Once Covered Code has been published under a particular version of the + License, You may always continue to use it under the terms of that + version. You may also choose to use such Covered Code under the terms + of any subsequent version of the License published by Netscape. No one + other than Netscape has the right to modify the terms applicable to + Covered Code created under this License. + + 6.3. Derivative Works. + If You create or use a modified version of this License (which you may + only do in order to apply it to code which is not already Covered Code + governed by this License), You must (a) rename Your license so that + the phrases "Mozilla", "MOZILLAPL", "MOZPL", "Netscape", + "MPL", "NPL" or any confusingly similar phrase do not appear in your + license (except to note that your license differs from this License) + and (b) otherwise make it clear that Your version of the license + contains terms which differ from the Mozilla Public License and + Netscape Public License. (Filling in the name of the Initial + Developer, Original Code or Contributor in the notice described in + Exhibit A shall not of themselves be deemed to be modifications of + this License.) + +7. DISCLAIMER OF WARRANTY. + + COVERED CODE IS PROVIDED UNDER THIS LICENSE ON AN "AS IS" BASIS, + WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, + WITHOUT LIMITATION, WARRANTIES THAT THE COVERED CODE IS FREE OF + DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE OR NON-INFRINGING. + THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE COVERED CODE + IS WITH YOU. SHOULD ANY COVERED CODE PROVE DEFECTIVE IN ANY RESPECT, + YOU (NOT THE INITIAL DEVELOPER OR ANY OTHER CONTRIBUTOR) ASSUME THE + COST OF ANY NECESSARY SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER + OF WARRANTY CONSTITUTES AN ESSENTIAL PART OF THIS LICENSE. NO USE OF + ANY COVERED CODE IS AUTHORIZED HEREUNDER EXCEPT UNDER THIS DISCLAIMER. + +8. TERMINATION. + + 8.1. This License and the rights granted hereunder will terminate + automatically if You fail to comply with terms herein and fail to cure + such breach within 30 days of becoming aware of the breach. All + sublicenses to the Covered Code which are properly granted shall + survive any termination of this License. Provisions which, by their + nature, must remain in effect beyond the termination of this License + shall survive. + + 8.2. If You initiate litigation by asserting a patent infringement + claim (excluding declatory judgment actions) against Initial Developer + or a Contributor (the Initial Developer or Contributor against whom + You file such action is referred to as "Participant") alleging that: + + (a) such Participant's Contributor Version directly or indirectly + infringes any patent, then any and all rights granted by such + Participant to You under Sections 2.1 and/or 2.2 of this License + shall, upon 60 days notice from Participant terminate prospectively, + unless if within 60 days after receipt of notice You either: (i) + agree in writing to pay Participant a mutually agreeable reasonable + royalty for Your past and future use of Modifications made by such + Participant, or (ii) withdraw Your litigation claim with respect to + the Contributor Version against such Participant. If within 60 days + of notice, a reasonable royalty and payment arrangement are not + mutually agreed upon in writing by the parties or the litigation claim + is not withdrawn, the rights granted by Participant to You under + Sections 2.1 and/or 2.2 automatically terminate at the expiration of + the 60 day notice period specified above. + + (b) any software, hardware, or device, other than such Participant's + Contributor Version, directly or indirectly infringes any patent, then + any rights granted to You by such Participant under Sections 2.1(b) + and 2.2(b) are revoked effective as of the date You first made, used, + sold, distributed, or had made, Modifications made by that + Participant. + + 8.3. If You assert a patent infringement claim against Participant + alleging that such Participant's Contributor Version directly or + indirectly infringes any patent where such claim is resolved (such as + by license or settlement) prior to the initiation of patent + infringement litigation, then the reasonable value of the licenses + granted by such Participant under Sections 2.1 or 2.2 shall be taken + into account in determining the amount or value of any payment or + license. + + 8.4. In the event of termination under Sections 8.1 or 8.2 above, + all end user license agreements (excluding distributors and resellers) + which have been validly granted by You or any distributor hereunder + prior to termination shall survive termination. + +9. LIMITATION OF LIABILITY. + + UNDER NO CIRCUMSTANCES AND UNDER NO LEGAL THEORY, WHETHER TORT + (INCLUDING NEGLIGENCE), CONTRACT, OR OTHERWISE, SHALL YOU, THE INITIAL + DEVELOPER, ANY OTHER CONTRIBUTOR, OR ANY DISTRIBUTOR OF COVERED CODE, + OR ANY SUPPLIER OF ANY OF SUCH PARTIES, BE LIABLE TO ANY PERSON FOR + ANY INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES OF ANY + CHARACTER INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF GOODWILL, + WORK STOPPAGE, COMPUTER FAILURE OR MALFUNCTION, OR ANY AND ALL OTHER + COMMERCIAL DAMAGES OR LOSSES, EVEN IF SUCH PARTY SHALL HAVE BEEN + INFORMED OF THE POSSIBILITY OF SUCH DAMAGES. THIS LIMITATION OF + LIABILITY SHALL NOT APPLY TO LIABILITY FOR DEATH OR PERSONAL INJURY + RESULTING FROM SUCH PARTY'S NEGLIGENCE TO THE EXTENT APPLICABLE LAW + PROHIBITS SUCH LIMITATION. SOME JURISDICTIONS DO NOT ALLOW THE + EXCLUSION OR LIMITATION OF INCIDENTAL OR CONSEQUENTIAL DAMAGES, SO + THIS EXCLUSION AND LIMITATION MAY NOT APPLY TO YOU. + +10. U.S. GOVERNMENT END USERS. + + The Covered Code is a "commercial item," as that term is defined in + 48 C.F.R. 2.101 (Oct. 1995), consisting of "commercial computer + software" and "commercial computer software documentation," as such + terms are used in 48 C.F.R. 12.212 (Sept. 1995). Consistent with 48 + C.F.R. 12.212 and 48 C.F.R. 227.7202-1 through 227.7202-4 (June 1995), + all U.S. Government End Users acquire Covered Code with only those + rights set forth herein. + +11. MISCELLANEOUS. + + This License represents the complete agreement concerning subject + matter hereof. If any provision of this License is held to be + unenforceable, such provision shall be reformed only to the extent + necessary to make it enforceable. This License shall be governed by + California law provisions (except to the extent applicable law, if + any, provides otherwise), excluding its conflict-of-law provisions. + With respect to disputes in which at least one party is a citizen of, + or an entity chartered or registered to do business in the United + States of America, any litigation relating to this License shall be + subject to the jurisdiction of the Federal Courts of the Northern + District of California, with venue lying in Santa Clara County, + California, with the losing party responsible for costs, including + without limitation, court costs and reasonable attorneys' fees and + expenses. The application of the United Nations Convention on + Contracts for the International Sale of Goods is expressly excluded. + Any law or regulation which provides that the language of a contract + shall be construed against the drafter shall not apply to this + License. + +12. RESPONSIBILITY FOR CLAIMS. + + As between Initial Developer and the Contributors, each party is + responsible for claims and damages arising, directly or indirectly, + out of its utilization of rights under this License and You agree to + work with Initial Developer and Contributors to distribute such + responsibility on an equitable basis. Nothing herein is intended or + shall be deemed to constitute any admission of liability. + +13. MULTIPLE-LICENSED CODE. + + Initial Developer may designate portions of the Covered Code as + "Multiple-Licensed". "Multiple-Licensed" means that the Initial + Developer permits you to utilize portions of the Covered Code under + Your choice of the NPL or the alternative licenses, if any, specified + by the Initial Developer in the file described in Exhibit A. + +EXHIBIT A - Mozilla Public License. + + ``The contents of this file are subject to the Mozilla Public License + Version 1.1 (the "License"); you may not use this file except in + compliance with the License. You may obtain a copy of the License at + http://www.mozilla.org/MPL/ + + Software distributed under the License is distributed on an "AS IS" + basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the + License for the specific language governing rights and limitations + under the License. + + The Original Code is ______________________________________. + + The Initial Developer of the Original Code is ________________________. + Portions created by ______________________ are Copyright (C) ______ + _______________________. All Rights Reserved. + + Contributor(s): ______________________________________. + + Alternatively, the contents of this file may be used under the terms + of the _____ license (the "[___] License"), in which case the + provisions of [______] License are applicable instead of those + above. If you wish to allow use of your version of this file only + under the terms of the [____] License and not to allow others to use + your version of this file under the MPL, indicate your decision by + deleting the provisions above and replace them with the notice and + other provisions required by the [___] License. If you do not delete + the provisions above, a recipient may use your version of this file + under either the MPL or the [___] License." + + [NOTE: The text of this Exhibit A may differ slightly from the text of + the notices in the Source Code files of the Original Code. You should + use the text of this Exhibit A rather than the text found in the + Original Code Source Code for Your Modifications.] + +--- end of LICENSE --- + +------------------------------------------------------------------------------- + +%% This notice is provided with respect to SAX 2.0.1, which is included +with JRE 7, JDK 7, and OpenJDK 7. + +--- begin of LICENSE --- + + SAX is free! + + In fact, it's not possible to own a license to SAX, since it's been placed in + the public domain. + + No Warranty + + Because SAX is released to the public domain, there is no warranty for the + design or for the software implementation, to the extent permitted by + applicable law. Except when otherwise stated in writing the copyright holders + and/or other parties provide SAX "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 SAX is with you. Should SAX prove + defective, you assume the cost of all necessary servicing, repair or + correction. + + 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 + SAX, be liable to you for damages, including any general, special, incidental + or consequential damages arising out of the use or inability to use SAX + (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 SAX to + operate with any other programs), even if such holder or other party has been + advised of the possibility of such damages. + + Copyright Disclaimers + + This page includes statements to that effect by David Megginson, who would + have been able to claim copyright for the original work. SAX 1.0 + + Version 1.0 of the Simple API for XML (SAX), created collectively by the + membership of the XML-DEV mailing list, is hereby released into the public + domain. + + No one owns SAX: you may use it freely in both commercial and non-commercial + applications, bundle it with your software distribution, include it on a + CD-ROM, list the source code in a book, mirror the documentation at your own + web site, or use it in any other way you see fit. + + David Megginson, sax@megginson.com + 1998-05-11 + + SAX 2.0 + + I hereby abandon any property rights to SAX 2.0 (the Simple API for XML), and + release all of the SAX 2.0 source code, compiled code, and documentation + contained in this distribution into the Public Domain. SAX comes with NO + WARRANTY or guarantee of fitness for any purpose. + + David Megginson, david@megginson.com + 2000-05-05 + +--- end of LICENSE --- + +------------------------------------------------------------------------------- + +%% This notice is provided with respect to SoftFloat version 2b, which is +included with JRE 7, JDK 7, and OpenJDK 7 on Linux/ARM. + +--- begin of LICENSE --- + +Use of any of this software is governed by the terms of the license below: + +SoftFloat was written by me, John R. Hauser. This work was made possible in +part by the International Computer Science Institute, located at Suite 600, +1947 Center Street, Berkeley, California 94704. Funding was partially +provided by the National Science Foundation under grant MIP-9311980. The +original version of this code was written as part of a project to build +a fixed-point vector processor in collaboration with the University of +California at Berkeley, overseen by Profs. Nelson Morgan and John Wawrzynek. + +THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort +has been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT +TIMES RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO +PERSONS AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ALL +LOSSES, COSTS, OR OTHER PROBLEMS THEY INCUR DUE TO THE SOFTWARE, AND WHO +FURTHERMORE EFFECTIVELY INDEMNIFY JOHN HAUSER AND THE INTERNATIONAL COMPUTER +SCIENCE INSTITUTE (possibly via similar legal warning) AGAINST ALL LOSSES, +COSTS, OR OTHER PROBLEMS INCURRED BY THEIR CUSTOMERS AND CLIENTS DUE TO THE +SOFTWARE. + +Derivative works are acceptable, even for commercial purposes, provided +that the minimal documentation requirements stated in the source code are +satisfied. + +--- end of LICENSE --- + +------------------------------------------------------------------------------- + +%% Portions licensed from Taligent, Inc. + +------------------------------------------------------------------------------- + +%% This notice is provided with respect to Thai Dictionary, which is +included with JRE 7, JDK 7, and OpenJDK 7. + +--- begin of LICENSE --- + +Copyright (C) 1982 The Royal Institute, Thai Royal Government. + +Copyright (C) 1998 National Electronics and Computer Technology Center, +National Science and Technology Development Agency, +Ministry of Science Technology and Environment, +Thai Royal Government. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +--- end of LICENSE --- + +------------------------------------------------------------------------------- + +%% This notice is provided with respect to Unicode 6.0.0, CLDR v1.4.1, & CLDR +v1.9, which is included with JRE 7, JDK 7, and OpenJDK 7. + +--- begin of LICENSE --- + +Unicode Terms of Use + +For the general privacy policy governing access to this site, see the Unicode +Privacy Policy. For trademark usage, see the Unicode® Consortium Name and +Trademark Usage Policy. + +A. Unicode Copyright. + 1. Copyright © 1991-2011 Unicode, Inc. All rights reserved. + + 2. Certain documents and files on this website contain a legend indicating + that "Modification is permitted." Any person is hereby authorized, + without fee, to modify such documents and files to create derivative + works conforming to the Unicode® Standard, subject to Terms and + Conditions herein. + + 3. Any person is hereby authorized, without fee, to view, use, reproduce, + and distribute all documents and files solely for informational + purposes in the creation of products supporting the Unicode Standard, + subject to the Terms and Conditions herein. + + 4. Further specifications of rights and restrictions pertaining to the use + of the particular set of data files known as the "Unicode Character + Database" can be found in Exhibit 1. + + 5. Each version of the Unicode Standard has further specifications of + rights and restrictions of use. For the book editions (Unicode 5.0 and + earlier), these are found on the back of the title page. The online + code charts carry specific restrictions. All other files, including + online documentation of the core specification for Unicode 6.0 and + later, are covered under these general Terms of Use. + + 6. No license is granted to "mirror" the Unicode website where a fee is + charged for access to the "mirror" site. + + 7. Modification is not permitted with respect to this document. All copies + of this document must be verbatim. + +B. Restricted Rights Legend. Any technical data or software which is licensed + to the United States of America, its agencies and/or instrumentalities + under this Agreement is commercial technical data or commercial computer + software developed exclusively at private expense as defined in FAR 2.101, + or DFARS 252.227-7014 (June 1995), as applicable. For technical data, use, + duplication, or disclosure by the Government is subject to restrictions as + set forth in DFARS 202.227-7015 Technical Data, Commercial and Items (Nov + 1995) and this Agreement. For Software, in accordance with FAR 12-212 or + DFARS 227-7202, as applicable, use, duplication or disclosure by the + Government is subject to the restrictions set forth in this Agreement. + +C. Warranties and Disclaimers. + 1. This publication and/or website may include technical or typographical + errors or other inaccuracies . Changes are periodically added to the + information herein; these changes will be incorporated in new editions + of the publication and/or website. Unicode may make improvements and/or + changes in the product(s) and/or program(s) described in this + publication and/or website at any time. + + 2. If this file has been purchased on magnetic or optical media from + Unicode, Inc. the sole and exclusive remedy for any claim will be + exchange of the defective media within ninety (90) days of original + purchase. + + 3. EXCEPT AS PROVIDED IN SECTION C.2, THIS PUBLICATION AND/OR SOFTWARE IS + PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND EITHER EXPRESS, IMPLIED, + OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, ANY WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT. + UNICODE AND ITS LICENSORS ASSUME NO RESPONSIBILITY FOR ERRORS OR + OMISSIONS IN THIS PUBLICATION AND/OR SOFTWARE OR OTHER DOCUMENTS WHICH + ARE REFERENCED BY OR LINKED TO THIS PUBLICATION OR THE UNICODE WEBSITE. + +D. Waiver of Damages. In no event shall Unicode or its licensors be liable for + any special, incidental, indirect or consequential damages of any kind, or + any damages whatsoever, whether or not Unicode was advised of the + possibility of the damage, including, without limitation, those resulting + from the following: loss of use, data or profits, in connection with the + use, modification or distribution of this information or its derivatives. + +E.Trademarks & Logos. + 1. The Unicode Word Mark and the Unicode Logo are trademarks of Unicode, + Inc. “The Unicode Consortium” and “Unicode, Inc.” are trade names of + Unicode, Inc. Use of the information and materials found on this + website indicates your acknowledgement of Unicode, Inc.’s exclusive + worldwide rights in the Unicode Word Mark, the Unicode Logo, and the + Unicode trade names. + + 2. The Unicode Consortium Name and Trademark Usage Policy (“Trademark + Policy”) are incorporated herein by reference and you agree to abide by + the provisions of the Trademark Policy, which may be changed from time + to time in the sole discretion of Unicode, Inc. + + 3. All third party trademarks referenced herein are the property of their + respective owners. + +Miscellaneous. + 1. Jurisdiction and Venue. This server is operated from a location in the + State of California, United States of America. Unicode makes no + representation that the materials are appropriate for use in other + locations. If you access this server from other locations, you are + responsible for compliance with local laws. This Agreement, all use of + this site and any claims and damages resulting from use of this site are + governed solely by the laws of the State of California without regard to + any principles which would apply the laws of a different jurisdiction. + The user agrees that any disputes regarding this site shall be resolved + solely in the courts located in Santa Clara County, California. The user + agrees said courts have personal jurisdiction and agree to waive any + right to transfer the dispute to any other forum. + + 2. Modification by Unicode. Unicode shall have the right to modify this + Agreement at any time by posting it to this site. The user may not + assign any part of this Agreement without Unicode’s prior written + consent. + + 3. Taxes. The user agrees to pay any taxes arising from access to this + website or use of the information herein, except for those based on + Unicode’s net income. + + 4. Severability. If any provision of this Agreement is declared invalid or + unenforceable, the remaining provisions of this Agreement shall remain + in effect. + + 5. Entire Agreement. This Agreement constitutes the entire agreement + between the parties. + +EXHIBIT 1 +UNICODE, INC. LICENSE AGREEMENT - DATA FILES AND SOFTWARE + +Unicode Data Files include all data files under the directories +http://www.unicode.org/Public/, http://www.unicode.org/reports/, and +http://www.unicode.org/cldr/data/. Unicode Data Files do not include PDF +online code charts under the directory http://www.unicode.org/Public/. +Software includes any source code published in the Unicode Standard or under +the directories http://www.unicode.org/Public/, +http://www.unicode.org/reports/, and http://www.unicode.org/cldr/data/. + +NOTICE TO USER: Carefully read the following legal agreement. BY DOWNLOADING, +INSTALLING, COPYING OR OTHERWISE USING UNICODE INC.'S DATA FILES ("DATA +FILES"), AND/OR SOFTWARE ("SOFTWARE"), YOU UNEQUIVOCALLY ACCEPT, AND AGREE TO +BE BOUND BY, ALL OF THE TERMS AND CONDITIONS OF THIS AGREEMENT. IF YOU DO NOT +AGREE, DO NOT DOWNLOAD, INSTALL, COPY, DISTRIBUTE OR USE THE DATA FILES OR +SOFTWARE. + +COPYRIGHT AND PERMISSION NOTICE + +Copyright © 1991-2011 Unicode, Inc. All rights reserved. Distributed under the +Terms of Use in http://www.unicode.org/copyright.html. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of the Unicode data files and any associated documentation (the "Data Files") +or Unicode software and any associated documentation (the "Software") to deal +in the Data Files or Software without restriction, including without +limitation the rights to use, copy, modify, merge, publish, distribute, and/or +sell copies of the Data Files or Software, and to permit persons to whom the +Data Files or Software are furnished to do so, provided that (a) the above +copyright notice(s) and this permission notice appear with all copies of the +Data Files or Software, (b) both the above copyright notice(s) and this +permission notice appear in associated documentation, and (c) there is clear +notice in each modified Data File or in the Software as well as in the +documentation associated with the Data File(s) or Software that the data or +software has been modified. + +THE DATA FILES AND SOFTWARE ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY +KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD +PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN +THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSEQUENTIAL +DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR +PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS +ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THE +DATA FILES OR SOFTWARE. + +Except as contained in this notice, the name of a copyright holder shall not +be used in advertising or otherwise to promote the sale, use or other dealings +in these Data Files or Software without prior written authorization of the +copyright holder. + +Unicode and the Unicode logo are trademarks of Unicode, Inc. in the United +States and other countries. All third party trademarks referenced herein are +the property of their respective owners. + +--- end of LICENSE --- + +------------------------------------------------------------------------------- + +%% This notice is provided with respect to UPX v3.01, which is included +with JRE 7 on Windows. + +--- begin of LICENSE --- + +Use of any of this software is governed by the terms of the license below: + + + ooooo ooo ooooooooo. ooooooo ooooo + `888' `8' `888 `Y88. `8888 d8' + 888 8 888 .d88' Y888..8P + 888 8 888ooo88P' `8888' + 888 8 888 .8PY888. + `88. .8' 888 d8' `888b + `YbodP' o888o o888o o88888o + + + The Ultimate Packer for eXecutables + Copyright (c) 1996-2000 Markus Oberhumer & Laszlo Molnar + http://wildsau.idv.uni-linz.ac.at/mfx/upx.html + http://www.nexus.hu/upx + http://upx.tsx.org + + +PLEASE CAREFULLY READ THIS LICENSE AGREEMENT, ESPECIALLY IF YOU PLAN +TO MODIFY THE UPX SOURCE CODE OR USE A MODIFIED UPX VERSION. + + +ABSTRACT +======== + + UPX and UCL are copyrighted software distributed under the terms + of the GNU General Public License (hereinafter the "GPL"). + + The stub which is imbedded in each UPX compressed program is part + of UPX and UCL, and contains code that is under our copyright. The + terms of the GNU General Public License still apply as compressing + a program is a special form of linking with our stub. + + As a special exception we grant the free usage of UPX for all + executables, including commercial programs. + See below for details and restrictions. + + +COPYRIGHT +========= + + UPX and UCL are copyrighted software. All rights remain with the authors. + + UPX is Copyright (C) 1996-2000 Markus Franz Xaver Johannes Oberhumer + UPX is Copyright (C) 1996-2000 Laszlo Molnar + + UCL is Copyright (C) 1996-2000 Markus Franz Xaver Johannes Oberhumer + + +GNU GENERAL PUBLIC LICENSE +========================== + + UPX and the UCL library are free software; you can redistribute them + and/or modify them under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of + the License, or (at your option) any later version. + + UPX and UCL are distributed in the hope that they will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; see the file COPYING. + + +SPECIAL EXCEPTION FOR COMPRESSED EXECUTABLES +============================================ + + The stub which is imbedded in each UPX compressed program is part + of UPX and UCL, and contains code that is under our copyright. The + terms of the GNU General Public License still apply as compressing + a program is a special form of linking with our stub. + + Hereby Markus F.X.J. Oberhumer and Laszlo Molnar grant you special + permission to freely use and distribute all UPX compressed programs + (including commercial ones), subject to the following restrictions: + + 1. You must compress your program with a completely unmodified UPX + version; either with our precompiled version, or (at your option) + with a self compiled version of the unmodified UPX sources as + distributed by us. + 2. This also implies that the UPX stub must be completely unmodfied, i.e. + the stub imbedded in your compressed program must be byte-identical + to the stub that is produced by the official unmodified UPX version. + 3. The decompressor and any other code from the stub must exclusively get + used by the unmodified UPX stub for decompressing your program at + program startup. No portion of the stub may get read, copied, + called or otherwise get used or accessed by your program. + + +ANNOTATIONS +=========== + + - You can use a modified UPX version or modified UPX stub only for + programs that are compatible with the GNU General Public License. + + - We grant you special permission to freely use and distribute all UPX + compressed programs. But any modification of the UPX stub (such as, + but not limited to, removing our copyright string or making your + program non-decompressible) will immediately revoke your right to + use and distribute a UPX compressed program. + + - UPX is not a software protection tool; by requiring that you use + the unmodified UPX version for your proprietary programs we + make sure that any user can decompress your program. This protects + both you and your users as nobody can hide malicious code - + any program that cannot be decompressed is highly suspicious + by definition. + + - You can integrate all or part of UPX and UCL into projects that + are compatible with the GNU GPL, but obviously you cannot grant + any special exceptions beyond the GPL for our code in your project. + + - We want to actively support manufacturers of virus scanners and + similar security software. Please contact us if you would like to + incorporate parts of UPX or UCL into such a product. + + + +Markus F.X.J. Oberhumer Laszlo Molnar +markus.oberhumer@jk.uni-linz.ac.at ml1050@cdata.tvnet.hu + +Linz, Austria, 25 Feb 2000 + +Additional License(s) + +The UPX license file is at http://upx.sourceforge.net/upx-license.html. + +--- end of LICENSE --- + +------------------------------------------------------------------------------- + +%% This notice is provided with respect to Xfree86-VidMode Extension 1.0, +which is included with JRE 7, JDK 7, and OpenJDK 7 on Linux and Solaris. + +--- begin of LICENSE --- + +Version 1.1 of XFree86 ProjectLicence. + +Copyright (C) 1994-2004 The XFree86 Project, Inc. All rights reserved. + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicence, and/or sell +copies of the Software, and to permit persons to whom the Software is furnished +to do so,subject to the following conditions: + + 1. Redistributions of source code must retain the above copyright + notice,this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution, and in the same place + and form as other copyright, license and disclaimer information. + + 3. The end-user documentation included with the redistribution, if any,must + include the following acknowledgment: "This product includes + software developed by The XFree86 Project, Inc (http://www.xfree86.org/) and + its contributors", in the same place and form as other third-party + acknowledgments. Alternately, this acknowledgment may appear in the software + itself, in the same form and location as other such third-party + acknowledgments. + + 4. Except as contained in this notice, the name of The XFree86 Project,Inc + shall not be used in advertising or otherwise to promote the sale, use + or other dealings in this Software without prior written authorization from + The XFree86 Project, Inc. + + THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + WARRANTIES,INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO + EVENT SHALL THE XFREE86 PROJECT, INC OR ITS CONTRIBUTORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL,SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO,PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH + DAMAGE. + +--- end of LICENSE --- + +------------------------------------------------------------------------------- + +%% This notice is provided with respect to X Window System 6.8.2, which is +included with JRE 7, JDK 7, and OpenJDK 7 on Linux and Solaris. + +--- begin of LICENSE --- + + Licenses +The X.Org Foundation March 2004 + +1. Introduction + +The X.org Foundation X Window System distribution is a compilation of code and +documentation from many sources. This document is intended primarily as a +guide to the licenses used in the distribution: you must check each file +and/or package for precise redistribution terms. None-the-less, this summary +may be useful to many users. No software incorporating the XFree86 1.1 license +has been incorporated. + +This document is based on the compilation from XFree86. + +2. XFree86 License + +XFree86 code without an explicit copyright is covered by the following +copyright/license: + +Copyright (C) 1994-2003 The XFree86 Project, Inc. All Rights Reserved. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +XFREE86 PROJECT BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of the XFree86 Project shall not +be used in advertising or otherwise to promote the sale, use or other dealings +in this Software without prior written authorization from the XFree86 Project. + +3. Other Licenses + +Portions of code are covered by the following licenses/copyrights. See +individual files for the copyright dates. + +3.1. X/MIT Copyrights + +3.1.1. X Consortium + +Copyright (C) X Consortium + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE X +CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of the X Consortium shall not be +used in advertising or otherwise to promote the sale, use or other dealings in +this Software without prior written authorization from the X Consortium. + +X Window System is a trademark of X Consortium, Inc. + +3.1.2. The Open Group + +Copyright The Open Group + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that the +above copyright notice appear in all copies and that both that copyright +notice and this permission notice appear in supporting documentation. + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN +ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +Except as contained in this notice, the name of The Open Group shall not be +used in advertising or otherwise to promote the sale, use or other dealings in +this Software without prior written authorization from The Open Group. 3.2. +Berkeley-based copyrights: + +o +3.2.1. General + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED +WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO +EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER +IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. 3.2.2. UCB/LBL + +Copyright (c) 1993 The Regents of the University of California. All rights +reserved. + +This software was developed by the Computer Systems Engineering group at +Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and contributed to +Berkeley. + +All advertising materials mentioning features or use of this software must +display the following acknowledgement: This product includes software +developed by the University of California, Lawrence Berkeley Laboratory. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 3. All advertising materials mentioning features or use of this software + must display the following acknowledgement: This product includes software + developed by the University of California, Berkeley and its contributors. + + 4. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 3.2.3. The +NetBSD Foundation, Inc. + +Copyright (c) 2003 The NetBSD Foundation, Inc. All rights reserved. + +This code is derived from software contributed to The NetBSD Foundation by Ben +Collver + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 3. All advertising materials mentioning features or use of this software + must display the following acknowledgement: This product includes software + developed by the NetBSD Foundation, Inc. and its contributors. + + 4. Neither the name of The NetBSD Foundation nor the names of its + contributors may be used to endorse or promote products derived from this + software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS ``AS +IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 3.2.4. Theodore +Ts'o. + +Copyright Theodore Ts'o, 1994, 1995, 1996, 1997, 1998, 1999. All rights +reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + and the entire permission notice in its entirety, including the disclaimer + of warranties. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 3. he name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, +INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE, ALL OF WHICH ARE HEREBY DISCLAIMED. IN NO +EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER +IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. 3.2.5. Theo de Raadt and Damien Miller + +Copyright (c) 1995,1999 Theo de Raadt. All rights reserved. Copyright (c) +2001-2002 Damien Miller. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED +WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO +EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER +IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. 3.2.6. Todd C. Miller + +Copyright (c) 1998 Todd C. Miller + +Permission to use, copy, modify, and distribute this software for any purpose +with or without fee is hereby granted, provided that the above copyright +notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND TODD C. MILLER DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL TODD C. MILLER BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION +OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN +CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 3.2.7. Thomas +Winischhofer + +Copyright (C) 2001-2004 Thomas Winischhofer + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + + 3. The name of the author may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESSED OR IMPLIED +WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO +EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER +IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. 3.3. NVIDIA Corp + +Copyright (c) 1996 NVIDIA, Corp. All rights reserved. + +NOTICE TO USER: The source code is copyrighted under U.S. and international +laws. NVIDIA, Corp. of Sunnyvale, California owns the copyright and as design +patents pending on the design and interface of the NV chips. Users and +possessors of this source code are hereby granted a nonexclusive, royalty-free +copyright and design patent license to use this code in individual and +commercial software. + +Any use of this source code must include, in the user documentation and +internal comments to the code, notices to the end user as follows: + +Copyright (c) 1996 NVIDIA, Corp. NVIDIA design patents pending in the U.S. and +foreign countries. + +NVIDIA, CORP. MAKES NO REPRESENTATION ABOUT THE SUITABILITY OF THIS SOURCE +CODE FOR ANY PURPOSE. IT IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED +WARRANTY OF ANY KIND. NVIDIA, CORP. DISCLAIMS ALL WARRANTIES WITH REGARD TO +THIS SOURCE CODE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL NVIDIA, CORP. BE LIABLE +FOR ANY SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, OR ANY +DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN +CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOURCE CODE. 3.4. GLX Public +License + +GLX PUBLIC LICENSE (Version 1.0 (2/11/99)) ("License") + +Subject to any third party claims, Silicon Graphics, Inc. ("SGI") hereby +grants permission to Recipient (defined below), under Recipient's copyrights +in the Original Software (defined below), to use, copy, modify, merge, +publish, distribute, sublicense and/or sell copies of Subject Software +(defined below), and to permit persons to whom the Subject Software is +furnished in accordance with this License to do the same, subject to all of +the following terms and conditions, which Recipient accepts by engaging in any +such use, copying, modifying, merging, publishing, distributing, sublicensing +or selling: + +1. Definitions. + + (a) "Original Software" means source code of computer software code which + is described in Exhibit A as Original Software. + + (b) "Modifications" means any addition to or deletion from the substance + or structure of either the Original Software or any previous + Modifications. When Subject Software is released as a series of files, a + Modification means (i) any addition to or deletion from the contents of a + file containing Original Software or previous Modifications and (ii) any + new file that contains any part of the Original Code or previous + Modifications. + + (c) "Subject Software" means the Original Software or Modifications or the + combination of the Original Software and Modifications, or portions of any + of the foregoing. + + (d) "Recipient" means an individual or a legal entity exercising rights + under, and complying with all of the terms of, this License. For legal + entities, "Recipient" includes any entity which controls, is controlled + by, or is under common control with Recipient. For purposes of this + definition, "control" of an entity means (a) the power, direct or + indirect, to direct or manage such entity, or (b) ownership of fifty + percent (50%) or more of the outstanding shares or beneficial ownership of + such entity. + +2. Redistribution of Source Code Subject to These Terms. Redistributions of +Subject Software in source code form must retain the notice set forth in +Exhibit A, below, in every file. A copy of this License must be included in +any documentation for such Subject Software where the recipients' rights +relating to Subject Software are described. Recipient may distribute the +source code version of Subject Software under a license of Recipient's choice, +which may contain terms different from this License, provided that (i) +Recipient is in compliance with the terms of this License, and (ii) the +license terms include this Section 2 and Sections 3, 4, 7, 8, 10, 12 and 13 of +this License, which terms may not be modified or superseded by any other terms +of such license. If Recipient distributes the source code version under a +different license Recipient must make it absolutely clear that any terms which +differ from this License are offered by Recipient alone, not by SGI. Recipient +hereby agrees to indemnify SGI for any liability incurred by SGI as a result +of any such terms Recipient offers. + +3. Redistribution in Executable Form. The notice set forth in Exhibit A must +be conspicuously included in any notice in an executable version of Subject +Software, related documentation or collateral in which Recipient describes the +user's rights relating to the Subject Software. Recipient may distribute the +executable version of Subject Software under a license of Recipient's choice, +which may contain terms different from this License, provided that (i) +Recipient is in compliance with the terms of this License, and (ii) the +license terms include this Section 3 and Sections 4, 7, 8, 10, 12 and 13 of +this License, which terms may not be modified or superseded by any other terms +of such license. If Recipient distributes the executable version under a +different license Recipient must make it absolutely clear that any terms which +differ from this License are offered by Recipient alone, not by SGI. Recipient +hereby agrees to indemnify SGI for any liability incurred by SGI as a result +of any such terms Recipient offers. + +4. Termination. This License and the rights granted hereunder will terminate +automatically if Recipient fails to comply with terms herein and fails to cure +such breach within 30 days of the breach. Any sublicense to the Subject +Software which is properly granted shall survive any termination of this +License absent termination by the terms of such sublicense. Provisions which, +by their nature, must remain in effect beyond the termination of this License +shall survive. + +5. No Trademark Rights. This License does not grant any rights to use any +trade name, trademark or service mark whatsoever. No trade name, trademark or +service mark of SGI may be used to endorse or promote products derived from +the Subject Software without prior written permission of SGI. + +6. No Other Rights. This License does not grant any rights with respect to the +OpenGL API or to any software or hardware implementation thereof or to any +other software whatsoever, nor shall any other rights or licenses not +expressly granted hereunder arise by implication, estoppel or otherwise with +respect to the Subject Software. Title to and ownership of the Original +Software at all times remains with SGI. All rights in the Original Software +not expressly granted under this License are reserved. + +7. Compliance with Laws; Non-Infringement. Recipient shall comply with all +applicable laws and regulations in connection with use and distribution of the +Subject Software, including but not limited to, all export and import control +laws and regulations of the U.S. government and other countries. Recipient may +not distribute Subject Software that (i) in any way infringes (directly or +contributorily) the rights (including patent, copyright, trade secret, +trademark or other intellectual property rights of any kind) of any other +person or entity or (ii) breaches any representation or warranty, express, +implied or statutory, which under any applicable law it might be deemed to +have been distributed. + +8. Claims of Infringement. If Recipient at any time has knowledge of any one +or more third party claims that reproduction, modification, use, distribution, +import or sale of Subject Software (including particular functionality or code +incorporated in Subject Software) infringes the third party's intellectual +property rights, Recipient must place in a well-identified web page bearing +the title "LEGAL" a description of each such claim and a description of the +party making each such claim in sufficient detail that a user of the Subject +Software will know whom to contact regarding the claim. Also, upon gaining +such knowledge of any such claim, Recipient must conspicuously include the URL +for such web page in the Exhibit A notice required under Sections 2 and 3, +above, and in the text of any related documentation, license agreement or +collateral in which Recipient describes end user's rights relating to the +Subject Software. If Recipient obtains such knowledge after it makes Subject +Software available to any other person or entity, Recipient shall take other +steps (such as notifying appropriate mailing lists or newsgroups) reasonably +calculated to inform those who received the Subject Software that new +knowledge has been obtained. + +9. DISCLAIMER OF WARRANTY. SUBJECT SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, +WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT +LIMITATION, WARRANTIES THAT THE SUBJECT SOFTWARE IS FREE OF DEFECTS, +MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE OR NON- INFRINGING. SGI ASSUMES NO +RISK AS TO THE QUALITY AND PERFORMANCE OF THE SOFTWARE. SHOULD ANY SOFTWARE +PROVE DEFECTIVE IN ANY RESPECT, SGI ASSUMES NO COST OR LIABILITY FOR ANY +SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN +ESSENTIAL PART OF THIS LICENSE. NO USE OF ANY SUBJECT SOFTWARE IS AUTHORIZED +HEREUNDER EXCEPT UNDER THIS DISCLAIMER. + +10. LIMITATION OF LIABILITY. UNDER NO CIRCUMSTANCES AND UNDER NO LEGAL THEORY, +WHETHER TORT (INCLUDING, WITHOUT LIMITATION, NEGLIGENCE OR STRICT LIABILITY), +CONTRACT, OR OTHERWISE, SHALL SGI OR ANY SGI LICENSOR BE LIABLE FOR ANY +DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES OF ANY +CHARACTER INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF GOODWILL, WORK +STOPPAGE, LOSS OF DATA, COMPUTER FAILURE OR MALFUNCTION, OR ANY AND ALL OTHER +COMMERCIAL DAMAGES OR LOSSES, EVEN IF SUCH PARTY SHALL HAVE BEEN INFORMED OF +THE POSSIBILITY OF SUCH DAMAGES. THIS LIMITATION OF LIABILITY SHALL NOT APPLY +TO LIABILITY FOR DEATH OR PERSONAL INJURY RESULTING FROM SGI's NEGLIGENCE TO +THE EXTENT APPLICABLE LAW PROHIBITS SUCH LIMITATION. SOME JURISDICTIONS DO NOT +ALLOW THE EXCLUSION OR LIMITATION OF INCIDENTAL OR CONSEQUENTIAL DAMAGES, SO +THAT EXCLUSION AND LIMITATION MAY NOT APPLY TO RECIPIENT. + +11. Indemnity. Recipient shall be solely responsible for damages arising, +directly or indirectly, out of its utilization of rights under this License. +Recipient will defend, indemnify and hold harmless Silicon Graphics, Inc. from +and against any loss, liability, damages, costs or expenses (including the +payment of reasonable attorneys fees) arising out of Recipient's use, +modification, reproduction and distribution of the Subject Software or out of +any representation or warranty made by Recipient. + +12. U.S. Government End Users. The Subject Software is a "commercial item" +consisting of "commercial computer software" as such terms are defined in +title 48 of the Code of Federal Regulations and all U.S. Government End Users +acquire only the rights set forth in this License and are subject to the terms +of this License. + +13. Miscellaneous. This License represents the complete agreement concerning +subject matter hereof. If any provision of this License is held to be +unenforceable, such provision shall be reformed so as to achieve as nearly as +possible the same economic effect as the original provision and the remainder +of this License will remain in effect. This License shall be governed by and +construed in accordance with the laws of the United States and the State of +California as applied to agreements entered into and to be performed entirely +within California between California residents. Any litigation relating to +this License shall be subject to the exclusive jurisdiction of the Federal +Courts of the Northern District of California (or, absent subject matter +jurisdiction in such courts, the courts of the State of California), with +venue lying exclusively in Santa Clara County, California, with the losing +party responsible for costs, including without limitation, court costs and +reasonable attorneys fees and expenses. The application of the United Nations +Convention on Contracts for the International Sale of Goods is expressly +excluded. Any law or regulation which provides that the language of a contract +shall be construed against the drafter shall not apply to this License. + +Exhibit A + +The contents of this file are subject to Sections 2, 3, 4, 7, 8, 10, 12 and 13 +of the GLX Public License Version 1.0 (the "License"). You may not use this +file except in compliance with those sections of the License. You may obtain a +copy of the License at Silicon Graphics, Inc., attn: Legal Services, 2011 N. +Shoreline Blvd., Mountain View, CA 94043 or at +http://www.sgi.com/software/opensource/glx/license.html. + +Software distributed under the License is distributed on an "AS IS" basis. ALL +WARRANTIES ARE DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED +WARRANTIES OF MERCHANTABILITY, OF FITNESS FOR A PARTICULAR PURPOSE OR OF NON- +INFRINGEMENT. See the License for the specific language governing rights and +limitations under the License. + +The Original Software is GLX version 1.2 source code, released February, 1999. +The developer of the Original Software is Silicon Graphics, Inc. Those +portions of the Subject Software created by Silicon Graphics, Inc. are +Copyright (c) 1991-9 Silicon Graphics, Inc. All Rights Reserved. 3.5. CID +Font Code Public License + +CID FONT CODE PUBLIC LICENSE (Version 1.0 (3/31/99))("License") + +Subject to any applicable third party claims, Silicon Graphics, Inc. ("SGI") +hereby grants permission to Recipient (defined below), under SGI's copyrights +in the Original Software (defined below), to use, copy, modify, merge, +publish, distribute, sublicense and/or sell copies of Subject Software +(defined below) in both source code and executable form, and to permit persons +to whom the Subject Software is furnished in accordance with this License to +do the same, subject to all of the following terms and conditions, which +Recipient accepts by engaging in any such use, copying, modifying, merging, +publication, distributing, sublicensing or selling: + +1. Definitions. + + a. "Original Software" means source code of computer software code that is + described in Exhibit A as Original Software. + + b. "Modifications" means any addition to or deletion from the substance or + structure of either the Original Software or any previous Modifications. + When Subject Software is released as a series of files, a Modification + means (i) any addition to or deletion from the contents of a file + containing Original Software or previous Modifications and (ii) any new + file that contains any part of the Original Code or previous + Modifications. + + c. "Subject Software" means the Original Software or Modifications or the + combination of the Original Software and Modifications, or portions of any + of the foregoing. + + d. "Recipient" means an individual or a legal entity exercising rights + under the terms of this License. For legal entities, "Recipient" includes + any entity that controls, is controlled by, or is under common control + with Recipient. For purposes of this definition, "control" of an entity + means (i) the power, direct or indirect, to direct or manage such entity, + or (ii) ownership of fifty percent (50%) or more of the outstanding shares + or beneficial ownership of such entity. + + e. "Required Notice" means the notice set forth in Exhibit A to this + License. + + f. "Accompanying Technology" means any software or other technology that + is not a Modification and that is distributed or made publicly available + by Recipient with the Subject Software. Separate software files that do + not contain any Original Software or any previous Modification shall not + be deemed a Modification, even if such software files are aggregated as + part of a product, or in any medium of storage, with any file that does + contain Original Software or any previous Modification. + +2. License Terms. All distribution of the Subject Software must be made +subject to the terms of this License. A copy of this License and the Required +Notice must be included in any documentation for Subject Software where +Recipient's rights relating to Subject Software and/or any Accompanying +Technology are described. Distributions of Subject Software in source code +form must also include the Required Notice in every file distributed. In +addition, a ReadMe file entitled "Important Legal Notice" must be distributed +with each distribution of one or more files that incorporate Subject Software. +That file must be included with distributions made in both source code and +executable form. A copy of the License and the Required Notice must be +included in that file. Recipient may distribute Accompanying Technology under +a license of Recipient's choice, which may contain terms different from this +License, provided that (i) Recipient is in compliance with the terms of this +License, (ii) such other license terms do not modify or supersede the terms of +this License as applicable to the Subject Software, (iii) Recipient hereby +indemnifies SGI for any liability incurred by SGI as a result of the +distribution of Accompanying Technology or the use of other license terms. + +3. Termination. This License and the rights granted hereunder will terminate +automatically if Recipient fails to comply with terms herein and fails to cure +such breach within 30 days of the breach. Any sublicense to the Subject +Software that is properly granted shall survive any termination of this +License absent termination by the terms of such sublicense. Provisions which, +by their nature, must remain in effect beyond the termination of this License +shall survive. + +4. Trademark Rights. This License does not grant any rights to use any trade +name, trademark or service mark whatsoever. No trade name, trademark or +service mark of SGI may be used to endorse or promote products derived from or +incorporating any Subject Software without prior written permission of SGI. + +5. No Other Rights. No rights or licenses not expressly granted hereunder +shall arise by implication, estoppel or otherwise. Title to and ownership of +the Original Software at all times remains with SGI. All rights in the +Original Software not expressly granted under this License are reserved. + +6. Compliance with Laws; Non-Infringement. Recipient shall comply with all +applicable laws and regulations in connection with use and distribution of the +Subject Software, including but not limited to, all export and import control +laws and regulations of the U.S. government and other countries. Recipient may +not distribute Subject Software that (i) in any way infringes (directly or +contributorily) the rights (including patent, copyright, trade secret, +trademark or other intellectual property rights of any kind) of any other +person or entity, or (ii) breaches any representation or warranty, express, +implied or statutory, which under any applicable law it might be deemed to +have been distributed. + +7. Claims of Infringement. If Recipient at any time has knowledge of any one +or more third party claims that reproduction, modification, use, distribution, +import or sale of Subject Software (including particular functionality or code +incorporated in Subject Software) infringes the third party's intellectual +property rights, Recipient must place in a well-identified web page bearing +the title "LEGAL" a description of each such claim and a description of the +party making each such claim in sufficient detail that a user of the Subject +Software will know whom to contact regarding the claim. Also, upon gaining +such knowledge of any such claim, Recipient must conspicuously include the URL +for such web page in the Required Notice, and in the text of any related +documentation, license agreement or collateral in which Recipient describes +end user's rights relating to the Subject Software. If Recipient obtains such +knowledge after it makes Subject Software available to any other person or +entity, Recipient shall take other steps (such as notifying appropriate +mailing lists or newsgroups) reasonably calculated to provide such knowledge +to those who received the Subject Software. + +8. DISCLAIMER OF WARRANTY. SUBJECT SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, +WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT +LIMITATION, WARRANTIES THAT THE SUBJECT SOFTWARE IS FREE OF DEFECTS, +MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE OR NON-INFRINGING. SGI ASSUMES NO +RISK AS TO THE QUALITY AND PERFORMANCE OF THE SOFTWARE. SHOULD ANY SOFTWARE +PROVE DEFECTIVE IN ANY RESPECT, SGI ASSUMES NO COST OR LIABILITY FOR ANY +SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY CONSTITUTES AN +ESSENTIAL PART OF THIS LICENSE. NO USE OF ANY SUBJECT SOFTWARE IS AUTHORIZED +HEREUNDER EXCEPT UNDER THIS DISCLAIMER. + +9. LIMITATION OF LIABILITY. UNDER NO CIRCUMSTANCES AND UNDER NO LEGAL THEORY, +WHETHER TORT (INCLUDING, WITHOUT LIMITATION, NEGLIGENCE OR STRICT LIABILITY), +CONTRACT, OR OTHERWISE, SHALL SGI OR ANY SGI LICENSOR BE LIABLE FOR ANY CLAIM, +DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SUBJECT SOFTWARE OR +THE USE OR OTHER DEALINGS IN THE SUBJECT SOFTWARE. SOME JURISDICTIONS DO NOT +ALLOW THE EXCLUSION OR LIMITATION OF CERTAIN DAMAGES, SO THIS EXCLUSION AND +LIMITATION MAY NOT APPLY TO RECIPIENT TO THE EXTENT SO DISALLOWED. + +10. Indemnity. Recipient shall be solely responsible for damages arising, +directly or indirectly, out of its utilization of rights under this License. +Recipient will defend, indemnify and hold SGI and its successors and assigns +harmless from and against any loss, liability, damages, costs or expenses +(including the payment of reasonable attorneys fees) arising out of +(Recipient's use, modification, reproduction and distribution of the Subject +Software or out of any representation or warranty made by Recipient. + +11. U.S. Government End Users. The Subject Software is a "commercial item" +consisting of "commercial computer software" as such terms are defined in +title 48 of the Code of Federal Regulations and all U.S. Government End Users +acquire only the rights set forth in this License and are subject to the terms +of this License. + +12. Miscellaneous. This License represents the complete agreement concerning +subject matter hereof. If any provision of this License is held to be +unenforceable by any judicial or administrative authority having proper +jurisdiction with respect thereto, such provision shall be reformed so as to +achieve as nearly as possible the same economic effect as the original +provision and the remainder of this License will remain in effect. This +License shall be governed by and construed in accordance with the laws of the +United States and the State of California as applied to agreements entered +into and to be performed entirely within California between California +residents. Any litigation relating to this License shall be subject to the +exclusive jurisdiction of the Federal Courts of the Northern District of +California (or, absent subject matter jurisdiction in such courts, the courts +of the State of California), with venue lying exclusively in Santa Clara +County, California, with the losing party responsible for costs, including +without limitation, court costs and reasonable attorneys fees and expenses. +The application of the United Nations Convention on Contracts for the +International Sale of Goods is expressly excluded. Any law or regulation that +provides that the language of a contract shall be construed against the +drafter shall not apply to this License. + +Exhibit A + +Copyright (c) 1994-1999 Silicon Graphics, Inc. + +The contents of this file are subject to the CID Font Code Public License +Version 1.0 (the "License"). You may not use this file except in compliance +with the License. You may obtain a copy of the License at Silicon Graphics, +Inc., attn: Legal Services, 2011 N. Shoreline Blvd., Mountain View, CA 94043 +or at http://www.sgi.com/software/opensource/cid/license.html + +Software distributed under the License is distributed on an "AS IS" basis. ALL +WARRANTIES ARE DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED +WARRANTIES OF MERCHANTABILITY, OF FITNESS FOR A PARTICULAR PURPOSE OR OF +NON-INFRINGEMENT. See the License for the specific language governing rights +and limitations under the License. + +The Original Software (as defined in the License) is CID font code that was +developed by Silicon Graphics, Inc. Those portions of the Subject Software (as +defined in the License) that were created by Silicon Graphics, Inc. are +Copyright (c) 1994-1999 Silicon Graphics, Inc. All Rights Reserved. + +[NOTE: When using this text in connection with Subject Software delivered +solely in object code form, Recipient may replace the words "this file" with +"this software" in both the first and second sentences.] 3.6. Bitstream Vera +Fonts Copyright + +The fonts have a generous copyright, allowing derivative works (as long as +"Bitstream" or "Vera" are not in the names), and full redistribution (so long +as they are not *sold* by themselves). They can be be bundled, redistributed +and sold with any software. + +The fonts are distributed under the following copyright: + +Copyright (c) 2003 by Bitstream, Inc. All Rights Reserved. Bitstream Vera is a +trademark of Bitstream, Inc. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of the fonts accompanying this license ("Fonts") and associated documentation +files (the "Font Software"), to reproduce and distribute the Font Software, +including without limitation the rights to use, copy, merge, publish, +distribute, and/or sell copies of the Font Software, and to permit persons to +whom the Font Software is furnished to do so, subject to the following +conditions: + +The above copyright and trademark notices and this permission notice shall be +included in all copies of one or more of the Font Software typefaces. + +The Font Software may be modified, altered, or added to, and in particular the +designs of glyphs or characters in the Fonts may be modified and additional +glyphs or characters may be added to the Fonts, only if the fonts are renamed +to names not containing either the words "Bitstream" or the word "Vera". + +This License becomes null and void to the extent applicable to Fonts or Font +Software that has been modified and is distributed under the "Bitstream Vera" +names. + +The Font Software may be sold as part of a larger software package but no copy +of one or more of the Font Software typefaces may be sold by itself. + +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF COPYRIGHT, PATENT, +TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL BITSTREAM OR THE GNOME FOUNDATION +BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, INCLUDING ANY GENERAL, +SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF THE USE OR INABILITY TO +USE THE FONT SOFTWARE OR FROM OTHER DEALINGS IN THE FONT SOFTWARE. + +Except as contained in this notice, the names of Gnome, the Gnome Foundation, +and Bitstream Inc., shall not be used in advertising or otherwise to promote +the sale, use or other dealings in this Font Software without prior written +authorization from the Gnome Foundation or Bitstream Inc., respectively. For +further information, contact: fonts at gnome dot org. 3.7. Bigelow & Holmes +Inc and URW++ GmbH Luxi font license + +Luxi fonts copyright (c) 2001 by Bigelow & Holmes Inc. Luxi font instruction +code copyright (c) 2001 by URW++ GmbH. All Rights Reserved. Luxi is a +registered trademark of Bigelow & Holmes Inc. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of these Fonts and associated documentation files (the "Font Software"), to +deal in the Font Software, including without limitation the rights to use, +copy, merge, publish, distribute, sublicense, and/or sell copies of the Font +Software, and to permit persons to whom the Font Software is furnished to do +so, subject to the following conditions: + +The above copyright and trademark notices and this permission notice shall be +included in all copies of one or more of the Font Software. + +The Font Software may not be modified, altered, or added to, and in particular +the designs of glyphs or characters in the Fonts may not be modified nor may +additional glyphs or characters be added to the Fonts. This License becomes +null and void when the Fonts or Font Software have been modified. + +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF COPYRIGHT, PATENT, +TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL BIGELOW & HOLMES INC. OR URW++ +GMBH. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, INCLUDING ANY +GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, WHETHER IN +AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF THE USE OR +INABILITY TO USE THE FONT SOFTWARE OR FROM OTHER DEALINGS IN THE FONT +SOFTWARE. + +Except as contained in this notice, the names of Bigelow & Holmes Inc. and +URW++ GmbH. shall not be used in advertising or otherwise to promote the sale, +use or other dealings in this Font Software without prior written +authorization from Bigelow & Holmes Inc. and URW++ GmbH. + +For further information, contact: + +info@urwpp.de or design@bigelowandholmes.com + + +--- end of LICENSE --- + +------------------------------------------------------------------------------- + +%% This notice is provided with respect to zlib v1.2.3, which is included +with JRE 7, JDK 7, and OpenJDK 7 + +--- begin of LICENSE --- + + version 1.2.3, July 18th, 2005 + + Copyright (C) 1995-2005 Jean-loup Gailly and Mark Adler + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jean-loup Gailly Mark Adler + jloup@gzip.org madler@alumni.caltech.edu + +--- end of LICENSE --- + +------------------------------------------------------------------------------- + +%% This notice is provided with respect to the following which is +included with JRE 7, JDK 7, and OpenJDK 7, except where noted: + + Apache Derby 10.8.1.2 [included with JDK 7 only] + Apache Jakarta BCEL 5.2 + Apache Jakarta Regexp 1.4 + Apache Santuario XMLSec-Java 1.4.2 + Apache Xalan-Java 2.7.1 + Apache Xerces2 Java 2.10.0 + Apache XML Resolver 1.1 + + +--- begin of LICENSE --- + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +--- end of LICENSE --- + +------------------------------------------------------------------------------- + diff -r 000000000000 -r a1985f14b030 dist/Makefile.in --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dist/Makefile.in Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,2715 @@ +# $Id$ +# +# Copyright (c) 1996, 2012 Oracle and/or its affiliates. All rights reserved. +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. Oracle designates this +# particular file as subject to the "Classpath" exception as provided +# by Oracle in the LICENSE file that accompanied this code. +# +# This code 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 General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. + +topdir= @topdir@ +srcdir= $(topdir)/src +langdir= $(topdir)/lang +exampledir= $(topdir)/examples +testdir= $(topdir)/test +utildir= $(topdir)/util +distdir= $(topdir)/dist +builddir=. + +################################################## +# Installation directories and permissions. +################################################## +prefix= @prefix@ +exec_prefix=@exec_prefix@ +bindir= @bindir@ +includedir=@includedir@ +libdir= @libdir@ +docdir= $(prefix)/docs + +dmode= 755 +emode= 555 +fmode= 444 + +transform=@program_transform_name@ + +################################################## +# Paths for standard user-level commands. +################################################## +AR= @AR@ +CHMOD= @CHMOD@ +CP= @CP@ +LN= @LN@ +MKDIR= @MKDIR@ +MV= @MV@ +RANLIB= @RANLIB@ +RM= @RM@ +SHELL= @db_cv_path_sh@ +STRIP= @STRIP@ +SED= @SED@ +PERL= @PERL@ + +################################################## +# General library information. +################################################## +DEF_LIB= @DEFAULT_LIB@ +DEF_LIB_CXX= @DEFAULT_LIB_CXX@ +DEF_LIB_SQL= @DEFAULT_LIB_SQL@ +DEF_LIB_SQLITE= @DEFAULT_LIB_SQLITE@ +DEF_LIB_STL= @DEFAULT_LIB_STL@ +DEF_LIB_TCL= @DEFAULT_LIB_TCL@ +INSTALLER= @INSTALLER@ +LIBTOOL= @LIBTOOL@ + +POSTLINK= @POSTLINK@ +SOLINK= @MAKEFILE_SOLINK@ @CFLAGS@ +SOFLAGS= @SOFLAGS@ +LIBMAJOR= @DB_VERSION_MAJOR@ +LIBVERSION= @DB_VERSION_MAJOR@.@DB_VERSION_MINOR@ + +CPPFLAGS= -I$(builddir) -I$(srcdir) @CPPFLAGS@ + +################################################## +# C API. +################################################## +CFLAGS= -c $(CPPFLAGS) @CFLAGS@ +CC= @MAKEFILE_CC@ +CCLINK= @MAKEFILE_CCLINK@ @CFLAGS@ + +LDFLAGS= @LDFLAGS@ +LIBS= @LIBSO_LIBS@ +TEST_LIBS= @TEST_LIBS@ +LIBCSO_LIBS= @LIBCSO_LIBS@ @LIBSO_LIBS@ + +libdb_base= libdb +libdb= $(libdb_base).a +libdb_version= $(libdb_base)-$(LIBVERSION).a +libso= $(libdb_base)-$(LIBVERSION)@SOSUFFIX@ +libso_target= $(libdb_base)-$(LIBVERSION).la +libso_default= $(libdb_base)@SOSUFFIX@ +libso_major= $(libdb_base)-$(LIBMAJOR)@SOSUFFIX@ + +################################################## +# C++ API. +# +# C++ support is optional, and can be built with static or shared libraries. +################################################## +CXXFLAGS= -c $(CPPFLAGS) @CXXFLAGS@ +CXX= @MAKEFILE_CXX@ +CXXLINK= @MAKEFILE_CXXLINK@ @CXXFLAGS@ +XSOLINK= @MAKEFILE_XSOLINK@ @CXXFLAGS@ +LIBXSO_LIBS= @LIBXSO_LIBS@ @LIBSO_LIBS@ + +libcxx_base= libdb_cxx +libcxx= $(libcxx_base).a +libcxx_version= $(libcxx_base)-$(LIBVERSION).a +libxso= $(libcxx_base)-$(LIBVERSION)@SOSUFFIX@ +libxso_target= $(libcxx_base)-$(LIBVERSION).la +libxso_default= $(libcxx_base)@SOSUFFIX@ +libxso_major= $(libcxx_base)-$(LIBMAJOR)@SOSUFFIX@ + +################################################## +# SQL API. +# +# SQL support is optional, and can be built with static or shared libraries. +################################################## +SQLFLAGS= -I$(builddir) -I$(builddir)/sql -I$(langdir)/sql/generated \ + -D_HAVE_SQLITE_CONFIG_H @SQL_FLAGS@ + +libsql_base= libdb_sql +libsql= $(libsql_base).a +libsql_version= $(libsql_base)-$(LIBVERSION).a +libsqlso= $(libsql_base)-$(LIBVERSION)@SOSUFFIX@ +libsqlso_target=$(libsql_base)-$(LIBVERSION).la +libsqlso_default=$(libsql_base)@SOSUFFIX@ +libsqlso_major= $(libsql_base)-$(LIBMAJOR)@SOSUFFIX@ + +libsqlite_base= libsqlite3 +libsqlite= $(libsqlite_base).a +libsqliteso= $(libsqlite_base)@SOSUFFIX@ +libsqliteso_target=$(libsqlite_base).la + +################################################## +# STL API. +# +# STL support is optional, and can be built with static or shared libraries. +################################################## +STLFLAGS= $(CXXFLAGS) -I$(langdir)/cxx/stl +LIBSTLSO_LIBS= @LIBXSO_LIBS@ @LIBSO_LIBS@ + +libstl_base= libdb_stl +libstl= $(libstl_base).a +libstl_version= $(libstl_base)-$(LIBVERSION).a +libstlso= $(libstl_base)-$(LIBVERSION)@SOSUFFIX@ +libstlso_target=$(libstl_base)-$(LIBVERSION).la +libstlso_default=$(libstl_base)@SOSUFFIX@ +libstlso_major= $(libstl_base)-$(LIBMAJOR)@SOSUFFIX@ + +################################################## +# Java API. +# +# Java support is optional and requires shared librarires. +################################################## +CLASSPATH= $(JAVA_CLASSTOP) +LIBJSO_LIBS= @LIBJSO_LIBS@ @LIBSO_LIBS@ +SWIGCFLAGS= @SWIGCFLAGS@ + +JAR= @JAR@ +JAVA= env CLASSPATH="$(CLASSPATH)" @JAVA@ +JAVAC= env CLASSPATH="$(CLASSPATH)" @JAVAC@ +JAVACFLAGS= @JAVACFLAGS@ +JAVA_CLASSTOP= ./classes +JAVA_EXCLASSTOP=./classes.ex +JAVA_SRCDIR= $(langdir)/java/src +JAVA_EXDIR= $(exampledir)/java/src +JAVA_SLEEPYCAT= $(langdir)/java/src/com/sleepycat +JAVA_MANIFEST= $(langdir)/java/jarManifestEntries + +libj_jarfile= db.jar +libj_exjarfile= dbexamples.jar +libjso_base= libdb_java +libjso= $(libjso_base)-$(LIBVERSION)@JMODSUFFIX@ +libjso_static= $(libjso_base)-$(LIBVERSION).a +libjso_target= $(libjso_base)-$(LIBVERSION).la +libjso_default= $(libjso_base)@JMODSUFFIX@ +libjso_major= $(libjso_base)-$(LIBMAJOR)@JMODSUFFIX@ +libjso_g= $(libjso_base)-$(LIBVERSION)_g@JMODSUFFIX@ + +################################################## +# TCL API. +# +# Tcl support is optional. +################################################## +TCL_INCLUDE_SPEC= @TCL_INCLUDE_SPEC@ +LIBTSO_LIBS= @LIBTSO_LIBS@ @LIBSO_LIBS@ +TCL_SRCDIR= $(langdir)/tcl +libtcl_base= libdb_tcl +libtcl= $(libtcl_base).a +libtcl_version= $(libtcl_base)-$(LIBVERSION).a +libtso= $(libtcl_base)-$(LIBVERSION)@LIBTSO_MODSUFFIX@ +libtso_target= $(libtcl_base)-$(LIBVERSION).la +libtso_default= $(libtcl_base)@LIBTSO_MODSUFFIX@ +libtso_major= $(libtcl_base)-$(LIBMAJOR)@LIBTSO_MODSUFFIX@ + +################################################## +# db_dump185 UTILITY +# +# The db_dump185 application should be compiled using the system's db.h file +# (which should be a DB 1.85/1.86 include file), and the system's 1.85/1.86 +# object library. To include the right db.h, don't include -I$(builddir) on +# the compile line. You may also need to add a local include directory and +# local libraries, for example. Do that by adding -I options to the DB185INC +# line, and -l options to the DB185LIB line. +################################################## +DB185INC= -c @CFLAGS@ -I$(topdir) @CPPFLAGS@ +DB185LIB= + +################################################## +# Performance Event Monitoring definitions +################################################## +DTRACE= @DTRACE@ +DTRACE_PROVIDER= $(distdir)/db_provider.d + +################################################## +# NOTHING BELOW THIS LINE SHOULD EVER NEED TO BE MODIFIED. +################################################## + +################################################## +# Object and utility lists. +################################################## +BTREE_VRFY_OBJS=\ + db_ovfl_vrfy@o@ db_vrfy@o@ db_vrfyutil@o@ bt_verify@o@ +HASH_OBJS=\ + hash@o@ hash_auto@o@ hash_compact@o@ hash_conv@o@ hash_dup@o@ \ + hash_meta@o@ hash_method@o@ hash_open@o@ hash_page@o@ hash_rec@o@ \ + hash_reclaim@o@ hash_stat@o@ hash_upgrade@o@ +HASH_VRFY_OBJS=\ + hash_verify@o@ +HEAP_OBJS=\ + heap@o@ heap_auto@o@ heap_backup@o@ heap_conv@o@ heap_method@o@ \ + heap_open@o@ heap_rec@o@ heap_reclaim@o@ heap_stat@o@ +HEAP_VRFY_OBJS=\ + heap_verify@o@ +QUEUE_OBJS=\ + qam@o@ qam_auto@o@ qam_conv@o@ qam_files@o@ qam_method@o@ \ + qam_open@o@ qam_rec@o@ qam_stat@o@ qam_upgrade@o@ +QUEUE_VRFY_OBJS=\ + qam_verify@o@ +LOCK_OBJS=\ + db_lock@o@ lock@o@ lock_deadlock@o@ lock_failchk@o@ lock_id@o@ \ + lock_list@o@ lock_method@o@ lock_region@o@ lock_stat@o@ lock_timer@o@ \ + lock_util@o@ +LOG_VRFY_OBJS=\ + log_verify@o@ log_verify_util@o@ log_verify_int@o@ \ + log_verify_auto@o@ +MUTEX_OBJS=\ + mut_alloc@o@ mut_method@o@ mut_region@o@ mut_stat@o@ +PARTITION_OBJS=\ + partition@o@ +REP_OBJS=\ + rep_automsg@o@ rep_backup@o@ rep_elect@o@ rep_lease@o@ rep_log@o@ \ + rep_method@o@ rep_record@o@ rep_region@o@ rep_stat@o@ \ + rep_util@o@ rep_verify@o@ +REPMGR_OBJS=\ + os_addrinfo@o@\ + repmgr_auto@o@ repmgr_automsg@o@ repmgr_elect@o@ \ + repmgr_method@o@ repmgr_msg@o@ \ + repmgr_net@o@ repmgr_posix@o@ repmgr_queue@o@ repmgr_rec@o@ \ + repmgr_sel@o@ repmgr_stat@o@ repmgr_util@o@ +PRINT_OBJS=\ + btree_autop@o@ crdel_autop@o@ db_autop@o@ dbreg_autop@o@ \ + fileops_autop@o@ hash_autop@o@ heap_autop@o@ qam_autop@o@ \ + repmgr_autop@o@ txn_autop@o@ +STD_OBJS=\ + bt_compact@o@ bt_compress@o@ bt_rec@o@ bt_upgrade@o@ btree_auto@o@ \ + crdel_auto@o@ crdel_rec@o@ db_auto@o@ db_backup@o@ db_cds@o@ \ + db_compact@o@ db_compint@o@ db_copy@o@ db_dispatch@o@ db_join@o@ \ + db_rec@o@ db_upg@o@ db_upg_opd@o@ dbreg@o@ dbreg_auto@o@ dbreg_rec@o@ \ + dbreg_stat@o@ dbreg_util@o@ env_backup@o@ env_failchk@o@ \ + env_recover@o@ env_register@o@ fileops_auto@o@ fop_rec@o@ \ + hmac@o@ log@o@ \ + log_archive@o@ log_compare@o@ log_debug@o@ log_get@o@ log_method@o@ \ + log_print@o@ log_put@o@ log_stat@o@ mp_backup@o@ mp_mvcc@o@ \ + mut_failchk@o@ openflags@o@ seq_stat@o@ sequence@o@ sha1@o@ txn@o@ txn_auto@o@ \ + txn_chkpt@o@ txn_failchk@o@ txn_method@o@ txn_rec@o@ txn_recover@o@ \ + txn_region@o@ txn_stat@o@ txn_util@o@ xa@o@ xa_map@o@ + +# When DTrace is enabled it may need to post-process (with -G) most of the +# object files in order to generate the additional objects in @FINAL_OBJS@. + +DTRACE_OBJS= @ADDITIONAL_OBJS@ @REPLACEMENT_OBJS@ @CRYPTO_OBJS@ \ + bt_compare@o@ bt_conv@o@ bt_curadj@o@ bt_cursor@o@ bt_delete@o@ \ + bt_method@o@ bt_open@o@ bt_put@o@ bt_reclaim@o@ bt_recno@o@ \ + bt_rsearch@o@ bt_search@o@ bt_split@o@ bt_stat@o@ clock@o@ db@o@ \ + db_am@o@ db_byteorder@o@ db_cam@o@ db_conv@o@ db_dup@o@ db_err@o@ \ + db_getlong@o@ db_idspace@o@ db_iface@o@ db_log2@o@ db_meta@o@ \ + db_method@o@ db_open@o@ db_overflow@o@ db_pr@o@ db_reclaim@o@ \ + db_remove@o@ db_rename@o@ db_ret@o@ db_setid@o@ db_setlsn@o@ \ + db_shash@o@ db_sort_multiple@o@ db_stati@o@ db_truncate@o@ dbt@o@ \ + env_alloc@o@ env_config@o@ env_file@o@ env_globals@o@ env_open@o@ \ + env_method@o@ env_name@o@ env_region@o@ env_sig@o@ env_stat@o@ \ + fop_basic@o@ fop_util@o@ hash_func@o@ mkpath@o@ mp_alloc@o@ \ + mp_bh@o@ mp_fget@o@ mp_fmethod@o@ mp_fopen@o@ mp_fput@o@ mp_fset@o@ \ + mp_method@o@ mp_region@o@ mp_register@o@ mp_resize@o@ mp_stat@o@ \ + mp_sync@o@ mp_trickle@o@ os_abort@o@ os_abs@o@ os_alloc@o@ \ + os_clock@o@ os_cpu@o@ os_ctime@o@ os_config@o@ os_dir@o@ os_errno@o@ \ + os_fid@o@ os_flock@o@ os_fsync@o@ os_getenv@o@ os_handle@o@ os_map@o@ \ + os_method@o@ os_mkdir@o@ os_open@o@ os_path@o@ os_pid@o@ os_rename@o@ \ + os_root@o@ os_rpath@o@ os_rw@o@ os_seek@o@ os_stack@o@ os_stat@o@ \ + os_tmpdir@o@ os_truncate@o@ os_uid@o@ os_unlink@o@ os_yield@o@ \ + snprintf@o@ zerofill@o@ + +C_OBJS= $(DTRACE_OBJS) @FINAL_OBJS@ + +CUTEST_OBJS=\ + CuTest@o@ CuTests@o@ Runner@o@ TestChannel@o@ TestDbHotBackup@o@ \ + TestDbTuner@o@ TestEncryption@o@ TestEnvConfig@o@ TestEnvMethod@o@ \ + TestKeyExistErrorReturn@o@ TestPartial@o@ TestQueue@o@ \ + +CXX_OBJS=\ + cxx_channel@o@ cxx_db@o@ cxx_dbc@o@ cxx_dbt@o@ cxx_env@o@ \ + cxx_except@o@ cxx_lock@o@ cxx_logc@o@ cxx_mpool@o@ cxx_multi@o@ \ + cxx_rid@o@ cxx_seq@o@ cxx_site@o@ cxx_txn@o@ + +CRYPTO_OBJS=\ + aes_method@o@ crypto@o@ mt19937db@o@ rijndael-alg-fst@o@ \ + rijndael-api-fst@o@ + +JAVA_OBJS=\ + db_java_wrap@o@ + +JAVA_DBSRCS=\ + $(JAVA_SLEEPYCAT)/asm/AnnotationVisitor.java \ + $(JAVA_SLEEPYCAT)/asm/AnnotationWriter.java \ + $(JAVA_SLEEPYCAT)/asm/Attribute.java \ + $(JAVA_SLEEPYCAT)/asm/ByteVector.java \ + $(JAVA_SLEEPYCAT)/asm/ClassReader.java \ + $(JAVA_SLEEPYCAT)/asm/ClassVisitor.java \ + $(JAVA_SLEEPYCAT)/asm/ClassWriter.java \ + $(JAVA_SLEEPYCAT)/asm/Edge.java \ + $(JAVA_SLEEPYCAT)/asm/FieldVisitor.java \ + $(JAVA_SLEEPYCAT)/asm/FieldWriter.java \ + $(JAVA_SLEEPYCAT)/asm/Frame.java \ + $(JAVA_SLEEPYCAT)/asm/Handle.java \ + $(JAVA_SLEEPYCAT)/asm/Handler.java \ + $(JAVA_SLEEPYCAT)/asm/Item.java \ + $(JAVA_SLEEPYCAT)/asm/Label.java \ + $(JAVA_SLEEPYCAT)/asm/MethodVisitor.java \ + $(JAVA_SLEEPYCAT)/asm/MethodWriter.java \ + $(JAVA_SLEEPYCAT)/asm/Opcodes.java \ + $(JAVA_SLEEPYCAT)/asm/Type.java \ + $(JAVA_SLEEPYCAT)/bind/ByteArrayBinding.java \ + $(JAVA_SLEEPYCAT)/bind/EntityBinding.java \ + $(JAVA_SLEEPYCAT)/bind/EntryBinding.java \ + $(JAVA_SLEEPYCAT)/bind/RecordNumberBinding.java \ + $(JAVA_SLEEPYCAT)/bind/serial/ClassCatalog.java \ + $(JAVA_SLEEPYCAT)/bind/serial/SerialBase.java \ + $(JAVA_SLEEPYCAT)/bind/serial/SerialBinding.java \ + $(JAVA_SLEEPYCAT)/bind/serial/SerialInput.java \ + $(JAVA_SLEEPYCAT)/bind/serial/SerialOutput.java \ + $(JAVA_SLEEPYCAT)/bind/serial/SerialSerialBinding.java \ + $(JAVA_SLEEPYCAT)/bind/serial/SerialSerialKeyCreator.java \ + $(JAVA_SLEEPYCAT)/bind/serial/StoredClassCatalog.java \ + $(JAVA_SLEEPYCAT)/bind/serial/TupleSerialBinding.java \ + $(JAVA_SLEEPYCAT)/bind/serial/TupleSerialKeyCreator.java \ + $(JAVA_SLEEPYCAT)/bind/serial/TupleSerialMarshalledBinding.java \ + $(JAVA_SLEEPYCAT)/bind/serial/TupleSerialMarshalledKeyCreator.java \ + $(JAVA_SLEEPYCAT)/bind/tuple/BigDecimalBinding.java \ + $(JAVA_SLEEPYCAT)/bind/tuple/BigIntegerBinding.java \ + $(JAVA_SLEEPYCAT)/bind/tuple/BooleanBinding.java \ + $(JAVA_SLEEPYCAT)/bind/tuple/ByteBinding.java \ + $(JAVA_SLEEPYCAT)/bind/tuple/CharacterBinding.java \ + $(JAVA_SLEEPYCAT)/bind/tuple/DoubleBinding.java \ + $(JAVA_SLEEPYCAT)/bind/tuple/FloatBinding.java \ + $(JAVA_SLEEPYCAT)/bind/tuple/IntegerBinding.java \ + $(JAVA_SLEEPYCAT)/bind/tuple/LongBinding.java \ + $(JAVA_SLEEPYCAT)/bind/tuple/MarshalledTupleEntry.java \ + $(JAVA_SLEEPYCAT)/bind/tuple/MarshalledTupleKeyEntity.java \ + $(JAVA_SLEEPYCAT)/bind/tuple/PackedIntegerBinding.java \ + $(JAVA_SLEEPYCAT)/bind/tuple/PackedLongBinding.java \ + $(JAVA_SLEEPYCAT)/bind/tuple/ShortBinding.java \ + $(JAVA_SLEEPYCAT)/bind/tuple/SortedBigDecimalBinding.java \ + $(JAVA_SLEEPYCAT)/bind/tuple/SortedDoubleBinding.java \ + $(JAVA_SLEEPYCAT)/bind/tuple/SortedFloatBinding.java \ + $(JAVA_SLEEPYCAT)/bind/tuple/SortedPackedIntegerBinding.java \ + $(JAVA_SLEEPYCAT)/bind/tuple/SortedPackedLongBinding.java \ + $(JAVA_SLEEPYCAT)/bind/tuple/StringBinding.java \ + $(JAVA_SLEEPYCAT)/bind/tuple/TupleBase.java \ + $(JAVA_SLEEPYCAT)/bind/tuple/TupleBinding.java \ + $(JAVA_SLEEPYCAT)/bind/tuple/TupleInput.java \ + $(JAVA_SLEEPYCAT)/bind/tuple/TupleInputBinding.java \ + $(JAVA_SLEEPYCAT)/bind/tuple/TupleMarshalledBinding.java \ + $(JAVA_SLEEPYCAT)/bind/tuple/TupleOutput.java \ + $(JAVA_SLEEPYCAT)/bind/tuple/TupleTupleBinding.java \ + $(JAVA_SLEEPYCAT)/bind/tuple/TupleTupleKeyCreator.java \ + $(JAVA_SLEEPYCAT)/bind/tuple/TupleTupleMarshalledBinding.java \ + $(JAVA_SLEEPYCAT)/bind/tuple/TupleTupleMarshalledKeyCreator.java \ + $(JAVA_SLEEPYCAT)/collections/BaseIterator.java \ + $(JAVA_SLEEPYCAT)/collections/BlockIterator.java \ + $(JAVA_SLEEPYCAT)/collections/CurrentTransaction.java \ + $(JAVA_SLEEPYCAT)/collections/DataCursor.java \ + $(JAVA_SLEEPYCAT)/collections/DataView.java \ + $(JAVA_SLEEPYCAT)/collections/MapEntryParameter.java \ + $(JAVA_SLEEPYCAT)/collections/MyRangeCursor.java \ + $(JAVA_SLEEPYCAT)/collections/PrimaryKeyAssigner.java \ + $(JAVA_SLEEPYCAT)/collections/StoredCollection.java \ + $(JAVA_SLEEPYCAT)/collections/StoredCollections.java \ + $(JAVA_SLEEPYCAT)/collections/StoredContainer.java \ + $(JAVA_SLEEPYCAT)/collections/StoredEntrySet.java \ + $(JAVA_SLEEPYCAT)/collections/StoredIterator.java \ + $(JAVA_SLEEPYCAT)/collections/StoredKeySet.java \ + $(JAVA_SLEEPYCAT)/collections/StoredList.java \ + $(JAVA_SLEEPYCAT)/collections/StoredMap.java \ + $(JAVA_SLEEPYCAT)/collections/StoredMapEntry.java \ + $(JAVA_SLEEPYCAT)/collections/StoredSortedEntrySet.java \ + $(JAVA_SLEEPYCAT)/collections/StoredSortedKeySet.java \ + $(JAVA_SLEEPYCAT)/collections/StoredSortedMap.java \ + $(JAVA_SLEEPYCAT)/collections/StoredSortedValueSet.java \ + $(JAVA_SLEEPYCAT)/collections/StoredValueSet.java \ + $(JAVA_SLEEPYCAT)/collections/TransactionRunner.java \ + $(JAVA_SLEEPYCAT)/collections/TransactionWorker.java \ + $(JAVA_SLEEPYCAT)/collections/TupleSerialFactory.java \ + $(JAVA_SLEEPYCAT)/compat/DbCompat.java \ + $(JAVA_SLEEPYCAT)/db/BackupHandler.java \ + $(JAVA_SLEEPYCAT)/db/BackupOptions.java \ + $(JAVA_SLEEPYCAT)/db/BtreeCompressor.java \ + $(JAVA_SLEEPYCAT)/db/BtreePrefixCalculator.java \ + $(JAVA_SLEEPYCAT)/db/BtreeStats.java \ + $(JAVA_SLEEPYCAT)/db/CacheFile.java \ + $(JAVA_SLEEPYCAT)/db/CacheFilePriority.java \ + $(JAVA_SLEEPYCAT)/db/CacheFileStats.java \ + $(JAVA_SLEEPYCAT)/db/CacheStats.java \ + $(JAVA_SLEEPYCAT)/db/ReplicationChannel.java \ + $(JAVA_SLEEPYCAT)/db/CheckpointConfig.java \ + $(JAVA_SLEEPYCAT)/db/CompactConfig.java \ + $(JAVA_SLEEPYCAT)/db/CompactStats.java \ + $(JAVA_SLEEPYCAT)/db/Cursor.java \ + $(JAVA_SLEEPYCAT)/db/CursorConfig.java \ + $(JAVA_SLEEPYCAT)/db/Database.java \ + $(JAVA_SLEEPYCAT)/db/DatabaseConfig.java \ + $(JAVA_SLEEPYCAT)/db/DatabaseEntry.java \ + $(JAVA_SLEEPYCAT)/db/DatabaseException.java \ + $(JAVA_SLEEPYCAT)/db/DatabaseStats.java \ + $(JAVA_SLEEPYCAT)/db/DatabaseType.java \ + $(JAVA_SLEEPYCAT)/db/DeadlockException.java \ + $(JAVA_SLEEPYCAT)/db/Environment.java \ + $(JAVA_SLEEPYCAT)/db/EnvironmentConfig.java \ + $(JAVA_SLEEPYCAT)/db/ErrorHandler.java \ + $(JAVA_SLEEPYCAT)/db/EventHandler.java \ + $(JAVA_SLEEPYCAT)/db/EventHandlerAdapter.java \ + $(JAVA_SLEEPYCAT)/db/FeedbackHandler.java \ + $(JAVA_SLEEPYCAT)/db/ForeignKeyDeleteAction.java \ + $(JAVA_SLEEPYCAT)/db/ForeignKeyNullifier.java \ + $(JAVA_SLEEPYCAT)/db/ForeignMultiKeyNullifier.java \ + $(JAVA_SLEEPYCAT)/db/HashStats.java \ + $(JAVA_SLEEPYCAT)/db/Hasher.java \ + $(JAVA_SLEEPYCAT)/db/HeapRecordId.java \ + $(JAVA_SLEEPYCAT)/db/HeapFullException.java \ + $(JAVA_SLEEPYCAT)/db/HeapStats.java \ + $(JAVA_SLEEPYCAT)/db/JoinConfig.java \ + $(JAVA_SLEEPYCAT)/db/JoinCursor.java \ + $(JAVA_SLEEPYCAT)/db/KeyRange.java \ + $(JAVA_SLEEPYCAT)/db/Lock.java \ + $(JAVA_SLEEPYCAT)/db/LockDetectMode.java \ + $(JAVA_SLEEPYCAT)/db/LockMode.java \ + $(JAVA_SLEEPYCAT)/db/LockNotGrantedException.java \ + $(JAVA_SLEEPYCAT)/db/LockOperation.java \ + $(JAVA_SLEEPYCAT)/db/LockRequest.java \ + $(JAVA_SLEEPYCAT)/db/LockRequestMode.java \ + $(JAVA_SLEEPYCAT)/db/LockStats.java \ + $(JAVA_SLEEPYCAT)/db/LogCursor.java \ + $(JAVA_SLEEPYCAT)/db/LogRecordHandler.java \ + $(JAVA_SLEEPYCAT)/db/LogSequenceNumber.java \ + $(JAVA_SLEEPYCAT)/db/LogStats.java \ + $(JAVA_SLEEPYCAT)/db/LogVerifyConfig.java \ + $(JAVA_SLEEPYCAT)/db/MemoryException.java \ + $(JAVA_SLEEPYCAT)/db/MessageHandler.java \ + $(JAVA_SLEEPYCAT)/db/MultipleNIODataEntry.java \ + $(JAVA_SLEEPYCAT)/db/MultipleKeyNIODataEntry.java \ + $(JAVA_SLEEPYCAT)/db/MultipleRecnoNIODataEntry.java \ + $(JAVA_SLEEPYCAT)/db/MultipleDataEntry.java \ + $(JAVA_SLEEPYCAT)/db/MultipleEntry.java \ + $(JAVA_SLEEPYCAT)/db/MultipleKeyDataEntry.java \ + $(JAVA_SLEEPYCAT)/db/MultipleRecnoDataEntry.java \ + $(JAVA_SLEEPYCAT)/db/MutexStats.java \ + $(JAVA_SLEEPYCAT)/db/OperationStatus.java \ + $(JAVA_SLEEPYCAT)/db/PanicHandler.java \ + $(JAVA_SLEEPYCAT)/db/PartitionHandler.java \ + $(JAVA_SLEEPYCAT)/db/PreparedTransaction.java \ + $(JAVA_SLEEPYCAT)/db/QueueStats.java \ + $(JAVA_SLEEPYCAT)/db/RecordNumberAppender.java \ + $(JAVA_SLEEPYCAT)/db/RecoveryOperation.java \ + $(JAVA_SLEEPYCAT)/db/RegionResourceType.java \ + $(JAVA_SLEEPYCAT)/db/ReplicationConfig.java \ + $(JAVA_SLEEPYCAT)/db/ReplicationDuplicateMasterException.java \ + $(JAVA_SLEEPYCAT)/db/ReplicationHandleDeadException.java \ + $(JAVA_SLEEPYCAT)/db/ReplicationHoldElectionException.java \ + $(JAVA_SLEEPYCAT)/db/ReplicationHostAddress.java \ + $(JAVA_SLEEPYCAT)/db/ReplicationJoinFailureException.java \ + $(JAVA_SLEEPYCAT)/db/ReplicationLeaseExpiredException.java \ + $(JAVA_SLEEPYCAT)/db/ReplicationLockoutException.java \ + $(JAVA_SLEEPYCAT)/db/ReplicationManagerAckPolicy.java \ + $(JAVA_SLEEPYCAT)/db/ReplicationManagerConnectionStatus.java \ + $(JAVA_SLEEPYCAT)/db/ReplicationManagerMessageDispatch.java \ + $(JAVA_SLEEPYCAT)/db/ReplicationManagerSite.java \ + $(JAVA_SLEEPYCAT)/db/ReplicationManagerSiteConfig.java \ + $(JAVA_SLEEPYCAT)/db/ReplicationManagerSiteInfo.java \ + $(JAVA_SLEEPYCAT)/db/ReplicationManagerStats.java \ + $(JAVA_SLEEPYCAT)/db/ReplicationManagerStartPolicy.java \ + $(JAVA_SLEEPYCAT)/db/ReplicationSiteUnavailableException.java \ + $(JAVA_SLEEPYCAT)/db/ReplicationStats.java \ + $(JAVA_SLEEPYCAT)/db/ReplicationStatus.java \ + $(JAVA_SLEEPYCAT)/db/ReplicationTimeoutType.java \ + $(JAVA_SLEEPYCAT)/db/ReplicationTransport.java \ + $(JAVA_SLEEPYCAT)/db/RunRecoveryException.java \ + $(JAVA_SLEEPYCAT)/db/SecondaryConfig.java \ + $(JAVA_SLEEPYCAT)/db/SecondaryCursor.java \ + $(JAVA_SLEEPYCAT)/db/SecondaryDatabase.java \ + $(JAVA_SLEEPYCAT)/db/SecondaryKeyCreator.java \ + $(JAVA_SLEEPYCAT)/db/SecondaryMultiKeyCreator.java \ + $(JAVA_SLEEPYCAT)/db/Sequence.java \ + $(JAVA_SLEEPYCAT)/db/SequenceConfig.java \ + $(JAVA_SLEEPYCAT)/db/SequenceStats.java \ + $(JAVA_SLEEPYCAT)/db/StatsConfig.java \ + $(JAVA_SLEEPYCAT)/db/Transaction.java \ + $(JAVA_SLEEPYCAT)/db/TransactionConfig.java \ + $(JAVA_SLEEPYCAT)/db/TransactionStats.java \ + $(JAVA_SLEEPYCAT)/db/TransactionStatus.java \ + $(JAVA_SLEEPYCAT)/db/VerboseConfig.java \ + $(JAVA_SLEEPYCAT)/db/VerifyConfig.java \ + $(JAVA_SLEEPYCAT)/db/VersionMismatchException.java \ + $(JAVA_SLEEPYCAT)/db/internal/Db.java \ + $(JAVA_SLEEPYCAT)/db/internal/DbConstants.java \ + $(JAVA_SLEEPYCAT)/db/internal/DbChannel.java \ + $(JAVA_SLEEPYCAT)/db/internal/DbEnv.java \ + $(JAVA_SLEEPYCAT)/db/internal/DbLock.java \ + $(JAVA_SLEEPYCAT)/db/internal/DbLogc.java \ + $(JAVA_SLEEPYCAT)/db/internal/DbMpoolFile.java \ + $(JAVA_SLEEPYCAT)/db/internal/DbSequence.java \ + $(JAVA_SLEEPYCAT)/db/internal/DbSite.java \ + $(JAVA_SLEEPYCAT)/db/internal/DbTxn.java \ + $(JAVA_SLEEPYCAT)/db/internal/DbUtil.java \ + $(JAVA_SLEEPYCAT)/db/internal/Dbc.java \ + $(JAVA_SLEEPYCAT)/db/internal/db_java.java \ + $(JAVA_SLEEPYCAT)/db/internal/db_javaJNI.java \ + $(JAVA_SLEEPYCAT)/persist/BasicCursor.java \ + $(JAVA_SLEEPYCAT)/persist/BasicIndex.java \ + $(JAVA_SLEEPYCAT)/persist/BasicIterator.java \ + $(JAVA_SLEEPYCAT)/persist/DataValueAdapter.java \ + $(JAVA_SLEEPYCAT)/persist/DatabaseNamer.java \ + $(JAVA_SLEEPYCAT)/persist/EntityCursor.java \ + $(JAVA_SLEEPYCAT)/persist/EntityIndex.java \ + $(JAVA_SLEEPYCAT)/persist/EntityJoin.java \ + $(JAVA_SLEEPYCAT)/persist/EntityStore.java \ + $(JAVA_SLEEPYCAT)/persist/EntityValueAdapter.java \ + $(JAVA_SLEEPYCAT)/persist/ForwardCursor.java \ + $(JAVA_SLEEPYCAT)/persist/IndexNotAvailableException.java \ + $(JAVA_SLEEPYCAT)/persist/KeySelector.java \ + $(JAVA_SLEEPYCAT)/persist/KeyValueAdapter.java \ + $(JAVA_SLEEPYCAT)/persist/KeysIndex.java \ + $(JAVA_SLEEPYCAT)/persist/PrimaryIndex.java \ + $(JAVA_SLEEPYCAT)/persist/PrimaryKeyValueAdapter.java \ + $(JAVA_SLEEPYCAT)/persist/SecondaryIndex.java \ + $(JAVA_SLEEPYCAT)/persist/StoreConfig.java \ + $(JAVA_SLEEPYCAT)/persist/StoreConfigBeanInfo.java \ + $(JAVA_SLEEPYCAT)/persist/StoreExistsException.java \ + $(JAVA_SLEEPYCAT)/persist/StoreNotFoundException.java \ + $(JAVA_SLEEPYCAT)/persist/SubIndex.java \ + $(JAVA_SLEEPYCAT)/persist/SubIndexCursor.java \ + $(JAVA_SLEEPYCAT)/persist/ValueAdapter.java \ + $(JAVA_SLEEPYCAT)/persist/evolve/Conversion.java \ + $(JAVA_SLEEPYCAT)/persist/evolve/Converter.java \ + $(JAVA_SLEEPYCAT)/persist/evolve/DeletedClassException.java \ + $(JAVA_SLEEPYCAT)/persist/evolve/Deleter.java \ + $(JAVA_SLEEPYCAT)/persist/evolve/EntityConverter.java \ + $(JAVA_SLEEPYCAT)/persist/evolve/EvolveConfig.java \ + $(JAVA_SLEEPYCAT)/persist/evolve/EvolveConfigBeanInfo.java \ + $(JAVA_SLEEPYCAT)/persist/evolve/EvolveEvent.java \ + $(JAVA_SLEEPYCAT)/persist/evolve/EvolveInternal.java \ + $(JAVA_SLEEPYCAT)/persist/evolve/EvolveListener.java \ + $(JAVA_SLEEPYCAT)/persist/evolve/EvolveStats.java \ + $(JAVA_SLEEPYCAT)/persist/evolve/IncompatibleClassException.java \ + $(JAVA_SLEEPYCAT)/persist/evolve/Mutation.java \ + $(JAVA_SLEEPYCAT)/persist/evolve/Mutations.java \ + $(JAVA_SLEEPYCAT)/persist/evolve/Renamer.java \ + $(JAVA_SLEEPYCAT)/persist/impl/AbstractInput.java \ + $(JAVA_SLEEPYCAT)/persist/impl/Accessor.java \ + $(JAVA_SLEEPYCAT)/persist/impl/Catalog.java \ + $(JAVA_SLEEPYCAT)/persist/impl/CollectionProxy.java \ + $(JAVA_SLEEPYCAT)/persist/impl/ComplexFormat.java \ + $(JAVA_SLEEPYCAT)/persist/impl/ComparatorCatalog.java \ + $(JAVA_SLEEPYCAT)/persist/impl/CompositeKeyFormat.java \ + $(JAVA_SLEEPYCAT)/persist/impl/ConverterReader.java \ + $(JAVA_SLEEPYCAT)/persist/impl/Enhanced.java \ + $(JAVA_SLEEPYCAT)/persist/impl/EnhancedAccessor.java \ + $(JAVA_SLEEPYCAT)/persist/impl/EntityInput.java \ + $(JAVA_SLEEPYCAT)/persist/impl/EntityOutput.java \ + $(JAVA_SLEEPYCAT)/persist/impl/EnumFormat.java \ + $(JAVA_SLEEPYCAT)/persist/impl/Evolver.java \ + $(JAVA_SLEEPYCAT)/persist/impl/FieldInfo.java \ + $(JAVA_SLEEPYCAT)/persist/impl/Format.java \ + $(JAVA_SLEEPYCAT)/persist/impl/KeyLocation.java \ + $(JAVA_SLEEPYCAT)/persist/impl/MapProxy.java \ + $(JAVA_SLEEPYCAT)/persist/impl/NonPersistentFormat.java \ + $(JAVA_SLEEPYCAT)/persist/impl/ObjectArrayFormat.java \ + $(JAVA_SLEEPYCAT)/persist/impl/PersistCatalog.java \ + $(JAVA_SLEEPYCAT)/persist/impl/PersistComparator.java \ + $(JAVA_SLEEPYCAT)/persist/impl/PersistEntityBinding.java \ + $(JAVA_SLEEPYCAT)/persist/impl/PersistKeyAssigner.java \ + $(JAVA_SLEEPYCAT)/persist/impl/PersistKeyBinding.java \ + $(JAVA_SLEEPYCAT)/persist/impl/PersistKeyCreator.java \ + $(JAVA_SLEEPYCAT)/persist/impl/PrimitiveArrayFormat.java \ + $(JAVA_SLEEPYCAT)/persist/impl/ProxiedFormat.java \ + $(JAVA_SLEEPYCAT)/persist/impl/RawAbstractInput.java \ + $(JAVA_SLEEPYCAT)/persist/impl/RawAccessor.java \ + $(JAVA_SLEEPYCAT)/persist/impl/RawArrayInput.java \ + $(JAVA_SLEEPYCAT)/persist/impl/RawComplexInput.java \ + $(JAVA_SLEEPYCAT)/persist/impl/RawSingleInput.java \ + $(JAVA_SLEEPYCAT)/persist/impl/ReadOnlyCatalog.java \ + $(JAVA_SLEEPYCAT)/persist/impl/Reader.java \ + $(JAVA_SLEEPYCAT)/persist/impl/RecordInput.java \ + $(JAVA_SLEEPYCAT)/persist/impl/RecordOutput.java \ + $(JAVA_SLEEPYCAT)/persist/impl/ReflectionAccessor.java \ + $(JAVA_SLEEPYCAT)/persist/impl/RefreshException.java \ + $(JAVA_SLEEPYCAT)/persist/impl/SimpleCatalog.java \ + $(JAVA_SLEEPYCAT)/persist/impl/SimpleFormat.java \ + $(JAVA_SLEEPYCAT)/persist/impl/Store.java \ + $(JAVA_SLEEPYCAT)/persist/impl/StoredModel.java \ + $(JAVA_SLEEPYCAT)/persist/impl/VisitedObjects.java \ + $(JAVA_SLEEPYCAT)/persist/impl/WidenerInput.java \ + $(JAVA_SLEEPYCAT)/persist/model/AnnotationModel.java \ + $(JAVA_SLEEPYCAT)/persist/model/BytecodeEnhancer.java \ + $(JAVA_SLEEPYCAT)/persist/model/ClassEnhancer.java \ + $(JAVA_SLEEPYCAT)/persist/model/ClassMetadata.java \ + $(JAVA_SLEEPYCAT)/persist/model/DeleteAction.java \ + $(JAVA_SLEEPYCAT)/persist/model/Entity.java \ + $(JAVA_SLEEPYCAT)/persist/model/EntityMetadata.java \ + $(JAVA_SLEEPYCAT)/persist/model/EntityModel.java \ + $(JAVA_SLEEPYCAT)/persist/model/FieldMetadata.java \ + $(JAVA_SLEEPYCAT)/persist/model/KeyField.java \ + $(JAVA_SLEEPYCAT)/persist/model/ModelInternal.java \ + $(JAVA_SLEEPYCAT)/persist/model/NotPersistent.java \ + $(JAVA_SLEEPYCAT)/persist/model/NotTransient.java \ + $(JAVA_SLEEPYCAT)/persist/model/Persistent.java \ + $(JAVA_SLEEPYCAT)/persist/model/PersistentProxy.java \ + $(JAVA_SLEEPYCAT)/persist/model/PrimaryKey.java \ + $(JAVA_SLEEPYCAT)/persist/model/PrimaryKeyMetadata.java \ + $(JAVA_SLEEPYCAT)/persist/model/Relationship.java \ + $(JAVA_SLEEPYCAT)/persist/model/SecondaryKey.java \ + $(JAVA_SLEEPYCAT)/persist/model/SecondaryKeyMetadata.java \ + $(JAVA_SLEEPYCAT)/persist/raw/RawField.java \ + $(JAVA_SLEEPYCAT)/persist/raw/RawObject.java \ + $(JAVA_SLEEPYCAT)/persist/raw/RawStore.java \ + $(JAVA_SLEEPYCAT)/persist/raw/RawType.java \ + $(JAVA_SLEEPYCAT)/util/ClassResolver.java \ + $(JAVA_SLEEPYCAT)/util/ConfigBeanInfoBase.java \ + $(JAVA_SLEEPYCAT)/util/ErrorBuffer.java \ + $(JAVA_SLEEPYCAT)/util/ExceptionUnwrapper.java \ + $(JAVA_SLEEPYCAT)/util/ExceptionWrapper.java \ + $(JAVA_SLEEPYCAT)/util/FastInputStream.java \ + $(JAVA_SLEEPYCAT)/util/FastOutputStream.java \ + $(JAVA_SLEEPYCAT)/util/IOExceptionWrapper.java \ + $(JAVA_SLEEPYCAT)/util/PackedInteger.java \ + $(JAVA_SLEEPYCAT)/util/RuntimeExceptionWrapper.java \ + $(JAVA_SLEEPYCAT)/util/UtfOps.java \ + $(JAVA_SLEEPYCAT)/util/keyrange/KeyRange.java \ + $(JAVA_SLEEPYCAT)/util/keyrange/KeyRangeException.java \ + $(JAVA_SLEEPYCAT)/util/keyrange/RangeCursor.java + +JAVA_EXSRCS=\ + $(JAVA_EXDIR)/collections/access/AccessExample.java \ + $(JAVA_EXDIR)/collections/hello/HelloDatabaseWorld.java \ + $(JAVA_EXDIR)/collections/ship/basic/PartData.java \ + $(JAVA_EXDIR)/collections/ship/basic/PartKey.java \ + $(JAVA_EXDIR)/collections/ship/basic/Sample.java \ + $(JAVA_EXDIR)/collections/ship/basic/SampleDatabase.java \ + $(JAVA_EXDIR)/collections/ship/basic/SampleViews.java \ + $(JAVA_EXDIR)/collections/ship/basic/ShipmentData.java \ + $(JAVA_EXDIR)/collections/ship/basic/ShipmentKey.java \ + $(JAVA_EXDIR)/collections/ship/basic/SupplierData.java \ + $(JAVA_EXDIR)/collections/ship/basic/SupplierKey.java \ + $(JAVA_EXDIR)/collections/ship/basic/Weight.java \ + $(JAVA_EXDIR)/collections/ship/entity/Part.java \ + $(JAVA_EXDIR)/collections/ship/entity/PartData.java \ + $(JAVA_EXDIR)/collections/ship/entity/PartKey.java \ + $(JAVA_EXDIR)/collections/ship/entity/Sample.java \ + $(JAVA_EXDIR)/collections/ship/entity/SampleDatabase.java \ + $(JAVA_EXDIR)/collections/ship/entity/SampleViews.java \ + $(JAVA_EXDIR)/collections/ship/entity/Shipment.java \ + $(JAVA_EXDIR)/collections/ship/entity/ShipmentData.java \ + $(JAVA_EXDIR)/collections/ship/entity/ShipmentKey.java \ + $(JAVA_EXDIR)/collections/ship/entity/Supplier.java \ + $(JAVA_EXDIR)/collections/ship/entity/SupplierData.java \ + $(JAVA_EXDIR)/collections/ship/entity/SupplierKey.java \ + $(JAVA_EXDIR)/collections/ship/entity/Weight.java \ + $(JAVA_EXDIR)/collections/ship/factory/Part.java \ + $(JAVA_EXDIR)/collections/ship/factory/PartKey.java \ + $(JAVA_EXDIR)/collections/ship/factory/Sample.java \ + $(JAVA_EXDIR)/collections/ship/factory/SampleDatabase.java \ + $(JAVA_EXDIR)/collections/ship/factory/SampleViews.java \ + $(JAVA_EXDIR)/collections/ship/factory/Shipment.java \ + $(JAVA_EXDIR)/collections/ship/factory/ShipmentKey.java \ + $(JAVA_EXDIR)/collections/ship/factory/Supplier.java \ + $(JAVA_EXDIR)/collections/ship/factory/SupplierKey.java \ + $(JAVA_EXDIR)/collections/ship/factory/Weight.java \ + $(JAVA_EXDIR)/collections/ship/index/PartData.java \ + $(JAVA_EXDIR)/collections/ship/index/PartKey.java \ + $(JAVA_EXDIR)/collections/ship/index/Sample.java \ + $(JAVA_EXDIR)/collections/ship/index/SampleDatabase.java \ + $(JAVA_EXDIR)/collections/ship/index/SampleViews.java \ + $(JAVA_EXDIR)/collections/ship/index/ShipmentData.java \ + $(JAVA_EXDIR)/collections/ship/index/ShipmentKey.java \ + $(JAVA_EXDIR)/collections/ship/index/SupplierData.java \ + $(JAVA_EXDIR)/collections/ship/index/SupplierKey.java \ + $(JAVA_EXDIR)/collections/ship/index/Weight.java \ + $(JAVA_EXDIR)/collections/ship/marshal/MarshalledEnt.java \ + $(JAVA_EXDIR)/collections/ship/marshal/MarshalledKey.java \ + $(JAVA_EXDIR)/collections/ship/marshal/Part.java \ + $(JAVA_EXDIR)/collections/ship/marshal/PartKey.java \ + $(JAVA_EXDIR)/collections/ship/marshal/Sample.java \ + $(JAVA_EXDIR)/collections/ship/marshal/SampleDatabase.java \ + $(JAVA_EXDIR)/collections/ship/marshal/SampleViews.java \ + $(JAVA_EXDIR)/collections/ship/marshal/Shipment.java \ + $(JAVA_EXDIR)/collections/ship/marshal/ShipmentKey.java \ + $(JAVA_EXDIR)/collections/ship/marshal/Supplier.java \ + $(JAVA_EXDIR)/collections/ship/marshal/SupplierKey.java \ + $(JAVA_EXDIR)/collections/ship/marshal/Weight.java \ + $(JAVA_EXDIR)/collections/ship/sentity/Part.java \ + $(JAVA_EXDIR)/collections/ship/sentity/PartKey.java \ + $(JAVA_EXDIR)/collections/ship/sentity/Sample.java \ + $(JAVA_EXDIR)/collections/ship/sentity/SampleDatabase.java \ + $(JAVA_EXDIR)/collections/ship/sentity/SampleViews.java \ + $(JAVA_EXDIR)/collections/ship/sentity/Shipment.java \ + $(JAVA_EXDIR)/collections/ship/sentity/ShipmentKey.java \ + $(JAVA_EXDIR)/collections/ship/sentity/Supplier.java \ + $(JAVA_EXDIR)/collections/ship/sentity/SupplierKey.java \ + $(JAVA_EXDIR)/collections/ship/sentity/Weight.java \ + $(JAVA_EXDIR)/collections/ship/tuple/Part.java \ + $(JAVA_EXDIR)/collections/ship/tuple/PartData.java \ + $(JAVA_EXDIR)/collections/ship/tuple/PartKey.java \ + $(JAVA_EXDIR)/collections/ship/tuple/Sample.java \ + $(JAVA_EXDIR)/collections/ship/tuple/SampleDatabase.java \ + $(JAVA_EXDIR)/collections/ship/tuple/SampleViews.java \ + $(JAVA_EXDIR)/collections/ship/tuple/Shipment.java \ + $(JAVA_EXDIR)/collections/ship/tuple/ShipmentData.java \ + $(JAVA_EXDIR)/collections/ship/tuple/ShipmentKey.java \ + $(JAVA_EXDIR)/collections/ship/tuple/Supplier.java \ + $(JAVA_EXDIR)/collections/ship/tuple/SupplierData.java \ + $(JAVA_EXDIR)/collections/ship/tuple/SupplierKey.java \ + $(JAVA_EXDIR)/collections/ship/tuple/Weight.java \ + $(JAVA_EXDIR)/db/AccessExample.java \ + $(JAVA_EXDIR)/db/BtRecExample.java \ + $(JAVA_EXDIR)/db/BulkAccessExample.java \ + $(JAVA_EXDIR)/db/BulkAccessNIOExample.java \ + $(JAVA_EXDIR)/db/BulkExample.java \ + $(JAVA_EXDIR)/db/EnvExample.java \ + $(JAVA_EXDIR)/db/GettingStarted/ExampleDatabaseLoad.java \ + $(JAVA_EXDIR)/db/GettingStarted/ExampleDatabaseRead.java \ + $(JAVA_EXDIR)/db/GettingStarted/Inventory.java \ + $(JAVA_EXDIR)/db/GettingStarted/InventoryBinding.java \ + $(JAVA_EXDIR)/db/GettingStarted/ItemNameKeyCreator.java \ + $(JAVA_EXDIR)/db/GettingStarted/MyDbs.java \ + $(JAVA_EXDIR)/db/GettingStarted/Vendor.java \ + $(JAVA_EXDIR)/db/LockExample.java \ + $(JAVA_EXDIR)/db/SequenceExample.java \ + $(JAVA_EXDIR)/db/TpcbExample.java \ + $(JAVA_EXDIR)/db/repquote/RepConfig.java \ + $(JAVA_EXDIR)/db/repquote/RepQuoteEnvironment.java \ + $(JAVA_EXDIR)/db/repquote/RepQuoteExample.java \ + $(JAVA_EXDIR)/db/repquote/RepRemoteHost.java \ + $(JAVA_EXDIR)/db/repquote_gsg/RepConfig.java \ + $(JAVA_EXDIR)/db/repquote_gsg/RepQuoteEnvironment.java \ + $(JAVA_EXDIR)/db/repquote_gsg/RepQuoteExampleGSG.java \ + $(JAVA_EXDIR)/db/repquote_gsg/SimpleConfig.java \ + $(JAVA_EXDIR)/db/repquote_gsg/SimpleTxn.java \ + $(JAVA_EXDIR)/db/txn/DBWriter.java \ + $(JAVA_EXDIR)/db/txn/PayloadData.java \ + $(JAVA_EXDIR)/db/txn/TxnGuide.java \ + $(JAVA_EXDIR)/db/txn/TxnGuideInMemory.java \ + $(JAVA_EXDIR)/persist/CustomKeyOrderExample.java \ + $(JAVA_EXDIR)/persist/DplDump.java \ + $(JAVA_EXDIR)/persist/EventExample.java \ + $(JAVA_EXDIR)/persist/EventExampleDPL.java \ + $(JAVA_EXDIR)/persist/PersonExample.java \ + $(JAVA_EXDIR)/persist/gettingStarted/SimpleDA.java \ + $(JAVA_EXDIR)/persist/gettingStarted/SimpleEntityClass.java \ + $(JAVA_EXDIR)/persist/gettingStarted/SimpleStoreGet.java \ + $(JAVA_EXDIR)/persist/gettingStarted/SimpleStorePut.java \ + $(JAVA_EXDIR)/persist/txn/PayloadDataEntity.java \ + $(JAVA_EXDIR)/persist/txn/StoreWriter.java \ + $(JAVA_EXDIR)/persist/txn/TxnGuideDPL.java + +SQL_OBJS=\ + sqlite3@o@ $(C_OBJS) + +STL_OBJS=\ + dbstl_container@o@ dbstl_resource_manager@o@ + +TCL_STD_OBJS=\ + tcl_lock@o@ tcl_log@o@ tcl_mp@o@ tcl_mutex@o@ \ + tcl_rep@o@ tcl_seq@o@ tcl_txn@o@ + +TCL_OBJS=\ + tcl_compat@o@ tcl_db@o@ tcl_db_pkg@o@ tcl_dbcursor@o@ tcl_env@o@ \ + tcl_internal@o@ tcl_util@o@ \ + @TCL_ADDITIONAL_OBJS@ + +TEST_MICRO_OBJS=\ + b_curalloc@o@ b_curwalk@o@ b_del@o@ b_get@o@ b_inmem@o@ b_latch@o@ \ + b_load@o@ b_open@o@ b_put@o@ b_recover@o@ b_txn@o@ b_txn_write@o@ \ + b_uname@o@ b_util@o@ b_workload@o@ test_micro@o@ util_arg@o@ + + +STD_PROGS=\ + db_archive db_checkpoint db_deadlock \ + db_hotbackup db_log_verify db_printlog db_recover \ + db_replicate db_tuner db_upgrade + +UTIL_PROGS=\ + db_dump db_load db_stat db_verify \ + @ADDITIONAL_PROGS@ + +################################################## +# List of files installed into the library directory. +################################################## +LIB_INSTALL_FILE_LIST=\ + $(libdb) \ + $(libso) \ + $(libso_default) \ + $(libso_major) \ + $(libdb_version) \ + $(libcxx) \ + $(libxso) \ + $(libxso_default) \ + $(libxso_major) \ + $(libcxx_version) \ + $(libsql) \ + $(libsqlso) \ + $(libsqlso_default) \ + $(libsqlso_major) \ + $(libsql_version) \ + $(libstl) \ + $(libstlso) \ + $(libstlso_default) \ + $(libstlso_major) \ + $(libstl_version) \ + $(libtcl) \ + $(libtso) \ + $(libtso_default) \ + $(libtso_major) \ + $(libtcl_version) \ + $(libjso) \ + $(libjso_default) \ + $(libjso_g) \ + $(libjso_major) \ + $(libjso_static) \ + $(libj_exjarfile) \ + $(libj_jarfile) \ + @INSTALL_LIBS@ @INSTALL_LIBS_EXTRA@ + +################################################## +# Note: "all" must be the first target in the Makefile. +################################################## +all: @BUILD_TARGET@ + +install: all @INSTALL_TARGET@ + +################################################## +# Library and standard utilities build. +################################################## +library_build: @INSTALL_LIBS@ @ADDITIONAL_LANG@ $(UTIL_PROGS) + +# Static C library named libdb.a. +$(libdb): $(DEF_LIB) + +# Real static C library. +$(libdb_version): $(C_OBJS) + $(AR) cr $@ $(C_OBJS) + $(RANLIB) $@ + $(RM) $(libdb) + $(LN) -s $(libdb_version) $(libdb) + +# Shared C library. +$(libso_target): $(C_OBJS) + $(SOLINK) $(SOFLAGS) $(LDFLAGS) -o $@ $(C_OBJS) \ + $(LIBCSO_LIBS) + $(RM) $(libdb) + $(LN) -s .libs/$(libdb_version) $(libdb) + +# Static C++ library named libdb_cxx.a. +$(libcxx): $(DEF_LIB_CXX) + +# Real static C++ library. +$(libcxx_version): $(CXX_OBJS) $(C_OBJS) + $(AR) cr $@ $(CXX_OBJS) $(C_OBJS) + $(RANLIB) $@ + $(RM) $(libcxx) + $(LN) -s $(libcxx_version) $(libcxx) + +# Shared C++ library. +$(libxso_target): $(CXX_OBJS) $(C_OBJS) + $(XSOLINK) $(SOFLAGS) $(LDFLAGS) \ + -o $@ $(CXX_OBJS) $(C_OBJS) $(LIBXSO_LIBS) + $(RM) $(libcxx) + $(LN) -s .libs/$(libcxx_version) $(libcxx) + +# Static SQL library named libdb_sql.a. +$(libsql): $(DEF_LIB_SQL) + +# Static SQL library. +$(libsql_version): $(SQL_OBJS) + $(AR) cr $@ $(SQL_OBJS) + $(RANLIB) $@ + $(RM) $(libsql) + $(LN) -s $(libsql_version) $(libsql) + +# Shared SQL library. +$(libsqlso_target): $(SQL_OBJS) + $(SOLINK) $(SOFLAGS) $(LDFLAGS) -o $@ $(SQL_OBJS) $(LIBCSO_LIBS) + $(RM) $(libsql) + $(LN) -s .libs/$(libsql_version) $(libsql) + +dbsql: shell@o@ $(DEF_LIB_SQL) + $(CCLINK) -o $@ $(LDFLAGS) shell@o@ $(DEF_LIB_SQL) @SQL_LIBS@ $(LIBS) + $(POSTLINK) $@ + +jdbc: $(DEF_LIB) + @(test -d jdbc && cd jdbc && PWD='.' $(MAKE)) + +sql-test: $(DEF_LIB) + @(cd sql && $(MAKE) LTLINK_EXTRAS="../$(DEF_LIB) $(LIBS)" testfixture@EXEEXT@) + +# SQL API header file to be installed +# Some configurations of Solaris make don't handle $< as an explicit dependency +# so duplicate the name in the rule. +dbsql.h: $(langdir)/sql/generated/sqlite3.h + $(CP) $(langdir)/sql/generated/sqlite3.h $@ + +# SQLite drop-in replacements +$(libsqlite): $(SQL_OBJS) + $(AR) cr $@ $(SQL_OBJS) + $(RANLIB) $@ + +$(libsqliteso_target): $(SQL_OBJS) + $(SOLINK) $(SOFLAGS) $(LDFLAGS) -version-info "8:6:8" -o $@ \ + $(SQL_OBJS) $(LIBCSO_LIBS) + +sqlite3: shell@o@ $(DEF_LIB_SQLITE) + $(CCLINK) -o $@ $(LDFLAGS) shell@o@ $(DEF_LIB_SQLITE) @SQL_LIBS@ $(LIBS) + $(POSTLINK) $@ + +# Static STL library named libdb_stl.a. +$(libstl): $(DEF_LIB_STL) + +# Real static STL library. +$(libstl_version): $(STL_OBJS) $(CXX_OBJS) $(C_OBJS) + $(AR) cr $@ $(STL_OBJS) $(CXX_OBJS) $(C_OBJS) + $(RANLIB) $@ + $(RM) $(libstl) + $(LN) -s $(libstl_version) $(libstl) + +# Shared STL library. +$(libstlso_target): $(STL_OBJS) $(CXX_OBJS) $(C_OBJS) + $(XSOLINK) $(SOFLAGS) $(LDFLAGS) -o $@ $(STL_OBJS) \ + $(LIBSTLSO_LIBS) $(CXX_OBJS) $(C_OBJS) $(LIBXSO_LIBS) + $(RM) $(libstl) + $(LN) -s .libs/$(libstl_version) $(libstl) + +# Shared Java library. +$(libjso_target): $(JAVA_OBJS) $(C_OBJS) + $(SOLINK) -shrext @JMODSUFFIX@ $(SOFLAGS) $(LDFLAGS) \ + -o $@ $(JAVA_OBJS) $(C_OBJS) $(LIBJSO_LIBS) + +# Static Tcl library +$(libtcl): $(DEF_LIB_TCL) + +# Real static Tcl library. +$(libtcl_version): $(TCL_OBJS) $(C_OBJS) + $(AR) cr $@ $(TCL_OBJS) $(C_OBJS) + $(RANLIB) $@ + $(RM) $(libtcl) + $(LN) -s $(libtcl_version) $(libtcl) + +# Shared Tcl library. +$(libtso_target): $(TCL_OBJS) $(C_OBJS) + $(SOLINK) @LIBTSO_MODULE@ $(SOFLAGS) $(LDFLAGS) \ + -o $@ $(TCL_OBJS) $(C_OBJS) $(LIBTSO_LIBS) + $(RM) $(libtcl) + $(LN) -s .libs/$(libtcl_version) $(libtcl) + +################################################## +# Creating individual dependencies and actions for building class +# files is possible, but it is very messy and error prone. +################################################## +java: $(libj_jarfile) $(libj_exjarfile) + +$(libj_jarfile): $(JAVA_DBSRCS) + @test -d $(JAVA_CLASSTOP) || \ + ($(MKDIR) -p $(JAVA_CLASSTOP) && \ + $(CHMOD) $(dmode) $(JAVA_CLASSTOP)) + $(JAVAC) -d $(JAVA_CLASSTOP) $(JAVACFLAGS) $(JAVA_DBSRCS) + $(JAVA) -classpath $(JAVA_CLASSTOP) \ + com.sleepycat.persist.model.ClassEnhancer $(JAVA_CLASSTOP) + cd $(JAVA_CLASSTOP) && \ + $(JAR) cfm ../$(libj_jarfile) ../$(JAVA_MANIFEST) ./com/sleepycat + +$(libj_exjarfile): $(libj_jarfile) $(JAVA_EXSRCS) + @test -d $(JAVA_EXCLASSTOP) || \ + ($(MKDIR) -p $(JAVA_EXCLASSTOP) && \ + $(CHMOD) $(dmode) $(JAVA_EXCLASSTOP)) + $(JAVAC) -classpath $(libj_jarfile) -d $(JAVA_EXCLASSTOP) \ + $(JAVACFLAGS) $(JAVA_EXSRCS) + cd $(JAVA_EXCLASSTOP) && $(JAR) cf ../$(libj_exjarfile) . + +################################################## +# Utilities +################################################## +db_archive: db_archive@o@ util_sig@o@ $(DEF_LIB) + $(CCLINK) -o $@ $(LDFLAGS) \ + db_archive@o@ util_sig@o@ $(DEF_LIB) $(LIBS) + $(POSTLINK) $@ + +db_checkpoint: db_checkpoint@o@ util_log@o@ util_sig@o@ $(DEF_LIB) + $(CCLINK) -o $@ $(LDFLAGS) \ + db_checkpoint@o@ util_log@o@ util_sig@o@ $(DEF_LIB) $(LIBS) + $(POSTLINK) $@ + +db_deadlock: db_deadlock@o@ util_log@o@ util_sig@o@ $(DEF_LIB) + $(CCLINK) -o $@ $(LDFLAGS) \ + db_deadlock@o@ util_log@o@ util_sig@o@ $(DEF_LIB) $(LIBS) + $(POSTLINK) $@ + +db_dump: db_dump@o@ util_cache@o@ util_sig@o@ $(DEF_LIB) + $(CCLINK) -o $@ $(LDFLAGS) \ + db_dump@o@ util_cache@o@ util_sig@o@ $(DEF_LIB) $(LIBS) + $(POSTLINK) $@ + +db_dump185: db_dump185@o@ @REPLACEMENT_OBJS@ + $(CCLINK) -o $@ $(LDFLAGS) db_dump185@o@ @REPLACEMENT_OBJS@ $(DB185LIB) + $(POSTLINK) $@ + +db_hotbackup: db_hotbackup@o@ util_sig@o@ $(DEF_LIB) + $(CCLINK) -o $@ $(LDFLAGS) \ + db_hotbackup@o@ util_sig@o@ $(DEF_LIB) $(LIBS) + $(POSTLINK) $@ + +db_load: db_load@o@ util_cache@o@ util_sig@o@ $(DEF_LIB) + $(CCLINK) -o $@ $(LDFLAGS) \ + db_load@o@ util_cache@o@ util_sig@o@ $(DEF_LIB) $(LIBS) + $(POSTLINK) $@ + +db_printlog: db_printlog@o@ @PRINTLOG_OBJS@ util_sig@o@ $(DEF_LIB) + $(CCLINK) -o $@ $(LDFLAGS) \ + db_printlog@o@ @PRINTLOG_OBJS@ util_sig@o@ $(DEF_LIB) $(LIBS) + $(POSTLINK) $@ + +db_recover: db_recover@o@ util_sig@o@ $(DEF_LIB) + $(CCLINK) -o $@ $(LDFLAGS) \ + db_recover@o@ util_sig@o@ $(DEF_LIB) $(LIBS) + $(POSTLINK) $@ + +db_replicate: db_replicate@o@ util_sig@o@ $(DEF_LIB) + $(CCLINK) -o $@ $(LDFLAGS) \ + db_replicate@o@ util_log@o@ util_sig@o@ $(DEF_LIB) $(LIBS) + $(POSTLINK) $@ + +DBSQL_CODEGEN_OBJS=\ + db_sql_codegen@o@ parse@o@ preparser@o@ parsefuncs@o@ tokenize@o@ \ + sqlprintf@o@ buildpt@o@ utils@o@ generate@o@ generate_test@o@ \ + generation_utils@o@ generate_verification@o@ hint_comment@o@ + +db_sql_codegen: $(DBSQL_CODEGEN_OBJS) $(DEF_LIB) + $(CCLINK) -o $@ $(LDFLAGS) $(DBSQL_CODEGEN_OBJS) $(DEF_LIB) $(LIBS) + $(POSTLINK) $@ + +db_stat: db_stat@o@ util_cache@o@ util_sig@o@ $(DEF_LIB) + $(CCLINK) -o $@ $(LDFLAGS) \ + db_stat@o@ util_cache@o@ util_sig@o@ $(DEF_LIB) $(LIBS) + $(POSTLINK) $@ + +db_tuner: db_tuner@o@ util_sig@o@ $(DEF_LIB) + $(CCLINK) -o $@ $(LDFLAGS) \ + db_tuner@o@ util_sig@o@ $(DEF_LIB) $(LIBS) + $(POSTLINK) $@ + +db_upgrade: db_upgrade@o@ util_sig@o@ $(DEF_LIB) + $(CCLINK) -o $@ $(LDFLAGS) \ + db_upgrade@o@ util_sig@o@ $(DEF_LIB) $(LIBS) + $(POSTLINK) $@ + +db_verify: db_verify@o@ util_cache@o@ util_sig@o@ $(DEF_LIB) + $(CCLINK) -o $@ $(LDFLAGS) \ + db_verify@o@ util_cache@o@ util_sig@o@ $(DEF_LIB) $(LIBS) + $(POSTLINK) $@ + +db_log_verify: db_log_verify@o@ util_cache@o@ util_sig@o@ $(DEF_LIB) + $(CCLINK) -o $@ $(LDFLAGS) \ + db_log_verify@o@ util_cache@o@ util_sig@o@ $(DEF_LIB) $(LIBS) + $(POSTLINK) $@ +################################################## +# Library and standard utilities install. +################################################## +library_install: install_setup +library_install: install_include install_lib install_utilities install_docs + +uninstall: uninstall_include uninstall_lib uninstall_utilities uninstall_docs + +install_setup: + @test -d $(DESTDIR)$(prefix) || \ + ($(MKDIR) -p $(DESTDIR)$(prefix) && \ + $(CHMOD) $(dmode) $(DESTDIR)$(prefix)) + +INCDOT= db.h db_cxx.h @ADDITIONAL_INCS@ +install_include: $(INCDOT) + @echo "Installing DB include files: $(DESTDIR)$(includedir) ..." + @test -d $(DESTDIR)$(includedir) || \ + ($(MKDIR) -p $(DESTDIR)$(includedir) && \ + $(CHMOD) $(dmode) $(DESTDIR)$(includedir)) + @for f in $(INCDOT); do \ + basef=`echo $$f | $(SED) 's,.*/,,'` ; \ + $(RM) $(DESTDIR)$(includedir)/$$basef ; \ + $(CP) -p $$f $(DESTDIR)$(includedir) ; \ + $(CHMOD) $(fmode) $(DESTDIR)$(includedir)/$$basef ; \ + done + +uninstall_include: + @for f in $(INCDOT); do \ + basef=`echo $$f | $(SED) 's,.*/,,'` ; \ + $(RM) $(DESTDIR)$(includedir)/$$basef ; \ + done + +install_lib: + @echo "Installing DB library: $(DESTDIR)$(libdir) ..." + @test -d $(DESTDIR)$(libdir) || \ + ($(MKDIR) -p $(DESTDIR)$(libdir) && \ + $(CHMOD) $(dmode) $(DESTDIR)$(libdir)) + @cd $(DESTDIR)$(libdir) && $(RM) $(LIB_INSTALL_FILE_LIST) + @$(INSTALLER) @INSTALL_LIBS@ $(DESTDIR)$(libdir) + @(cd $(DESTDIR)$(libdir) && \ + test -f $(libso) && $(LN) -s $(libso) $(libso_default); \ + test -f $(libso) && $(LN) -s $(libso) $(libso_major); \ + test -f $(libxso) && $(LN) -s $(libxso) $(libxso_default); \ + test -f $(libxso) && $(LN) -s $(libxso) $(libxso_major); \ + test -f $(libsqlso) && $(LN) -s $(libsqlso) $(libsqlso_default); \ + test -f $(libsqlso) && $(LN) -s $(libsqlso) $(libsqlso_major); \ + test -f $(libstlso) && $(LN) -s $(libstlso) $(libstlso_default); \ + test -f $(libstlso) && $(LN) -s $(libstlso) $(libstlso_major); \ + test -f $(libtso) && $(LN) -s $(libtso) $(libtso_default); \ + test -f $(libtso) && $(LN) -s $(libtso) $(libtso_major); \ + test -f $(libjso) && $(LN) -s $(libjso) $(libjso_default); \ + test -f $(libjso) && $(LN) -s $(libjso) $(libjso_major); \ + test -f $(libjso) && $(LN) -s $(libjso) $(libjso_g)) || exit 0 + @(test -f $(libj_jarfile) && \ + $(CP) $(libj_jarfile) $(DESTDIR)$(libdir) && \ + $(CHMOD) $(fmode) $(DESTDIR)$(libdir)/$(libj_jarfile)) || exit 0 + @(test -d jdbc && cd jdbc && make install && cd -) || exit 0 + +uninstall_lib: + @cd $(DESTDIR)$(libdir) && $(RM) $(LIB_INSTALL_FILE_LIST) + +install_utilities: + @echo "Installing DB utilities: $(DESTDIR)$(bindir) ..." + @test -d $(DESTDIR)$(bindir) || \ + ($(MKDIR) -p $(DESTDIR)$(bindir) && \ + $(CHMOD) $(dmode) $(DESTDIR)$(bindir)) + @for i in $(UTIL_PROGS); do \ + test -f $$i.exe && i=$$i.exe; \ + e=`echo $$i | $(SED) '$(transform)'`; \ + $(RM) $(DESTDIR)$(bindir)/$$e; \ + $(INSTALLER) $$i $(DESTDIR)$(bindir)/$$e; \ + $(STRIP) $(DESTDIR)$(bindir)/$$e; \ + $(CHMOD) $(emode) $(DESTDIR)$(bindir)/$$e; \ + done + +uninstall_utilities: + @(cd $(DESTDIR)$(bindir); for i in $(UTIL_PROGS); do \ + i=`echo $$i | $(SED) '$(transform)'`; \ + test -f $$i.exe && i=$$i.exe; \ + $(RM) $$i; \ + done) + +# We install csharp docs even on UNIX so we don't have a +# broken link on the landing page. +DOCLIST=api_reference articles bdb-sql collections csharp \ + gsg gsg_db_rep gsg_txn index.html installation java \ + license porting programmer_reference upgrading + +install_docs: + @echo "Installing documentation: $(DESTDIR)$(docdir) ..." + @test -d $(DESTDIR)$(docdir) || \ + ($(MKDIR) -p $(DESTDIR)$(docdir) && \ + $(CHMOD) $(dmode) $(DESTDIR)$(docdir)) + @cd $(DESTDIR)$(docdir) && $(RM) -r $(DOCLIST) + @cd $(topdir)/docs && $(CP) -pr $(DOCLIST) $(DESTDIR)$(docdir)/ + +uninstall_docs: + @cd $(DESTDIR)$(docdir) && $(RM) -r $(DOCLIST) + +################################################## +# Remaining standard Makefile targets. +################################################## +CLEAN_LIST=\ + StlTxnGuide TxnGuide TxnGuideInMemory berkeley_db_cxxsvc \ + berkeley_db_svc cutest db_dump185 db_perf db_repsite db_reptest dbs \ + ex_access ex_apprec ex_btrec ex_bulk ex_dbclient ex_env ex_heap ex_lock \ + ex_mpool ex_rep_base ex_rep_chan ex_rep_gsg_repmgr ex_rep_gsg_simple \ + ex_rep_mgr ex_sequence ex_stream ex_thread ex_tpcb \ + example_database_load example_database_read excxx_access \ + excxx_btrec excxx_env excxx_example_database_load \ + excxx_example_database_read excxx_lock excxx_mpool \ + excxx_repquote excxx_repquote_gsg_repmgr excxx_repquote_gsg_simple \ + excxx_sequence excxx_tpcb ex_sql_binding ex_sql_fts3 ex_sql_index \ + ex_sql_load ex_sql_multi_thread ex_sql_query ex_sql_rtree \ + ex_sql_savepoint ex_sql_statement ex_sql_transaction exstl_access \ + exstl_advancedfeatures exstl_repquote exstl_tpcb txn_guide test_dbstl \ + test_dbstl_ms_examples test_dbstl_stlport txn_guide_inmemory + +mostly-clean clean: + $(RM) -r $(C_OBJS) $(CUTEST_OBJS) + $(RM) -r $(CXX_OBJS) $(JAVA_OBJS) $(SQL_OBJS) $(SQL_OBJS) $(STL_OBJS) + $(RM) -r $(TCL_OBJS) $(UTIL_PROGS) *.exe $(CLEAN_LIST) + $(RM) -r $(JAVA_CLASSTOP) $(JAVA_EXCLASSTOP) + $(RM) -r $(DB_STL_TEST_OBJS) $(TEST_MICRO_OBJS) + $(RM) -r tags *@o@ *.o *.o.lock *.lo core *.core core.* + $(RM) -r ALL.OUT.* PARALLEL_TESTDIR.* + $(RM) -r RUN_LOG RUNQUEUE TESTDIR TESTDIR.A TEST.LIST + $(RM) -r logtrack_seen.db test_micro test_mutex .libs + $(RM) -r $(LIB_INSTALL_FILE_LIST) + @subdir_cmd@ + +REALCLEAN_LIST=\ + Makefile clib_port.h confdefs.h config.cache config.log config.status \ + configure.lineno db.h db185_int.h db_185.h db_config.h db_cxx.h \ + db_int.h db_int_def.h db_provider.c db_provider.h dbstl_common.h \ + db_server.h db_server_clnt.c db_server_svc.c db_server_xdr.c \ + gen_db_server.c include.tcl dbsql.h $(builddir)/sql $(builddir)/jdbc + +distclean maintainer-clean realclean: clean + $(RM) -r $(REALCLEAN_LIST) + $(RM) -r libtool + +check depend dvi info obj TAGS: + @echo "make: $@ target not available" + +dist rpm rpmbuild: + @echo "make: $@ target not available" && exit 1 + +################################################## +# Testers, benchmarks. +################################################## +dbs@o@: $(testdir)/server/dbs.c + $(CC) $(CFLAGS) $? +dbs_am@o@: $(testdir)/server/dbs_am.c + $(CC) $(CFLAGS) $? +dbs_checkpoint@o@: $(testdir)/server/dbs_checkpoint.c + $(CC) $(CFLAGS) $? +dbs_debug@o@: $(testdir)/server/dbs_debug.c + $(CC) $(CFLAGS) $? +dbs_handles@o@: $(testdir)/server/dbs_handles.c + $(CC) $(CFLAGS) $? +dbs_log@o@: $(testdir)/server/dbs_log.c + $(CC) $(CFLAGS) $? +dbs_qam@o@: $(testdir)/server/dbs_qam.c + $(CC) $(CFLAGS) $? +dbs_spawn@o@: $(testdir)/server/dbs_spawn.c + $(CC) $(CFLAGS) $? +dbs_trickle@o@: $(testdir)/server/dbs_trickle.c + $(CC) $(CFLAGS) $? +dbs_util@o@: $(testdir)/server/dbs_util.c + $(CC) $(CFLAGS) $? +dbs_yield@o@: $(testdir)/server/dbs_yield.c + $(CC) $(CFLAGS) $? +DBS_OBJS=\ + dbs@o@ dbs_am@o@ dbs_checkpoint@o@ dbs_debug@o@ dbs_handles@o@ \ + dbs_log@o@ dbs_qam@o@ dbs_spawn@o@ dbs_trickle@o@ dbs_util@o@ \ + dbs_yield@o@ +dbs: $(DBS_OBJS) $(DEF_LIB) + $(CCLINK) -o $@ \ + $(LDFLAGS) $(DBS_OBJS) $(DEF_LIB) $(TEST_LIBS) $(LIBS) + $(POSTLINK) $@ + +db_perf@o@: $(testdir)/perf/db_perf.c + $(CC) $(CFLAGS) $? +perf_checkpoint@o@: $(testdir)/perf/perf_checkpoint.c + $(CC) $(CFLAGS) $? +perf_config@o@: $(testdir)/perf/perf_config.c + $(CC) $(CFLAGS) $? +perf_dbs@o@: $(testdir)/perf/perf_dbs.c + $(CC) $(CFLAGS) $? +perf_dead@o@: $(testdir)/perf/perf_dead.c + $(CC) $(CFLAGS) $? +perf_debug@o@: $(testdir)/perf/perf_debug.c + $(CC) $(CFLAGS) $? +perf_file@o@: $(testdir)/perf/perf_file.c + $(CC) $(CFLAGS) $? +perf_key@o@: $(testdir)/perf/perf_key.c + $(CC) $(CFLAGS) $? +perf_log@o@: $(testdir)/perf/perf_log.c + $(CC) $(CFLAGS) $? +perf_misc@o@: $(testdir)/perf/perf_misc.c + $(CC) $(CFLAGS) $? +perf_op@o@: $(testdir)/perf/perf_op.c + $(CC) $(CFLAGS) $? +perf_parse@o@: $(testdir)/perf/perf_parse.c + $(CC) $(CFLAGS) $? +perf_rand@o@: $(testdir)/perf/perf_rand.c + $(CC) $(CFLAGS) $? +perf_spawn@o@: $(testdir)/perf/perf_spawn.c + $(CC) $(CFLAGS) $? +perf_stat@o@: $(testdir)/perf/perf_stat.c + $(CC) $(CFLAGS) $? +perf_sync@o@: $(testdir)/perf/perf_sync.c + $(CC) $(CFLAGS) $? +perf_thread@o@: $(testdir)/perf/perf_thread.c + $(CC) $(CFLAGS) $? +perf_trickle@o@: $(testdir)/perf/perf_trickle.c + $(CC) $(CFLAGS) $? +perf_txn@o@: $(testdir)/perf/perf_txn.c + $(CC) $(CFLAGS) $? +perf_util@o@: $(testdir)/perf/perf_util.c + $(CC) $(CFLAGS) $? +perf_vx@o@: $(testdir)/perf/perf_vx.c + $(CC) $(CFLAGS) $? +DBPERF_OBJS=\ + db_perf@o@ perf_checkpoint@o@ perf_config@o@ perf_dbs@o@ \ + perf_dead@o@ perf_debug@o@ perf_file@o@ perf_key@o@ perf_log@o@ \ + perf_misc@o@ perf_op@o@ perf_parse@o@ perf_rand@o@ perf_spawn@o@ \ + perf_stat@o@ perf_sync@o@ perf_thread@o@ perf_trickle@o@ \ + perf_txn@o@ perf_util@o@ perf_vx@o@ util_sig@o@ +db_perf: $(DBPERF_OBJS) $(DEF_LIB) + $(CCLINK) -o $@ \ + $(LDFLAGS) $(DBPERF_OBJS) $(DEF_LIB) $(TEST_LIBS) $(LIBS) + $(POSTLINK) $@ + +# C unit test suite. +CUTEST_FLAGS= $(CFLAGS) -I$(testdir)/c/cutest -I$(testdir)/c/suites -I$(testdir)/c/common + +CuTest@o@: $(testdir)/c/cutest/CuTest.c + $(CC) $(CUTEST_FLAGS) $? +CuTests@o@: $(testdir)/c/cutest/CuTests.c + $(CC) $(CUTEST_FLAGS) $? +Runner@o@: $(testdir)/c/cutest/Runner.c + $(CC) $(CUTEST_FLAGS) $? +TestChannel@o@: $(testdir)/c/suites/TestChannel.c + $(CC) $(CUTEST_FLAGS) $? +TestDbHotBackup@o@: $(testdir)/c/suites/TestDbHotBackup.c + $(CC) $(CUTEST_FLAGS) $? +TestDbTuner@o@: $(testdir)/c/suites/TestDbTuner.c + $(CC) $(CUTEST_FLAGS) $? +TestEncryption@o@: $(testdir)/c/suites/TestEncryption.c + $(CC) $(CUTEST_FLAGS) $? +TestEnvConfig@o@: $(testdir)/c/suites/TestEnvConfig.c + $(CC) $(CUTEST_FLAGS) $? +TestEnvMethod@o@: $(testdir)/c/suites/TestEnvMethod.c + $(CC) $(CUTEST_FLAGS) $? +TestKeyExistErrorReturn@o@: $(testdir)/c/suites/TestKeyExistErrorReturn.c + $(CC) $(CUTEST_FLAGS) $? +TestPartial@o@: $(testdir)/c/suites/TestPartial.c + $(CC) $(CUTEST_FLAGS) $? +TestQueue@o@: $(testdir)/c/suites/TestQueue.c + $(CC) $(CUTEST_FLAGS) $? + +cutest: $(CUTEST_OBJS) $(DEF_LIB) db_tuner.lo + $(CCLINK) -o $@ \ + $(LDFLAGS) $(CUTEST_OBJS) $(DEF_LIB) $(TEST_LIBS) $(LIBS) + $(POSTLINK) $@ + +db_repsite@o@: $(testdir)/repmgr/db_repsite.cpp + $(CXX) $(CXXFLAGS) $? +DBREPSITE_OBJS=db_repsite@o@ +db_repsite: $(DBREPSITE_OBJS) $(DEF_LIB_CXX) + $(CXXLINK) -o $@ \ + $(LDFLAGS) $(DBREPSITE_OBJS) $(DEF_LIB_CXX) $(TEST_LIBS) $(LIBS) + $(POSTLINK) $@ + +db_reptest@o@: $(testdir)/repmgr/db_reptest.c + $(CC) $(CFLAGS) $? +reptest_am@o@: $(testdir)/repmgr/reptest_am.c + $(CC) $(CFLAGS) $? +reptest_handles@o@: $(testdir)/repmgr/reptest_handles.c + $(CC) $(CFLAGS) $? +reptest_spawn@o@: $(testdir)/repmgr/reptest_spawn.c + $(CC) $(CFLAGS) $? +reptest_util@o@: $(testdir)/repmgr/reptest_util.c + $(CC) $(CFLAGS) $? +DBREPTEST_OBJS=\ + db_reptest@o@ reptest_am@o@ reptest_handles@o@ \ + reptest_spawn@o@ reptest_util@o@ + +db_reptest: $(DBREPTEST_OBJS) $(DEF_LIB) + $(CCLINK) -o $@ \ + $(LDFLAGS) $(DBREPTEST_OBJS) $(DEF_LIB) $(TEST_LIBS) $(LIBS) + $(POSTLINK) $@ + +test_dbstl@o@: $(testdir)/stl/base/test_dbstl.cpp + $(CXX) $(STLFLAGS) $? +test_util@o@: $(testdir)/stl/base/test_util.cpp + $(CXX) $(STLFLAGS) $? + +stl_test@o@: $(testdir)/stl/stlport/stl_test.cpp + $(CXX) $(STLFLAGS) $? +utility@o@: $(testdir)/stl/stlport/utility.cpp + $(CXX) $(STLFLAGS) $? +stlport_test_builder@o@: $(testdir)/stl/stlport/stlport_test_builder.cpp + $(CXX) $(STLFLAGS) $? + +ms_stl_main@o@: $(testdir)/stl/ms_examples/ms_stl_main.cpp + $(CXX) $(STLFLAGS) -DGCC_BAD_AUTO_CONVERSION $? +ms_stl_common@o@: $(testdir)/stl/ms_examples/ms_stl_common.cpp + $(CXX) $(STLFLAGS) -DGCC_BAD_AUTO_CONVERSION $? +test_builder@o@: $(testdir)/stl/ms_examples/test_builder.cpp + $(CXX) $(STLFLAGS) -DGCC_BAD_AUTO_CONVERSION $? + +DB_STL_TEST_OBJS=test_dbstl@o@ test_util@o@ +DB_STL_STLPORT_TEST_OBJS=stl_test@o@ stlport_test_builder@o@ utility@o@ +DB_STL_MS_TEST_OBJS=ms_stl_main@o@ ms_stl_common@o@ \ + test_builder@o@ + +test_dbstl: $(DB_STL_TEST_OBJS) $(DEF_LIB_CXX) $(DEF_LIB_STL) + $(CXXLINK) -o $@ $(LDFLAGS) $(DB_STL_TEST_OBJS) \ + $(DEF_LIB_CXX) $(DEF_LIB_STL) $(LIBS) $(LIBSTLSO_LIBS) + $(POSTLINK) $@ + +test_dbstl_ms_examples: $(DB_STL_MS_TEST_OBJS) $(DEF_LIB_CXX) $(DEF_LIB_STL) + $(CXXLINK) -o $@ $(LDFLAGS) $(DB_STL_MS_TEST_OBJS) \ + $(DEF_LIB_CXX) $(DEF_LIB_STL) $(LIBS) $(LIBSTLSO_LIBS) + $(POSTLINK) $@ +test_dbstl_stlport: $(DB_STL_STLPORT_TEST_OBJS) $(DEF_LIB_CXX) $(DEF_LIB_STL) + $(CXXLINK) -o $@ $(LDFLAGS) $(DB_STL_STLPORT_TEST_OBJS) \ + $(DEF_LIB_CXX) $(DEF_LIB_STL) $(LIBS) $(LIBSTLSO_LIBS) + $(POSTLINK) $@ + +b_curalloc@o@: $(testdir)/micro/source/b_curalloc.c + $(CC) $(CFLAGS) -I$(testdir)/micro/source $? +b_curwalk@o@: $(testdir)/micro/source/b_curwalk.c + $(CC) $(CFLAGS) -I$(testdir)/micro/source $? +b_del@o@: $(testdir)/micro/source/b_del.c + $(CC) $(CFLAGS) -I$(testdir)/micro/source $? +b_get@o@: $(testdir)/micro/source/b_get.c + $(CC) $(CFLAGS) -I$(testdir)/micro/source $? +b_inmem@o@: $(testdir)/micro/source/b_inmem.c + $(CC) $(CFLAGS) -I$(testdir)/micro/source $? +b_latch@o@: $(testdir)/micro/source/b_latch.c + $(CC) $(CFLAGS) -I$(testdir)/micro/source $? +b_load@o@: $(testdir)/micro/source/b_load.c + $(CC) $(CFLAGS) -I$(testdir)/micro/source $? +b_open@o@: $(testdir)/micro/source/b_open.c + $(CC) $(CFLAGS) -I$(testdir)/micro/source $? +b_put@o@: $(testdir)/micro/source/b_put.c + $(CC) $(CFLAGS) -I$(testdir)/micro/source $? +b_recover@o@: $(testdir)/micro/source/b_recover.c + $(CC) $(CFLAGS) -I$(testdir)/micro/source $? +b_txn@o@: $(testdir)/micro/source/b_txn.c + $(CC) $(CFLAGS) -I$(testdir)/micro/source $? +b_txn_write@o@: $(testdir)/micro/source/b_txn_write.c + $(CC) $(CFLAGS) -I$(testdir)/micro/source $? +b_uname@o@: $(testdir)/micro/source/b_uname.c + $(CC) $(CFLAGS) -I$(testdir)/micro/source $? +b_util@o@: $(testdir)/micro/source/b_util.c + $(CC) $(CFLAGS) -I$(testdir)/micro/source $? +b_workload@o@: $(testdir)/micro/source/b_workload.c + $(CC) $(CFLAGS) -I$(testdir)/micro/source $? +test_micro@o@: $(testdir)/micro/source/test_micro.c + $(CC) $(CFLAGS) -I$(testdir)/micro/source $? +test_micro: $(TEST_MICRO_OBJS) $(DEF_LIB) + $(CCLINK) -o $@ \ + $(LDFLAGS) $(TEST_MICRO_OBJS) $(DEF_LIB) $(TEST_LIBS) $(LIBS) + $(POSTLINK) $@ + +test_mutex@o@: $(srcdir)/mutex/test_mutex.c + $(CC) $(CFLAGS) $? +test_mutex: test_mutex@o@ $(DEF_LIB) + $(CCLINK) -o $@ $(LDFLAGS) test_mutex@o@ $(DEF_LIB) $(TEST_LIBS) $(LIBS) + $(POSTLINK) $@ + +################################################## +# Targets for example programs. +################################################## +examples_c: ex_access ex_apprec ex_btrec ex_bulk ex_env ex_heap ex_lock \ + ex_mpool ex_rep_base ex_rep_chan ex_rep_gsg_repmgr ex_rep_gsg_simple \ + ex_rep_mgr ex_sequence ex_stream ex_thread ex_tpcb \ + example_database_load example_database_read txn_guide txn_guide_inmemory + +examples_cxx: TxnGuide TxnGuideInMemory excxx_access \ + excxx_example_database_load excxx_example_database_read \ + excxx_lock excxx_mpool excxx_repquote excxx_repquote_gsg_repmgr \ + excxx_repquote_gsg_simple excxx_sequence excxx_tpcb + +examples_stl: StlTxnGuide exstl_access exstl_advancedfeatures exstl_repquote \ + exstl_tpcb + +examples_sql: ex_sql_binding ex_sql_fts3 ex_sql_index ex_sql_load \ + ex_sql_multi_thread ex_sql_query ex_sql_rtree ex_sql_savepoint \ + ex_sql_statement ex_sql_transaction + +examples: examples_c examples_cxx examples_stl examples_sql + +################################################## +# Example programs for C. +################################################## +ex_access@o@: $(exampledir)/c/ex_access.c + $(CC) $(CFLAGS) $? +ex_access: ex_access@o@ $(DEF_LIB) + $(CCLINK) -o $@ $(LDFLAGS) ex_access@o@ $(DEF_LIB) $(LIBS) + $(POSTLINK) $@ + +ex_apprec@o@: $(exampledir)/c/ex_apprec/ex_apprec.c + $(CC) $(CFLAGS) $? +ex_apprec_auto@o@: $(exampledir)/c/ex_apprec/ex_apprec_auto.c + $(CC) $(CFLAGS) $? +ex_apprec_autop@o@: $(exampledir)/c/ex_apprec/ex_apprec_autop.c + $(CC) $(CFLAGS) $? +ex_apprec_rec@o@: $(exampledir)/c/ex_apprec/ex_apprec_rec.c + $(CC) $(CFLAGS) $? +EX_APPREC_OBJS=\ + ex_apprec@o@ ex_apprec_auto@o@ ex_apprec_autop@o@ ex_apprec_rec@o@ +ex_apprec: $(EX_APPREC_OBJS) $(DEF_LIB) + $(CCLINK) -o $@ \ + $(LDFLAGS) $(EX_APPREC_OBJS) $(DEF_LIB) $(TEST_LIBS) $(LIBS) + +ex_btrec@o@: $(exampledir)/c/ex_btrec.c + $(CC) $(CFLAGS) $? +ex_btrec: ex_btrec@o@ $(DEF_LIB) + $(CCLINK) -o $@ $(LDFLAGS) ex_btrec@o@ $(DEF_LIB) $(LIBS) + $(POSTLINK) $@ + +ex_bulk@o@: $(exampledir)/c/ex_bulk.c + $(CC) $(CFLAGS) $? +ex_bulk: ex_bulk@o@ $(DEF_LIB) + $(CCLINK) -o $@ $(LDFLAGS) ex_bulk@o@ $(DEF_LIB) $(LIBS) + $(POSTLINK) $@ + +ex_dbclient@o@: $(exampledir)/c/ex_dbclient.c + $(CC) $(CFLAGS) $? +ex_dbclient: ex_dbclient@o@ $(DEF_LIB) + $(CCLINK) -o $@ $(LDFLAGS) ex_dbclient@o@ $(DEF_LIB) $(LIBS) + $(POSTLINK) $@ + +ex_env@o@: @LOCALEXAMPLES@/c/ex_env.c + $(CC) $(CFLAGS) $? +ex_env: ex_env@o@ $(DEF_LIB) + $(CCLINK) -o $@ $(LDFLAGS) ex_env@o@ $(DEF_LIB) $(LIBS) + $(POSTLINK) $@ + +ex_heap@o@: $(exampledir)/c/ex_heap.c + $(CC) $(CFLAGS) $? +ex_heap: ex_heap@o@ $(DEF_LIB) + $(CCLINK) -o $@ $(LDFLAGS) ex_heap@o@ $(DEF_LIB) $(LIBS) + $(POSTLINK) $@ + +ex_lock@o@: $(exampledir)/c/ex_lock.c + $(CC) $(CFLAGS) $? +ex_lock: ex_lock@o@ $(DEF_LIB) + $(CCLINK) -o $@ $(LDFLAGS) ex_lock@o@ $(DEF_LIB) $(LIBS) + $(POSTLINK) $@ + +ex_mpool@o@: $(exampledir)/c/ex_mpool.c + $(CC) $(CFLAGS) $? +ex_mpool: ex_mpool@o@ $(DEF_LIB) + $(CCLINK) -o $@ $(LDFLAGS) ex_mpool@o@ $(DEF_LIB) $(LIBS) + $(POSTLINK) $@ + +rep_base@o@: $(exampledir)/c/ex_rep/base/rep_base.c + $(CC) $(CFLAGS) $? +rep_common@o@: $(exampledir)/c/ex_rep/common/rep_common.c + $(CC) $(CFLAGS) $? +rep_msg@o@: $(exampledir)/c/ex_rep/base/rep_msg.c + $(CC) $(CFLAGS) $? +rep_net@o@: $(exampledir)/c/ex_rep/base/rep_net.c + $(CC) $(CFLAGS) $? +EX_REP_BASE_OBJS=\ + rep_base@o@ rep_common@o@ rep_msg@o@ rep_net@o@ +ex_rep_base: $(EX_REP_BASE_OBJS) $(DEF_LIB) + $(CCLINK) -o $@ \ + $(LDFLAGS) $(EX_REP_BASE_OBJS) $(DEF_LIB) $(TEST_LIBS) $(LIBS) + $(POSTLINK) $@ + +rep_chan@o@: $(exampledir)/c/ex_rep_chan/rep_chan.c + $(CC) $(CFLAGS) $? +rep_chan_util@o@: $(exampledir)/c/ex_rep_chan/rep_chan_util.c + $(CC) $(CFLAGS) $? +EX_REP_CHAN_OBJS=\ + rep_chan@o@ rep_chan_util@o@ +ex_rep_chan: $(EX_REP_CHAN_OBJS) $(DEF_LIB) + $(CCLINK) -o $@ \ + $(LDFLAGS) $(EX_REP_CHAN_OBJS) $(DEF_LIB) $(TEST_LIBS) $(LIBS) + $(POSTLINK) $@ + +simple_txn@o@: $(exampledir)/c/ex_rep_gsg/simple_txn.c + $(CC) $(CFLAGS) $? +ex_rep_gsg_simple: simple_txn@o@ $(DEF_LIB) + $(CCLINK) -o $@ \ + $(LDFLAGS) simple_txn@o@ $(DEF_LIB) $(TEST_LIBS) $(LIBS) + $(POSTLINK) $@ + +rep_mgr_gsg@o@: $(exampledir)/c/ex_rep_gsg/rep_mgr_gsg.c + $(CC) $(CFLAGS) $? +ex_rep_gsg_repmgr: rep_mgr_gsg@o@ $(DEF_LIB) + $(CCLINK) -o $@ \ + $(LDFLAGS) rep_mgr_gsg@o@ $(DEF_LIB) $(TEST_LIBS) $(LIBS) + $(POSTLINK) $@ + +rep_mgr@o@: $(exampledir)/c/ex_rep/mgr/rep_mgr.c + $(CC) $(CFLAGS) $? +EX_REP_MGR_OBJS=\ + rep_common@o@ rep_mgr@o@ +ex_rep_mgr: $(EX_REP_MGR_OBJS) $(DEF_LIB) + $(CCLINK) -o $@ \ + $(LDFLAGS) $(EX_REP_MGR_OBJS) $(DEF_LIB) $(TEST_LIBS) $(LIBS) + $(POSTLINK) $@ + +ex_sequence@o@: $(exampledir)/c/ex_sequence.c + $(CC) $(CFLAGS) $? +ex_sequence: ex_sequence@o@ $(DEF_LIB) + $(CCLINK) -o $@ $(LDFLAGS) ex_sequence@o@ $(DEF_LIB) $(LIBS) + $(POSTLINK) $@ + +ex_stream@o@: $(exampledir)/c/ex_stream.c + $(CC) $(CFLAGS) $? +ex_stream: ex_stream@o@ $(DEF_LIB) + $(CCLINK) -o $@ $(LDFLAGS) ex_stream@o@ $(DEF_LIB) $(LIBS) + $(POSTLINK) $@ + +ex_thread@o@: @LOCALEXAMPLES@/c/ex_thread.c + $(CC) $(CFLAGS) $? +ex_thread: ex_thread@o@ $(DEF_LIB) + $(CCLINK) -o $@ \ + $(LDFLAGS) ex_thread@o@ $(DEF_LIB) $(TEST_LIBS) $(LIBS) + $(POSTLINK) $@ + +ex_tpcb@o@: $(exampledir)/c/ex_tpcb.c + $(CC) $(CFLAGS) $? +ex_tpcb: ex_tpcb@o@ $(DEF_LIB) + $(CCLINK) -o $@ $(LDFLAGS) ex_tpcb@o@ $(DEF_LIB) $(LIBS) + $(POSTLINK) $@ + +gettingstarted_common@o@: \ + $(exampledir)/c/getting_started/gettingstarted_common.c + $(CC) -I$(exampledir)/c/getting_started $(CFLAGS) $? +example_database_load@o@: \ + $(exampledir)/c/getting_started/example_database_load.c + $(CC) $(CFLAGS) $? +example_database_read@o@: \ + $(exampledir)/c/getting_started/example_database_read.c + $(CC) $(CFLAGS) $? +example_database_load: example_database_load@o@ gettingstarted_common@o@ \ + $(DEF_LIB) + $(CCLINK) -o $@ $(LDFLAGS) \ + example_database_load@o@ gettingstarted_common@o@ $(DEF_LIB) $(LIBS) + $(POSTLINK) $@ +example_database_read: example_database_read@o@ gettingstarted_common@o@ \ + $(DEF_LIB) + $(CCLINK) -o $@ $(LDFLAGS) \ + example_database_read@o@ gettingstarted_common@o@ $(DEF_LIB) $(LIBS) + $(POSTLINK) $@ + +txn_guide_inmemory@o@: $(exampledir)/c/txn_guide/txn_guide_inmemory.c + $(CC) $(CFLAGS) $? +txn_guide_inmemory: txn_guide_inmemory@o@ $(DEF_LIB) + $(CCLINK) -o $@ $(LDFLAGS) txn_guide_inmemory@o@ $(DEF_LIB) $(LIBS) + $(POSTLINK) $@ + +txn_guide@o@: $(exampledir)/c/txn_guide/txn_guide.c + $(CC) $(CFLAGS) $? +txn_guide: txn_guide@o@ $(DEF_LIB) + $(CCLINK) -o $@ $(LDFLAGS) txn_guide@o@ $(DEF_LIB) $(LIBS) + $(POSTLINK) $@ + +################################################## +# Example programs for C++. +################################################## +AccessExample@o@: $(exampledir)/cxx/AccessExample.cpp + $(CXX) $(CXXFLAGS) $? +excxx_access: AccessExample@o@ $(DEF_LIB_CXX) + $(CXXLINK) -o $@ $(LDFLAGS) AccessExample@o@ $(DEF_LIB_CXX) $(LIBS) + $(POSTLINK) $@ + +BtRecExample@o@: $(exampledir)/cxx/BtRecExample.cpp + $(CXX) $(CXXFLAGS) $? +excxx_btrec: BtRecExample@o@ $(DEF_LIB_CXX) + $(CXXLINK) -o $@ $(LDFLAGS) BtRecExample@o@ $(DEF_LIB_CXX) $(LIBS) + $(POSTLINK) $@ + +EnvExample@o@: $(exampledir)/cxx/EnvExample.cpp + $(CXX) $(CXXFLAGS) $? +excxx_env: EnvExample@o@ $(DEF_LIB_CXX) + $(CXXLINK) -o $@ $(LDFLAGS) EnvExample@o@ $(DEF_LIB_CXX) $(LIBS) + $(POSTLINK) $@ + +LockExample@o@: $(exampledir)/cxx/LockExample.cpp + $(CXX) $(CXXFLAGS) $? +excxx_lock: LockExample@o@ $(DEF_LIB_CXX) + $(CXXLINK) -o $@ $(LDFLAGS) LockExample@o@ $(DEF_LIB_CXX) $(LIBS) + $(POSTLINK) $@ + +MpoolExample@o@: $(exampledir)/cxx/MpoolExample.cpp + $(CXX) $(CXXFLAGS) $? +excxx_mpool: MpoolExample@o@ $(DEF_LIB_CXX) + $(CXXLINK) -o $@ $(LDFLAGS) MpoolExample@o@ $(DEF_LIB_CXX) $(LIBS) + $(POSTLINK) $@ + +RepQuoteExample@o@: $(exampledir)/cxx/excxx_repquote/RepQuoteExample.cpp + $(CXX) -I$(exampledir)/cxx/excxx_repquote $(CXXFLAGS) $? +RepConfigInfo@o@: $(exampledir)/cxx/excxx_repquote/RepConfigInfo.cpp + $(CXX) -I$(exampledir)/cxx/excxx_repquote $(CXXFLAGS) $? +excxx_repquote: RepQuoteExample@o@ RepConfigInfo@o@ $(DEF_LIB_CXX) + $(CXXLINK) -o $@ $(LDFLAGS) \ + RepQuoteExample@o@ RepConfigInfo@o@ $(DEF_LIB_CXX) $(LIBS) + $(POSTLINK) $@ + +RepMgrGSG@o@: $(exampledir)/cxx/excxx_repquote_gsg/RepMgrGSG.cpp + $(CXX) -I$(exampledir)/cxx/excxx_repquote_gsg $(CXXFLAGS) $? +excxx_repquote_gsg_repmgr: RepMgrGSG@o@ $(DEF_LIB_CXX) + $(CXXLINK) -o $@ $(LDFLAGS) RepMgrGSG@o@ $(DEF_LIB_CXX) $(LIBS) + $(POSTLINK) $@ + +SimpleTxn@o@: $(exampledir)/cxx/excxx_repquote_gsg/SimpleTxn.cpp + $(CXX) -I$(exampledir)/cxx/excxx_repquote_gsg $(CXXFLAGS) $? +excxx_repquote_gsg_simple: SimpleTxn@o@ $(DEF_LIB_CXX) + $(CXXLINK) -o $@ $(LDFLAGS) SimpleTxn@o@ $(DEF_LIB_CXX) $(LIBS) + $(POSTLINK) $@ + +SequenceExample@o@: $(exampledir)/cxx/SequenceExample.cpp + $(CXX) $(CXXFLAGS) $? +excxx_sequence: SequenceExample@o@ $(DEF_LIB_CXX) + $(CXXLINK) -o $@ $(LDFLAGS) SequenceExample@o@ $(DEF_LIB_CXX) $(LIBS) + $(POSTLINK) $@ + +TpcbExample@o@: $(exampledir)/cxx/TpcbExample.cpp + $(CXX) $(CXXFLAGS) $? +excxx_tpcb: TpcbExample@o@ $(DEF_LIB_CXX) + $(CXXLINK) -o $@ $(LDFLAGS) TpcbExample@o@ $(DEF_LIB_CXX) $(LIBS) + $(POSTLINK) $@ + +excxx_example_database_load@o@: \ + $(exampledir)/cxx/getting_started/excxx_example_database_load.cpp + $(CXX) -I$(exampledir)/cxx/getting_started $(CXXFLAGS) $? +excxx_example_database_read@o@: \ + $(exampledir)/cxx/getting_started/excxx_example_database_read.cpp + $(CXX) -I$(exampledir)/cxx/getting_started $(CXXFLAGS) $? +MyDb@o@: $(exampledir)/cxx/getting_started/MyDb.cpp + $(CXX) -I$(exampledir)/cxx/getting_started $(CXXFLAGS) $? +excxx_example_database_load: \ + excxx_example_database_load@o@ MyDb@o@ $(DEF_LIB_CXX) + $(CXXLINK) -o $@ $(LDFLAGS) \ + excxx_example_database_load@o@ MyDb@o@ $(DEF_LIB_CXX) $(LIBS) + $(POSTLINK) $@ +excxx_example_database_read: \ + excxx_example_database_read@o@ MyDb@o@ $(DEF_LIB_CXX) + $(CXXLINK) -o $@ $(LDFLAGS) \ + excxx_example_database_read@o@ MyDb@o@ $(DEF_LIB_CXX) $(LIBS) + $(POSTLINK) $@ + +TxnGuideInMemory@o@: $(exampledir)/cxx/txn_guide/TxnGuideInMemory.cpp + $(CXX) $(CXXFLAGS) $? +TxnGuideInMemory: TxnGuideInMemory@o@ $(DEF_LIB_CXX) + $(CXXLINK) -o $@ $(LDFLAGS) TxnGuideInMemory@o@ $(DEF_LIB_CXX) $(LIBS) + $(POSTLINK) $@ + +TxnGuide@o@: $(exampledir)/cxx/txn_guide/TxnGuide.cpp + $(CXX) $(CXXFLAGS) $? +TxnGuide: TxnGuide@o@ $(DEF_LIB_CXX) + $(CXXLINK) -o $@ $(LDFLAGS) TxnGuide@o@ $(DEF_LIB_CXX) $(LIBS) + $(POSTLINK) $@ + +################################################## +# Example programs for STL. +################################################## +StlAccessExample@o@: $(exampledir)/stl/StlAccessExample.cpp + $(CXX) $(STLFLAGS) $? +exstl_access: StlAccessExample@o@ $(DEF_LIB_STL) + $(CXXLINK) -o $@ $(LDFLAGS) StlAccessExample@o@ $(DEF_LIB_STL) $(LIBS) + $(POSTLINK) $@ + +StlAdvancedFeatures@o@: $(exampledir)/stl/StlAdvancedFeatures.cpp + $(CXX) -I$(exampledir)/stl $(STLFLAGS) $? +exstl_advancedfeatures: StlAdvancedFeatures@o@ $(DEF_LIB_STL) + $(CXXLINK) -o $@ $(LDFLAGS) StlAdvancedFeatures@o@ $(DEF_LIB_STL) $(LIBS) + $(POSTLINK) $@ + +StlRepQuoteExample@o@: $(exampledir)/stl/repquote/StlRepQuoteExample.cpp + $(CXX) -I$(exampledir)/stl/repquote $(STLFLAGS) $? +StlRepConfigInfo@o@: $(exampledir)/stl/repquote/StlRepConfigInfo.cpp + $(CXX) -I$(exampledir)/stl/repquote $(STLFLAGS) $? +exstl_repquote: StlRepQuoteExample@o@ StlRepConfigInfo@o@ $(DEF_LIB_STL) + $(CXXLINK) -o $@ $(LDFLAGS) \ + StlRepQuoteExample@o@ StlRepConfigInfo@o@ $(DEF_LIB_STL) $(LIBS) + $(POSTLINK) $@ + +StlTpcbExample@o@: $(exampledir)/stl/StlTpcbExample.cpp + $(CXX) $(STLFLAGS) $? +exstl_tpcb: StlTpcbExample@o@ $(DEF_LIB_STL) + $(CXXLINK) -o $@ $(LDFLAGS) StlTpcbExample@o@ $(DEF_LIB_STL) $(LIBS) + $(POSTLINK) $@ + +StlTransactionGuideExample@o@: $(exampledir)/stl/StlTransactionGuideExample.cpp + $(CXX) $(STLFLAGS) $? +StlTxnGuide: StlTransactionGuideExample@o@ $(DEF_LIB_STL) + $(CXXLINK) -o $@ $(LDFLAGS) StlTransactionGuideExample@o@ $(DEF_LIB_STL) $(LIBS) + $(POSTLINK) $@ + +################################################## +# Example programs for SQL. +################################################## +ex_sql_binding: ex_sql_binding@o@ ex_sql_utils@o@ $(DEF_LIB_SQL) + $(CCLINK) -o $@ $(LDFLAGS) ex_sql_binding@o@ ex_sql_utils@o@ $(DEF_LIB_SQL) @SQL_LIBS@ $(LIBS) + $(POSTLINK) $@ + +ex_sql_fts3: ex_sql_fts3@o@ ex_sql_utils@o@ $(DEF_LIB_SQL) + $(CCLINK) -o $@ $(LDFLAGS) ex_sql_fts3@o@ ex_sql_utils@o@ $(DEF_LIB_SQL) @SQL_LIBS@ $(LIBS) + $(POSTLINK) $@ + +ex_sql_index: ex_sql_index@o@ ex_sql_utils@o@ $(DEF_LIB_SQL) + $(CCLINK) -o $@ $(LDFLAGS) ex_sql_index@o@ ex_sql_utils@o@ $(DEF_LIB_SQL) @SQL_LIBS@ $(LIBS) + $(POSTLINK) $@ + +ex_sql_load: ex_sql_load@o@ ex_sql_utils@o@ $(DEF_LIB_SQL) + $(CCLINK) -o $@ $(LDFLAGS) ex_sql_load@o@ ex_sql_utils@o@ $(DEF_LIB_SQL) @SQL_LIBS@ $(LIBS) + $(POSTLINK) $@ + +ex_sql_multi_thread: ex_sql_multi_thread@o@ ex_sql_utils@o@ $(DEF_LIB_SQL) + $(CCLINK) -o $@ $(LDFLAGS) ex_sql_multi_thread@o@ ex_sql_utils@o@ $(DEF_LIB_SQL) @SQL_LIBS@ $(LIBS) + $(POSTLINK) $@ + +ex_sql_query: ex_sql_query@o@ ex_sql_utils@o@ $(DEF_LIB_SQL) + $(CCLINK) -o $@ $(LDFLAGS) ex_sql_query@o@ ex_sql_utils@o@ $(DEF_LIB_SQL) @SQL_LIBS@ $(LIBS) + $(POSTLINK) $@ + +ex_sql_rtree: ex_sql_rtree@o@ ex_sql_utils@o@ $(DEF_LIB_SQL) + $(CCLINK) -o $@ $(LDFLAGS) ex_sql_rtree@o@ ex_sql_utils@o@ $(DEF_LIB_SQL) @SQL_LIBS@ $(LIBS) + $(POSTLINK) $@ + +ex_sql_savepoint: ex_sql_savepoint@o@ ex_sql_utils@o@ $(DEF_LIB_SQL) + $(CCLINK) -o $@ $(LDFLAGS) ex_sql_savepoint@o@ ex_sql_utils@o@ $(DEF_LIB_SQL) @SQL_LIBS@ $(LIBS) + $(POSTLINK) $@ + +ex_sql_statement: ex_sql_statement@o@ ex_sql_utils@o@ $(DEF_LIB_SQL) + $(CCLINK) -o $@ $(LDFLAGS) ex_sql_statement@o@ ex_sql_utils@o@ $(DEF_LIB_SQL) @SQL_LIBS@ $(LIBS) + $(POSTLINK) $@ + +ex_sql_transaction: ex_sql_transaction@o@ ex_sql_utils@o@ $(DEF_LIB_SQL) + $(CCLINK) -o $@ $(LDFLAGS) ex_sql_transaction@o@ ex_sql_utils@o@ $(DEF_LIB_SQL) @SQL_LIBS@ $(LIBS) + $(POSTLINK) $@ + +ex_sql_binding@o@: $(exampledir)/sql/c/ex_sql_binding.c + $(CC) $(CFLAGS) $(SQLFLAGS) $? +ex_sql_fts3@o@: $(exampledir)/sql/c/ex_sql_fts3.c + $(CC) $(CFLAGS) $(SQLFLAGS) $? +ex_sql_index@o@: $(exampledir)/sql/c/ex_sql_index.c + $(CC) $(CFLAGS) $(SQLFLAGS) $? +ex_sql_load@o@: $(exampledir)/sql/c/ex_sql_load.c + $(CC) $(CFLAGS) $(SQLFLAGS) $? +ex_sql_multi_thread@o@: $(exampledir)/sql/c/ex_sql_multi_thread.c + $(CC) $(CFLAGS) $(SQLFLAGS) $? +ex_sql_utils@o@: $(exampledir)/sql/c/ex_sql_utils.c + $(CC) $(CFLAGS) $(SQLFLAGS) $? +ex_sql_query@o@: $(exampledir)/sql/c/ex_sql_query.c + $(CC) $(CFLAGS) $(SQLFLAGS) $? +ex_sql_rtree@o@: $(exampledir)/sql/c/ex_sql_rtree.c + $(CC) $(CFLAGS) $(SQLFLAGS) $? +ex_sql_savepoint@o@: $(exampledir)/sql/c/ex_sql_savepoint.c + $(CC) $(CFLAGS) $(SQLFLAGS) $? +ex_sql_statement@o@: $(exampledir)/sql/c/ex_sql_statement.c + $(CC) $(CFLAGS) $(SQLFLAGS) $? +ex_sql_transaction@o@: $(exampledir)/sql/c/ex_sql_transaction.c + $(CC) $(CFLAGS) $(SQLFLAGS) $? + +################################################## +# C API build rules. +################################################## +aes_method@o@: $(srcdir)/crypto/aes_method.c + $(CC) $(CFLAGS) $? +bt_compare@o@: $(srcdir)/btree/bt_compare.c + $(CC) $(CFLAGS) $? +bt_compress@o@: $(srcdir)/btree/bt_compress.c + $(CC) $(CFLAGS) $? +bt_conv@o@: $(srcdir)/btree/bt_conv.c + $(CC) $(CFLAGS) $? +bt_curadj@o@: $(srcdir)/btree/bt_curadj.c + $(CC) $(CFLAGS) $? +bt_cursor@o@: $(srcdir)/btree/bt_cursor.c + $(CC) $(CFLAGS) $? +bt_delete@o@: $(srcdir)/btree/bt_delete.c + $(CC) $(CFLAGS) $? +bt_method@o@: @LOCALSRC@/btree/bt_method.c + $(CC) $(CFLAGS) $? +bt_open@o@: $(srcdir)/btree/bt_open.c + $(CC) $(CFLAGS) $? +bt_put@o@: $(srcdir)/btree/bt_put.c + $(CC) $(CFLAGS) $? +bt_rec@o@: $(srcdir)/btree/bt_rec.c + $(CC) $(CFLAGS) $? +bt_reclaim@o@: $(srcdir)/btree/bt_reclaim.c + $(CC) $(CFLAGS) $? +bt_recno@o@: $(srcdir)/btree/bt_recno.c + $(CC) $(CFLAGS) $? +bt_rsearch@o@: $(srcdir)/btree/bt_rsearch.c + $(CC) $(CFLAGS) $? +bt_search@o@: $(srcdir)/btree/bt_search.c + $(CC) $(CFLAGS) $? +bt_split@o@: $(srcdir)/btree/bt_split.c + $(CC) $(CFLAGS) $? +bt_stat@o@: $(srcdir)/btree/bt_stat.c + $(CC) $(CFLAGS) $? +bt_compact@o@: $(srcdir)/btree/bt_compact.c + $(CC) $(CFLAGS) $? +bt_upgrade@o@: $(srcdir)/btree/bt_upgrade.c + $(CC) $(CFLAGS) $? +bt_verify@o@: $(srcdir)/btree/bt_verify.c + $(CC) $(CFLAGS) $? +btree_auto@o@: $(srcdir)/btree/btree_auto.c + $(CC) $(CFLAGS) $? +btree_autop@o@: $(srcdir)/btree/btree_autop.c + $(CC) $(CFLAGS) $? +clock@o@: $(srcdir)/common/clock.c + $(CC) $(CFLAGS) $? +crdel_auto@o@: $(srcdir)/db/crdel_auto.c + $(CC) $(CFLAGS) $? +crdel_autop@o@: $(srcdir)/db/crdel_autop.c + $(CC) $(CFLAGS) $? +crdel_rec@o@: $(srcdir)/db/crdel_rec.c + $(CC) $(CFLAGS) $? +crypto@o@: $(srcdir)/crypto/crypto.c + $(CC) $(CFLAGS) $? +crypto_stub@o@: $(srcdir)/common/crypto_stub.c + $(CC) $(CFLAGS) $? +db185@o@: $(langdir)/db185/db185.c + $(CC) $(CFLAGS) $? +db@o@: $(srcdir)/db/db.c + $(CC) $(CFLAGS) $? +db_am@o@: $(srcdir)/db/db_am.c + $(CC) $(CFLAGS) $? +db_auto@o@: $(srcdir)/db/db_auto.c + $(CC) $(CFLAGS) $? +db_autop@o@: $(srcdir)/db/db_autop.c + $(CC) $(CFLAGS) $? +db_byteorder@o@: $(srcdir)/common/db_byteorder.c + $(CC) $(CFLAGS) $? +db_backup@o@: $(srcdir)/db/db_backup.c + $(CC) $(CFLAGS) $? +db_cam@o@: $(srcdir)/db/db_cam.c + $(CC) $(CFLAGS) $? +db_cds@o@: $(srcdir)/db/db_cds.c + $(CC) $(CFLAGS) $? +db_compact@o@: $(srcdir)/db/db_compact.c + $(CC) $(CFLAGS) $? +db_compint@o@: $(srcdir)/common/db_compint.c + $(CC) $(CFLAGS) $? +db_conv@o@: $(srcdir)/db/db_conv.c + $(CC) $(CFLAGS) $? +db_copy@o@: $(srcdir)/db/db_copy.c + $(CC) $(CFLAGS) $? +db_dispatch@o@: $(srcdir)/db/db_dispatch.c + $(CC) $(CFLAGS) $? +db_dup@o@: $(srcdir)/db/db_dup.c + $(CC) $(CFLAGS) $? +db_err@o@: $(srcdir)/common/db_err.c + $(CC) $(CFLAGS) $? +db_getlong@o@: @LOCALSRC@/common/db_getlong.c + $(CC) $(CFLAGS) $? +db_idspace@o@: $(srcdir)/common/db_idspace.c + $(CC) $(CFLAGS) $? +db_iface@o@: $(srcdir)/db/db_iface.c + $(CC) $(CFLAGS) $? +db_join@o@: $(srcdir)/db/db_join.c + $(CC) $(CFLAGS) $? +db_lock@o@: $(srcdir)/lock/db_lock.c + $(CC) $(CFLAGS) $? +db_log2@o@: $(srcdir)/common/db_log2.c + $(CC) $(CFLAGS) $? +db_meta@o@: $(srcdir)/db/db_meta.c + $(CC) $(CFLAGS) $? +db_method@o@: @LOCALSRC@/db/db_method.c + $(CC) $(CFLAGS) $? +db_open@o@: $(srcdir)/db/db_open.c + $(CC) $(CFLAGS) $? +db_overflow@o@: $(srcdir)/db/db_overflow.c + $(CC) $(CFLAGS) $? +db_ovfl_vrfy@o@: $(srcdir)/db/db_ovfl_vrfy.c + $(CC) $(CFLAGS) $? +db_pr@o@: $(srcdir)/db/db_pr.c + $(CC) $(CFLAGS) $? +db_rec@o@: $(srcdir)/db/db_rec.c + $(CC) $(CFLAGS) $? +db_reclaim@o@: $(srcdir)/db/db_reclaim.c + $(CC) $(CFLAGS) $? +db_rename@o@: $(srcdir)/db/db_rename.c + $(CC) $(CFLAGS) $? +db_remove@o@: $(srcdir)/db/db_remove.c + $(CC) $(CFLAGS) $? +db_ret@o@: $(srcdir)/db/db_ret.c + $(CC) $(CFLAGS) $? +db_setid@o@: $(srcdir)/db/db_setid.c + $(CC) $(CFLAGS) $? +db_setlsn@o@: $(srcdir)/db/db_setlsn.c + $(CC) $(CFLAGS) $? +db_shash@o@: $(srcdir)/common/db_shash.c + $(CC) $(CFLAGS) $? +db_sort_multiple@o@: $(srcdir)/db/db_sort_multiple.c + $(CC) $(CFLAGS) $? +db_stati@o@: $(srcdir)/db/db_stati.c + $(CC) $(CFLAGS) $? +db_truncate@o@: $(srcdir)/db/db_truncate.c + $(CC) $(CFLAGS) $? +db_upg@o@: $(srcdir)/db/db_upg.c + $(CC) $(CFLAGS) $? +db_upg_opd@o@: $(srcdir)/db/db_upg_opd.c + $(CC) $(CFLAGS) $? +db_vrfy@o@: $(srcdir)/db/db_vrfy.c + $(CC) $(CFLAGS) $? +db_vrfyutil@o@: $(srcdir)/db/db_vrfyutil.c + $(CC) $(CFLAGS) $? +db_vrfy_stub@o@: $(srcdir)/db/db_vrfy_stub.c + $(CC) $(CFLAGS) $? +dbm@o@: $(langdir)/dbm/dbm.c + $(CC) $(CFLAGS) $? +dbreg@o@: $(srcdir)/dbreg/dbreg.c + $(CC) $(CFLAGS) $? +dbreg_auto@o@: $(srcdir)/dbreg/dbreg_auto.c + $(CC) $(CFLAGS) $? +dbreg_autop@o@: $(srcdir)/dbreg/dbreg_autop.c + $(CC) $(CFLAGS) $? +dbreg_rec@o@: $(srcdir)/dbreg/dbreg_rec.c + $(CC) $(CFLAGS) $? +dbreg_stat@o@: $(srcdir)/dbreg/dbreg_stat.c + $(CC) $(CFLAGS) $? +dbreg_util@o@: $(srcdir)/dbreg/dbreg_util.c + $(CC) $(CFLAGS) $? +dbt@o@: $(srcdir)/common/dbt.c + $(CC) $(CFLAGS) $? +env_alloc@o@: $(srcdir)/env/env_alloc.c + $(CC) $(CFLAGS) $? +env_config@o@: $(srcdir)/env/env_config.c + $(CC) $(CFLAGS) $? +env_backup@o@: $(srcdir)/env/env_backup.c + $(CC) $(CFLAGS) $? +env_failchk@o@: $(srcdir)/env/env_failchk.c + $(CC) $(CFLAGS) $? +env_file@o@: $(srcdir)/env/env_file.c + $(CC) $(CFLAGS) $? +env_globals@o@: $(srcdir)/env/env_globals.c + $(CC) $(CFLAGS) $? +env_method@o@: @LOCALSRC@/env/env_method.c + $(CC) $(CFLAGS) $? +env_name@o@: $(srcdir)/env/env_name.c + $(CC) $(CFLAGS) $? +env_open@o@: $(srcdir)/env/env_open.c + $(CC) $(CFLAGS) $? +env_recover@o@: $(srcdir)/env/env_recover.c + $(CC) $(CFLAGS) $? +env_region@o@: $(srcdir)/env/env_region.c + $(CC) $(CFLAGS) $? +env_register@o@: $(srcdir)/env/env_register.c + $(CC) $(CFLAGS) $? +env_sig@o@: @LOCALSRC@/env/env_sig.c + $(CC) $(CFLAGS) $? +env_stat@o@: $(srcdir)/env/env_stat.c + $(CC) $(CFLAGS) $? +fileops_auto@o@: $(srcdir)/fileops/fileops_auto.c + $(CC) $(CFLAGS) $? +fileops_autop@o@: $(srcdir)/fileops/fileops_autop.c + $(CC) $(CFLAGS) $? +fop_basic@o@: $(srcdir)/fileops/fop_basic.c + $(CC) $(CFLAGS) $? +fop_rec@o@: $(srcdir)/fileops/fop_rec.c + $(CC) $(CFLAGS) $? +fop_util@o@: @LOCALSRC@/fileops/fop_util.c + $(CC) $(CFLAGS) $? +hash@o@: $(srcdir)/hash/hash.c + $(CC) $(CFLAGS) $? +hash_auto@o@: $(srcdir)/hash/hash_auto.c + $(CC) $(CFLAGS) $? +hash_autop@o@: $(srcdir)/hash/hash_autop.c + $(CC) $(CFLAGS) $? +hash_compact@o@: $(srcdir)/hash/hash_compact.c + $(CC) $(CFLAGS) $? +hash_conv@o@: $(srcdir)/hash/hash_conv.c + $(CC) $(CFLAGS) $? +hash_dup@o@: $(srcdir)/hash/hash_dup.c + $(CC) $(CFLAGS) $? +hash_func@o@: $(srcdir)/hash/hash_func.c + $(CC) $(CFLAGS) $? +hash_meta@o@: $(srcdir)/hash/hash_meta.c + $(CC) $(CFLAGS) $? +hash_method@o@: $(srcdir)/hash/hash_method.c + $(CC) $(CFLAGS) $? +hash_open@o@: $(srcdir)/hash/hash_open.c + $(CC) $(CFLAGS) $? +hash_page@o@: $(srcdir)/hash/hash_page.c + $(CC) $(CFLAGS) $? +hash_rec@o@: $(srcdir)/hash/hash_rec.c + $(CC) $(CFLAGS) $? +hash_reclaim@o@: $(srcdir)/hash/hash_reclaim.c + $(CC) $(CFLAGS) $? +hash_stat@o@: $(srcdir)/hash/hash_stat.c + $(CC) $(CFLAGS) $? +hash_stub@o@: $(srcdir)/hash/hash_stub.c + $(CC) $(CFLAGS) $? +hash_upgrade@o@: $(srcdir)/hash/hash_upgrade.c + $(CC) $(CFLAGS) $? +hash_verify@o@: $(srcdir)/hash/hash_verify.c + $(CC) $(CFLAGS) $? +heap@o@: $(srcdir)/heap/heap.c + $(CC) $(CFLAGS) $? +heap_auto@o@: $(srcdir)/heap/heap_auto.c + $(CC) $(CFLAGS) $? +heap_autop@o@: $(srcdir)/heap/heap_autop.c + $(CC) $(CFLAGS) $? +heap_backup@o@: $(srcdir)/heap/heap_backup.c + $(CC) $(CFLAGS) $? +heap_conv@o@: $(srcdir)/heap/heap_conv.c + $(CC) $(CFLAGS) $? +heap_method@o@: $(srcdir)/heap/heap_method.c + $(CC) $(CFLAGS) $? +heap_open@o@: $(srcdir)/heap/heap_open.c + $(CC) $(CFLAGS) $? +heap_rec@o@: $(srcdir)/heap/heap_rec.c + $(CC) $(CFLAGS) $? +heap_reclaim@o@: $(srcdir)/heap/heap_reclaim.c + $(CC) $(CFLAGS) $? +heap_stat@o@: $(srcdir)/heap/heap_stat.c + $(CC) $(CFLAGS) $? +heap_stub@o@: $(srcdir)/heap/heap_stub.c + $(CC) $(CFLAGS) $? +heap_verify@o@: $(srcdir)/heap/heap_verify.c + $(CC) $(CFLAGS) $? +hmac@o@: $(srcdir)/hmac/hmac.c + $(CC) $(CFLAGS) $? +hsearch@o@: $(langdir)/hsearch/hsearch.c + $(CC) $(CFLAGS) $? +lock@o@: $(srcdir)/lock/lock.c $(srcdir)/lock/lock_alloc.incl + $(CC) $(CFLAGS) $(srcdir)/lock/lock.c +lock_deadlock@o@:$(srcdir)/lock/lock_deadlock.c + $(CC) $(CFLAGS) $? +lock_failchk@o@:$(srcdir)/lock/lock_failchk.c + $(CC) $(CFLAGS) $? +lock_id@o@:$(srcdir)/lock/lock_id.c + $(CC) $(CFLAGS) $? +lock_list@o@:$(srcdir)/lock/lock_list.c + $(CC) $(CFLAGS) $? +lock_method@o@:$(srcdir)/lock/lock_method.c + $(CC) $(CFLAGS) $? +lock_region@o@:$(srcdir)/lock/lock_region.c + $(CC) $(CFLAGS) $? +lock_stat@o@:$(srcdir)/lock/lock_stat.c + $(CC) $(CFLAGS) $? +lock_stub@o@: $(srcdir)/lock/lock_stub.c + $(CC) $(CFLAGS) $? +lock_timer@o@:$(srcdir)/lock/lock_timer.c + $(CC) $(CFLAGS) $? +lock_util@o@:$(srcdir)/lock/lock_util.c + $(CC) $(CFLAGS) $? +log@o@: $(srcdir)/log/log.c + $(CC) $(CFLAGS) $? +log_archive@o@: $(srcdir)/log/log_archive.c + $(CC) $(CFLAGS) $? +log_compare@o@: $(srcdir)/log/log_compare.c + $(CC) $(CFLAGS) $? +log_debug@o@: $(srcdir)/log/log_debug.c + $(CC) $(CFLAGS) $? +log_get@o@: $(srcdir)/log/log_get.c + $(CC) $(CFLAGS) $? +log_method@o@: $(srcdir)/log/log_method.c + $(CC) $(CFLAGS) $? +log_print@o@: $(srcdir)/log/log_print.c + $(CC) $(CFLAGS) $? +log_put@o@: $(srcdir)/log/log_put.c + $(CC) $(CFLAGS) $? +log_stat@o@: $(srcdir)/log/log_stat.c + $(CC) $(CFLAGS) $? +log_verify@o@: $(srcdir)/log/log_verify.c + $(CC) $(CFLAGS) $? +log_verify_auto@o@: $(srcdir)/log/log_verify_auto.c + $(CC) $(CFLAGS) $? +log_verify_int@o@: $(srcdir)/log/log_verify_int.c + $(CC) $(CFLAGS) $? +log_verify_util@o@: $(srcdir)/log/log_verify_util.c + $(CC) $(CFLAGS) $? +log_verify_stub@o@: $(srcdir)/log/log_verify_stub.c + $(CC) $(CFLAGS) $? +db_log_verify@o@: $(utildir)/db_log_verify.c + $(CC) $(CFLAGS) $? +mkpath@o@: $(srcdir)/common/mkpath.c + $(CC) $(CFLAGS) $? +mp_alloc@o@: @LOCALSRC@/mp/mp_alloc.c + $(CC) $(CFLAGS) $? +mp_bh@o@: $(srcdir)/mp/mp_bh.c + $(CC) $(CFLAGS) $? +mp_backup@o@: $(srcdir)/mp/mp_backup.c + $(CC) $(CFLAGS) $? +mp_fget@o@: @LOCALSRC@/mp/mp_fget.c + $(CC) $(CFLAGS) $? +mp_fmethod@o@: $(srcdir)/mp/mp_fmethod.c + $(CC) $(CFLAGS) $? +mp_fopen@o@: $(srcdir)/mp/mp_fopen.c + $(CC) $(CFLAGS) $? +mp_fput@o@: $(srcdir)/mp/mp_fput.c + $(CC) $(CFLAGS) $? +mp_fset@o@: @LOCALSRC@/mp/mp_fset.c + $(CC) $(CFLAGS) $? +mp_method@o@: $(srcdir)/mp/mp_method.c + $(CC) $(CFLAGS) $? +mp_mvcc@o@: $(srcdir)/mp/mp_mvcc.c + $(CC) $(CFLAGS) $? +mp_region@o@: $(srcdir)/mp/mp_region.c + $(CC) $(CFLAGS) $? +mp_register@o@: $(srcdir)/mp/mp_register.c + $(CC) $(CFLAGS) $? +mp_resize@o@: @LOCALSRC@/mp/mp_resize.c + $(CC) $(CFLAGS) $? +mp_stat@o@: $(srcdir)/mp/mp_stat.c + $(CC) $(CFLAGS) $? +mp_sync@o@: $(srcdir)/mp/mp_sync.c + $(CC) $(CFLAGS) $? +mp_trickle@o@: $(srcdir)/mp/mp_trickle.c + $(CC) $(CFLAGS) $? +mt19937db@o@: $(srcdir)/crypto/mersenne/mt19937db.c + $(CC) $(CFLAGS) $? +mut_alloc@o@: $(srcdir)/mutex/mut_alloc.c + $(CC) $(CFLAGS) $? +mut_failchk@o@: $(srcdir)/mutex/mut_failchk.c + $(CC) $(CFLAGS) $? +mut_fcntl@o@: $(srcdir)/mutex/mut_fcntl.c + $(CC) $(CFLAGS) $? +mut_method@o@: $(srcdir)/mutex/mut_method.c + $(CC) $(CFLAGS) $? +mut_pthread@o@: $(srcdir)/mutex/mut_pthread.c + $(CC) $(CFLAGS) $? +mut_region@o@: $(srcdir)/mutex/mut_region.c + $(CC) $(CFLAGS) $? +mut_stat@o@: $(srcdir)/mutex/mut_stat.c + $(CC) $(CFLAGS) $? +mut_stub@o@: $(srcdir)/mutex/mut_stub.c + $(CC) $(CFLAGS) $? +mut_tas@o@: $(srcdir)/mutex/mut_tas.c + $(CC) $(CFLAGS) $? +mut_win32@o@: $(srcdir)/mutex/mut_win32.c + $(CC) $(CFLAGS) $? +openflags@o@: $(srcdir)/common/openflags.c + $(CC) $(CFLAGS) $? +os_abs@o@: $(srcdir)/@OSDIR@/os_abs.c + $(CC) $(CFLAGS) $? +os_abort@o@: $(srcdir)/os/os_abort.c + $(CC) $(CFLAGS) $? +os_addrinfo@o@: $(srcdir)/os/os_addrinfo.c + $(CC) $(CFLAGS) $? +os_alloc@o@: $(srcdir)/os/os_alloc.c + $(CC) $(CFLAGS) $? +os_clock@o@: $(srcdir)/@OSDIR@/os_clock.c + $(CC) $(CFLAGS) $? +os_config@o@: $(srcdir)/@OSDIR@/os_config.c + $(CC) $(CFLAGS) $? +os_cpu@o@: $(srcdir)/@OSDIR@/os_cpu.c + $(CC) $(CFLAGS) $? +os_ctime@o@: $(srcdir)/os/os_ctime.c + $(CC) $(CFLAGS) $? +os_dir@o@: $(srcdir)/@OSDIR@/os_dir.c + $(CC) $(CFLAGS) $? +os_errno@o@: $(srcdir)/@OSDIR@/os_errno.c + $(CC) $(CFLAGS) $? +os_fid@o@: $(srcdir)/@OSDIR@/os_fid.c + $(CC) $(CFLAGS) $? +os_flock@o@: $(srcdir)/@OSDIR@/os_flock.c + $(CC) $(CFLAGS) $? +os_fsync@o@: $(srcdir)/@OSDIR@/os_fsync.c + $(CC) $(CFLAGS) $? +os_getenv@o@: $(srcdir)/@OSDIR@/os_getenv.c + $(CC) $(CFLAGS) $? +os_handle@o@: $(srcdir)/@OSDIR@/os_handle.c + $(CC) $(CFLAGS) $? +os_map@o@: $(srcdir)/@OSDIR@/os_map.c + $(CC) $(CFLAGS) $? +os_method@o@: $(srcdir)/common/os_method.c + $(CC) $(CFLAGS) $? +os_mkdir@o@: $(srcdir)/@OSDIR@/os_mkdir.c + $(CC) $(CFLAGS) $? +os_open@o@: $(srcdir)/@OSDIR@/os_open.c + $(CC) $(CFLAGS) $? +os_path@o@: $(srcdir)/os/os_path.c + $(CC) $(CFLAGS) $? +os_pid@o@: $(srcdir)/os/os_pid.c + $(CC) $(CFLAGS) $? +os_qnx_fsync@o@: $(srcdir)/os_qnx/os_qnx_fsync.c + $(CC) $(CFLAGS) $? +os_qnx_open@o@: $(srcdir)/os_qnx/os_qnx_open.c + $(CC) $(CFLAGS) $? +os_rename@o@: $(srcdir)/@OSDIR@/os_rename.c + $(CC) $(CFLAGS) $? +os_root@o@: $(srcdir)/os/os_root.c + $(CC) $(CFLAGS) $? +os_rpath@o@: $(srcdir)/os/os_rpath.c + $(CC) $(CFLAGS) $? +os_rw@o@: $(srcdir)/@OSDIR@/os_rw.c + $(CC) $(CFLAGS) $? +os_seek@o@: $(srcdir)/@OSDIR@/os_seek.c + $(CC) $(CFLAGS) $? +os_stack@o@: $(srcdir)/os/os_stack.c + $(CC) $(CFLAGS) $? +os_stat@o@: $(srcdir)/@OSDIR@/os_stat.c + $(CC) $(CFLAGS) $? +os_tmpdir@o@: $(srcdir)/os/os_tmpdir.c + $(CC) $(CFLAGS) $? +os_truncate@o@: $(srcdir)/@OSDIR@/os_truncate.c + $(CC) $(CFLAGS) $? +os_uid@o@: $(srcdir)/os/os_uid.c + $(CC) $(CFLAGS) $? +os_unlink@o@: $(srcdir)/@OSDIR@/os_unlink.c + $(CC) $(CFLAGS) $? +os_yield@o@: $(srcdir)/@OSDIR@/os_yield.c + $(CC) $(CFLAGS) $? +partition@o@: $(srcdir)/db/partition.c + $(CC) $(CFLAGS) $? +partition_stub@o@: $(srcdir)/db/partition_stub.c + $(CC) $(CFLAGS) $? +qam@o@: $(srcdir)/qam/qam.c + $(CC) $(CFLAGS) $? +qam_auto@o@: $(srcdir)/qam/qam_auto.c + $(CC) $(CFLAGS) $? +qam_autop@o@: $(srcdir)/qam/qam_autop.c + $(CC) $(CFLAGS) $? +qam_conv@o@: $(srcdir)/qam/qam_conv.c + $(CC) $(CFLAGS) $? +qam_files@o@: $(srcdir)/qam/qam_files.c + $(CC) $(CFLAGS) $? +qam_method@o@: $(srcdir)/qam/qam_method.c + $(CC) $(CFLAGS) $? +qam_open@o@: $(srcdir)/qam/qam_open.c + $(CC) $(CFLAGS) $? +qam_rec@o@: $(srcdir)/qam/qam_rec.c + $(CC) $(CFLAGS) $? +qam_stat@o@: $(srcdir)/qam/qam_stat.c + $(CC) $(CFLAGS) $? +qam_stub@o@: $(srcdir)/qam/qam_stub.c + $(CC) $(CFLAGS) $? +qam_upgrade@o@: $(srcdir)/qam/qam_upgrade.c + $(CC) $(CFLAGS) $? +qam_verify@o@: $(srcdir)/qam/qam_verify.c + $(CC) $(CFLAGS) $? +rds_stub@o@: $(srcdir)/common/rds_stub.c + $(CC) $(CFLAGS) $? +rep_automsg@o@: $(srcdir)/rep/rep_automsg.c + $(CC) $(CFLAGS) $? +rep_backup@o@: $(srcdir)/rep/rep_backup.c + $(CC) $(CFLAGS) $? +rep_elect@o@: $(srcdir)/rep/rep_elect.c + $(CC) $(CFLAGS) $? +rep_lease@o@: $(srcdir)/rep/rep_lease.c + $(CC) $(CFLAGS) $? +rep_log@o@: $(srcdir)/rep/rep_log.c + $(CC) $(CFLAGS) $? +rep_method@o@: $(srcdir)/rep/rep_method.c + $(CC) $(CFLAGS) $? +rep_record@o@: $(srcdir)/rep/rep_record.c + $(CC) $(CFLAGS) $? +rep_region@o@: $(srcdir)/rep/rep_region.c + $(CC) $(CFLAGS) $? +rep_stub@o@: $(srcdir)/rep/rep_stub.c + $(CC) $(CFLAGS) $? +rep_stat@o@: $(srcdir)/rep/rep_stat.c + $(CC) $(CFLAGS) $? +rep_util@o@: $(srcdir)/rep/rep_util.c + $(CC) $(CFLAGS) $? +rep_verify@o@: $(srcdir)/rep/rep_verify.c + $(CC) $(CFLAGS) $? +repmgr_auto@o@: $(srcdir)/repmgr/repmgr_auto.c + $(CC) $(CFLAGS) $? +repmgr_automsg@o@: $(srcdir)/repmgr/repmgr_automsg.c + $(CC) $(CFLAGS) $? +repmgr_autop@o@: $(srcdir)/repmgr/repmgr_autop.c + $(CC) $(CFLAGS) $? +repmgr_elect@o@: $(srcdir)/repmgr/repmgr_elect.c + $(CC) $(CFLAGS) $? +repmgr_method@o@: $(srcdir)/repmgr/repmgr_method.c + $(CC) $(CFLAGS) $? +repmgr_msg@o@: $(srcdir)/repmgr/repmgr_msg.c + $(CC) $(CFLAGS) $? +repmgr_net@o@: $(srcdir)/repmgr/repmgr_net.c + $(CC) $(CFLAGS) $? +repmgr_posix@o@: $(srcdir)/repmgr/repmgr_posix.c + $(CC) $(CFLAGS) $? +repmgr_queue@o@: $(srcdir)/repmgr/repmgr_queue.c + $(CC) $(CFLAGS) $? +repmgr_rec@o@: $(srcdir)/repmgr/repmgr_rec.c + $(CC) $(CFLAGS) $? +repmgr_sel@o@: $(srcdir)/repmgr/repmgr_sel.c + $(CC) $(CFLAGS) $? +repmgr_stat@o@: $(srcdir)/repmgr/repmgr_stat.c + $(CC) $(CFLAGS) $? +repmgr_stub@o@: $(srcdir)/repmgr/repmgr_stub.c + $(CC) $(CFLAGS) $? +repmgr_util@o@: $(srcdir)/repmgr/repmgr_util.c + $(CC) $(CFLAGS) $? +rijndael-alg-fst@o@: $(srcdir)/crypto/rijndael/rijndael-alg-fst.c + $(CC) $(CFLAGS) $? +rijndael-api-fst@o@: $(srcdir)/crypto/rijndael/rijndael-api-fst.c + $(CC) $(CFLAGS) $? +seq_stat@o@: $(srcdir)/sequence/seq_stat.c + $(CC) $(CFLAGS) $? +sequence@o@: $(srcdir)/sequence/sequence.c + $(CC) $(CFLAGS) $? +sha1@o@: $(srcdir)/hmac/sha1.c + $(CC) $(CFLAGS) $? +stat_stub@o@: $(srcdir)/common/stat_stub.c + $(CC) $(CFLAGS) $? +txn@o@: $(srcdir)/txn/txn.c + $(CC) $(CFLAGS) $? +txn_auto@o@: $(srcdir)/txn/txn_auto.c + $(CC) $(CFLAGS) $? +txn_autop@o@: $(srcdir)/txn/txn_autop.c + $(CC) $(CFLAGS) $? +txn_chkpt@o@: $(srcdir)/txn/txn_chkpt.c + $(CC) $(CFLAGS) $? +txn_failchk@o@: $(srcdir)/txn/txn_failchk.c + $(CC) $(CFLAGS) $? +txn_method@o@: $(srcdir)/txn/txn_method.c + $(CC) $(CFLAGS) $? +txn_rec@o@: $(srcdir)/txn/txn_rec.c + $(CC) $(CFLAGS) $? +txn_recover@o@: $(srcdir)/txn/txn_recover.c + $(CC) $(CFLAGS) $? +txn_region@o@: $(srcdir)/txn/txn_region.c + $(CC) $(CFLAGS) $? +txn_stat@o@: $(srcdir)/txn/txn_stat.c + $(CC) $(CFLAGS) $? +txn_util@o@: $(srcdir)/txn/txn_util.c + $(CC) $(CFLAGS) $? +util_arg@o@: $(srcdir)/common/util_arg.c + $(CC) $(CFLAGS) $? +util_cache@o@: $(srcdir)/common/util_cache.c + $(CC) $(CFLAGS) $? +util_log@o@: $(srcdir)/common/util_log.c + $(CC) $(CFLAGS) $? +util_sig@o@: $(srcdir)/common/util_sig.c + $(CC) $(CFLAGS) $? +uts4_cc@o@: $(srcdir)/mutex/uts4_cc.s + $(AS) $(ASFLAGS) -o $@ $? +xa@o@: $(srcdir)/xa/xa.c + $(CC) $(CFLAGS) $? +xa_map@o@: $(srcdir)/xa/xa_map.c + $(CC) $(CFLAGS) $? +zerofill@o@: $(srcdir)/common/zerofill.c + $(CC) $(CFLAGS) $? + +################################################## +# C++ API build rules. +################################################## +cxx_channel@o@: $(langdir)/cxx/cxx_channel.cpp + $(CXX) $(CXXFLAGS) $? +cxx_db@o@: $(langdir)/cxx/cxx_db.cpp + $(CXX) $(CXXFLAGS) $? +cxx_dbc@o@: $(langdir)/cxx/cxx_dbc.cpp + $(CXX) $(CXXFLAGS) $? +cxx_dbt@o@: $(langdir)/cxx/cxx_dbt.cpp + $(CXX) $(CXXFLAGS) $? +cxx_env@o@: $(langdir)/cxx/cxx_env.cpp + $(CXX) $(CXXFLAGS) $? +cxx_except@o@: $(langdir)/cxx/cxx_except.cpp + $(CXX) $(CXXFLAGS) $? +cxx_lock@o@: $(langdir)/cxx/cxx_lock.cpp + $(CXX) $(CXXFLAGS) $? +cxx_logc@o@: $(langdir)/cxx/cxx_logc.cpp + $(CXX) $(CXXFLAGS) $? +cxx_mpool@o@: $(langdir)/cxx/cxx_mpool.cpp + $(CXX) $(CXXFLAGS) $? +cxx_multi@o@: $(langdir)/cxx/cxx_multi.cpp + $(CXX) $(CXXFLAGS) $? +cxx_rid@o@: $(langdir)/cxx/cxx_rid.cpp + $(CXX) $(CXXFLAGS) $? +cxx_seq@o@: $(langdir)/cxx/cxx_seq.cpp + $(CXX) $(CXXFLAGS) $? +cxx_site@o@: $(langdir)/cxx/cxx_site.cpp + $(CXX) $(CXXFLAGS) $? +cxx_txn@o@: $(langdir)/cxx/cxx_txn.cpp + $(CXX) $(CXXFLAGS) $? + +################################################## +# Java API build rules. +################################################## +db_java_wrap@o@: $(langdir)/java/libdb_java/db_java_wrap.c + $(CC) $(CFLAGS) $(SWIGCFLAGS) $? + +################################################## +# SQL API build rules. +################################################## +sqlite3@o@: $(langdir)/sql/generated/sqlite3.c + $(CC) $(CFLAGS) $(SQLFLAGS) $? +shell@o@: $(langdir)/sql/sqlite/src/shell.c + $(CC) $(CFLAGS) $(SQLFLAGS) $? + +################################################## +# STL API build rules. +################################################## +dbstl_container@o@: $(langdir)/cxx/stl/dbstl_container.cpp + $(CXX) $(STLFLAGS) $? +dbstl_resource_manager@o@: $(langdir)/cxx/stl/dbstl_resource_manager.cpp + $(CXX) $(STLFLAGS) $? + +################################################## +# Tcl API build rules. +################################################## +tcl_compat@o@: $(TCL_SRCDIR)/tcl_compat.c + $(CC) $(CFLAGS) $(TCL_INCLUDE_SPEC) $? +tcl_db@o@: $(TCL_SRCDIR)/tcl_db.c + $(CC) $(CFLAGS) $(TCL_INCLUDE_SPEC) $? +tcl_db_pkg@o@: $(TCL_SRCDIR)/tcl_db_pkg.c + $(CC) $(CFLAGS) $(TCL_INCLUDE_SPEC) $? +tcl_dbcursor@o@: $(TCL_SRCDIR)/tcl_dbcursor.c + $(CC) $(CFLAGS) $(TCL_INCLUDE_SPEC) $? +tcl_env@o@: $(TCL_SRCDIR)/tcl_env.c + $(CC) $(CFLAGS) $(TCL_INCLUDE_SPEC) $? +tcl_internal@o@: $(TCL_SRCDIR)/tcl_internal.c + $(CC) $(CFLAGS) $(TCL_INCLUDE_SPEC) $? +tcl_lock@o@: $(TCL_SRCDIR)/tcl_lock.c + $(CC) $(CFLAGS) $(TCL_INCLUDE_SPEC) $? +tcl_log@o@: $(TCL_SRCDIR)/tcl_log.c + $(CC) $(CFLAGS) $(TCL_INCLUDE_SPEC) $? +tcl_mp@o@: $(TCL_SRCDIR)/tcl_mp.c + $(CC) $(CFLAGS) $(TCL_INCLUDE_SPEC) $? +tcl_mutex@o@: $(TCL_SRCDIR)/tcl_mutex.c + $(CC) $(CFLAGS) $(TCL_INCLUDE_SPEC) $? +tcl_rep@o@: $(TCL_SRCDIR)/tcl_rep.c + $(CC) $(CFLAGS) $(TCL_INCLUDE_SPEC) $? +tcl_seq@o@: $(TCL_SRCDIR)/tcl_seq.c + $(CC) $(CFLAGS) $(TCL_INCLUDE_SPEC) $? +tcl_txn@o@: $(TCL_SRCDIR)/tcl_txn.c + $(CC) $(CFLAGS) $(TCL_INCLUDE_SPEC) $? +tcl_util@o@: $(TCL_SRCDIR)/tcl_util.c + $(CC) $(CFLAGS) $(TCL_INCLUDE_SPEC) $? + +################################################## +# Utility build rules. +################################################## +db_archive@o@: $(utildir)/db_archive.c + $(CC) $(CFLAGS) $? +db_checkpoint@o@: $(utildir)/db_checkpoint.c + $(CC) $(CFLAGS) $? +db_deadlock@o@: $(utildir)/db_deadlock.c + $(CC) $(CFLAGS) $? +db_dump@o@: $(utildir)/db_dump.c + $(CC) $(CFLAGS) $? +db_dump185@o@: $(utildir)/db_dump185.c + $(CC) $(DB185INC) $? +db_hotbackup@o@: $(utildir)/db_hotbackup.c + $(CC) $(CFLAGS) $? +db_load@o@: @LOCALUTILS@/db_load.c + $(CC) $(CFLAGS) $? +db_printlog@o@: $(utildir)/db_printlog.c + $(CC) $(CFLAGS) $? +db_recover@o@: $(utildir)/db_recover.c + $(CC) $(CFLAGS) $? +db_replicate@o@: $(utildir)/db_replicate.c + $(CC) $(CFLAGS) $? +db_stat@o@: @LOCALUTILS@/db_stat.c + $(CC) $(CFLAGS) $? +db_tuner@o@: $(utildir)/db_tuner.c + $(CC) $(CFLAGS) $? +db_upgrade@o@: $(utildir)/db_upgrade.c + $(CC) $(CFLAGS) $? +db_verify@o@: $(utildir)/db_verify.c + $(CC) $(CFLAGS) $? + +db_sql_codegen@o@: $(utildir)/db_sql_codegen/db_sql_codegen.c + $(CC) $(CFLAGS) $? +preparser@o@: $(utildir)/db_sql_codegen/preparser.c + $(CC) $(CFLAGS) $? +parsefuncs@o@: $(utildir)/db_sql_codegen/parsefuncs.c + $(CC) $(CFLAGS) $? +tokenize@o@: $(utildir)/db_sql_codegen/tokenize.c + $(CC) $(CFLAGS) $? +buildpt@o@: $(utildir)/db_sql_codegen/buildpt.c + $(CC) $(CFLAGS) $? +utils@o@: $(utildir)/db_sql_codegen/utils.c + $(CC) $(CFLAGS) $? +generate@o@: $(utildir)/db_sql_codegen/generate.c + $(CC) $(CFLAGS) $? +generate_test@o@: $(utildir)/db_sql_codegen/generate_test.c + $(CC) $(CFLAGS) $? +generate_verification@o@: $(utildir)/db_sql_codegen/generate_verification.c + $(CC) $(CFLAGS) $? +generation_utils@o@: $(utildir)/db_sql_codegen/generation_utils.c + $(CC) $(CFLAGS) $? +hint_comment@o@: $(utildir)/db_sql_codegen/hint_comment.c + $(CC) $(CFLAGS) $? +sqlprintf@o@: $(utildir)/db_sql_codegen/sqlite/sqlprintf.c + $(CC) $(CFLAGS) $? +parse@o@: $(utildir)/db_sql_codegen/sqlite/parse.c + $(CC) $(CFLAGS) $? + +################################################## +# C library replacement files. +################################################## +atoi@o@: $(srcdir)/clib/atoi.c + $(CC) $(CFLAGS) $? +atol@o@: $(srcdir)/clib/atol.c + $(CC) $(CFLAGS) $? +bsearch@o@: $(srcdir)/clib/bsearch.c + $(CC) $(CFLAGS) $? +getcwd@o@: $(srcdir)/clib/getcwd.c + $(CC) $(CFLAGS) $? +getopt@o@: $(srcdir)/clib/getopt.c + $(CC) $(CFLAGS) $? +isalpha@o@: $(srcdir)/clib/isalpha.c + $(CC) $(CFLAGS) $? +isdigit@o@: $(srcdir)/clib/isdigit.c + $(CC) $(CFLAGS) $? +isprint@o@: $(srcdir)/clib/isprint.c + $(CC) $(CFLAGS) $? +isspace@o@: $(srcdir)/clib/isspace.c + $(CC) $(CFLAGS) $? +memcmp@o@: $(srcdir)/clib/memcmp.c + $(CC) $(CFLAGS) $? +memcpy@o@: $(srcdir)/clib/memmove.c + $(CC) -DMEMCOPY $(CFLAGS) $? -o $@ +memmove@o@: $(srcdir)/clib/memmove.c + $(CC) -DMEMMOVE $(CFLAGS) $? +printf@o@: $(srcdir)/clib/printf.c + $(CC) $(CFLAGS) $? +qsort@o@: $(srcdir)/clib/qsort.c + $(CC) $(CFLAGS) $? +raise@o@: $(srcdir)/clib/raise.c + $(CC) $(CFLAGS) $? +rand@o@: $(srcdir)/clib/rand.c + $(CC) $(CFLAGS) $? +strcasecmp@o@: $(srcdir)/clib/strcasecmp.c + $(CC) $(CFLAGS) $? +strdup@o@: $(srcdir)/clib/strdup.c + $(CC) $(CFLAGS) $? +snprintf@o@: $(srcdir)/clib/snprintf.c + $(CC) $(CFLAGS) $? +strcat@o@: $(srcdir)/clib/strcat.c + $(CC) $(CFLAGS) $? +strchr@o@: $(srcdir)/clib/strchr.c + $(CC) $(CFLAGS) $? +strerror@o@: $(srcdir)/clib/strerror.c + $(CC) $(CFLAGS) $? +strncat@o@: $(srcdir)/clib/strncat.c + $(CC) $(CFLAGS) $? +strncmp@o@: $(srcdir)/clib/strncmp.c + $(CC) $(CFLAGS) $? +strrchr@o@: $(srcdir)/clib/strrchr.c + $(CC) $(CFLAGS) $? +strsep@o@: $(srcdir)/clib/strsep.c + $(CC) $(CFLAGS) $? +strtol@o@: $(srcdir)/clib/strtol.c + $(CC) $(CFLAGS) $? +strtoul@o@: $(srcdir)/clib/strtoul.c + $(CC) $(CFLAGS) $? +time@o@: $(srcdir)/clib/time.c + $(CC) $(CFLAGS) $? + +################################################## +# Performance Event Monitoring build rules +################################################## + +# DTrace rules: +# The DTrace DB provider description (db_provider.d) is included in the +# distribution. It needs to be rebuilt when adding events to +# $(distdir)/events.in. The C/C++ header file db_provider.h is +# created at configure time, and is rebuilt when db_provider.d changes. +# It has lower-case versions of the event class and type names. +# +# To list the DB static probes, try: +# [pfexec | sudo] dtrace -l -n 'bdb$target:::' -c " " +# [sudo] stap -l 'process(".libs/libdb-@DB_VERSION_MAJOR@.@DB_VERSION_MINOR@.so").mark("*")' +listevents listprobes: @LISTPROBES_DEPENDENCY@ + @LISTPROBES_COMMAND@ + +$(DTRACE_PROVIDER): $(distdir)/gen_provider.pl $(distdir)/events.in + -@$(RM) $@ + $(PERL) $(distdir)/gen_provider.pl $(distdir)/events.in > $@ + +SED_PROVIDER_PATTERN='/^\#define[ ]*BDB_[A-Z_]*(/y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/' +db_provider.h : $(DTRACE_PROVIDER) + -@$(RM) $@ + @if test -z "$(DTRACE)" ; then echo "$@ is used only with dtrace or stap"; exit 1; fi + ($(DTRACE) -h @DTRACE_CPP@ -I$(utildir)/dtrace -s $(DTRACE_PROVIDER) -o $@ && \ + $(MV) $@ $@.tmp && \ + $(SED) -e $(SED_PROVIDER_PATTERN) $@.tmp > $@) || $(RM) $@ + @$(RM) $@.tmp + +# DTrace on platforms which require dtrace -G (e.g., Solaris) need to include +# an extra object file when linking. This placeholder 'db_provider.lo' has a +# special update rule which knows that the PIC object files may be in .libs. +# If that directory exists, the object files located there are updated by a +# separate dtrace -G call. +# +# Should this be added to libtool's --mode=link step on Solaris? +# +DTRACE_OFILES=`echo $(DTRACE_OBJS) " " | $(SED) -e 's/\.lo /\.o /g'` + +db_provider@o@: db_provider.c $(DTRACE_OBJS) $(DTRACE_PROVIDER) + $(RM) db_provider.o .libs/db_provider.o + @# A compilation warning such as 'empty translation unit' is harmless. + $(CC) $(CFLAGS) db_provider.c + if test -f db_provider.o ; then \ + $(DTRACE) -G @DTRACE_CPP@ -I$(utildir)/dtrace -s $(DTRACE_PROVIDER) $(DTRACE_OFILES) ; \ + fi + if test -f .libs/db_provider.o ; then \ + (cd .libs && \ + $(DTRACE) -G @DTRACE_CPP@ -I../$(utildir)/dtrace -s ../$(DTRACE_PROVIDER) $(DTRACE_OFILES)) || \ + $(RM) $@ ; \ + fi + +# db_provider.c is created as an empty file at configure time with +# --enable-dtrace. If missing then configure should be re-run. +# So far only Solaris needs it. +db_provider.c: + @echo "The file db_provider@o@ is used only for configurations requiring dtrace -G" + @echo "Re-run configure with --enable-dtrace if needed" + @exit 1 diff -r 000000000000 -r a1985f14b030 dist/RELEASE --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dist/RELEASE Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,40 @@ +# $Id$ +# Copyright (c) 1999, 2012 Oracle and/or its affiliates. All rights reserved. +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. Oracle designates this +# particular file as subject to the "Classpath" exception as provided +# by Oracle in the LICENSE file that accompanied this code. +# +# This code 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 General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. + +DB_VERSION_FAMILY=11 +DB_VERSION_LETTER="g" +DB_VERSION_RELEASE=2 +DB_VERSION_MAJOR=5 +DB_VERSION_MINOR=4 +DB_VERSION_PATCH=0 +DB_VERSION="$DB_VERSION_MAJOR.$DB_VERSION_MINOR.$DB_VERSION_PATCH" +DB_VERSION_FULL="$DB_VERSION_FAMILY.$DB_VERSION_RELEASE.$DB_VERSION_MAJOR.$DB_VERSION_MINOR.$DB_VERSION_PATCH" + +DB_VERSION_UNIQUE_NAME=`printf "_%d%03d" $DB_VERSION_MAJOR $DB_VERSION_MINOR` + +DB_RELEASE_DATE="May 7, 2012" +DB_PRODUCT_NAME="Berkeley DB" +DB_VERSION_STRING="$DB_PRODUCT_NAME $DB_VERSION: ($DB_RELEASE_DATE)" +DB_VERSION_FULL_STRING="$DB_PRODUCT_NAME $DB_VERSION_FAMILY$DB_VERSION_LETTER Release $DB_VERSION_RELEASE, library version $DB_VERSION_FULL: ($DB_RELEASE_DATE)" diff -r 000000000000 -r a1985f14b030 dist/api_flags --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dist/api_flags Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,565 @@ +# Copyright (c) 2008, 2012 Oracle and/or its affiliates. All rights reserved. +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. Oracle designates this +# particular file as subject to the "Classpath" exception as provided +# by Oracle in the LICENSE file that accompanied this code. +# +# This code 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 General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. +db_env_create + DB_CXX_NO_EXCEPTIONS # C++: return error values + +DbEnv.backup + # Remove all files from the target directory tree first. + DB_BACKUP_CLEAN + DB_BACKUP_FILES # Copy plain files too. + DB_BACKUP_NO_LOGS # Don't backup log files. + DB_BACKUP_SINGLE_DIR # All files go to a single directory. + DB_BACKUP_UPDATE # Incremental backup. + DB_CREATE # Create the target directories. + DB_EXCL # Error if a target file exists. + +DbEnv.close + # Sync database when automatically closing its db handles. + DB_FORCESYNC + +DbEnv.dbremove + DB_AUTO_COMMIT # Implied transaction + DB_LOG_NO_DATA # UNDOC: Don't log the data. + DB_NOSYNC # UNDOC: Don't sync for a subdb remove + DB_TXN_NOT_DURABLE # UNDOC: Don't log the remove + +DbEnv.dbrename + DB_AUTO_COMMIT # Implied transaction + DB_NOSYNC # Don't sync for a subdb rename + +DbEnv.fileid_reset + DB_ENCRYPT # File contains encrypted databases + +DbEnv.log_verify + DB_LOG_VERIFY_ERR # Verify failed. + DB_LOG_VERIFY_CAF # Continue after a failed check. + # Not the entire logs are verified, due to user specified log range, + # archiving, or other reasons. Only part of the entire logs verified. + DB_LOG_VERIFY_PARTIAL + DB_LOG_VERIFY_DBFILE # Verify only logs of one db file. + # Pre-scan log from last to first record to get aborts and timestamps. + DB_LOG_VERIFY_FORWARD + DB_LOG_VERIFY_INTERR # Got internal error during verify. + DB_LOG_VERIFY_WARNING # Got warnings during verify. + DB_LOG_VERIFY_VERBOSE # Output verbose information. + +DbEnv.open + DB_CREATE # Create as necessary + DB_FAILCHK # Run failchk on open + DB_FAILCHK_ISALIVE # UNDOC: failchk with isalive, for SQL + DB_INIT_CDB # Concurrent Access Methods + DB_INIT_LOCK # Initialize locking + DB_INIT_LOG # Initialize logging + DB_INIT_MPOOL # Initialize mpool + DB_INIT_MUTEX # Initialize mutex + DB_INIT_REP # Initialize replication + DB_INIT_TXN # Initialize transactions + DB_LOCKDOWN # Lock memory into physical core + DB_NO_CHECKPOINT # UNDOC: Recover but do not checkpoint + DB_PRIVATE # DB_ENV is process local + DB_RECOVER # Run normal recovery + DB_RECOVER_FATAL # Run catastrophic recovery + DB_REGISTER # Multi-process registry + DB_SYSTEM_MEM # Use system-backed memory + DB_THREAD # Handle is free-threaded + DB_USE_ENVIRON # Use the environment + DB_USE_ENVIRON_ROOT # Use the environment if root + +DbEnv.lock_stat + DB_STAT_CLEAR # Clear stats after return + +DbEnv.lock_stat_print + DB_STAT_ALL # Everything + DB_STAT_ALLOC # Print allocation information + DB_STAT_CLEAR # Clear stats after return + DB_STAT_LOCK_CONF # Print lock conflict matrix + DB_STAT_LOCK_LOCKERS # Print lockers + DB_STAT_LOCK_OBJECTS # Print lock objects + DB_STAT_LOCK_PARAMS # Print lock parameters + DB_STAT_SUBSYSTEM # Print subsystems + +DbEnv.lock_vec + DB_LOCK_CHECK # UNDOC: check for a lock + DB_LOCK_IGNORE_REC # UNDOC: get lock during recovery + DB_LOCK_NOWAIT # Don't wait for an unavailable lock + DB_LOCK_RECORD # UNDOC: record lock + DB_LOCK_SET_TIMEOUT # UNDOC: set lock timeout + DB_LOCK_SWITCH # UNDOC: switch existing lock + DB_LOCK_UPGRADE # UNDOC: upgrade existing lock + +DbEnv.log_archive + DB_ARCH_ABS # Absolute pathnames + DB_ARCH_DATA # Data files + DB_ARCH_LOG # Log files + DB_ARCH_REMOVE # Remove log files + +DbEnv.log_put + DB_FLUSH # Flush data to disk + DB_LOG_CHKPNT # UNDOC: Flush supports a checkpoint + DB_LOG_COMMIT # UNDOC: Flush supports a commit + DB_LOG_NOCOPY # UNDOC: Don't copy data + DB_LOG_NOT_DURABLE # UNDOC: Do not log; keep in memory + DB_LOG_WRNOSYNC # UNDOC: Write, don't sync log_put + +DbEnv.log_set_config + DB_LOG_DIRECT # Don't buffer log files in the OS + DB_LOG_DSYNC # Set O_DSYNC on the log + DB_LOG_AUTO_REMOVE # Automatically remove log files + DB_LOG_IN_MEMORY # Store logs in buffers in memory + DB_LOG_ZERO # Zero log file on creation + +DbEnv.log_stat + DB_STAT_CLEAR # Clear stats after return + +DbEnv.log_stat_print + DB_STAT_ALL # Everything + DB_STAT_ALLOC # Print allocation information + DB_STAT_CLEAR # Clear stats after return + DB_STAT_SUBSYSTEM # Print subsystems + +DbEnv.lsn_reset + DB_ENCRYPT # File contains encrypted databases + +DbEnv.memp_stat + DB_STAT_CLEAR # Clear stats after return + +DbEnv.memp_stat_print + DB_STAT_ALL # Everything + DB_STAT_ALLOC # Print allocation information + DB_STAT_CLEAR # Clear stats after return + DB_STAT_MEMP_HASH # Print mpool hash buckets + DB_STAT_MEMP_NOERROR # UNDOC: continue on error + DB_STAT_SUBSYSTEM # Print subsystems + +DbEnv.mutex_alloc + DB_MUTEX_ALLOCATED # UNDOC: Mutex currently allocated + DB_MUTEX_LOCKED # UNDOC: Mutex currently locked + DB_MUTEX_LOGICAL_LOCK # UNDOC: Mutex backs a database lock + DB_MUTEX_PROCESS_ONLY # Mutex private to a process + DB_MUTEX_SELF_BLOCK # Must be able to block self + DB_MUTEX_SHARED # Shared (read/write) mutex + +DbEnv.mutex_stat + DB_STAT_CLEAR # Clear stats after return + +DbEnv.mutex_stat_print + DB_STAT_ALL # Everything + DB_STAT_ALLOC # Print allocation information + DB_STAT_CLEAR # Clear stats after return + DB_STAT_SUBSYSTEM # Print subsystems + +DbEnv.remove + DB_FORCE + DB_USE_ENVIRON # Use the environment + DB_USE_ENVIRON_ROOT # Use the environment if root + +DbEnv.rep_set_config + DB_REPMGR_CONF_2SITE_STRICT # Don't cheat on election votes + DB_REPMGR_CONF_ELECTIONS # Manage elections to choose master + DB_REP_CONF_AUTOINIT # automatic client init + DB_REP_CONF_AUTOROLLBACK # UNDOC: discard txns to sync w/ master + DB_REP_CONF_BULK # Bulk transfer + DB_REP_CONF_DELAYCLIENT # Delay client synchronization + DB_REP_CONF_INMEM # In-memory replication + DB_REP_CONF_LEASE # Master leases + DB_REP_CONF_NOWAIT # Don't wait, return error + +DbEnv.rep_set_transport + DB_REP_ANYWHERE # Message can be serviced anywhere + DB_REP_NOBUFFER # Do not buffer this message + DB_REP_PERMANENT # Important -- app may want to flush + DB_REP_REREQUEST # This msg already been requested + +DbEnv.rep_start + DB_REP_CLIENT # Client + DB_REP_MASTER # Master + +DbEnv.rep_stat + DB_STAT_CLEAR # Clear stats after return + +DbEnv.rep_stat_print + DB_STAT_ALL # Everything + DB_STAT_ALLOC # Print allocation information + DB_STAT_CLEAR # Clear stats after return + DB_STAT_SUBSYSTEM # Print subsystems + DB_STAT_SUMMARY # UNDOC: print summary + +# Covers both flags to the callback-setting method, and the callback itself +DbEnv.repmgr_msg_dispatch + DB_REPMGR_NEED_RESPONSE # Synchronous request message type + +DbEnv.repmgr_start + DB_REP_CLIENT # Client + DB_REP_ELECTION # Election + DB_REP_MASTER # Master + +DbEnv.repmgr_stat + DB_STAT_CLEAR # Clear stats after return + +DbEnv.repmgr_stat_print + DB_STAT_ALL # Everything + DB_STAT_ALLOC # Print allocation information + DB_STAT_CLEAR # Clear stats after return + DB_STAT_SUBSYSTEM # Print subsystems + +DbEnv.set_encrypt + DB_ENCRYPT_AES # AES, assumes SHA1 checksum + +DbEnv.set_feedback.op + DB_RECOVER # Running recovery. + +DbEnv.set_flags + DB_AUTO_COMMIT # Implied transaction + DB_CDB_ALLDB # Set CDB locking per environment + DB_DATABASE_LOCKING # UNDOC: try database-level locking + DB_DIRECT_DB # Don't buffer databases in the OS + DB_DSYNC_DB # Set O_DSYNC on the databases + DB_HOTBACKUP_IN_PROGRESS # Inhibit bulk loading optimization + DB_MULTIVERSION # Multiversion concurrency control + DB_NOLOCKING # Set locking/mutex behavior + DB_NOMMAP # Don't mmap the underlying file + DB_NOPANIC # Set panic state per environment + DB_NOFLUSH # UNDOC: don't flush cache on close + DB_OVERWRITE # Overwrite unlinked region files + DB_PANIC_ENVIRONMENT # Set panic state per environment + DB_REGION_INIT # Page-fault regions on open + DB_TIME_NOTGRANTED # Return NOTGRANTED on timeout + DB_TXN_NOSYNC # Do not sync log on commit + DB_TXN_NOWAIT # Do not wait for locks + DB_TXN_SNAPSHOT # Snapshot isolation + DB_TXN_WRITE_NOSYNC # Write the log bug don't sync + DB_YIELDCPU # Yield the CPU (a lot) + +DbEnv.set_isalive + DB_MUTEX_ALLOCATED # UNDOC: Mutex currently allocated + DB_MUTEX_LOCKED # UNDOC: Mutex currently locked + DB_MUTEX_LOGICAL_LOCK # UNDOC: Mutex backs a database lock + DB_MUTEX_PROCESS_ONLY # Mutex private to a process + DB_MUTEX_SELF_BLOCK # Must be able to block self + +DbEnv.set_timeout + DB_SET_LOCK_TIMEOUT # Set lock timeout + DB_SET_TXN_NOW # UNDOC: Timeout lock now + DB_SET_TXN_TIMEOUT # Set transaction timeout + DB_SET_REG_TIMEOUT # Set dbregister timeout + +DbEnv.set_verbose + DB_VERB_BACKUP # Backup information + DB_VERB_DEADLOCK # Deadlock detection information + DB_VERB_FILEOPS # Major file operations + DB_VERB_FILEOPS_ALL # All file operations + DB_VERB_RECOVERY # Recovery information + DB_VERB_REGISTER # Dump waits-for table + DB_VERB_REPLICATION # All replication and repmgr output + DB_VERB_REPMGR_CONNFAIL # Repmgr connection failure output + DB_VERB_REPMGR_MISC # Miscellaneous repmgr output + DB_VERB_REP_ELECT # Replication election output + DB_VERB_REP_LEASE # Replication master lease output + DB_VERB_REP_MISC # Miscellaneous replication output + DB_VERB_REP_MSGS # Replication message output + DB_VERB_REP_SYNC # Replication client sync output + DB_VERB_REP_SYSTEM # Replication system messages + DB_VERB_REP_TEST # Replication temporary test output + DB_VERB_WAITSFOR # Dump waits-for table + +DbEnv.stat_print + DB_STAT_ALL # Everything + DB_STAT_ALLOC # Print allocation information + DB_STAT_CLEAR # Clear stats after return + DB_STAT_SUBSYSTEM # Print subsystems + +DbEnv.txn_begin + DB_IGNORE_LEASE # UNDOC: Ignore leases + DB_READ_COMMITTED # Degree 2 isolation + DB_READ_UNCOMMITTED # Degree 1 isolation + DB_TXN_NOSYNC # Do not sync log on commit + DB_TXN_NOWAIT # Do not wait for locks + DB_TXN_FAMILY # Cursors and child txns are + # independent but lock-compatible + DB_TXN_SNAPSHOT # Snapshot isolation + DB_TXN_SYNC # Always sync log on commit + DB_TXN_WAIT # Always wait for locks in this txn + DB_TXN_WRITE_NOSYNC # Write the log but don't sync + DB_TXN_BULK # Enable transactional bulk loading + +DbEnv.txn_checkpoint + DB_CKP_INTERNAL # UNDOC: internally generated checkpoint + DB_FORCE # Force + +DbEnv.txn_recover + __MASK=0xff # Berkeley DB operation codes. + +DbEnv.txn_stat + DB_STAT_CLEAR # Clear stats after return + +DbEnv.txn_stat_print + DB_STAT_ALL # Everything + DB_STAT_ALLOC # Print allocation information + DB_STAT_CLEAR # Clear stats after return + DB_STAT_SUBSYSTEM # Print subsystems + +DbLogc.get + __MASK=0xff # Berkeley DB operation codes. + +DbMpoolFile.close + DB_MPOOL_DISCARD # UNDOC: Discard file + DB_FLUSH # UNDOC: opened to flush a page + DB_MPOOL_NOLOCK # UNDOC: Already have mpf locked + +DbMpoolFile.get + DB_MPOOL_CREATE # Create a page + DB_MPOOL_DIRTY # Get page for an update + DB_MPOOL_EDIT # Modify without copying + DB_MPOOL_FREE # UNDOC: Free page if present + DB_MPOOL_LAST # Return the last page + DB_MPOOL_NEW # Create a new page + DB_MPOOL_TRY # Try to read a page, but don't block + +DbMpoolFile.open + DB_CREATE # Create as necessary + DB_DIRECT # Don't buffer the file in the OS + DB_DURABLE_UNKNOWN # UNDOC: Durability on open + DB_EXTENT # UNDOC: dealing with an extent + DB_FLUSH # UNDOC: opened to flush a page + DB_MULTIVERSION # Multiversion concurrency control + DB_NOMMAP # Don't mmap underlying file + DB_ODDFILESIZE # Truncate file to N * pgsize + DB_RDONLY # Read-only (O_RDONLY) + DB_TXN_NOT_DURABLE # UNDOC: Mark file not durable on open + +DbMpoolFile.set_flags + DB_MPOOL_NOFILE # Never open a backing file + DB_MPOOL_UNLINK # Unlink the file on last close + +DbSequence.get + DB_AUTO_COMMIT # UNDOC: compatibility only + DB_TXN_NOSYNC # Do not sync log on commit + +DbSequence.open + DB_AUTO_COMMIT # UNDOC: compatibility only + DB_CREATE # Create as necessary + DB_EXCL # Exclusive open (O_EXCL) + DB_THREAD # Handle is free-threaded + +DbSequence.remove + DB_TXN_NOSYNC # Do not sync log on commit + +DbSequence.set_flags + DB_SEQ_DEC # Decrement sequence + DB_SEQ_INC # Increment sequence + DB_SEQ_RANGE_SET # UNDOC: Range set + DB_SEQ_WRAP # Wrap sequence at min/max + DB_SEQ_WRAPPED # UNDOC: Just wrapped + +DbSequence.stat + DB_STAT_CLEAR # Clear stats after return + +DbSequence.stat_print + DB_STAT_CLEAR # Clear stats after return + DB_STAT_SUBSYSTEM # Print subsystems + +DbSite.set_config + DB_BOOTSTRAP_HELPER # Join target for new group member + DB_GROUP_CREATOR # Primordial membership DB creator + DB_LEGACY # Upgrading pre-5.2 group + DB_LOCAL_SITE # Identifies this as the local site + DB_REPMGR_PEER # C2C synchronization + +DbTxn.commit + DB_TXN_NOSYNC # Do not sync log on commit + DB_TXN_SYNC # Always sync log on commit + +DbTxn.set_timeout + DB_SET_LOCK_TIMEOUT # Set lock timeout + DB_SET_TXN_TIMEOUT # Set transaction timeout + +db_create + DB_CXX_NO_EXCEPTIONS # C++: return error values + DB_XA_CREATE # Create a DBP for an XA database + +Db.associate + DB_AUTO_COMMIT # UNDOC: compatibility only + DB_CREATE # Create as necessary + DB_IMMUTABLE_KEY # Secondary key is immutable + +Db.associate_foreign + DB_FOREIGN_ABORT # If foreign key exists, delete aborts + DB_FOREIGN_CASCADE # If foreign key exists, delete cascades + DB_FOREIGN_NULLIFY # If foreign key exists, nullify it + +Db.close + DB_NOSYNC # Berkeley DB operation codes. + +Db.compact + DB_FREELIST_ONLY # Just sort and truncate + DB_FREE_SPACE # Free space + +Db.cursor + DB_CURSOR_BULK # Optimize for bulk updates + DB_CURSOR_TRANSIENT # UNDOC: Single-use cursor + DB_READ_COMMITTED # Degree 2 isolation + DB_READ_UNCOMMITTED # Degree 1 isolation + DB_RECOVER # Called from recovery (internal) + DB_WRITECURSOR # Cursor can update (CDB) + DB_WRITELOCK # Cursor should get write locks + DB_TXN_SNAPSHOT # Snapshot isolation + +Db.del + DB_AUTO_COMMIT # UNDOC: compatibility only + DB_MULTIPLE # Delete multiple data values + DB_MULTIPLE_KEY # Delete multiple key/data pairs + +Db.exists + DB_READ_COMMITTED # Degree 2 isolation + DB_READ_UNCOMMITTED # Degree 1 isolation + DB_RMW # Acquire write lock immediately + +Db.get + __MASK=0xff # Berkeley DB operation codes. + DB_AUTO_COMMIT # UNDOC: compatibility only + DB_IGNORE_LEASE # Ignore leases + DB_MULTIPLE # Return multiple data values + DB_READ_COMMITTED # Degree 2 isolation + DB_READ_UNCOMMITTED # Degree 1 isolation + DB_RMW # Acquire write lock immediately + +Db.pget + __MASK=0xff # Berkeley DB operation codes. + DB_IGNORE_LEASE # Ignore leases + DB_MULTIPLE # Return multiple data values + DB_READ_COMMITTED # Degree 2 isolation + DB_READ_UNCOMMITTED # Degree 1 isolation + DB_RMW # Acquire write lock immediately + +Db.join + DB_JOIN_NOSORT # Don't try to optmize join + +Db.open + DB_AUTO_COMMIT # Implied transaction + DB_CREATE # Create file as necessary + DB_EXCL # Exclusive open (O_EXCL) + DB_FCNTL_LOCKING # UNDOC: fcntl(2) locking + DB_MULTIVERSION # Multiversion concurrency control + DB_NOMMAP # Don't mmap underlying file + DB_NO_AUTO_COMMIT # UNDOC: override env's AUTO_COMMIT + DB_RDONLY # Read-only (O_RDONLY) + DB_RDWRMASTER # UNDOC: allow subdb master open R/W + DB_READ_UNCOMMITTED # Degree 1 isolation + DB_THREAD # Handle is free-threaded + DB_TRUNCATE # Discard existing DB (O_TRUNC) + + # The following flags aren't actually part of the Db.open method + # API, but they are accepted by the underlying __db_open function. + DB_DURABLE_UNKNOWN # UNDOC: Durability on open + DB_INTERNAL_PERSISTENT_DB # UNDOC: Open db in metadata dir + DB_INTERNAL_TEMPORARY_DB # UNDOC: Open db in env home dir + DB_NOERROR # UNDOC: Don't raise errors. + DB_ODDFILESIZE # UNDOC: Truncate file to N * pgsize + DB_WRITEOPEN # UNDOC: open with write lock + + # The following flags are DB constructor flags. However, create and/or + # open of BDB XML containers is done in a single call (rather than the + # two-call "construct the object, then open it" paradigm used by DB), + # and they can't collide for that reason. + DB_CXX_NO_EXCEPTIONS # C++: return error values + +Db.put + __MASK=0xff # Berkeley DB operation codes. + DB_AUTO_COMMIT # UNDOC: compatibility only + DB_MULTIPLE # Put multiple (from key and data DBTs) + DB_MULTIPLE_KEY # Put multiple (from key DBT) + +Db.set_encrypt + DB_ENCRYPT_AES # AES, assumes SHA1 checksum + +Db.set_feedback + DB_UPGRADE # Upgrading + DB_VERIFY # Verifying + +Db.set_flags + DB_CHKSUM # Checksums + DB_DUP # Btree, Hash: duplicate keys + DB_DUPSORT # Btree, Hash: sorted duplicated + DB_ENCRYPT # AES, assumes SHA1 checksum + DB_INORDER # Queue: strict ordering on consume + DB_RECNUM # Btree: record numbers + DB_RENUMBER # Recno: renumber on insert/delete + DB_REVSPLITOFF # Btree: turn off reverse splits + DB_SNAPSHOT # Recno: snapshot the input + DB_TXN_NOT_DURABLE # Do not log changes + +Db.stat + DB_FAST_STAT # Don't traverse the database + DB_READ_COMMITTED # Degree 2 isolation + DB_READ_UNCOMMITTED # Degree 1 isolation + +Db.truncate + DB_AUTO_COMMIT # UNDOC: compatibility only + +Db.upgrade + DB_DUPSORT # Upgrade duplicate data items + +Db.verify + DB_AGGRESSIVE # Salvage whatever could be data + DB_NOORDERCHK # Skip sort order/hashing check + DB_ORDERCHKONLY # Only perform the order check + DB_PRINTABLE # Use printable format for salvage + DB_PR_PAGE # UNDOC: Show page contents (-da) + DB_PR_RECOVERYTEST # UNDOC: Recover test (-dr) + DB_SALVAGE # Salvage what looks like data + DB_UNREF # UNDOC: Report unreferenced pages + DB_VERIFY_PARTITION # Verifying a partition + + # Flags understood by the btree structure checks (__bam_vrfy_subtree). + # These share the same space as the global flags to Db.verify. + DB_ST_DUPOK # UNDOC: Duplicates are acceptable + DB_ST_DUPSET # UNDOC: Subtree is in a duplicate tree + DB_ST_DUPSORT # UNDOC: Duplicates are sorted + DB_ST_IS_RECNO # UNDOC: Subtree is a recno + DB_ST_OVFL_LEAF # UNDOC: Overflow reffed from leaf page + DB_ST_RECNUM # UNDOC: Subtree has record numbering on + DB_ST_RELEN # UNDOC: Subtree has fixed-length recs + DB_ST_TOPLEVEL # UNDOC: Subtree == entire tree + + # Flags understood by __bam_salvage and __db_salvage. These need not + # share name space with the __bam_vrfy_subtree flags, but must share + # with Db.verify. + DB_SA_SKIPFIRSTKEY # UNDOC: I have no idea what this does. + DB_SA_UNKNOWNKEY # UNDOC: The salvage key is unknown + +DbCursor.dup + __MASK=0xff # Berkeley DB operation codes. + DB_SHALLOW_DUP # UNDOC: Don't duplicate compression info + +DbCursor.get + __MASK=0xff # Berkeley DB operation codes. + DB_IGNORE_LEASE # Ignore leases + DB_MULTIPLE # Return multiple data values + DB_MULTIPLE_KEY # Return multiple key/data pairs + DB_READ_COMMITTED # Degree 2 isolation + DB_READ_UNCOMMITTED # Degree 1 isolation + DB_RMW # Acquire write lock immediately + +DbCursor.put + __MASK=0xff # Berkeley DB operation codes. diff -r 000000000000 -r a1985f14b030 dist/api_flags.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dist/api_flags.c Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,466 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 1996, 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +#include + +#include +#include +#include +#include +#include +#include + +typedef struct { + char *name; /* API name */ + + u_int used_mask; /* Bits used. */ +} API; +API **api_list, **api_end; + +typedef struct { + char *name; /* Flag name */ + + int api_cnt; /* APIs that use this flag. */ + API **api, **api_end; + + u_int value; /* Bit value */ +} FLAG; +FLAG **flag_list, **flag_end; + +int verbose; +char *progname; + +int add_entry(char *, char *); +void define_print(char *, u_int); +void dump_api(void); +void dump_flags(void); +int flag_cmp_alpha(const void *, const void *); +int flag_cmp_api_cnt(const void *, const void *); +int generate_flags(void); +int parse(void); +void print_api_mask(void); +void print_api_remainder(void); +void print_flag_value(void); +int syserr(void); +int usage(void); + +int +main(int argc, char *argv[]) +{ + enum { API_MASK, API_REMAINDER, FLAG_VALUE } output; + int ch; + + if ((progname = strrchr(argv[0], '/')) == NULL) + progname = argv[0]; + else + ++progname; + + output = FLAG_VALUE; + while ((ch = getopt(argc, argv, "mrv")) != EOF) + switch (ch) { + case 'm': + output = API_MASK; + break; + case 'r': + output = API_REMAINDER; + break; + case 'v': + verbose = 1; + break; + case '?': + default: + return (usage()); + } + argc -= optind; + argv += optind; + + if (parse() || generate_flags()) + return (EXIT_FAILURE); + + switch (output) { + case API_MASK: + print_api_mask(); + break; + case API_REMAINDER: + print_api_remainder(); + break; + case FLAG_VALUE: + print_flag_value(); + break; + } + + if (verbose) { + dump_api(); + dump_flags(); + } + + return (EXIT_SUCCESS); +} + +int +parse() +{ + int lc; + char *p, *api, buf[256]; + + api = NULL; + + /* + * Read the method name/flag pairs. + */ + for (lc = 1; fgets(buf, sizeof(buf), stdin) != NULL; ++lc) { + if ((p = strchr(buf, '\n')) != NULL) + *p = '\0'; + else { + fprintf( + stderr, "%s: %d: line too long\n", progname, lc); + return (1); + } + + /* Ignore any empty line or hash mark. */ + if (buf[0] == '\0' || buf[0] == '#') + continue; + + /* + * A line without leading whitespace is an API name, a line + * with leading whitespace is a flag name. + */ + if (isspace(buf[0])) { + if ((p = strtok(buf, " \t")) == NULL || *p == '#') + continue; + + /* A flag without an API makes no sense. */ + if (api == NULL) + goto format; + + /* Enter the pair into the array. */ + if (add_entry(api, p)) + return (1); + } else { + if ((p = strtok(buf, " \t")) == NULL) + continue; + if (api != NULL) + free(api); + if ((api = strdup(p)) == NULL) + return (syserr()); + } + if ((p = strtok(NULL, " \t")) != NULL && *p != '#') + goto format; + } + + return (0); + +format: fprintf(stderr, "%s: format error: line %d\n", progname, lc); + return (1); +} + +int +add_entry(char *api_name, char *flag_name) +{ + FLAG **fpp, *fp; + API **app, *ap, **p; + u_int cnt; + + /* Search for this api's API structure. */ + for (app = api_list; + app != NULL && *app != NULL && app < api_end; ++app) + if (strcmp(api_name, (*app)->name) == 0) + break; + + /* Allocate new space in the API array if necessary. */ + if (app == NULL || app == api_end) { + cnt = app == NULL ? 100 : (u_int)(api_end - api_list) + 100; + if ((api_list = realloc(api_list, sizeof(API *) * cnt)) == NULL) + return (syserr()); + api_end = api_list + cnt; + app = api_list + (cnt - 100); + memset(app, 0, (u_int)(api_end - app) * sizeof(API *)); + } + + /* Allocate a new API structure and fill in the name if necessary. */ + if (*app == NULL && + ((*app = calloc(sizeof(API), 1)) == NULL || + ((*app)->name = strdup(api_name)) == NULL)) + return (syserr()); + + ap = *app; + + /* + * There's a special keyword, "__MASK=" that sets the initial + * flags value for an API, and so prevents those flag bits from being + * chosen for that API's flags. + */ + if (strncmp(flag_name, "__MASK=", sizeof("__MASK=") - 1) == 0) { + ap->used_mask |= + strtoul(flag_name + sizeof("__MASK=") - 1, NULL, 0); + return (0); + } + + /* Search for this flag's FLAG structure. */ + for (fpp = flag_list; + fpp != NULL && *fpp != NULL && fpp < flag_end; ++fpp) + if (strcmp(flag_name, (*fpp)->name) == 0) + break; + + /* Realloc space in the FLAG array if necessary. */ + if (fpp == NULL || fpp == flag_end) { + cnt = fpp == NULL ? 100 : (u_int)(flag_end - flag_list) + 100; + if ((flag_list = + realloc(flag_list, sizeof(FLAG *) * cnt)) == NULL) + return (syserr()); + flag_end = flag_list + cnt; + fpp = flag_list + (cnt - 100); + memset(fpp, 0, (u_int)(flag_end - fpp) * sizeof(FLAG *)); + } + + /* Allocate a new FLAG structure and fill in the name if necessary. */ + if (*fpp == NULL && + ((*fpp = calloc(sizeof(FLAG), 1)) == NULL || + ((*fpp)->name = strdup(flag_name)) == NULL)) + return (syserr()); + + fp = *fpp; + ++fp->api_cnt; + + /* Check to see if this API is already listed for this flag. */ + for (p = fp->api; p != NULL && *p != NULL && p < fp->api_end; ++p) + if (strcmp(api_name, (*p)->name) == 0) { + fprintf(stderr, + "duplicate entry: %s / %s\n", api_name, flag_name); + return (1); + } + + /* Realloc space in the FLAG's API array if necessary. */ + if (p == NULL || p == fp->api_end) { + cnt = p == NULL ? 20 : (u_int)(fp->api_end - fp->api) + 20; + if ((fp->api = realloc(fp->api, sizeof(API *) * cnt)) == NULL) + return (syserr()); + fp->api_end = fp->api + cnt; + p = fp->api + (cnt - 20); + memset(p, 0, (u_int)(fp->api_end - fp->api) * sizeof(API *)); + } + *p = ap; + + return (0); +} + +void +dump_api() +{ + API **app; + + printf("=============================\nAPI:\n"); + for (app = api_list; *app != NULL; ++app) + printf("%s (%#x)\n", (*app)->name, (*app)->used_mask); +} + +void +dump_flags() +{ + FLAG **fpp; + API **api; + char *sep; + + printf("=============================\nFLAGS:\n"); + for (fpp = flag_list; *fpp != NULL; ++fpp) { + printf("%s (%#x, %d): ", + (*fpp)->name, (*fpp)->value, (*fpp)->api_cnt); + sep = ""; + for (api = (*fpp)->api; *api != NULL; ++api) { + printf("%s%s", sep, (*api)->name); + sep = ", "; + } + printf("\n"); + } +} + +int +flag_cmp_api_cnt(const void *a, const void *b) +{ + FLAG *af, *bf; + + af = *(FLAG **)a; + bf = *(FLAG **)b; + + if (af == NULL) { + if (bf == NULL) + return (0); + return (1); + } + if (bf == NULL) { + if (af == NULL) + return (0); + return (-1); + } + if (af->api_cnt > bf->api_cnt) + return (-1); + if (af->api_cnt < bf->api_cnt) + return (1); + return (strcmp(af->name, bf->name)); +} + +int +generate_flags() +{ + FLAG **fpp; + API **api; + u_int mask; + + /* Sort the FLAGS array by reference count, in reverse order. */ + qsort(flag_list, + (u_int)(flag_end - flag_list), sizeof(FLAG *), flag_cmp_api_cnt); + + /* + * Here's the plan: walk the list of flags, allocating bits. For + * each flag, we walk the list of APIs that use it and find a bit + * none of them are using. That bit becomes the flag's value. + */ + for (fpp = flag_list; *fpp != NULL; ++fpp) { + mask = 0xffffffff; /* Set to all 1's */ + for (api = (*fpp)->api; *api != NULL; ++api) + mask &= ~(*api)->used_mask; /* Clear API's bits */ + if (mask == 0) { + fprintf(stderr, "%s: ran out of bits at flag %s\n", + progname, (*fpp)->name); + return (1); + } + (*fpp)->value = mask = 1 << (ffs(mask) - 1); + for (api = (*fpp)->api; *api != NULL; ++api) + (*api)->used_mask |= mask; /* Set bit for API */ + } + + return (0); +} + +int +flag_cmp_alpha(const void *a, const void *b) +{ + FLAG *af, *bf; + + af = *(FLAG **)a; + bf = *(FLAG **)b; + + if (af == NULL) { + if (bf == NULL) + return (0); + return (1); + } + if (bf == NULL) { + if (af == NULL) + return (0); + return (-1); + } + return (strcmp(af->name, bf->name)); +} + +void +print_api_mask() +{ + API **app; + char *p, buf[256]; + + /* Output a mask for the API. */ + for (app = api_list; *app != NULL; ++app) { + (void)snprintf( + buf, sizeof(buf), "_%s_API_MASK", (*app)->name); + for (p = buf; *p != '\0'; ++p) + if (islower(*p)) + *p = toupper(*p); + else if (!isalpha(*p)) + *p = '_'; + define_print(buf, (*app)->used_mask); + } +} + +void +print_api_remainder() +{ + API **app; + int unused, i; + + /* Output the bits remaining for the API. */ + for (app = api_list; *app != NULL; ++app) { + for (i = unused = 0; i < 32; ++i) + if (!((*app)->used_mask & (1 << i))) + ++unused; + printf("%s: %d bits unused\n", (*app)->name, unused); + } +} + +void +print_flag_value() +{ + FLAG **fpp; + + /* Sort the FLAGS array in alphabetical order. */ + qsort(flag_list, + (u_int)(flag_end - flag_list), sizeof(FLAG *), flag_cmp_alpha); + + /* Output each flag's value. */ + for (fpp = flag_list; *fpp != NULL; ++fpp) + define_print((*fpp)->name, (*fpp)->value); +} + +void +define_print(char *name, u_int value) +{ + char *sep; + + switch (strlen(name) / 8) { + case 0: + sep = "\t\t\t\t\t"; + break; + case 1: + sep = "\t\t\t\t"; + break; + case 2: + sep = "\t\t\t"; + break; + case 3: + sep = "\t\t"; + break; + default: + sep = "\t"; + break; + } + printf("#define\t%s%s%#010x\n", name, sep, value); +} + +int +syserr(void) +{ + fprintf(stderr, "%s: %s\n", progname, strerror(errno)); + return (1); +} + +int +usage() +{ + (void)fprintf(stderr, "usage: %s [-mrv]\n", progname); + return (EXIT_FAILURE); +} diff -r 000000000000 -r a1985f14b030 dist/buildpkg --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dist/buildpkg Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,267 @@ +#!/bin/sh +# Copyright (c) 2009, 2012 Oracle and/or its affiliates. All rights reserved. +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. Oracle designates this +# particular file as subject to the "Classpath" exception as provided +# by Oracle in the LICENSE file that accompanied this code. +# +# This code 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 General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. +# $Id: $ +# +die() +{ + echo >&2 "$@" + exit 1 +} + +# Build the distribution package. +. ./RELEASE || die "Can't read the RELEASE file" + +CSHARP_DOC_SRC="" +# 0 is none, 1 is local dir, 2 is remote dir +CSHARP_DOC_LOCATION=0 +test_run=0 + +while [ $# -gt 0 ] +do + case "$1" in + -n) + nodocs=true;; + -csharp_doc_src) + shift + if [ ! $# -gt 0 ]; then + die "csharp_doc_dir param requires argument." + fi + CSHARP_DOC_SRC=$1 + CSHARP_DOC_LOCATION=1 + if [ ! -f $CSHARP_DOC_SRC ]; then + die "CSharp doc archive must exist." + fi;; + -csharp_doc_url) + shift + if [ ! $# -gt 0 ]; then + die "csharp_doc_dir param requires argument." + fi + CSHARP_DOC_SRC=$1 + CSHARP_DOC_LOCATION=2;; + -test) + echo "Doing a test run - this may contain changes that aren't\ +reflected in a tag, so the package won't be reproducible." + test_run=1;; + esac + shift +done + +# A version string can be specified on the command line (e.g., "20080219"). +# Otherwise, use the standard X.X.X format. +VERSION=${1:-${DB_VERSION_MAJOR}.${DB_VERSION_MINOR}.${DB_VERSION_PATCH}} + +# Use "ustar" as the archiver +TAR=ustar + +# Set root directory where we do the work, can be anywhere. +START_DIR=`pwd` +D=`pwd`/../release +R="$D/db-${VERSION}" +RNC="$D/db-$VERSION.NC" +DOCS=`pwd`/../../docs_books +DB_ADDONS=`pwd`/../../db_addons + +if [ ! -d $DB_ADDONS ]; then + echo "buildpkg requires a db_addons repository at the same level as the db repository." + exit 1 +fi + +# Create directory, remove any previous release tree. +rm -rf $R $RNC +mkdir -p $R + +echo "Removed old release build from $R" + +# Copy the files in the current tip to $R +hg archive $R + +# If doing a test run, apply any local changes to the new tree. +if [ $test_run != 0 ]; then + hg diff | patch -p1 -d $R +fi + +echo "Created hg archive in $R" + +if [ "$nodocs" = true ] ; then + rm -rf $R/docs +else + [ -d $DOCS ] || die "buildpkg requires a docs_books repository at the same level as the db repository." + + # Check that the doc repo is up to date, and create a tag if necessary. + cd $DOCS + hg pull -u + if [ $? != 0 ]; then + rm -rf $R + die "Failed updating the docs_books repository." + fi + has_tag=`hg tags | grep "db-${VERSION}"` + if [ "$has_tag" = "" ]; then + hg tag "db-${VERSION}" + TAG_CREATED="true" + else + hg up -r "db-${VERSION}" + fi + + # Build a copy of the documentation in the release tree. + cd $R/dist + sh s_docs db-${VERSION} $DOCS + + if [ $? != 0 ]; then + rm -rf $R + die "Failed generating documentation." + fi + + # Copy in the C sharp doc. + if [ $CSHARP_DOC_LOCATION -eq 2 ]; then + scp $CSHARP_DOC_SRC . + CSHARP_DOC_SRC="csharp_docs.tgz" + if [ ! -f $CSHARP_DOC_SRC ]; then + echo "WARNING: Invalid csharp doc file - csharp_docs.tgz expected." + fi + fi + if [ $CSHARP_DOC_LOCATION -eq 0 -o ! -f $CSHARP_DOC_SRC ]; then + echo "WARNING: No csharp docs, skipping." + CSHARP_DOC_LOCATION=0 + fi + if [ $CSHARP_DOC_LOCATION != 0 ]; then + rm -rf $R/docs/csharp + mkdir -p $R/docs/csharp + $TAR zxf $CSHARP_DOC_SRC -C $R/docs/csharp + fi + + # Build the Java documentation. + cd $R/dist && sh s_javadoc +fi + +# Pull a copy of the JDBC and ODBC libraries into the package. +# Build the ADO.NET package, including moving the ADO.NET doc built above +# into that package. +# Tell the script where to look for packages. +cd $R/dist && sh s_sql_drivers -addons ../../../.. +# Warn if s_sql_drivers didn't move its docs. +if [ -e "$R/docs/bdb-sql-ado" ]; then + echo "WARNING: ADO.NET doc is still in the non ADO.NET package." +fi + +cd $START_DIR + +# Pull a copy of the bfile directory into the package. +cd $DB_ADDONS +hg pull -u +if [ $? != 0 ]; then + echo "Failed updating the db_addons repository. Exiting." + rm -rf $R + exit 1 +fi + +cd $START_DIR +SQL_EXT_DIR=$R/lang/sql/sqlite/ext +if [ ! -d $SQL_EXT_DIR ]; then + mkdir -p $SQL_EXT_DIR +fi +if [ -d $SQL_EXT_DIR/bfile ]; then + rm -rf $SQL_EXT_DIR/bfile +fi +cp -rp $DB_ADDONS/bfile $SQL_EXT_DIR + +# Remove source directories we don't distribute. +cd $R && rm -rf test/tcl/TODO test/upgrade test/scr036 test/erlang +cd $R && rm -rf test/perf test/purify test/repmgr +cd $R && rm -rf test/server test/stl test/vxworks +cd $R && find . -name '.hg*' | xargs rm -f +cd $R && find . -name 'tags' | xargs rm -f + +# Create symbolic links and cscope output, fix permissions. +#cd $R/dist && sh s_perm +#cd $R/dist && sh s_cscope + +# Build a regular version and smoke test. +### cd $R && rm -rf build_run && mkdir build_run +### cd $R/build_run && ../dist/configure && make >& mklog +### cd $R/build_run && make ex_access && echo "test" | ./ex_access +# Check the install +### cd $R/build_run && make prefix=`pwd`/BDB install + +# Build a small-footprint version and smoke test. +### cd $R && rm -rf build_run && mkdir build_run +### cd $R/build_run && ../dist/configure --enable-smallbuild && make >& mklog +### cd $R/build_run && make ex_access && echo "test" | ./ex_access + +# Remove the build directory +### cd $R && rm -rf build_run + +(cd $R/dist && ./s_perm) + +# Check for file names differing only in case. +cd $R && find . | sort -f | uniq -ic | sed '/1 /d' + +# Create the crypto tar archive release. +T="$D/db-$VERSION.tar.gz" +rm -f $T +cd $D || die "Can't find $D" +# Move package files in db-$VERSION/release to current directory so that +# regular packages won't includes generated package twice. +if [ -d "db-$VERSION/release" ]; then + mv db-$VERSION/release/* . + rm -rf db-$VERSION/release +fi +$TAR czf $T -find db-$VERSION -chown 100 -chgrp 100 +chmod 444 $T + +# Create the non-crypto tree. +cd $D && mv -i db-$VERSION $RNC && $TAR xzf $T +cd $RNC/dist && sh s_crypto + +(cd $RNC/dist && ./s_perm) + +# Create the non-crypto tar archive release. +T="$D/db-$VERSION.NC.tar.gz" +rm -f $T +cd $RNC/.. && $TAR czf $T -find db-$VERSION.NC -chown 100 -chgrp 100 +chmod 444 $T + +t=__tmp +cd $R && awk '{print $0 "\r"}' < LICENSE > $t && rm -f LICENSE && cp $t LICENSE +cd $R && awk '{print $0 "\r"}' < README > $t && rm -f README && cp $t README && rm $t +cd $RNC && awk '{print $0 "\r"}' < LICENSE > $t && rm -f LICENSE && cp $t LICENSE +cd $RNC && awk '{print $0 "\r"}' < README > $t && rm -f README && cp $t README && rm $t + +# Create the crypto zip archive release. +T="$D/db-$VERSION.zip" +rm -f $T +cd $R/.. && rm -f $T && zip -q -r $T db-$VERSION +chmod 444 $T + +# Create the non-crypto zip archive release. +T="$D/db-$VERSION.NC.zip" +rm -f $T +cd $RNC/.. && rm -f $T && zip -q -r $T db-$VERSION.NC +chmod 444 $T + +rm -rf $R $RNC + +if [ "$TAG_CREATED" = "true" ]; then + echo "Created a tag in docs_books repository. Please push." +fi diff -r 000000000000 -r a1985f14b030 dist/bumprel --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dist/bumprel Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,82 @@ +#!/bin/sh +# Copyright (c) 2009, 2012 Oracle and/or its affiliates. All rights reserved. +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. Oracle designates this +# particular file as subject to the "Classpath" exception as provided +# by Oracle in the LICENSE file that accompanied this code. +# +# This code 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 General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. +# +# $Id: $ +# +# Bump the Berkeley DB version + +P=`pwd` +R=`dirname $P` +progname="$0" +VERSION="$1" +assembly="../lang/csharp/src/Properties/AssemblyInfo.cs" +t=/tmp/__assembly + +# Sanity check +if [ ! -f $R/dist/RELEASE ] ; then + echo "$progname must be run in the dist directory of a Berkeley DB tree" + exit 1 +fi + +OIFS="$IFS" +IFS=. +set -- $VERSION + +if [ $# != 5 ] ; then + echo "Usage: $progname X.X.X.X.X -- sets the Berkeley DB version to X.X.X.X.X" + exit 1 +fi +FAMILY="$1" RELEASE="$2" MAJOR="$3" MINOR="$4" PATCH="$5" +DATE=`date "+%B %e, %Y"` + +IFS="$OFS" + +# Update the change log patch number -- there's 1 location to update in +# the change log "table of contents", and 2 in the Change Log itself. +#cd $R/docs_src/ref/changelog && vi toc.so ${MAJOR}.${MINOR}.html + +# Update the release number. +cd $R/dist &&\ + (echo "/^DB_VERSION_FAMILY/s/=.*/=$FAMILY/" &&\ + echo "/^DB_VERSION_RELEASE/s/=.*/=$RELEASE/" &&\ + echo "/^DB_VERSION_MAJOR/s/=.*/=$MAJOR/" &&\ + echo "/^DB_VERSION_MINOR/s/=.*/=$MINOR/" &&\ + echo "/^DB_VERSION_PATCH/s/=.*/=$PATCH/" &&\ + echo "/^DB_RELEASE_DATE/s/=.*/=\"$DATE\"/" &&\ + echo w &&\ + echo q) | ed RELEASE > /dev/null +VERSION=`sh -c '. ./RELEASE; echo $DB_VERSION'` +echo "Berkeley DB release $VERSION." + +# Build auto-generated files. +cd $R/dist && sh s_all + +# Update the CSharp assembly information +sed -e "s:AssemblyVersion(\"[0-9]*\.[0-9]*\.[0-9]*\"):AssemblyVersion(\"$MAJOR\.$MINOR\.$PATCH\"):" < $assembly > $t +cmp $t $assembly > /dev/null 2>&1 || + (rm -f $assembly && cp $t $assembly && rm -f $t && chmod 444 $assembly) + +# Commit all of the changes. +echo "Now run 'hg commit && hg tag db-$MAJOR.$MINOR.$PATCH && hg push'" diff -r 000000000000 -r a1985f14b030 dist/clib_port.in --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dist/clib_port.in Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,304 @@ +/* DO NOT EDIT: automatically built from dist/clib_port.in. + * + * Copyright (c) 2006, 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +/* + * Minimum/maximum values for various types. + */ +#ifndef UINT16_MAX /* Maximum 16-bit unsigned. */ +#define UINT16_MAX 65535 +#endif +#ifndef UINT32_MAX /* Maximum 32-bit unsigned. */ +#define UINT32_MAX 4294967295U +#endif + +#ifndef INT_MAX +#if SIZEOF_INT == 4 +#define INT_MAX 2147483647 +#endif +#if SIZEOF_INT == 8 +#define INT_MAX 9223372036854775807 +#endif +#endif + +#ifndef INT_MIN /* minimum (signed) int value */ +#define INT_MIN (-INT_MAX-1) +#endif + +#ifndef UINT_MAX /* maximum (signed) int value */ +#if SIZEOF_INT == 4 +#define UINT_MAX 4294967295U +#endif +#if SIZEOF_INT == 8 +#define UINT_MAX 18446744073709551615U +#endif +#endif + +#ifndef LONG_MAX /* maximum (signed) long value */ +#if SIZEOF_LONG == 4 +#define LONG_MAX 2147483647 +#endif +#if SIZEOF_LONG == 8 +#define LONG_MAX 9223372036854775807L +#endif +#endif + +#ifndef LONG_MIN /* minimum (signed) long value */ +#define LONG_MIN (-LONG_MAX-1) +#endif + +#ifndef ULONG_MAX /* maximum (unsigned) long value */ +#if SIZEOF_LONG == 4 +#define ULONG_MAX 4294967295U +#endif +#if SIZEOF_LONG == 8 +#define ULONG_MAX 18446744073709551615UL +#endif +#endif + +#if defined(HAVE_64BIT_TYPES) +/* + * Override the system's 64-bit min/max constants. AIX's 32-bit compiler can + * handle 64-bit values, but the system's constants don't include the LL/ULL + * suffix, and so can't be compiled using the 32-bit compiler. + */ +#undef INT64_MAX +#undef INT64_MIN +#undef UINT64_MAX + +#ifdef DB_WIN32 +#define INT64_MAX _I64_MAX +#define INT64_MIN _I64_MIN +#define UINT64_MAX _UI64_MAX +#else +#define INT64_MAX 9223372036854775807LL +#define INT64_MIN (-INT64_MAX-1) +#define UINT64_MAX 18446744073709551615ULL +#endif /* DB_WIN32 */ + +@INT64_FMT@ +@UINT64_FMT@ +#endif /* HAVE_64BIT_TYPES */ + +/* + * Exit success/failure macros. + */ +#ifndef HAVE_EXIT_SUCCESS +#define EXIT_FAILURE 1 +#define EXIT_SUCCESS 0 +#endif + +/* + * File modes. + */ +#ifdef DB_WIN32 +#ifndef S_IREAD /* WinCE doesn't have S_IREAD. */ +#define S_IREAD 0 +#endif +#ifndef S_IWRITE /* WinCE doesn't have S_IWRITE. */ +#define S_IWRITE 0 +#endif +#ifndef S_IRUSR +#define S_IRUSR S_IREAD /* R for owner */ +#endif +#ifndef S_IWUSR +#define S_IWUSR S_IWRITE /* W for owner */ +#endif +#ifndef S_IXUSR +#define S_IXUSR 0 /* X for owner */ +#endif +#ifndef S_IRGRP +#define S_IRGRP 0 /* R for group */ +#endif +#ifndef S_IWGRP +#define S_IWGRP 0 /* W for group */ +#endif +#ifndef S_IXGRP +#define S_IXGRP 0 /* X for group */ +#endif +#ifndef S_IROTH +#define S_IROTH 0 /* R for other */ +#endif +#ifndef S_IWOTH +#define S_IWOTH 0 /* W for other */ +#endif +#ifndef S_IXOTH +#define S_IXOTH 0 /* X for other */ +#endif +#else /* !DB_WIN32 */ +#ifndef S_IRUSR +#define S_IRUSR 0000400 /* R for owner */ +#endif +#ifndef S_IWUSR +#define S_IWUSR 0000200 /* W for owner */ +#endif +#ifndef S_IXUSR +#define S_IXUSR 0000100 /* X for owner */ +#endif +#ifndef S_IRGRP +#define S_IRGRP 0000040 /* R for group */ +#endif +#ifndef S_IWGRP +#define S_IWGRP 0000020 /* W for group */ +#endif +#ifndef S_IXGRP +#define S_IXGRP 0000010 /* X for group */ +#endif +#ifndef S_IROTH +#define S_IROTH 0000004 /* R for other */ +#endif +#ifndef S_IWOTH +#define S_IWOTH 0000002 /* W for other */ +#endif +#ifndef S_IXOTH +#define S_IXOTH 0000001 /* X for other */ +#endif +#endif /* !DB_WIN32 */ + +/* + * Don't step on the namespace. Other libraries may have their own + * implementations of these functions, we don't want to use their + * implementations or force them to use ours based on the load order. + */ +#ifndef HAVE_ATOI +#define atoi __db_Catoi +#endif +#ifndef HAVE_ATOL +#define atol __db_Catol +#endif +#ifndef HAVE_BSEARCH +#define bsearch __db_Cbsearch +#endif +#ifndef HAVE_FCLOSE +#define fclose __db_Cfclose +#endif +#ifndef HAVE_FGETC +#define fgetc __db_Cfgetc +#endif +#ifndef HAVE_FGETS +#define fgets __db_Cfgets +#endif +#ifndef HAVE_FOPEN +#define fopen __db_Cfopen +#endif +#ifndef HAVE_FWRITE +#define fwrite __db_Cfwrite +#endif +#ifndef HAVE_GETADDRINFO +#define freeaddrinfo(a) __db_Cfreeaddrinfo(a) +#define getaddrinfo(a, b, c, d) __db_Cgetaddrinfo(a, b, c, d) +#endif +#ifndef HAVE_GETCWD +#define getcwd __db_Cgetcwd +#endif +#ifndef HAVE_GETOPT +#define getopt __db_Cgetopt +#define optarg __db_Coptarg +#define opterr __db_Copterr +#define optind __db_Coptind +#define optopt __db_Coptopt +#define optreset __db_Coptreset +#endif +#ifndef HAVE_ISALPHA +#define isalpha __db_Cisalpha +#endif +#ifndef HAVE_ISDIGIT +#define isdigit __db_Cisdigit +#endif +#ifndef HAVE_ISPRINT +#define isprint __db_Cisprint +#endif +#ifndef HAVE_ISSPACE +#define isspace __db_Cisspace +#endif +#ifndef HAVE_LOCALTIME +#define localtime __db_Clocaltime +#endif +#ifndef HAVE_MEMCMP +#define memcmp __db_Cmemcmp +#endif +#ifndef HAVE_MEMCPY +#define memcpy __db_Cmemcpy +#endif +#ifndef HAVE_MEMMOVE +#define memmove __db_Cmemmove +#endif +#ifndef HAVE_PRINTF +#define printf __db_Cprintf +#define fprintf __db_Cfprintf +#endif +#ifndef HAVE_QSORT +#define qsort __db_Cqsort +#endif +#ifndef HAVE_RAISE +#define raise __db_Craise +#endif +#ifndef HAVE_RAND +#define rand __db_Crand +#define srand __db_Csrand +#endif +#ifndef HAVE_SNPRINTF +#define snprintf __db_Csnprintf +#endif +#ifndef HAVE_STRCASECMP +#define strcasecmp __db_Cstrcasecmp +#define strncasecmp __db_Cstrncasecmp +#endif +#ifndef HAVE_STRCAT +#define strcat __db_Cstrcat +#endif +#ifndef HAVE_STRCHR +#define strchr __db_Cstrchr +#endif +#ifndef HAVE_STRDUP +#define strdup __db_Cstrdup +#endif +#ifndef HAVE_STRERROR +#define strerror __db_Cstrerror +#endif +#ifndef HAVE_STRNCAT +#define strncat __db_Cstrncat +#endif +#ifndef HAVE_STRNCMP +#define strncmp __db_Cstrncmp +#endif +#ifndef HAVE_STRRCHR +#define strrchr __db_Cstrrchr +#endif +#ifndef HAVE_STRSEP +#define strsep __db_Cstrsep +#endif +#ifndef HAVE_STRTOL +#define strtol __db_Cstrtol +#endif +#ifndef HAVE_STRTOUL +#define strtoul __db_Cstrtoul +#endif +#ifndef HAVE_TIME +#define time __db_Ctime +#endif +#ifndef HAVE_VSNPRINTF +#define vsnprintf __db_Cvsnprintf +#endif diff -r 000000000000 -r a1985f14b030 dist/config.guess --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dist/config.guess Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,1522 @@ +#! /bin/sh +# Attempt to guess a canonical system name. +# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, +# 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, +# 2011 Free Software Foundation, Inc. + +timestamp='2011-11-11' + +# This file is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA +# 02110-1301, USA. +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + + +# Originally written by Per Bothner. Please send patches (context +# diff format) to and include a ChangeLog +# entry. +# +# This script attempts to guess a canonical system name similar to +# config.sub. If it succeeds, it prints the system name on stdout, and +# exits with 0. Otherwise, it exits with 1. +# +# You can get the latest version of this script from: +# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD + +me=`echo "$0" | sed -e 's,.*/,,'` + +usage="\ +Usage: $0 [OPTION] + +Output the configuration name of the system \`$me' is run on. + +Operation modes: + -h, --help print this help, then exit + -t, --time-stamp print date of last modification, then exit + -v, --version print version number, then exit + +Report bugs and patches to ." + +version="\ +GNU config.guess ($timestamp) + +Originally written by Per Bothner. +Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, +2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free +Software Foundation, Inc. + +This is free software; see the source for copying conditions. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." + +help=" +Try \`$me --help' for more information." + +# Parse command line +while test $# -gt 0 ; do + case $1 in + --time-stamp | --time* | -t ) + echo "$timestamp" ; exit ;; + --version | -v ) + echo "$version" ; exit ;; + --help | --h* | -h ) + echo "$usage"; exit ;; + -- ) # Stop option processing + shift; break ;; + - ) # Use stdin as input. + break ;; + -* ) + echo "$me: invalid option $1$help" >&2 + exit 1 ;; + * ) + break ;; + esac +done + +if test $# != 0; then + echo "$me: too many arguments$help" >&2 + exit 1 +fi + +trap 'exit 1' 1 2 15 + +# CC_FOR_BUILD -- compiler used by this script. Note that the use of a +# compiler to aid in system detection is discouraged as it requires +# temporary files to be created and, as you can see below, it is a +# headache to deal with in a portable fashion. + +# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still +# use `HOST_CC' if defined, but it is deprecated. + +# Portable tmp directory creation inspired by the Autoconf team. + +set_cc_for_build=' +trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ; +trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ; +: ${TMPDIR=/tmp} ; + { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } || + { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } || + { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } || + { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ; +dummy=$tmp/dummy ; +tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ; +case $CC_FOR_BUILD,$HOST_CC,$CC in + ,,) echo "int x;" > $dummy.c ; + for c in cc gcc c89 c99 ; do + if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then + CC_FOR_BUILD="$c"; break ; + fi ; + done ; + if test x"$CC_FOR_BUILD" = x ; then + CC_FOR_BUILD=no_compiler_found ; + fi + ;; + ,,*) CC_FOR_BUILD=$CC ;; + ,*,*) CC_FOR_BUILD=$HOST_CC ;; +esac ; set_cc_for_build= ;' + +# This is needed to find uname on a Pyramid OSx when run in the BSD universe. +# (ghazi@noc.rutgers.edu 1994-08-24) +if (test -f /.attbin/uname) >/dev/null 2>&1 ; then + PATH=$PATH:/.attbin ; export PATH +fi + +UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown +UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown +UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown +UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown + +# Note: order is significant - the case branches are not exclusive. + +case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in + *:NetBSD:*:*) + # NetBSD (nbsd) targets should (where applicable) match one or + # more of the tupples: *-*-netbsdelf*, *-*-netbsdaout*, + # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently + # switched to ELF, *-*-netbsd* would select the old + # object file format. This provides both forward + # compatibility and a consistent mechanism for selecting the + # object file format. + # + # Note: NetBSD doesn't particularly care about the vendor + # portion of the name. We always set it to "unknown". + sysctl="sysctl -n hw.machine_arch" + UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \ + /usr/sbin/$sysctl 2>/dev/null || echo unknown)` + case "${UNAME_MACHINE_ARCH}" in + armeb) machine=armeb-unknown ;; + arm*) machine=arm-unknown ;; + sh3el) machine=shl-unknown ;; + sh3eb) machine=sh-unknown ;; + sh5el) machine=sh5le-unknown ;; + *) machine=${UNAME_MACHINE_ARCH}-unknown ;; + esac + # The Operating System including object format, if it has switched + # to ELF recently, or will in the future. + case "${UNAME_MACHINE_ARCH}" in + arm*|i386|m68k|ns32k|sh3*|sparc|vax) + eval $set_cc_for_build + if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep -q __ELF__ + then + # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout). + # Return netbsd for either. FIX? + os=netbsd + else + os=netbsdelf + fi + ;; + *) + os=netbsd + ;; + esac + # The OS release + # Debian GNU/NetBSD machines have a different userland, and + # thus, need a distinct triplet. However, they do not need + # kernel version information, so it can be replaced with a + # suitable tag, in the style of linux-gnu. + case "${UNAME_VERSION}" in + Debian*) + release='-gnu' + ;; + *) + release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'` + ;; + esac + # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM: + # contains redundant information, the shorter form: + # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used. + echo "${machine}-${os}${release}" + exit ;; + *:OpenBSD:*:*) + UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'` + echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE} + exit ;; + *:ekkoBSD:*:*) + echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE} + exit ;; + *:SolidBSD:*:*) + echo ${UNAME_MACHINE}-unknown-solidbsd${UNAME_RELEASE} + exit ;; + macppc:MirBSD:*:*) + echo powerpc-unknown-mirbsd${UNAME_RELEASE} + exit ;; + *:MirBSD:*:*) + echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE} + exit ;; + alpha:OSF1:*:*) + case $UNAME_RELEASE in + *4.0) + UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'` + ;; + *5.*) + UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'` + ;; + esac + # According to Compaq, /usr/sbin/psrinfo has been available on + # OSF/1 and Tru64 systems produced since 1995. I hope that + # covers most systems running today. This code pipes the CPU + # types through head -n 1, so we only detect the type of CPU 0. + ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^ The alpha \(.*\) processor.*$/\1/p' | head -n 1` + case "$ALPHA_CPU_TYPE" in + "EV4 (21064)") + UNAME_MACHINE="alpha" ;; + "EV4.5 (21064)") + UNAME_MACHINE="alpha" ;; + "LCA4 (21066/21068)") + UNAME_MACHINE="alpha" ;; + "EV5 (21164)") + UNAME_MACHINE="alphaev5" ;; + "EV5.6 (21164A)") + UNAME_MACHINE="alphaev56" ;; + "EV5.6 (21164PC)") + UNAME_MACHINE="alphapca56" ;; + "EV5.7 (21164PC)") + UNAME_MACHINE="alphapca57" ;; + "EV6 (21264)") + UNAME_MACHINE="alphaev6" ;; + "EV6.7 (21264A)") + UNAME_MACHINE="alphaev67" ;; + "EV6.8CB (21264C)") + UNAME_MACHINE="alphaev68" ;; + "EV6.8AL (21264B)") + UNAME_MACHINE="alphaev68" ;; + "EV6.8CX (21264D)") + UNAME_MACHINE="alphaev68" ;; + "EV6.9A (21264/EV69A)") + UNAME_MACHINE="alphaev69" ;; + "EV7 (21364)") + UNAME_MACHINE="alphaev7" ;; + "EV7.9 (21364A)") + UNAME_MACHINE="alphaev79" ;; + esac + # A Pn.n version is a patched version. + # A Vn.n version is a released version. + # A Tn.n version is a released field test version. + # A Xn.n version is an unreleased experimental baselevel. + # 1.2 uses "1.2" for uname -r. + echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` + # Reset EXIT trap before exiting to avoid spurious non-zero exit code. + exitcode=$? + trap '' 0 + exit $exitcode ;; + Alpha\ *:Windows_NT*:*) + # How do we know it's Interix rather than the generic POSIX subsystem? + # Should we change UNAME_MACHINE based on the output of uname instead + # of the specific Alpha model? + echo alpha-pc-interix + exit ;; + 21064:Windows_NT:50:3) + echo alpha-dec-winnt3.5 + exit ;; + Amiga*:UNIX_System_V:4.0:*) + echo m68k-unknown-sysv4 + exit ;; + *:[Aa]miga[Oo][Ss]:*:*) + echo ${UNAME_MACHINE}-unknown-amigaos + exit ;; + *:[Mm]orph[Oo][Ss]:*:*) + echo ${UNAME_MACHINE}-unknown-morphos + exit ;; + *:OS/390:*:*) + echo i370-ibm-openedition + exit ;; + *:z/VM:*:*) + echo s390-ibm-zvmoe + exit ;; + *:OS400:*:*) + echo powerpc-ibm-os400 + exit ;; + arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) + echo arm-acorn-riscix${UNAME_RELEASE} + exit ;; + arm:riscos:*:*|arm:RISCOS:*:*) + echo arm-unknown-riscos + exit ;; + SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*) + echo hppa1.1-hitachi-hiuxmpp + exit ;; + Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*) + # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE. + if test "`(/bin/universe) 2>/dev/null`" = att ; then + echo pyramid-pyramid-sysv3 + else + echo pyramid-pyramid-bsd + fi + exit ;; + NILE*:*:*:dcosx) + echo pyramid-pyramid-svr4 + exit ;; + DRS?6000:unix:4.0:6*) + echo sparc-icl-nx6 + exit ;; + DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*) + case `/usr/bin/uname -p` in + sparc) echo sparc-icl-nx7; exit ;; + esac ;; + s390x:SunOS:*:*) + echo ${UNAME_MACHINE}-ibm-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4H:SunOS:5.*:*) + echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*) + echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + i86pc:AuroraUX:5.*:* | i86xen:AuroraUX:5.*:*) + echo i386-pc-auroraux${UNAME_RELEASE} + exit ;; + i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*) + eval $set_cc_for_build + SUN_ARCH="i386" + # If there is a compiler, see if it is configured for 64-bit objects. + # Note that the Sun cc does not turn __LP64__ into 1 like gcc does. + # This test works for both compilers. + if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then + if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \ + (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \ + grep IS_64BIT_ARCH >/dev/null + then + SUN_ARCH="x86_64" + fi + fi + echo ${SUN_ARCH}-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4*:SunOS:6*:*) + # According to config.sub, this is the proper way to canonicalize + # SunOS6. Hard to guess exactly what SunOS6 will be like, but + # it's likely to be more like Solaris than SunOS4. + echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + sun4*:SunOS:*:*) + case "`/usr/bin/arch -k`" in + Series*|S4*) + UNAME_RELEASE=`uname -v` + ;; + esac + # Japanese Language versions have a version number like `4.1.3-JL'. + echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'` + exit ;; + sun3*:SunOS:*:*) + echo m68k-sun-sunos${UNAME_RELEASE} + exit ;; + sun*:*:4.2BSD:*) + UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null` + test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3 + case "`/bin/arch`" in + sun3) + echo m68k-sun-sunos${UNAME_RELEASE} + ;; + sun4) + echo sparc-sun-sunos${UNAME_RELEASE} + ;; + esac + exit ;; + aushp:SunOS:*:*) + echo sparc-auspex-sunos${UNAME_RELEASE} + exit ;; + # The situation for MiNT is a little confusing. The machine name + # can be virtually everything (everything which is not + # "atarist" or "atariste" at least should have a processor + # > m68000). The system name ranges from "MiNT" over "FreeMiNT" + # to the lowercase version "mint" (or "freemint"). Finally + # the system name "TOS" denotes a system which is actually not + # MiNT. But MiNT is downward compatible to TOS, so this should + # be no problem. + atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit ;; + atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit ;; + *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit ;; + milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*) + echo m68k-milan-mint${UNAME_RELEASE} + exit ;; + hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*) + echo m68k-hades-mint${UNAME_RELEASE} + exit ;; + *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*) + echo m68k-unknown-mint${UNAME_RELEASE} + exit ;; + m68k:machten:*:*) + echo m68k-apple-machten${UNAME_RELEASE} + exit ;; + powerpc:machten:*:*) + echo powerpc-apple-machten${UNAME_RELEASE} + exit ;; + RISC*:Mach:*:*) + echo mips-dec-mach_bsd4.3 + exit ;; + RISC*:ULTRIX:*:*) + echo mips-dec-ultrix${UNAME_RELEASE} + exit ;; + VAX*:ULTRIX*:*:*) + echo vax-dec-ultrix${UNAME_RELEASE} + exit ;; + 2020:CLIX:*:* | 2430:CLIX:*:*) + echo clipper-intergraph-clix${UNAME_RELEASE} + exit ;; + mips:*:*:UMIPS | mips:*:*:RISCos) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c +#ifdef __cplusplus +#include /* for printf() prototype */ + int main (int argc, char *argv[]) { +#else + int main (argc, argv) int argc; char *argv[]; { +#endif + #if defined (host_mips) && defined (MIPSEB) + #if defined (SYSTYPE_SYSV) + printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0); + #endif + #if defined (SYSTYPE_SVR4) + printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0); + #endif + #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD) + printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0); + #endif + #endif + exit (-1); + } +EOF + $CC_FOR_BUILD -o $dummy $dummy.c && + dummyarg=`echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` && + SYSTEM_NAME=`$dummy $dummyarg` && + { echo "$SYSTEM_NAME"; exit; } + echo mips-mips-riscos${UNAME_RELEASE} + exit ;; + Motorola:PowerMAX_OS:*:*) + echo powerpc-motorola-powermax + exit ;; + Motorola:*:4.3:PL8-*) + echo powerpc-harris-powermax + exit ;; + Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*) + echo powerpc-harris-powermax + exit ;; + Night_Hawk:Power_UNIX:*:*) + echo powerpc-harris-powerunix + exit ;; + m88k:CX/UX:7*:*) + echo m88k-harris-cxux7 + exit ;; + m88k:*:4*:R4*) + echo m88k-motorola-sysv4 + exit ;; + m88k:*:3*:R3*) + echo m88k-motorola-sysv3 + exit ;; + AViiON:dgux:*:*) + # DG/UX returns AViiON for all architectures + UNAME_PROCESSOR=`/usr/bin/uname -p` + if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ] + then + if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \ + [ ${TARGET_BINARY_INTERFACE}x = x ] + then + echo m88k-dg-dgux${UNAME_RELEASE} + else + echo m88k-dg-dguxbcs${UNAME_RELEASE} + fi + else + echo i586-dg-dgux${UNAME_RELEASE} + fi + exit ;; + M88*:DolphinOS:*:*) # DolphinOS (SVR3) + echo m88k-dolphin-sysv3 + exit ;; + M88*:*:R3*:*) + # Delta 88k system running SVR3 + echo m88k-motorola-sysv3 + exit ;; + XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3) + echo m88k-tektronix-sysv3 + exit ;; + Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD) + echo m68k-tektronix-bsd + exit ;; + *:IRIX*:*:*) + echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'` + exit ;; + ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX. + echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id + exit ;; # Note that: echo "'`uname -s`'" gives 'AIX ' + i*86:AIX:*:*) + echo i386-ibm-aix + exit ;; + ia64:AIX:*:*) + if [ -x /usr/bin/oslevel ] ; then + IBM_REV=`/usr/bin/oslevel` + else + IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} + fi + echo ${UNAME_MACHINE}-ibm-aix${IBM_REV} + exit ;; + *:AIX:2:3) + if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #include + + main() + { + if (!__power_pc()) + exit(1); + puts("powerpc-ibm-aix3.2.5"); + exit(0); + } +EOF + if $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` + then + echo "$SYSTEM_NAME" + else + echo rs6000-ibm-aix3.2.5 + fi + elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then + echo rs6000-ibm-aix3.2.4 + else + echo rs6000-ibm-aix3.2 + fi + exit ;; + *:AIX:*:[4567]) + IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'` + if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then + IBM_ARCH=rs6000 + else + IBM_ARCH=powerpc + fi + if [ -x /usr/bin/oslevel ] ; then + IBM_REV=`/usr/bin/oslevel` + else + IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} + fi + echo ${IBM_ARCH}-ibm-aix${IBM_REV} + exit ;; + *:AIX:*:*) + echo rs6000-ibm-aix + exit ;; + ibmrt:4.4BSD:*|romp-ibm:BSD:*) + echo romp-ibm-bsd4.4 + exit ;; + ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and + echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to + exit ;; # report: romp-ibm BSD 4.3 + *:BOSX:*:*) + echo rs6000-bull-bosx + exit ;; + DPX/2?00:B.O.S.:*:*) + echo m68k-bull-sysv3 + exit ;; + 9000/[34]??:4.3bsd:1.*:*) + echo m68k-hp-bsd + exit ;; + hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*) + echo m68k-hp-bsd4.4 + exit ;; + 9000/[34678]??:HP-UX:*:*) + HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` + case "${UNAME_MACHINE}" in + 9000/31? ) HP_ARCH=m68000 ;; + 9000/[34]?? ) HP_ARCH=m68k ;; + 9000/[678][0-9][0-9]) + if [ -x /usr/bin/getconf ]; then + sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null` + sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null` + case "${sc_cpu_version}" in + 523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0 + 528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1 + 532) # CPU_PA_RISC2_0 + case "${sc_kernel_bits}" in + 32) HP_ARCH="hppa2.0n" ;; + 64) HP_ARCH="hppa2.0w" ;; + '') HP_ARCH="hppa2.0" ;; # HP-UX 10.20 + esac ;; + esac + fi + if [ "${HP_ARCH}" = "" ]; then + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + + #define _HPUX_SOURCE + #include + #include + + int main () + { + #if defined(_SC_KERNEL_BITS) + long bits = sysconf(_SC_KERNEL_BITS); + #endif + long cpu = sysconf (_SC_CPU_VERSION); + + switch (cpu) + { + case CPU_PA_RISC1_0: puts ("hppa1.0"); break; + case CPU_PA_RISC1_1: puts ("hppa1.1"); break; + case CPU_PA_RISC2_0: + #if defined(_SC_KERNEL_BITS) + switch (bits) + { + case 64: puts ("hppa2.0w"); break; + case 32: puts ("hppa2.0n"); break; + default: puts ("hppa2.0"); break; + } break; + #else /* !defined(_SC_KERNEL_BITS) */ + puts ("hppa2.0"); break; + #endif + default: puts ("hppa1.0"); break; + } + exit (0); + } +EOF + (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy` + test -z "$HP_ARCH" && HP_ARCH=hppa + fi ;; + esac + if [ ${HP_ARCH} = "hppa2.0w" ] + then + eval $set_cc_for_build + + # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating + # 32-bit code. hppa64-hp-hpux* has the same kernel and a compiler + # generating 64-bit code. GNU and HP use different nomenclature: + # + # $ CC_FOR_BUILD=cc ./config.guess + # => hppa2.0w-hp-hpux11.23 + # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess + # => hppa64-hp-hpux11.23 + + if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | + grep -q __LP64__ + then + HP_ARCH="hppa2.0w" + else + HP_ARCH="hppa64" + fi + fi + echo ${HP_ARCH}-hp-hpux${HPUX_REV} + exit ;; + ia64:HP-UX:*:*) + HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` + echo ia64-hp-hpux${HPUX_REV} + exit ;; + 3050*:HI-UX:*:*) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #include + int + main () + { + long cpu = sysconf (_SC_CPU_VERSION); + /* The order matters, because CPU_IS_HP_MC68K erroneously returns + true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct + results, however. */ + if (CPU_IS_PA_RISC (cpu)) + { + switch (cpu) + { + case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break; + case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break; + case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break; + default: puts ("hppa-hitachi-hiuxwe2"); break; + } + } + else if (CPU_IS_HP_MC68K (cpu)) + puts ("m68k-hitachi-hiuxwe2"); + else puts ("unknown-hitachi-hiuxwe2"); + exit (0); + } +EOF + $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` && + { echo "$SYSTEM_NAME"; exit; } + echo unknown-hitachi-hiuxwe2 + exit ;; + 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* ) + echo hppa1.1-hp-bsd + exit ;; + 9000/8??:4.3bsd:*:*) + echo hppa1.0-hp-bsd + exit ;; + *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*) + echo hppa1.0-hp-mpeix + exit ;; + hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* ) + echo hppa1.1-hp-osf + exit ;; + hp8??:OSF1:*:*) + echo hppa1.0-hp-osf + exit ;; + i*86:OSF1:*:*) + if [ -x /usr/sbin/sysversion ] ; then + echo ${UNAME_MACHINE}-unknown-osf1mk + else + echo ${UNAME_MACHINE}-unknown-osf1 + fi + exit ;; + parisc*:Lites*:*:*) + echo hppa1.1-hp-lites + exit ;; + C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*) + echo c1-convex-bsd + exit ;; + C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*) + if getsysinfo -f scalar_acc + then echo c32-convex-bsd + else echo c2-convex-bsd + fi + exit ;; + C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*) + echo c34-convex-bsd + exit ;; + C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*) + echo c38-convex-bsd + exit ;; + C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*) + echo c4-convex-bsd + exit ;; + CRAY*Y-MP:*:*:*) + echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*[A-Z]90:*:*:*) + echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \ + | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \ + -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \ + -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*TS:*:*:*) + echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*T3E:*:*:*) + echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + CRAY*SV1:*:*:*) + echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + *:UNICOS/mp:*:*) + echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit ;; + F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*) + FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` + FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` + FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'` + echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" + exit ;; + 5000:UNIX_System_V:4.*:*) + FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` + FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'` + echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" + exit ;; + i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) + echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE} + exit ;; + sparc*:BSD/OS:*:*) + echo sparc-unknown-bsdi${UNAME_RELEASE} + exit ;; + *:BSD/OS:*:*) + echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE} + exit ;; + *:FreeBSD:*:*) + UNAME_PROCESSOR=`/usr/bin/uname -p` + case ${UNAME_PROCESSOR} in + amd64) + echo x86_64-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; + *) + echo ${UNAME_PROCESSOR}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; + esac + exit ;; + i*:CYGWIN*:*) + echo ${UNAME_MACHINE}-pc-cygwin + exit ;; + *:MINGW*:*) + echo ${UNAME_MACHINE}-pc-mingw32 + exit ;; + i*:MSYS*:*) + echo ${UNAME_MACHINE}-pc-msys + exit ;; + i*:windows32*:*) + # uname -m includes "-pc" on this system. + echo ${UNAME_MACHINE}-mingw32 + exit ;; + i*:PW*:*) + echo ${UNAME_MACHINE}-pc-pw32 + exit ;; + *:Interix*:*) + case ${UNAME_MACHINE} in + x86) + echo i586-pc-interix${UNAME_RELEASE} + exit ;; + authenticamd | genuineintel | EM64T) + echo x86_64-unknown-interix${UNAME_RELEASE} + exit ;; + IA64) + echo ia64-unknown-interix${UNAME_RELEASE} + exit ;; + esac ;; + [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*) + echo i${UNAME_MACHINE}-pc-mks + exit ;; + 8664:Windows_NT:*) + echo x86_64-pc-mks + exit ;; + i*:Windows_NT*:* | Pentium*:Windows_NT*:*) + # How do we know it's Interix rather than the generic POSIX subsystem? + # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we + # UNAME_MACHINE based on the output of uname instead of i386? + echo i586-pc-interix + exit ;; + i*:UWIN*:*) + echo ${UNAME_MACHINE}-pc-uwin + exit ;; + amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*) + echo x86_64-unknown-cygwin + exit ;; + p*:CYGWIN*:*) + echo powerpcle-unknown-cygwin + exit ;; + prep*:SunOS:5.*:*) + echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; + *:GNU:*:*) + # the GNU system + echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'` + exit ;; + *:GNU/*:*:*) + # other systems with GNU libc and userland + echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr '[A-Z]' '[a-z]'``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-gnu + exit ;; + i*86:Minix:*:*) + echo ${UNAME_MACHINE}-pc-minix + exit ;; + alpha:Linux:*:*) + case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in + EV5) UNAME_MACHINE=alphaev5 ;; + EV56) UNAME_MACHINE=alphaev56 ;; + PCA56) UNAME_MACHINE=alphapca56 ;; + PCA57) UNAME_MACHINE=alphapca56 ;; + EV6) UNAME_MACHINE=alphaev6 ;; + EV67) UNAME_MACHINE=alphaev67 ;; + EV68*) UNAME_MACHINE=alphaev68 ;; + esac + objdump --private-headers /bin/sh | grep -q ld.so.1 + if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi + echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC} + exit ;; + arm*:Linux:*:*) + eval $set_cc_for_build + if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep -q __ARM_EABI__ + then + echo ${UNAME_MACHINE}-unknown-linux-gnu + else + if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep -q __ARM_PCS_VFP + then + echo ${UNAME_MACHINE}-unknown-linux-gnueabi + else + echo ${UNAME_MACHINE}-unknown-linux-gnueabihf + fi + fi + exit ;; + avr32*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + cris:Linux:*:*) + echo cris-axis-linux-gnu + exit ;; + crisv32:Linux:*:*) + echo crisv32-axis-linux-gnu + exit ;; + frv:Linux:*:*) + echo frv-unknown-linux-gnu + exit ;; + hexagon:Linux:*:*) + echo hexagon-unknown-linux-gnu + exit ;; + i*86:Linux:*:*) + LIBC=gnu + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #ifdef __dietlibc__ + LIBC=dietlibc + #endif +EOF + eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^LIBC'` + echo "${UNAME_MACHINE}-pc-linux-${LIBC}" + exit ;; + ia64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + m32r*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + m68*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + mips:Linux:*:* | mips64:Linux:*:*) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #undef CPU + #undef ${UNAME_MACHINE} + #undef ${UNAME_MACHINE}el + #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) + CPU=${UNAME_MACHINE}el + #else + #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) + CPU=${UNAME_MACHINE} + #else + CPU= + #endif + #endif +EOF + eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^CPU'` + test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; } + ;; + or32:Linux:*:*) + echo or32-unknown-linux-gnu + exit ;; + padre:Linux:*:*) + echo sparc-unknown-linux-gnu + exit ;; + parisc64:Linux:*:* | hppa64:Linux:*:*) + echo hppa64-unknown-linux-gnu + exit ;; + parisc:Linux:*:* | hppa:Linux:*:*) + # Look for CPU level + case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in + PA7*) echo hppa1.1-unknown-linux-gnu ;; + PA8*) echo hppa2.0-unknown-linux-gnu ;; + *) echo hppa-unknown-linux-gnu ;; + esac + exit ;; + ppc64:Linux:*:*) + echo powerpc64-unknown-linux-gnu + exit ;; + ppc:Linux:*:*) + echo powerpc-unknown-linux-gnu + exit ;; + s390:Linux:*:* | s390x:Linux:*:*) + echo ${UNAME_MACHINE}-ibm-linux + exit ;; + sh64*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + sh*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + sparc:Linux:*:* | sparc64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + tile*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + vax:Linux:*:*) + echo ${UNAME_MACHINE}-dec-linux-gnu + exit ;; + x86_64:Linux:*:*) + echo x86_64-unknown-linux-gnu + exit ;; + xtensa*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + i*86:DYNIX/ptx:4*:*) + # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. + # earlier versions are messed up and put the nodename in both + # sysname and nodename. + echo i386-sequent-sysv4 + exit ;; + i*86:UNIX_SV:4.2MP:2.*) + # Unixware is an offshoot of SVR4, but it has its own version + # number series starting with 2... + # I am not positive that other SVR4 systems won't match this, + # I just have to hope. -- rms. + # Use sysv4.2uw... so that sysv4* matches it. + echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION} + exit ;; + i*86:OS/2:*:*) + # If we were able to find `uname', then EMX Unix compatibility + # is probably installed. + echo ${UNAME_MACHINE}-pc-os2-emx + exit ;; + i*86:XTS-300:*:STOP) + echo ${UNAME_MACHINE}-unknown-stop + exit ;; + i*86:atheos:*:*) + echo ${UNAME_MACHINE}-unknown-atheos + exit ;; + i*86:syllable:*:*) + echo ${UNAME_MACHINE}-pc-syllable + exit ;; + i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.[02]*:*) + echo i386-unknown-lynxos${UNAME_RELEASE} + exit ;; + i*86:*DOS:*:*) + echo ${UNAME_MACHINE}-pc-msdosdjgpp + exit ;; + i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*) + UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'` + if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then + echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL} + else + echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL} + fi + exit ;; + i*86:*:5:[678]*) + # UnixWare 7.x, OpenUNIX and OpenServer 6. + case `/bin/uname -X | grep "^Machine"` in + *486*) UNAME_MACHINE=i486 ;; + *Pentium) UNAME_MACHINE=i586 ;; + *Pent*|*Celeron) UNAME_MACHINE=i686 ;; + esac + echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION} + exit ;; + i*86:*:3.2:*) + if test -f /usr/options/cb.name; then + UNAME_REL=`sed -n 's/.*Version //p' /dev/null >/dev/null ; then + UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')` + (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486 + (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \ + && UNAME_MACHINE=i586 + (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \ + && UNAME_MACHINE=i686 + (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \ + && UNAME_MACHINE=i686 + echo ${UNAME_MACHINE}-pc-sco$UNAME_REL + else + echo ${UNAME_MACHINE}-pc-sysv32 + fi + exit ;; + pc:*:*:*) + # Left here for compatibility: + # uname -m prints for DJGPP always 'pc', but it prints nothing about + # the processor, so we play safe by assuming i586. + # Note: whatever this is, it MUST be the same as what config.sub + # prints for the "djgpp" host, or else GDB configury will decide that + # this is a cross-build. + echo i586-pc-msdosdjgpp + exit ;; + Intel:Mach:3*:*) + echo i386-pc-mach3 + exit ;; + paragon:*:*:*) + echo i860-intel-osf1 + exit ;; + i860:*:4.*:*) # i860-SVR4 + if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then + echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4 + else # Add other i860-SVR4 vendors below as they are discovered. + echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4 + fi + exit ;; + mini*:CTIX:SYS*5:*) + # "miniframe" + echo m68010-convergent-sysv + exit ;; + mc68k:UNIX:SYSTEM5:3.51m) + echo m68k-convergent-sysv + exit ;; + M680?0:D-NIX:5.3:*) + echo m68k-diab-dnix + exit ;; + M68*:*:R3V[5678]*:*) + test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;; + 3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0) + OS_REL='' + test -r /etc/.relid \ + && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && { echo i486-ncr-sysv4.3${OS_REL}; exit; } + /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ + && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; + 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*) + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && { echo i486-ncr-sysv4; exit; } ;; + NCR*:*:4.2:* | MPRAS*:*:4.2:*) + OS_REL='.3' + test -r /etc/.relid \ + && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && { echo i486-ncr-sysv4.3${OS_REL}; exit; } + /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ + && { echo i586-ncr-sysv4.3${OS_REL}; exit; } + /bin/uname -p 2>/dev/null | /bin/grep pteron >/dev/null \ + && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; + m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*) + echo m68k-unknown-lynxos${UNAME_RELEASE} + exit ;; + mc68030:UNIX_System_V:4.*:*) + echo m68k-atari-sysv4 + exit ;; + TSUNAMI:LynxOS:2.*:*) + echo sparc-unknown-lynxos${UNAME_RELEASE} + exit ;; + rs6000:LynxOS:2.*:*) + echo rs6000-unknown-lynxos${UNAME_RELEASE} + exit ;; + PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.[02]*:*) + echo powerpc-unknown-lynxos${UNAME_RELEASE} + exit ;; + SM[BE]S:UNIX_SV:*:*) + echo mips-dde-sysv${UNAME_RELEASE} + exit ;; + RM*:ReliantUNIX-*:*:*) + echo mips-sni-sysv4 + exit ;; + RM*:SINIX-*:*:*) + echo mips-sni-sysv4 + exit ;; + *:SINIX-*:*:*) + if uname -p 2>/dev/null >/dev/null ; then + UNAME_MACHINE=`(uname -p) 2>/dev/null` + echo ${UNAME_MACHINE}-sni-sysv4 + else + echo ns32k-sni-sysv + fi + exit ;; + PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort + # says + echo i586-unisys-sysv4 + exit ;; + *:UNIX_System_V:4*:FTX*) + # From Gerald Hewes . + # How about differentiating between stratus architectures? -djm + echo hppa1.1-stratus-sysv4 + exit ;; + *:*:*:FTX*) + # From seanf@swdc.stratus.com. + echo i860-stratus-sysv4 + exit ;; + i*86:VOS:*:*) + # From Paul.Green@stratus.com. + echo ${UNAME_MACHINE}-stratus-vos + exit ;; + *:VOS:*:*) + # From Paul.Green@stratus.com. + echo hppa1.1-stratus-vos + exit ;; + mc68*:A/UX:*:*) + echo m68k-apple-aux${UNAME_RELEASE} + exit ;; + news*:NEWS-OS:6*:*) + echo mips-sony-newsos6 + exit ;; + R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*) + if [ -d /usr/nec ]; then + echo mips-nec-sysv${UNAME_RELEASE} + else + echo mips-unknown-sysv${UNAME_RELEASE} + fi + exit ;; + BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only. + echo powerpc-be-beos + exit ;; + BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only. + echo powerpc-apple-beos + exit ;; + BePC:BeOS:*:*) # BeOS running on Intel PC compatible. + echo i586-pc-beos + exit ;; + BePC:Haiku:*:*) # Haiku running on Intel PC compatible. + echo i586-pc-haiku + exit ;; + SX-4:SUPER-UX:*:*) + echo sx4-nec-superux${UNAME_RELEASE} + exit ;; + SX-5:SUPER-UX:*:*) + echo sx5-nec-superux${UNAME_RELEASE} + exit ;; + SX-6:SUPER-UX:*:*) + echo sx6-nec-superux${UNAME_RELEASE} + exit ;; + SX-7:SUPER-UX:*:*) + echo sx7-nec-superux${UNAME_RELEASE} + exit ;; + SX-8:SUPER-UX:*:*) + echo sx8-nec-superux${UNAME_RELEASE} + exit ;; + SX-8R:SUPER-UX:*:*) + echo sx8r-nec-superux${UNAME_RELEASE} + exit ;; + Power*:Rhapsody:*:*) + echo powerpc-apple-rhapsody${UNAME_RELEASE} + exit ;; + *:Rhapsody:*:*) + echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE} + exit ;; + *:Darwin:*:*) + UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown + case $UNAME_PROCESSOR in + i386) + eval $set_cc_for_build + if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then + if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \ + (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \ + grep IS_64BIT_ARCH >/dev/null + then + UNAME_PROCESSOR="x86_64" + fi + fi ;; + unknown) UNAME_PROCESSOR=powerpc ;; + esac + echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE} + exit ;; + *:procnto*:*:* | *:QNX:[0123456789]*:*) + UNAME_PROCESSOR=`uname -p` + if test "$UNAME_PROCESSOR" = "x86"; then + UNAME_PROCESSOR=i386 + UNAME_MACHINE=pc + fi + echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE} + exit ;; + *:QNX:*:4*) + echo i386-pc-qnx + exit ;; + NEO-?:NONSTOP_KERNEL:*:*) + echo neo-tandem-nsk${UNAME_RELEASE} + exit ;; + NSE-?:NONSTOP_KERNEL:*:*) + echo nse-tandem-nsk${UNAME_RELEASE} + exit ;; + NSR-?:NONSTOP_KERNEL:*:*) + echo nsr-tandem-nsk${UNAME_RELEASE} + exit ;; + *:NonStop-UX:*:*) + echo mips-compaq-nonstopux + exit ;; + BS2000:POSIX*:*:*) + echo bs2000-siemens-sysv + exit ;; + DS/*:UNIX_System_V:*:*) + echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE} + exit ;; + *:Plan9:*:*) + # "uname -m" is not consistent, so use $cputype instead. 386 + # is converted to i386 for consistency with other x86 + # operating systems. + if test "$cputype" = "386"; then + UNAME_MACHINE=i386 + else + UNAME_MACHINE="$cputype" + fi + echo ${UNAME_MACHINE}-unknown-plan9 + exit ;; + *:TOPS-10:*:*) + echo pdp10-unknown-tops10 + exit ;; + *:TENEX:*:*) + echo pdp10-unknown-tenex + exit ;; + KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*) + echo pdp10-dec-tops20 + exit ;; + XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*) + echo pdp10-xkl-tops20 + exit ;; + *:TOPS-20:*:*) + echo pdp10-unknown-tops20 + exit ;; + *:ITS:*:*) + echo pdp10-unknown-its + exit ;; + SEI:*:*:SEIUX) + echo mips-sei-seiux${UNAME_RELEASE} + exit ;; + *:DragonFly:*:*) + echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` + exit ;; + *:*VMS:*:*) + UNAME_MACHINE=`(uname -p) 2>/dev/null` + case "${UNAME_MACHINE}" in + A*) echo alpha-dec-vms ; exit ;; + I*) echo ia64-dec-vms ; exit ;; + V*) echo vax-dec-vms ; exit ;; + esac ;; + *:XENIX:*:SysV) + echo i386-pc-xenix + exit ;; + i*86:skyos:*:*) + echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE}` | sed -e 's/ .*$//' + exit ;; + i*86:rdos:*:*) + echo ${UNAME_MACHINE}-pc-rdos + exit ;; + i*86:AROS:*:*) + echo ${UNAME_MACHINE}-pc-aros + exit ;; +esac + +#echo '(No uname command or uname output not recognized.)' 1>&2 +#echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2 + +eval $set_cc_for_build +cat >$dummy.c < +# include +#endif +main () +{ +#if defined (sony) +#if defined (MIPSEB) + /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed, + I don't know.... */ + printf ("mips-sony-bsd\n"); exit (0); +#else +#include + printf ("m68k-sony-newsos%s\n", +#ifdef NEWSOS4 + "4" +#else + "" +#endif + ); exit (0); +#endif +#endif + +#if defined (__arm) && defined (__acorn) && defined (__unix) + printf ("arm-acorn-riscix\n"); exit (0); +#endif + +#if defined (hp300) && !defined (hpux) + printf ("m68k-hp-bsd\n"); exit (0); +#endif + +#if defined (NeXT) +#if !defined (__ARCHITECTURE__) +#define __ARCHITECTURE__ "m68k" +#endif + int version; + version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`; + if (version < 4) + printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version); + else + printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version); + exit (0); +#endif + +#if defined (MULTIMAX) || defined (n16) +#if defined (UMAXV) + printf ("ns32k-encore-sysv\n"); exit (0); +#else +#if defined (CMU) + printf ("ns32k-encore-mach\n"); exit (0); +#else + printf ("ns32k-encore-bsd\n"); exit (0); +#endif +#endif +#endif + +#if defined (__386BSD__) + printf ("i386-pc-bsd\n"); exit (0); +#endif + +#if defined (sequent) +#if defined (i386) + printf ("i386-sequent-dynix\n"); exit (0); +#endif +#if defined (ns32000) + printf ("ns32k-sequent-dynix\n"); exit (0); +#endif +#endif + +#if defined (_SEQUENT_) + struct utsname un; + + uname(&un); + + if (strncmp(un.version, "V2", 2) == 0) { + printf ("i386-sequent-ptx2\n"); exit (0); + } + if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */ + printf ("i386-sequent-ptx1\n"); exit (0); + } + printf ("i386-sequent-ptx\n"); exit (0); + +#endif + +#if defined (vax) +# if !defined (ultrix) +# include +# if defined (BSD) +# if BSD == 43 + printf ("vax-dec-bsd4.3\n"); exit (0); +# else +# if BSD == 199006 + printf ("vax-dec-bsd4.3reno\n"); exit (0); +# else + printf ("vax-dec-bsd\n"); exit (0); +# endif +# endif +# else + printf ("vax-dec-bsd\n"); exit (0); +# endif +# else + printf ("vax-dec-ultrix\n"); exit (0); +# endif +#endif + +#if defined (alliant) && defined (i860) + printf ("i860-alliant-bsd\n"); exit (0); +#endif + + exit (1); +} +EOF + +$CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null && SYSTEM_NAME=`$dummy` && + { echo "$SYSTEM_NAME"; exit; } + +# Apollos put the system type in the environment. + +test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit; } + +# Convex versions that predate uname can use getsysinfo(1) + +if [ -x /usr/convex/getsysinfo ] +then + case `getsysinfo -f cpu_type` in + c1*) + echo c1-convex-bsd + exit ;; + c2*) + if getsysinfo -f scalar_acc + then echo c32-convex-bsd + else echo c2-convex-bsd + fi + exit ;; + c34*) + echo c34-convex-bsd + exit ;; + c38*) + echo c38-convex-bsd + exit ;; + c4*) + echo c4-convex-bsd + exit ;; + esac +fi + +cat >&2 < in order to provide the needed +information to handle your system. + +config.guess timestamp = $timestamp + +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` +/bin/uname -X = `(/bin/uname -X) 2>/dev/null` + +hostinfo = `(hostinfo) 2>/dev/null` +/bin/universe = `(/bin/universe) 2>/dev/null` +/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null` +/bin/arch = `(/bin/arch) 2>/dev/null` +/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null` +/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null` + +UNAME_MACHINE = ${UNAME_MACHINE} +UNAME_RELEASE = ${UNAME_RELEASE} +UNAME_SYSTEM = ${UNAME_SYSTEM} +UNAME_VERSION = ${UNAME_VERSION} +EOF + +exit 1 + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "timestamp='" +# time-stamp-format: "%:y-%02m-%02d" +# time-stamp-end: "'" +# End: diff -r 000000000000 -r a1985f14b030 dist/config.hin --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dist/config.hin Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,670 @@ +/* config.hin. Generated from configure.ac by autoheader. + * + * Copyright (c) 2012 Oracle and/or its affiliates. All rights reserved. * + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* Define to 1 if you want to build a version for running the test suite. */ +#undef CONFIG_TEST + +/* Defined to a size to limit the stack size of Berkeley DB threads. */ +#undef DB_STACKSIZE + +/* We use DB_WIN32 much as one would use _WIN32 -- to specify that we're using + an operating system environment that supports Win32 calls and semantics. We + don't use _WIN32 because Cygwin/GCC also defines _WIN32, even though + Cygwin/GCC closely emulates the Unix environment. */ +#undef DB_WIN32 + +/* Define to 1 if you want a debugging version. */ +#undef DEBUG + +/* Define to 1 if you want a version that logs read operations. */ +#undef DEBUG_ROP + +/* Define to 1 if you want a version that logs write operations. */ +#undef DEBUG_WOP + +/* Define to 1 if you want a version with run-time diagnostic checking. */ +#undef DIAGNOSTIC + +/* Define to 1 if 64-bit types are available. */ +#undef HAVE_64BIT_TYPES + +/* Define to 1 if you have the `abort' function. */ +#undef HAVE_ABORT + +/* Define to 1 if you have the `atoi' function. */ +#undef HAVE_ATOI + +/* Define to 1 if you have the `atol' function. */ +#undef HAVE_ATOL + +/* Define to 1 if platform reads and writes files atomically. */ +#undef HAVE_ATOMICFILEREAD + +/* Define to 1 to use Solaris library routes for atomic operations. */ +#undef HAVE_ATOMIC_SOLARIS + +/* Define to 1 to use native atomic operations. */ +#undef HAVE_ATOMIC_SUPPORT + +/* Define to 1 to use GCC and x86 or x86_64 assemlby language atomic + operations. */ +#undef HAVE_ATOMIC_X86_GCC_ASSEMBLY + +/* Define to 1 if you have the `backtrace' function. */ +#undef HAVE_BACKTRACE + +/* Define to 1 if you have the `backtrace_symbols' function. */ +#undef HAVE_BACKTRACE_SYMBOLS + +/* Define to 1 if you have the `bsearch' function. */ +#undef HAVE_BSEARCH + +/* Define to 1 if you have the `clock_gettime' function. */ +#undef HAVE_CLOCK_GETTIME + +/* Define to 1 if clock_gettime supports CLOCK_MONOTONIC. */ +#undef HAVE_CLOCK_MONOTONIC + +/* Define to 1 if building compression support. */ +#undef HAVE_COMPRESSION + +/* Define to 1 if building cryptography support. */ +#undef HAVE_CRYPTO + +/* Define to 1 if using Intel IPP for cryptography. */ +#undef HAVE_CRYPTO_IPP + +/* Define to 1 if you have the `ctime_r' function. */ +#undef HAVE_CTIME_R + +/* Define to 1 if ctime_r takes a buffer length as a third argument. */ +#undef HAVE_CTIME_R_3ARG + +/* Define to 1 if building the DBM API. */ +#undef HAVE_DBM + +/* Define to 1 if you have the `directio' function. */ +#undef HAVE_DIRECTIO + +/* Define to 1 if you have the header file, and it defines `DIR'. + */ +#undef HAVE_DIRENT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_DLFCN_H + +/* Define to 1 to use dtrace for performance monitoring. */ +#undef HAVE_DTRACE + +/* Define to 1 if you have the header file. */ +#undef HAVE_EXECINFO_H + +/* Define to 1 if platform has EXIT_SUCCESS/EXIT_FAILURE #defines. */ +#undef HAVE_EXIT_SUCCESS + +/* Define to 1 if you have the `fchmod' function. */ +#undef HAVE_FCHMOD + +/* Define to 1 if you have the `fclose' function. */ +#undef HAVE_FCLOSE + +/* Define to 1 if you have the `fcntl' function. */ +#undef HAVE_FCNTL + +/* Define to 1 if fcntl/F_SETFD denies child access to file descriptors. */ +#undef HAVE_FCNTL_F_SETFD + +/* Define to 1 if you have the `fdatasync' function. */ +#undef HAVE_FDATASYNC + +/* Define to 1 if you have the `fgetc' function. */ +#undef HAVE_FGETC + +/* Define to 1 if you have the `fgets' function. */ +#undef HAVE_FGETS + +/* Define to 1 if allocated filesystem blocks are not zeroed. */ +#undef HAVE_FILESYSTEM_NOTZERO + +/* Define to 1 if you have the `fopen' function. */ +#undef HAVE_FOPEN + +/* Define to 1 if you have the `ftruncate' function. */ +#undef HAVE_FTRUNCATE + +/* Define to 1 if you have the `fwrite' function. */ +#undef HAVE_FWRITE + +/* Define to 1 if you have the `getaddrinfo' function. */ +#undef HAVE_GETADDRINFO + +/* Define to 1 if you have the `getcwd' function. */ +#undef HAVE_GETCWD + +/* Define to 1 if you have the `getenv' function. */ +#undef HAVE_GETENV + +/* Define to 1 if you have the `getgid' function. */ +#undef HAVE_GETGID + +/* Define to 1 if you have the `getopt' function. */ +#undef HAVE_GETOPT + +/* Define to 1 if getopt supports the optreset variable. */ +#undef HAVE_GETOPT_OPTRESET + +/* Define to 1 if you have the `getrusage' function. */ +#undef HAVE_GETRUSAGE + +/* Define to 1 if you have the `gettimeofday' function. */ +#undef HAVE_GETTIMEOFDAY + +/* Define to 1 if you have the `getuid' function. */ +#undef HAVE_GETUID + +/* Define to 1 if building Hash access method. */ +#undef HAVE_HASH + +/* Define to 1 if building Heap access method. */ +#undef HAVE_HEAP + +/* Define to 1 if you have the `hstrerror' function. */ +#undef HAVE_HSTRERROR + +/* Define to 1 if you have the header file. */ +#undef HAVE_INTTYPES_H + +/* Define to 1 if you have the `isalpha' function. */ +#undef HAVE_ISALPHA + +/* Define to 1 if you have the `isdigit' function. */ +#undef HAVE_ISDIGIT + +/* Define to 1 if you have the `isprint' function. */ +#undef HAVE_ISPRINT + +/* Define to 1 if you have the `isspace' function. */ +#undef HAVE_ISSPACE + +/* Define to 1 if you have localization function to support globalization. */ +#undef HAVE_LOCALIZATION + +/* Define to 1 if you have the `localtime' function. */ +#undef HAVE_LOCALTIME + +/* Define to 1 if enabling checksums in log records. */ +#undef HAVE_LOG_CHECKSUM + +/* Define to 1 if you have the `memcmp' function. */ +#undef HAVE_MEMCMP + +/* Define to 1 if you have the `memcpy' function. */ +#undef HAVE_MEMCPY + +/* Define to 1 if you have the `memmove' function. */ +#undef HAVE_MEMMOVE + +/* Define to 1 if you have the header file. */ +#undef HAVE_MEMORY_H + +/* Define to 1 if you have the `mlock' function. */ +#undef HAVE_MLOCK + +/* Define to 1 if you have the `mmap' function. */ +#undef HAVE_MMAP + +/* Define to 1 where mmap() incrementally extends the accessible mapping as + the underlying file grows. */ +#undef HAVE_MMAP_EXTEND + +/* Define to 1 if you have the `mprotect' function. */ +#undef HAVE_MPROTECT + +/* Define to 1 if you have the `munlock' function. */ +#undef HAVE_MUNLOCK + +/* Define to 1 if you have the `munmap' function. */ +#undef HAVE_MUNMAP + +/* Define to 1 to use the GCC compiler and 68K assembly language mutexes. */ +#undef HAVE_MUTEX_68K_GCC_ASSEMBLY + +/* Define to 1 to use the AIX _check_lock mutexes. */ +#undef HAVE_MUTEX_AIX_CHECK_LOCK + +/* Define to 1 to use the GCC compiler and Alpha assembly language mutexes. */ +#undef HAVE_MUTEX_ALPHA_GCC_ASSEMBLY + +/* Define to 1 to use the GCC compiler and ARM assembly language mutexes. */ +#undef HAVE_MUTEX_ARM_GCC_ASSEMBLY + +/* Define to 1 to use the Apple/Darwin _spin_lock_try mutexes. */ +#undef HAVE_MUTEX_DARWIN_SPIN_LOCK_TRY + +/* Define to 1 to use the UNIX fcntl system call mutexes. */ +#undef HAVE_MUTEX_FCNTL + +/* Define to 1 to use the GCC compiler and PaRisc assembly language mutexes. + */ +#undef HAVE_MUTEX_HPPA_GCC_ASSEMBLY + +/* Define to 1 to use the msem_XXX mutexes on HP-UX. */ +#undef HAVE_MUTEX_HPPA_MSEM_INIT + +/* Define to 1 to use test-and-set mutexes with blocking mutexes. */ +#undef HAVE_MUTEX_HYBRID + +/* Define to 1 to use the GCC compiler and IA64 assembly language mutexes. */ +#undef HAVE_MUTEX_IA64_GCC_ASSEMBLY + +/* Define to 1 to use the GCC compiler and MIPS assembly language mutexes. */ +#undef HAVE_MUTEX_MIPS_GCC_ASSEMBLY + +/* Define to 1 to use the msem_XXX mutexes on systems other than HP-UX. */ +#undef HAVE_MUTEX_MSEM_INIT + +/* Define to 1 to use the GCC compiler and PowerPC assembly language mutexes. + */ +#undef HAVE_MUTEX_PPC_GCC_ASSEMBLY + +/* Define to 1 to use POSIX 1003.1 pthread_XXX mutexes. */ +#undef HAVE_MUTEX_PTHREADS + +/* Define to 1 to use Reliant UNIX initspin mutexes. */ +#undef HAVE_MUTEX_RELIANTUNIX_INITSPIN + +/* Define to 1 to use the IBM C compiler and S/390 assembly language mutexes. + */ +#undef HAVE_MUTEX_S390_CC_ASSEMBLY + +/* Define to 1 to use the GCC compiler and S/390 assembly language mutexes. */ +#undef HAVE_MUTEX_S390_GCC_ASSEMBLY + +/* Define to 1 to use the SCO compiler and x86 assembly language mutexes. */ +#undef HAVE_MUTEX_SCO_X86_CC_ASSEMBLY + +/* Define to 1 to use the obsolete POSIX 1003.1 sema_XXX mutexes. */ +#undef HAVE_MUTEX_SEMA_INIT + +/* Define to 1 to use the SGI XXX_lock mutexes. */ +#undef HAVE_MUTEX_SGI_INIT_LOCK + +/* Define to 1 to use the Solaris _lock_XXX mutexes. */ +#undef HAVE_MUTEX_SOLARIS_LOCK_TRY + +/* Define to 1 to use the Solaris lwp threads mutexes. */ +#undef HAVE_MUTEX_SOLARIS_LWP + +/* Define to 1 to use the GCC compiler and Sparc assembly language mutexes. */ +#undef HAVE_MUTEX_SPARC_GCC_ASSEMBLY + +/* Define to 1 if the Berkeley DB library should support mutexes. */ +#undef HAVE_MUTEX_SUPPORT + +/* Define to 1 if mutexes hold system resources. */ +#undef HAVE_MUTEX_SYSTEM_RESOURCES + +/* Define to 1 to configure mutexes intra-process only. */ +#undef HAVE_MUTEX_THREAD_ONLY + +/* Define to 1 to use the CC compiler and Tru64 assembly language mutexes. */ +#undef HAVE_MUTEX_TRU64_CC_ASSEMBLY + +/* Define to 1 to use the UNIX International mutexes. */ +#undef HAVE_MUTEX_UI_THREADS + +/* Define to 1 to use the UTS compiler and assembly language mutexes. */ +#undef HAVE_MUTEX_UTS_CC_ASSEMBLY + +/* Define to 1 to use VMS mutexes. */ +#undef HAVE_MUTEX_VMS + +/* Define to 1 to use VxWorks mutexes. */ +#undef HAVE_MUTEX_VXWORKS + +/* Define to 1 to use the MSVC compiler and Windows mutexes. */ +#undef HAVE_MUTEX_WIN32 + +/* Define to 1 to use the GCC compiler and Windows mutexes. */ +#undef HAVE_MUTEX_WIN32_GCC + +/* Define to 1 to use the GCC compiler and 64-bit x86 assembly language + mutexes. */ +#undef HAVE_MUTEX_X86_64_GCC_ASSEMBLY + +/* Define to 1 to use the GCC compiler and 32-bit x86 assembly language + mutexes. */ +#undef HAVE_MUTEX_X86_GCC_ASSEMBLY + +/* Define to 1 if you have the header file, and it defines `DIR'. */ +#undef HAVE_NDIR_H + +/* Define to 1 if you have the O_DIRECT flag. */ +#undef HAVE_O_DIRECT + +/* Define to 1 if building partitioned database support. */ +#undef HAVE_PARTITION + +/* Define to 1 to enable some kind of performance event monitoring. */ +#undef HAVE_PERFMON + +/* Define to 1 to enable performance event monitoring of *_stat() statistics. + */ +#undef HAVE_PERFMON_STATISTICS + +/* Define to 1 if you have the `pread' function. */ +#undef HAVE_PREAD + +/* Define to 1 if you have the `printf' function. */ +#undef HAVE_PRINTF + +/* Define to 1 if you have the `pstat_getdynamic' function. */ +#undef HAVE_PSTAT_GETDYNAMIC + +/* Define to 1 if it is OK to initialize an already initialized + pthread_cond_t. */ +#undef HAVE_PTHREAD_COND_REINIT_OKAY + +/* Define to 1 if it is OK to initialize an already initialized + pthread_rwlock_t. */ +#undef HAVE_PTHREAD_RWLOCK_REINIT_OKAY + +/* Define to 1 if you have the `pthread_self' function. */ +#undef HAVE_PTHREAD_SELF + +/* Define to 1 if you have the `pthread_yield' function. */ +#undef HAVE_PTHREAD_YIELD + +/* Define to 1 if you have the `pwrite' function. */ +#undef HAVE_PWRITE + +/* Define to 1 if building on QNX. */ +#undef HAVE_QNX + +/* Define to 1 if you have the `qsort' function. */ +#undef HAVE_QSORT + +/* Define to 1 if building Queue access method. */ +#undef HAVE_QUEUE + +/* Define to 1 if you have the `raise' function. */ +#undef HAVE_RAISE + +/* Define to 1 if you have the `rand' function. */ +#undef HAVE_RAND + +/* Define to 1 if you have the `random' function. */ +#undef HAVE_RANDOM + +/* Define to 1 if building only the most basic features. */ +#undef HAVE_RDS_BUILD + +/* Define to 1 if building replication support. */ +#undef HAVE_REPLICATION + +/* Define to 1 if building the Berkeley DB replication framework. */ +#undef HAVE_REPLICATION_THREADS + +/* Define to 1 if you have the `sched_yield' function. */ +#undef HAVE_SCHED_YIELD + +/* Define to 1 if you have the `select' function. */ +#undef HAVE_SELECT + +/* Define to 1 if you have the `setgid' function. */ +#undef HAVE_SETGID + +/* Define to 1 if you have the `setuid' function. */ +#undef HAVE_SETUID + +/* Define to 1 to configure Berkeley DB to use read/write latches. */ +#undef HAVE_SHARED_LATCHES + +/* Define to 1 if shmctl/SHM_LOCK locks down shared memory segments. */ +#undef HAVE_SHMCTL_SHM_LOCK + +/* Define to 1 if you have the `shmget' function. */ +#undef HAVE_SHMGET + +/* Define to 1 if you have the `sigaction' function. */ +#undef HAVE_SIGACTION + +/* Define to 1 if thread identifier type db_threadid_t is integral. */ +#undef HAVE_SIMPLE_THREAD_TYPE + +/* Define to 1 if you have the `snprintf' function. */ +#undef HAVE_SNPRINTF + +/* Define to 1 if you have the `stat' function. */ +#undef HAVE_STAT + +/* Define to 1 if building statistics support. */ +#undef HAVE_STATISTICS + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDINT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDLIB_H + +/* Define to 1 if you have the `strcasecmp' function. */ +#undef HAVE_STRCASECMP + +/* Define to 1 if you have the `strcat' function. */ +#undef HAVE_STRCAT + +/* Define to 1 if you have the `strchr' function. */ +#undef HAVE_STRCHR + +/* Define to 1 if you have the `strdup' function. */ +#undef HAVE_STRDUP + +/* Define to 1 if you have the `strerror' function. */ +#undef HAVE_STRERROR + +/* Define to 1 if you have the `strftime' function. */ +#undef HAVE_STRFTIME + +/* Define to 1 if you have the header file. */ +#undef HAVE_STRINGS_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STRING_H + +/* Define to 1 if building without output message content. */ +#undef HAVE_STRIPPED_MESSAGES + +/* Define to 1 if you have the `strncat' function. */ +#undef HAVE_STRNCAT + +/* Define to 1 if you have the `strncmp' function. */ +#undef HAVE_STRNCMP + +/* Define to 1 if you have the `strrchr' function. */ +#undef HAVE_STRRCHR + +/* Define to 1 if you have the `strsep' function. */ +#undef HAVE_STRSEP + +/* Define to 1 if you have the `strtol' function. */ +#undef HAVE_STRTOL + +/* Define to 1 if you have the `strtoul' function. */ +#undef HAVE_STRTOUL + +/* Define to 1 if `st_blksize' is a member of `struct stat'. */ +#undef HAVE_STRUCT_STAT_ST_BLKSIZE + +/* Define to 1 if you have the `sysconf' function. */ +#undef HAVE_SYSCONF + +/* Define to 1 if port includes files in the Berkeley DB source code. */ +#undef HAVE_SYSTEM_INCLUDE_FILES + +/* Define to 1 if you have the header file, and it defines `DIR'. + */ +#undef HAVE_SYS_DIR_H + +/* Define to 1 if you have the header file, and it defines `DIR'. + */ +#undef HAVE_SYS_NDIR_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_SDT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_SELECT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_SOCKET_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_STAT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_TIME_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_TYPES_H + +/* Define to 1 if you have the `time' function. */ +#undef HAVE_TIME + +/* Define to 1 if building in transaction support. */ +#undef HAVE_TRANSACTIONS + +/* Define to 1 if you have the header file. */ +#undef HAVE_UNISTD_H + +/* Define to 1 if unlink of file with open file descriptors will fail. */ +#undef HAVE_UNLINK_WITH_OPEN_FAILURE + +/* Define to 1 if port includes historic database upgrade support. */ +#undef HAVE_UPGRADE_SUPPORT + +/* Define to 1 if building access method verification support. */ +#undef HAVE_VERIFY + +/* Define to 1 if you have the `vsnprintf' function. */ +#undef HAVE_VSNPRINTF + +/* Define to 1 if building on VxWorks. */ +#undef HAVE_VXWORKS + +/* Define to 1 if you have the `yield' function. */ +#undef HAVE_YIELD + +/* Define to 1 if you have the `_fstati64' function. */ +#undef HAVE__FSTATI64 + +/* Define to the sub-directory in which libtool stores uninstalled libraries. + */ +#undef LT_OBJDIR + +/* Define to the address where bug reports for this package should be sent. */ +#undef PACKAGE_BUGREPORT + +/* Define to the full name of this package. */ +#undef PACKAGE_NAME + +/* Define to the full name and version of this package. */ +#undef PACKAGE_STRING + +/* Define to the one symbol short name of this package. */ +#undef PACKAGE_TARNAME + +/* Define to the home page for this package. */ +#undef PACKAGE_URL + +/* Define to the version of this package. */ +#undef PACKAGE_VERSION + +/* The size of `char', as computed by sizeof. */ +#undef SIZEOF_CHAR + +/* The size of `char *', as computed by sizeof. */ +#undef SIZEOF_CHAR_P + +/* The size of `int', as computed by sizeof. */ +#undef SIZEOF_INT + +/* The size of `long', as computed by sizeof. */ +#undef SIZEOF_LONG + +/* The size of `long long', as computed by sizeof. */ +#undef SIZEOF_LONG_LONG + +/* The size of `short', as computed by sizeof. */ +#undef SIZEOF_SHORT + +/* The size of `size_t', as computed by sizeof. */ +#undef SIZEOF_SIZE_T + +/* The size of `unsigned char', as computed by sizeof. */ +#undef SIZEOF_UNSIGNED_CHAR + +/* The size of `unsigned int', as computed by sizeof. */ +#undef SIZEOF_UNSIGNED_INT + +/* The size of `unsigned long', as computed by sizeof. */ +#undef SIZEOF_UNSIGNED_LONG + +/* The size of `unsigned long long', as computed by sizeof. */ +#undef SIZEOF_UNSIGNED_LONG_LONG + +/* The size of `unsigned short', as computed by sizeof. */ +#undef SIZEOF_UNSIGNED_SHORT + +/* Define to 1 if the `S_IS*' macros in do not work properly. */ +#undef STAT_MACROS_BROKEN + +/* Define to 1 if you have the ANSI C header files. */ +#undef STDC_HEADERS + +/* Define to 1 if you can safely include both and . */ +#undef TIME_WITH_SYS_TIME + +/* Define to 1 to mask harmless uninitialized memory read/writes. */ +#undef UMRW + +/* Number of bits in a file offset, on hosts where this is settable. */ +#undef _FILE_OFFSET_BITS + +/* Define for large files, on AIX-style hosts. */ +#undef _LARGE_FILES + +/* Define to empty if `const' does not conform to ANSI C. */ +#undef const + +/* Define to `__inline__' or `__inline' if that's what the C compiler + calls it, or to nothing if 'inline' is not supported under any name. */ +#ifndef __cplusplus +#undef inline +#endif + +/* type to use in place of socklen_t if not defined */ +#undef socklen_t diff -r 000000000000 -r a1985f14b030 dist/config.sub --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dist/config.sub Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,1771 @@ +#! /bin/sh +# Configuration validation subroutine script. +# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, +# 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, +# 2011 Free Software Foundation, Inc. + +timestamp='2011-11-11' + +# This file is (in principle) common to ALL GNU software. +# The presence of a machine in this file suggests that SOME GNU software +# can handle that machine. It does not imply ALL GNU software can. +# +# This file is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA +# 02110-1301, USA. +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + + +# Please send patches to . Submit a context +# diff and a properly formatted GNU ChangeLog entry. +# +# Configuration subroutine to validate and canonicalize a configuration type. +# Supply the specified configuration type as an argument. +# If it is invalid, we print an error message on stderr and exit with code 1. +# Otherwise, we print the canonical config type on stdout and succeed. + +# You can get the latest version of this script from: +# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub;hb=HEAD + +# This file is supposed to be the same for all GNU packages +# and recognize all the CPU types, system types and aliases +# that are meaningful with *any* GNU software. +# Each package is responsible for reporting which valid configurations +# it does not support. The user should be able to distinguish +# a failure to support a valid configuration from a meaningless +# configuration. + +# The goal of this file is to map all the various variations of a given +# machine specification into a single specification in the form: +# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM +# or in some cases, the newer four-part form: +# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM +# It is wrong to echo any other type of specification. + +me=`echo "$0" | sed -e 's,.*/,,'` + +usage="\ +Usage: $0 [OPTION] CPU-MFR-OPSYS + $0 [OPTION] ALIAS + +Canonicalize a configuration name. + +Operation modes: + -h, --help print this help, then exit + -t, --time-stamp print date of last modification, then exit + -v, --version print version number, then exit + +Report bugs and patches to ." + +version="\ +GNU config.sub ($timestamp) + +Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, +2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free +Software Foundation, Inc. + +This is free software; see the source for copying conditions. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." + +help=" +Try \`$me --help' for more information." + +# Parse command line +while test $# -gt 0 ; do + case $1 in + --time-stamp | --time* | -t ) + echo "$timestamp" ; exit ;; + --version | -v ) + echo "$version" ; exit ;; + --help | --h* | -h ) + echo "$usage"; exit ;; + -- ) # Stop option processing + shift; break ;; + - ) # Use stdin as input. + break ;; + -* ) + echo "$me: invalid option $1$help" + exit 1 ;; + + *local*) + # First pass through any local machine types. + echo $1 + exit ;; + + * ) + break ;; + esac +done + +case $# in + 0) echo "$me: missing argument$help" >&2 + exit 1;; + 1) ;; + *) echo "$me: too many arguments$help" >&2 + exit 1;; +esac + +# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any). +# Here we must recognize all the valid KERNEL-OS combinations. +maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` +case $maybe_os in + nto-qnx* | linux-gnu* | linux-android* | linux-dietlibc | linux-newlib* | \ + linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | \ + knetbsd*-gnu* | netbsd*-gnu* | \ + kopensolaris*-gnu* | \ + storm-chaos* | os2-emx* | rtmk-nova*) + os=-$maybe_os + basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` + ;; + *) + basic_machine=`echo $1 | sed 's/-[^-]*$//'` + if [ $basic_machine != $1 ] + then os=`echo $1 | sed 's/.*-/-/'` + else os=; fi + ;; +esac + +### Let's recognize common machines as not being operating systems so +### that things like config.sub decstation-3100 work. We also +### recognize some manufacturers as not being operating systems, so we +### can provide default operating systems below. +case $os in + -sun*os*) + # Prevent following clause from handling this invalid input. + ;; + -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \ + -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \ + -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \ + -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\ + -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \ + -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \ + -apple | -axis | -knuth | -cray | -microblaze) + os= + basic_machine=$1 + ;; + -bluegene*) + os=-cnk + ;; + -sim | -cisco | -oki | -wec | -winbond) + os= + basic_machine=$1 + ;; + -scout) + ;; + -wrs) + os=-vxworks + basic_machine=$1 + ;; + -chorusos*) + os=-chorusos + basic_machine=$1 + ;; + -chorusrdb) + os=-chorusrdb + basic_machine=$1 + ;; + -hiux*) + os=-hiuxwe2 + ;; + -sco6) + os=-sco5v6 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco5) + os=-sco3.2v5 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco4) + os=-sco3.2v4 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco3.2.[4-9]*) + os=`echo $os | sed -e 's/sco3.2./sco3.2v/'` + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco3.2v[4-9]*) + # Don't forget version if it is 3.2v4 or newer. + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco5v6*) + # Don't forget version if it is 3.2v4 or newer. + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco*) + os=-sco3.2v2 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -udk*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -isc) + os=-isc2.2 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -clix*) + basic_machine=clipper-intergraph + ;; + -isc*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -lynx*) + os=-lynxos + ;; + -ptx*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'` + ;; + -windowsnt*) + os=`echo $os | sed -e 's/windowsnt/winnt/'` + ;; + -psos*) + os=-psos + ;; + -mint | -mint[0-9]*) + basic_machine=m68k-atari + os=-mint + ;; +esac + +# Decode aliases for certain CPU-COMPANY combinations. +case $basic_machine in + # Recognize the basic CPU types without company name. + # Some are omitted here because they have special meanings below. + 1750a | 580 \ + | a29k \ + | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \ + | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \ + | am33_2.0 \ + | arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr | avr32 \ + | be32 | be64 \ + | bfin \ + | c4x | clipper \ + | d10v | d30v | dlx | dsp16xx \ + | epiphany \ + | fido | fr30 | frv \ + | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ + | hexagon \ + | i370 | i860 | i960 | ia64 \ + | ip2k | iq2000 \ + | le32 | le64 \ + | lm32 \ + | m32c | m32r | m32rle | m68000 | m68k | m88k \ + | maxq | mb | microblaze | mcore | mep | metag \ + | mips | mipsbe | mipseb | mipsel | mipsle \ + | mips16 \ + | mips64 | mips64el \ + | mips64octeon | mips64octeonel \ + | mips64orion | mips64orionel \ + | mips64r5900 | mips64r5900el \ + | mips64vr | mips64vrel \ + | mips64vr4100 | mips64vr4100el \ + | mips64vr4300 | mips64vr4300el \ + | mips64vr5000 | mips64vr5000el \ + | mips64vr5900 | mips64vr5900el \ + | mipsisa32 | mipsisa32el \ + | mipsisa32r2 | mipsisa32r2el \ + | mipsisa64 | mipsisa64el \ + | mipsisa64r2 | mipsisa64r2el \ + | mipsisa64sb1 | mipsisa64sb1el \ + | mipsisa64sr71k | mipsisa64sr71kel \ + | mipstx39 | mipstx39el \ + | mn10200 | mn10300 \ + | moxie \ + | mt \ + | msp430 \ + | nds32 | nds32le | nds32be \ + | nios | nios2 \ + | ns16k | ns32k \ + | open8 \ + | or32 \ + | pdp10 | pdp11 | pj | pjl \ + | powerpc | powerpc64 | powerpc64le | powerpcle \ + | pyramid \ + | rl78 | rx \ + | score \ + | sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \ + | sh64 | sh64le \ + | sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \ + | sparcv8 | sparcv9 | sparcv9b | sparcv9v \ + | spu \ + | tahoe | tic4x | tic54x | tic55x | tic6x | tic80 | tron \ + | ubicom32 \ + | v850 | v850e | v850e1 | v850e2 | v850es | v850e2v3 \ + | we32k \ + | x86 | xc16x | xstormy16 | xtensa \ + | z8k | z80) + basic_machine=$basic_machine-unknown + ;; + c54x) + basic_machine=tic54x-unknown + ;; + c55x) + basic_machine=tic55x-unknown + ;; + c6x) + basic_machine=tic6x-unknown + ;; + m6811 | m68hc11 | m6812 | m68hc12 | picochip) + # Motorola 68HC11/12. + basic_machine=$basic_machine-unknown + os=-none + ;; + m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k) + ;; + ms1) + basic_machine=mt-unknown + ;; + + strongarm | thumb | xscale) + basic_machine=arm-unknown + ;; + + xscaleeb) + basic_machine=armeb-unknown + ;; + + xscaleel) + basic_machine=armel-unknown + ;; + + # We use `pc' rather than `unknown' + # because (1) that's what they normally are, and + # (2) the word "unknown" tends to confuse beginning users. + i*86 | x86_64) + basic_machine=$basic_machine-pc + ;; + # Object if more than one company name word. + *-*-*) + echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 + exit 1 + ;; + # Recognize the basic CPU types with company name. + 580-* \ + | a29k-* \ + | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \ + | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \ + | alphapca5[67]-* | alpha64pca5[67]-* | arc-* \ + | arm-* | armbe-* | armle-* | armeb-* | armv*-* \ + | avr-* | avr32-* \ + | be32-* | be64-* \ + | bfin-* | bs2000-* \ + | c[123]* | c30-* | [cjt]90-* | c4x-* \ + | clipper-* | craynv-* | cydra-* \ + | d10v-* | d30v-* | dlx-* \ + | elxsi-* \ + | f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \ + | h8300-* | h8500-* \ + | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ + | hexagon-* \ + | i*86-* | i860-* | i960-* | ia64-* \ + | ip2k-* | iq2000-* \ + | le32-* | le64-* \ + | lm32-* \ + | m32c-* | m32r-* | m32rle-* \ + | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \ + | m88110-* | m88k-* | maxq-* | mcore-* | metag-* | microblaze-* \ + | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \ + | mips16-* \ + | mips64-* | mips64el-* \ + | mips64octeon-* | mips64octeonel-* \ + | mips64orion-* | mips64orionel-* \ + | mips64r5900-* | mips64r5900el-* \ + | mips64vr-* | mips64vrel-* \ + | mips64vr4100-* | mips64vr4100el-* \ + | mips64vr4300-* | mips64vr4300el-* \ + | mips64vr5000-* | mips64vr5000el-* \ + | mips64vr5900-* | mips64vr5900el-* \ + | mipsisa32-* | mipsisa32el-* \ + | mipsisa32r2-* | mipsisa32r2el-* \ + | mipsisa64-* | mipsisa64el-* \ + | mipsisa64r2-* | mipsisa64r2el-* \ + | mipsisa64sb1-* | mipsisa64sb1el-* \ + | mipsisa64sr71k-* | mipsisa64sr71kel-* \ + | mipstx39-* | mipstx39el-* \ + | mmix-* \ + | mt-* \ + | msp430-* \ + | nds32-* | nds32le-* | nds32be-* \ + | nios-* | nios2-* \ + | none-* | np1-* | ns16k-* | ns32k-* \ + | open8-* \ + | orion-* \ + | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ + | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* \ + | pyramid-* \ + | rl78-* | romp-* | rs6000-* | rx-* \ + | sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \ + | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \ + | sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \ + | sparclite-* \ + | sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | sv1-* | sx?-* \ + | tahoe-* \ + | tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \ + | tile*-* \ + | tron-* \ + | ubicom32-* \ + | v850-* | v850e-* | v850e1-* | v850es-* | v850e2-* | v850e2v3-* \ + | vax-* \ + | we32k-* \ + | x86-* | x86_64-* | xc16x-* | xps100-* \ + | xstormy16-* | xtensa*-* \ + | ymp-* \ + | z8k-* | z80-*) + ;; + # Recognize the basic CPU types without company name, with glob match. + xtensa*) + basic_machine=$basic_machine-unknown + ;; + # Recognize the various machine names and aliases which stand + # for a CPU type and a company and sometimes even an OS. + 386bsd) + basic_machine=i386-unknown + os=-bsd + ;; + 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc) + basic_machine=m68000-att + ;; + 3b*) + basic_machine=we32k-att + ;; + a29khif) + basic_machine=a29k-amd + os=-udi + ;; + abacus) + basic_machine=abacus-unknown + ;; + adobe68k) + basic_machine=m68010-adobe + os=-scout + ;; + alliant | fx80) + basic_machine=fx80-alliant + ;; + altos | altos3068) + basic_machine=m68k-altos + ;; + am29k) + basic_machine=a29k-none + os=-bsd + ;; + amd64) + basic_machine=x86_64-pc + ;; + amd64-*) + basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + amdahl) + basic_machine=580-amdahl + os=-sysv + ;; + amiga | amiga-*) + basic_machine=m68k-unknown + ;; + amigaos | amigados) + basic_machine=m68k-unknown + os=-amigaos + ;; + amigaunix | amix) + basic_machine=m68k-unknown + os=-sysv4 + ;; + apollo68) + basic_machine=m68k-apollo + os=-sysv + ;; + apollo68bsd) + basic_machine=m68k-apollo + os=-bsd + ;; + aros) + basic_machine=i386-pc + os=-aros + ;; + aux) + basic_machine=m68k-apple + os=-aux + ;; + balance) + basic_machine=ns32k-sequent + os=-dynix + ;; + blackfin) + basic_machine=bfin-unknown + os=-linux + ;; + blackfin-*) + basic_machine=bfin-`echo $basic_machine | sed 's/^[^-]*-//'` + os=-linux + ;; + bluegene*) + basic_machine=powerpc-ibm + os=-cnk + ;; + c54x-*) + basic_machine=tic54x-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + c55x-*) + basic_machine=tic55x-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + c6x-*) + basic_machine=tic6x-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + c90) + basic_machine=c90-cray + os=-unicos + ;; + cegcc) + basic_machine=arm-unknown + os=-cegcc + ;; + convex-c1) + basic_machine=c1-convex + os=-bsd + ;; + convex-c2) + basic_machine=c2-convex + os=-bsd + ;; + convex-c32) + basic_machine=c32-convex + os=-bsd + ;; + convex-c34) + basic_machine=c34-convex + os=-bsd + ;; + convex-c38) + basic_machine=c38-convex + os=-bsd + ;; + cray | j90) + basic_machine=j90-cray + os=-unicos + ;; + craynv) + basic_machine=craynv-cray + os=-unicosmp + ;; + cr16 | cr16-*) + basic_machine=cr16-unknown + os=-elf + ;; + crds | unos) + basic_machine=m68k-crds + ;; + crisv32 | crisv32-* | etraxfs*) + basic_machine=crisv32-axis + ;; + cris | cris-* | etrax*) + basic_machine=cris-axis + ;; + crx) + basic_machine=crx-unknown + os=-elf + ;; + da30 | da30-*) + basic_machine=m68k-da30 + ;; + decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn) + basic_machine=mips-dec + ;; + decsystem10* | dec10*) + basic_machine=pdp10-dec + os=-tops10 + ;; + decsystem20* | dec20*) + basic_machine=pdp10-dec + os=-tops20 + ;; + delta | 3300 | motorola-3300 | motorola-delta \ + | 3300-motorola | delta-motorola) + basic_machine=m68k-motorola + ;; + delta88) + basic_machine=m88k-motorola + os=-sysv3 + ;; + dicos) + basic_machine=i686-pc + os=-dicos + ;; + djgpp) + basic_machine=i586-pc + os=-msdosdjgpp + ;; + dpx20 | dpx20-*) + basic_machine=rs6000-bull + os=-bosx + ;; + dpx2* | dpx2*-bull) + basic_machine=m68k-bull + os=-sysv3 + ;; + ebmon29k) + basic_machine=a29k-amd + os=-ebmon + ;; + elxsi) + basic_machine=elxsi-elxsi + os=-bsd + ;; + encore | umax | mmax) + basic_machine=ns32k-encore + ;; + es1800 | OSE68k | ose68k | ose | OSE) + basic_machine=m68k-ericsson + os=-ose + ;; + fx2800) + basic_machine=i860-alliant + ;; + genix) + basic_machine=ns32k-ns + ;; + gmicro) + basic_machine=tron-gmicro + os=-sysv + ;; + go32) + basic_machine=i386-pc + os=-go32 + ;; + h3050r* | hiux*) + basic_machine=hppa1.1-hitachi + os=-hiuxwe2 + ;; + h8300hms) + basic_machine=h8300-hitachi + os=-hms + ;; + h8300xray) + basic_machine=h8300-hitachi + os=-xray + ;; + h8500hms) + basic_machine=h8500-hitachi + os=-hms + ;; + harris) + basic_machine=m88k-harris + os=-sysv3 + ;; + hp300-*) + basic_machine=m68k-hp + ;; + hp300bsd) + basic_machine=m68k-hp + os=-bsd + ;; + hp300hpux) + basic_machine=m68k-hp + os=-hpux + ;; + hp3k9[0-9][0-9] | hp9[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hp9k2[0-9][0-9] | hp9k31[0-9]) + basic_machine=m68000-hp + ;; + hp9k3[2-9][0-9]) + basic_machine=m68k-hp + ;; + hp9k6[0-9][0-9] | hp6[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hp9k7[0-79][0-9] | hp7[0-79][0-9]) + basic_machine=hppa1.1-hp + ;; + hp9k78[0-9] | hp78[0-9]) + # FIXME: really hppa2.0-hp + basic_machine=hppa1.1-hp + ;; + hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893) + # FIXME: really hppa2.0-hp + basic_machine=hppa1.1-hp + ;; + hp9k8[0-9][13679] | hp8[0-9][13679]) + basic_machine=hppa1.1-hp + ;; + hp9k8[0-9][0-9] | hp8[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hppa-next) + os=-nextstep3 + ;; + hppaosf) + basic_machine=hppa1.1-hp + os=-osf + ;; + hppro) + basic_machine=hppa1.1-hp + os=-proelf + ;; + i370-ibm* | ibm*) + basic_machine=i370-ibm + ;; +# I'm not sure what "Sysv32" means. Should this be sysv3.2? + i*86v32) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv32 + ;; + i*86v4*) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv4 + ;; + i*86v) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv + ;; + i*86sol2) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-solaris2 + ;; + i386mach) + basic_machine=i386-mach + os=-mach + ;; + i386-vsta | vsta) + basic_machine=i386-unknown + os=-vsta + ;; + iris | iris4d) + basic_machine=mips-sgi + case $os in + -irix*) + ;; + *) + os=-irix4 + ;; + esac + ;; + isi68 | isi) + basic_machine=m68k-isi + os=-sysv + ;; + m68knommu) + basic_machine=m68k-unknown + os=-linux + ;; + m68knommu-*) + basic_machine=m68k-`echo $basic_machine | sed 's/^[^-]*-//'` + os=-linux + ;; + m88k-omron*) + basic_machine=m88k-omron + ;; + magnum | m3230) + basic_machine=mips-mips + os=-sysv + ;; + merlin) + basic_machine=ns32k-utek + os=-sysv + ;; + microblaze) + basic_machine=microblaze-xilinx + ;; + mingw32) + basic_machine=i386-pc + os=-mingw32 + ;; + mingw32ce) + basic_machine=arm-unknown + os=-mingw32ce + ;; + miniframe) + basic_machine=m68000-convergent + ;; + *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*) + basic_machine=m68k-atari + os=-mint + ;; + mips3*-*) + basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'` + ;; + mips3*) + basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown + ;; + monitor) + basic_machine=m68k-rom68k + os=-coff + ;; + morphos) + basic_machine=powerpc-unknown + os=-morphos + ;; + msdos) + basic_machine=i386-pc + os=-msdos + ;; + ms1-*) + basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'` + ;; + msys) + basic_machine=i386-pc + os=-msys + ;; + mvs) + basic_machine=i370-ibm + os=-mvs + ;; + nacl) + basic_machine=le32-unknown + os=-nacl + ;; + ncr3000) + basic_machine=i486-ncr + os=-sysv4 + ;; + netbsd386) + basic_machine=i386-unknown + os=-netbsd + ;; + netwinder) + basic_machine=armv4l-rebel + os=-linux + ;; + news | news700 | news800 | news900) + basic_machine=m68k-sony + os=-newsos + ;; + news1000) + basic_machine=m68030-sony + os=-newsos + ;; + news-3600 | risc-news) + basic_machine=mips-sony + os=-newsos + ;; + necv70) + basic_machine=v70-nec + os=-sysv + ;; + next | m*-next ) + basic_machine=m68k-next + case $os in + -nextstep* ) + ;; + -ns2*) + os=-nextstep2 + ;; + *) + os=-nextstep3 + ;; + esac + ;; + nh3000) + basic_machine=m68k-harris + os=-cxux + ;; + nh[45]000) + basic_machine=m88k-harris + os=-cxux + ;; + nindy960) + basic_machine=i960-intel + os=-nindy + ;; + mon960) + basic_machine=i960-intel + os=-mon960 + ;; + nonstopux) + basic_machine=mips-compaq + os=-nonstopux + ;; + np1) + basic_machine=np1-gould + ;; + neo-tandem) + basic_machine=neo-tandem + ;; + nse-tandem) + basic_machine=nse-tandem + ;; + nsr-tandem) + basic_machine=nsr-tandem + ;; + op50n-* | op60c-*) + basic_machine=hppa1.1-oki + os=-proelf + ;; + openrisc | openrisc-*) + basic_machine=or32-unknown + ;; + os400) + basic_machine=powerpc-ibm + os=-os400 + ;; + OSE68000 | ose68000) + basic_machine=m68000-ericsson + os=-ose + ;; + os68k) + basic_machine=m68k-none + os=-os68k + ;; + pa-hitachi) + basic_machine=hppa1.1-hitachi + os=-hiuxwe2 + ;; + paragon) + basic_machine=i860-intel + os=-osf + ;; + parisc) + basic_machine=hppa-unknown + os=-linux + ;; + parisc-*) + basic_machine=hppa-`echo $basic_machine | sed 's/^[^-]*-//'` + os=-linux + ;; + pbd) + basic_machine=sparc-tti + ;; + pbb) + basic_machine=m68k-tti + ;; + pc532 | pc532-*) + basic_machine=ns32k-pc532 + ;; + pc98) + basic_machine=i386-pc + ;; + pc98-*) + basic_machine=i386-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentium | p5 | k5 | k6 | nexgen | viac3) + basic_machine=i586-pc + ;; + pentiumpro | p6 | 6x86 | athlon | athlon_*) + basic_machine=i686-pc + ;; + pentiumii | pentium2 | pentiumiii | pentium3) + basic_machine=i686-pc + ;; + pentium4) + basic_machine=i786-pc + ;; + pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*) + basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentiumpro-* | p6-* | 6x86-* | athlon-*) + basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*) + basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentium4-*) + basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pn) + basic_machine=pn-gould + ;; + power) basic_machine=power-ibm + ;; + ppc | ppcbe) basic_machine=powerpc-unknown + ;; + ppc-* | ppcbe-*) + basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppcle | powerpclittle | ppc-le | powerpc-little) + basic_machine=powerpcle-unknown + ;; + ppcle-* | powerpclittle-*) + basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppc64) basic_machine=powerpc64-unknown + ;; + ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppc64le | powerpc64little | ppc64-le | powerpc64-little) + basic_machine=powerpc64le-unknown + ;; + ppc64le-* | powerpc64little-*) + basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ps2) + basic_machine=i386-ibm + ;; + pw32) + basic_machine=i586-unknown + os=-pw32 + ;; + rdos) + basic_machine=i386-pc + os=-rdos + ;; + rom68k) + basic_machine=m68k-rom68k + os=-coff + ;; + rm[46]00) + basic_machine=mips-siemens + ;; + rtpc | rtpc-*) + basic_machine=romp-ibm + ;; + s390 | s390-*) + basic_machine=s390-ibm + ;; + s390x | s390x-*) + basic_machine=s390x-ibm + ;; + sa29200) + basic_machine=a29k-amd + os=-udi + ;; + sb1) + basic_machine=mipsisa64sb1-unknown + ;; + sb1el) + basic_machine=mipsisa64sb1el-unknown + ;; + sde) + basic_machine=mipsisa32-sde + os=-elf + ;; + sei) + basic_machine=mips-sei + os=-seiux + ;; + sequent) + basic_machine=i386-sequent + ;; + sh) + basic_machine=sh-hitachi + os=-hms + ;; + sh5el) + basic_machine=sh5le-unknown + ;; + sh64) + basic_machine=sh64-unknown + ;; + sparclite-wrs | simso-wrs) + basic_machine=sparclite-wrs + os=-vxworks + ;; + sps7) + basic_machine=m68k-bull + os=-sysv2 + ;; + spur) + basic_machine=spur-unknown + ;; + st2000) + basic_machine=m68k-tandem + ;; + stratus) + basic_machine=i860-stratus + os=-sysv4 + ;; + strongarm-* | thumb-*) + basic_machine=arm-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + sun2) + basic_machine=m68000-sun + ;; + sun2os3) + basic_machine=m68000-sun + os=-sunos3 + ;; + sun2os4) + basic_machine=m68000-sun + os=-sunos4 + ;; + sun3os3) + basic_machine=m68k-sun + os=-sunos3 + ;; + sun3os4) + basic_machine=m68k-sun + os=-sunos4 + ;; + sun4os3) + basic_machine=sparc-sun + os=-sunos3 + ;; + sun4os4) + basic_machine=sparc-sun + os=-sunos4 + ;; + sun4sol2) + basic_machine=sparc-sun + os=-solaris2 + ;; + sun3 | sun3-*) + basic_machine=m68k-sun + ;; + sun4) + basic_machine=sparc-sun + ;; + sun386 | sun386i | roadrunner) + basic_machine=i386-sun + ;; + sv1) + basic_machine=sv1-cray + os=-unicos + ;; + symmetry) + basic_machine=i386-sequent + os=-dynix + ;; + t3e) + basic_machine=alphaev5-cray + os=-unicos + ;; + t90) + basic_machine=t90-cray + os=-unicos + ;; + tile*) + basic_machine=$basic_machine-unknown + os=-linux-gnu + ;; + tx39) + basic_machine=mipstx39-unknown + ;; + tx39el) + basic_machine=mipstx39el-unknown + ;; + toad1) + basic_machine=pdp10-xkl + os=-tops20 + ;; + tower | tower-32) + basic_machine=m68k-ncr + ;; + tpf) + basic_machine=s390x-ibm + os=-tpf + ;; + udi29k) + basic_machine=a29k-amd + os=-udi + ;; + ultra3) + basic_machine=a29k-nyu + os=-sym1 + ;; + v810 | necv810) + basic_machine=v810-nec + os=-none + ;; + vaxv) + basic_machine=vax-dec + os=-sysv + ;; + vms) + basic_machine=vax-dec + os=-vms + ;; + vpp*|vx|vx-*) + basic_machine=f301-fujitsu + ;; + vxworks960) + basic_machine=i960-wrs + os=-vxworks + ;; + vxworks68) + basic_machine=m68k-wrs + os=-vxworks + ;; + vxworks29k) + basic_machine=a29k-wrs + os=-vxworks + ;; + w65*) + basic_machine=w65-wdc + os=-none + ;; + w89k-*) + basic_machine=hppa1.1-winbond + os=-proelf + ;; + xbox) + basic_machine=i686-pc + os=-mingw32 + ;; + xps | xps100) + basic_machine=xps100-honeywell + ;; + xscale-* | xscalee[bl]-*) + basic_machine=`echo $basic_machine | sed 's/^xscale/arm/'` + ;; + ymp) + basic_machine=ymp-cray + os=-unicos + ;; + z8k-*-coff) + basic_machine=z8k-unknown + os=-sim + ;; + z80-*-coff) + basic_machine=z80-unknown + os=-sim + ;; + none) + basic_machine=none-none + os=-none + ;; + +# Here we handle the default manufacturer of certain CPU types. It is in +# some cases the only manufacturer, in others, it is the most popular. + w89k) + basic_machine=hppa1.1-winbond + ;; + op50n) + basic_machine=hppa1.1-oki + ;; + op60c) + basic_machine=hppa1.1-oki + ;; + romp) + basic_machine=romp-ibm + ;; + mmix) + basic_machine=mmix-knuth + ;; + rs6000) + basic_machine=rs6000-ibm + ;; + vax) + basic_machine=vax-dec + ;; + pdp10) + # there are many clones, so DEC is not a safe bet + basic_machine=pdp10-unknown + ;; + pdp11) + basic_machine=pdp11-dec + ;; + we32k) + basic_machine=we32k-att + ;; + sh[1234] | sh[24]a | sh[24]aeb | sh[34]eb | sh[1234]le | sh[23]ele) + basic_machine=sh-unknown + ;; + sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v) + basic_machine=sparc-sun + ;; + cydra) + basic_machine=cydra-cydrome + ;; + orion) + basic_machine=orion-highlevel + ;; + orion105) + basic_machine=clipper-highlevel + ;; + mac | mpw | mac-mpw) + basic_machine=m68k-apple + ;; + pmac | pmac-mpw) + basic_machine=powerpc-apple + ;; + *-unknown) + # Make sure to match an already-canonicalized machine name. + ;; + *) + echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 + exit 1 + ;; +esac + +# Here we canonicalize certain aliases for manufacturers. +case $basic_machine in + *-digital*) + basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'` + ;; + *-commodore*) + basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'` + ;; + *) + ;; +esac + +# Decode manufacturer-specific aliases for certain operating systems. + +if [ x"$os" != x"" ] +then +case $os in + # First match some system type aliases + # that might get confused with valid system types. + # -solaris* is a basic system type, with this one exception. + -auroraux) + os=-auroraux + ;; + -solaris1 | -solaris1.*) + os=`echo $os | sed -e 's|solaris1|sunos4|'` + ;; + -solaris) + os=-solaris2 + ;; + -svr4*) + os=-sysv4 + ;; + -unixware*) + os=-sysv4.2uw + ;; + -gnu/linux*) + os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'` + ;; + # First accept the basic system types. + # The portable systems comes first. + # Each alternative MUST END IN A *, to match a version number. + # -sysv* is not here because it comes later, after sysvr4. + -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \ + | -*vms* | -sco* | -esix* | -isc* | -aix* | -cnk* | -sunos | -sunos[34]*\ + | -hpux* | -unos* | -osf* | -luna* | -dgux* | -auroraux* | -solaris* \ + | -sym* | -kopensolaris* \ + | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \ + | -aos* | -aros* \ + | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ + | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ + | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \ + | -openbsd* | -solidbsd* \ + | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \ + | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \ + | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ + | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ + | -chorusos* | -chorusrdb* | -cegcc* \ + | -cygwin* | -msys* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ + | -mingw32* | -linux-gnu* | -linux-android* \ + | -linux-newlib* | -linux-uclibc* \ + | -uxpv* | -beos* | -mpeix* | -udk* \ + | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \ + | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \ + | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \ + | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \ + | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \ + | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \ + | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es*) + # Remember, each alternative MUST END IN *, to match a version number. + ;; + -qnx*) + case $basic_machine in + x86-* | i*86-*) + ;; + *) + os=-nto$os + ;; + esac + ;; + -nto-qnx*) + ;; + -nto*) + os=`echo $os | sed -e 's|nto|nto-qnx|'` + ;; + -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \ + | -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \ + | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*) + ;; + -mac*) + os=`echo $os | sed -e 's|mac|macos|'` + ;; + -linux-dietlibc) + os=-linux-dietlibc + ;; + -linux*) + os=`echo $os | sed -e 's|linux|linux-gnu|'` + ;; + -sunos5*) + os=`echo $os | sed -e 's|sunos5|solaris2|'` + ;; + -sunos6*) + os=`echo $os | sed -e 's|sunos6|solaris3|'` + ;; + -opened*) + os=-openedition + ;; + -os400*) + os=-os400 + ;; + -wince*) + os=-wince + ;; + -osfrose*) + os=-osfrose + ;; + -osf*) + os=-osf + ;; + -utek*) + os=-bsd + ;; + -dynix*) + os=-bsd + ;; + -acis*) + os=-aos + ;; + -atheos*) + os=-atheos + ;; + -syllable*) + os=-syllable + ;; + -386bsd) + os=-bsd + ;; + -ctix* | -uts*) + os=-sysv + ;; + -nova*) + os=-rtmk-nova + ;; + -ns2 ) + os=-nextstep2 + ;; + -nsk*) + os=-nsk + ;; + # Preserve the version number of sinix5. + -sinix5.*) + os=`echo $os | sed -e 's|sinix|sysv|'` + ;; + -sinix*) + os=-sysv4 + ;; + -tpf*) + os=-tpf + ;; + -triton*) + os=-sysv3 + ;; + -oss*) + os=-sysv3 + ;; + -svr4) + os=-sysv4 + ;; + -svr3) + os=-sysv3 + ;; + -sysvr4) + os=-sysv4 + ;; + # This must come after -sysvr4. + -sysv*) + ;; + -ose*) + os=-ose + ;; + -es1800*) + os=-ose + ;; + -xenix) + os=-xenix + ;; + -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) + os=-mint + ;; + -aros*) + os=-aros + ;; + -kaos*) + os=-kaos + ;; + -zvmoe) + os=-zvmoe + ;; + -dicos*) + os=-dicos + ;; + -nacl*) + ;; + -none) + ;; + *) + # Get rid of the `-' at the beginning of $os. + os=`echo $os | sed 's/[^-]*-//'` + echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2 + exit 1 + ;; +esac +else + +# Here we handle the default operating systems that come with various machines. +# The value should be what the vendor currently ships out the door with their +# machine or put another way, the most popular os provided with the machine. + +# Note that if you're going to try to match "-MANUFACTURER" here (say, +# "-sun"), then you have to tell the case statement up towards the top +# that MANUFACTURER isn't an operating system. Otherwise, code above +# will signal an error saying that MANUFACTURER isn't an operating +# system, and we'll never get to this point. + +case $basic_machine in + score-*) + os=-elf + ;; + spu-*) + os=-elf + ;; + *-acorn) + os=-riscix1.2 + ;; + arm*-rebel) + os=-linux + ;; + arm*-semi) + os=-aout + ;; + c4x-* | tic4x-*) + os=-coff + ;; + tic54x-*) + os=-coff + ;; + tic55x-*) + os=-coff + ;; + tic6x-*) + os=-coff + ;; + # This must come before the *-dec entry. + pdp10-*) + os=-tops20 + ;; + pdp11-*) + os=-none + ;; + *-dec | vax-*) + os=-ultrix4.2 + ;; + m68*-apollo) + os=-domain + ;; + i386-sun) + os=-sunos4.0.2 + ;; + m68000-sun) + os=-sunos3 + # This also exists in the configure program, but was not the + # default. + # os=-sunos4 + ;; + m68*-cisco) + os=-aout + ;; + mep-*) + os=-elf + ;; + mips*-cisco) + os=-elf + ;; + mips*-*) + os=-elf + ;; + or32-*) + os=-coff + ;; + *-tti) # must be before sparc entry or we get the wrong os. + os=-sysv3 + ;; + sparc-* | *-sun) + os=-sunos4.1.1 + ;; + *-be) + os=-beos + ;; + *-haiku) + os=-haiku + ;; + *-ibm) + os=-aix + ;; + *-knuth) + os=-mmixware + ;; + *-wec) + os=-proelf + ;; + *-winbond) + os=-proelf + ;; + *-oki) + os=-proelf + ;; + *-hp) + os=-hpux + ;; + *-hitachi) + os=-hiux + ;; + i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent) + os=-sysv + ;; + *-cbm) + os=-amigaos + ;; + *-dg) + os=-dgux + ;; + *-dolphin) + os=-sysv3 + ;; + m68k-ccur) + os=-rtu + ;; + m88k-omron*) + os=-luna + ;; + *-next ) + os=-nextstep + ;; + *-sequent) + os=-ptx + ;; + *-crds) + os=-unos + ;; + *-ns) + os=-genix + ;; + i370-*) + os=-mvs + ;; + *-next) + os=-nextstep3 + ;; + *-gould) + os=-sysv + ;; + *-highlevel) + os=-bsd + ;; + *-encore) + os=-bsd + ;; + *-sgi) + os=-irix + ;; + *-siemens) + os=-sysv4 + ;; + *-masscomp) + os=-rtu + ;; + f30[01]-fujitsu | f700-fujitsu) + os=-uxpv + ;; + *-rom68k) + os=-coff + ;; + *-*bug) + os=-coff + ;; + *-apple) + os=-macos + ;; + *-atari*) + os=-mint + ;; + *) + os=-none + ;; +esac +fi + +# Here we handle the case where we know the os, and the CPU type, but not the +# manufacturer. We pick the logical manufacturer. +vendor=unknown +case $basic_machine in + *-unknown) + case $os in + -riscix*) + vendor=acorn + ;; + -sunos*) + vendor=sun + ;; + -cnk*|-aix*) + vendor=ibm + ;; + -beos*) + vendor=be + ;; + -hpux*) + vendor=hp + ;; + -mpeix*) + vendor=hp + ;; + -hiux*) + vendor=hitachi + ;; + -unos*) + vendor=crds + ;; + -dgux*) + vendor=dg + ;; + -luna*) + vendor=omron + ;; + -genix*) + vendor=ns + ;; + -mvs* | -opened*) + vendor=ibm + ;; + -os400*) + vendor=ibm + ;; + -ptx*) + vendor=sequent + ;; + -tpf*) + vendor=ibm + ;; + -vxsim* | -vxworks* | -windiss*) + vendor=wrs + ;; + -aux*) + vendor=apple + ;; + -hms*) + vendor=hitachi + ;; + -mpw* | -macos*) + vendor=apple + ;; + -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) + vendor=atari + ;; + -vos*) + vendor=stratus + ;; + esac + basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"` + ;; +esac + +echo $basic_machine$os +exit + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "timestamp='" +# time-stamp-format: "%:y-%02m-%02d" +# time-stamp-end: "'" +# End: diff -r 000000000000 -r a1985f14b030 dist/configure --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dist/configure Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,27505 @@ +#! /bin/sh +# Guess values for system-dependent variables and create Makefiles. +# Generated by GNU Autoconf 2.68 for Berkeley DB 5.4.0. +# +# Report bugs to . +# +# +# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, +# 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 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 more Bourne compatible +DUALCASE=1; export DUALCASE # for MKS sh +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : + emulate sh + NULLCMD=: + # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else + case `(set -o) 2>/dev/null` in #( + *posix*) : + set -o posix ;; #( + *) : + ;; +esac +fi + + +as_nl=' +' +export as_nl +# Printing a long string crashes Solaris 7 /usr/bin/printf. +as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo +# Prefer a ksh shell builtin over an external printf program on Solaris, +# but without wasting forks for bash or zsh. +if test -z "$BASH_VERSION$ZSH_VERSION" \ + && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='print -r --' + as_echo_n='print -rn --' +elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='printf %s\n' + as_echo_n='printf %s' +else + if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then + as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' + as_echo_n='/usr/ucb/echo -n' + else + as_echo_body='eval expr "X$1" : "X\\(.*\\)"' + as_echo_n_body='eval + arg=$1; + case $arg in #( + *"$as_nl"*) + expr "X$arg" : "X\\(.*\\)$as_nl"; + arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; + esac; + expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" + ' + export as_echo_n_body + as_echo_n='sh -c $as_echo_n_body as_echo' + fi + export as_echo_body + as_echo='sh -c $as_echo_body as_echo' +fi + +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + PATH_SEPARATOR=: + (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { + (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || + PATH_SEPARATOR=';' + } +fi + + +# IFS +# We need space, tab and new line, in precisely that order. Quoting is +# there to prevent editors from complaining about space-tab. +# (If _AS_PATH_WALK were called with IFS unset, it would disable word +# splitting by setting IFS to empty value.) +IFS=" "" $as_nl" + +# Find who we are. Look in the path if we contain no directory separator. +as_myself= +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 +IFS=$as_save_IFS + + ;; +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 + $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 + exit 1 +fi + +# Unset variables that we do not need and which cause bugs (e.g. in +# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" +# suppresses any "Segmentation fault" message there. '((' could +# trigger a bug in pdksh 5.2.14. +for as_var in BASH_ENV ENV MAIL MAILPATH +do eval test x\${$as_var+set} = xset \ + && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : +done +PS1='$ ' +PS2='> ' +PS4='+ ' + +# NLS nuisances. +LC_ALL=C +export LC_ALL +LANGUAGE=C +export LANGUAGE + +# CDPATH. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + +if test "x$CONFIG_SHELL" = x; then + as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then : + emulate sh + NULLCMD=: + # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which + # is contrary to our usage. Disable this feature. + alias -g '\${1+\"\$@\"}'='\"\$@\"' + setopt NO_GLOB_SUBST +else + case \`(set -o) 2>/dev/null\` in #( + *posix*) : + set -o posix ;; #( + *) : + ;; +esac +fi +" + as_required="as_fn_return () { (exit \$1); } +as_fn_success () { as_fn_return 0; } +as_fn_failure () { as_fn_return 1; } +as_fn_ret_success () { return 0; } +as_fn_ret_failure () { return 1; } + +exitcode=0 +as_fn_success || { exitcode=1; echo as_fn_success failed.; } +as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; } +as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; } +as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; } +if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then : + +else + exitcode=1; echo positional parameters were not saved. +fi +test x\$exitcode = x0 || exit 1" + as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO + as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO + eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" && + test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1 + + test -n \"\${ZSH_VERSION+set}\${BASH_VERSION+set}\" || ( + ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' + ECHO=\$ECHO\$ECHO\$ECHO\$ECHO\$ECHO + ECHO=\$ECHO\$ECHO\$ECHO\$ECHO\$ECHO\$ECHO + PATH=/empty FPATH=/empty; export PATH FPATH + test \"X\`printf %s \$ECHO\`\" = \"X\$ECHO\" \\ + || test \"X\`print -r -- \$ECHO\`\" = \"X\$ECHO\" ) || exit 1 +test \$(( 1 + 1 )) = 2 || exit 1" + if (eval "$as_required") 2>/dev/null; then : + as_have_required=yes +else + as_have_required=no +fi + if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then : + +else + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +as_found=false +for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + as_found=: + case $as_dir in #( + /*) + for as_base in sh bash ksh sh5; do + # Try only shells that exist, to save several forks. + as_shell=$as_dir/$as_base + if { test -f "$as_shell" || test -f "$as_shell.exe"; } && + { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then : + CONFIG_SHELL=$as_shell as_have_required=yes + if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then : + break 2 +fi +fi + done;; + esac + as_found=false +done +$as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } && + { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then : + CONFIG_SHELL=$SHELL as_have_required=yes +fi; } +IFS=$as_save_IFS + + + if test "x$CONFIG_SHELL" != x; then : + # We cannot yet assume a decent shell, so we have to provide a + # neutralization value for shells without unset; and this also + # works around shells that cannot unset nonexistent variables. + # Preserve -v and -x to the replacement shell. + BASH_ENV=/dev/null + ENV=/dev/null + (unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV + export CONFIG_SHELL + case $- in # (((( + *v*x* | *x*v* ) as_opts=-vx ;; + *v* ) as_opts=-v ;; + *x* ) as_opts=-x ;; + * ) as_opts= ;; + esac + exec "$CONFIG_SHELL" $as_opts "$as_myself" ${1+"$@"} +fi + + if test x$as_have_required = xno; then : + $as_echo "$0: This script requires a shell more modern than all" + $as_echo "$0: the shells that I found on your system." + if test x${ZSH_VERSION+set} = xset ; then + $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should" + $as_echo "$0: be upgraded to zsh 4.3.4 or later." + else + $as_echo "$0: Please tell bug-autoconf@gnu.org and Oracle Technology +$0: Network Berkeley DB forum about your system, including +$0: any error possibly output before this message. Then +$0: install a modern shell, or manually run the script +$0: under such a shell if you do have one." + fi + exit 1 +fi +fi +fi +SHELL=${CONFIG_SHELL-/bin/sh} +export SHELL +# Unset more variables known to interfere with behavior of common tools. +CLICOLOR_FORCE= GREP_OPTIONS= +unset CLICOLOR_FORCE GREP_OPTIONS + +## --------------------- ## +## M4sh Shell Functions. ## +## --------------------- ## +# as_fn_unset VAR +# --------------- +# Portably unset VAR. +as_fn_unset () +{ + { eval $1=; unset $1;} +} +as_unset=as_fn_unset + +# as_fn_set_status STATUS +# ----------------------- +# Set $? to STATUS, without forking. +as_fn_set_status () +{ + return $1 +} # as_fn_set_status + +# as_fn_exit STATUS +# ----------------- +# Exit the shell with STATUS, even in a "trap 0" or "set -e" context. +as_fn_exit () +{ + set +e + as_fn_set_status $1 + exit $1 +} # as_fn_exit + +# as_fn_mkdir_p +# ------------- +# Create "$as_dir" as a directory, including parents if necessary. +as_fn_mkdir_p () +{ + + case $as_dir in #( + -*) as_dir=./$as_dir;; + esac + test -d "$as_dir" || eval $as_mkdir_p || { + as_dirs= + while :; do + case $as_dir in #( + *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( + *) as_qdir=$as_dir;; + esac + as_dirs="'$as_qdir' $as_dirs" + as_dir=`$as_dirname -- "$as_dir" || +$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_dir" : 'X\(//\)[^/]' \| \ + X"$as_dir" : 'X\(//\)$' \| \ + X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$as_dir" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + test -d "$as_dir" && break + done + test -z "$as_dirs" || eval "mkdir $as_dirs" + } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" + + +} # as_fn_mkdir_p +# as_fn_append VAR VALUE +# ---------------------- +# Append the text in VALUE to the end of the definition contained in VAR. Take +# advantage of any shell optimizations that allow amortized linear growth over +# repeated appends, instead of the typical quadratic growth present in naive +# implementations. +if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : + eval 'as_fn_append () + { + eval $1+=\$2 + }' +else + as_fn_append () + { + eval $1=\$$1\$2 + } +fi # as_fn_append + +# as_fn_arith ARG... +# ------------------ +# Perform arithmetic evaluation on the ARGs, and store the result in the +# global $as_val. Take advantage of shells that can avoid forks. The arguments +# must be portable across $(()) and expr. +if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : + eval 'as_fn_arith () + { + as_val=$(( $* )) + }' +else + as_fn_arith () + { + as_val=`expr "$@" || test $? -eq 1` + } +fi # as_fn_arith + + +# as_fn_error STATUS ERROR [LINENO LOG_FD] +# ---------------------------------------- +# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are +# provided, also output the error to LOG_FD, referencing LINENO. Then exit the +# script with STATUS, using 1 if that was 0. +as_fn_error () +{ + as_status=$1; test $as_status -eq 0 && as_status=1 + if test "$4"; then + as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 + fi + $as_echo "$as_me: error: $2" >&2 + as_fn_exit $as_status +} # as_fn_error + +if expr a : '\(a\)' >/dev/null 2>&1 && + test "X`expr 00001 : '.*\(...\)'`" = X001; 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 + +if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then + as_dirname=dirname +else + as_dirname=false +fi + +as_me=`$as_basename -- "$0" || +$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X/"$0" | + sed '/^.*\/\([^/][^/]*\)\/*$/{ + s//\1/ + q + } + /^X\/\(\/\/\)$/{ + s//\1/ + q + } + /^X\/\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + +# 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 + + + as_lineno_1=$LINENO as_lineno_1a=$LINENO + as_lineno_2=$LINENO as_lineno_2a=$LINENO + eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" && + test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || { + # Blame Lee E. McMahon (1931-1989) for sed's syntax. :-) + sed -n ' + p + /[$]LINENO/= + ' <$as_myself | + sed ' + s/[$]LINENO.*/&-/ + t lineno + b + :lineno + N + :loop + s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/ + t loop + s/-\n.*// + ' >$as_me.lineno && + chmod +x "$as_me.lineno" || + { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_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 sensitive to this). + . "./$as_me.lineno" + # Exit status is that of the last command. + exit +} + +ECHO_C= ECHO_N= ECHO_T= +case `echo -n x` in #((((( +-n*) + case `echo 'xy\c'` in + *c*) ECHO_T=' ';; # ECHO_T is single tab character. + xy) ECHO_C='\c';; + *) echo `echo ksh88 bug on AIX 6.1` > /dev/null + ECHO_T=' ';; + esac;; +*) + ECHO_N='-n';; +esac + +rm -f conf$$ conf$$.exe conf$$.file +if test -d conf$$.dir; then + rm -f conf$$.dir/conf$$.file +else + rm -f conf$$.dir + mkdir conf$$.dir 2>/dev/null +fi +if (echo >conf$$.file) 2>/dev/null; then + if ln -s conf$$.file conf$$ 2>/dev/null; then + as_ln_s='ln -s' + # ... but there are two gotchas: + # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. + # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. + # In both cases, we have to default to `cp -p'. + ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || + as_ln_s='cp -p' + elif ln conf$$.file conf$$ 2>/dev/null; then + as_ln_s=ln + else + as_ln_s='cp -p' + fi +else + as_ln_s='cp -p' +fi +rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file +rmdir conf$$.dir 2>/dev/null + +if mkdir -p . 2>/dev/null; then + as_mkdir_p='mkdir -p "$as_dir"' +else + test -d ./-p && rmdir ./-p + as_mkdir_p=false +fi + +if test -x / >/dev/null 2>&1; then + as_test_x='test -x' +else + if ls -dL / >/dev/null 2>&1; then + as_ls_L_option=L + else + as_ls_L_option= + fi + as_test_x=' + eval sh -c '\'' + if test -d "$1"; then + test -d "$1/."; + else + case $1 in #( + -*)set "./$1";; + esac; + case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in #(( + ???[sx]*):;;*)false;;esac;fi + '\'' sh + ' +fi +as_executable_p=$as_test_x + +# 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'" + +SHELL=${CONFIG_SHELL-/bin/sh} + + +test -n "$DJDIR" || exec 7<&0 &1 + +# Name of the host. +# hostname on some systems (SVR3.2, old GNU/Linux) returns a bogus exit status, +# so uname gets run too. +ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` + +# +# Initializations. +# +ac_default_prefix=/usr/local +ac_clean_files= +ac_config_libobj_dir=. +LIBOBJS= +cross_compiling=no +subdirs= +MFLAGS= +MAKEFLAGS= + +# Identity of this package. +PACKAGE_NAME='Berkeley DB' +PACKAGE_TARNAME='db-5.4.0' +PACKAGE_VERSION='5.4.0' +PACKAGE_STRING='Berkeley DB 5.4.0' +PACKAGE_BUGREPORT='Oracle Technology Network Berkeley DB forum' +PACKAGE_URL='' + +ac_unique_file="../src/db/db.c" +enable_option_checking=no +ac_default_prefix=/usr/local/BerkeleyDB.5.4 +# Factoring default headers for most tests. +ac_includes_default="\ +#include +#ifdef HAVE_SYS_TYPES_H +# include +#endif +#ifdef HAVE_SYS_STAT_H +# include +#endif +#ifdef STDC_HEADERS +# include +# include +#else +# ifdef HAVE_STDLIB_H +# include +# endif +#endif +#ifdef HAVE_STRING_H +# if !defined STDC_HEADERS && defined HAVE_MEMORY_H +# include +# endif +# include +#endif +#ifdef HAVE_STRINGS_H +# include +#endif +#ifdef HAVE_INTTYPES_H +# include +#endif +#ifdef HAVE_STDINT_H +# include +#endif +#ifdef HAVE_UNISTD_H +# include +#endif" + +ac_subst_vars='LTLIBOBJS +db_seq_decl +UINT64_FMT +INT64_FMT +TCL_TCLSH +TCL_SRC_DIR +TCL_LIB_FILE +TCL_INCLUDE_SPEC +TCL_BIN_DIR +LIBOBJS +LISTPROBES_COMMAND +LISTPROBES_DEPENDENCY +DTRACE_CPP +db_threadid_t_decl +thread_h_decl +uintptr_t_decl +uintmax_t_decl +ssize_t_decl +time_t_decl +size_t_decl +pid_t_decl +off_t_decl +FILE_t_decl +int64_decl +u_int64_decl +int32_decl +u_int32_decl +int16_decl +u_int16_decl +u_int8_decl +u_long_decl +u_int_decl +u_short_decl +u_char_decl +unistd_h_decl +stddef_h_decl +stdint_h_decl +inttypes_h_decl +TLS_defn +TLS_decl +WSTRING_decl +_ACJNI_JAVAC +uudecode +JAVA +JAVAC +JMODSUFFIX +MODSUFFIX +SOSUFFIX +CPP +OTOOL64 +OTOOL +LIPO +NMEDIT +DSYMUTIL +MANIFEST_TOOL +AWK +RANLIB +STRIP +ac_ct_AR +AR +DLLTOOL +OBJDUMP +LN_S +NM +ac_ct_DUMPBIN +DUMPBIN +LD +FGREP +EGREP +GREP +cxx_have_stdheaders +CXXCPP +ac_ct_CXX +CCC +OBJEXT +EXEEXT +ac_ct_CC +CC +INSTALL_DATA +INSTALL_SCRIPT +INSTALL_PROGRAM +db_cv_path_sh +PERL +SED +STAP +MV +RM +MKDIR +LN +KILL +CP +CHMOD +DB_VERSION_UNIQUE_NAME +DB_VERSION_FULL_STRING +DB_VERSION_STRING +DB_VERSION_PATCH +DB_VERSION_MINOR +DB_VERSION_MAJOR +DB_VERSION_RELEASE +DB_VERSION_FAMILY +platform_footer +platform_header +topdir +subdir_cmd +o +db_int_def +TEST_LIBS +TCL_ADDITIONAL_OBJS +SWIGCFLAGS +SQL_LIBS +SQL_FLAGS +SOFLAGS +REPLACEMENT_OBJS +PRINTLOG_OBJS +POSTLINK +OSDIR +MAKEFILE_XSOLINK +MAKEFILE_SOLINK +MAKEFILE_CXXLINK +MAKEFILE_CXX +MAKEFILE_CCLINK +MAKEFILE_CC +LOCALUTILS +LOCALSRC +LOCALEXAMPLES +LIBXSO_LIBS +LIBTSO_MODULE +LIBTSO_MODSUFFIX +LIBTSO_LIBS +LIBTOOL +LIBSO_LIBS +LIBJSO_LIBS +LIBCSO_LIBS +LDFLAGS +JAVACFLAGS +JAR +INSTALL_TARGET +INSTALL_LIBS_EXTRA +INSTALL_LIBS +INSTALLER +FINAL_OBJS +DTRACE +DEFAULT_LIB_TCL +DEFAULT_LIB_STL +DEFAULT_LIB_SQLITE +DEFAULT_LIB_SQL +DEFAULT_LIB_CXX +DEFAULT_LIB +DB_STRUCT_ALIGN8 +DB_PROTO2 +DB_PROTO1 +DB_CONST +CXXFLAGS +CXX +CRYPTO_OBJS +CPPFLAGS +CONFIGURATION_PATH +CONFIGURATION_ARGS +CFLAGS +BUILD_TARGET +ADDITIONAL_PROGS +ADDITIONAL_OBJS +ADDITIONAL_LANG +ADDITIONAL_INCS +host_os +host_vendor +host_cpu +host +build_os +build_vendor +build_cpu +build +target_alias +host_alias +build_alias +LIBS +ECHO_T +ECHO_N +ECHO_C +DEFS +mandir +localedir +libdir +psdir +pdfdir +dvidir +htmldir +infodir +docdir +oldincludedir +includedir +localstatedir +sharedstatedir +sysconfdir +datadir +datarootdir +libexecdir +sbindir +bindir +program_transform_name +prefix +exec_prefix +PACKAGE_URL +PACKAGE_BUGREPORT +PACKAGE_STRING +PACKAGE_VERSION +PACKAGE_TARNAME +PACKAGE_NAME +PATH_SEPARATOR +SHELL' +ac_subst_files='' +ac_user_opts=' +enable_option_checking +enable_smallbuild +enable_rdsbuild +enable_atomicsupport +enable_bigfile +enable_compression +enable_hash +enable_heap +enable_mutexsupport +enable_log_checksum +enable_partition +enable_queue +enable_replication +enable_statistics +enable_verify +enable_compat185 +enable_cxx +enable_debug +enable_debug_rop +enable_debug_wop +enable_diagnostic +enable_dump185 +enable_java +enable_mingw +enable_o_direct +enable_posixmutexes +enable_pthread_self +enable_pthread_api +enable_rpc +enable_sql +enable_sql_compat +enable_jdbc +with_jdbc +enable_amalgamation +enable_sql_codegen +enable_stl +enable_tcl +enable_test +enable_localization +enable_stripped_messages +enable_dbm +enable_dtrace +enable_systemtap +enable_perfmon_statistics +enable_uimutexes +enable_umrw +enable_atomicfileread +enable_cryptography +with_cryptography +with_mutex +with_mutexalign +with_stacksize +with_tcl +with_uniquename +enable_readline +enable_shared +enable_static +with_pic +enable_fast_install +with_gnu_ld +with_sysroot +enable_libtool_lock +enable_largefile +' + ac_precious_vars='build_alias +host_alias +target_alias +CC +CFLAGS +LDFLAGS +LIBS +CPPFLAGS +CXX +CXXFLAGS +CCC +CXXCPP +CPP' + + +# Initialize some variables set by options. +ac_init_help= +ac_init_version=false +ac_unrecognized_opts= +ac_unrecognized_sep= +# 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. +# (The list follows the same order as the GNU Coding Standards.) +bindir='${exec_prefix}/bin' +sbindir='${exec_prefix}/sbin' +libexecdir='${exec_prefix}/libexec' +datarootdir='${prefix}/share' +datadir='${datarootdir}' +sysconfdir='${prefix}/etc' +sharedstatedir='${prefix}/com' +localstatedir='${prefix}/var' +includedir='${prefix}/include' +oldincludedir='/usr/include' +docdir='${datarootdir}/doc/${PACKAGE_TARNAME}' +infodir='${datarootdir}/info' +htmldir='${docdir}' +dvidir='${docdir}' +pdfdir='${docdir}' +psdir='${docdir}' +libdir='${exec_prefix}/lib' +localedir='${datarootdir}/locale' +mandir='${datarootdir}/man' + +ac_prev= +ac_dashdash= +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 + + case $ac_option in + *=?*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;; + *=) ac_optarg= ;; + *) ac_optarg=yes ;; + esac + + # Accept the important Cygnus configure options, so we can diagnose typos. + + case $ac_dashdash$ac_option in + --) + ac_dashdash=yes ;; + + -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) + ac_prev=datadir ;; + -datadir=* | --datadir=* | --datadi=* | --datad=*) + datadir=$ac_optarg ;; + + -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \ + | --dataroo | --dataro | --datar) + ac_prev=datarootdir ;; + -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \ + | --dataroot=* | --dataroo=* | --dataro=* | --datar=*) + datarootdir=$ac_optarg ;; + + -disable-* | --disable-*) + ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error $? "invalid feature name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"enable_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval enable_$ac_useropt=no ;; + + -docdir | --docdir | --docdi | --doc | --do) + ac_prev=docdir ;; + -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*) + docdir=$ac_optarg ;; + + -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv) + ac_prev=dvidir ;; + -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*) + dvidir=$ac_optarg ;; + + -enable-* | --enable-*) + ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error $? "invalid feature name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"enable_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval enable_$ac_useropt=\$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 ;; + + -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht) + ac_prev=htmldir ;; + -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \ + | --ht=*) + htmldir=$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 ;; + + -localedir | --localedir | --localedi | --localed | --locale) + ac_prev=localedir ;; + -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*) + localedir=$ac_optarg ;; + + -localstatedir | --localstatedir | --localstatedi | --localstated \ + | --localstate | --localstat | --localsta | --localst | --locals) + ac_prev=localstatedir ;; + -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ + | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*) + 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 ;; + + -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd) + ac_prev=pdfdir ;; + -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*) + pdfdir=$ac_optarg ;; + + -psdir | --psdir | --psdi | --psd | --ps) + ac_prev=psdir ;; + -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*) + psdir=$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_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error $? "invalid package name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"with_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval with_$ac_useropt=\$ac_optarg ;; + + -without-* | --without-*) + ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error $? "invalid package name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"with_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval with_$ac_useropt=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 ;; + + -*) as_fn_error $? "unrecognized option: \`$ac_option' +Try \`$0 --help' for more information" + ;; + + *=*) + ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` + # Reject names that are not valid shell variable names. + case $ac_envvar in #( + '' | [0-9]* | *[!_$as_cr_alnum]* ) + as_fn_error $? "invalid variable name: \`$ac_envvar'" ;; + esac + eval $ac_envvar=\$ac_optarg + export $ac_envvar ;; + + *) + # FIXME: should be removed in autoconf 3.0. + $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2 + expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && + $as_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'` + as_fn_error $? "missing argument to $ac_option" +fi + +if test -n "$ac_unrecognized_opts"; then + case $enable_option_checking in + no) ;; + fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;; + *) $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;; + esac +fi + +# Check all directory arguments for consistency. +for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ + datadir sysconfdir sharedstatedir localstatedir includedir \ + oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ + libdir localedir mandir +do + eval ac_val=\$$ac_var + # Remove trailing slashes. + case $ac_val in + */ ) + ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'` + eval $ac_var=\$ac_val;; + esac + # Be sure to have absolute directory names. + case $ac_val in + [\\/$]* | ?:[\\/]* ) continue;; + NONE | '' ) case $ac_var in *prefix ) continue;; esac;; + esac + as_fn_error $? "expected an absolute directory name for --$ac_var: $ac_val" +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 + $as_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 + + +ac_pwd=`pwd` && test -n "$ac_pwd" && +ac_ls_di=`ls -di .` && +ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` || + as_fn_error $? "working directory cannot be determined" +test "X$ac_ls_di" = "X$ac_pwd_ls_di" || + as_fn_error $? "pwd does not report name of working directory" + + +# 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 the parent directory. + ac_confdir=`$as_dirname -- "$as_myself" || +$as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_myself" : 'X\(//\)[^/]' \| \ + X"$as_myself" : 'X\(//\)$' \| \ + X"$as_myself" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$as_myself" | + 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 + test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .." + as_fn_error $? "cannot find sources ($ac_unique_file) in $srcdir" +fi +ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work" +ac_abs_confdir=`( + cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error $? "$ac_msg" + pwd)` +# When building in place, set srcdir=. +if test "$ac_abs_confdir" = "$ac_pwd"; then + srcdir=. +fi +# Remove unnecessary trailing slashes from srcdir. +# Double slashes in file names in object file debugging info +# mess up M-x gdb in Emacs. +case $srcdir in +*/) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;; +esac +for ac_var in $ac_precious_vars; do + eval ac_env_${ac_var}_set=\${${ac_var}+set} + eval ac_env_${ac_var}_value=\$${ac_var} + eval ac_cv_env_${ac_var}_set=\${${ac_var}+set} + eval ac_cv_env_${ac_var}_value=\$${ac_var} +done + +# +# 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 Berkeley DB 5.4.0 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 \`..'] + +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] + --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] + --datarootdir=DIR read-only arch.-independent data root [PREFIX/share] + --datadir=DIR read-only architecture-independent data [DATAROOTDIR] + --infodir=DIR info documentation [DATAROOTDIR/info] + --localedir=DIR locale-dependent data [DATAROOTDIR/locale] + --mandir=DIR man documentation [DATAROOTDIR/man] + --docdir=DIR documentation root + [DATAROOTDIR/doc/db-5.4.0] + --htmldir=DIR html documentation [DOCDIR] + --dvidir=DIR dvi documentation [DOCDIR] + --pdfdir=DIR pdf documentation [DOCDIR] + --psdir=DIR ps documentation [DOCDIR] +_ACEOF + + cat <<\_ACEOF + +Program names: + --program-prefix=PREFIX prepend PREFIX to installed program names + --program-suffix=SUFFIX append SUFFIX to installed program names + --program-transform-name=PROGRAM run sed PROGRAM on installed program names + +System types: + --build=BUILD configure for building on BUILD [guessed] + --host=HOST cross-compile to build programs to run on HOST [BUILD] +_ACEOF +fi + +if test -n "$ac_init_help"; then + case $ac_init_help in + short | recursive ) echo "Configuration of Berkeley DB 5.4.0:";; + esac + cat <<\_ACEOF + +Optional Features: + --disable-option-checking ignore unrecognized --enable/--with options + --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) + --enable-FEATURE[=ARG] include FEATURE [ARG=yes] + --enable-smallbuild Build small footprint version of the library. + --enable-rdsbuild Build the restricted-DS version of the library. + --disable-atomicsupport Do not build any native atomic operation support. + --disable-bigfile Obsolete; use --disable-largefile instead. + --disable-compression Do not build compression support. + --disable-hash Do not build Hash access method. + --disable-heap Do not build Heap access method. + --disable-mutexsupport Do not build any mutex support. + --disable-log_checksum Disable log checksums. + --disable-partition Do not build partitioned database support. + --disable-queue Do not build Queue access method. + --disable-replication Do not build database replication support. + --disable-statistics Do not build statistics support. + --disable-verify Do not build database verification support. + --enable-compat185 Build DB 1.85 compatibility API. + --enable-cxx Build C++ API. + --enable-debug Build a debugging version. + --enable-debug_rop Build a version that logs read operations. + --enable-debug_wop Build a version that logs write operations. + --enable-diagnostic Build a version with run-time diagnostics. + --enable-dump185 Build db_dump185(1) to dump 1.85 databases. + --enable-java Build Java API. + --enable-mingw Build Berkeley DB for MinGW. + --enable-o_direct Enable the O_DIRECT flag for direct I/O. + --enable-posixmutexes Force use of POSIX standard mutexes. + + --enable-sql Build the SQL API. + --enable-sql_compat Build a drop-in replacement sqlite3 library. + --enable-jdbc Build BDB SQL JDBC library. + --enable-amalgamation Build a SQL amalgamation instead of building files + separately. + --enable-sql_codegen Build the SQL-to-C code generation tool. + --enable-stl Build STL API. + --enable-tcl Build Tcl API. + --enable-test Configure to run the test suite. + --enable-localization Configure to enable localization. + --enable-stripped_messages + Configure to enable stripped messages. + --enable-dbm Configure to enable the historic dbm interface. + --enable-dtrace Configure to build in dtrace static probes + --enable-systemtap Configure to use systemtap to emulate dtrace static + probes + --enable-perfmon-statistics + Configure to build in performance monitoring of + statistics values [default=no]. + --enable-uimutexes Force use of Unix International mutexes. + --enable-umrw Mask harmless uninitialized memory read/writes. + --enable-atomicfileread Indicate that the platform reads and writes files + atomically. + --enable-shared[=PKGS] build shared libraries [default=yes] + --enable-static[=PKGS] build static libraries [default=yes] + --enable-fast-install[=PKGS] + optimize for fast installation [default=yes] + --disable-libtool-lock avoid locking (might break parallel builds) + --disable-largefile omit support for large files + +Optional Packages: + --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] + --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) + --with-jdbc=DIR Specify source directory of JDBC. + --with-cryptography=yes|no|ipp + Build database cryptography support [default=yes]. + --with-mutex=MUTEX Select non-default mutex implementation. + --with-mutexalign=ALIGNMENT + Obsolete; use DbEnv::mutex_set_align instead. + --with-stacksize=SIZE Set the stack size for Berkeley DB threads. + --with-tcl=DIR Directory location of tclConfig.sh. + --with-uniquename=NAME Build a uniquely named library. + --with-pic try to use only PIC/non-PIC objects [default=use + both] + --with-gnu-ld assume the C compiler uses GNU ld [default=no] + --with-sysroot=DIR Search for dependent libraries within DIR + (or the compiler's sysroot if not specified). + +Some influential environment variables: + CC C compiler command + CFLAGS C compiler flags + LDFLAGS linker flags, e.g. -L if you have libraries in a + nonstandard directory + LIBS libraries to pass to the linker, e.g. -l + CPPFLAGS (Objective) C/C++ preprocessor flags, e.g. -I if + you have headers in a nonstandard directory + CXX C++ compiler command + CXXFLAGS C++ compiler flags + CXXCPP C++ preprocessor + CPP C preprocessor + +Use these variables to override the choices made by `configure' or to help +it to find libraries and programs with nonstandard names/locations. + +Report bugs to . +_ACEOF +ac_status=$? +fi + +if test "$ac_init_help" = "recursive"; then + # If there are subdirs, report their specific --help. + for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue + test -d "$ac_dir" || + { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } || + continue + ac_builddir=. + +case "$ac_dir" in +.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; +*) + ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` + # A ".." for each directory in $ac_dir_suffix. + ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` + case $ac_top_builddir_sub in + "") ac_top_builddir_sub=. ac_top_build_prefix= ;; + *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; + esac ;; +esac +ac_abs_top_builddir=$ac_pwd +ac_abs_builddir=$ac_pwd$ac_dir_suffix +# for backward compatibility: +ac_top_builddir=$ac_top_build_prefix + +case $srcdir in + .) # We are building in place. + ac_srcdir=. + ac_top_srcdir=$ac_top_builddir_sub + ac_abs_top_srcdir=$ac_pwd ;; + [\\/]* | ?:[\\/]* ) # Absolute name. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir + ac_abs_top_srcdir=$srcdir ;; + *) # Relative name. + ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_build_prefix$srcdir + ac_abs_top_srcdir=$ac_pwd/$srcdir ;; +esac +ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix + + cd "$ac_dir" || { ac_status=$?; continue; } + # Check for guested 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 + else + $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2 + fi || ac_status=$? + cd "$ac_pwd" || { ac_status=$?; break; } + done +fi + +test -n "$ac_init_help" && exit $ac_status +if $ac_init_version; then + cat <<\_ACEOF +Berkeley DB configure 5.4.0 +generated by GNU Autoconf 2.68 + +Copyright (C) 2010 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 +fi + +## ------------------------ ## +## Autoconf initialization. ## +## ------------------------ ## + +# ac_fn_c_try_compile LINENO +# -------------------------- +# Try to compile conftest.$ac_ext, and return whether this succeeded. +ac_fn_c_try_compile () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + rm -f conftest.$ac_objext + if { { ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_compile") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then : + ac_retval=0 +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=1 +fi + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_c_try_compile + +# ac_fn_cxx_try_compile LINENO +# ---------------------------- +# Try to compile conftest.$ac_ext, and return whether this succeeded. +ac_fn_cxx_try_compile () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + rm -f conftest.$ac_objext + if { { ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_compile") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && { + test -z "$ac_cxx_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then : + ac_retval=0 +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=1 +fi + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_cxx_try_compile + +# ac_fn_cxx_try_cpp LINENO +# ------------------------ +# Try to preprocess conftest.$ac_ext, and return whether this succeeded. +ac_fn_cxx_try_cpp () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + if { { ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } > conftest.i && { + test -z "$ac_cxx_preproc_warn_flag$ac_cxx_werror_flag" || + test ! -s conftest.err + }; then : + ac_retval=0 +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=1 +fi + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_cxx_try_cpp + +# ac_fn_c_try_link LINENO +# ----------------------- +# Try to link conftest.$ac_ext, and return whether this succeeded. +ac_fn_c_try_link () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + rm -f conftest.$ac_objext conftest$ac_exeext + if { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && { + test -z "$ac_c_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && { + test "$cross_compiling" = yes || + $as_test_x conftest$ac_exeext + }; then : + ac_retval=0 +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=1 +fi + # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information + # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would + # interfere with the next link command; also delete a directory that is + # left behind by Apple's compiler. We do this before executing the actions. + rm -rf conftest.dSYM conftest_ipa8_conftest.oo + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_c_try_link + +# ac_fn_c_check_header_compile LINENO HEADER VAR INCLUDES +# ------------------------------------------------------- +# Tests whether HEADER exists and can be compiled using the include files in +# INCLUDES, setting the cache variable VAR accordingly. +ac_fn_c_check_header_compile () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +#include <$2> +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + eval "$3=yes" +else + eval "$3=no" +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_c_check_header_compile + +# ac_fn_c_try_cpp LINENO +# ---------------------- +# Try to preprocess conftest.$ac_ext, and return whether this succeeded. +ac_fn_c_try_cpp () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + if { { ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } > conftest.i && { + test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" || + test ! -s conftest.err + }; then : + ac_retval=0 +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=1 +fi + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_c_try_cpp + +# ac_fn_c_try_run LINENO +# ---------------------- +# Try to link conftest.$ac_ext, and return whether this succeeded. Assumes +# that executables *can* be run. +ac_fn_c_try_run () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + if { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && { ac_try='./conftest$ac_exeext' + { { case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; }; then : + ac_retval=0 +else + $as_echo "$as_me: program exited with status $ac_status" >&5 + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=$ac_status +fi + rm -rf conftest.dSYM conftest_ipa8_conftest.oo + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_c_try_run + +# ac_fn_c_check_func LINENO FUNC VAR +# ---------------------------------- +# Tests whether FUNC exists, setting the cache variable VAR accordingly +ac_fn_c_check_func () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +/* Define $2 to an innocuous variant, in case declares $2. + For example, HP-UX 11i declares gettimeofday. */ +#define $2 innocuous_$2 + +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char $2 (); below. + Prefer to if __STDC__ is defined, since + exists even on freestanding compilers. */ + +#ifdef __STDC__ +# include +#else +# include +#endif + +#undef $2 + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char $2 (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined __stub_$2 || defined __stub___$2 +choke me +#endif + +int +main () +{ +return $2 (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + eval "$3=yes" +else + eval "$3=no" +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_c_check_func + +# ac_fn_cxx_try_link LINENO +# ------------------------- +# Try to link conftest.$ac_ext, and return whether this succeeded. +ac_fn_cxx_try_link () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + rm -f conftest.$ac_objext conftest$ac_exeext + if { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && { + test -z "$ac_cxx_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && { + test "$cross_compiling" = yes || + $as_test_x conftest$ac_exeext + }; then : + ac_retval=0 +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=1 +fi + # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information + # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would + # interfere with the next link command; also delete a directory that is + # left behind by Apple's compiler. We do this before executing the actions. + rm -rf conftest.dSYM conftest_ipa8_conftest.oo + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_cxx_try_link + +# ac_fn_c_check_header_mongrel LINENO HEADER VAR INCLUDES +# ------------------------------------------------------- +# Tests whether HEADER exists, giving a warning if it cannot be compiled using +# the include files in INCLUDES and setting the cache variable VAR +# accordingly. +ac_fn_c_check_header_mongrel () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + if eval \${$3+:} false; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } +else + # Is the header compilable? +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 usability" >&5 +$as_echo_n "checking $2 usability... " >&6; } +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +#include <$2> +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_header_compiler=yes +else + ac_header_compiler=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_compiler" >&5 +$as_echo "$ac_header_compiler" >&6; } + +# Is the header present? +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 presence" >&5 +$as_echo_n "checking $2 presence... " >&6; } +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <$2> +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + ac_header_preproc=yes +else + ac_header_preproc=no +fi +rm -f conftest.err conftest.i conftest.$ac_ext +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_preproc" >&5 +$as_echo "$ac_header_preproc" >&6; } + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in #(( + yes:no: ) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&5 +$as_echo "$as_me: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 +$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} + ;; + no:yes:* ) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: present but cannot be compiled" >&5 +$as_echo "$as_me: WARNING: $2: present but cannot be compiled" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: check for missing prerequisite headers?" >&5 +$as_echo "$as_me: WARNING: $2: check for missing prerequisite headers?" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: see the Autoconf documentation" >&5 +$as_echo "$as_me: WARNING: $2: see the Autoconf documentation" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&5 +$as_echo "$as_me: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 +$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} +( $as_echo "## ---------------------------------------------------------- ## +## Report this to Oracle Technology Network Berkeley DB forum ## +## ---------------------------------------------------------- ##" + ) | sed "s/^/$as_me: WARNING: /" >&2 + ;; +esac + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +else + eval "$3=\$ac_header_compiler" +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } +fi + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_c_check_header_mongrel + +# ac_fn_c_check_member LINENO AGGR MEMBER VAR INCLUDES +# ---------------------------------------------------- +# Tries to find if the field MEMBER exists in type AGGR, after including +# INCLUDES, setting cache variable VAR accordingly. +ac_fn_c_check_member () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2.$3" >&5 +$as_echo_n "checking for $2.$3... " >&6; } +if eval \${$4+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$5 +int +main () +{ +static $2 ac_aggr; +if (ac_aggr.$3) +return 0; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + eval "$4=yes" +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$5 +int +main () +{ +static $2 ac_aggr; +if (sizeof ac_aggr.$3) +return 0; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + eval "$4=yes" +else + eval "$4=no" +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +eval ac_res=\$$4 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_c_check_member + +# ac_fn_c_compute_int LINENO EXPR VAR INCLUDES +# -------------------------------------------- +# Tries to find the compile-time value of EXPR in a program that includes +# INCLUDES, setting VAR accordingly. Returns whether the value could be +# computed +ac_fn_c_compute_int () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + if test "$cross_compiling" = yes; then + # Depending upon the size, compute the lo and hi bounds. +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +int +main () +{ +static int test_array [1 - 2 * !(($2) >= 0)]; +test_array [0] = 0 + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_lo=0 ac_mid=0 + while :; do + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +int +main () +{ +static int test_array [1 - 2 * !(($2) <= $ac_mid)]; +test_array [0] = 0 + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_hi=$ac_mid; break +else + as_fn_arith $ac_mid + 1 && ac_lo=$as_val + if test $ac_lo -le $ac_mid; then + ac_lo= ac_hi= + break + fi + as_fn_arith 2 '*' $ac_mid + 1 && ac_mid=$as_val +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + done +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +int +main () +{ +static int test_array [1 - 2 * !(($2) < 0)]; +test_array [0] = 0 + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_hi=-1 ac_mid=-1 + while :; do + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +int +main () +{ +static int test_array [1 - 2 * !(($2) >= $ac_mid)]; +test_array [0] = 0 + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_lo=$ac_mid; break +else + as_fn_arith '(' $ac_mid ')' - 1 && ac_hi=$as_val + if test $ac_mid -le $ac_hi; then + ac_lo= ac_hi= + break + fi + as_fn_arith 2 '*' $ac_mid && ac_mid=$as_val +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + done +else + ac_lo= ac_hi= +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +# Binary search between lo and hi bounds. +while test "x$ac_lo" != "x$ac_hi"; do + as_fn_arith '(' $ac_hi - $ac_lo ')' / 2 + $ac_lo && ac_mid=$as_val + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +int +main () +{ +static int test_array [1 - 2 * !(($2) <= $ac_mid)]; +test_array [0] = 0 + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_hi=$ac_mid +else + as_fn_arith '(' $ac_mid ')' + 1 && ac_lo=$as_val +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +done +case $ac_lo in #(( +?*) eval "$3=\$ac_lo"; ac_retval=0 ;; +'') ac_retval=1 ;; +esac + else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +static long int longval () { return $2; } +static unsigned long int ulongval () { return $2; } +#include +#include +int +main () +{ + + FILE *f = fopen ("conftest.val", "w"); + if (! f) + return 1; + if (($2) < 0) + { + long int i = longval (); + if (i != ($2)) + return 1; + fprintf (f, "%ld", i); + } + else + { + unsigned long int i = ulongval (); + if (i != ($2)) + return 1; + fprintf (f, "%lu", i); + } + /* Do not output a trailing newline, as this causes \r\n confusion + on some platforms. */ + return ferror (f) || fclose (f) != 0; + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_run "$LINENO"; then : + echo >>conftest.val; read $3 &5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +else + eval "$3=no" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +int +main () +{ +if (sizeof ($2)) + return 0; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +int +main () +{ +if (sizeof (($2))) + return 0; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + +else + eval "$3=yes" +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_c_check_type +cat >config.log <<_ACEOF +This file contains any messages produced by compilers while +running configure, to aid debugging if configure makes a mistake. + +It was created by Berkeley DB $as_me 5.4.0, which was +generated by GNU Autoconf 2.68. Invocation command line was + + $ $0 $@ + +_ACEOF +exec 5>>config.log +{ +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` +/usr/bin/hostinfo = `(/usr/bin/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=. + $as_echo "PATH: $as_dir" + done +IFS=$as_save_IFS + +} >&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_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=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; + esac + case $ac_pass in + 1) as_fn_append ac_configure_args0 " '$ac_arg'" ;; + 2) + as_fn_append 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 + as_fn_append ac_configure_args " '$ac_arg'" + ;; + esac + done +done +{ ac_configure_args0=; unset ac_configure_args0;} +{ ac_configure_args1=; unset 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: Use '\'' to represent an apostrophe within the trap. +# WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug. +trap 'exit_status=$? + # Save into config.log some information that might help in debugging. + { + echo + + $as_echo "## ---------------- ## +## Cache variables. ## +## ---------------- ##" + echo + # The following way of writing the cache mishandles newlines in values, +( + for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do + eval ac_val=\$$ac_var + case $ac_val in #( + *${as_nl}*) + case $ac_var in #( + *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 +$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; + esac + case $ac_var in #( + _ | IFS | as_nl) ;; #( + BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( + *) { eval $ac_var=; unset $ac_var;} ;; + esac ;; + esac + done + (set) 2>&1 | + case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #( + *${as_nl}ac_space=\ *) + sed -n \ + "s/'\''/'\''\\\\'\'''\''/g; + s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p" + ;; #( + *) + sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" + ;; + esac | + sort +) + echo + + $as_echo "## ----------------- ## +## Output variables. ## +## ----------------- ##" + echo + for ac_var in $ac_subst_vars + do + eval ac_val=\$$ac_var + case $ac_val in + *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; + esac + $as_echo "$ac_var='\''$ac_val'\''" + done | sort + echo + + if test -n "$ac_subst_files"; then + $as_echo "## ------------------- ## +## File substitutions. ## +## ------------------- ##" + echo + for ac_var in $ac_subst_files + do + eval ac_val=\$$ac_var + case $ac_val in + *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; + esac + $as_echo "$ac_var='\''$ac_val'\''" + done | sort + echo + fi + + if test -s confdefs.h; then + $as_echo "## ----------- ## +## confdefs.h. ## +## ----------- ##" + echo + cat confdefs.h + echo + fi + test "$ac_signal" != 0 && + $as_echo "$as_me: caught signal $ac_signal" + $as_echo "$as_me: exit $exit_status" + } >&5 + rm -f core *.core core.conftest.* && + rm -f -r conftest* confdefs* conf$$* $ac_clean_files && + exit $exit_status +' 0 +for ac_signal in 1 2 13 15; do + trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal +done +ac_signal=0 + +# confdefs.h avoids OS command line length limits that DEFS can exceed. +rm -f -r conftest* confdefs.h + +$as_echo "/* confdefs.h */" > 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 + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_URL "$PACKAGE_URL" +_ACEOF + + +# Let the site file select an alternate cache file if it wants to. +# Prefer an explicitly selected file to automatically selected ones. +ac_site_file1=NONE +ac_site_file2=NONE +if test -n "$CONFIG_SITE"; then + # We do not want a PATH search for config.site. + case $CONFIG_SITE in #(( + -*) ac_site_file1=./$CONFIG_SITE;; + */*) ac_site_file1=$CONFIG_SITE;; + *) ac_site_file1=./$CONFIG_SITE;; + esac +elif test "x$prefix" != xNONE; then + ac_site_file1=$prefix/share/config.site + ac_site_file2=$prefix/etc/config.site +else + ac_site_file1=$ac_default_prefix/share/config.site + ac_site_file2=$ac_default_prefix/etc/config.site +fi +for ac_site_file in "$ac_site_file1" "$ac_site_file2" +do + test "x$ac_site_file" = xNONE && continue + if test /dev/null != "$ac_site_file" && test -r "$ac_site_file"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5 +$as_echo "$as_me: loading site script $ac_site_file" >&6;} + sed 's/^/| /' "$ac_site_file" >&5 + . "$ac_site_file" \ + || { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "failed to load site script $ac_site_file +See \`config.log' for more details" "$LINENO" 5; } + 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. DJGPP emulates it as a regular file. + if test /dev/null != "$cache_file" && test -f "$cache_file"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5 +$as_echo "$as_me: loading cache $cache_file" >&6;} + case $cache_file in + [\\/]* | ?:[\\/]* ) . "$cache_file";; + *) . "./$cache_file";; + esac + fi +else + { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5 +$as_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 $ac_precious_vars; 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,) + { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 +$as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} + ac_cache_corrupted=: ;; + ,set) + { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5 +$as_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 + # differences in whitespace do not lead to failure. + ac_old_val_w=`echo x $ac_old_val` + ac_new_val_w=`echo x $ac_new_val` + if test "$ac_old_val_w" != "$ac_new_val_w"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5 +$as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} + ac_cache_corrupted=: + else + { $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5 +$as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;} + eval $ac_var=\$ac_old_val + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: former value: \`$ac_old_val'" >&5 +$as_echo "$as_me: former value: \`$ac_old_val'" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: current value: \`$ac_new_val'" >&5 +$as_echo "$as_me: current value: \`$ac_new_val'" >&2;} + fi;; + esac + # Pass precious variables to config.status. + if test "$ac_new_set" = set; then + case $ac_new_val in + *\'*) ac_arg=$ac_var=`$as_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. + *) as_fn_append ac_configure_args " '$ac_arg'" ;; + esac + fi +done +if $ac_cache_corrupted; then + { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5 +$as_echo "$as_me: error: changes in the environment can compromise the build" >&2;} + as_fn_error $? "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5 +fi +## -------------------- ## +## Main body of script. ## +## -------------------- ## + +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 + + + +ac_config_headers="$ac_config_headers db_config.h:config.hin" + + + + +# We're going to pass options through to SQLite, don't check them first. + + + +# Configure setup. +ac_aux_dir= +for ac_dir in "$srcdir" "$srcdir/.." "$srcdir/../.."; do + if test -f "$ac_dir/install-sh"; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install-sh -c" + break + elif test -f "$ac_dir/install.sh"; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install.sh -c" + break + elif test -f "$ac_dir/shtool"; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/shtool install -c" + break + fi +done +if test -z "$ac_aux_dir"; then + as_fn_error $? "cannot find install-sh, install.sh, or shtool in \"$srcdir\" \"$srcdir/..\" \"$srcdir/../..\"" "$LINENO" 5 +fi + +# These three variables are undocumented and unsupported, +# and are intended to be withdrawn in a future Autoconf release. +# They can cause serious problems if a builder's source tree is in a directory +# whose full name contains unusual characters. +ac_config_guess="$SHELL $ac_aux_dir/config.guess" # Please don't use this var. +ac_config_sub="$SHELL $ac_aux_dir/config.sub" # Please don't use this var. +ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var. + + +# Make sure we can run config.sub. +$SHELL "$ac_aux_dir/config.sub" sun4 >/dev/null 2>&1 || + as_fn_error $? "cannot run $SHELL $ac_aux_dir/config.sub" "$LINENO" 5 + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking build system type" >&5 +$as_echo_n "checking build system type... " >&6; } +if ${ac_cv_build+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_build_alias=$build_alias +test "x$ac_build_alias" = x && + ac_build_alias=`$SHELL "$ac_aux_dir/config.guess"` +test "x$ac_build_alias" = x && + as_fn_error $? "cannot guess build type; you must specify one" "$LINENO" 5 +ac_cv_build=`$SHELL "$ac_aux_dir/config.sub" $ac_build_alias` || + as_fn_error $? "$SHELL $ac_aux_dir/config.sub $ac_build_alias failed" "$LINENO" 5 + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_build" >&5 +$as_echo "$ac_cv_build" >&6; } +case $ac_cv_build in +*-*-*) ;; +*) as_fn_error $? "invalid value of canonical build" "$LINENO" 5;; +esac +build=$ac_cv_build +ac_save_IFS=$IFS; IFS='-' +set x $ac_cv_build +shift +build_cpu=$1 +build_vendor=$2 +shift; shift +# Remember, the first character of IFS is used to create $*, +# except with old shells: +build_os=$* +IFS=$ac_save_IFS +case $build_os in *\ *) build_os=`echo "$build_os" | sed 's/ /-/g'`;; esac + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking host system type" >&5 +$as_echo_n "checking host system type... " >&6; } +if ${ac_cv_host+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test "x$host_alias" = x; then + ac_cv_host=$ac_cv_build +else + ac_cv_host=`$SHELL "$ac_aux_dir/config.sub" $host_alias` || + as_fn_error $? "$SHELL $ac_aux_dir/config.sub $host_alias failed" "$LINENO" 5 +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_host" >&5 +$as_echo "$ac_cv_host" >&6; } +case $ac_cv_host in +*-*-*) ;; +*) as_fn_error $? "invalid value of canonical host" "$LINENO" 5;; +esac +host=$ac_cv_host +ac_save_IFS=$IFS; IFS='-' +set x $ac_cv_host +shift +host_cpu=$1 +host_vendor=$2 +shift; shift +# Remember, the first character of IFS is used to create $*, +# except with old shells: +host_os=$* +IFS=$ac_save_IFS +case $host_os in *\ *) host_os=`echo "$host_os" | sed 's/ /-/g'`;; esac + + +test "$program_prefix" != NONE && + program_transform_name="s&^&$program_prefix&;$program_transform_name" +# Use a double $ so make ignores it. +test "$program_suffix" != NONE && + program_transform_name="s&\$&$program_suffix&;$program_transform_name" +# Double any \ or $. +# By default was `s,x,x', remove it if useless. +ac_script='s/[\\$]/&&/g;s/;s,x,x,$//' +program_transform_name=`$as_echo "$program_transform_name" | sed "$ac_script"` + + +# Don't build in the dist directory. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if building in the top-level or dist directories" >&5 +$as_echo_n "checking if building in the top-level or dist directories... " >&6; } +if test -f configure.ac ; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + as_fn_error $? "\ +Berkeley DB should not be built in the \"dist\" directory. \ +Change directory to the build_unix directory and run ../dist/configure \ +from there." "$LINENO" 5 +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + +topdir=`echo "$srcdir/.." | sed 's,/dist/\.\.,,'` +# Substitution variables. BDB additions need to be documented. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +# The Windows public header has two extra symbols we need to remove. + + + +# Set the default installation location. + + +# Configure the version information. + +DB_VERSION_FAMILY="11" + +DB_VERSION_RELEASE="2" + +DB_VERSION_MAJOR="5" + +DB_VERSION_MINOR="4" + +DB_VERSION_PATCH="0" + +DB_VERSION_STRING='"Berkeley DB 5.4.0: (May 7, 2012)"' + +DB_VERSION_FULL_STRING='"Berkeley DB 11g Release 2, library version 11.2.5.4.0: (May 7, 2012)"' + + +# Process all options before using them. + + +db_cv_build_full="yes" +db_cv_build_main="yes" +# db_rdsbuild_default is set to yes by buildrds +db_rdsbuild_default="yes" +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if --enable-smallbuild option specified" >&5 +$as_echo_n "checking if --enable-smallbuild option specified... " >&6; } +# Check whether --enable-smallbuild was given. +if test "${enable_smallbuild+set}" = set; then : + enableval=$enable_smallbuild; db_cv_smallbuild="$enable_smallbuild" +else + db_cv_smallbuild="no" +fi + +case "$db_cv_smallbuild" in +yes) db_cv_build_full="no" +esac +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $db_cv_smallbuild" >&5 +$as_echo "$db_cv_smallbuild" >&6; } + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if --enable-rdsbuild option specified" >&5 +$as_echo_n "checking if --enable-rdsbuild option specified... " >&6; } +# Check whether --enable-rdsbuild was given. +if test "${enable_rdsbuild+set}" = set; then : + enableval=$enable_rdsbuild; db_cv_rdsbuild="$enable_rdsbuild" +else + db_cv_rdsbuild=$db_rdsbuild_default +fi + +case "$db_cv_rdsbuild" in +yes) db_cv_build_full="no" + db_cv_build_main="no";; +*) db_cv_rdsbuild="no";; +esac +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $db_cv_rdsbuild" >&5 +$as_echo "$db_cv_rdsbuild" >&6; } + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if --disable-atomicsupport option specified" >&5 +$as_echo_n "checking if --disable-atomicsupport option specified... " >&6; } +# Check whether --enable-atomicsupport was given. +if test "${enable_atomicsupport+set}" = set; then : + enableval=$enable_atomicsupport; +else + enableval="yes" +fi + +db_cv_build_atomicsupport="$enableval" +case "$enableval" in + no) { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; };; +yes) { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; };; +esac + +# --enable-bigfile was the configuration option that Berkeley DB used before +# autoconf 2.50 was released (which had --enable-largefile integrated in). +# Check whether --enable-bigfile was given. +if test "${enable_bigfile+set}" = set; then : + enableval=$enable_bigfile; as_fn_error $? "--enable-bigfile no longer supported, use --enable-largefile" "$LINENO" 5 +fi + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if --disable-compression option specified" >&5 +$as_echo_n "checking if --disable-compression option specified... " >&6; } +# Check whether --enable-compression was given. +if test "${enable_compression+set}" = set; then : + enableval=$enable_compression; +else + enableval=$db_cv_build_full +fi + +db_cv_build_compression="$enableval" +case "$enableval" in + no) { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; };; +yes) { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; };; +esac + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if --disable-hash option specified" >&5 +$as_echo_n "checking if --disable-hash option specified... " >&6; } +# Check whether --enable-hash was given. +if test "${enable_hash+set}" = set; then : + enableval=$enable_hash; +else + enableval=$db_cv_build_full +fi + +db_cv_build_hash="$enableval" +case "$enableval" in + no) { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; };; +yes) { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; };; +esac + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if --disable-heap option specified" >&5 +$as_echo_n "checking if --disable-heap option specified... " >&6; } +# Check whether --enable-heap was given. +if test "${enable_heap+set}" = set; then : + enableval=$enable_heap; +else + enableval=$db_cv_build_full +fi + +db_cv_build_heap="$enableval" +case "$enableval" in + no) { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; };; +yes) { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; };; +esac + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if --disable-mutexsupport option specified" >&5 +$as_echo_n "checking if --disable-mutexsupport option specified... " >&6; } +# Check whether --enable-mutexsupport was given. +if test "${enable_mutexsupport+set}" = set; then : + enableval=$enable_mutexsupport; +else + enableval="yes" +fi + +db_cv_build_mutexsupport="$enableval" +case "$enableval" in + no) { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; };; +yes) { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; };; +esac + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if --disable-log_checksum option specified" >&5 +$as_echo_n "checking if --disable-log_checksum option specified... " >&6; } +# Check whether --enable-log_checksum was given. +if test "${enable_log_checksum+set}" = set; then : + enableval=$enable_log_checksum; case "$enableval" in + no | yes) db_cv_log_checksum="$enableval" ;; + *) db_cv_log_checksum="yes" ;; + esac +else + db_cv_log_checksum=$db_cv_build_main +fi + +case "$db_cv_log_checksum" in + no) { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; };; +yes) { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; };; +esac + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if --disable-partition option specified" >&5 +$as_echo_n "checking if --disable-partition option specified... " >&6; } +# Check whether --enable-partition was given. +if test "${enable_partition+set}" = set; then : + enableval=$enable_partition; +else + enableval=$db_cv_build_full +fi + +db_cv_build_partition="$enableval" +case "$enableval" in + no) { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; };; +yes) { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; };; +esac + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if --disable-queue option specified" >&5 +$as_echo_n "checking if --disable-queue option specified... " >&6; } +# Check whether --enable-queue was given. +if test "${enable_queue+set}" = set; then : + enableval=$enable_queue; +else + enableval=$db_cv_build_full +fi + +db_cv_build_queue="$enableval" +case "$enableval" in + no) { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; };; +yes) { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; };; +esac + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if --disable-replication option specified" >&5 +$as_echo_n "checking if --disable-replication option specified... " >&6; } +# Check whether --enable-replication was given. +if test "${enable_replication+set}" = set; then : + enableval=$enable_replication; +else + enableval=$db_cv_build_full +fi + +db_cv_build_replication="$enableval" +case "$enableval" in + no) { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; };; +yes) { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; };; +esac + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if --disable-statistics option specified" >&5 +$as_echo_n "checking if --disable-statistics option specified... " >&6; } +# Check whether --enable-statistics was given. +if test "${enable_statistics+set}" = set; then : + enableval=$enable_statistics; +else + enableval=$db_cv_build_full +fi + +db_cv_build_statistics="$enableval" +case "$enableval" in + no) { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; };; +yes) { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; };; +esac + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if --disable-verify option specified" >&5 +$as_echo_n "checking if --disable-verify option specified... " >&6; } +# Check whether --enable-verify was given. +if test "${enable_verify+set}" = set; then : + enableval=$enable_verify; +else + enableval=$db_cv_build_full +fi + +db_cv_build_verify="$enableval" +case "$enableval" in + no) { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; };; +yes) { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; };; +esac + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if --enable-compat185 option specified" >&5 +$as_echo_n "checking if --enable-compat185 option specified... " >&6; } +# Check whether --enable-compat185 was given. +if test "${enable_compat185+set}" = set; then : + enableval=$enable_compat185; db_cv_compat185="$enable_compat185" +else + db_cv_compat185="no" +fi + +if test $db_cv_compat185 = "yes" -a "$db_cv_rds" = "yes"; then + as_fn_error $? "--enable-compat185 is not compatible with --enable-rdsbuild" "$LINENO" 5 +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $db_cv_compat185" >&5 +$as_echo "$db_cv_compat185" >&6; } + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if --enable-cxx option specified" >&5 +$as_echo_n "checking if --enable-cxx option specified... " >&6; } +# Check whether --enable-cxx was given. +if test "${enable_cxx+set}" = set; then : + enableval=$enable_cxx; db_cv_cxx="$enable_cxx" +else + db_cv_cxx="no" +fi + +if test $db_cv_cxx = "yes" -a "$db_cv_rds" = "yes"; then + as_fn_error $? "--enable-cxx is not compatible with --enable-rdsbuild" "$LINENO" 5 +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $db_cv_cxx" >&5 +$as_echo "$db_cv_cxx" >&6; } + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if --enable-debug option specified" >&5 +$as_echo_n "checking if --enable-debug option specified... " >&6; } +# Check whether --enable-debug was given. +if test "${enable_debug+set}" = set; then : + enableval=$enable_debug; db_cv_debug="$enable_debug" +else + db_cv_debug="no" +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $db_cv_debug" >&5 +$as_echo "$db_cv_debug" >&6; } + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if --enable-debug_rop option specified" >&5 +$as_echo_n "checking if --enable-debug_rop option specified... " >&6; } +# Check whether --enable-debug_rop was given. +if test "${enable_debug_rop+set}" = set; then : + enableval=$enable_debug_rop; db_cv_debug_rop="$enable_debug_rop" +else + db_cv_debug_rop="no" +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $db_cv_debug_rop" >&5 +$as_echo "$db_cv_debug_rop" >&6; } + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if --enable-debug_wop option specified" >&5 +$as_echo_n "checking if --enable-debug_wop option specified... " >&6; } +# Check whether --enable-debug_wop was given. +if test "${enable_debug_wop+set}" = set; then : + enableval=$enable_debug_wop; db_cv_debug_wop="$enable_debug_wop" +else + db_cv_debug_wop="no" +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $db_cv_debug_wop" >&5 +$as_echo "$db_cv_debug_wop" >&6; } + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if --enable-diagnostic option specified" >&5 +$as_echo_n "checking if --enable-diagnostic option specified... " >&6; } +# Check whether --enable-diagnostic was given. +if test "${enable_diagnostic+set}" = set; then : + enableval=$enable_diagnostic; db_cv_diagnostic="$enable_diagnostic" +else + db_cv_diagnostic="no" +fi + +if test "$db_cv_diagnostic" = "yes"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $db_cv_diagnostic" >&5 +$as_echo "$db_cv_diagnostic" >&6; } +fi +if test "$db_cv_diagnostic" = "no" -a "$db_cv_debug_rop" = "yes"; then + db_cv_diagnostic="yes" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: by --enable-debug_rop" >&5 +$as_echo "by --enable-debug_rop" >&6; } +fi +if test "$db_cv_diagnostic" = "no" -a "$db_cv_debug_wop" = "yes"; then + db_cv_diagnostic="yes" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: by --enable-debug_wop" >&5 +$as_echo "by --enable-debug_wop" >&6; } +fi +if test "$db_cv_diagnostic" = "no"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $db_cv_diagnostic" >&5 +$as_echo "$db_cv_diagnostic" >&6; } +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if --enable-dump185 option specified" >&5 +$as_echo_n "checking if --enable-dump185 option specified... " >&6; } +# Check whether --enable-dump185 was given. +if test "${enable_dump185+set}" = set; then : + enableval=$enable_dump185; db_cv_dump185="$enable_dump185" +else + db_cv_dump185="no" +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $db_cv_dump185" >&5 +$as_echo "$db_cv_dump185" >&6; } + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if --enable-java option specified" >&5 +$as_echo_n "checking if --enable-java option specified... " >&6; } +# Check whether --enable-java was given. +if test "${enable_java+set}" = set; then : + enableval=$enable_java; db_cv_java="$enable_java" +else + db_cv_java="no" +fi + +if test $db_cv_java = "yes" -a "$db_cv_rds" = "yes"; then + as_fn_error $? "--enable-java is not compatible with --enable-rdsbuild" "$LINENO" 5 +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $db_cv_java" >&5 +$as_echo "$db_cv_java" >&6; } + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if --enable-mingw option specified" >&5 +$as_echo_n "checking if --enable-mingw option specified... " >&6; } +# Check whether --enable-mingw was given. +if test "${enable_mingw+set}" = set; then : + enableval=$enable_mingw; db_cv_mingw="$enable_mingw" +else + db_cv_mingw="no" +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $db_cv_mingw" >&5 +$as_echo "$db_cv_mingw" >&6; } + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if --enable-o_direct option specified" >&5 +$as_echo_n "checking if --enable-o_direct option specified... " >&6; } +# Check whether --enable-o_direct was given. +if test "${enable_o_direct+set}" = set; then : + enableval=$enable_o_direct; db_cv_o_direct="$enable_o_direct" +else + db_cv_o_direct="no" +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $db_cv_o_direct" >&5 +$as_echo "$db_cv_o_direct" >&6; } + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if --enable-posixmutexes option specified" >&5 +$as_echo_n "checking if --enable-posixmutexes option specified... " >&6; } +# Check whether --enable-posixmutexes was given. +if test "${enable_posixmutexes+set}" = set; then : + enableval=$enable_posixmutexes; db_cv_posixmutexes="$enable_posixmutexes" +else + db_cv_posixmutexes="no" +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $db_cv_posixmutexes" >&5 +$as_echo "$db_cv_posixmutexes" >&6; } + +# Check whether --enable-pthread_self was given. +if test "${enable_pthread_self+set}" = set; then : + enableval=$enable_pthread_self; { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: --enable-pthread_self is now always enabled" >&5 +$as_echo "$as_me: WARNING: --enable-pthread_self is now always enabled" >&2;} +fi + + +# Check whether --enable-pthread_api was given. +if test "${enable_pthread_api+set}" = set; then : + enableval=$enable_pthread_api; { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: --enable-pthread_api is now always enabled" >&5 +$as_echo "$as_me: WARNING: --enable-pthread_api is now always enabled" >&2;} +fi + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if --enable-rpc option specified" >&5 +$as_echo_n "checking if --enable-rpc option specified... " >&6; } +# Check whether --enable-rpc was given. +if test "${enable_rpc+set}" = set; then : + enableval=$enable_rpc; as_fn_error $? "RPC support has been removed from Berkeley DB." "$LINENO" 5 + +else + db_cv_rpc="no" +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $db_cv_rpc" >&5 +$as_echo "$db_cv_rpc" >&6; } + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if --enable-sql option specified" >&5 +$as_echo_n "checking if --enable-sql option specified... " >&6; } +# Check whether --enable-sql was given. +if test "${enable_sql+set}" = set; then : + enableval=$enable_sql; db_cv_sql="$enable_sql" +else + db_cv_sql="no" +fi + +if test $db_cv_sql = "yes" -a "$db_cv_rds" = "yes"; then + as_fn_error $? "--enable-sql is not compatible with --enable-rdsbuild" "$LINENO" 5 +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $db_cv_sql" >&5 +$as_echo "$db_cv_sql" >&6; } + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if --enable-sql_compat option specified" >&5 +$as_echo_n "checking if --enable-sql_compat option specified... " >&6; } +# Check whether --enable-sql_compat was given. +if test "${enable_sql_compat+set}" = set; then : + enableval=$enable_sql_compat; db_cv_sql_compat="$enable_sql_compat" +else + db_cv_sql_compat="no" +fi + +if test $db_cv_sql_compat = "yes" -a "$db_cv_rds" = "yes"; then + as_fn_error $? "--enable-sql_compat is not compatible with --enable-rdsbuild" "$LINENO" 5 +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $db_cv_sql_compat" >&5 +$as_echo "$db_cv_sql_compat" >&6; } + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if --enable-jdbc option specified" >&5 +$as_echo_n "checking if --enable-jdbc option specified... " >&6; } +# Check whether --enable-jdbc was given. +if test "${enable_jdbc+set}" = set; then : + enableval=$enable_jdbc; db_cv_jdbc="$enable_jdbc" +else + db_cv_jdbc="no" +fi + +if test $db_cv_jdbc = "yes" -a "$db_cv_rds" = "yes"; then + as_fn_error $? "--enable-jdbc is not compatible with --enable-rdsbuild" "$LINENO" 5 +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $db_cv_jdbc" >&5 +$as_echo "$db_cv_jdbc" >&6; } + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if --with-jdbc=DIR option specified" >&5 +$as_echo_n "checking if --with-jdbc=DIR option specified... " >&6; } + +# Check whether --with-jdbc was given. +if test "${with_jdbc+set}" = set; then : + withval=$with_jdbc; with_jdbc="$withval" +else + with_jdbc="no" +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $with_jdbc" >&5 +$as_echo "$with_jdbc" >&6; } +if test "$with_jdbc" != "no"; then + db_cv_jdbc="yes" +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if --enable-amalgamation option specified" >&5 +$as_echo_n "checking if --enable-amalgamation option specified... " >&6; } +# Check whether --enable-amalgamation was given. +if test "${enable_amalgamation+set}" = set; then : + enableval=$enable_amalgamation; db_cv_sql_amalgamation="$enable_amalgamation" +else + db_cv_sql_amalgamation="no" +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $db_cv_sql_amalgamation" >&5 +$as_echo "$db_cv_sql_amalgamation" >&6; } + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if --enable-sql_codegen option specified" >&5 +$as_echo_n "checking if --enable-sql_codegen option specified... " >&6; } +# Check whether --enable-sql_codegen was given. +if test "${enable_sql_codegen+set}" = set; then : + enableval=$enable_sql_codegen; db_cv_sql_codegen="$enable_sql_codegen" +else + db_cv_sql_codegen="no" +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $db_cv_sql_codegen" >&5 +$as_echo "$db_cv_sql_codegen" >&6; } + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if --enable-stl option specified" >&5 +$as_echo_n "checking if --enable-stl option specified... " >&6; } +# Check whether --enable-stl was given. +if test "${enable_stl+set}" = set; then : + enableval=$enable_stl; db_cv_stl="$enable_stl" +else + db_cv_stl="no" +fi + +if test $db_cv_stl = "yes" -a "$db_cv_rds" = "yes"; then + as_fn_error $? "--enable-stl is not compatible with --enable-rdsbuild" "$LINENO" 5 +fi +if test "$db_cv_stl" = "yes" -a "$db_cv_cxx" = "no"; then + db_cv_cxx="yes" +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $db_cv_stl" >&5 +$as_echo "$db_cv_stl" >&6; } + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if --enable-tcl option specified" >&5 +$as_echo_n "checking if --enable-tcl option specified... " >&6; } +# Check whether --enable-tcl was given. +if test "${enable_tcl+set}" = set; then : + enableval=$enable_tcl; db_cv_tcl="$enable_tcl" +else + db_cv_tcl="no" +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $db_cv_tcl" >&5 +$as_echo "$db_cv_tcl" >&6; } + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if --enable-test option specified" >&5 +$as_echo_n "checking if --enable-test option specified... " >&6; } +# Check whether --enable-test was given. +if test "${enable_test+set}" = set; then : + enableval=$enable_test; db_cv_test="$enable_test" +else + db_cv_test="no" +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $db_cv_test" >&5 +$as_echo "$db_cv_test" >&6; } + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if --enable-localization option specified" >&5 +$as_echo_n "checking if --enable-localization option specified... " >&6; } +# Check whether --enable-localization was given. +if test "${enable_localization+set}" = set; then : + enableval=$enable_localization; db_cv_localization="$enable_localization" +else + db_cv_localization="no" +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $db_cv_localization" >&5 +$as_echo "$db_cv_localization" >&6; } + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if --enable-stripped_messages option specified" >&5 +$as_echo_n "checking if --enable-stripped_messages option specified... " >&6; } +# Check whether --enable-stripped_messages was given. +if test "${enable_stripped_messages+set}" = set; then : + enableval=$enable_stripped_messages; db_cv_stripped_messages="$enable_stripped_messages" +else + db_cv_stripped_messages="no" +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $db_cv_stripped_messages" >&5 +$as_echo "$db_cv_stripped_messages" >&6; } + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if --enable-dbm option specified" >&5 +$as_echo_n "checking if --enable-dbm option specified... " >&6; } +# Check whether --enable-dbm was given. +if test "${enable_dbm+set}" = set; then : + enableval=$enable_dbm; db_cv_dbm="$enable_dbm" +else + db_cv_dbm="$db_cv_test" +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $db_cv_dbm" >&5 +$as_echo "$db_cv_dbm" >&6; } + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if --enable-dtrace option specified" >&5 +$as_echo_n "checking if --enable-dtrace option specified... " >&6; } +# Check whether --enable-dtrace was given. +if test "${enable_dtrace+set}" = set; then : + enableval=$enable_dtrace; db_cv_dtrace="$enable_dtrace" +else + db_cv_dtrace="no" +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $db_cv_dtrace" >&5 +$as_echo "$db_cv_dtrace" >&6; } + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if --enable-systemtap option specified" >&5 +$as_echo_n "checking if --enable-systemtap option specified... " >&6; } +# Check whether --enable-systemtap was given. +if test "${enable_systemtap+set}" = set; then : + enableval=$enable_systemtap; db_cv_systemtap="$enable_systemtap" +else + db_cv_systemtap="no" +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $db_cv_systemtap" >&5 +$as_echo "$db_cv_systemtap" >&6; } + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if --enable-perfmon-statistics option specified" >&5 +$as_echo_n "checking if --enable-perfmon-statistics option specified... " >&6; } +# Check whether --enable-perfmon_statistics was given. +if test "${enable_perfmon_statistics+set}" = set; then : + enableval=$enable_perfmon_statistics; db_cv_perfmon_statistics="$enable_perfmon_statistics" +else + db_cv_perfmon_statistics="no" +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $db_cv_perfmon_statistics" >&5 +$as_echo "$db_cv_perfmon_statistics" >&6; } + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if --enable-uimutexes option specified" >&5 +$as_echo_n "checking if --enable-uimutexes option specified... " >&6; } +# Check whether --enable-uimutexes was given. +if test "${enable_uimutexes+set}" = set; then : + enableval=$enable_uimutexes; db_cv_uimutexes="$enable_uimutexes" +else + db_cv_uimutexes="no" +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $db_cv_uimutexes" >&5 +$as_echo "$db_cv_uimutexes" >&6; } + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if --enable-umrw option specified" >&5 +$as_echo_n "checking if --enable-umrw option specified... " >&6; } +# Check whether --enable-umrw was given. +if test "${enable_umrw+set}" = set; then : + enableval=$enable_umrw; db_cv_umrw="$enable_umrw" +else + db_cv_umrw="no" +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $db_cv_umrw" >&5 +$as_echo "$db_cv_umrw" >&6; } + +# Solaris, AI/X, OS/X and other BSD-derived systems default to POSIX-conforming +# disk i/o: A single read or write call is atomic. Other systems do not +# guarantee atomicity; in particular Linux and Microsoft Windows. +atomicfileread="no" +case "$host_os" in +solaris* | aix* | bsdi3* | freebsd* | darwin*) + atomicfileread="yes";; +esac +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if --enable-atomicfileread option specified" >&5 +$as_echo_n "checking if --enable-atomicfileread option specified... " >&6; } +# Check whether --enable-atomicfileread was given. +if test "${enable_atomicfileread+set}" = set; then : + enableval=$enable_atomicfileread; db_cv_atomicfileread="$enable_atomicfileread" +else + db_cv_atomicfileread=$atomicfileread +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $db_cv_atomicfileread" >&5 +$as_echo "$db_cv_atomicfileread" >&6; } +if test "$db_cv_atomicfileread" = "yes"; then + $as_echo "#define HAVE_ATOMICFILEREAD 1" >>confdefs.h + + +fi + +# Cryptography support. +# Until Berkeley DB 5.0, this was a simple yes/no decision. +# With the addition of support for Intel Integrated Performance Primitives (ipp) +# things are more complex. There are now three options: +# 1) don't build cryptography (no) +# 2) build using the built-in software implementation (yes) +# 3) build using the Intel IPP implementation (ipp) +# We handle this by making the primary configuration method: +# --with-cryptography={yes|no|ipp} +# which defaults to yes. The old enable/disable-cryptography argument is still +# supported for backwards compatibility. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if --with-cryptography option specified" >&5 +$as_echo_n "checking if --with-cryptography option specified... " >&6; } +# Check whether --enable-cryptography was given. +if test "${enable_cryptography+set}" = set; then : + enableval=$enable_cryptography; +else + enableval=$db_cv_build_full +fi + +enable_cryptography="$enableval" + +# Check whether --with-cryptography was given. +if test "${with_cryptography+set}" = set; then : + withval=$with_cryptography; +else + with_cryptography=$enable_cryptography +fi + +case "$with_cryptography" in +yes|no|ipp) ;; +*) as_fn_error $? "unknown --with-cryptography argument \'$with_cryptography\'" "$LINENO" 5 ;; +esac +db_cv_build_cryptography="$with_cryptography" +if test $db_cv_build_cryptography != "no" -a "$db_cv_rds" = "yes"; then + as_fn_error $? "--with_cryptography is not compatible with --enable-rdsbuild" "$LINENO" 5 +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $db_cv_build_cryptography" >&5 +$as_echo "$db_cv_build_cryptography" >&6; } + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if --with-mutex=MUTEX option specified" >&5 +$as_echo_n "checking if --with-mutex=MUTEX option specified... " >&6; } + +# Check whether --with-mutex was given. +if test "${with_mutex+set}" = set; then : + withval=$with_mutex; with_mutex="$withval" +else + with_mutex="no" +fi + +if test "$with_mutex" = "yes"; then + as_fn_error $? "--with-mutex requires a mutex name argument" "$LINENO" 5 +fi +if test "$with_mutex" != "no"; then + db_cv_mutex="$with_mutex" +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $with_mutex" >&5 +$as_echo "$with_mutex" >&6; } + +# --with-mutexalign=ALIGNMENT was the configuration option that Berkeley DB +# used before the DbEnv::mutex_set_align method was added. + +# Check whether --with-mutexalign was given. +if test "${with_mutexalign+set}" = set; then : + withval=$with_mutexalign; as_fn_error $? "--with-mutexalign no longer supported, use DbEnv::mutex_set_align" "$LINENO" 5 +fi + + + +# Check whether --with-stacksize was given. +if test "${with_stacksize+set}" = set; then : + withval=$with_stacksize; with_stacksize="$withval" +else + with_stacksize="no" +fi + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if --with-tcl=DIR option specified" >&5 +$as_echo_n "checking if --with-tcl=DIR option specified... " >&6; } + +# Check whether --with-tcl was given. +if test "${with_tcl+set}" = set; then : + withval=$with_tcl; with_tclconfig="$withval" +else + with_tclconfig="no" +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $with_tclconfig" >&5 +$as_echo "$with_tclconfig" >&6; } +if test "$with_tclconfig" != "no"; then + db_cv_tcl="yes" +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if --with-uniquename=NAME option specified" >&5 +$as_echo_n "checking if --with-uniquename=NAME option specified... " >&6; } + +# Check whether --with-uniquename was given. +if test "${with_uniquename+set}" = set; then : + withval=$with_uniquename; with_uniquename="$withval" +else + with_uniquename="no" +fi + +if test "$with_uniquename" = "no"; then + db_cv_uniquename="no" + DB_VERSION_UNIQUE_NAME="" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $with_uniquename" >&5 +$as_echo "$with_uniquename" >&6; } +else + db_cv_uniquename="yes" + if test "$db_cv_rds" = "yes"; then + as_fn_error $? "--with-uniquename is not compatible with --enable-rdsbuild" "$LINENO" 5 + fi + if test "$with_uniquename" = "yes"; then + DB_VERSION_UNIQUE_NAME="_5004" + else + DB_VERSION_UNIQUE_NAME="$with_uniquename" + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DB_VERSION_UNIQUE_NAME" >&5 +$as_echo "$DB_VERSION_UNIQUE_NAME" >&6; } +fi + +# Undocumented option used for the dbsql command line tool (to match SQLite). +# Check whether --enable-readline was given. +if test "${enable_readline+set}" = set; then : + enableval=$enable_readline; with_readline=$enableval +else + with_readline=no +fi + + +# --enable-sql_compat implies --enable-sql +if test "$db_cv_sql_compat" = "yes" -a "$db_cv_sql" = "no"; then + db_cv_sql=$db_cv_sql_compat +fi + +# --enable-jdbc implies --enable-sql +if test "$db_cv_jdbc" = "yes" -a "$db_cv_sql" = "no"; then + db_cv_sql=$db_cv_jdbc +fi + +# Testing requires Tcl. +if test "$db_cv_test" = "yes" -a "$db_cv_tcl" = "no"; then + as_fn_error $? "--enable-test requires --enable-tcl" "$LINENO" 5 +fi + +# Set some #defines based on configuration options. +if test "$db_cv_diagnostic" = "yes"; then + $as_echo "#define DIAGNOSTIC 1" >>confdefs.h + + +fi +if test "$db_cv_debug_rop" = "yes"; then + $as_echo "#define DEBUG_ROP 1" >>confdefs.h + + +fi +if test "$db_cv_debug_wop" = "yes"; then + $as_echo "#define DEBUG_WOP 1" >>confdefs.h + + +fi +if test "$db_cv_umrw" = "yes"; then + $as_echo "#define UMRW 1" >>confdefs.h + + + +fi +if test "$db_cv_test" = "yes"; then + $as_echo "#define CONFIG_TEST 1" >>confdefs.h + + +fi + + +$as_echo "#define HAVE_UPGRADE_SUPPORT 1" >>confdefs.h + + +# Check for programs used in building and installation. + + +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}chmod", so it can be a program name with args. +set dummy ${ac_tool_prefix}chmod; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CHMOD+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CHMOD"; then + ac_cv_prog_CHMOD="$CHMOD" # 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_CHMOD="${ac_tool_prefix}chmod" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CHMOD=$ac_cv_prog_CHMOD +if test -n "$CHMOD"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CHMOD" >&5 +$as_echo "$CHMOD" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_CHMOD"; then + ac_ct_CHMOD=$CHMOD + # Extract the first word of "chmod", so it can be a program name with args. +set dummy chmod; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_CHMOD+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_CHMOD"; then + ac_cv_prog_ac_ct_CHMOD="$ac_ct_CHMOD" # 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_CHMOD="chmod" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_CHMOD=$ac_cv_prog_ac_ct_CHMOD +if test -n "$ac_ct_CHMOD"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CHMOD" >&5 +$as_echo "$ac_ct_CHMOD" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_CHMOD" = x; then + CHMOD="none" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + CHMOD=$ac_ct_CHMOD + fi +else + CHMOD="$ac_cv_prog_CHMOD" +fi + +test "$CHMOD" = "none" && as_fn_error $? "No chmod utility found." "$LINENO" 5 + +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}cp", so it can be a program name with args. +set dummy ${ac_tool_prefix}cp; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CP"; then + ac_cv_prog_CP="$CP" # 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_CP="${ac_tool_prefix}cp" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CP=$ac_cv_prog_CP +if test -n "$CP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CP" >&5 +$as_echo "$CP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_CP"; then + ac_ct_CP=$CP + # Extract the first word of "cp", so it can be a program name with args. +set dummy cp; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_CP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_CP"; then + ac_cv_prog_ac_ct_CP="$ac_ct_CP" # 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_CP="cp" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_CP=$ac_cv_prog_ac_ct_CP +if test -n "$ac_ct_CP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CP" >&5 +$as_echo "$ac_ct_CP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_CP" = x; then + CP="none" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + CP=$ac_ct_CP + fi +else + CP="$ac_cv_prog_CP" +fi + +test "$CP" = "none" && as_fn_error $? "No cp utility found." "$LINENO" 5 + +# The Tcl test suite requires a kill utility. +if test "$db_cv_test" = "yes"; then + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}kill", so it can be a program name with args. +set dummy ${ac_tool_prefix}kill; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_KILL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$KILL"; then + ac_cv_prog_KILL="$KILL" # 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_KILL="${ac_tool_prefix}kill" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +KILL=$ac_cv_prog_KILL +if test -n "$KILL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $KILL" >&5 +$as_echo "$KILL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_KILL"; then + ac_ct_KILL=$KILL + # Extract the first word of "kill", so it can be a program name with args. +set dummy kill; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_KILL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_KILL"; then + ac_cv_prog_ac_ct_KILL="$ac_ct_KILL" # 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_KILL="kill" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_KILL=$ac_cv_prog_ac_ct_KILL +if test -n "$ac_ct_KILL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_KILL" >&5 +$as_echo "$ac_ct_KILL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_KILL" = x; then + KILL="none" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + KILL=$ac_ct_KILL + fi +else + KILL="$ac_cv_prog_KILL" +fi + + test "$KILL" = "none" && as_fn_error $? "No kill utility found." "$LINENO" 5 +fi + +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}ln", so it can be a program name with args. +set dummy ${ac_tool_prefix}ln; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_LN+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$LN"; then + ac_cv_prog_LN="$LN" # 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_LN="${ac_tool_prefix}ln" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +LN=$ac_cv_prog_LN +if test -n "$LN"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LN" >&5 +$as_echo "$LN" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_LN"; then + ac_ct_LN=$LN + # Extract the first word of "ln", so it can be a program name with args. +set dummy ln; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_LN+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_LN"; then + ac_cv_prog_ac_ct_LN="$ac_ct_LN" # 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_LN="ln" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_LN=$ac_cv_prog_ac_ct_LN +if test -n "$ac_ct_LN"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_LN" >&5 +$as_echo "$ac_ct_LN" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_LN" = x; then + LN="none" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + LN=$ac_ct_LN + fi +else + LN="$ac_cv_prog_LN" +fi + +test "$LN" = "none" && as_fn_error $? "No ln utility found." "$LINENO" 5 + +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}mkdir", so it can be a program name with args. +set dummy ${ac_tool_prefix}mkdir; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_MKDIR+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$MKDIR"; then + ac_cv_prog_MKDIR="$MKDIR" # 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_MKDIR="${ac_tool_prefix}mkdir" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +MKDIR=$ac_cv_prog_MKDIR +if test -n "$MKDIR"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MKDIR" >&5 +$as_echo "$MKDIR" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_MKDIR"; then + ac_ct_MKDIR=$MKDIR + # Extract the first word of "mkdir", so it can be a program name with args. +set dummy mkdir; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_MKDIR+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_MKDIR"; then + ac_cv_prog_ac_ct_MKDIR="$ac_ct_MKDIR" # 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_MKDIR="mkdir" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_MKDIR=$ac_cv_prog_ac_ct_MKDIR +if test -n "$ac_ct_MKDIR"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_MKDIR" >&5 +$as_echo "$ac_ct_MKDIR" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_MKDIR" = x; then + MKDIR="none" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + MKDIR=$ac_ct_MKDIR + fi +else + MKDIR="$ac_cv_prog_MKDIR" +fi + +test "$MKDIR" = "none" && as_fn_error $? "No mkdir utility found." "$LINENO" 5 + +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}rm", so it can be a program name with args. +set dummy ${ac_tool_prefix}rm; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_RM+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$RM"; then + ac_cv_prog_RM="$RM" # 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_RM="${ac_tool_prefix}rm" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +RM=$ac_cv_prog_RM +if test -n "$RM"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $RM" >&5 +$as_echo "$RM" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_RM"; then + ac_ct_RM=$RM + # Extract the first word of "rm", so it can be a program name with args. +set dummy rm; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_RM+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_RM"; then + ac_cv_prog_ac_ct_RM="$ac_ct_RM" # 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_RM="rm" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_RM=$ac_cv_prog_ac_ct_RM +if test -n "$ac_ct_RM"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_RM" >&5 +$as_echo "$ac_ct_RM" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_RM" = x; then + RM="none" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + RM=$ac_ct_RM + fi +else + RM="$ac_cv_prog_RM" +fi + +test "$RM" = "none" && as_fn_error $? "No rm utility found." "$LINENO" 5 + +# We always want to force removes, and libtool assumes the same. +RM="$RM -f" + +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}mv", so it can be a program name with args. +set dummy ${ac_tool_prefix}mv; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_MV+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$MV"; then + ac_cv_prog_MV="$MV" # 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_MV="${ac_tool_prefix}mv" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +MV=$ac_cv_prog_MV +if test -n "$MV"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MV" >&5 +$as_echo "$MV" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_MV"; then + ac_ct_MV=$MV + # Extract the first word of "mv", so it can be a program name with args. +set dummy mv; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_MV+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_MV"; then + ac_cv_prog_ac_ct_MV="$ac_ct_MV" # 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_MV="mv" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_MV=$ac_cv_prog_ac_ct_MV +if test -n "$ac_ct_MV"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_MV" >&5 +$as_echo "$ac_ct_MV" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_MV" = x; then + MV="none" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + MV=$ac_ct_MV + fi +else + MV="$ac_cv_prog_MV" +fi + +test "$MV" = "none" && as_fn_error $? "No mv utility found." "$LINENO" 5 + +if test "$db_cv_systemtap" = "yes" -o "$db_cv_dtrace" = "yes"; then + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}stap", so it can be a program name with args. +set dummy ${ac_tool_prefix}stap; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_STAP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$STAP"; then + ac_cv_prog_STAP="$STAP" # 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_STAP="${ac_tool_prefix}stap" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +STAP=$ac_cv_prog_STAP +if test -n "$STAP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $STAP" >&5 +$as_echo "$STAP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_STAP"; then + ac_ct_STAP=$STAP + # Extract the first word of "stap", so it can be a program name with args. +set dummy stap; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_STAP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_STAP"; then + ac_cv_prog_ac_ct_STAP="$ac_ct_STAP" # 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_STAP="stap" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_STAP=$ac_cv_prog_ac_ct_STAP +if test -n "$ac_ct_STAP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_STAP" >&5 +$as_echo "$ac_ct_STAP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_STAP" = x; then + STAP="none" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + STAP=$ac_ct_STAP + fi +else + STAP="$ac_cv_prog_STAP" +fi + + test "$STAP" = "none" -a "$db_cv_systemtap" = "yes" && \ + as_fn_error $? "No stap utility found." "$LINENO" 5 + db_cv_dtrace=yes +fi + +if test "$db_cv_dtrace" = "yes"; then + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}dtrace", so it can be a program name with args. +set dummy ${ac_tool_prefix}dtrace; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_DTRACE+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$DTRACE"; then + ac_cv_prog_DTRACE="$DTRACE" # 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_DTRACE="${ac_tool_prefix}dtrace" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +DTRACE=$ac_cv_prog_DTRACE +if test -n "$DTRACE"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DTRACE" >&5 +$as_echo "$DTRACE" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_DTRACE"; then + ac_ct_DTRACE=$DTRACE + # Extract the first word of "dtrace", so it can be a program name with args. +set dummy dtrace; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_DTRACE+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_DTRACE"; then + ac_cv_prog_ac_ct_DTRACE="$ac_ct_DTRACE" # 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_DTRACE="dtrace" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_DTRACE=$ac_cv_prog_ac_ct_DTRACE +if test -n "$ac_ct_DTRACE"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DTRACE" >&5 +$as_echo "$ac_ct_DTRACE" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_DTRACE" = x; then + DTRACE="none" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + DTRACE=$ac_ct_DTRACE + fi +else + DTRACE="$ac_cv_prog_DTRACE" +fi + + test "$DTRACE" = "none" && as_fn_error $? "No dtrace utility found." "$LINENO" 5 + # Sed and perl are needed only if events are added after building + # the distribution; if either is missing it is not an error for now. + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}sed", so it can be a program name with args. +set dummy ${ac_tool_prefix}sed; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_SED+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$SED"; then + ac_cv_prog_SED="$SED" # 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_SED="${ac_tool_prefix}sed" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +SED=$ac_cv_prog_SED +if test -n "$SED"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $SED" >&5 +$as_echo "$SED" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_SED"; then + ac_ct_SED=$SED + # Extract the first word of "sed", so it can be a program name with args. +set dummy sed; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_SED+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_SED"; then + ac_cv_prog_ac_ct_SED="$ac_ct_SED" # 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_SED="sed" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_SED=$ac_cv_prog_ac_ct_SED +if test -n "$ac_ct_SED"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_SED" >&5 +$as_echo "$ac_ct_SED" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_SED" = x; then + SED="none" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + SED=$ac_ct_SED + fi +else + SED="$ac_cv_prog_SED" +fi + + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}perl", so it can be a program name with args. +set dummy ${ac_tool_prefix}perl; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_PERL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$PERL"; then + ac_cv_prog_PERL="$PERL" # 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_PERL="${ac_tool_prefix}perl" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +PERL=$ac_cv_prog_PERL +if test -n "$PERL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PERL" >&5 +$as_echo "$PERL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_PERL"; then + ac_ct_PERL=$PERL + # Extract the first word of "perl", so it can be a program name with args. +set dummy perl; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_PERL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_PERL"; then + ac_cv_prog_ac_ct_PERL="$ac_ct_PERL" # 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_PERL="perl" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_PERL=$ac_cv_prog_ac_ct_PERL +if test -n "$ac_ct_PERL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_PERL" >&5 +$as_echo "$ac_ct_PERL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_PERL" = x; then + PERL="none" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + PERL=$ac_ct_PERL + fi +else + PERL="$ac_cv_prog_PERL" +fi + +fi + +# We need a complete path for sh, because some make utility implementations get +# upset if SHELL is set to just the command name. Don't use the SHELL variable +# here because the user likely has the SHELL variable set to something other +# than the Bourne shell, which is what Make wants. +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}sh", so it can be a program name with args. +set dummy ${ac_tool_prefix}sh; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_db_cv_path_sh+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $db_cv_path_sh in + [\\/]* | ?:[\\/]*) + ac_cv_path_db_cv_path_sh="$db_cv_path_sh" # Let the user override the test with a path. + ;; + *) + 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_path_db_cv_path_sh="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + ;; +esac +fi +db_cv_path_sh=$ac_cv_path_db_cv_path_sh +if test -n "$db_cv_path_sh"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $db_cv_path_sh" >&5 +$as_echo "$db_cv_path_sh" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_path_db_cv_path_sh"; then + ac_pt_db_cv_path_sh=$db_cv_path_sh + # Extract the first word of "sh", so it can be a program name with args. +set dummy sh; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_ac_pt_db_cv_path_sh+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $ac_pt_db_cv_path_sh in + [\\/]* | ?:[\\/]*) + ac_cv_path_ac_pt_db_cv_path_sh="$ac_pt_db_cv_path_sh" # Let the user override the test with a path. + ;; + *) + 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_path_ac_pt_db_cv_path_sh="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + ;; +esac +fi +ac_pt_db_cv_path_sh=$ac_cv_path_ac_pt_db_cv_path_sh +if test -n "$ac_pt_db_cv_path_sh"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_pt_db_cv_path_sh" >&5 +$as_echo "$ac_pt_db_cv_path_sh" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_pt_db_cv_path_sh" = x; then + db_cv_path_sh="none" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + db_cv_path_sh=$ac_pt_db_cv_path_sh + fi +else + db_cv_path_sh="$ac_cv_path_db_cv_path_sh" +fi + +test "$db_cv_path_sh" = "none" && as_fn_error $? "No sh utility found." "$LINENO" 5 + +# Don't strip the binaries if --enable-debug was specified. +if test "$db_cv_debug" = yes; then + STRIP=":" +fi +# Find a good install program. We prefer a C program (faster), +# so one script is as good as another. But avoid the broken or +# incompatible versions: +# SysV /etc/install, /usr/sbin/install +# SunOS /usr/etc/install +# IRIX /sbin/install +# AIX /bin/install +# AmigaOS /C/install, which installs bootblocks on floppy discs +# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag +# AFS /usr/afsws/bin/install, which mishandles nonexistent args +# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" +# OS/2's system install, which has a completely different semantic +# ./install, which can be erroneously created by make from ./install.sh. +# Reject install programs that cannot install multiple files. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a BSD-compatible install" >&5 +$as_echo_n "checking for a BSD-compatible install... " >&6; } +if test -z "$INSTALL"; then +if ${ac_cv_path_install+:} false; then : + $as_echo_n "(cached) " >&6 +else + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + # Account for people who put trailing slashes in PATH elements. +case $as_dir/ in #(( + ./ | .// | /[cC]/* | \ + /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \ + ?:[\\/]os2[\\/]install[\\/]* | ?:[\\/]OS2[\\/]INSTALL[\\/]* | \ + /usr/ucb/* ) ;; + *) + # OSF1 and SCO ODT 3.0 have their own names for install. + # Don't use installbsd from OSF since it installs stuff as root + # by default. + for ac_prog in ginstall scoinst install; do + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_prog$ac_exec_ext" && $as_test_x "$as_dir/$ac_prog$ac_exec_ext"; }; then + if test $ac_prog = install && + grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then + # AIX install. It has an incompatible calling convention. + : + elif test $ac_prog = install && + grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then + # program-specific install script used by HP pwplus--don't use. + : + else + rm -rf conftest.one conftest.two conftest.dir + echo one > conftest.one + echo two > conftest.two + mkdir conftest.dir + if "$as_dir/$ac_prog$ac_exec_ext" -c conftest.one conftest.two "`pwd`/conftest.dir" && + test -s conftest.one && test -s conftest.two && + test -s conftest.dir/conftest.one && + test -s conftest.dir/conftest.two + then + ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c" + break 3 + fi + fi + fi + done + done + ;; +esac + + done +IFS=$as_save_IFS + +rm -rf conftest.one conftest.two conftest.dir + +fi + if test "${ac_cv_path_install+set}" = set; then + INSTALL=$ac_cv_path_install + else + # As a last resort, use the slow shell script. Don't cache a + # value for INSTALL within a source directory, because that will + # break other packages using the cache if that directory is + # removed, or if the value is a relative name. + INSTALL=$ac_install_sh + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $INSTALL" >&5 +$as_echo "$INSTALL" >&6; } + +# Use test -z because SunOS4 sh mishandles braces in ${var-val}. +# It thinks the first close brace ends the variable substitution. +test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}' + +test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}' + +test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' + + +BUILD_TARGET="library_build" +INSTALL_TARGET="library_install" + +# Respect the environment LIBS settings +LIBSO_LIBS="$LIBS" + +# This is where we handle stuff that autoconf can't handle: compiler, +# preprocessor and load flags, libraries that the standard tests don't +# look for. +# +# There are additional libraries we need for some compiler/architecture +# combinations. +# +# Some architectures require DB to be compiled with special flags and/or +# libraries for threaded applications +# +# The makefile CC may be different than the CC used in config testing, +# because the makefile CC may be set to use $(LIBTOOL). +# +# Don't override anything if it's already set from the environment. +optimize_flag="-O" +extra_cflags="" + +case "$host_os" in +aix4.3.*|aix[56]*) + case "$host_os" in + aix4.3.*) + CPPFLAGS="$CPPFLAGS -D_LINUX_SOURCE_COMPAT";; + esac + # IBM's XLC compilers (at least versions 7/8/9) generate incorrect code + # when ordinary optimization is enabled because they make strong + # assumptions about the types held at each memory location, and some + # Berkeley DB code violates those assumptions. [#16141] + extra_cflags=" -qalias=noansi" + optimize_flag="-O2" + CC=${CC-"xlc_r"} + CPPFLAGS="$CPPFLAGS -D_THREAD_SAFE" + LDFLAGS="$LDFLAGS -Wl,-brtl";; +bsdi3*) CC=${CC-"shlicc2"} + LIBSO_LIBS="$LIBSO_LIBS -lipc";; +cygwin*) + CPPFLAGS="$CPPFLAGS -D_GNU_SOURCE -D_REENTRANT";; +freebsd*) + CPPFLAGS="$CPPFLAGS -D_THREAD_SAFE" + LDFLAGS="$LDFLAGS -pthread";; +gnu*|k*bsd*-gnu|linux*) + CPPFLAGS="$CPPFLAGS -D_GNU_SOURCE -D_REENTRANT";; +hpux*) CPPFLAGS="$CPPFLAGS -D_REENTRANT";; +irix*) optimize_flag="-O2" + CPPFLAGS="$CPPFLAGS -D_SGI_MP_SOURCE";; +mpeix*) CPPFLAGS="$CPPFLAGS -D_POSIX_SOURCE -D_SOCKET_SOURCE" + LIBSO_LIBS="$LIBSO_LIBS -lsocket -lsvipc";; +osf*) CPPFLAGS="$CPPFLAGS -pthread";; +*qnx*) qnx_build="yes" + $as_echo "#define HAVE_QNX 1" >>confdefs.h + + ;; +solaris*) + CPPFLAGS="$CPPFLAGS -D_REENTRANT -D_POSIX_PTHREAD_SEMANTICS ";; +esac + +# Set CFLAGS/CXXFLAGS. We MUST set the flags before we call autoconf +# compiler configuration macros, because if we don't, they set CFLAGS +# to no optimization and -g, which isn't what we want. +# +# If the user wants a debugging environment, add -g the their compiler flags +# and don't automatically optimize. If you want to compile with a different +# set of flags, specify CFLAGS in the environment before configuring. +if test "$db_cv_debug" = "yes"; then + $as_echo "#define DEBUG 1" >>confdefs.h + + + + CFLAGS="-g $CFLAGS" +else + CFLAGS=${CFLAGS-$optimize_flag} +fi + +CFLAGS="$CFLAGS$extra_cflags" +CXXFLAGS=${CXXFLAGS-"$CFLAGS"} + +# The default compiler is cc (NOT gcc), the default CFLAGS is as specified +# above, NOT what is set by AC_PROG_CC, as it won't set optimization flags +# for any compiler other than gcc. +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 + for ac_prog in cc gcc + 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 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CC+:} false; then : + $as_echo_n "(cached) " >&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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_CC="$ac_tool_prefix$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5 +$as_echo "$CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$CC" && break + done +fi +if test -z "$CC"; then + ac_ct_CC=$CC + for ac_prog in cc gcc +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_CC+:} false; then : + $as_echo_n "(cached) " >&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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_CC="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5 +$as_echo "$ac_ct_CC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$ac_ct_CC" && break +done + + if test "x$ac_ct_CC" = x; then + CC="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + CC=$ac_ct_CC + fi +fi + + +test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "no acceptable C compiler found in \$PATH +See \`config.log' for more details" "$LINENO" 5; } + +# Provide some information about the compiler. +$as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5 +set X $ac_compile +ac_compiler=$2 +for ac_option in --version -v -V -qversion; do + { { ac_try="$ac_compiler $ac_option >&5" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_compiler $ac_option >&5") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + sed '10a\ +... rest of stderr output deleted ... + 10q' conftest.err >conftest.er1 + cat conftest.er1 >&5 + fi + rm -f conftest.er1 conftest.err + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } +done + +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +ac_clean_files_save=$ac_clean_files +ac_clean_files="$ac_clean_files a.out a.out.dSYM 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. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5 +$as_echo_n "checking whether the C compiler works... " >&6; } +ac_link_default=`$as_echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'` + +# The possible output files: +ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*" + +ac_rmfiles= +for ac_file in $ac_files +do + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; + * ) ac_rmfiles="$ac_rmfiles $ac_file";; + esac +done +rm -f $ac_rmfiles + +if { { ac_try="$ac_link_default" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link_default") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then : + # Autoconf-2.13 could set the ac_cv_exeext variable to `no'. +# So ignore a value of `no', otherwise this would lead to `EXEEXT = no' +# in a Makefile. We should not override ac_cv_exeext if it was cached, +# so that the user can short-circuit this test for compilers unknown to +# Autoconf. +for ac_file in $ac_files '' +do + test -f "$ac_file" || continue + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) + ;; + [ab].out ) + # We found the default executable, but exeext='' is most + # certainly right. + break;; + *.* ) + if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no; + then :; else + ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` + fi + # We set ac_cv_exeext here because the later test for it is not + # safe: cross compilers may not add the suffix if given an `-o' + # argument, so we may need to know it at that point already. + # Even if this section looks crufty: it has the advantage of + # actually working. + break;; + * ) + break;; + esac +done +test "$ac_cv_exeext" = no && ac_cv_exeext= + +else + ac_file='' +fi +if test -z "$ac_file"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +$as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error 77 "C compiler cannot create executables +See \`config.log' for more details" "$LINENO" 5; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5 +$as_echo_n "checking for C compiler default output file name... " >&6; } +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5 +$as_echo "$ac_file" >&6; } +ac_exeext=$ac_cv_exeext + +rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out +ac_clean_files=$ac_clean_files_save +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5 +$as_echo_n "checking for suffix of executables... " >&6; } +if { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; 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 | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; + *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` + break;; + * ) break;; + esac +done +else + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "cannot compute suffix of executables: cannot compile and link +See \`config.log' for more details" "$LINENO" 5; } +fi +rm -f conftest conftest$ac_cv_exeext +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5 +$as_echo "$ac_cv_exeext" >&6; } + +rm -f conftest.$ac_ext +EXEEXT=$ac_cv_exeext +ac_exeext=$EXEEXT +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +int +main () +{ +FILE *f = fopen ("conftest.out", "w"); + return ferror (f) || fclose (f) != 0; + + ; + return 0; +} +_ACEOF +ac_clean_files="$ac_clean_files conftest.out" +# Check that the compiler produces executables we can run. If not, either +# the compiler is broken, or we cross compile. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5 +$as_echo_n "checking whether we are cross compiling... " >&6; } +if test "$cross_compiling" != yes; then + { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + if { ac_try='./conftest$ac_cv_exeext' + { { case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; }; then + cross_compiling=no + else + if test "$cross_compiling" = maybe; then + cross_compiling=yes + else + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "cannot run C compiled programs. +If you meant to cross compile, use \`--host'. +See \`config.log' for more details" "$LINENO" 5; } + fi + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5 +$as_echo "$cross_compiling" >&6; } + +rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out +ac_clean_files=$ac_clean_files_save +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5 +$as_echo_n "checking for suffix of object files... " >&6; } +if ${ac_cv_objext+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.o conftest.obj +if { { ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_compile") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then : + for ac_file in conftest.o conftest.obj conftest.*; do + test -f "$ac_file" || continue; + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;; + *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'` + break;; + esac +done +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "cannot compute suffix of object files: cannot compile +See \`config.log' for more details" "$LINENO" 5; } +fi +rm -f conftest.$ac_cv_objext conftest.$ac_ext +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5 +$as_echo "$ac_cv_objext" >&6; } +OBJEXT=$ac_cv_objext +ac_objext=$OBJEXT +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5 +$as_echo_n "checking whether we are using the GNU C compiler... " >&6; } +if ${ac_cv_c_compiler_gnu+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ +#ifndef __GNUC__ + choke me +#endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_compiler_gnu=yes +else + ac_compiler_gnu=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +ac_cv_c_compiler_gnu=$ac_compiler_gnu + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5 +$as_echo "$ac_cv_c_compiler_gnu" >&6; } +if test $ac_compiler_gnu = yes; then + GCC=yes +else + GCC= +fi +ac_test_CFLAGS=${CFLAGS+set} +ac_save_CFLAGS=$CFLAGS +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5 +$as_echo_n "checking whether $CC accepts -g... " >&6; } +if ${ac_cv_prog_cc_g+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_save_c_werror_flag=$ac_c_werror_flag + ac_c_werror_flag=yes + ac_cv_prog_cc_g=no + CFLAGS="-g" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_prog_cc_g=yes +else + CFLAGS="" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + +else + ac_c_werror_flag=$ac_save_c_werror_flag + CFLAGS="-g" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_prog_cc_g=yes +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + ac_c_werror_flag=$ac_save_c_werror_flag +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5 +$as_echo "$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 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5 +$as_echo_n "checking for $CC option to accept ISO C89... " >&6; } +if ${ac_cv_prog_cc_c89+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_cv_prog_cc_c89=no +ac_save_CC=$CC +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include +#include +#include +/* 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 -std 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 -std. */ +int osf4_cc_array ['\x00' == 0 ? 1 : -1]; + +/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters + inside strings and character constants. */ +#define FOO(x) 'x' +int xlc6_cc_array[FOO(a) == 'x' ? 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 +for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \ + -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" +do + CC="$ac_save_CC $ac_arg" + if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_prog_cc_c89=$ac_arg +fi +rm -f core conftest.err conftest.$ac_objext + test "x$ac_cv_prog_cc_c89" != "xno" && break +done +rm -f conftest.$ac_ext +CC=$ac_save_CC + +fi +# AC_CACHE_VAL +case "x$ac_cv_prog_cc_c89" in + x) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5 +$as_echo "none needed" >&6; } ;; + xno) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5 +$as_echo "unsupported" >&6; } ;; + *) + CC="$CC $ac_cv_prog_cc_c89" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5 +$as_echo "$ac_cv_prog_cc_c89" >&6; } ;; +esac +if test "x$ac_cv_prog_cc_c89" != xno; then : + +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 + + +# We know what compiler we're going to use, now. Set per-compiler flags. +if test "$GCC" = "yes"; then + # Use -O3 if we're using gcc, unless we're doing a small build, in + # which case we use -Os alone. The code size for -O3 is quite a + # bit larger than -O2: a compromise is "-Os -finline-functions", + # it's smaller and explicitly inlining the functions helps Berkeley + # DB. + CFLAGS="$CFLAGS " + if test "$db_cv_smallbuild" = "yes" -o "$db_cv_rdsbuild" = "yes" ; then + CFLAGS=`echo "$CFLAGS" | sed 's/-O /-Os /g'` + else + CFLAGS=`echo "$CFLAGS" | sed 's/-O /-O3 /g'` + fi +else + case "$host_os" in + hpux11.0*) ;; + hpux11*) CPPFLAGS="$CPPFLAGS -mt" + test "$host_cpu" = "ia64" && + CFLAGS="$CFLAGS +u1";; + esac +fi + +# Check for "const" and "inline" keywords. + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for an ANSI C-conforming const" >&5 +$as_echo_n "checking for an ANSI C-conforming const... " >&6; } +if ${ac_cv_c_const+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ +/* FIXME: Include the comments suggested by Paul. */ +#ifndef __cplusplus + /* Ultrix mips cc rejects this. */ + typedef int charset[2]; + const charset cs; + /* SunOS 4.1.1 cc rejects this. */ + char const *const *pcpcc; + char **ppc; + /* NEC SVR4.0.2 mips cc rejects this. */ + struct point {int x, y;}; + static struct point const zero = {0,0}; + /* AIX XL C 1.02.0.0 rejects this. + It does not let you subtract one const X* pointer from another in + an arm of an if-expression whose if-part is not a constant + expression */ + const char *g = "string"; + pcpcc = &g + (g ? g-g : 0); + /* HPUX 7.0 cc rejects these. */ + ++pcpcc; + ppc = (char**) pcpcc; + pcpcc = (char const *const *) ppc; + { /* SCO 3.2v4 cc rejects this. */ + char *t; + char const *s = 0 ? (char *) 0 : (char const *) 0; + + *t++ = 0; + if (s) return 0; + } + { /* Someone thinks the Sun supposedly-ANSI compiler will reject this. */ + int x[] = {25, 17}; + const int *foo = &x[0]; + ++foo; + } + { /* Sun SC1.0 ANSI compiler rejects this -- but not the above. */ + typedef const int *iptr; + iptr p = 0; + ++p; + } + { /* AIX XL C 1.02.0.0 rejects this saying + "k.c", line 2.27: 1506-025 (S) Operand must be a modifiable lvalue. */ + struct s { int j; const int *ap[3]; }; + struct s *b; b->j = 5; + } + { /* ULTRIX-32 V3.1 (Rev 9) vcc rejects this */ + const int foo = 10; + if (!foo) return 0; + } + return !cs[0] && !zero.x; +#endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_c_const=yes +else + ac_cv_c_const=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_const" >&5 +$as_echo "$ac_cv_c_const" >&6; } +if test $ac_cv_c_const = no; then + +$as_echo "#define const /**/" >>confdefs.h + +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for inline" >&5 +$as_echo_n "checking for inline... " >&6; } +if ${ac_cv_c_inline+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_cv_c_inline=no +for ac_kw in inline __inline__ __inline; do + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifndef __cplusplus +typedef int foo_t; +static $ac_kw foo_t static_foo () {return 0; } +$ac_kw foo_t foo () {return 0; } +#endif + +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_c_inline=$ac_kw +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + test "$ac_cv_c_inline" != no && break +done + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_inline" >&5 +$as_echo "$ac_cv_c_inline" >&6; } + +case $ac_cv_c_inline in + inline | yes) ;; + *) + case $ac_cv_c_inline in + no) ac_val=;; + *) ac_val=$ac_cv_c_inline;; + esac + cat >>confdefs.h <<_ACEOF +#ifndef __cplusplus +#define inline $ac_val +#endif +_ACEOF + ;; +esac + + +# We use prototypes and the keyword "const" in db.h which doesn't include +# db_config.h, so we have to figure out what to do there. +# +# There is an autoconf AC_C_PROTOTYPES macro, but as all it does is define +# db_config.h variables, it doesn't help us. +# +# We don't have much choice, we look at internal autoconf variables. +if test "$ac_cv_c_const" != "yes"; then + DB_CONST="#define const" +fi + +# We use alignment attributes in db.h - figure out if the compiler supports +# them. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for GCC aligned attribute" >&5 +$as_echo_n "checking for GCC aligned attribute... " >&6; } +if ${db_cv_aligned_attribute+:} false; then : + $as_echo_n "(cached) " >&6 +else + +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ +__attribute__ ((aligned (8))) int i; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + db_cv_aligned_attribute=yes +else + db_cv_aligned_attribute=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $db_cv_aligned_attribute" >&5 +$as_echo "$db_cv_aligned_attribute" >&6; } +if test "$db_cv_aligned_attribute" = "yes"; then + DB_STRUCT_ALIGN8="__attribute__ ((aligned (8)))" +fi + +# Clear __P, some other systems use it too. +DB_PROTO1="#undef __P" +if test "$ac_cv_prog_cc_c89" = "no"; then + DB_PROTO2="#define __P(protos) ()" +else + DB_PROTO2="#define __P(protos) protos" +fi + +# Because of shared library building, the ${CC} used for config tests +# may be different than the ${CC} we want to put in the Makefile. +# The latter is known as ${MAKEFILE_CC} in this script. +MAKEFILE_CC="${CC}" +MAKEFILE_CCLINK="${CC}" +MAKEFILE_CXX="nocxx" +MAKEFILE_CXXLINK="nocxx" + +# See if we need the C++ compiler at all. If so, we'd like to find one that +# interoperates with the C compiler we chose. Since we prefered cc over gcc, +# we'll also prefer the vendor's compiler over g++/gcc. If we're wrong, the +# user can set CC and CXX in their environment before running configure. +# +# AC_PROG_CXX sets CXX, but it uses $CXX and $CCC (in that order) as its +# first choices. +if test "$db_cv_cxx" = "yes"; then + if test "$GCC" != "yes"; then + case "$host_os" in + aix*) if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}xlC_r", so it can be a program name with args. +set dummy ${ac_tool_prefix}xlC_r; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CCC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CCC"; then + ac_cv_prog_CCC="$CCC" # 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_CCC="${ac_tool_prefix}xlC_r" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CCC=$ac_cv_prog_CCC +if test -n "$CCC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CCC" >&5 +$as_echo "$CCC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_CCC"; then + ac_ct_CCC=$CCC + # Extract the first word of "xlC_r", so it can be a program name with args. +set dummy xlC_r; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_CCC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_CCC"; then + ac_cv_prog_ac_ct_CCC="$ac_ct_CCC" # 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_CCC="xlC_r" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_CCC=$ac_cv_prog_ac_ct_CCC +if test -n "$ac_ct_CCC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CCC" >&5 +$as_echo "$ac_ct_CCC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_CCC" = x; then + CCC="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + CCC=$ac_ct_CCC + fi +else + CCC="$ac_cv_prog_CCC" +fi + + LIBXSO_LIBS="-lC_r $LIBXSO_LIBS" + LIBSO_LIBS="-lC_r $LIBSO_LIBS";; + hpux*) if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}aCC", so it can be a program name with args. +set dummy ${ac_tool_prefix}aCC; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CCC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CCC"; then + ac_cv_prog_CCC="$CCC" # 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_CCC="${ac_tool_prefix}aCC" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CCC=$ac_cv_prog_CCC +if test -n "$CCC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CCC" >&5 +$as_echo "$CCC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_CCC"; then + ac_ct_CCC=$CCC + # Extract the first word of "aCC", so it can be a program name with args. +set dummy aCC; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_CCC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_CCC"; then + ac_cv_prog_ac_ct_CCC="$ac_ct_CCC" # 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_CCC="aCC" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_CCC=$ac_cv_prog_ac_ct_CCC +if test -n "$ac_ct_CCC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CCC" >&5 +$as_echo "$ac_ct_CCC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_CCC" = x; then + CCC="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + CCC=$ac_ct_CCC + fi +else + CCC="$ac_cv_prog_CCC" +fi +;; + irix*) 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 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CCC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CCC"; then + ac_cv_prog_CCC="$CCC" # 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_CCC="${ac_tool_prefix}CC" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CCC=$ac_cv_prog_CCC +if test -n "$CCC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CCC" >&5 +$as_echo "$CCC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_CCC"; then + ac_ct_CCC=$CCC + # Extract the first word of "CC", so it can be a program name with args. +set dummy CC; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_CCC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_CCC"; then + ac_cv_prog_ac_ct_CCC="$ac_ct_CCC" # 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_CCC="CC" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_CCC=$ac_cv_prog_ac_ct_CCC +if test -n "$ac_ct_CCC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CCC" >&5 +$as_echo "$ac_ct_CCC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_CCC" = x; then + CCC="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + CCC=$ac_ct_CCC + fi +else + CCC="$ac_cv_prog_CCC" +fi +;; + osf*) if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}cxx", so it can be a program name with args. +set dummy ${ac_tool_prefix}cxx; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CCC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CCC"; then + ac_cv_prog_CCC="$CCC" # 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_CCC="${ac_tool_prefix}cxx" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CCC=$ac_cv_prog_CCC +if test -n "$CCC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CCC" >&5 +$as_echo "$CCC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_CCC"; then + ac_ct_CCC=$CCC + # Extract the first word of "cxx", so it can be a program name with args. +set dummy cxx; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_CCC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_CCC"; then + ac_cv_prog_ac_ct_CCC="$ac_ct_CCC" # 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_CCC="cxx" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_CCC=$ac_cv_prog_ac_ct_CCC +if test -n "$ac_ct_CCC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CCC" >&5 +$as_echo "$ac_ct_CCC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_CCC" = x; then + CCC="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + CCC=$ac_ct_CCC + fi +else + CCC="$ac_cv_prog_CCC" +fi + + CXXFLAGS="$CXXFLAGS -D__USE_STD_IOSTREAM" + test -d /usr/include.dtk && + CXXFLAGS="$CXXFLAGS -I/usr/include.dtk";; + solaris*) 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 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CCC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CCC"; then + ac_cv_prog_CCC="$CCC" # 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_CCC="${ac_tool_prefix}CC" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CCC=$ac_cv_prog_CCC +if test -n "$CCC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CCC" >&5 +$as_echo "$CCC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_CCC"; then + ac_ct_CCC=$CCC + # Extract the first word of "CC", so it can be a program name with args. +set dummy CC; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_CCC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_CCC"; then + ac_cv_prog_ac_ct_CCC="$ac_ct_CCC" # 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_CCC="CC" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_CCC=$ac_cv_prog_ac_ct_CCC +if test -n "$ac_ct_CCC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CCC" >&5 +$as_echo "$ac_ct_CCC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_CCC" = x; then + CCC="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + CCC=$ac_ct_CCC + fi +else + CCC="$ac_cv_prog_CCC" +fi +;; + esac + fi + ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu +if test -z "$CXX"; then + if test -n "$CCC"; then + CXX=$CCC + else + if test -n "$ac_tool_prefix"; then + for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC + 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 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CXX+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CXX"; then + ac_cv_prog_CXX="$CXX" # 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_CXX="$ac_tool_prefix$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CXX=$ac_cv_prog_CXX +if test -n "$CXX"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CXX" >&5 +$as_echo "$CXX" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$CXX" && break + done +fi +if test -z "$CXX"; then + ac_ct_CXX=$CXX + for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_CXX+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_CXX"; then + ac_cv_prog_ac_ct_CXX="$ac_ct_CXX" # 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_CXX="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_CXX=$ac_cv_prog_ac_ct_CXX +if test -n "$ac_ct_CXX"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CXX" >&5 +$as_echo "$ac_ct_CXX" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$ac_ct_CXX" && break +done + + if test "x$ac_ct_CXX" = x; then + CXX="g++" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + CXX=$ac_ct_CXX + fi +fi + + fi +fi +# Provide some information about the compiler. +$as_echo "$as_me:${as_lineno-$LINENO}: checking for C++ compiler version" >&5 +set X $ac_compile +ac_compiler=$2 +for ac_option in --version -v -V -qversion; do + { { ac_try="$ac_compiler $ac_option >&5" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_compiler $ac_option >&5") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + sed '10a\ +... rest of stderr output deleted ... + 10q' conftest.err >conftest.er1 + cat conftest.er1 >&5 + fi + rm -f conftest.er1 conftest.err + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } +done + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C++ compiler" >&5 +$as_echo_n "checking whether we are using the GNU C++ compiler... " >&6; } +if ${ac_cv_cxx_compiler_gnu+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ +#ifndef __GNUC__ + choke me +#endif + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + ac_compiler_gnu=yes +else + ac_compiler_gnu=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +ac_cv_cxx_compiler_gnu=$ac_compiler_gnu + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_cxx_compiler_gnu" >&5 +$as_echo "$ac_cv_cxx_compiler_gnu" >&6; } +if test $ac_compiler_gnu = yes; then + GXX=yes +else + GXX= +fi +ac_test_CXXFLAGS=${CXXFLAGS+set} +ac_save_CXXFLAGS=$CXXFLAGS +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CXX accepts -g" >&5 +$as_echo_n "checking whether $CXX accepts -g... " >&6; } +if ${ac_cv_prog_cxx_g+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_save_cxx_werror_flag=$ac_cxx_werror_flag + ac_cxx_werror_flag=yes + ac_cv_prog_cxx_g=no + CXXFLAGS="-g" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + ac_cv_prog_cxx_g=yes +else + CXXFLAGS="" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + +else + ac_cxx_werror_flag=$ac_save_cxx_werror_flag + CXXFLAGS="-g" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + ac_cv_prog_cxx_g=yes +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + ac_cxx_werror_flag=$ac_save_cxx_werror_flag +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cxx_g" >&5 +$as_echo "$ac_cv_prog_cxx_g" >&6; } +if test "$ac_test_CXXFLAGS" = set; then + CXXFLAGS=$ac_save_CXXFLAGS +elif test $ac_cv_prog_cxx_g = yes; then + if test "$GXX" = yes; then + CXXFLAGS="-g -O2" + else + CXXFLAGS="-g" + fi +else + if test "$GXX" = yes; then + CXXFLAGS="-O2" + else + CXXFLAGS= + fi +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 + + ###### WORKAROUND: SEE SR #7938 + ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C++ preprocessor" >&5 +$as_echo_n "checking how to run the C++ preprocessor... " >&6; } +if test -z "$CXXCPP"; then + if ${ac_cv_prog_CXXCPP+:} false; then : + $as_echo_n "(cached) " >&6 +else + # Double quotes because CXXCPP needs to be expanded + for CXXCPP in "$CXX -E" "/lib/cpp" + do + ac_preproc_ok=false +for ac_cxx_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer to if __STDC__ is defined, since + # exists even on freestanding compilers. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifdef __STDC__ +# include +#else +# include +#endif + Syntax error +_ACEOF +if ac_fn_cxx_try_cpp "$LINENO"; then : + +else + # Broken: fails on valid input. +continue +fi +rm -f conftest.err conftest.i conftest.$ac_ext + + # OK, works on sane cases. Now check whether nonexistent headers + # can be detected and how. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +_ACEOF +if ac_fn_cxx_try_cpp "$LINENO"; then : + # Broken: success on invalid input. +continue +else + # Passes both tests. +ac_preproc_ok=: +break +fi +rm -f conftest.err conftest.i conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.i conftest.err conftest.$ac_ext +if $ac_preproc_ok; then : + break +fi + + done + ac_cv_prog_CXXCPP=$CXXCPP + +fi + CXXCPP=$ac_cv_prog_CXXCPP +else + ac_cv_prog_CXXCPP=$CXXCPP +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $CXXCPP" >&5 +$as_echo "$CXXCPP" >&6; } +ac_preproc_ok=false +for ac_cxx_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer to if __STDC__ is defined, since + # exists even on freestanding compilers. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifdef __STDC__ +# include +#else +# include +#endif + Syntax error +_ACEOF +if ac_fn_cxx_try_cpp "$LINENO"; then : + +else + # Broken: fails on valid input. +continue +fi +rm -f conftest.err conftest.i conftest.$ac_ext + + # OK, works on sane cases. Now check whether nonexistent headers + # can be detected and how. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +_ACEOF +if ac_fn_cxx_try_cpp "$LINENO"; then : + # Broken: success on invalid input. +continue +else + # Passes both tests. +ac_preproc_ok=: +break +fi +rm -f conftest.err conftest.i conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.i conftest.err conftest.$ac_ext +if $ac_preproc_ok; then : + +else + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "C++ preprocessor \"$CXXCPP\" fails sanity check +See \`config.log' for more details" "$LINENO" 5; } +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 + + ############################### + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C++ supports the ISO C++ standard includes" >&5 +$as_echo_n "checking whether C++ supports the ISO C++ standard includes... " >&6; } + +ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu + +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +int +main () +{ +std::ostream *o; return 0; + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + db_cv_cxx_have_stdheaders=yes +else + db_cv_cxx_have_stdheaders=no +fi +rm -f core 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 + +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $db_cv_cxx_have_stdheaders" >&5 +$as_echo "$db_cv_cxx_have_stdheaders" >&6; } +if test "$db_cv_cxx_have_stdheaders" = yes; then + cxx_have_stdheaders="#define HAVE_CXX_STDHEADERS 1" +fi + MAKEFILE_CXX="${CXX}" + MAKEFILE_CXXLINK="${CXX}" +fi + +# Do some gcc specific configuration. + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using gcc version 2.96" >&5 +$as_echo_n "checking whether we are using gcc version 2.96... " >&6; } +if ${db_cv_gcc_2_96+:} false; then : + $as_echo_n "(cached) " >&6 +else + +db_cv_gcc_2_96=no +if test "$GCC" = "yes"; then + GCC_VERSION=`${MAKEFILE_CC} --version` + case ${GCC_VERSION} in + 2.96*) + db_cv_gcc_2_96=yes;; + esac +fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $db_cv_gcc_2_96" >&5 +$as_echo "$db_cv_gcc_2_96" >&6; } +if test "$db_cv_gcc_2_96" = "yes"; then + CFLAGS=`echo "$CFLAGS" | sed 's/-O2/-O/'` + CXXFLAGS=`echo "$CXXFLAGS" | sed 's/-O2/-O/'` + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: INSTALLED GCC COMPILER HAS SERIOUS BUGS; PLEASE UPGRADE." >&5 +$as_echo "$as_me: WARNING: INSTALLED GCC COMPILER HAS SERIOUS BUGS; PLEASE UPGRADE." >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: GCC OPTIMIZATION LEVEL SET TO -O." >&5 +$as_echo "$as_me: WARNING: GCC OPTIMIZATION LEVEL SET TO -O." >&2;} +fi + +# We need the -Kthread/-pthread flag when compiling on SCO/Caldera's UnixWare +# and OpenUNIX releases. We can't make the test until we know which compiler +# we're using. +case "$host_os" in +sysv5UnixWare*|sysv5OpenUNIX8*) + if test "$GCC" == "yes"; then + CPPFLAGS="$CPPFLAGS -pthread" + LDFLAGS="$LDFLAGS -pthread" + else + CPPFLAGS="$CPPFLAGS -Kthread" + LDFLAGS="$LDFLAGS -Kthread" + fi;; +esac + +# Export our compiler preferences for the libtool configuration. +export CC CCC +CCC=$CXX + +# Libtool configuration. +case `pwd` in + *\ * | *\ *) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Libtool does not cope well with whitespace in \`pwd\`" >&5 +$as_echo "$as_me: WARNING: Libtool does not cope well with whitespace in \`pwd\`" >&2;} ;; +esac + + + +macro_version='2.4' +macro_revision='1.3293' + + + + + + + + + + + + + +ltmain="$ac_aux_dir/ltmain.sh" + +# Backslashify metacharacters that are still active within +# double-quoted strings. +sed_quote_subst='s/\(["`$\\]\)/\\\1/g' + +# Same as above, but do not quote variable references. +double_quote_subst='s/\(["`\\]\)/\\\1/g' + +# Sed substitution to delay expansion of an escaped shell variable in a +# double_quote_subst'ed string. +delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g' + +# Sed substitution to delay expansion of an escaped single quote. +delay_single_quote_subst='s/'\''/'\'\\\\\\\'\''/g' + +# Sed substitution to avoid accidental globbing in evaled expressions +no_glob_subst='s/\*/\\\*/g' + +ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' +ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO +ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to print strings" >&5 +$as_echo_n "checking how to print strings... " >&6; } +# Test print first, because it will be a builtin if present. +if test "X`( print -r -- -n ) 2>/dev/null`" = X-n && \ + test "X`print -r -- $ECHO 2>/dev/null`" = "X$ECHO"; then + ECHO='print -r --' +elif test "X`printf %s $ECHO 2>/dev/null`" = "X$ECHO"; then + ECHO='printf %s\n' +else + # Use this function as a fallback that always works. + func_fallback_echo () + { + eval 'cat <<_LTECHO_EOF +$1 +_LTECHO_EOF' + } + ECHO='func_fallback_echo' +fi + +# func_echo_all arg... +# Invoke $ECHO with all args, space-separated. +func_echo_all () +{ + $ECHO "" +} + +case "$ECHO" in + printf*) { $as_echo "$as_me:${as_lineno-$LINENO}: result: printf" >&5 +$as_echo "printf" >&6; } ;; + print*) { $as_echo "$as_me:${as_lineno-$LINENO}: result: print -r" >&5 +$as_echo "print -r" >&6; } ;; + *) { $as_echo "$as_me:${as_lineno-$LINENO}: result: cat" >&5 +$as_echo "cat" >&6; } ;; +esac + + + + + + + + + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a sed that does not truncate output" >&5 +$as_echo_n "checking for a sed that does not truncate output... " >&6; } +if ${ac_cv_path_SED+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_script=s/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb/ + for ac_i in 1 2 3 4 5 6 7; do + ac_script="$ac_script$as_nl$ac_script" + done + echo "$ac_script" 2>/dev/null | sed 99q >conftest.sed + { ac_script=; unset ac_script;} + if test -z "$SED"; then + ac_path_SED_found=false + # Loop through the user's path and test for each of PROGNAME-LIST + 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_prog in sed gsed; do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_SED="$as_dir/$ac_prog$ac_exec_ext" + { test -f "$ac_path_SED" && $as_test_x "$ac_path_SED"; } || continue +# Check for GNU ac_path_SED and select it if it is found. + # Check for GNU $ac_path_SED +case `"$ac_path_SED" --version 2>&1` in +*GNU*) + ac_cv_path_SED="$ac_path_SED" ac_path_SED_found=:;; +*) + ac_count=0 + $as_echo_n 0123456789 >"conftest.in" + while : + do + cat "conftest.in" "conftest.in" >"conftest.tmp" + mv "conftest.tmp" "conftest.in" + cp "conftest.in" "conftest.nl" + $as_echo '' >> "conftest.nl" + "$ac_path_SED" -f conftest.sed < "conftest.nl" >"conftest.out" 2>/dev/null || break + diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break + as_fn_arith $ac_count + 1 && ac_count=$as_val + if test $ac_count -gt ${ac_path_SED_max-0}; then + # Best one so far, save it but keep looking for a better one + ac_cv_path_SED="$ac_path_SED" + ac_path_SED_max=$ac_count + fi + # 10*(2^10) chars as input seems more than enough + test $ac_count -gt 10 && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out;; +esac + + $ac_path_SED_found && break 3 + done + done + done +IFS=$as_save_IFS + if test -z "$ac_cv_path_SED"; then + as_fn_error $? "no acceptable sed could be found in \$PATH" "$LINENO" 5 + fi +else + ac_cv_path_SED=$SED +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_SED" >&5 +$as_echo "$ac_cv_path_SED" >&6; } + SED="$ac_cv_path_SED" + rm -f conftest.sed + +test -z "$SED" && SED=sed +Xsed="$SED -e 1s/^X//" + + + + + + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5 +$as_echo_n "checking for grep that handles long lines and -e... " >&6; } +if ${ac_cv_path_GREP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -z "$GREP"; then + ac_path_GREP_found=false + # Loop through the user's path and test for each of PROGNAME-LIST + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in grep ggrep; do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext" + { test -f "$ac_path_GREP" && $as_test_x "$ac_path_GREP"; } || continue +# Check for GNU ac_path_GREP and select it if it is found. + # Check for GNU $ac_path_GREP +case `"$ac_path_GREP" --version 2>&1` in +*GNU*) + ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;; +*) + ac_count=0 + $as_echo_n 0123456789 >"conftest.in" + while : + do + cat "conftest.in" "conftest.in" >"conftest.tmp" + mv "conftest.tmp" "conftest.in" + cp "conftest.in" "conftest.nl" + $as_echo 'GREP' >> "conftest.nl" + "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break + diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break + as_fn_arith $ac_count + 1 && ac_count=$as_val + if test $ac_count -gt ${ac_path_GREP_max-0}; then + # Best one so far, save it but keep looking for a better one + ac_cv_path_GREP="$ac_path_GREP" + ac_path_GREP_max=$ac_count + fi + # 10*(2^10) chars as input seems more than enough + test $ac_count -gt 10 && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out;; +esac + + $ac_path_GREP_found && break 3 + done + done + done +IFS=$as_save_IFS + if test -z "$ac_cv_path_GREP"; then + as_fn_error $? "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 + fi +else + ac_cv_path_GREP=$GREP +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5 +$as_echo "$ac_cv_path_GREP" >&6; } + GREP="$ac_cv_path_GREP" + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5 +$as_echo_n "checking for egrep... " >&6; } +if ${ac_cv_path_EGREP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if echo a | $GREP -E '(a|b)' >/dev/null 2>&1 + then ac_cv_path_EGREP="$GREP -E" + else + if test -z "$EGREP"; then + ac_path_EGREP_found=false + # Loop through the user's path and test for each of PROGNAME-LIST + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in egrep; do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext" + { test -f "$ac_path_EGREP" && $as_test_x "$ac_path_EGREP"; } || continue +# Check for GNU ac_path_EGREP and select it if it is found. + # Check for GNU $ac_path_EGREP +case `"$ac_path_EGREP" --version 2>&1` in +*GNU*) + ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;; +*) + ac_count=0 + $as_echo_n 0123456789 >"conftest.in" + while : + do + cat "conftest.in" "conftest.in" >"conftest.tmp" + mv "conftest.tmp" "conftest.in" + cp "conftest.in" "conftest.nl" + $as_echo 'EGREP' >> "conftest.nl" + "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break + diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break + as_fn_arith $ac_count + 1 && ac_count=$as_val + if test $ac_count -gt ${ac_path_EGREP_max-0}; then + # Best one so far, save it but keep looking for a better one + ac_cv_path_EGREP="$ac_path_EGREP" + ac_path_EGREP_max=$ac_count + fi + # 10*(2^10) chars as input seems more than enough + test $ac_count -gt 10 && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out;; +esac + + $ac_path_EGREP_found && break 3 + done + done + done +IFS=$as_save_IFS + if test -z "$ac_cv_path_EGREP"; then + as_fn_error $? "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 + fi +else + ac_cv_path_EGREP=$EGREP +fi + + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5 +$as_echo "$ac_cv_path_EGREP" >&6; } + EGREP="$ac_cv_path_EGREP" + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for fgrep" >&5 +$as_echo_n "checking for fgrep... " >&6; } +if ${ac_cv_path_FGREP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if echo 'ab*c' | $GREP -F 'ab*c' >/dev/null 2>&1 + then ac_cv_path_FGREP="$GREP -F" + else + if test -z "$FGREP"; then + ac_path_FGREP_found=false + # Loop through the user's path and test for each of PROGNAME-LIST + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in fgrep; do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_FGREP="$as_dir/$ac_prog$ac_exec_ext" + { test -f "$ac_path_FGREP" && $as_test_x "$ac_path_FGREP"; } || continue +# Check for GNU ac_path_FGREP and select it if it is found. + # Check for GNU $ac_path_FGREP +case `"$ac_path_FGREP" --version 2>&1` in +*GNU*) + ac_cv_path_FGREP="$ac_path_FGREP" ac_path_FGREP_found=:;; +*) + ac_count=0 + $as_echo_n 0123456789 >"conftest.in" + while : + do + cat "conftest.in" "conftest.in" >"conftest.tmp" + mv "conftest.tmp" "conftest.in" + cp "conftest.in" "conftest.nl" + $as_echo 'FGREP' >> "conftest.nl" + "$ac_path_FGREP" FGREP < "conftest.nl" >"conftest.out" 2>/dev/null || break + diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break + as_fn_arith $ac_count + 1 && ac_count=$as_val + if test $ac_count -gt ${ac_path_FGREP_max-0}; then + # Best one so far, save it but keep looking for a better one + ac_cv_path_FGREP="$ac_path_FGREP" + ac_path_FGREP_max=$ac_count + fi + # 10*(2^10) chars as input seems more than enough + test $ac_count -gt 10 && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out;; +esac + + $ac_path_FGREP_found && break 3 + done + done + done +IFS=$as_save_IFS + if test -z "$ac_cv_path_FGREP"; then + as_fn_error $? "no acceptable fgrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 + fi +else + ac_cv_path_FGREP=$FGREP +fi + + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_FGREP" >&5 +$as_echo "$ac_cv_path_FGREP" >&6; } + FGREP="$ac_cv_path_FGREP" + + +test -z "$GREP" && GREP=grep + + + + + + + + + + + + + + + + + + + +# Check whether --with-gnu-ld was given. +if test "${with_gnu_ld+set}" = set; then : + withval=$with_gnu_ld; test "$withval" = no || with_gnu_ld=yes +else + with_gnu_ld=no +fi + +ac_prog=ld +if test "$GCC" = yes; then + # Check if gcc -print-prog-name=ld gives a path. + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ld used by $CC" >&5 +$as_echo_n "checking for ld used by $CC... " >&6; } + case $host in + *-*-mingw*) + # gcc leaves a trailing carriage return which upsets mingw + ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; + *) + ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; + esac + case $ac_prog in + # Accept absolute paths. + [\\/]* | ?:[\\/]*) + re_direlt='/[^/][^/]*/\.\./' + # Canonicalize the pathname of ld + ac_prog=`$ECHO "$ac_prog"| $SED 's%\\\\%/%g'` + while $ECHO "$ac_prog" | $GREP "$re_direlt" > /dev/null 2>&1; do + ac_prog=`$ECHO $ac_prog| $SED "s%$re_direlt%/%"` + done + test -z "$LD" && LD="$ac_prog" + ;; + "") + # If it fails, then pretend we aren't using GCC. + ac_prog=ld + ;; + *) + # If it is relative, then search for the first ld in PATH. + with_gnu_ld=unknown + ;; + esac +elif test "$with_gnu_ld" = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GNU ld" >&5 +$as_echo_n "checking for GNU ld... " >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for non-GNU ld" >&5 +$as_echo_n "checking for non-GNU ld... " >&6; } +fi +if ${lt_cv_path_LD+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -z "$LD"; then + lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR + for ac_dir in $PATH; do + IFS="$lt_save_ifs" + test -z "$ac_dir" && ac_dir=. + if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then + lt_cv_path_LD="$ac_dir/$ac_prog" + # Check to see if the program is GNU ld. I'd rather use --version, + # but apparently some variants of GNU ld only accept -v. + # Break only if it was the GNU/non-GNU ld that we prefer. + case `"$lt_cv_path_LD" -v 2>&1 &5 +$as_echo "$LD" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi +test -z "$LD" && as_fn_error $? "no acceptable ld found in \$PATH" "$LINENO" 5 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if the linker ($LD) is GNU ld" >&5 +$as_echo_n "checking if the linker ($LD) is GNU ld... " >&6; } +if ${lt_cv_prog_gnu_ld+:} false; then : + $as_echo_n "(cached) " >&6 +else + # I'd rather use --version here, but apparently some GNU lds only accept -v. +case `$LD -v 2>&1 &5 +$as_echo "$lt_cv_prog_gnu_ld" >&6; } +with_gnu_ld=$lt_cv_prog_gnu_ld + + + + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for BSD- or MS-compatible name lister (nm)" >&5 +$as_echo_n "checking for BSD- or MS-compatible name lister (nm)... " >&6; } +if ${lt_cv_path_NM+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$NM"; then + # Let the user override the test. + lt_cv_path_NM="$NM" +else + lt_nm_to_check="${ac_tool_prefix}nm" + if test -n "$ac_tool_prefix" && test "$build" = "$host"; then + lt_nm_to_check="$lt_nm_to_check nm" + fi + for lt_tmp_nm in $lt_nm_to_check; do + lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR + for ac_dir in $PATH /usr/ccs/bin/elf /usr/ccs/bin /usr/ucb /bin; do + IFS="$lt_save_ifs" + test -z "$ac_dir" && ac_dir=. + tmp_nm="$ac_dir/$lt_tmp_nm" + if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext" ; then + # Check to see if the nm accepts a BSD-compat flag. + # Adding the `sed 1q' prevents false positives on HP-UX, which says: + # nm: unknown option "B" ignored + # Tru64's nm complains that /dev/null is an invalid object file + case `"$tmp_nm" -B /dev/null 2>&1 | sed '1q'` in + */dev/null* | *'Invalid file or object type'*) + lt_cv_path_NM="$tmp_nm -B" + break + ;; + *) + case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in + */dev/null*) + lt_cv_path_NM="$tmp_nm -p" + break + ;; + *) + lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but + continue # so that we can try to find one that supports BSD flags + ;; + esac + ;; + esac + fi + done + IFS="$lt_save_ifs" + done + : ${lt_cv_path_NM=no} +fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_path_NM" >&5 +$as_echo "$lt_cv_path_NM" >&6; } +if test "$lt_cv_path_NM" != "no"; then + NM="$lt_cv_path_NM" +else + # Didn't find any BSD compatible name lister, look for dumpbin. + if test -n "$DUMPBIN"; then : + # Let the user override the test. + else + if test -n "$ac_tool_prefix"; then + for ac_prog in dumpbin "link -dump" + 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 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_DUMPBIN+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$DUMPBIN"; then + ac_cv_prog_DUMPBIN="$DUMPBIN" # 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_DUMPBIN="$ac_tool_prefix$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +DUMPBIN=$ac_cv_prog_DUMPBIN +if test -n "$DUMPBIN"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DUMPBIN" >&5 +$as_echo "$DUMPBIN" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$DUMPBIN" && break + done +fi +if test -z "$DUMPBIN"; then + ac_ct_DUMPBIN=$DUMPBIN + for ac_prog in dumpbin "link -dump" +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_DUMPBIN+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_DUMPBIN"; then + ac_cv_prog_ac_ct_DUMPBIN="$ac_ct_DUMPBIN" # 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_DUMPBIN="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_DUMPBIN=$ac_cv_prog_ac_ct_DUMPBIN +if test -n "$ac_ct_DUMPBIN"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DUMPBIN" >&5 +$as_echo "$ac_ct_DUMPBIN" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$ac_ct_DUMPBIN" && break +done + + if test "x$ac_ct_DUMPBIN" = x; then + DUMPBIN=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + DUMPBIN=$ac_ct_DUMPBIN + fi +fi + + case `$DUMPBIN -symbols /dev/null 2>&1 | sed '1q'` in + *COFF*) + DUMPBIN="$DUMPBIN -symbols" + ;; + *) + DUMPBIN=: + ;; + esac + fi + + if test "$DUMPBIN" != ":"; then + NM="$DUMPBIN" + fi +fi +test -z "$NM" && NM=nm + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking the name lister ($NM) interface" >&5 +$as_echo_n "checking the name lister ($NM) interface... " >&6; } +if ${lt_cv_nm_interface+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_nm_interface="BSD nm" + echo "int some_variable = 0;" > conftest.$ac_ext + (eval echo "\"\$as_me:$LINENO: $ac_compile\"" >&5) + (eval "$ac_compile" 2>conftest.err) + cat conftest.err >&5 + (eval echo "\"\$as_me:$LINENO: $NM \\\"conftest.$ac_objext\\\"\"" >&5) + (eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out) + cat conftest.err >&5 + (eval echo "\"\$as_me:$LINENO: output\"" >&5) + cat conftest.out >&5 + if $GREP 'External.*some_variable' conftest.out > /dev/null; then + lt_cv_nm_interface="MS dumpbin" + fi + rm -f conftest* +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_nm_interface" >&5 +$as_echo "$lt_cv_nm_interface" >&6; } + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ln -s works" >&5 +$as_echo_n "checking whether ln -s works... " >&6; } +LN_S=$as_ln_s +if test "$LN_S" = "ln -s"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no, using $LN_S" >&5 +$as_echo "no, using $LN_S" >&6; } +fi + +# find the maximum length of command line arguments +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking the maximum length of command line arguments" >&5 +$as_echo_n "checking the maximum length of command line arguments... " >&6; } +if ${lt_cv_sys_max_cmd_len+:} false; then : + $as_echo_n "(cached) " >&6 +else + i=0 + teststring="ABCD" + + case $build_os in + msdosdjgpp*) + # On DJGPP, this test can blow up pretty badly due to problems in libc + # (any single argument exceeding 2000 bytes causes a buffer overrun + # during glob expansion). Even if it were fixed, the result of this + # check would be larger than it should be. + lt_cv_sys_max_cmd_len=12288; # 12K is about right + ;; + + gnu*) + # Under GNU Hurd, this test is not required because there is + # no limit to the length of command line arguments. + # Libtool will interpret -1 as no limit whatsoever + lt_cv_sys_max_cmd_len=-1; + ;; + + cygwin* | mingw* | cegcc*) + # On Win9x/ME, this test blows up -- it succeeds, but takes + # about 5 minutes as the teststring grows exponentially. + # Worse, since 9x/ME are not pre-emptively multitasking, + # you end up with a "frozen" computer, even though with patience + # the test eventually succeeds (with a max line length of 256k). + # Instead, let's just punt: use the minimum linelength reported by + # all of the supported platforms: 8192 (on NT/2K/XP). + lt_cv_sys_max_cmd_len=8192; + ;; + + mint*) + # On MiNT this can take a long time and run out of memory. + lt_cv_sys_max_cmd_len=8192; + ;; + + amigaos*) + # On AmigaOS with pdksh, this test takes hours, literally. + # So we just punt and use a minimum line length of 8192. + lt_cv_sys_max_cmd_len=8192; + ;; + + netbsd* | freebsd* | openbsd* | darwin* | dragonfly*) + # This has been around since 386BSD, at least. Likely further. + if test -x /sbin/sysctl; then + lt_cv_sys_max_cmd_len=`/sbin/sysctl -n kern.argmax` + elif test -x /usr/sbin/sysctl; then + lt_cv_sys_max_cmd_len=`/usr/sbin/sysctl -n kern.argmax` + else + lt_cv_sys_max_cmd_len=65536 # usable default for all BSDs + fi + # And add a safety zone + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` + ;; + + interix*) + # We know the value 262144 and hardcode it with a safety zone (like BSD) + lt_cv_sys_max_cmd_len=196608 + ;; + + osf*) + # Dr. Hans Ekkehard Plesser reports seeing a kernel panic running configure + # due to this test when exec_disable_arg_limit is 1 on Tru64. It is not + # nice to cause kernel panics so lets avoid the loop below. + # First set a reasonable default. + lt_cv_sys_max_cmd_len=16384 + # + if test -x /sbin/sysconfig; then + case `/sbin/sysconfig -q proc exec_disable_arg_limit` in + *1*) lt_cv_sys_max_cmd_len=-1 ;; + esac + fi + ;; + sco3.2v5*) + lt_cv_sys_max_cmd_len=102400 + ;; + sysv5* | sco5v6* | sysv4.2uw2*) + kargmax=`grep ARG_MAX /etc/conf/cf.d/stune 2>/dev/null` + if test -n "$kargmax"; then + lt_cv_sys_max_cmd_len=`echo $kargmax | sed 's/.*[ ]//'` + else + lt_cv_sys_max_cmd_len=32768 + fi + ;; + *) + lt_cv_sys_max_cmd_len=`(getconf ARG_MAX) 2> /dev/null` + if test -n "$lt_cv_sys_max_cmd_len"; then + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 4` + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \* 3` + else + # Make teststring a little bigger before we do anything with it. + # a 1K string should be a reasonable start. + for i in 1 2 3 4 5 6 7 8 ; do + teststring=$teststring$teststring + done + SHELL=${SHELL-${CONFIG_SHELL-/bin/sh}} + # If test is not a shell built-in, we'll probably end up computing a + # maximum length that is only half of the actual maximum length, but + # we can't tell. + while { test "X"`func_fallback_echo "$teststring$teststring" 2>/dev/null` \ + = "X$teststring$teststring"; } >/dev/null 2>&1 && + test $i != 17 # 1/2 MB should be enough + do + i=`expr $i + 1` + teststring=$teststring$teststring + done + # Only check the string length outside the loop. + lt_cv_sys_max_cmd_len=`expr "X$teststring" : ".*" 2>&1` + teststring= + # Add a significant safety factor because C++ compilers can tack on + # massive amounts of additional arguments before passing them to the + # linker. It appears as though 1/2 is a usable value. + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2` + fi + ;; + esac + +fi + +if test -n $lt_cv_sys_max_cmd_len ; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_sys_max_cmd_len" >&5 +$as_echo "$lt_cv_sys_max_cmd_len" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: none" >&5 +$as_echo "none" >&6; } +fi +max_cmd_len=$lt_cv_sys_max_cmd_len + + + + + + +: ${CP="cp -f"} +: ${MV="mv -f"} +: ${RM="rm -f"} + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the shell understands some XSI constructs" >&5 +$as_echo_n "checking whether the shell understands some XSI constructs... " >&6; } +# Try some XSI features +xsi_shell=no +( _lt_dummy="a/b/c" + test "${_lt_dummy##*/},${_lt_dummy%/*},${_lt_dummy#??}"${_lt_dummy%"$_lt_dummy"}, \ + = c,a/b,b/c, \ + && eval 'test $(( 1 + 1 )) -eq 2 \ + && test "${#_lt_dummy}" -eq 5' ) >/dev/null 2>&1 \ + && xsi_shell=yes +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $xsi_shell" >&5 +$as_echo "$xsi_shell" >&6; } + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the shell understands \"+=\"" >&5 +$as_echo_n "checking whether the shell understands \"+=\"... " >&6; } +lt_shell_append=no +( foo=bar; set foo baz; eval "$1+=\$2" && test "$foo" = barbaz ) \ + >/dev/null 2>&1 \ + && lt_shell_append=yes +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_shell_append" >&5 +$as_echo "$lt_shell_append" >&6; } + + +if ( (MAIL=60; unset MAIL) || exit) >/dev/null 2>&1; then + lt_unset=unset +else + lt_unset=false +fi + + + + + +# test EBCDIC or ASCII +case `echo X|tr X '\101'` in + A) # ASCII based system + # \n is not interpreted correctly by Solaris 8 /usr/ucb/tr + lt_SP2NL='tr \040 \012' + lt_NL2SP='tr \015\012 \040\040' + ;; + *) # EBCDIC based system + lt_SP2NL='tr \100 \n' + lt_NL2SP='tr \r\n \100\100' + ;; +esac + + + + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to convert $build file names to $host format" >&5 +$as_echo_n "checking how to convert $build file names to $host format... " >&6; } +if ${lt_cv_to_host_file_cmd+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $host in + *-*-mingw* ) + case $build in + *-*-mingw* ) # actually msys + lt_cv_to_host_file_cmd=func_convert_file_msys_to_w32 + ;; + *-*-cygwin* ) + lt_cv_to_host_file_cmd=func_convert_file_cygwin_to_w32 + ;; + * ) # otherwise, assume *nix + lt_cv_to_host_file_cmd=func_convert_file_nix_to_w32 + ;; + esac + ;; + *-*-cygwin* ) + case $build in + *-*-mingw* ) # actually msys + lt_cv_to_host_file_cmd=func_convert_file_msys_to_cygwin + ;; + *-*-cygwin* ) + lt_cv_to_host_file_cmd=func_convert_file_noop + ;; + * ) # otherwise, assume *nix + lt_cv_to_host_file_cmd=func_convert_file_nix_to_cygwin + ;; + esac + ;; + * ) # unhandled hosts (and "normal" native builds) + lt_cv_to_host_file_cmd=func_convert_file_noop + ;; +esac + +fi + +to_host_file_cmd=$lt_cv_to_host_file_cmd +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_to_host_file_cmd" >&5 +$as_echo "$lt_cv_to_host_file_cmd" >&6; } + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to convert $build file names to toolchain format" >&5 +$as_echo_n "checking how to convert $build file names to toolchain format... " >&6; } +if ${lt_cv_to_tool_file_cmd+:} false; then : + $as_echo_n "(cached) " >&6 +else + #assume ordinary cross tools, or native build. +lt_cv_to_tool_file_cmd=func_convert_file_noop +case $host in + *-*-mingw* ) + case $build in + *-*-mingw* ) # actually msys + lt_cv_to_tool_file_cmd=func_convert_file_msys_to_w32 + ;; + esac + ;; +esac + +fi + +to_tool_file_cmd=$lt_cv_to_tool_file_cmd +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_to_tool_file_cmd" >&5 +$as_echo "$lt_cv_to_tool_file_cmd" >&6; } + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $LD option to reload object files" >&5 +$as_echo_n "checking for $LD option to reload object files... " >&6; } +if ${lt_cv_ld_reload_flag+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_ld_reload_flag='-r' +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_reload_flag" >&5 +$as_echo "$lt_cv_ld_reload_flag" >&6; } +reload_flag=$lt_cv_ld_reload_flag +case $reload_flag in +"" | " "*) ;; +*) reload_flag=" $reload_flag" ;; +esac +reload_cmds='$LD$reload_flag -o $output$reload_objs' +case $host_os in + cygwin* | mingw* | pw32* | cegcc*) + if test "$GCC" != yes; then + reload_cmds=false + fi + ;; + darwin*) + if test "$GCC" = yes; then + reload_cmds='$LTCC $LTCFLAGS -nostdlib ${wl}-r -o $output$reload_objs' + else + reload_cmds='$LD$reload_flag -o $output$reload_objs' + fi + ;; +esac + + + + + + + + + +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}objdump", so it can be a program name with args. +set dummy ${ac_tool_prefix}objdump; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_OBJDUMP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$OBJDUMP"; then + ac_cv_prog_OBJDUMP="$OBJDUMP" # 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_OBJDUMP="${ac_tool_prefix}objdump" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +OBJDUMP=$ac_cv_prog_OBJDUMP +if test -n "$OBJDUMP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OBJDUMP" >&5 +$as_echo "$OBJDUMP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_OBJDUMP"; then + ac_ct_OBJDUMP=$OBJDUMP + # Extract the first word of "objdump", so it can be a program name with args. +set dummy objdump; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_OBJDUMP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_OBJDUMP"; then + ac_cv_prog_ac_ct_OBJDUMP="$ac_ct_OBJDUMP" # 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_OBJDUMP="objdump" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_OBJDUMP=$ac_cv_prog_ac_ct_OBJDUMP +if test -n "$ac_ct_OBJDUMP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OBJDUMP" >&5 +$as_echo "$ac_ct_OBJDUMP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_OBJDUMP" = x; then + OBJDUMP="false" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + OBJDUMP=$ac_ct_OBJDUMP + fi +else + OBJDUMP="$ac_cv_prog_OBJDUMP" +fi + +test -z "$OBJDUMP" && OBJDUMP=objdump + + + + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to recognize dependent libraries" >&5 +$as_echo_n "checking how to recognize dependent libraries... " >&6; } +if ${lt_cv_deplibs_check_method+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_file_magic_cmd='$MAGIC_CMD' +lt_cv_file_magic_test_file= +lt_cv_deplibs_check_method='unknown' +# Need to set the preceding variable on all platforms that support +# interlibrary dependencies. +# 'none' -- dependencies not supported. +# `unknown' -- same as none, but documents that we really don't know. +# 'pass_all' -- all dependencies passed with no checks. +# 'test_compile' -- check by making test program. +# 'file_magic [[regex]]' -- check by looking for files in library path +# which responds to the $file_magic_cmd with a given extended regex. +# If you have `file' or equivalent on your system and you're not sure +# whether `pass_all' will *always* work, you probably want this one. + +case $host_os in +aix[4-9]*) + lt_cv_deplibs_check_method=pass_all + ;; + +beos*) + lt_cv_deplibs_check_method=pass_all + ;; + +bsdi[45]*) + lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib)' + lt_cv_file_magic_cmd='/usr/bin/file -L' + lt_cv_file_magic_test_file=/shlib/libc.so + ;; + +cygwin*) + # func_win32_libid is a shell function defined in ltmain.sh + lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' + lt_cv_file_magic_cmd='func_win32_libid' + ;; + +mingw* | pw32*) + # Base MSYS/MinGW do not provide the 'file' command needed by + # func_win32_libid shell function, so use a weaker test based on 'objdump', + # unless we find 'file', for example because we are cross-compiling. + # func_win32_libid assumes BSD nm, so disallow it if using MS dumpbin. + if ( test "$lt_cv_nm_interface" = "BSD nm" && file / ) >/dev/null 2>&1; then + lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' + lt_cv_file_magic_cmd='func_win32_libid' + else + # Keep this pattern in sync with the one in func_win32_libid. + lt_cv_deplibs_check_method='file_magic file format (pei*-i386(.*architecture: i386)?|pe-arm-wince|pe-x86-64)' + lt_cv_file_magic_cmd='$OBJDUMP -f' + fi + ;; + +cegcc*) + # use the weaker test based on 'objdump'. See mingw*. + lt_cv_deplibs_check_method='file_magic file format pe-arm-.*little(.*architecture: arm)?' + lt_cv_file_magic_cmd='$OBJDUMP -f' + ;; + +darwin* | rhapsody*) + lt_cv_deplibs_check_method=pass_all + ;; + +freebsd* | dragonfly*) + if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then + case $host_cpu in + i*86 ) + # Not sure whether the presence of OpenBSD here was a mistake. + # Let's accept both of them until this is cleared up. + lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD|DragonFly)/i[3-9]86 (compact )?demand paged shared library' + lt_cv_file_magic_cmd=/usr/bin/file + lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*` + ;; + esac + else + lt_cv_deplibs_check_method=pass_all + fi + ;; + +gnu*) + lt_cv_deplibs_check_method=pass_all + ;; + +haiku*) + lt_cv_deplibs_check_method=pass_all + ;; + +hpux10.20* | hpux11*) + lt_cv_file_magic_cmd=/usr/bin/file + case $host_cpu in + ia64*) + lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF-[0-9][0-9]) shared object file - IA64' + lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so + ;; + hppa*64*) + lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF[ -][0-9][0-9])(-bit)?( [LM]SB)? shared object( file)?[, -]* PA-RISC [0-9]\.[0-9]' + lt_cv_file_magic_test_file=/usr/lib/pa20_64/libc.sl + ;; + *) + lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|PA-RISC[0-9]\.[0-9]) shared library' + lt_cv_file_magic_test_file=/usr/lib/libc.sl + ;; + esac + ;; + +interix[3-9]*) + # PIC code is broken on Interix 3.x, that's why |\.a not |_pic\.a here + lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so|\.a)$' + ;; + +irix5* | irix6* | nonstopux*) + case $LD in + *-32|*"-32 ") libmagic=32-bit;; + *-n32|*"-n32 ") libmagic=N32;; + *-64|*"-64 ") libmagic=64-bit;; + *) libmagic=never-match;; + esac + lt_cv_deplibs_check_method=pass_all + ;; + +# This must be Linux ELF. +linux* | k*bsd*-gnu | kopensolaris*-gnu) + lt_cv_deplibs_check_method=pass_all + ;; + +netbsd*) + if echo __ELF__ | $CC -E - | $GREP __ELF__ > /dev/null; then + lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|_pic\.a)$' + else + lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so|_pic\.a)$' + fi + ;; + +newos6*) + lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (executable|dynamic lib)' + lt_cv_file_magic_cmd=/usr/bin/file + lt_cv_file_magic_test_file=/usr/lib/libnls.so + ;; + +*nto* | *qnx*) + lt_cv_deplibs_check_method=pass_all + ;; + +openbsd*) + if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|\.so|_pic\.a)$' + else + lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|_pic\.a)$' + fi + ;; + +osf3* | osf4* | osf5*) + lt_cv_deplibs_check_method=pass_all + ;; + +rdos*) + lt_cv_deplibs_check_method=pass_all + ;; + +solaris*) + lt_cv_deplibs_check_method=pass_all + ;; + +sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) + lt_cv_deplibs_check_method=pass_all + ;; + +sysv4 | sysv4.3*) + case $host_vendor in + motorola) + lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib) M[0-9][0-9]* Version [0-9]' + lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*` + ;; + ncr) + lt_cv_deplibs_check_method=pass_all + ;; + sequent) + lt_cv_file_magic_cmd='/bin/file' + lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [LM]SB (shared object|dynamic lib )' + ;; + sni) + lt_cv_file_magic_cmd='/bin/file' + lt_cv_deplibs_check_method="file_magic ELF [0-9][0-9]*-bit [LM]SB dynamic lib" + lt_cv_file_magic_test_file=/lib/libc.so + ;; + siemens) + lt_cv_deplibs_check_method=pass_all + ;; + pc) + lt_cv_deplibs_check_method=pass_all + ;; + esac + ;; + +tpf*) + lt_cv_deplibs_check_method=pass_all + ;; +esac + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_deplibs_check_method" >&5 +$as_echo "$lt_cv_deplibs_check_method" >&6; } + +file_magic_glob= +want_nocaseglob=no +if test "$build" = "$host"; then + case $host_os in + mingw* | pw32*) + if ( shopt | grep nocaseglob ) >/dev/null 2>&1; then + want_nocaseglob=yes + else + file_magic_glob=`echo aAbBcCdDeEfFgGhHiIjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ | $SED -e "s/\(..\)/s\/[\1]\/[\1]\/g;/g"` + fi + ;; + esac +fi + +file_magic_cmd=$lt_cv_file_magic_cmd +deplibs_check_method=$lt_cv_deplibs_check_method +test -z "$deplibs_check_method" && deplibs_check_method=unknown + + + + + + + + + + + + + + + + + + + + + + +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}dlltool", so it can be a program name with args. +set dummy ${ac_tool_prefix}dlltool; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_DLLTOOL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$DLLTOOL"; then + ac_cv_prog_DLLTOOL="$DLLTOOL" # 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_DLLTOOL="${ac_tool_prefix}dlltool" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +DLLTOOL=$ac_cv_prog_DLLTOOL +if test -n "$DLLTOOL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DLLTOOL" >&5 +$as_echo "$DLLTOOL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_DLLTOOL"; then + ac_ct_DLLTOOL=$DLLTOOL + # Extract the first word of "dlltool", so it can be a program name with args. +set dummy dlltool; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_DLLTOOL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_DLLTOOL"; then + ac_cv_prog_ac_ct_DLLTOOL="$ac_ct_DLLTOOL" # 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_DLLTOOL="dlltool" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_DLLTOOL=$ac_cv_prog_ac_ct_DLLTOOL +if test -n "$ac_ct_DLLTOOL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DLLTOOL" >&5 +$as_echo "$ac_ct_DLLTOOL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_DLLTOOL" = x; then + DLLTOOL="false" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + DLLTOOL=$ac_ct_DLLTOOL + fi +else + DLLTOOL="$ac_cv_prog_DLLTOOL" +fi + +test -z "$DLLTOOL" && DLLTOOL=dlltool + + + + + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to associate runtime and link libraries" >&5 +$as_echo_n "checking how to associate runtime and link libraries... " >&6; } +if ${lt_cv_sharedlib_from_linklib_cmd+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_sharedlib_from_linklib_cmd='unknown' + +case $host_os in +cygwin* | mingw* | pw32* | cegcc*) + # two different shell functions defined in ltmain.sh + # decide which to use based on capabilities of $DLLTOOL + case `$DLLTOOL --help 2>&1` in + *--identify-strict*) + lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib + ;; + *) + lt_cv_sharedlib_from_linklib_cmd=func_cygming_dll_for_implib_fallback + ;; + esac + ;; +*) + # fallback: assume linklib IS sharedlib + lt_cv_sharedlib_from_linklib_cmd="$ECHO" + ;; +esac + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_sharedlib_from_linklib_cmd" >&5 +$as_echo "$lt_cv_sharedlib_from_linklib_cmd" >&6; } +sharedlib_from_linklib_cmd=$lt_cv_sharedlib_from_linklib_cmd +test -z "$sharedlib_from_linklib_cmd" && sharedlib_from_linklib_cmd=$ECHO + + + + + + + +if test -n "$ac_tool_prefix"; then + for ac_prog in ar + 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 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_AR+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$AR"; then + ac_cv_prog_AR="$AR" # 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_AR="$ac_tool_prefix$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +AR=$ac_cv_prog_AR +if test -n "$AR"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AR" >&5 +$as_echo "$AR" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$AR" && break + done +fi +if test -z "$AR"; then + ac_ct_AR=$AR + for ac_prog in ar +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_AR+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_AR"; then + ac_cv_prog_ac_ct_AR="$ac_ct_AR" # 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_AR="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_AR=$ac_cv_prog_ac_ct_AR +if test -n "$ac_ct_AR"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_AR" >&5 +$as_echo "$ac_ct_AR" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$ac_ct_AR" && break +done + + if test "x$ac_ct_AR" = x; then + AR="false" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + AR=$ac_ct_AR + fi +fi + +: ${AR=ar} +: ${AR_FLAGS=cru} + + + + + + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for archiver @FILE support" >&5 +$as_echo_n "checking for archiver @FILE support... " >&6; } +if ${lt_cv_ar_at_file+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_ar_at_file=no + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + echo conftest.$ac_objext > conftest.lst + lt_ar_try='$AR $AR_FLAGS libconftest.a @conftest.lst >&5' + { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$lt_ar_try\""; } >&5 + (eval $lt_ar_try) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + if test "$ac_status" -eq 0; then + # Ensure the archiver fails upon bogus file names. + rm -f conftest.$ac_objext libconftest.a + { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$lt_ar_try\""; } >&5 + (eval $lt_ar_try) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + if test "$ac_status" -ne 0; then + lt_cv_ar_at_file=@ + fi + fi + rm -f conftest.* libconftest.a + +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ar_at_file" >&5 +$as_echo "$lt_cv_ar_at_file" >&6; } + +if test "x$lt_cv_ar_at_file" = xno; then + archiver_list_spec= +else + archiver_list_spec=$lt_cv_ar_at_file +fi + + + + + + + +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args. +set dummy ${ac_tool_prefix}strip; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_STRIP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$STRIP"; then + ac_cv_prog_STRIP="$STRIP" # 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_STRIP="${ac_tool_prefix}strip" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +STRIP=$ac_cv_prog_STRIP +if test -n "$STRIP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $STRIP" >&5 +$as_echo "$STRIP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_STRIP"; then + ac_ct_STRIP=$STRIP + # Extract the first word of "strip", so it can be a program name with args. +set dummy strip; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_STRIP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_STRIP"; then + ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_STRIP="strip" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP +if test -n "$ac_ct_STRIP"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_STRIP" >&5 +$as_echo "$ac_ct_STRIP" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_STRIP" = x; then + STRIP=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + STRIP=$ac_ct_STRIP + fi +else + STRIP="$ac_cv_prog_STRIP" +fi + +test -z "$STRIP" && STRIP=: + + + + + + +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args. +set dummy ${ac_tool_prefix}ranlib; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_RANLIB+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$RANLIB"; then + ac_cv_prog_RANLIB="$RANLIB" # 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +RANLIB=$ac_cv_prog_RANLIB +if test -n "$RANLIB"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $RANLIB" >&5 +$as_echo "$RANLIB" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_RANLIB"; then + ac_ct_RANLIB=$RANLIB + # Extract the first word of "ranlib", so it can be a program name with args. +set dummy ranlib; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_RANLIB+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_RANLIB"; then + ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_RANLIB="ranlib" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB +if test -n "$ac_ct_RANLIB"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_RANLIB" >&5 +$as_echo "$ac_ct_RANLIB" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_RANLIB" = x; then + RANLIB=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + RANLIB=$ac_ct_RANLIB + fi +else + RANLIB="$ac_cv_prog_RANLIB" +fi + +test -z "$RANLIB" && RANLIB=: + + + + + + +# Determine commands to create old-style static archives. +old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs' +old_postinstall_cmds='chmod 644 $oldlib' +old_postuninstall_cmds= + +if test -n "$RANLIB"; then + case $host_os in + openbsd*) + old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB -t \$oldlib" + ;; + *) + old_postinstall_cmds="$old_postinstall_cmds~\$RANLIB \$oldlib" + ;; + esac + old_archive_cmds="$old_archive_cmds~\$RANLIB \$oldlib" +fi + +case $host_os in + darwin*) + lock_old_archive_extraction=yes ;; + *) + lock_old_archive_extraction=no ;; +esac + + + + + + + + + + + + + + + + + + + + + +for ac_prog in gawk mawk nawk awk +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_AWK+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$AWK"; then + ac_cv_prog_AWK="$AWK" # 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_AWK="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +AWK=$ac_cv_prog_AWK +if test -n "$AWK"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AWK" >&5 +$as_echo "$AWK" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$AWK" && break +done + + + + + + + + + + + + + + + + + + + +# If no C compiler was specified, use CC. +LTCC=${LTCC-"$CC"} + +# If no C compiler flags were specified, use CFLAGS. +LTCFLAGS=${LTCFLAGS-"$CFLAGS"} + +# Allow CC to be a program name with arguments. +compiler=$CC + + +# Check for command to grab the raw symbol name followed by C symbol from nm. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking command to parse $NM output from $compiler object" >&5 +$as_echo_n "checking command to parse $NM output from $compiler object... " >&6; } +if ${lt_cv_sys_global_symbol_pipe+:} false; then : + $as_echo_n "(cached) " >&6 +else + +# These are sane defaults that work on at least a few old systems. +# [They come from Ultrix. What could be older than Ultrix?!! ;)] + +# Character class describing NM global symbol codes. +symcode='[BCDEGRST]' + +# Regexp to match symbols that can be accessed directly from C. +sympat='\([_A-Za-z][_A-Za-z0-9]*\)' + +# Define system-specific variables. +case $host_os in +aix*) + symcode='[BCDT]' + ;; +cygwin* | mingw* | pw32* | cegcc*) + symcode='[ABCDGISTW]' + ;; +hpux*) + if test "$host_cpu" = ia64; then + symcode='[ABCDEGRST]' + fi + ;; +irix* | nonstopux*) + symcode='[BCDEGRST]' + ;; +osf*) + symcode='[BCDEGQRST]' + ;; +solaris*) + symcode='[BDRT]' + ;; +sco3.2v5*) + symcode='[DT]' + ;; +sysv4.2uw2*) + symcode='[DT]' + ;; +sysv5* | sco5v6* | unixware* | OpenUNIX*) + symcode='[ABDT]' + ;; +sysv4) + symcode='[DFNSTU]' + ;; +esac + +# If we're using GNU nm, then use its standard symbol codes. +case `$NM -V 2>&1` in +*GNU* | *'with BFD'*) + symcode='[ABCDGIRSTW]' ;; +esac + +# Transform an extracted symbol line into a proper C declaration. +# Some systems (esp. on ia64) link data and code symbols differently, +# so use this general approach. +lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern int \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'" + +# Transform an extracted symbol line into symbol name and symbol address +lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([^ ]*\)[ ]*$/ {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([^ ]*\) \([^ ]*\)$/ {\"\2\", (void *) \&\2},/p'" +lt_cv_sys_global_symbol_to_c_name_address_lib_prefix="sed -n -e 's/^: \([^ ]*\)[ ]*$/ {\\\"\1\\\", (void *) 0},/p' -e 's/^$symcode* \([^ ]*\) \(lib[^ ]*\)$/ {\"\2\", (void *) \&\2},/p' -e 's/^$symcode* \([^ ]*\) \([^ ]*\)$/ {\"lib\2\", (void *) \&\2},/p'" + +# Handle CRLF in mingw tool chain +opt_cr= +case $build_os in +mingw*) + opt_cr=`$ECHO 'x\{0,1\}' | tr x '\015'` # option cr in regexp + ;; +esac + +# Try without a prefix underscore, then with it. +for ac_symprfx in "" "_"; do + + # Transform symcode, sympat, and symprfx into a raw symbol and a C symbol. + symxfrm="\\1 $ac_symprfx\\2 \\2" + + # Write the raw and C identifiers. + if test "$lt_cv_nm_interface" = "MS dumpbin"; then + # Fake it for dumpbin and say T for any non-static function + # and D for any global variable. + # Also find C++ and __fastcall symbols from MSVC++, + # which start with @ or ?. + lt_cv_sys_global_symbol_pipe="$AWK '"\ +" {last_section=section; section=\$ 3};"\ +" /Section length .*#relocs.*(pick any)/{hide[last_section]=1};"\ +" \$ 0!~/External *\|/{next};"\ +" / 0+ UNDEF /{next}; / UNDEF \([^|]\)*()/{next};"\ +" {if(hide[section]) next};"\ +" {f=0}; \$ 0~/\(\).*\|/{f=1}; {printf f ? \"T \" : \"D \"};"\ +" {split(\$ 0, a, /\||\r/); split(a[2], s)};"\ +" s[1]~/^[@?]/{print s[1], s[1]; next};"\ +" s[1]~prfx {split(s[1],t,\"@\"); print t[1], substr(t[1],length(prfx))}"\ +" ' prfx=^$ac_symprfx" + else + lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[ ]\($symcode$symcode*\)[ ][ ]*$ac_symprfx$sympat$opt_cr$/$symxfrm/p'" + fi + lt_cv_sys_global_symbol_pipe="$lt_cv_sys_global_symbol_pipe | sed '/ __gnu_lto/d'" + + # Check to see that the pipe works correctly. + pipe_works=no + + rm -f conftest* + cat > conftest.$ac_ext <<_LT_EOF +#ifdef __cplusplus +extern "C" { +#endif +char nm_test_var; +void nm_test_func(void); +void nm_test_func(void){} +#ifdef __cplusplus +} +#endif +int main(){nm_test_var='a';nm_test_func();return(0);} +_LT_EOF + + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + # Now try to grab the symbols. + nlist=conftest.nm + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$NM conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist\""; } >&5 + (eval $NM conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && test -s "$nlist"; then + # Try sorting and uniquifying the output. + if sort "$nlist" | uniq > "$nlist"T; then + mv -f "$nlist"T "$nlist" + else + rm -f "$nlist"T + fi + + # Make sure that we snagged all the symbols we need. + if $GREP ' nm_test_var$' "$nlist" >/dev/null; then + if $GREP ' nm_test_func$' "$nlist" >/dev/null; then + cat <<_LT_EOF > conftest.$ac_ext +/* Keep this code in sync between libtool.m4, ltmain, lt_system.h, and tests. */ +#if defined(_WIN32) || defined(__CYGWIN__) || defined(_WIN32_WCE) +/* DATA imports from DLLs on WIN32 con't be const, because runtime + relocations are performed -- see ld's documentation on pseudo-relocs. */ +# define LT_DLSYM_CONST +#elif defined(__osf__) +/* This system does not cope well with relocations in const data. */ +# define LT_DLSYM_CONST +#else +# define LT_DLSYM_CONST const +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +_LT_EOF + # Now generate the symbol file. + eval "$lt_cv_sys_global_symbol_to_cdecl"' < "$nlist" | $GREP -v main >> conftest.$ac_ext' + + cat <<_LT_EOF >> conftest.$ac_ext + +/* The mapping between symbol names and symbols. */ +LT_DLSYM_CONST struct { + const char *name; + void *address; +} +lt__PROGRAM__LTX_preloaded_symbols[] = +{ + { "@PROGRAM@", (void *) 0 }, +_LT_EOF + $SED "s/^$symcode$symcode* \(.*\) \(.*\)$/ {\"\2\", (void *) \&\2},/" < "$nlist" | $GREP -v main >> conftest.$ac_ext + cat <<\_LT_EOF >> conftest.$ac_ext + {0, (void *) 0} +}; + +/* This works around a problem in FreeBSD linker */ +#ifdef FREEBSD_WORKAROUND +static const void *lt_preloaded_setup() { + return lt__PROGRAM__LTX_preloaded_symbols; +} +#endif + +#ifdef __cplusplus +} +#endif +_LT_EOF + # Now try linking the two files. + mv conftest.$ac_objext conftstm.$ac_objext + lt_globsym_save_LIBS=$LIBS + lt_globsym_save_CFLAGS=$CFLAGS + LIBS="conftstm.$ac_objext" + CFLAGS="$CFLAGS$lt_prog_compiler_no_builtin_flag" + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5 + (eval $ac_link) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && test -s conftest${ac_exeext}; then + pipe_works=yes + fi + LIBS=$lt_globsym_save_LIBS + CFLAGS=$lt_globsym_save_CFLAGS + else + echo "cannot find nm_test_func in $nlist" >&5 + fi + else + echo "cannot find nm_test_var in $nlist" >&5 + fi + else + echo "cannot run $lt_cv_sys_global_symbol_pipe" >&5 + fi + else + echo "$progname: failed program was:" >&5 + cat conftest.$ac_ext >&5 + fi + rm -rf conftest* conftst* + + # Do not use the global_symbol_pipe unless it works. + if test "$pipe_works" = yes; then + break + else + lt_cv_sys_global_symbol_pipe= + fi +done + +fi + +if test -z "$lt_cv_sys_global_symbol_pipe"; then + lt_cv_sys_global_symbol_to_cdecl= +fi +if test -z "$lt_cv_sys_global_symbol_pipe$lt_cv_sys_global_symbol_to_cdecl"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: failed" >&5 +$as_echo "failed" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: ok" >&5 +$as_echo "ok" >&6; } +fi + +# Response file support. +if test "$lt_cv_nm_interface" = "MS dumpbin"; then + nm_file_list_spec='@' +elif $NM --help 2>/dev/null | grep '[@]FILE' >/dev/null; then + nm_file_list_spec='@' +fi + + + + + + + + + + + + + + + + + + + + + + + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for sysroot" >&5 +$as_echo_n "checking for sysroot... " >&6; } + +# Check whether --with-sysroot was given. +if test "${with_sysroot+set}" = set; then : + withval=$with_sysroot; +else + with_sysroot=no +fi + + +lt_sysroot= +case ${with_sysroot} in #( + yes) + if test "$GCC" = yes; then + lt_sysroot=`$CC --print-sysroot 2>/dev/null` + fi + ;; #( + /*) + lt_sysroot=`echo "$with_sysroot" | sed -e "$sed_quote_subst"` + ;; #( + no|'') + ;; #( + *) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: ${with_sysroot}" >&5 +$as_echo "${with_sysroot}" >&6; } + as_fn_error $? "The sysroot must be an absolute path." "$LINENO" 5 + ;; +esac + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: ${lt_sysroot:-no}" >&5 +$as_echo "${lt_sysroot:-no}" >&6; } + + + + + +# Check whether --enable-libtool-lock was given. +if test "${enable_libtool_lock+set}" = set; then : + enableval=$enable_libtool_lock; +fi + +test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes + +# Some flags need to be propagated to the compiler or linker for good +# libtool support. +case $host in +ia64-*-hpux*) + # Find out which ABI we are using. + echo 'int i;' > conftest.$ac_ext + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + case `/usr/bin/file conftest.$ac_objext` in + *ELF-32*) + HPUX_IA64_MODE="32" + ;; + *ELF-64*) + HPUX_IA64_MODE="64" + ;; + esac + fi + rm -rf conftest* + ;; +*-*-irix6*) + # Find out which ABI we are using. + echo '#line '$LINENO' "configure"' > conftest.$ac_ext + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + if test "$lt_cv_prog_gnu_ld" = yes; then + case `/usr/bin/file conftest.$ac_objext` in + *32-bit*) + LD="${LD-ld} -melf32bsmip" + ;; + *N32*) + LD="${LD-ld} -melf32bmipn32" + ;; + *64-bit*) + LD="${LD-ld} -melf64bmip" + ;; + esac + else + case `/usr/bin/file conftest.$ac_objext` in + *32-bit*) + LD="${LD-ld} -32" + ;; + *N32*) + LD="${LD-ld} -n32" + ;; + *64-bit*) + LD="${LD-ld} -64" + ;; + esac + fi + fi + rm -rf conftest* + ;; + +x86_64-*kfreebsd*-gnu|x86_64-*linux*|ppc*-*linux*|powerpc*-*linux*| \ +s390*-*linux*|s390*-*tpf*|sparc*-*linux*) + # Find out which ABI we are using. + echo 'int i;' > conftest.$ac_ext + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + case `/usr/bin/file conftest.o` in + *32-bit*) + case $host in + x86_64-*kfreebsd*-gnu) + LD="${LD-ld} -m elf_i386_fbsd" + ;; + x86_64-*linux*) + LD="${LD-ld} -m elf_i386" + ;; + ppc64-*linux*|powerpc64-*linux*) + LD="${LD-ld} -m elf32ppclinux" + ;; + s390x-*linux*) + LD="${LD-ld} -m elf_s390" + ;; + sparc64-*linux*) + LD="${LD-ld} -m elf32_sparc" + ;; + esac + ;; + *64-bit*) + case $host in + x86_64-*kfreebsd*-gnu) + LD="${LD-ld} -m elf_x86_64_fbsd" + ;; + x86_64-*linux*) + LD="${LD-ld} -m elf_x86_64" + ;; + ppc*-*linux*|powerpc*-*linux*) + LD="${LD-ld} -m elf64ppc" + ;; + s390*-*linux*|s390*-*tpf*) + LD="${LD-ld} -m elf64_s390" + ;; + sparc*-*linux*) + LD="${LD-ld} -m elf64_sparc" + ;; + esac + ;; + esac + fi + rm -rf conftest* + ;; + +*-*-sco3.2v5*) + # On SCO OpenServer 5, we need -belf to get full-featured binaries. + SAVE_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS -belf" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler needs -belf" >&5 +$as_echo_n "checking whether the C compiler needs -belf... " >&6; } +if ${lt_cv_cc_needs_belf+:} false; then : + $as_echo_n "(cached) " >&6 +else + 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 + + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + lt_cv_cc_needs_belf=yes +else + lt_cv_cc_needs_belf=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext 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 + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_cc_needs_belf" >&5 +$as_echo "$lt_cv_cc_needs_belf" >&6; } + if test x"$lt_cv_cc_needs_belf" != x"yes"; then + # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf + CFLAGS="$SAVE_CFLAGS" + fi + ;; +sparc*-*solaris*) + # Find out which ABI we are using. + echo 'int i;' > conftest.$ac_ext + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + case `/usr/bin/file conftest.o` in + *64-bit*) + case $lt_cv_prog_gnu_ld in + yes*) LD="${LD-ld} -m elf64_sparc" ;; + *) + if ${LD-ld} -64 -r -o conftest2.o conftest.o >/dev/null 2>&1; then + LD="${LD-ld} -64" + fi + ;; + esac + ;; + esac + fi + rm -rf conftest* + ;; +esac + +need_locks="$enable_libtool_lock" + +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}mt", so it can be a program name with args. +set dummy ${ac_tool_prefix}mt; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_MANIFEST_TOOL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$MANIFEST_TOOL"; then + ac_cv_prog_MANIFEST_TOOL="$MANIFEST_TOOL" # 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_MANIFEST_TOOL="${ac_tool_prefix}mt" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +MANIFEST_TOOL=$ac_cv_prog_MANIFEST_TOOL +if test -n "$MANIFEST_TOOL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MANIFEST_TOOL" >&5 +$as_echo "$MANIFEST_TOOL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_MANIFEST_TOOL"; then + ac_ct_MANIFEST_TOOL=$MANIFEST_TOOL + # Extract the first word of "mt", so it can be a program name with args. +set dummy mt; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_MANIFEST_TOOL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_MANIFEST_TOOL"; then + ac_cv_prog_ac_ct_MANIFEST_TOOL="$ac_ct_MANIFEST_TOOL" # 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_MANIFEST_TOOL="mt" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_MANIFEST_TOOL=$ac_cv_prog_ac_ct_MANIFEST_TOOL +if test -n "$ac_ct_MANIFEST_TOOL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_MANIFEST_TOOL" >&5 +$as_echo "$ac_ct_MANIFEST_TOOL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_MANIFEST_TOOL" = x; then + MANIFEST_TOOL=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + MANIFEST_TOOL=$ac_ct_MANIFEST_TOOL + fi +else + MANIFEST_TOOL="$ac_cv_prog_MANIFEST_TOOL" +fi + +test -z "$MANIFEST_TOOL" && MANIFEST_TOOL=mt +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if $MANIFEST_TOOL is a manifest tool" >&5 +$as_echo_n "checking if $MANIFEST_TOOL is a manifest tool... " >&6; } +if ${lt_cv_path_mainfest_tool+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_path_mainfest_tool=no + echo "$as_me:$LINENO: $MANIFEST_TOOL '-?'" >&5 + $MANIFEST_TOOL '-?' 2>conftest.err > conftest.out + cat conftest.err >&5 + if $GREP 'Manifest Tool' conftest.out > /dev/null; then + lt_cv_path_mainfest_tool=yes + fi + rm -f conftest* +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_path_mainfest_tool" >&5 +$as_echo "$lt_cv_path_mainfest_tool" >&6; } +if test "x$lt_cv_path_mainfest_tool" != xyes; then + MANIFEST_TOOL=: +fi + + + + + + + case $host_os in + rhapsody* | darwin*) + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}dsymutil", so it can be a program name with args. +set dummy ${ac_tool_prefix}dsymutil; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_DSYMUTIL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$DSYMUTIL"; then + ac_cv_prog_DSYMUTIL="$DSYMUTIL" # 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_DSYMUTIL="${ac_tool_prefix}dsymutil" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +DSYMUTIL=$ac_cv_prog_DSYMUTIL +if test -n "$DSYMUTIL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DSYMUTIL" >&5 +$as_echo "$DSYMUTIL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_DSYMUTIL"; then + ac_ct_DSYMUTIL=$DSYMUTIL + # Extract the first word of "dsymutil", so it can be a program name with args. +set dummy dsymutil; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_DSYMUTIL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_DSYMUTIL"; then + ac_cv_prog_ac_ct_DSYMUTIL="$ac_ct_DSYMUTIL" # 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_DSYMUTIL="dsymutil" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_DSYMUTIL=$ac_cv_prog_ac_ct_DSYMUTIL +if test -n "$ac_ct_DSYMUTIL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_DSYMUTIL" >&5 +$as_echo "$ac_ct_DSYMUTIL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_DSYMUTIL" = x; then + DSYMUTIL=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + DSYMUTIL=$ac_ct_DSYMUTIL + fi +else + DSYMUTIL="$ac_cv_prog_DSYMUTIL" +fi + + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}nmedit", so it can be a program name with args. +set dummy ${ac_tool_prefix}nmedit; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_NMEDIT+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$NMEDIT"; then + ac_cv_prog_NMEDIT="$NMEDIT" # 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_NMEDIT="${ac_tool_prefix}nmedit" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +NMEDIT=$ac_cv_prog_NMEDIT +if test -n "$NMEDIT"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $NMEDIT" >&5 +$as_echo "$NMEDIT" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_NMEDIT"; then + ac_ct_NMEDIT=$NMEDIT + # Extract the first word of "nmedit", so it can be a program name with args. +set dummy nmedit; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_NMEDIT+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_NMEDIT"; then + ac_cv_prog_ac_ct_NMEDIT="$ac_ct_NMEDIT" # 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_NMEDIT="nmedit" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_NMEDIT=$ac_cv_prog_ac_ct_NMEDIT +if test -n "$ac_ct_NMEDIT"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_NMEDIT" >&5 +$as_echo "$ac_ct_NMEDIT" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_NMEDIT" = x; then + NMEDIT=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + NMEDIT=$ac_ct_NMEDIT + fi +else + NMEDIT="$ac_cv_prog_NMEDIT" +fi + + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}lipo", so it can be a program name with args. +set dummy ${ac_tool_prefix}lipo; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_LIPO+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$LIPO"; then + ac_cv_prog_LIPO="$LIPO" # 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_LIPO="${ac_tool_prefix}lipo" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +LIPO=$ac_cv_prog_LIPO +if test -n "$LIPO"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $LIPO" >&5 +$as_echo "$LIPO" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_LIPO"; then + ac_ct_LIPO=$LIPO + # Extract the first word of "lipo", so it can be a program name with args. +set dummy lipo; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_LIPO+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_LIPO"; then + ac_cv_prog_ac_ct_LIPO="$ac_ct_LIPO" # 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_LIPO="lipo" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_LIPO=$ac_cv_prog_ac_ct_LIPO +if test -n "$ac_ct_LIPO"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_LIPO" >&5 +$as_echo "$ac_ct_LIPO" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_LIPO" = x; then + LIPO=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + LIPO=$ac_ct_LIPO + fi +else + LIPO="$ac_cv_prog_LIPO" +fi + + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}otool", so it can be a program name with args. +set dummy ${ac_tool_prefix}otool; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_OTOOL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$OTOOL"; then + ac_cv_prog_OTOOL="$OTOOL" # 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_OTOOL="${ac_tool_prefix}otool" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +OTOOL=$ac_cv_prog_OTOOL +if test -n "$OTOOL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OTOOL" >&5 +$as_echo "$OTOOL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_OTOOL"; then + ac_ct_OTOOL=$OTOOL + # Extract the first word of "otool", so it can be a program name with args. +set dummy otool; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_OTOOL+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_OTOOL"; then + ac_cv_prog_ac_ct_OTOOL="$ac_ct_OTOOL" # 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_OTOOL="otool" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_OTOOL=$ac_cv_prog_ac_ct_OTOOL +if test -n "$ac_ct_OTOOL"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OTOOL" >&5 +$as_echo "$ac_ct_OTOOL" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_OTOOL" = x; then + OTOOL=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + OTOOL=$ac_ct_OTOOL + fi +else + OTOOL="$ac_cv_prog_OTOOL" +fi + + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}otool64", so it can be a program name with args. +set dummy ${ac_tool_prefix}otool64; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_OTOOL64+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$OTOOL64"; then + ac_cv_prog_OTOOL64="$OTOOL64" # 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_OTOOL64="${ac_tool_prefix}otool64" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +OTOOL64=$ac_cv_prog_OTOOL64 +if test -n "$OTOOL64"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OTOOL64" >&5 +$as_echo "$OTOOL64" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_prog_OTOOL64"; then + ac_ct_OTOOL64=$OTOOL64 + # Extract the first word of "otool64", so it can be a program name with args. +set dummy otool64; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_OTOOL64+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_OTOOL64"; then + ac_cv_prog_ac_ct_OTOOL64="$ac_ct_OTOOL64" # 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_ac_ct_OTOOL64="otool64" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_OTOOL64=$ac_cv_prog_ac_ct_OTOOL64 +if test -n "$ac_ct_OTOOL64"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_OTOOL64" >&5 +$as_echo "$ac_ct_OTOOL64" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_ct_OTOOL64" = x; then + OTOOL64=":" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + OTOOL64=$ac_ct_OTOOL64 + fi +else + OTOOL64="$ac_cv_prog_OTOOL64" +fi + + + + + + + + + + + + + + + + + + + + + + + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -single_module linker flag" >&5 +$as_echo_n "checking for -single_module linker flag... " >&6; } +if ${lt_cv_apple_cc_single_mod+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_apple_cc_single_mod=no + if test -z "${LT_MULTI_MODULE}"; then + # By default we will add the -single_module flag. You can override + # by either setting the environment variable LT_MULTI_MODULE + # non-empty at configure time, or by adding -multi_module to the + # link flags. + rm -rf libconftest.dylib* + echo "int foo(void){return 1;}" > conftest.c + echo "$LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ +-dynamiclib -Wl,-single_module conftest.c" >&5 + $LTCC $LTCFLAGS $LDFLAGS -o libconftest.dylib \ + -dynamiclib -Wl,-single_module conftest.c 2>conftest.err + _lt_result=$? + if test -f libconftest.dylib && test ! -s conftest.err && test $_lt_result = 0; then + lt_cv_apple_cc_single_mod=yes + else + cat conftest.err >&5 + fi + rm -rf libconftest.dylib* + rm -f conftest.* + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_apple_cc_single_mod" >&5 +$as_echo "$lt_cv_apple_cc_single_mod" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -exported_symbols_list linker flag" >&5 +$as_echo_n "checking for -exported_symbols_list linker flag... " >&6; } +if ${lt_cv_ld_exported_symbols_list+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_ld_exported_symbols_list=no + save_LDFLAGS=$LDFLAGS + echo "_main" > conftest.sym + LDFLAGS="$LDFLAGS -Wl,-exported_symbols_list,conftest.sym" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + lt_cv_ld_exported_symbols_list=yes +else + lt_cv_ld_exported_symbols_list=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + LDFLAGS="$save_LDFLAGS" + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_exported_symbols_list" >&5 +$as_echo "$lt_cv_ld_exported_symbols_list" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -force_load linker flag" >&5 +$as_echo_n "checking for -force_load linker flag... " >&6; } +if ${lt_cv_ld_force_load+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_ld_force_load=no + cat > conftest.c << _LT_EOF +int forced_loaded() { return 2;} +_LT_EOF + echo "$LTCC $LTCFLAGS -c -o conftest.o conftest.c" >&5 + $LTCC $LTCFLAGS -c -o conftest.o conftest.c 2>&5 + echo "$AR cru libconftest.a conftest.o" >&5 + $AR cru libconftest.a conftest.o 2>&5 + echo "$RANLIB libconftest.a" >&5 + $RANLIB libconftest.a 2>&5 + cat > conftest.c << _LT_EOF +int main() { return 0;} +_LT_EOF + echo "$LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a" >&5 + $LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a 2>conftest.err + _lt_result=$? + if test -f conftest && test ! -s conftest.err && test $_lt_result = 0 && $GREP forced_load conftest 2>&1 >/dev/null; then + lt_cv_ld_force_load=yes + else + cat conftest.err >&5 + fi + rm -f conftest.err libconftest.a conftest conftest.c + rm -rf conftest.dSYM + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_force_load" >&5 +$as_echo "$lt_cv_ld_force_load" >&6; } + case $host_os in + rhapsody* | darwin1.[012]) + _lt_dar_allow_undefined='${wl}-undefined ${wl}suppress' ;; + darwin1.*) + _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;; + darwin*) # darwin 5.x on + # if running on 10.5 or later, the deployment target defaults + # to the OS version, if on x86, and 10.4, the deployment + # target defaults to 10.4. Don't you love it? + case ${MACOSX_DEPLOYMENT_TARGET-10.0},$host in + 10.0,*86*-darwin8*|10.0,*-darwin[91]*) + _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;; + 10.[012]*) + _lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;; + 10.*) + _lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;; + esac + ;; + esac + if test "$lt_cv_apple_cc_single_mod" = "yes"; then + _lt_dar_single_mod='$single_module' + fi + if test "$lt_cv_ld_exported_symbols_list" = "yes"; then + _lt_dar_export_syms=' ${wl}-exported_symbols_list,$output_objdir/${libname}-symbols.expsym' + else + _lt_dar_export_syms='~$NMEDIT -s $output_objdir/${libname}-symbols.expsym ${lib}' + fi + if test "$DSYMUTIL" != ":" && test "$lt_cv_ld_force_load" = "no"; then + _lt_dsymutil='~$DSYMUTIL $lib || :' + else + _lt_dsymutil= + fi + ;; + esac + +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 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5 +$as_echo_n "checking how to run the C preprocessor... " >&6; } +# On Suns, sometimes $CPP names a directory. +if test -n "$CPP" && test -d "$CPP"; then + CPP= +fi +if test -z "$CPP"; then + if ${ac_cv_prog_CPP+:} false; then : + $as_echo_n "(cached) " >&6 +else + # Double quotes because CPP needs to be expanded + for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp" + do + ac_preproc_ok=false +for ac_c_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer to if __STDC__ is defined, since + # exists even on freestanding compilers. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifdef __STDC__ +# include +#else +# include +#endif + Syntax error +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + +else + # Broken: fails on valid input. +continue +fi +rm -f conftest.err conftest.i conftest.$ac_ext + + # OK, works on sane cases. Now check whether nonexistent headers + # can be detected and how. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + # Broken: success on invalid input. +continue +else + # Passes both tests. +ac_preproc_ok=: +break +fi +rm -f conftest.err conftest.i conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.i conftest.err conftest.$ac_ext +if $ac_preproc_ok; then : + break +fi + + done + ac_cv_prog_CPP=$CPP + +fi + CPP=$ac_cv_prog_CPP +else + ac_cv_prog_CPP=$CPP +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $CPP" >&5 +$as_echo "$CPP" >&6; } +ac_preproc_ok=false +for ac_c_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer to if __STDC__ is defined, since + # exists even on freestanding compilers. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifdef __STDC__ +# include +#else +# include +#endif + Syntax error +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + +else + # Broken: fails on valid input. +continue +fi +rm -f conftest.err conftest.i conftest.$ac_ext + + # OK, works on sane cases. Now check whether nonexistent headers + # can be detected and how. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +_ACEOF +if ac_fn_c_try_cpp "$LINENO"; then : + # Broken: success on invalid input. +continue +else + # Passes both tests. +ac_preproc_ok=: +break +fi +rm -f conftest.err conftest.i conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.i conftest.err conftest.$ac_ext +if $ac_preproc_ok; then : + +else + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "C preprocessor \"$CPP\" fails sanity check +See \`config.log' for more details" "$LINENO" 5; } +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 + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5 +$as_echo_n "checking for ANSI C header files... " >&6; } +if ${ac_cv_header_stdc+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include +#include +#include + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_header_stdc=yes +else + ac_cv_header_stdc=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + +if test $ac_cv_header_stdc = yes; then + # SunOS 4.x string.h does not declare mem*, contrary to ANSI. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "memchr" >/dev/null 2>&1; then : + +else + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "free" >/dev/null 2>&1; then : + +else + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. + if test "$cross_compiling" = yes; then : + : +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include +#if ((' ' & 0x0FF) == 0x020) +# define ISLOWER(c) ('a' <= (c) && (c) <= 'z') +# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) +#else +# define ISLOWER(c) \ + (('a' <= (c) && (c) <= 'i') \ + || ('j' <= (c) && (c) <= 'r') \ + || ('s' <= (c) && (c) <= 'z')) +# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) +#endif + +#define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) +int +main () +{ + int i; + for (i = 0; i < 256; i++) + if (XOR (islower (i), ISLOWER (i)) + || toupper (i) != TOUPPER (i)) + return 2; + return 0; +} +_ACEOF +if ac_fn_c_try_run "$LINENO"; then : + +else + ac_cv_header_stdc=no +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + +fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5 +$as_echo "$ac_cv_header_stdc" >&6; } +if test $ac_cv_header_stdc = yes; then + +$as_echo "#define STDC_HEADERS 1" >>confdefs.h + +fi + +# On IRIX 5.3, sys/types and inttypes.h are conflicting. +for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \ + inttypes.h stdint.h unistd.h +do : + as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` +ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default +" +if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + +for ac_header in dlfcn.h +do : + ac_fn_c_check_header_compile "$LINENO" "dlfcn.h" "ac_cv_header_dlfcn_h" "$ac_includes_default +" +if test "x$ac_cv_header_dlfcn_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_DLFCN_H 1 +_ACEOF + +fi + +done + + + +func_stripname_cnf () +{ + case ${2} in + .*) func_stripname_result=`$ECHO "${3}" | $SED "s%^${1}%%; s%\\\\${2}\$%%"`;; + *) func_stripname_result=`$ECHO "${3}" | $SED "s%^${1}%%; s%${2}\$%%"`;; + esac +} # func_stripname_cnf + + + + + +# Set options + + + + enable_dlopen=no + + + enable_win32_dll=no + + + # Check whether --enable-shared was given. +if test "${enable_shared+set}" = set; then : + enableval=$enable_shared; p=${PACKAGE-default} + case $enableval in + yes) enable_shared=yes ;; + no) enable_shared=no ;; + *) + enable_shared=no + # Look at the argument we got. We use all the common list separators. + lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," + for pkg in $enableval; do + IFS="$lt_save_ifs" + if test "X$pkg" = "X$p"; then + enable_shared=yes + fi + done + IFS="$lt_save_ifs" + ;; + esac +else + enable_shared=yes +fi + + + + + + + + + + # Check whether --enable-static was given. +if test "${enable_static+set}" = set; then : + enableval=$enable_static; p=${PACKAGE-default} + case $enableval in + yes) enable_static=yes ;; + no) enable_static=no ;; + *) + enable_static=no + # Look at the argument we got. We use all the common list separators. + lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," + for pkg in $enableval; do + IFS="$lt_save_ifs" + if test "X$pkg" = "X$p"; then + enable_static=yes + fi + done + IFS="$lt_save_ifs" + ;; + esac +else + enable_static=yes +fi + + + + + + + + + + +# Check whether --with-pic was given. +if test "${with_pic+set}" = set; then : + withval=$with_pic; pic_mode="$withval" +else + pic_mode=default +fi + + +test -z "$pic_mode" && pic_mode=default + + + + + + + + # Check whether --enable-fast-install was given. +if test "${enable_fast_install+set}" = set; then : + enableval=$enable_fast_install; p=${PACKAGE-default} + case $enableval in + yes) enable_fast_install=yes ;; + no) enable_fast_install=no ;; + *) + enable_fast_install=no + # Look at the argument we got. We use all the common list separators. + lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," + for pkg in $enableval; do + IFS="$lt_save_ifs" + if test "X$pkg" = "X$p"; then + enable_fast_install=yes + fi + done + IFS="$lt_save_ifs" + ;; + esac +else + enable_fast_install=yes +fi + + + + + + + + + + + +# This can be used to rebuild libtool when needed +LIBTOOL_DEPS="$ltmain" + +# Always use our own libtool. +LIBTOOL='$(SHELL) $(top_builddir)/libtool' + + + + + + + + + + + + + + + + + + + + + + + + + + +test -z "$LN_S" && LN_S="ln -s" + + + + + + + + + + + + + + +if test -n "${ZSH_VERSION+set}" ; then + setopt NO_GLOB_SUBST +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for objdir" >&5 +$as_echo_n "checking for objdir... " >&6; } +if ${lt_cv_objdir+:} false; then : + $as_echo_n "(cached) " >&6 +else + rm -f .libs 2>/dev/null +mkdir .libs 2>/dev/null +if test -d .libs; then + lt_cv_objdir=.libs +else + # MS-DOS does not allow filenames that begin with a dot. + lt_cv_objdir=_libs +fi +rmdir .libs 2>/dev/null +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_objdir" >&5 +$as_echo "$lt_cv_objdir" >&6; } +objdir=$lt_cv_objdir + + + + + +cat >>confdefs.h <<_ACEOF +#define LT_OBJDIR "$lt_cv_objdir/" +_ACEOF + + + + +case $host_os in +aix3*) + # AIX sometimes has problems with the GCC collect2 program. For some + # reason, if we set the COLLECT_NAMES environment variable, the problems + # vanish in a puff of smoke. + if test "X${COLLECT_NAMES+set}" != Xset; then + COLLECT_NAMES= + export COLLECT_NAMES + fi + ;; +esac + +# Global variables: +ofile=libtool +can_build_shared=yes + +# All known linkers require a `.a' archive for static linking (except MSVC, +# which needs '.lib'). +libext=a + +with_gnu_ld="$lt_cv_prog_gnu_ld" + +old_CC="$CC" +old_CFLAGS="$CFLAGS" + +# Set sane defaults for various variables +test -z "$CC" && CC=cc +test -z "$LTCC" && LTCC=$CC +test -z "$LTCFLAGS" && LTCFLAGS=$CFLAGS +test -z "$LD" && LD=ld +test -z "$ac_objext" && ac_objext=o + +for cc_temp in $compiler""; do + case $cc_temp in + compile | *[\\/]compile | ccache | *[\\/]ccache ) ;; + distcc | *[\\/]distcc | purify | *[\\/]purify ) ;; + \-*) ;; + *) break;; + esac +done +cc_basename=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"` + + +# Only perform the check for file, if the check method requires it +test -z "$MAGIC_CMD" && MAGIC_CMD=file +case $deplibs_check_method in +file_magic*) + if test "$file_magic_cmd" = '$MAGIC_CMD'; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ${ac_tool_prefix}file" >&5 +$as_echo_n "checking for ${ac_tool_prefix}file... " >&6; } +if ${lt_cv_path_MAGIC_CMD+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $MAGIC_CMD in +[\\/*] | ?:[\\/]*) + lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path. + ;; +*) + lt_save_MAGIC_CMD="$MAGIC_CMD" + lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR + ac_dummy="/usr/bin$PATH_SEPARATOR$PATH" + for ac_dir in $ac_dummy; do + IFS="$lt_save_ifs" + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/${ac_tool_prefix}file; then + lt_cv_path_MAGIC_CMD="$ac_dir/${ac_tool_prefix}file" + if test -n "$file_magic_test_file"; then + case $deplibs_check_method in + "file_magic "*) + file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"` + MAGIC_CMD="$lt_cv_path_MAGIC_CMD" + if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | + $EGREP "$file_magic_regex" > /dev/null; then + : + else + cat <<_LT_EOF 1>&2 + +*** Warning: the command libtool uses to detect shared libraries, +*** $file_magic_cmd, produces output that libtool cannot recognize. +*** The result is that libtool may fail to recognize shared libraries +*** as such. This will affect the creation of libtool libraries that +*** depend on shared libraries, but programs linked with such libtool +*** libraries will work regardless of this problem. Nevertheless, you +*** may want to report the problem to your system manager and/or to +*** bug-libtool@gnu.org + +_LT_EOF + fi ;; + esac + fi + break + fi + done + IFS="$lt_save_ifs" + MAGIC_CMD="$lt_save_MAGIC_CMD" + ;; +esac +fi + +MAGIC_CMD="$lt_cv_path_MAGIC_CMD" +if test -n "$MAGIC_CMD"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MAGIC_CMD" >&5 +$as_echo "$MAGIC_CMD" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + + + +if test -z "$lt_cv_path_MAGIC_CMD"; then + if test -n "$ac_tool_prefix"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for file" >&5 +$as_echo_n "checking for file... " >&6; } +if ${lt_cv_path_MAGIC_CMD+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $MAGIC_CMD in +[\\/*] | ?:[\\/]*) + lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path. + ;; +*) + lt_save_MAGIC_CMD="$MAGIC_CMD" + lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR + ac_dummy="/usr/bin$PATH_SEPARATOR$PATH" + for ac_dir in $ac_dummy; do + IFS="$lt_save_ifs" + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/file; then + lt_cv_path_MAGIC_CMD="$ac_dir/file" + if test -n "$file_magic_test_file"; then + case $deplibs_check_method in + "file_magic "*) + file_magic_regex=`expr "$deplibs_check_method" : "file_magic \(.*\)"` + MAGIC_CMD="$lt_cv_path_MAGIC_CMD" + if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | + $EGREP "$file_magic_regex" > /dev/null; then + : + else + cat <<_LT_EOF 1>&2 + +*** Warning: the command libtool uses to detect shared libraries, +*** $file_magic_cmd, produces output that libtool cannot recognize. +*** The result is that libtool may fail to recognize shared libraries +*** as such. This will affect the creation of libtool libraries that +*** depend on shared libraries, but programs linked with such libtool +*** libraries will work regardless of this problem. Nevertheless, you +*** may want to report the problem to your system manager and/or to +*** bug-libtool@gnu.org + +_LT_EOF + fi ;; + esac + fi + break + fi + done + IFS="$lt_save_ifs" + MAGIC_CMD="$lt_save_MAGIC_CMD" + ;; +esac +fi + +MAGIC_CMD="$lt_cv_path_MAGIC_CMD" +if test -n "$MAGIC_CMD"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MAGIC_CMD" >&5 +$as_echo "$MAGIC_CMD" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + else + MAGIC_CMD=: + fi +fi + + fi + ;; +esac + +# Use C for the default configuration in the libtool script + +lt_save_CC="$CC" +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 + + +# Source file extension for C test sources. +ac_ext=c + +# Object file extension for compiled C test sources. +objext=o +objext=$objext + +# Code to be used in simple compile tests +lt_simple_compile_test_code="int some_variable = 0;" + +# Code to be used in simple link tests +lt_simple_link_test_code='int main(){return(0);}' + + + + + + + +# If no C compiler was specified, use CC. +LTCC=${LTCC-"$CC"} + +# If no C compiler flags were specified, use CFLAGS. +LTCFLAGS=${LTCFLAGS-"$CFLAGS"} + +# Allow CC to be a program name with arguments. +compiler=$CC + +# Save the default compiler, since it gets overwritten when the other +# tags are being tested, and _LT_TAGVAR(compiler, []) is a NOP. +compiler_DEFAULT=$CC + +# save warnings/boilerplate of simple test code +ac_outfile=conftest.$ac_objext +echo "$lt_simple_compile_test_code" >conftest.$ac_ext +eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err +_lt_compiler_boilerplate=`cat conftest.err` +$RM conftest* + +ac_outfile=conftest.$ac_objext +echo "$lt_simple_link_test_code" >conftest.$ac_ext +eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err +_lt_linker_boilerplate=`cat conftest.err` +$RM -r conftest* + + +## CAVEAT EMPTOR: +## There is no encapsulation within the following macros, do not change +## the running order or otherwise move them around unless you know exactly +## what you are doing... +if test -n "$compiler"; then + +lt_prog_compiler_no_builtin_flag= + +if test "$GCC" = yes; then + case $cc_basename in + nvcc*) + lt_prog_compiler_no_builtin_flag=' -Xcompiler -fno-builtin' ;; + *) + lt_prog_compiler_no_builtin_flag=' -fno-builtin' ;; + esac + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -fno-rtti -fno-exceptions" >&5 +$as_echo_n "checking if $compiler supports -fno-rtti -fno-exceptions... " >&6; } +if ${lt_cv_prog_compiler_rtti_exceptions+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler_rtti_exceptions=no + ac_outfile=conftest.$ac_objext + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + lt_compiler_flag="-fno-rtti -fno-exceptions" + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + # The option is referenced via a variable to avoid confusing sed. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) + (eval "$lt_compile" 2>conftest.err) + ac_status=$? + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + if (exit $ac_status) && test -s "$ac_outfile"; then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings other than the usual output. + $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then + lt_cv_prog_compiler_rtti_exceptions=yes + fi + fi + $RM conftest* + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_rtti_exceptions" >&5 +$as_echo "$lt_cv_prog_compiler_rtti_exceptions" >&6; } + +if test x"$lt_cv_prog_compiler_rtti_exceptions" = xyes; then + lt_prog_compiler_no_builtin_flag="$lt_prog_compiler_no_builtin_flag -fno-rtti -fno-exceptions" +else + : +fi + +fi + + + + + + + lt_prog_compiler_wl= +lt_prog_compiler_pic= +lt_prog_compiler_static= + + + if test "$GCC" = yes; then + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_static='-static' + + case $host_os in + aix*) + # All AIX code is PIC. + if test "$host_cpu" = ia64; then + # AIX 5 now supports IA64 processor + lt_prog_compiler_static='-Bstatic' + fi + ;; + + amigaos*) + case $host_cpu in + powerpc) + # see comment about AmigaOS4 .so support + lt_prog_compiler_pic='-fPIC' + ;; + m68k) + # FIXME: we need at least 68020 code to build shared libraries, but + # adding the `-m68020' flag to GCC prevents building anything better, + # like `-m68040'. + lt_prog_compiler_pic='-m68020 -resident32 -malways-restore-a4' + ;; + esac + ;; + + beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) + # PIC is the default for these OSes. + ;; + + mingw* | cygwin* | pw32* | os2* | cegcc*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + # Although the cygwin gcc ignores -fPIC, still need this for old-style + # (--disable-auto-import) libraries + lt_prog_compiler_pic='-DDLL_EXPORT' + ;; + + darwin* | rhapsody*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + lt_prog_compiler_pic='-fno-common' + ;; + + haiku*) + # PIC is the default for Haiku. + # The "-static" flag exists, but is broken. + lt_prog_compiler_static= + ;; + + hpux*) + # PIC is the default for 64-bit PA HP-UX, but not for 32-bit + # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag + # sets the default TLS model and affects inlining. + case $host_cpu in + hppa*64*) + # +Z the default + ;; + *) + lt_prog_compiler_pic='-fPIC' + ;; + esac + ;; + + interix[3-9]*) + # Interix 3.x gcc -fpic/-fPIC options generate broken code. + # Instead, we relocate shared libraries at runtime. + ;; + + msdosdjgpp*) + # Just because we use GCC doesn't mean we suddenly get shared libraries + # on systems that don't support them. + lt_prog_compiler_can_build_shared=no + enable_shared=no + ;; + + *nto* | *qnx*) + # QNX uses GNU C++, but need to define -shared option too, otherwise + # it will coredump. + lt_prog_compiler_pic='-fPIC -shared' + ;; + + sysv4*MP*) + if test -d /usr/nec; then + lt_prog_compiler_pic=-Kconform_pic + fi + ;; + + *) + lt_prog_compiler_pic='-fPIC' + ;; + esac + + case $cc_basename in + nvcc*) # Cuda Compiler Driver 2.2 + lt_prog_compiler_wl='-Xlinker ' + lt_prog_compiler_pic='-Xcompiler -fPIC' + ;; + esac + else + # PORTME Check for flag to pass linker flags through the system compiler. + case $host_os in + aix*) + lt_prog_compiler_wl='-Wl,' + if test "$host_cpu" = ia64; then + # AIX 5 now supports IA64 processor + lt_prog_compiler_static='-Bstatic' + else + lt_prog_compiler_static='-bnso -bI:/lib/syscalls.exp' + fi + ;; + + mingw* | cygwin* | pw32* | os2* | cegcc*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + lt_prog_compiler_pic='-DDLL_EXPORT' + ;; + + hpux9* | hpux10* | hpux11*) + lt_prog_compiler_wl='-Wl,' + # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but + # not for PA HP-UX. + case $host_cpu in + hppa*64*|ia64*) + # +Z the default + ;; + *) + lt_prog_compiler_pic='+Z' + ;; + esac + # Is there a better lt_prog_compiler_static that works with the bundled CC? + lt_prog_compiler_static='${wl}-a ${wl}archive' + ;; + + irix5* | irix6* | nonstopux*) + lt_prog_compiler_wl='-Wl,' + # PIC (with -KPIC) is the default. + lt_prog_compiler_static='-non_shared' + ;; + + linux* | k*bsd*-gnu | kopensolaris*-gnu) + case $cc_basename in + # old Intel for x86_64 which still supported -KPIC. + ecc*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-static' + ;; + # icc used to be incompatible with GCC. + # ICC 10 doesn't accept -KPIC any more. + icc* | ifort*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-fPIC' + lt_prog_compiler_static='-static' + ;; + # Lahey Fortran 8.1. + lf95*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='--shared' + lt_prog_compiler_static='--static' + ;; + nagfor*) + # NAG Fortran compiler + lt_prog_compiler_wl='-Wl,-Wl,,' + lt_prog_compiler_pic='-PIC' + lt_prog_compiler_static='-Bstatic' + ;; + pgcc* | pgf77* | pgf90* | pgf95* | pgfortran*) + # Portland Group compilers (*not* the Pentium gcc compiler, + # which looks to be a dead project) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-fpic' + lt_prog_compiler_static='-Bstatic' + ;; + ccc*) + lt_prog_compiler_wl='-Wl,' + # All Alpha code is PIC. + lt_prog_compiler_static='-non_shared' + ;; + xl* | bgxl* | bgf* | mpixl*) + # IBM XL C 8.0/Fortran 10.1, 11.1 on PPC and BlueGene + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-qpic' + lt_prog_compiler_static='-qstaticlink' + ;; + *) + case `$CC -V 2>&1 | sed 5q` in + *Sun\ F* | *Sun*Fortran*) + # Sun Fortran 8.3 passes all unrecognized flags to the linker + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-Bstatic' + lt_prog_compiler_wl='' + ;; + *Sun\ C*) + # Sun C 5.9 + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-Bstatic' + lt_prog_compiler_wl='-Wl,' + ;; + esac + ;; + esac + ;; + + newsos6) + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-Bstatic' + ;; + + *nto* | *qnx*) + # QNX uses GNU C++, but need to define -shared option too, otherwise + # it will coredump. + lt_prog_compiler_pic='-fPIC -shared' + ;; + + osf3* | osf4* | osf5*) + lt_prog_compiler_wl='-Wl,' + # All OSF/1 code is PIC. + lt_prog_compiler_static='-non_shared' + ;; + + rdos*) + lt_prog_compiler_static='-non_shared' + ;; + + solaris*) + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-Bstatic' + case $cc_basename in + f77* | f90* | f95* | sunf77* | sunf90* | sunf95*) + lt_prog_compiler_wl='-Qoption ld ';; + *) + lt_prog_compiler_wl='-Wl,';; + esac + ;; + + sunos4*) + lt_prog_compiler_wl='-Qoption ld ' + lt_prog_compiler_pic='-PIC' + lt_prog_compiler_static='-Bstatic' + ;; + + sysv4 | sysv4.2uw2* | sysv4.3*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-Bstatic' + ;; + + sysv4*MP*) + if test -d /usr/nec ;then + lt_prog_compiler_pic='-Kconform_pic' + lt_prog_compiler_static='-Bstatic' + fi + ;; + + sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-Bstatic' + ;; + + unicos*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_can_build_shared=no + ;; + + uts4*) + lt_prog_compiler_pic='-pic' + lt_prog_compiler_static='-Bstatic' + ;; + + *) + lt_prog_compiler_can_build_shared=no + ;; + esac + fi + +case $host_os in + # For platforms which do not support PIC, -DPIC is meaningless: + *djgpp*) + lt_prog_compiler_pic= + ;; + *) + lt_prog_compiler_pic="$lt_prog_compiler_pic -DPIC" + ;; +esac + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $compiler option to produce PIC" >&5 +$as_echo_n "checking for $compiler option to produce PIC... " >&6; } +if ${lt_cv_prog_compiler_pic+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler_pic=$lt_prog_compiler_pic +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_pic" >&5 +$as_echo "$lt_cv_prog_compiler_pic" >&6; } +lt_prog_compiler_pic=$lt_cv_prog_compiler_pic + +# +# Check to make sure the PIC flag actually works. +# +if test -n "$lt_prog_compiler_pic"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler PIC flag $lt_prog_compiler_pic works" >&5 +$as_echo_n "checking if $compiler PIC flag $lt_prog_compiler_pic works... " >&6; } +if ${lt_cv_prog_compiler_pic_works+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler_pic_works=no + ac_outfile=conftest.$ac_objext + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + lt_compiler_flag="$lt_prog_compiler_pic -DPIC" + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + # The option is referenced via a variable to avoid confusing sed. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) + (eval "$lt_compile" 2>conftest.err) + ac_status=$? + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + if (exit $ac_status) && test -s "$ac_outfile"; then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings other than the usual output. + $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then + lt_cv_prog_compiler_pic_works=yes + fi + fi + $RM conftest* + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_pic_works" >&5 +$as_echo "$lt_cv_prog_compiler_pic_works" >&6; } + +if test x"$lt_cv_prog_compiler_pic_works" = xyes; then + case $lt_prog_compiler_pic in + "" | " "*) ;; + *) lt_prog_compiler_pic=" $lt_prog_compiler_pic" ;; + esac +else + lt_prog_compiler_pic= + lt_prog_compiler_can_build_shared=no +fi + +fi + + + + + + + + + + + +# +# Check to make sure the static flag actually works. +# +wl=$lt_prog_compiler_wl eval lt_tmp_static_flag=\"$lt_prog_compiler_static\" +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler static flag $lt_tmp_static_flag works" >&5 +$as_echo_n "checking if $compiler static flag $lt_tmp_static_flag works... " >&6; } +if ${lt_cv_prog_compiler_static_works+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler_static_works=no + save_LDFLAGS="$LDFLAGS" + LDFLAGS="$LDFLAGS $lt_tmp_static_flag" + echo "$lt_simple_link_test_code" > conftest.$ac_ext + if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then + # The linker can only warn and ignore the option if not recognized + # So say no if there are warnings + if test -s conftest.err; then + # Append any errors to the config.log. + cat conftest.err 1>&5 + $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if diff conftest.exp conftest.er2 >/dev/null; then + lt_cv_prog_compiler_static_works=yes + fi + else + lt_cv_prog_compiler_static_works=yes + fi + fi + $RM -r conftest* + LDFLAGS="$save_LDFLAGS" + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_static_works" >&5 +$as_echo "$lt_cv_prog_compiler_static_works" >&6; } + +if test x"$lt_cv_prog_compiler_static_works" = xyes; then + : +else + lt_prog_compiler_static= +fi + + + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5 +$as_echo_n "checking if $compiler supports -c -o file.$ac_objext... " >&6; } +if ${lt_cv_prog_compiler_c_o+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler_c_o=no + $RM -r conftest 2>/dev/null + mkdir conftest + cd conftest + mkdir out + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + + lt_compiler_flag="-o out/conftest2.$ac_objext" + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) + (eval "$lt_compile" 2>out/conftest.err) + ac_status=$? + cat out/conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + if (exit $ac_status) && test -s out/conftest2.$ac_objext + then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings + $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp + $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 + if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then + lt_cv_prog_compiler_c_o=yes + fi + fi + chmod u+w . 2>&5 + $RM conftest* + # SGI C++ compiler will create directory out/ii_files/ for + # template instantiation + test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files + $RM out/* && rmdir out + cd .. + $RM -r conftest + $RM conftest* + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o" >&5 +$as_echo "$lt_cv_prog_compiler_c_o" >&6; } + + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5 +$as_echo_n "checking if $compiler supports -c -o file.$ac_objext... " >&6; } +if ${lt_cv_prog_compiler_c_o+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler_c_o=no + $RM -r conftest 2>/dev/null + mkdir conftest + cd conftest + mkdir out + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + + lt_compiler_flag="-o out/conftest2.$ac_objext" + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) + (eval "$lt_compile" 2>out/conftest.err) + ac_status=$? + cat out/conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + if (exit $ac_status) && test -s out/conftest2.$ac_objext + then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings + $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp + $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 + if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then + lt_cv_prog_compiler_c_o=yes + fi + fi + chmod u+w . 2>&5 + $RM conftest* + # SGI C++ compiler will create directory out/ii_files/ for + # template instantiation + test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files + $RM out/* && rmdir out + cd .. + $RM -r conftest + $RM conftest* + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o" >&5 +$as_echo "$lt_cv_prog_compiler_c_o" >&6; } + + + + +hard_links="nottested" +if test "$lt_cv_prog_compiler_c_o" = no && test "$need_locks" != no; then + # do not overwrite the value of need_locks provided by the user + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if we can lock with hard links" >&5 +$as_echo_n "checking if we can lock with hard links... " >&6; } + hard_links=yes + $RM conftest* + ln conftest.a conftest.b 2>/dev/null && hard_links=no + touch conftest.a + ln conftest.a conftest.b 2>&5 || hard_links=no + ln conftest.a conftest.b 2>/dev/null && hard_links=no + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $hard_links" >&5 +$as_echo "$hard_links" >&6; } + if test "$hard_links" = no; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&5 +$as_echo "$as_me: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&2;} + need_locks=warn + fi +else + need_locks=no +fi + + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the $compiler linker ($LD) supports shared libraries" >&5 +$as_echo_n "checking whether the $compiler linker ($LD) supports shared libraries... " >&6; } + + runpath_var= + allow_undefined_flag= + always_export_symbols=no + archive_cmds= + archive_expsym_cmds= + compiler_needs_object=no + enable_shared_with_static_runtimes=no + export_dynamic_flag_spec= + export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' + hardcode_automatic=no + hardcode_direct=no + hardcode_direct_absolute=no + hardcode_libdir_flag_spec= + hardcode_libdir_flag_spec_ld= + hardcode_libdir_separator= + hardcode_minus_L=no + hardcode_shlibpath_var=unsupported + inherit_rpath=no + link_all_deplibs=unknown + module_cmds= + module_expsym_cmds= + old_archive_from_new_cmds= + old_archive_from_expsyms_cmds= + thread_safe_flag_spec= + whole_archive_flag_spec= + # include_expsyms should be a list of space-separated symbols to be *always* + # included in the symbol list + include_expsyms= + # exclude_expsyms can be an extended regexp of symbols to exclude + # it will be wrapped by ` (' and `)$', so one must not match beginning or + # end of line. Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc', + # as well as any symbol that contains `d'. + exclude_expsyms='_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*' + # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out + # platforms (ab)use it in PIC code, but their linkers get confused if + # the symbol is explicitly referenced. Since portable code cannot + # rely on this symbol name, it's probably fine to never include it in + # preloaded symbol tables. + # Exclude shared library initialization/finalization symbols. + extract_expsyms_cmds= + + case $host_os in + cygwin* | mingw* | pw32* | cegcc*) + # FIXME: the MSVC++ port hasn't been tested in a loooong time + # When not using gcc, we currently assume that we are using + # Microsoft Visual C++. + if test "$GCC" != yes; then + with_gnu_ld=no + fi + ;; + interix*) + # we just hope/assume this is gcc and not c89 (= MSVC++) + with_gnu_ld=yes + ;; + openbsd*) + with_gnu_ld=no + ;; + esac + + ld_shlibs=yes + + # On some targets, GNU ld is compatible enough with the native linker + # that we're better off using the native interface for both. + lt_use_gnu_ld_interface=no + if test "$with_gnu_ld" = yes; then + case $host_os in + aix*) + # The AIX port of GNU ld has always aspired to compatibility + # with the native linker. However, as the warning in the GNU ld + # block says, versions before 2.19.5* couldn't really create working + # shared libraries, regardless of the interface used. + case `$LD -v 2>&1` in + *\ \(GNU\ Binutils\)\ 2.19.5*) ;; + *\ \(GNU\ Binutils\)\ 2.[2-9]*) ;; + *\ \(GNU\ Binutils\)\ [3-9]*) ;; + *) + lt_use_gnu_ld_interface=yes + ;; + esac + ;; + *) + lt_use_gnu_ld_interface=yes + ;; + esac + fi + + if test "$lt_use_gnu_ld_interface" = yes; then + # If archive_cmds runs LD, not CC, wlarc should be empty + wlarc='${wl}' + + # Set some defaults for GNU ld with shared library support. These + # are reset later if shared libraries are not supported. Putting them + # here allows them to be overridden if necessary. + runpath_var=LD_RUN_PATH + hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' + export_dynamic_flag_spec='${wl}--export-dynamic' + # ancient GNU ld didn't support --whole-archive et. al. + if $LD --help 2>&1 | $GREP 'no-whole-archive' > /dev/null; then + whole_archive_flag_spec="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' + else + whole_archive_flag_spec= + fi + supports_anon_versioning=no + case `$LD -v 2>&1` in + *GNU\ gold*) supports_anon_versioning=yes ;; + *\ [01].* | *\ 2.[0-9].* | *\ 2.10.*) ;; # catch versions < 2.11 + *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ... + *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ... + *\ 2.11.*) ;; # other 2.11 versions + *) supports_anon_versioning=yes ;; + esac + + # See if GNU ld supports shared libraries. + case $host_os in + aix[3-9]*) + # On AIX/PPC, the GNU linker is very broken + if test "$host_cpu" != ia64; then + ld_shlibs=no + cat <<_LT_EOF 1>&2 + +*** Warning: the GNU linker, at least up to release 2.19, is reported +*** to be unable to reliably create shared libraries on AIX. +*** Therefore, libtool is disabling shared libraries support. If you +*** really care for shared libraries, you may want to install binutils +*** 2.20 or above, or modify your PATH so that a non-GNU linker is found. +*** You will then need to restart the configuration process. + +_LT_EOF + fi + ;; + + amigaos*) + case $host_cpu in + powerpc) + # see comment about AmigaOS4 .so support + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + archive_expsym_cmds='' + ;; + m68k) + archive_cmds='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' + hardcode_libdir_flag_spec='-L$libdir' + hardcode_minus_L=yes + ;; + esac + ;; + + beos*) + if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + allow_undefined_flag=unsupported + # Joseph Beckenbach says some releases of gcc + # support --undefined. This deserves some investigation. FIXME + archive_cmds='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + else + ld_shlibs=no + fi + ;; + + cygwin* | mingw* | pw32* | cegcc*) + # _LT_TAGVAR(hardcode_libdir_flag_spec, ) is actually meaningless, + # as there is no search path for DLLs. + hardcode_libdir_flag_spec='-L$libdir' + export_dynamic_flag_spec='${wl}--export-all-symbols' + allow_undefined_flag=unsupported + always_export_symbols=no + enable_shared_with_static_runtimes=yes + export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS][ ]/s/.*[ ]\([^ ]*\)/\1 DATA/;s/^.*[ ]__nm__\([^ ]*\)[ ][^ ]*/\1 DATA/;/^I[ ]/d;/^[AITW][ ]/s/.* //'\'' | sort | uniq > $export_symbols' + exclude_expsyms='[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname' + + if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + # If the export-symbols file already is a .def file (1st line + # is EXPORTS), use it as is; otherwise, prepend... + archive_expsym_cmds='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then + cp $export_symbols $output_objdir/$soname.def; + else + echo EXPORTS > $output_objdir/$soname.def; + cat $export_symbols >> $output_objdir/$soname.def; + fi~ + $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + else + ld_shlibs=no + fi + ;; + + haiku*) + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + link_all_deplibs=yes + ;; + + interix[3-9]*) + hardcode_direct=no + hardcode_shlibpath_var=no + hardcode_libdir_flag_spec='${wl}-rpath,$libdir' + export_dynamic_flag_spec='${wl}-E' + # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. + # Instead, shared libraries are loaded at an image base (0x10000000 by + # default) and relocated if they conflict, which is a slow very memory + # consuming and fragmenting process. To avoid this, we pick a random, + # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link + # time. Moving up from 0x10000000 also allows more sbrk(2) space. + archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + archive_expsym_cmds='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + ;; + + gnu* | linux* | tpf* | k*bsd*-gnu | kopensolaris*-gnu) + tmp_diet=no + if test "$host_os" = linux-dietlibc; then + case $cc_basename in + diet\ *) tmp_diet=yes;; # linux-dietlibc with static linking (!diet-dyn) + esac + fi + if $LD --help 2>&1 | $EGREP ': supported targets:.* elf' > /dev/null \ + && test "$tmp_diet" = no + then + tmp_addflag=' $pic_flag' + tmp_sharedflag='-shared' + case $cc_basename,$host_cpu in + pgcc*) # Portland Group C compiler + whole_archive_flag_spec='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' + tmp_addflag=' $pic_flag' + ;; + pgf77* | pgf90* | pgf95* | pgfortran*) + # Portland Group f77 and f90 compilers + whole_archive_flag_spec='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' + tmp_addflag=' $pic_flag -Mnomain' ;; + ecc*,ia64* | icc*,ia64*) # Intel C compiler on ia64 + tmp_addflag=' -i_dynamic' ;; + efc*,ia64* | ifort*,ia64*) # Intel Fortran compiler on ia64 + tmp_addflag=' -i_dynamic -nofor_main' ;; + ifc* | ifort*) # Intel Fortran compiler + tmp_addflag=' -nofor_main' ;; + lf95*) # Lahey Fortran 8.1 + whole_archive_flag_spec= + tmp_sharedflag='--shared' ;; + xl[cC]* | bgxl[cC]* | mpixl[cC]*) # IBM XL C 8.0 on PPC (deal with xlf below) + tmp_sharedflag='-qmkshrobj' + tmp_addflag= ;; + nvcc*) # Cuda Compiler Driver 2.2 + whole_archive_flag_spec='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' + compiler_needs_object=yes + ;; + esac + case `$CC -V 2>&1 | sed 5q` in + *Sun\ C*) # Sun C 5.9 + whole_archive_flag_spec='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' + compiler_needs_object=yes + tmp_sharedflag='-G' ;; + *Sun\ F*) # Sun Fortran 8.3 + tmp_sharedflag='-G' ;; + esac + archive_cmds='$CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + + if test "x$supports_anon_versioning" = xyes; then + archive_expsym_cmds='echo "{ global:" > $output_objdir/$libname.ver~ + cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ + echo "local: *; };" >> $output_objdir/$libname.ver~ + $CC '"$tmp_sharedflag""$tmp_addflag"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib' + fi + + case $cc_basename in + xlf* | bgf* | bgxlf* | mpixlf*) + # IBM XL Fortran 10.1 on PPC cannot create shared libs itself + whole_archive_flag_spec='--whole-archive$convenience --no-whole-archive' + hardcode_libdir_flag_spec= + hardcode_libdir_flag_spec_ld='-rpath $libdir' + archive_cmds='$LD -shared $libobjs $deplibs $linker_flags -soname $soname -o $lib' + if test "x$supports_anon_versioning" = xyes; then + archive_expsym_cmds='echo "{ global:" > $output_objdir/$libname.ver~ + cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ + echo "local: *; };" >> $output_objdir/$libname.ver~ + $LD -shared $libobjs $deplibs $linker_flags -soname $soname -version-script $output_objdir/$libname.ver -o $lib' + fi + ;; + esac + else + ld_shlibs=no + fi + ;; + + netbsd*) + if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then + archive_cmds='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib' + wlarc= + else + archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + fi + ;; + + solaris*) + if $LD -v 2>&1 | $GREP 'BFD 2\.8' > /dev/null; then + ld_shlibs=no + cat <<_LT_EOF 1>&2 + +*** Warning: The releases 2.8.* of the GNU linker cannot reliably +*** create shared libraries on Solaris systems. Therefore, libtool +*** is disabling shared libraries support. We urge you to upgrade GNU +*** binutils to release 2.9.1 or newer. Another option is to modify +*** your PATH or compiler configuration so that the native linker is +*** used, and then restart. + +_LT_EOF + elif $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + else + ld_shlibs=no + fi + ;; + + sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX*) + case `$LD -v 2>&1` in + *\ [01].* | *\ 2.[0-9].* | *\ 2.1[0-5].*) + ld_shlibs=no + cat <<_LT_EOF 1>&2 + +*** Warning: Releases of the GNU linker prior to 2.16.91.0.3 can not +*** reliably create shared libraries on SCO systems. Therefore, libtool +*** is disabling shared libraries support. We urge you to upgrade GNU +*** binutils to release 2.16.91.0.3 or newer. Another option is to modify +*** your PATH or compiler configuration so that the native linker is +*** used, and then restart. + +_LT_EOF + ;; + *) + # For security reasons, it is highly recommended that you always + # use absolute paths for naming shared libraries, and exclude the + # DT_RUNPATH tag from executables and libraries. But doing so + # requires that you compile everything twice, which is a pain. + if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + else + ld_shlibs=no + fi + ;; + esac + ;; + + sunos4*) + archive_cmds='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags' + wlarc= + hardcode_direct=yes + hardcode_shlibpath_var=no + ;; + + *) + if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + else + ld_shlibs=no + fi + ;; + esac + + if test "$ld_shlibs" = no; then + runpath_var= + hardcode_libdir_flag_spec= + export_dynamic_flag_spec= + whole_archive_flag_spec= + fi + else + # PORTME fill in a description of your system's linker (not GNU ld) + case $host_os in + aix3*) + allow_undefined_flag=unsupported + always_export_symbols=yes + archive_expsym_cmds='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname' + # Note: this linker hardcodes the directories in LIBPATH if there + # are no directories specified by -L. + hardcode_minus_L=yes + if test "$GCC" = yes && test -z "$lt_prog_compiler_static"; then + # Neither direct hardcoding nor static linking is supported with a + # broken collect2. + hardcode_direct=unsupported + fi + ;; + + aix[4-9]*) + if test "$host_cpu" = ia64; then + # On IA64, the linker does run time linking by default, so we don't + # have to do anything special. + aix_use_runtimelinking=no + exp_sym_flag='-Bexport' + no_entry_flag="" + else + # If we're using GNU nm, then we don't want the "-C" option. + # -C means demangle to AIX nm, but means don't demangle with GNU nm + # Also, AIX nm treats weak defined symbols like other global + # defined symbols, whereas GNU nm marks them as "W". + if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then + export_symbols_cmds='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && (substr(\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' + else + export_symbols_cmds='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && (substr(\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' + fi + aix_use_runtimelinking=no + + # Test if we are trying to use run time linking or normal + # AIX style linking. If -brtl is somewhere in LDFLAGS, we + # need to do runtime linking. + case $host_os in aix4.[23]|aix4.[23].*|aix[5-9]*) + for ld_flag in $LDFLAGS; do + if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then + aix_use_runtimelinking=yes + break + fi + done + ;; + esac + + exp_sym_flag='-bexport' + no_entry_flag='-bnoentry' + fi + + # When large executables or shared objects are built, AIX ld can + # have problems creating the table of contents. If linking a library + # or program results in "error TOC overflow" add -mminimal-toc to + # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not + # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. + + archive_cmds='' + hardcode_direct=yes + hardcode_direct_absolute=yes + hardcode_libdir_separator=':' + link_all_deplibs=yes + file_list_spec='${wl}-f,' + + if test "$GCC" = yes; then + case $host_os in aix4.[012]|aix4.[012].*) + # We only want to do this on AIX 4.2 and lower, the check + # below for broken collect2 doesn't work under 4.3+ + collect2name=`${CC} -print-prog-name=collect2` + if test -f "$collect2name" && + strings "$collect2name" | $GREP resolve_lib_name >/dev/null + then + # We have reworked collect2 + : + else + # We have old collect2 + hardcode_direct=unsupported + # It fails to find uninstalled libraries when the uninstalled + # path is not listed in the libpath. Setting hardcode_minus_L + # to unsupported forces relinking + hardcode_minus_L=yes + hardcode_libdir_flag_spec='-L$libdir' + hardcode_libdir_separator= + fi + ;; + esac + shared_flag='-shared' + if test "$aix_use_runtimelinking" = yes; then + shared_flag="$shared_flag "'${wl}-G' + fi + else + # not using gcc + if test "$host_cpu" = ia64; then + # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release + # chokes on -Wl,-G. The following line is correct: + shared_flag='-G' + else + if test "$aix_use_runtimelinking" = yes; then + shared_flag='${wl}-G' + else + shared_flag='${wl}-bM:SRE' + fi + fi + fi + + export_dynamic_flag_spec='${wl}-bexpall' + # It seems that -bexpall does not export symbols beginning with + # underscore (_), so it is better to generate a list of symbols to export. + always_export_symbols=yes + if test "$aix_use_runtimelinking" = yes; then + # Warning - without using the other runtime loading flags (-brtl), + # -berok will link without error, but may produce a broken library. + allow_undefined_flag='-berok' + # Determine the default libpath from the value encoded in an + # empty executable. + if test "${lt_cv_aix_libpath+set}" = set; then + aix_libpath=$lt_cv_aix_libpath +else + if ${lt_cv_aix_libpath_+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + + lt_aix_libpath_sed=' + /Import File Strings/,/^$/ { + /^0/ { + s/^0 *\([^ ]*\) *$/\1/ + p + } + }' + lt_cv_aix_libpath_=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` + # Check for a 64-bit object if we didn't find anything. + if test -z "$lt_cv_aix_libpath_"; then + lt_cv_aix_libpath_=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` + fi +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + if test -z "$lt_cv_aix_libpath_"; then + lt_cv_aix_libpath_="/usr/lib:/lib" + fi + +fi + + aix_libpath=$lt_cv_aix_libpath_ +fi + + hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath" + archive_expsym_cmds='$CC -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then func_echo_all "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag" + else + if test "$host_cpu" = ia64; then + hardcode_libdir_flag_spec='${wl}-R $libdir:/usr/lib:/lib' + allow_undefined_flag="-z nodefs" + archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols" + else + # Determine the default libpath from the value encoded in an + # empty executable. + if test "${lt_cv_aix_libpath+set}" = set; then + aix_libpath=$lt_cv_aix_libpath +else + if ${lt_cv_aix_libpath_+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + + lt_aix_libpath_sed=' + /Import File Strings/,/^$/ { + /^0/ { + s/^0 *\([^ ]*\) *$/\1/ + p + } + }' + lt_cv_aix_libpath_=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` + # Check for a 64-bit object if we didn't find anything. + if test -z "$lt_cv_aix_libpath_"; then + lt_cv_aix_libpath_=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` + fi +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + if test -z "$lt_cv_aix_libpath_"; then + lt_cv_aix_libpath_="/usr/lib:/lib" + fi + +fi + + aix_libpath=$lt_cv_aix_libpath_ +fi + + hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath" + # Warning - without using the other run time loading flags, + # -berok will link without error, but may produce a broken library. + no_undefined_flag=' ${wl}-bernotok' + allow_undefined_flag=' ${wl}-berok' + if test "$with_gnu_ld" = yes; then + # We only use this code for GNU lds that support --whole-archive. + whole_archive_flag_spec='${wl}--whole-archive$convenience ${wl}--no-whole-archive' + else + # Exported symbols can be pulled into shared objects from archives + whole_archive_flag_spec='$convenience' + fi + archive_cmds_need_lc=yes + # This is similar to how AIX traditionally builds its shared libraries. + archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' + fi + fi + ;; + + amigaos*) + case $host_cpu in + powerpc) + # see comment about AmigaOS4 .so support + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + archive_expsym_cmds='' + ;; + m68k) + archive_cmds='$RM $output_objdir/a2ixlibrary.data~$ECHO "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$ECHO "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$ECHO "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$ECHO "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' + hardcode_libdir_flag_spec='-L$libdir' + hardcode_minus_L=yes + ;; + esac + ;; + + bsdi[45]*) + export_dynamic_flag_spec=-rdynamic + ;; + + cygwin* | mingw* | pw32* | cegcc*) + # When not using gcc, we currently assume that we are using + # Microsoft Visual C++. + # hardcode_libdir_flag_spec is actually meaningless, as there is + # no search path for DLLs. + case $cc_basename in + cl*) + # Native MSVC + hardcode_libdir_flag_spec=' ' + allow_undefined_flag=unsupported + always_export_symbols=yes + file_list_spec='@' + # Tell ltmain to make .lib files, not .a files. + libext=lib + # Tell ltmain to make .dll files, not .so files. + shrext_cmds=".dll" + # FIXME: Setting linknames here is a bad hack. + archive_cmds='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-dll~linknames=' + archive_expsym_cmds='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then + sed -n -e 's/\\\\\\\(.*\\\\\\\)/-link\\\ -EXPORT:\\\\\\\1/' -e '1\\\!p' < $export_symbols > $output_objdir/$soname.exp; + else + sed -e 's/\\\\\\\(.*\\\\\\\)/-link\\\ -EXPORT:\\\\\\\1/' < $export_symbols > $output_objdir/$soname.exp; + fi~ + $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~ + linknames=' + # The linker will not automatically build a static lib if we build a DLL. + # _LT_TAGVAR(old_archive_from_new_cmds, )='true' + enable_shared_with_static_runtimes=yes + export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS][ ]/s/.*[ ]\([^ ]*\)/\1,DATA/'\'' | $SED -e '\''/^[AITW][ ]/s/.*[ ]//'\'' | sort | uniq > $export_symbols' + # Don't use ranlib + old_postinstall_cmds='chmod 644 $oldlib' + postlink_cmds='lt_outputfile="@OUTPUT@"~ + lt_tool_outputfile="@TOOL_OUTPUT@"~ + case $lt_outputfile in + *.exe|*.EXE) ;; + *) + lt_outputfile="$lt_outputfile.exe" + lt_tool_outputfile="$lt_tool_outputfile.exe" + ;; + esac~ + if test "$MANIFEST_TOOL" != ":" && test -f "$lt_outputfile.manifest"; then + $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1; + $RM "$lt_outputfile.manifest"; + fi' + ;; + *) + # Assume MSVC wrapper + hardcode_libdir_flag_spec=' ' + allow_undefined_flag=unsupported + # Tell ltmain to make .lib files, not .a files. + libext=lib + # Tell ltmain to make .dll files, not .so files. + shrext_cmds=".dll" + # FIXME: Setting linknames here is a bad hack. + archive_cmds='$CC -o $lib $libobjs $compiler_flags `func_echo_all "$deplibs" | $SED '\''s/ -lc$//'\''` -link -dll~linknames=' + # The linker will automatically build a .lib file if we build a DLL. + old_archive_from_new_cmds='true' + # FIXME: Should let the user specify the lib program. + old_archive_cmds='lib -OUT:$oldlib$oldobjs$old_deplibs' + enable_shared_with_static_runtimes=yes + ;; + esac + ;; + + darwin* | rhapsody*) + + + archive_cmds_need_lc=no + hardcode_direct=no + hardcode_automatic=yes + hardcode_shlibpath_var=unsupported + if test "$lt_cv_ld_force_load" = "yes"; then + whole_archive_flag_spec='`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience ${wl}-force_load,$conv\"; done; func_echo_all \"$new_convenience\"`' + else + whole_archive_flag_spec='' + fi + link_all_deplibs=yes + allow_undefined_flag="$_lt_dar_allow_undefined" + case $cc_basename in + ifort*) _lt_dar_can_shared=yes ;; + *) _lt_dar_can_shared=$GCC ;; + esac + if test "$_lt_dar_can_shared" = "yes"; then + output_verbose_link_cmd=func_echo_all + archive_cmds="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod${_lt_dsymutil}" + module_cmds="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dsymutil}" + archive_expsym_cmds="sed 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring ${_lt_dar_single_mod}${_lt_dar_export_syms}${_lt_dsymutil}" + module_expsym_cmds="sed -e 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dar_export_syms}${_lt_dsymutil}" + + else + ld_shlibs=no + fi + + ;; + + dgux*) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_libdir_flag_spec='-L$libdir' + hardcode_shlibpath_var=no + ;; + + freebsd1*) + ld_shlibs=no + ;; + + # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor + # support. Future versions do this automatically, but an explicit c++rt0.o + # does not break anything, and helps significantly (at the cost of a little + # extra space). + freebsd2.2*) + archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o' + hardcode_libdir_flag_spec='-R$libdir' + hardcode_direct=yes + hardcode_shlibpath_var=no + ;; + + # Unfortunately, older versions of FreeBSD 2 do not have this feature. + freebsd2*) + archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' + hardcode_direct=yes + hardcode_minus_L=yes + hardcode_shlibpath_var=no + ;; + + # FreeBSD 3 and greater uses gcc -shared to do shared libraries. + freebsd* | dragonfly*) + archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + hardcode_libdir_flag_spec='-R$libdir' + hardcode_direct=yes + hardcode_shlibpath_var=no + ;; + + hpux9*) + if test "$GCC" = yes; then + archive_cmds='$RM $output_objdir/$soname~$CC -shared $pic_flag ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' + else + archive_cmds='$RM $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' + fi + hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' + hardcode_libdir_separator=: + hardcode_direct=yes + + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + hardcode_minus_L=yes + export_dynamic_flag_spec='${wl}-E' + ;; + + hpux10*) + if test "$GCC" = yes && test "$with_gnu_ld" = no; then + archive_cmds='$CC -shared $pic_flag ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' + else + archive_cmds='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' + fi + if test "$with_gnu_ld" = no; then + hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' + hardcode_libdir_flag_spec_ld='+b $libdir' + hardcode_libdir_separator=: + hardcode_direct=yes + hardcode_direct_absolute=yes + export_dynamic_flag_spec='${wl}-E' + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + hardcode_minus_L=yes + fi + ;; + + hpux11*) + if test "$GCC" = yes && test "$with_gnu_ld" = no; then + case $host_cpu in + hppa*64*) + archive_cmds='$CC -shared ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + ia64*) + archive_cmds='$CC -shared $pic_flag ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + archive_cmds='$CC -shared $pic_flag ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + else + case $host_cpu in + hppa*64*) + archive_cmds='$CC -b ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + ia64*) + archive_cmds='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + + # Older versions of the 11.00 compiler do not understand -b yet + # (HP92453-01 A.11.01.20 doesn't, HP92453-01 B.11.X.35175-35176.GP does) + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $CC understands -b" >&5 +$as_echo_n "checking if $CC understands -b... " >&6; } +if ${lt_cv_prog_compiler__b+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler__b=no + save_LDFLAGS="$LDFLAGS" + LDFLAGS="$LDFLAGS -b" + echo "$lt_simple_link_test_code" > conftest.$ac_ext + if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then + # The linker can only warn and ignore the option if not recognized + # So say no if there are warnings + if test -s conftest.err; then + # Append any errors to the config.log. + cat conftest.err 1>&5 + $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if diff conftest.exp conftest.er2 >/dev/null; then + lt_cv_prog_compiler__b=yes + fi + else + lt_cv_prog_compiler__b=yes + fi + fi + $RM -r conftest* + LDFLAGS="$save_LDFLAGS" + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler__b" >&5 +$as_echo "$lt_cv_prog_compiler__b" >&6; } + +if test x"$lt_cv_prog_compiler__b" = xyes; then + archive_cmds='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' +else + archive_cmds='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' +fi + + ;; + esac + fi + if test "$with_gnu_ld" = no; then + hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' + hardcode_libdir_separator=: + + case $host_cpu in + hppa*64*|ia64*) + hardcode_direct=no + hardcode_shlibpath_var=no + ;; + *) + hardcode_direct=yes + hardcode_direct_absolute=yes + export_dynamic_flag_spec='${wl}-E' + + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + hardcode_minus_L=yes + ;; + esac + fi + ;; + + irix5* | irix6* | nonstopux*) + if test "$GCC" = yes; then + archive_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + # Try to use the -exported_symbol ld option, if it does not + # work, assume that -exports_file does not work either and + # implicitly export all symbols. + # This should be the same for all languages, so no per-tag cache variable. + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the $host_os linker accepts -exported_symbol" >&5 +$as_echo_n "checking whether the $host_os linker accepts -exported_symbol... " >&6; } +if ${lt_cv_irix_exported_symbol+:} false; then : + $as_echo_n "(cached) " >&6 +else + save_LDFLAGS="$LDFLAGS" + LDFLAGS="$LDFLAGS -shared ${wl}-exported_symbol ${wl}foo ${wl}-update_registry ${wl}/dev/null" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +int foo (void) { return 0; } +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + lt_cv_irix_exported_symbol=yes +else + lt_cv_irix_exported_symbol=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + LDFLAGS="$save_LDFLAGS" +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_irix_exported_symbol" >&5 +$as_echo "$lt_cv_irix_exported_symbol" >&6; } + if test "$lt_cv_irix_exported_symbol" = yes; then + archive_expsym_cmds='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations ${wl}-exports_file ${wl}$export_symbols -o $lib' + fi + else + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' + archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -exports_file $export_symbols -o $lib' + fi + archive_cmds_need_lc='no' + hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' + hardcode_libdir_separator=: + inherit_rpath=yes + link_all_deplibs=yes + ;; + + netbsd*) + if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then + archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out + else + archive_cmds='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF + fi + hardcode_libdir_flag_spec='-R$libdir' + hardcode_direct=yes + hardcode_shlibpath_var=no + ;; + + newsos6) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_direct=yes + hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' + hardcode_libdir_separator=: + hardcode_shlibpath_var=no + ;; + + *nto* | *qnx*) + ;; + + openbsd*) + if test -f /usr/libexec/ld.so; then + hardcode_direct=yes + hardcode_shlibpath_var=no + hardcode_direct_absolute=yes + if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags ${wl}-retain-symbols-file,$export_symbols' + hardcode_libdir_flag_spec='${wl}-rpath,$libdir' + export_dynamic_flag_spec='${wl}-E' + else + case $host_os in + openbsd[01].* | openbsd2.[0-7] | openbsd2.[0-7].*) + archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' + hardcode_libdir_flag_spec='-R$libdir' + ;; + *) + archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + hardcode_libdir_flag_spec='${wl}-rpath,$libdir' + ;; + esac + fi + else + ld_shlibs=no + fi + ;; + + os2*) + hardcode_libdir_flag_spec='-L$libdir' + hardcode_minus_L=yes + allow_undefined_flag=unsupported + archive_cmds='$ECHO "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~echo DATA >> $output_objdir/$libname.def~echo " SINGLE NONSHARED" >> $output_objdir/$libname.def~echo EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def' + old_archive_from_new_cmds='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def' + ;; + + osf3*) + if test "$GCC" = yes; then + allow_undefined_flag=' ${wl}-expect_unresolved ${wl}\*' + archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + else + allow_undefined_flag=' -expect_unresolved \*' + archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' + fi + archive_cmds_need_lc='no' + hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' + hardcode_libdir_separator=: + ;; + + osf4* | osf5*) # as osf3* with the addition of -msym flag + if test "$GCC" = yes; then + allow_undefined_flag=' ${wl}-expect_unresolved ${wl}\*' + archive_cmds='$CC -shared${allow_undefined_flag} $pic_flag $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' + else + allow_undefined_flag=' -expect_unresolved \*' + archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' + archive_expsym_cmds='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; printf "%s\\n" "-hidden">> $lib.exp~ + $CC -shared${allow_undefined_flag} ${wl}-input ${wl}$lib.exp $compiler_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib~$RM $lib.exp' + + # Both c and cxx compiler support -rpath directly + hardcode_libdir_flag_spec='-rpath $libdir' + fi + archive_cmds_need_lc='no' + hardcode_libdir_separator=: + ;; + + solaris*) + no_undefined_flag=' -z defs' + if test "$GCC" = yes; then + wlarc='${wl}' + archive_cmds='$CC -shared $pic_flag ${wl}-z ${wl}text ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $CC -shared $pic_flag ${wl}-z ${wl}text ${wl}-M ${wl}$lib.exp ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' + else + case `$CC -V 2>&1` in + *"Compilers 5.0"*) + wlarc='' + archive_cmds='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags' + archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$RM $lib.exp' + ;; + *) + wlarc='${wl}' + archive_cmds='$CC -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $CC -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $compiler_flags~$RM $lib.exp' + ;; + esac + fi + hardcode_libdir_flag_spec='-R$libdir' + hardcode_shlibpath_var=no + case $host_os in + solaris2.[0-5] | solaris2.[0-5].*) ;; + *) + # The compiler driver will combine and reorder linker options, + # but understands `-z linker_flag'. GCC discards it without `$wl', + # but is careful enough not to reorder. + # Supported since Solaris 2.6 (maybe 2.5.1?) + if test "$GCC" = yes; then + whole_archive_flag_spec='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract' + else + whole_archive_flag_spec='-z allextract$convenience -z defaultextract' + fi + ;; + esac + link_all_deplibs=yes + ;; + + sunos4*) + if test "x$host_vendor" = xsequent; then + # Use $CC to link under sequent, because it throws in some extra .o + # files that make .init and .fini sections work. + archive_cmds='$CC -G ${wl}-h $soname -o $lib $libobjs $deplibs $compiler_flags' + else + archive_cmds='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags' + fi + hardcode_libdir_flag_spec='-L$libdir' + hardcode_direct=yes + hardcode_minus_L=yes + hardcode_shlibpath_var=no + ;; + + sysv4) + case $host_vendor in + sni) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_direct=yes # is this really true??? + ;; + siemens) + ## LD is ld it makes a PLAMLIB + ## CC just makes a GrossModule. + archive_cmds='$LD -G -o $lib $libobjs $deplibs $linker_flags' + reload_cmds='$CC -r -o $output$reload_objs' + hardcode_direct=no + ;; + motorola) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_direct=no #Motorola manual says yes, but my tests say they lie + ;; + esac + runpath_var='LD_RUN_PATH' + hardcode_shlibpath_var=no + ;; + + sysv4.3*) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_shlibpath_var=no + export_dynamic_flag_spec='-Bexport' + ;; + + sysv4*MP*) + if test -d /usr/nec; then + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_shlibpath_var=no + runpath_var=LD_RUN_PATH + hardcode_runpath_var=yes + ld_shlibs=yes + fi + ;; + + sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7* | sco3.2v5.0.[024]*) + no_undefined_flag='${wl}-z,text' + archive_cmds_need_lc=no + hardcode_shlibpath_var=no + runpath_var='LD_RUN_PATH' + + if test "$GCC" = yes; then + archive_cmds='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + else + archive_cmds='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + fi + ;; + + sysv5* | sco3.2v5* | sco5v6*) + # Note: We can NOT use -z defs as we might desire, because we do not + # link with -lc, and that would cause any symbols used from libc to + # always be unresolved, which means just about no library would + # ever link correctly. If we're not using GNU ld we use -z text + # though, which does catch some bad symbols but isn't as heavy-handed + # as -z defs. + no_undefined_flag='${wl}-z,text' + allow_undefined_flag='${wl}-z,nodefs' + archive_cmds_need_lc=no + hardcode_shlibpath_var=no + hardcode_libdir_flag_spec='${wl}-R,$libdir' + hardcode_libdir_separator=':' + link_all_deplibs=yes + export_dynamic_flag_spec='${wl}-Bexport' + runpath_var='LD_RUN_PATH' + + if test "$GCC" = yes; then + archive_cmds='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + else + archive_cmds='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + fi + ;; + + uts4*) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_libdir_flag_spec='-L$libdir' + hardcode_shlibpath_var=no + ;; + + *) + ld_shlibs=no + ;; + esac + + if test x$host_vendor = xsni; then + case $host in + sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) + export_dynamic_flag_spec='${wl}-Blargedynsym' + ;; + esac + fi + fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ld_shlibs" >&5 +$as_echo "$ld_shlibs" >&6; } +test "$ld_shlibs" = no && can_build_shared=no + +with_gnu_ld=$with_gnu_ld + + + + + + + + + + + + + + + +# +# Do we need to explicitly link libc? +# +case "x$archive_cmds_need_lc" in +x|xyes) + # Assume -lc should be added + archive_cmds_need_lc=yes + + if test "$enable_shared" = yes && test "$GCC" = yes; then + case $archive_cmds in + *'~'*) + # FIXME: we may have to deal with multi-command sequences. + ;; + '$CC '*) + # Test whether the compiler implicitly links with -lc since on some + # systems, -lgcc has to come before -lc. If gcc already passes -lc + # to ld, don't add -lc before -lgcc. + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether -lc should be explicitly linked in" >&5 +$as_echo_n "checking whether -lc should be explicitly linked in... " >&6; } +if ${lt_cv_archive_cmds_need_lc+:} false; then : + $as_echo_n "(cached) " >&6 +else + $RM conftest* + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } 2>conftest.err; then + soname=conftest + lib=conftest + libobjs=conftest.$ac_objext + deplibs= + wl=$lt_prog_compiler_wl + pic_flag=$lt_prog_compiler_pic + compiler_flags=-v + linker_flags=-v + verstring= + output_objdir=. + libname=conftest + lt_save_allow_undefined_flag=$allow_undefined_flag + allow_undefined_flag= + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$archive_cmds 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1\""; } >&5 + (eval $archive_cmds 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + then + lt_cv_archive_cmds_need_lc=no + else + lt_cv_archive_cmds_need_lc=yes + fi + allow_undefined_flag=$lt_save_allow_undefined_flag + else + cat conftest.err 1>&5 + fi + $RM conftest* + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_archive_cmds_need_lc" >&5 +$as_echo "$lt_cv_archive_cmds_need_lc" >&6; } + archive_cmds_need_lc=$lt_cv_archive_cmds_need_lc + ;; + esac + fi + ;; +esac + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking dynamic linker characteristics" >&5 +$as_echo_n "checking dynamic linker characteristics... " >&6; } + +if test "$GCC" = yes; then + case $host_os in + darwin*) lt_awk_arg="/^libraries:/,/LR/" ;; + *) lt_awk_arg="/^libraries:/" ;; + esac + case $host_os in + mingw* | cegcc*) lt_sed_strip_eq="s,=\([A-Za-z]:\),\1,g" ;; + *) lt_sed_strip_eq="s,=/,/,g" ;; + esac + lt_search_path_spec=`$CC -print-search-dirs | awk $lt_awk_arg | $SED -e "s/^libraries://" -e $lt_sed_strip_eq` + case $lt_search_path_spec in + *\;*) + # if the path contains ";" then we assume it to be the separator + # otherwise default to the standard path separator (i.e. ":") - it is + # assumed that no part of a normal pathname contains ";" but that should + # okay in the real world where ";" in dirpaths is itself problematic. + lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED 's/;/ /g'` + ;; + *) + lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED "s/$PATH_SEPARATOR/ /g"` + ;; + esac + # Ok, now we have the path, separated by spaces, we can step through it + # and add multilib dir if necessary. + lt_tmp_lt_search_path_spec= + lt_multi_os_dir=`$CC $CPPFLAGS $CFLAGS $LDFLAGS -print-multi-os-directory 2>/dev/null` + for lt_sys_path in $lt_search_path_spec; do + if test -d "$lt_sys_path/$lt_multi_os_dir"; then + lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path/$lt_multi_os_dir" + else + test -d "$lt_sys_path" && \ + lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path" + fi + done + lt_search_path_spec=`$ECHO "$lt_tmp_lt_search_path_spec" | awk ' +BEGIN {RS=" "; FS="/|\n";} { + lt_foo=""; + lt_count=0; + for (lt_i = NF; lt_i > 0; lt_i--) { + if ($lt_i != "" && $lt_i != ".") { + if ($lt_i == "..") { + lt_count++; + } else { + if (lt_count == 0) { + lt_foo="/" $lt_i lt_foo; + } else { + lt_count--; + } + } + } + } + if (lt_foo != "") { lt_freq[lt_foo]++; } + if (lt_freq[lt_foo] == 1) { print lt_foo; } +}'` + # AWK program above erroneously prepends '/' to C:/dos/paths + # for these hosts. + case $host_os in + mingw* | cegcc*) lt_search_path_spec=`$ECHO "$lt_search_path_spec" |\ + $SED 's,/\([A-Za-z]:\),\1,g'` ;; + esac + sys_lib_search_path_spec=`$ECHO "$lt_search_path_spec" | $lt_NL2SP` +else + sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" +fi +library_names_spec= +libname_spec='lib$name' +soname_spec= +shrext_cmds=".so" +postinstall_cmds= +postuninstall_cmds= +finish_cmds= +finish_eval= +shlibpath_var= +shlibpath_overrides_runpath=unknown +version_type=none +dynamic_linker="$host_os ld.so" +sys_lib_dlsearch_path_spec="/lib /usr/lib" +need_lib_prefix=unknown +hardcode_into_libs=no + +# when you set need_version to no, make sure it does not cause -set_version +# flags to be left without arguments +need_version=unknown + +case $host_os in +aix3*) + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a' + shlibpath_var=LIBPATH + + # AIX 3 has no versioning support, so we append a major version to the name. + soname_spec='${libname}${release}${shared_ext}$major' + ;; + +aix[4-9]*) + version_type=linux + need_lib_prefix=no + need_version=no + hardcode_into_libs=yes + if test "$host_cpu" = ia64; then + # AIX 5 supports IA64 + library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + else + # With GCC up to 2.95.x, collect2 would create an import file + # for dependence libraries. The import file would start with + # the line `#! .'. This would cause the generated library to + # depend on `.', always an invalid library. This was fixed in + # development snapshots of GCC prior to 3.0. + case $host_os in + aix4 | aix4.[01] | aix4.[01].*) + if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' + echo ' yes ' + echo '#endif'; } | ${CC} -E - | $GREP yes > /dev/null; then + : + else + can_build_shared=no + fi + ;; + esac + # AIX (on Power*) has no versioning support, so currently we can not hardcode correct + # soname into executable. Probably we can add versioning support to + # collect2, so additional links can be useful in future. + if test "$aix_use_runtimelinking" = yes; then + # If using run time linking (on AIX 4.2 or later) use lib.so + # instead of lib.a to let people know that these are not + # typical AIX shared libraries. + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + else + # We preserve .a as extension for shared libraries through AIX4.2 + # and later when we are not doing run time linking. + library_names_spec='${libname}${release}.a $libname.a' + soname_spec='${libname}${release}${shared_ext}$major' + fi + shlibpath_var=LIBPATH + fi + ;; + +amigaos*) + case $host_cpu in + powerpc) + # Since July 2007 AmigaOS4 officially supports .so libraries. + # When compiling the executable, add -use-dynld -Lsobjs: to the compileline. + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + ;; + m68k) + library_names_spec='$libname.ixlibrary $libname.a' + # Create ${libname}_ixlibrary.a entries in /sys/libs. + finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`func_echo_all "$lib" | $SED '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; test $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' + ;; + esac + ;; + +beos*) + library_names_spec='${libname}${shared_ext}' + dynamic_linker="$host_os ld.so" + shlibpath_var=LIBRARY_PATH + ;; + +bsdi[45]*) + version_type=linux + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' + shlibpath_var=LD_LIBRARY_PATH + sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" + sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" + # the default ld.so.conf also contains /usr/contrib/lib and + # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow + # libtool to hard-code these into programs + ;; + +cygwin* | mingw* | pw32* | cegcc*) + version_type=windows + shrext_cmds=".dll" + need_version=no + need_lib_prefix=no + + case $GCC,$cc_basename in + yes,*) + # gcc + library_names_spec='$libname.dll.a' + # DLL is installed to $(libdir)/../bin by postinstall_cmds + postinstall_cmds='base_file=`basename \${file}`~ + dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i; echo \$dlname'\''`~ + dldir=$destdir/`dirname \$dlpath`~ + test -d \$dldir || mkdir -p \$dldir~ + $install_prog $dir/$dlname \$dldir/$dlname~ + chmod a+x \$dldir/$dlname~ + if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then + eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; + fi' + postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ + dlpath=$dir/\$dldll~ + $RM \$dlpath' + shlibpath_overrides_runpath=yes + + case $host_os in + cygwin*) + # Cygwin DLLs use 'cyg' prefix rather than 'lib' + soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' + + sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/lib/w32api" + ;; + mingw* | cegcc*) + # MinGW DLLs use traditional 'lib' prefix + soname_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' + ;; + pw32*) + # pw32 DLLs use 'pw' prefix rather than 'lib' + library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' + ;; + esac + dynamic_linker='Win32 ld.exe' + ;; + + *,cl*) + # Native MSVC + libname_spec='$name' + soname_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' + library_names_spec='${libname}.dll.lib' + + case $build_os in + mingw*) + sys_lib_search_path_spec= + lt_save_ifs=$IFS + IFS=';' + for lt_path in $LIB + do + IFS=$lt_save_ifs + # Let DOS variable expansion print the short 8.3 style file name. + lt_path=`cd "$lt_path" 2>/dev/null && cmd //C "for %i in (".") do @echo %~si"` + sys_lib_search_path_spec="$sys_lib_search_path_spec $lt_path" + done + IFS=$lt_save_ifs + # Convert to MSYS style. + sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | sed -e 's|\\\\|/|g' -e 's| \\([a-zA-Z]\\):| /\\1|g' -e 's|^ ||'` + ;; + cygwin*) + # Convert to unix form, then to dos form, then back to unix form + # but this time dos style (no spaces!) so that the unix form looks + # like /cygdrive/c/PROGRA~1:/cygdr... + sys_lib_search_path_spec=`cygpath --path --unix "$LIB"` + sys_lib_search_path_spec=`cygpath --path --dos "$sys_lib_search_path_spec" 2>/dev/null` + sys_lib_search_path_spec=`cygpath --path --unix "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` + ;; + *) + sys_lib_search_path_spec="$LIB" + if $ECHO "$sys_lib_search_path_spec" | $GREP ';[c-zC-Z]:/' >/dev/null; then + # It is most probably a Windows format PATH. + sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` + else + sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` + fi + # FIXME: find the short name or the path components, as spaces are + # common. (e.g. "Program Files" -> "PROGRA~1") + ;; + esac + + # DLL is installed to $(libdir)/../bin by postinstall_cmds + postinstall_cmds='base_file=`basename \${file}`~ + dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i; echo \$dlname'\''`~ + dldir=$destdir/`dirname \$dlpath`~ + test -d \$dldir || mkdir -p \$dldir~ + $install_prog $dir/$dlname \$dldir/$dlname' + postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ + dlpath=$dir/\$dldll~ + $RM \$dlpath' + shlibpath_overrides_runpath=yes + dynamic_linker='Win32 link.exe' + ;; + + *) + # Assume MSVC wrapper + library_names_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext} $libname.lib' + dynamic_linker='Win32 ld.exe' + ;; + esac + # FIXME: first we should search . and the directory the executable is in + shlibpath_var=PATH + ;; + +darwin* | rhapsody*) + dynamic_linker="$host_os dyld" + version_type=darwin + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${major}$shared_ext ${libname}$shared_ext' + soname_spec='${libname}${release}${major}$shared_ext' + shlibpath_overrides_runpath=yes + shlibpath_var=DYLD_LIBRARY_PATH + shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`' + + sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/local/lib" + sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' + ;; + +dgux*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + +freebsd1*) + dynamic_linker=no + ;; + +freebsd* | dragonfly*) + # DragonFly does not have aout. When/if they implement a new + # versioning mechanism, adjust this. + if test -x /usr/bin/objformat; then + objformat=`/usr/bin/objformat` + else + case $host_os in + freebsd[123]*) objformat=aout ;; + *) objformat=elf ;; + esac + fi + version_type=freebsd-$objformat + case $version_type in + freebsd-elf*) + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' + need_version=no + need_lib_prefix=no + ;; + freebsd-*) + library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix' + need_version=yes + ;; + esac + shlibpath_var=LD_LIBRARY_PATH + case $host_os in + freebsd2*) + shlibpath_overrides_runpath=yes + ;; + freebsd3.[01]* | freebsdelf3.[01]*) + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + freebsd3.[2-9]* | freebsdelf3.[2-9]* | \ + freebsd4.[0-5] | freebsdelf4.[0-5] | freebsd4.1.1 | freebsdelf4.1.1) + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + *) # from 4.6 on, and DragonFly + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + esac + ;; + +gnu*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + hardcode_into_libs=yes + ;; + +haiku*) + version_type=linux + need_lib_prefix=no + need_version=no + dynamic_linker="$host_os runtime_loader" + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LIBRARY_PATH + shlibpath_overrides_runpath=yes + sys_lib_dlsearch_path_spec='/boot/home/config/lib /boot/common/lib /boot/system/lib' + hardcode_into_libs=yes + ;; + +hpux9* | hpux10* | hpux11*) + # Give a soname corresponding to the major version so that dld.sl refuses to + # link against other versions. + version_type=sunos + need_lib_prefix=no + need_version=no + case $host_cpu in + ia64*) + shrext_cmds='.so' + hardcode_into_libs=yes + dynamic_linker="$host_os dld.so" + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + if test "X$HPUX_IA64_MODE" = X32; then + sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" + else + sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" + fi + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + ;; + hppa*64*) + shrext_cmds='.sl' + hardcode_into_libs=yes + dynamic_linker="$host_os dld.sl" + shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH + shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + ;; + *) + shrext_cmds='.sl' + dynamic_linker="$host_os dld.sl" + shlibpath_var=SHLIB_PATH + shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + ;; + esac + # HP-UX runs *really* slowly unless shared libraries are mode 555, ... + postinstall_cmds='chmod 555 $lib' + # or fails outright, so override atomically: + install_override_mode=555 + ;; + +interix[3-9]*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + +irix5* | irix6* | nonstopux*) + case $host_os in + nonstopux*) version_type=nonstopux ;; + *) + if test "$lt_cv_prog_gnu_ld" = yes; then + version_type=linux + else + version_type=irix + fi ;; + esac + need_lib_prefix=no + need_version=no + soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}' + case $host_os in + irix5* | nonstopux*) + libsuff= shlibsuff= + ;; + *) + case $LD in # libtool.m4 will add one of these switches to LD + *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") + libsuff= shlibsuff= libmagic=32-bit;; + *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") + libsuff=32 shlibsuff=N32 libmagic=N32;; + *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") + libsuff=64 shlibsuff=64 libmagic=64-bit;; + *) libsuff= shlibsuff= libmagic=never-match;; + esac + ;; + esac + shlibpath_var=LD_LIBRARY${shlibsuff}_PATH + shlibpath_overrides_runpath=no + sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}" + sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}" + hardcode_into_libs=yes + ;; + +# No shared lib support for Linux oldld, aout, or coff. +linux*oldld* | linux*aout* | linux*coff*) + dynamic_linker=no + ;; + +# This must be Linux ELF. +linux* | k*bsd*-gnu | kopensolaris*-gnu) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + + # Some binutils ld are patched to set DT_RUNPATH + if ${lt_cv_shlibpath_overrides_runpath+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_shlibpath_overrides_runpath=no + save_LDFLAGS=$LDFLAGS + save_libdir=$libdir + eval "libdir=/foo; wl=\"$lt_prog_compiler_wl\"; \ + LDFLAGS=\"\$LDFLAGS $hardcode_libdir_flag_spec\"" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + if ($OBJDUMP -p conftest$ac_exeext) 2>/dev/null | grep "RUNPATH.*$libdir" >/dev/null; then : + lt_cv_shlibpath_overrides_runpath=yes +fi +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + LDFLAGS=$save_LDFLAGS + libdir=$save_libdir + +fi + + shlibpath_overrides_runpath=$lt_cv_shlibpath_overrides_runpath + + # This implies no fast_install, which is unacceptable. + # Some rework will be needed to allow for fast_install + # before this can be enabled. + hardcode_into_libs=yes + + # Append ld.so.conf contents to the search path + if test -f /etc/ld.so.conf; then + lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[ ]*hwcap[ ]/d;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;s/"//g;/^$/d' | tr '\n' ' '` + sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra" + fi + + # We used to test for /lib/ld.so.1 and disable shared libraries on + # powerpc, because MkLinux only supported shared libraries with the + # GNU dynamic linker. Since this was broken with cross compilers, + # most powerpc-linux boxes support dynamic linking these days and + # people can always --disable-shared, the test was removed, and we + # assume the GNU/Linux dynamic linker is in use. + dynamic_linker='GNU/Linux ld.so' + ;; + +netbsd*) + version_type=sunos + need_lib_prefix=no + need_version=no + if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' + dynamic_linker='NetBSD (a.out) ld.so' + else + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + dynamic_linker='NetBSD ld.elf_so' + fi + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + +newsos6) + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + ;; + +*nto* | *qnx*) + version_type=qnx + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + dynamic_linker='ldqnx.so' + ;; + +openbsd*) + version_type=sunos + sys_lib_dlsearch_path_spec="/usr/lib" + need_lib_prefix=no + # Some older versions of OpenBSD (3.3 at least) *do* need versioned libs. + case $host_os in + openbsd3.3 | openbsd3.3.*) need_version=yes ;; + *) need_version=no ;; + esac + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' + shlibpath_var=LD_LIBRARY_PATH + if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + case $host_os in + openbsd2.[89] | openbsd2.[89].*) + shlibpath_overrides_runpath=no + ;; + *) + shlibpath_overrides_runpath=yes + ;; + esac + else + shlibpath_overrides_runpath=yes + fi + ;; + +os2*) + libname_spec='$name' + shrext_cmds=".dll" + need_lib_prefix=no + library_names_spec='$libname${shared_ext} $libname.a' + dynamic_linker='OS/2 ld.exe' + shlibpath_var=LIBPATH + ;; + +osf3* | osf4* | osf5*) + version_type=osf + need_lib_prefix=no + need_version=no + soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" + sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec" + ;; + +rdos*) + dynamic_linker=no + ;; + +solaris*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + # ldd complains unless libraries are executable + postinstall_cmds='chmod +x $lib' + ;; + +sunos4*) + version_type=sunos + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' + finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + if test "$with_gnu_ld" = yes; then + need_lib_prefix=no + fi + need_version=yes + ;; + +sysv4 | sysv4.3*) + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + case $host_vendor in + sni) + shlibpath_overrides_runpath=no + need_lib_prefix=no + runpath_var=LD_RUN_PATH + ;; + siemens) + need_lib_prefix=no + ;; + motorola) + need_lib_prefix=no + need_version=no + shlibpath_overrides_runpath=no + sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' + ;; + esac + ;; + +sysv4*MP*) + if test -d /usr/nec ;then + version_type=linux + library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}' + soname_spec='$libname${shared_ext}.$major' + shlibpath_var=LD_LIBRARY_PATH + fi + ;; + +sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) + version_type=freebsd-elf + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + if test "$with_gnu_ld" = yes; then + sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib' + else + sys_lib_search_path_spec='/usr/ccs/lib /usr/lib' + case $host_os in + sco3.2v5*) + sys_lib_search_path_spec="$sys_lib_search_path_spec /lib" + ;; + esac + fi + sys_lib_dlsearch_path_spec='/usr/lib' + ;; + +tpf*) + # TPF is a cross-target only. Preferred cross-host = GNU/Linux. + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + +uts4*) + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + +*) + dynamic_linker=no + ;; +esac +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $dynamic_linker" >&5 +$as_echo "$dynamic_linker" >&6; } +test "$dynamic_linker" = no && can_build_shared=no + +variables_saved_for_relink="PATH $shlibpath_var $runpath_var" +if test "$GCC" = yes; then + variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" +fi + +if test "${lt_cv_sys_lib_search_path_spec+set}" = set; then + sys_lib_search_path_spec="$lt_cv_sys_lib_search_path_spec" +fi +if test "${lt_cv_sys_lib_dlsearch_path_spec+set}" = set; then + sys_lib_dlsearch_path_spec="$lt_cv_sys_lib_dlsearch_path_spec" +fi + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to hardcode library paths into programs" >&5 +$as_echo_n "checking how to hardcode library paths into programs... " >&6; } +hardcode_action= +if test -n "$hardcode_libdir_flag_spec" || + test -n "$runpath_var" || + test "X$hardcode_automatic" = "Xyes" ; then + + # We can hardcode non-existent directories. + if test "$hardcode_direct" != no && + # If the only mechanism to avoid hardcoding is shlibpath_var, we + # have to relink, otherwise we might link with an installed library + # when we should be linking with a yet-to-be-installed one + ## test "$_LT_TAGVAR(hardcode_shlibpath_var, )" != no && + test "$hardcode_minus_L" != no; then + # Linking always hardcodes the temporary library directory. + hardcode_action=relink + else + # We can link without hardcoding, and we can hardcode nonexisting dirs. + hardcode_action=immediate + fi +else + # We cannot hardcode anything, or else we can only hardcode existing + # directories. + hardcode_action=unsupported +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $hardcode_action" >&5 +$as_echo "$hardcode_action" >&6; } + +if test "$hardcode_action" = relink || + test "$inherit_rpath" = yes; then + # Fast installation is not supported + enable_fast_install=no +elif test "$shlibpath_overrides_runpath" = yes || + test "$enable_shared" = no; then + # Fast installation is not necessary + enable_fast_install=needless +fi + + + + + + + if test "x$enable_dlopen" != xyes; then + enable_dlopen=unknown + enable_dlopen_self=unknown + enable_dlopen_self_static=unknown +else + lt_cv_dlopen=no + lt_cv_dlopen_libs= + + case $host_os in + beos*) + lt_cv_dlopen="load_add_on" + lt_cv_dlopen_libs= + lt_cv_dlopen_self=yes + ;; + + mingw* | pw32* | cegcc*) + lt_cv_dlopen="LoadLibrary" + lt_cv_dlopen_libs= + ;; + + cygwin*) + lt_cv_dlopen="dlopen" + lt_cv_dlopen_libs= + ;; + + darwin*) + # if libdl is installed we need to link against it + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5 +$as_echo_n "checking for dlopen in -ldl... " >&6; } +if ${ac_cv_lib_dl_dlopen+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-ldl $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char dlopen (); +int +main () +{ +return dlopen (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_dl_dlopen=yes +else + ac_cv_lib_dl_dlopen=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5 +$as_echo "$ac_cv_lib_dl_dlopen" >&6; } +if test "x$ac_cv_lib_dl_dlopen" = xyes; then : + lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl" +else + + lt_cv_dlopen="dyld" + lt_cv_dlopen_libs= + lt_cv_dlopen_self=yes + +fi + + ;; + + *) + ac_fn_c_check_func "$LINENO" "shl_load" "ac_cv_func_shl_load" +if test "x$ac_cv_func_shl_load" = xyes; then : + lt_cv_dlopen="shl_load" +else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for shl_load in -ldld" >&5 +$as_echo_n "checking for shl_load in -ldld... " >&6; } +if ${ac_cv_lib_dld_shl_load+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-ldld $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char shl_load (); +int +main () +{ +return shl_load (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_dld_shl_load=yes +else + ac_cv_lib_dld_shl_load=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dld_shl_load" >&5 +$as_echo "$ac_cv_lib_dld_shl_load" >&6; } +if test "x$ac_cv_lib_dld_shl_load" = xyes; then : + lt_cv_dlopen="shl_load" lt_cv_dlopen_libs="-ldld" +else + ac_fn_c_check_func "$LINENO" "dlopen" "ac_cv_func_dlopen" +if test "x$ac_cv_func_dlopen" = xyes; then : + lt_cv_dlopen="dlopen" +else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -ldl" >&5 +$as_echo_n "checking for dlopen in -ldl... " >&6; } +if ${ac_cv_lib_dl_dlopen+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-ldl $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char dlopen (); +int +main () +{ +return dlopen (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_dl_dlopen=yes +else + ac_cv_lib_dl_dlopen=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_dlopen" >&5 +$as_echo "$ac_cv_lib_dl_dlopen" >&6; } +if test "x$ac_cv_lib_dl_dlopen" = xyes; then : + lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl" +else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dlopen in -lsvld" >&5 +$as_echo_n "checking for dlopen in -lsvld... " >&6; } +if ${ac_cv_lib_svld_dlopen+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lsvld $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char dlopen (); +int +main () +{ +return dlopen (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_svld_dlopen=yes +else + ac_cv_lib_svld_dlopen=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_svld_dlopen" >&5 +$as_echo "$ac_cv_lib_svld_dlopen" >&6; } +if test "x$ac_cv_lib_svld_dlopen" = xyes; then : + lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-lsvld" +else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for dld_link in -ldld" >&5 +$as_echo_n "checking for dld_link in -ldld... " >&6; } +if ${ac_cv_lib_dld_dld_link+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-ldld $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char dld_link (); +int +main () +{ +return dld_link (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_dld_dld_link=yes +else + ac_cv_lib_dld_dld_link=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dld_dld_link" >&5 +$as_echo "$ac_cv_lib_dld_dld_link" >&6; } +if test "x$ac_cv_lib_dld_dld_link" = xyes; then : + lt_cv_dlopen="dld_link" lt_cv_dlopen_libs="-ldld" +fi + + +fi + + +fi + + +fi + + +fi + + +fi + + ;; + esac + + if test "x$lt_cv_dlopen" != xno; then + enable_dlopen=yes + else + enable_dlopen=no + fi + + case $lt_cv_dlopen in + dlopen) + save_CPPFLAGS="$CPPFLAGS" + test "x$ac_cv_header_dlfcn_h" = xyes && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H" + + save_LDFLAGS="$LDFLAGS" + wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\" + + save_LIBS="$LIBS" + LIBS="$lt_cv_dlopen_libs $LIBS" + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether a program can dlopen itself" >&5 +$as_echo_n "checking whether a program can dlopen itself... " >&6; } +if ${lt_cv_dlopen_self+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test "$cross_compiling" = yes; then : + lt_cv_dlopen_self=cross +else + lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 + lt_status=$lt_dlunknown + cat > conftest.$ac_ext <<_LT_EOF +#line $LINENO "configure" +#include "confdefs.h" + +#if HAVE_DLFCN_H +#include +#endif + +#include + +#ifdef RTLD_GLOBAL +# define LT_DLGLOBAL RTLD_GLOBAL +#else +# ifdef DL_GLOBAL +# define LT_DLGLOBAL DL_GLOBAL +# else +# define LT_DLGLOBAL 0 +# endif +#endif + +/* We may have to define LT_DLLAZY_OR_NOW in the command line if we + find out it does not work in some platform. */ +#ifndef LT_DLLAZY_OR_NOW +# ifdef RTLD_LAZY +# define LT_DLLAZY_OR_NOW RTLD_LAZY +# else +# ifdef DL_LAZY +# define LT_DLLAZY_OR_NOW DL_LAZY +# else +# ifdef RTLD_NOW +# define LT_DLLAZY_OR_NOW RTLD_NOW +# else +# ifdef DL_NOW +# define LT_DLLAZY_OR_NOW DL_NOW +# else +# define LT_DLLAZY_OR_NOW 0 +# endif +# endif +# endif +# endif +#endif + +/* When -fvisbility=hidden is used, assume the code has been annotated + correspondingly for the symbols needed. */ +#if defined(__GNUC__) && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3)) +int fnord () __attribute__((visibility("default"))); +#endif + +int fnord () { return 42; } +int main () +{ + void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); + int status = $lt_dlunknown; + + if (self) + { + if (dlsym (self,"fnord")) status = $lt_dlno_uscore; + else + { + if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; + else puts (dlerror ()); + } + /* dlclose (self); */ + } + else + puts (dlerror ()); + + return status; +} +_LT_EOF + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5 + (eval $ac_link) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && test -s conftest${ac_exeext} 2>/dev/null; then + (./conftest; exit; ) >&5 2>/dev/null + lt_status=$? + case x$lt_status in + x$lt_dlno_uscore) lt_cv_dlopen_self=yes ;; + x$lt_dlneed_uscore) lt_cv_dlopen_self=yes ;; + x$lt_dlunknown|x*) lt_cv_dlopen_self=no ;; + esac + else : + # compilation failed + lt_cv_dlopen_self=no + fi +fi +rm -fr conftest* + + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_dlopen_self" >&5 +$as_echo "$lt_cv_dlopen_self" >&6; } + + if test "x$lt_cv_dlopen_self" = xyes; then + wl=$lt_prog_compiler_wl eval LDFLAGS=\"\$LDFLAGS $lt_prog_compiler_static\" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether a statically linked program can dlopen itself" >&5 +$as_echo_n "checking whether a statically linked program can dlopen itself... " >&6; } +if ${lt_cv_dlopen_self_static+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test "$cross_compiling" = yes; then : + lt_cv_dlopen_self_static=cross +else + lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 + lt_status=$lt_dlunknown + cat > conftest.$ac_ext <<_LT_EOF +#line $LINENO "configure" +#include "confdefs.h" + +#if HAVE_DLFCN_H +#include +#endif + +#include + +#ifdef RTLD_GLOBAL +# define LT_DLGLOBAL RTLD_GLOBAL +#else +# ifdef DL_GLOBAL +# define LT_DLGLOBAL DL_GLOBAL +# else +# define LT_DLGLOBAL 0 +# endif +#endif + +/* We may have to define LT_DLLAZY_OR_NOW in the command line if we + find out it does not work in some platform. */ +#ifndef LT_DLLAZY_OR_NOW +# ifdef RTLD_LAZY +# define LT_DLLAZY_OR_NOW RTLD_LAZY +# else +# ifdef DL_LAZY +# define LT_DLLAZY_OR_NOW DL_LAZY +# else +# ifdef RTLD_NOW +# define LT_DLLAZY_OR_NOW RTLD_NOW +# else +# ifdef DL_NOW +# define LT_DLLAZY_OR_NOW DL_NOW +# else +# define LT_DLLAZY_OR_NOW 0 +# endif +# endif +# endif +# endif +#endif + +/* When -fvisbility=hidden is used, assume the code has been annotated + correspondingly for the symbols needed. */ +#if defined(__GNUC__) && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3)) +int fnord () __attribute__((visibility("default"))); +#endif + +int fnord () { return 42; } +int main () +{ + void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); + int status = $lt_dlunknown; + + if (self) + { + if (dlsym (self,"fnord")) status = $lt_dlno_uscore; + else + { + if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; + else puts (dlerror ()); + } + /* dlclose (self); */ + } + else + puts (dlerror ()); + + return status; +} +_LT_EOF + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_link\""; } >&5 + (eval $ac_link) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && test -s conftest${ac_exeext} 2>/dev/null; then + (./conftest; exit; ) >&5 2>/dev/null + lt_status=$? + case x$lt_status in + x$lt_dlno_uscore) lt_cv_dlopen_self_static=yes ;; + x$lt_dlneed_uscore) lt_cv_dlopen_self_static=yes ;; + x$lt_dlunknown|x*) lt_cv_dlopen_self_static=no ;; + esac + else : + # compilation failed + lt_cv_dlopen_self_static=no + fi +fi +rm -fr conftest* + + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_dlopen_self_static" >&5 +$as_echo "$lt_cv_dlopen_self_static" >&6; } + fi + + CPPFLAGS="$save_CPPFLAGS" + LDFLAGS="$save_LDFLAGS" + LIBS="$save_LIBS" + ;; + esac + + case $lt_cv_dlopen_self in + yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;; + *) enable_dlopen_self=unknown ;; + esac + + case $lt_cv_dlopen_self_static in + yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;; + *) enable_dlopen_self_static=unknown ;; + esac +fi + + + + + + + + + + + + + + + + + +striplib= +old_striplib= +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether stripping libraries is possible" >&5 +$as_echo_n "checking whether stripping libraries is possible... " >&6; } +if test -n "$STRIP" && $STRIP -V 2>&1 | $GREP "GNU strip" >/dev/null; then + test -z "$old_striplib" && old_striplib="$STRIP --strip-debug" + test -z "$striplib" && striplib="$STRIP --strip-unneeded" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +else +# FIXME - insert some real tests, host_os isn't really good enough + case $host_os in + darwin*) + if test -n "$STRIP" ; then + striplib="$STRIP -x" + old_striplib="$STRIP -S" + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + fi + ;; + *) + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + ;; + esac +fi + + + + + + + + + + + + + # Report which library types will actually be built + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if libtool supports shared libraries" >&5 +$as_echo_n "checking if libtool supports shared libraries... " >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $can_build_shared" >&5 +$as_echo "$can_build_shared" >&6; } + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build shared libraries" >&5 +$as_echo_n "checking whether to build shared libraries... " >&6; } + test "$can_build_shared" = "no" && enable_shared=no + + # On AIX, shared libraries and static libraries use the same namespace, and + # are all built from PIC. + case $host_os in + aix3*) + test "$enable_shared" = yes && enable_static=no + if test -n "$RANLIB"; then + archive_cmds="$archive_cmds~\$RANLIB \$lib" + postinstall_cmds='$RANLIB $lib' + fi + ;; + + aix[4-9]*) + if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then + test "$enable_shared" = yes && enable_static=no + fi + ;; + esac + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_shared" >&5 +$as_echo "$enable_shared" >&6; } + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to build static libraries" >&5 +$as_echo_n "checking whether to build static libraries... " >&6; } + # Make sure either enable_shared or enable_static is yes. + test "$enable_shared" = yes || enable_static=yes + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $enable_static" >&5 +$as_echo "$enable_static" >&6; } + + + + +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 + +CC="$lt_save_CC" + + if test -n "$CXX" && ( test "X$CXX" != "Xno" && + ( (test "X$CXX" = "Xg++" && `g++ -v >/dev/null 2>&1` ) || + (test "X$CXX" != "Xg++"))) ; then + ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C++ preprocessor" >&5 +$as_echo_n "checking how to run the C++ preprocessor... " >&6; } +if test -z "$CXXCPP"; then + if ${ac_cv_prog_CXXCPP+:} false; then : + $as_echo_n "(cached) " >&6 +else + # Double quotes because CXXCPP needs to be expanded + for CXXCPP in "$CXX -E" "/lib/cpp" + do + ac_preproc_ok=false +for ac_cxx_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer to if __STDC__ is defined, since + # exists even on freestanding compilers. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifdef __STDC__ +# include +#else +# include +#endif + Syntax error +_ACEOF +if ac_fn_cxx_try_cpp "$LINENO"; then : + +else + # Broken: fails on valid input. +continue +fi +rm -f conftest.err conftest.i conftest.$ac_ext + + # OK, works on sane cases. Now check whether nonexistent headers + # can be detected and how. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +_ACEOF +if ac_fn_cxx_try_cpp "$LINENO"; then : + # Broken: success on invalid input. +continue +else + # Passes both tests. +ac_preproc_ok=: +break +fi +rm -f conftest.err conftest.i conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.i conftest.err conftest.$ac_ext +if $ac_preproc_ok; then : + break +fi + + done + ac_cv_prog_CXXCPP=$CXXCPP + +fi + CXXCPP=$ac_cv_prog_CXXCPP +else + ac_cv_prog_CXXCPP=$CXXCPP +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $CXXCPP" >&5 +$as_echo "$CXXCPP" >&6; } +ac_preproc_ok=false +for ac_cxx_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer to if __STDC__ is defined, since + # exists even on freestanding compilers. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifdef __STDC__ +# include +#else +# include +#endif + Syntax error +_ACEOF +if ac_fn_cxx_try_cpp "$LINENO"; then : + +else + # Broken: fails on valid input. +continue +fi +rm -f conftest.err conftest.i conftest.$ac_ext + + # OK, works on sane cases. Now check whether nonexistent headers + # can be detected and how. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +_ACEOF +if ac_fn_cxx_try_cpp "$LINENO"; then : + # Broken: success on invalid input. +continue +else + # Passes both tests. +ac_preproc_ok=: +break +fi +rm -f conftest.err conftest.i conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.i conftest.err conftest.$ac_ext +if $ac_preproc_ok; then : + +else + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "C++ preprocessor \"$CXXCPP\" fails sanity check +See \`config.log' for more details" "$LINENO" 5; } +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 + +else + _lt_caught_CXX_error=yes +fi + +ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu + +archive_cmds_need_lc_CXX=no +allow_undefined_flag_CXX= +always_export_symbols_CXX=no +archive_expsym_cmds_CXX= +compiler_needs_object_CXX=no +export_dynamic_flag_spec_CXX= +hardcode_direct_CXX=no +hardcode_direct_absolute_CXX=no +hardcode_libdir_flag_spec_CXX= +hardcode_libdir_flag_spec_ld_CXX= +hardcode_libdir_separator_CXX= +hardcode_minus_L_CXX=no +hardcode_shlibpath_var_CXX=unsupported +hardcode_automatic_CXX=no +inherit_rpath_CXX=no +module_cmds_CXX= +module_expsym_cmds_CXX= +link_all_deplibs_CXX=unknown +old_archive_cmds_CXX=$old_archive_cmds +reload_flag_CXX=$reload_flag +reload_cmds_CXX=$reload_cmds +no_undefined_flag_CXX= +whole_archive_flag_spec_CXX= +enable_shared_with_static_runtimes_CXX=no + +# Source file extension for C++ test sources. +ac_ext=cpp + +# Object file extension for compiled C++ test sources. +objext=o +objext_CXX=$objext + +# No sense in running all these tests if we already determined that +# the CXX compiler isn't working. Some variables (like enable_shared) +# are currently assumed to apply to all compilers on this platform, +# and will be corrupted by setting them based on a non-working compiler. +if test "$_lt_caught_CXX_error" != yes; then + # Code to be used in simple compile tests + lt_simple_compile_test_code="int some_variable = 0;" + + # Code to be used in simple link tests + lt_simple_link_test_code='int main(int, char *[]) { return(0); }' + + # ltmain only uses $CC for tagged configurations so make sure $CC is set. + + + + + + +# If no C compiler was specified, use CC. +LTCC=${LTCC-"$CC"} + +# If no C compiler flags were specified, use CFLAGS. +LTCFLAGS=${LTCFLAGS-"$CFLAGS"} + +# Allow CC to be a program name with arguments. +compiler=$CC + + + # save warnings/boilerplate of simple test code + ac_outfile=conftest.$ac_objext +echo "$lt_simple_compile_test_code" >conftest.$ac_ext +eval "$ac_compile" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err +_lt_compiler_boilerplate=`cat conftest.err` +$RM conftest* + + ac_outfile=conftest.$ac_objext +echo "$lt_simple_link_test_code" >conftest.$ac_ext +eval "$ac_link" 2>&1 >/dev/null | $SED '/^$/d; /^ *+/d' >conftest.err +_lt_linker_boilerplate=`cat conftest.err` +$RM -r conftest* + + + # Allow CC to be a program name with arguments. + lt_save_CC=$CC + lt_save_CFLAGS=$CFLAGS + lt_save_LD=$LD + lt_save_GCC=$GCC + GCC=$GXX + lt_save_with_gnu_ld=$with_gnu_ld + lt_save_path_LD=$lt_cv_path_LD + if test -n "${lt_cv_prog_gnu_ldcxx+set}"; then + lt_cv_prog_gnu_ld=$lt_cv_prog_gnu_ldcxx + else + $as_unset lt_cv_prog_gnu_ld + fi + if test -n "${lt_cv_path_LDCXX+set}"; then + lt_cv_path_LD=$lt_cv_path_LDCXX + else + $as_unset lt_cv_path_LD + fi + test -z "${LDCXX+set}" || LD=$LDCXX + CC=${CXX-"c++"} + CFLAGS=$CXXFLAGS + compiler=$CC + compiler_CXX=$CC + for cc_temp in $compiler""; do + case $cc_temp in + compile | *[\\/]compile | ccache | *[\\/]ccache ) ;; + distcc | *[\\/]distcc | purify | *[\\/]purify ) ;; + \-*) ;; + *) break;; + esac +done +cc_basename=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"` + + + if test -n "$compiler"; then + # We don't want -fno-exception when compiling C++ code, so set the + # no_builtin_flag separately + if test "$GXX" = yes; then + lt_prog_compiler_no_builtin_flag_CXX=' -fno-builtin' + else + lt_prog_compiler_no_builtin_flag_CXX= + fi + + if test "$GXX" = yes; then + # Set up default GNU C++ configuration + + + +# Check whether --with-gnu-ld was given. +if test "${with_gnu_ld+set}" = set; then : + withval=$with_gnu_ld; test "$withval" = no || with_gnu_ld=yes +else + with_gnu_ld=no +fi + +ac_prog=ld +if test "$GCC" = yes; then + # Check if gcc -print-prog-name=ld gives a path. + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ld used by $CC" >&5 +$as_echo_n "checking for ld used by $CC... " >&6; } + case $host in + *-*-mingw*) + # gcc leaves a trailing carriage return which upsets mingw + ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; + *) + ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; + esac + case $ac_prog in + # Accept absolute paths. + [\\/]* | ?:[\\/]*) + re_direlt='/[^/][^/]*/\.\./' + # Canonicalize the pathname of ld + ac_prog=`$ECHO "$ac_prog"| $SED 's%\\\\%/%g'` + while $ECHO "$ac_prog" | $GREP "$re_direlt" > /dev/null 2>&1; do + ac_prog=`$ECHO $ac_prog| $SED "s%$re_direlt%/%"` + done + test -z "$LD" && LD="$ac_prog" + ;; + "") + # If it fails, then pretend we aren't using GCC. + ac_prog=ld + ;; + *) + # If it is relative, then search for the first ld in PATH. + with_gnu_ld=unknown + ;; + esac +elif test "$with_gnu_ld" = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GNU ld" >&5 +$as_echo_n "checking for GNU ld... " >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for non-GNU ld" >&5 +$as_echo_n "checking for non-GNU ld... " >&6; } +fi +if ${lt_cv_path_LD+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -z "$LD"; then + lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR + for ac_dir in $PATH; do + IFS="$lt_save_ifs" + test -z "$ac_dir" && ac_dir=. + if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then + lt_cv_path_LD="$ac_dir/$ac_prog" + # Check to see if the program is GNU ld. I'd rather use --version, + # but apparently some variants of GNU ld only accept -v. + # Break only if it was the GNU/non-GNU ld that we prefer. + case `"$lt_cv_path_LD" -v 2>&1 &5 +$as_echo "$LD" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi +test -z "$LD" && as_fn_error $? "no acceptable ld found in \$PATH" "$LINENO" 5 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if the linker ($LD) is GNU ld" >&5 +$as_echo_n "checking if the linker ($LD) is GNU ld... " >&6; } +if ${lt_cv_prog_gnu_ld+:} false; then : + $as_echo_n "(cached) " >&6 +else + # I'd rather use --version here, but apparently some GNU lds only accept -v. +case `$LD -v 2>&1 &5 +$as_echo "$lt_cv_prog_gnu_ld" >&6; } +with_gnu_ld=$lt_cv_prog_gnu_ld + + + + + + + + # Check if GNU C++ uses GNU ld as the underlying linker, since the + # archiving commands below assume that GNU ld is being used. + if test "$with_gnu_ld" = yes; then + archive_cmds_CXX='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' + archive_expsym_cmds_CXX='$CC $pic_flag -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + + hardcode_libdir_flag_spec_CXX='${wl}-rpath ${wl}$libdir' + export_dynamic_flag_spec_CXX='${wl}--export-dynamic' + + # If archive_cmds runs LD, not CC, wlarc should be empty + # XXX I think wlarc can be eliminated in ltcf-cxx, but I need to + # investigate it a little bit more. (MM) + wlarc='${wl}' + + # ancient GNU ld didn't support --whole-archive et. al. + if eval "`$CC -print-prog-name=ld` --help 2>&1" | + $GREP 'no-whole-archive' > /dev/null; then + whole_archive_flag_spec_CXX="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' + else + whole_archive_flag_spec_CXX= + fi + else + with_gnu_ld=no + wlarc= + + # A generic and very simple default shared library creation + # command for GNU C++ for the case where it uses the native + # linker, instead of GNU ld. If possible, this setting should + # overridden to take advantage of the native linker features on + # the platform it is being used on. + archive_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' + fi + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' + + else + GXX=no + with_gnu_ld=no + wlarc= + fi + + # PORTME: fill in a description of your system's C++ link characteristics + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the $compiler linker ($LD) supports shared libraries" >&5 +$as_echo_n "checking whether the $compiler linker ($LD) supports shared libraries... " >&6; } + ld_shlibs_CXX=yes + case $host_os in + aix3*) + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + aix[4-9]*) + if test "$host_cpu" = ia64; then + # On IA64, the linker does run time linking by default, so we don't + # have to do anything special. + aix_use_runtimelinking=no + exp_sym_flag='-Bexport' + no_entry_flag="" + else + aix_use_runtimelinking=no + + # Test if we are trying to use run time linking or normal + # AIX style linking. If -brtl is somewhere in LDFLAGS, we + # need to do runtime linking. + case $host_os in aix4.[23]|aix4.[23].*|aix[5-9]*) + for ld_flag in $LDFLAGS; do + case $ld_flag in + *-brtl*) + aix_use_runtimelinking=yes + break + ;; + esac + done + ;; + esac + + exp_sym_flag='-bexport' + no_entry_flag='-bnoentry' + fi + + # When large executables or shared objects are built, AIX ld can + # have problems creating the table of contents. If linking a library + # or program results in "error TOC overflow" add -mminimal-toc to + # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not + # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. + + archive_cmds_CXX='' + hardcode_direct_CXX=yes + hardcode_direct_absolute_CXX=yes + hardcode_libdir_separator_CXX=':' + link_all_deplibs_CXX=yes + file_list_spec_CXX='${wl}-f,' + + if test "$GXX" = yes; then + case $host_os in aix4.[012]|aix4.[012].*) + # We only want to do this on AIX 4.2 and lower, the check + # below for broken collect2 doesn't work under 4.3+ + collect2name=`${CC} -print-prog-name=collect2` + if test -f "$collect2name" && + strings "$collect2name" | $GREP resolve_lib_name >/dev/null + then + # We have reworked collect2 + : + else + # We have old collect2 + hardcode_direct_CXX=unsupported + # It fails to find uninstalled libraries when the uninstalled + # path is not listed in the libpath. Setting hardcode_minus_L + # to unsupported forces relinking + hardcode_minus_L_CXX=yes + hardcode_libdir_flag_spec_CXX='-L$libdir' + hardcode_libdir_separator_CXX= + fi + esac + shared_flag='-shared' + if test "$aix_use_runtimelinking" = yes; then + shared_flag="$shared_flag "'${wl}-G' + fi + else + # not using gcc + if test "$host_cpu" = ia64; then + # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release + # chokes on -Wl,-G. The following line is correct: + shared_flag='-G' + else + if test "$aix_use_runtimelinking" = yes; then + shared_flag='${wl}-G' + else + shared_flag='${wl}-bM:SRE' + fi + fi + fi + + export_dynamic_flag_spec_CXX='${wl}-bexpall' + # It seems that -bexpall does not export symbols beginning with + # underscore (_), so it is better to generate a list of symbols to + # export. + always_export_symbols_CXX=yes + if test "$aix_use_runtimelinking" = yes; then + # Warning - without using the other runtime loading flags (-brtl), + # -berok will link without error, but may produce a broken library. + allow_undefined_flag_CXX='-berok' + # Determine the default libpath from the value encoded in an empty + # executable. + if test "${lt_cv_aix_libpath+set}" = set; then + aix_libpath=$lt_cv_aix_libpath +else + if ${lt_cv_aix_libpath__CXX+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_link "$LINENO"; then : + + lt_aix_libpath_sed=' + /Import File Strings/,/^$/ { + /^0/ { + s/^0 *\([^ ]*\) *$/\1/ + p + } + }' + lt_cv_aix_libpath__CXX=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` + # Check for a 64-bit object if we didn't find anything. + if test -z "$lt_cv_aix_libpath__CXX"; then + lt_cv_aix_libpath__CXX=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` + fi +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + if test -z "$lt_cv_aix_libpath__CXX"; then + lt_cv_aix_libpath__CXX="/usr/lib:/lib" + fi + +fi + + aix_libpath=$lt_cv_aix_libpath__CXX +fi + + hardcode_libdir_flag_spec_CXX='${wl}-blibpath:$libdir:'"$aix_libpath" + + archive_expsym_cmds_CXX='$CC -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then func_echo_all "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag" + else + if test "$host_cpu" = ia64; then + hardcode_libdir_flag_spec_CXX='${wl}-R $libdir:/usr/lib:/lib' + allow_undefined_flag_CXX="-z nodefs" + archive_expsym_cmds_CXX="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$exp_sym_flag:\$export_symbols" + else + # Determine the default libpath from the value encoded in an + # empty executable. + if test "${lt_cv_aix_libpath+set}" = set; then + aix_libpath=$lt_cv_aix_libpath +else + if ${lt_cv_aix_libpath__CXX+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_link "$LINENO"; then : + + lt_aix_libpath_sed=' + /Import File Strings/,/^$/ { + /^0/ { + s/^0 *\([^ ]*\) *$/\1/ + p + } + }' + lt_cv_aix_libpath__CXX=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` + # Check for a 64-bit object if we didn't find anything. + if test -z "$lt_cv_aix_libpath__CXX"; then + lt_cv_aix_libpath__CXX=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e "$lt_aix_libpath_sed"` + fi +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + if test -z "$lt_cv_aix_libpath__CXX"; then + lt_cv_aix_libpath__CXX="/usr/lib:/lib" + fi + +fi + + aix_libpath=$lt_cv_aix_libpath__CXX +fi + + hardcode_libdir_flag_spec_CXX='${wl}-blibpath:$libdir:'"$aix_libpath" + # Warning - without using the other run time loading flags, + # -berok will link without error, but may produce a broken library. + no_undefined_flag_CXX=' ${wl}-bernotok' + allow_undefined_flag_CXX=' ${wl}-berok' + if test "$with_gnu_ld" = yes; then + # We only use this code for GNU lds that support --whole-archive. + whole_archive_flag_spec_CXX='${wl}--whole-archive$convenience ${wl}--no-whole-archive' + else + # Exported symbols can be pulled into shared objects from archives + whole_archive_flag_spec_CXX='$convenience' + fi + archive_cmds_need_lc_CXX=yes + # This is similar to how AIX traditionally builds its shared + # libraries. + archive_expsym_cmds_CXX="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' + fi + fi + ;; + + beos*) + if $LD --help 2>&1 | $GREP ': supported targets:.* elf' > /dev/null; then + allow_undefined_flag_CXX=unsupported + # Joseph Beckenbach says some releases of gcc + # support --undefined. This deserves some investigation. FIXME + archive_cmds_CXX='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + else + ld_shlibs_CXX=no + fi + ;; + + chorus*) + case $cc_basename in + *) + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + esac + ;; + + cygwin* | mingw* | pw32* | cegcc*) + case $GXX,$cc_basename in + ,cl* | no,cl*) + # Native MSVC + # hardcode_libdir_flag_spec is actually meaningless, as there is + # no search path for DLLs. + hardcode_libdir_flag_spec_CXX=' ' + allow_undefined_flag_CXX=unsupported + always_export_symbols_CXX=yes + file_list_spec_CXX='@' + # Tell ltmain to make .lib files, not .a files. + libext=lib + # Tell ltmain to make .dll files, not .so files. + shrext_cmds=".dll" + # FIXME: Setting linknames here is a bad hack. + archive_cmds_CXX='$CC -o $output_objdir/$soname $libobjs $compiler_flags $deplibs -Wl,-dll~linknames=' + archive_expsym_cmds_CXX='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then + $SED -n -e 's/\\\\\\\(.*\\\\\\\)/-link\\\ -EXPORT:\\\\\\\1/' -e '1\\\!p' < $export_symbols > $output_objdir/$soname.exp; + else + $SED -e 's/\\\\\\\(.*\\\\\\\)/-link\\\ -EXPORT:\\\\\\\1/' < $export_symbols > $output_objdir/$soname.exp; + fi~ + $CC -o $tool_output_objdir$soname $libobjs $compiler_flags $deplibs "@$tool_output_objdir$soname.exp" -Wl,-DLL,-IMPLIB:"$tool_output_objdir$libname.dll.lib"~ + linknames=' + # The linker will not automatically build a static lib if we build a DLL. + # _LT_TAGVAR(old_archive_from_new_cmds, CXX)='true' + enable_shared_with_static_runtimes_CXX=yes + # Don't use ranlib + old_postinstall_cmds_CXX='chmod 644 $oldlib' + postlink_cmds_CXX='lt_outputfile="@OUTPUT@"~ + lt_tool_outputfile="@TOOL_OUTPUT@"~ + case $lt_outputfile in + *.exe|*.EXE) ;; + *) + lt_outputfile="$lt_outputfile.exe" + lt_tool_outputfile="$lt_tool_outputfile.exe" + ;; + esac~ + func_to_tool_file "$lt_outputfile"~ + if test "$MANIFEST_TOOL" != ":" && test -f "$lt_outputfile.manifest"; then + $MANIFEST_TOOL -manifest "$lt_tool_outputfile.manifest" -outputresource:"$lt_tool_outputfile" || exit 1; + $RM "$lt_outputfile.manifest"; + fi' + ;; + *) + # g++ + # _LT_TAGVAR(hardcode_libdir_flag_spec, CXX) is actually meaningless, + # as there is no search path for DLLs. + hardcode_libdir_flag_spec_CXX='-L$libdir' + export_dynamic_flag_spec_CXX='${wl}--export-all-symbols' + allow_undefined_flag_CXX=unsupported + always_export_symbols_CXX=no + enable_shared_with_static_runtimes_CXX=yes + + if $LD --help 2>&1 | $GREP 'auto-import' > /dev/null; then + archive_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + # If the export-symbols file already is a .def file (1st line + # is EXPORTS), use it as is; otherwise, prepend... + archive_expsym_cmds_CXX='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then + cp $export_symbols $output_objdir/$soname.def; + else + echo EXPORTS > $output_objdir/$soname.def; + cat $export_symbols >> $output_objdir/$soname.def; + fi~ + $CC -shared -nostdlib $output_objdir/$soname.def $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--enable-auto-image-base -Xlinker --out-implib -Xlinker $lib' + else + ld_shlibs_CXX=no + fi + ;; + esac + ;; + darwin* | rhapsody*) + + + archive_cmds_need_lc_CXX=no + hardcode_direct_CXX=no + hardcode_automatic_CXX=yes + hardcode_shlibpath_var_CXX=unsupported + if test "$lt_cv_ld_force_load" = "yes"; then + whole_archive_flag_spec_CXX='`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience ${wl}-force_load,$conv\"; done; func_echo_all \"$new_convenience\"`' + else + whole_archive_flag_spec_CXX='' + fi + link_all_deplibs_CXX=yes + allow_undefined_flag_CXX="$_lt_dar_allow_undefined" + case $cc_basename in + ifort*) _lt_dar_can_shared=yes ;; + *) _lt_dar_can_shared=$GCC ;; + esac + if test "$_lt_dar_can_shared" = "yes"; then + output_verbose_link_cmd=func_echo_all + archive_cmds_CXX="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod${_lt_dsymutil}" + module_cmds_CXX="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dsymutil}" + archive_expsym_cmds_CXX="sed 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring ${_lt_dar_single_mod}${_lt_dar_export_syms}${_lt_dsymutil}" + module_expsym_cmds_CXX="sed -e 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dar_export_syms}${_lt_dsymutil}" + if test "$lt_cv_apple_cc_single_mod" != "yes"; then + archive_cmds_CXX="\$CC -r -keep_private_externs -nostdlib -o \${lib}-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \${lib}-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring${_lt_dsymutil}" + archive_expsym_cmds_CXX="sed 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC -r -keep_private_externs -nostdlib -o \${lib}-master.o \$libobjs~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \${lib}-master.o \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring${_lt_dar_export_syms}${_lt_dsymutil}" + fi + + else + ld_shlibs_CXX=no + fi + + ;; + + dgux*) + case $cc_basename in + ec++*) + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + ghcx*) + # Green Hills C++ Compiler + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + *) + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + esac + ;; + + freebsd[12]*) + # C++ shared libraries reported to be fairly broken before + # switch to ELF + ld_shlibs_CXX=no + ;; + + freebsd-elf*) + archive_cmds_need_lc_CXX=no + ;; + + freebsd* | dragonfly*) + # FreeBSD 3 and later use GNU C++ and GNU ld with standard ELF + # conventions + ld_shlibs_CXX=yes + ;; + + gnu*) + ;; + + haiku*) + archive_cmds_CXX='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + link_all_deplibs_CXX=yes + ;; + + hpux9*) + hardcode_libdir_flag_spec_CXX='${wl}+b ${wl}$libdir' + hardcode_libdir_separator_CXX=: + export_dynamic_flag_spec_CXX='${wl}-E' + hardcode_direct_CXX=yes + hardcode_minus_L_CXX=yes # Not in the search PATH, + # but as the default + # location of the library. + + case $cc_basename in + CC*) + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + aCC*) + archive_cmds_CXX='$RM $output_objdir/$soname~$CC -b ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $EGREP "\-L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' + ;; + *) + if test "$GXX" = yes; then + archive_cmds_CXX='$RM $output_objdir/$soname~$CC -shared -nostdlib $pic_flag ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' + else + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + fi + ;; + esac + ;; + + hpux10*|hpux11*) + if test $with_gnu_ld = no; then + hardcode_libdir_flag_spec_CXX='${wl}+b ${wl}$libdir' + hardcode_libdir_separator_CXX=: + + case $host_cpu in + hppa*64*|ia64*) + ;; + *) + export_dynamic_flag_spec_CXX='${wl}-E' + ;; + esac + fi + case $host_cpu in + hppa*64*|ia64*) + hardcode_direct_CXX=no + hardcode_shlibpath_var_CXX=no + ;; + *) + hardcode_direct_CXX=yes + hardcode_direct_absolute_CXX=yes + hardcode_minus_L_CXX=yes # Not in the search PATH, + # but as the default + # location of the library. + ;; + esac + + case $cc_basename in + CC*) + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + aCC*) + case $host_cpu in + hppa*64*) + archive_cmds_CXX='$CC -b ${wl}+h ${wl}$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + ia64*) + archive_cmds_CXX='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + *) + archive_cmds_CXX='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + esac + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $GREP "\-L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' + ;; + *) + if test "$GXX" = yes; then + if test $with_gnu_ld = no; then + case $host_cpu in + hppa*64*) + archive_cmds_CXX='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + ia64*) + archive_cmds_CXX='$CC -shared -nostdlib $pic_flag ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + *) + archive_cmds_CXX='$CC -shared -nostdlib $pic_flag ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + esac + fi + else + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + fi + ;; + esac + ;; + + interix[3-9]*) + hardcode_direct_CXX=no + hardcode_shlibpath_var_CXX=no + hardcode_libdir_flag_spec_CXX='${wl}-rpath,$libdir' + export_dynamic_flag_spec_CXX='${wl}-E' + # Hack: On Interix 3.x, we cannot compile PIC because of a broken gcc. + # Instead, shared libraries are loaded at an image base (0x10000000 by + # default) and relocated if they conflict, which is a slow very memory + # consuming and fragmenting process. To avoid this, we pick a random, + # 256 KiB-aligned image base between 0x50000000 and 0x6FFC0000 at link + # time. Moving up from 0x10000000 also allows more sbrk(2) space. + archive_cmds_CXX='$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + archive_expsym_cmds_CXX='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' + ;; + irix5* | irix6*) + case $cc_basename in + CC*) + # SGI C++ + archive_cmds_CXX='$CC -shared -all -multigot $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' + + # Archives containing C++ object files must be created using + # "CC -ar", where "CC" is the IRIX C++ compiler. This is + # necessary to make sure instantiated templates are included + # in the archive. + old_archive_cmds_CXX='$CC -ar -WR,-u -o $oldlib $oldobjs' + ;; + *) + if test "$GXX" = yes; then + if test "$with_gnu_ld" = no; then + archive_cmds_CXX='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + else + archive_cmds_CXX='$CC -shared $pic_flag -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` -o $lib' + fi + fi + link_all_deplibs_CXX=yes + ;; + esac + hardcode_libdir_flag_spec_CXX='${wl}-rpath ${wl}$libdir' + hardcode_libdir_separator_CXX=: + inherit_rpath_CXX=yes + ;; + + linux* | k*bsd*-gnu | kopensolaris*-gnu) + case $cc_basename in + KCC*) + # Kuck and Associates, Inc. (KAI) C++ Compiler + + # KCC will only create a shared library if the output file + # ends with ".so" (or ".sl" for HP-UX), so rename the library + # to its proper name (with version) after linking. + archive_cmds_CXX='tempext=`echo $shared_ext | $SED -e '\''s/\([^()0-9A-Za-z{}]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' + archive_expsym_cmds_CXX='tempext=`echo $shared_ext | $SED -e '\''s/\([^()0-9A-Za-z{}]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib ${wl}-retain-symbols-file,$export_symbols; mv \$templib $lib' + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`$CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 | $GREP "ld"`; rm -f libconftest$shared_ext; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' + + hardcode_libdir_flag_spec_CXX='${wl}-rpath,$libdir' + export_dynamic_flag_spec_CXX='${wl}--export-dynamic' + + # Archives containing C++ object files must be created using + # "CC -Bstatic", where "CC" is the KAI C++ compiler. + old_archive_cmds_CXX='$CC -Bstatic -o $oldlib $oldobjs' + ;; + icpc* | ecpc* ) + # Intel C++ + with_gnu_ld=yes + # version 8.0 and above of icpc choke on multiply defined symbols + # if we add $predep_objects and $postdep_objects, however 7.1 and + # earlier do not add the objects themselves. + case `$CC -V 2>&1` in + *"Version 7."*) + archive_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' + archive_expsym_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + ;; + *) # Version 8.0 or newer + tmp_idyn= + case $host_cpu in + ia64*) tmp_idyn=' -i_dynamic';; + esac + archive_cmds_CXX='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + archive_expsym_cmds_CXX='$CC -shared'"$tmp_idyn"' $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + ;; + esac + archive_cmds_need_lc_CXX=no + hardcode_libdir_flag_spec_CXX='${wl}-rpath,$libdir' + export_dynamic_flag_spec_CXX='${wl}--export-dynamic' + whole_archive_flag_spec_CXX='${wl}--whole-archive$convenience ${wl}--no-whole-archive' + ;; + pgCC* | pgcpp*) + # Portland Group C++ compiler + case `$CC -V` in + *pgCC\ [1-5].* | *pgcpp\ [1-5].*) + prelink_cmds_CXX='tpldir=Template.dir~ + rm -rf $tpldir~ + $CC --prelink_objects --instantiation_dir $tpldir $objs $libobjs $compile_deplibs~ + compile_command="$compile_command `find $tpldir -name \*.o | sort | $NL2SP`"' + old_archive_cmds_CXX='tpldir=Template.dir~ + rm -rf $tpldir~ + $CC --prelink_objects --instantiation_dir $tpldir $oldobjs$old_deplibs~ + $AR $AR_FLAGS $oldlib$oldobjs$old_deplibs `find $tpldir -name \*.o | sort | $NL2SP`~ + $RANLIB $oldlib' + archive_cmds_CXX='tpldir=Template.dir~ + rm -rf $tpldir~ + $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~ + $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | $NL2SP` $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname -o $lib' + archive_expsym_cmds_CXX='tpldir=Template.dir~ + rm -rf $tpldir~ + $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~ + $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | $NL2SP` $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname ${wl}-retain-symbols-file ${wl}$export_symbols -o $lib' + ;; + *) # Version 6 and above use weak symbols + archive_cmds_CXX='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname -o $lib' + archive_expsym_cmds_CXX='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname ${wl}-retain-symbols-file ${wl}$export_symbols -o $lib' + ;; + esac + + hardcode_libdir_flag_spec_CXX='${wl}--rpath ${wl}$libdir' + export_dynamic_flag_spec_CXX='${wl}--export-dynamic' + whole_archive_flag_spec_CXX='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' + ;; + cxx*) + # Compaq C++ + archive_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' + archive_expsym_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib ${wl}-retain-symbols-file $wl$export_symbols' + + runpath_var=LD_RUN_PATH + hardcode_libdir_flag_spec_CXX='-rpath $libdir' + hardcode_libdir_separator_CXX=: + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld"`; templist=`func_echo_all "$templist" | $SED "s/\(^.*ld.*\)\( .*ld .*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "X$list" | $Xsed' + ;; + xl* | mpixl* | bgxl*) + # IBM XL 8.0 on PPC, with GNU ld + hardcode_libdir_flag_spec_CXX='${wl}-rpath ${wl}$libdir' + export_dynamic_flag_spec_CXX='${wl}--export-dynamic' + archive_cmds_CXX='$CC -qmkshrobj $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + if test "x$supports_anon_versioning" = xyes; then + archive_expsym_cmds_CXX='echo "{ global:" > $output_objdir/$libname.ver~ + cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ + echo "local: *; };" >> $output_objdir/$libname.ver~ + $CC -qmkshrobj $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib' + fi + ;; + *) + case `$CC -V 2>&1 | sed 5q` in + *Sun\ C*) + # Sun C++ 5.9 + no_undefined_flag_CXX=' -zdefs' + archive_cmds_CXX='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + archive_expsym_cmds_CXX='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-retain-symbols-file ${wl}$export_symbols' + hardcode_libdir_flag_spec_CXX='-R$libdir' + whole_archive_flag_spec_CXX='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' + compiler_needs_object_CXX=yes + + # Not sure whether something based on + # $CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 + # would be better. + output_verbose_link_cmd='func_echo_all' + + # Archives containing C++ object files must be created using + # "CC -xar", where "CC" is the Sun C++ compiler. This is + # necessary to make sure instantiated templates are included + # in the archive. + old_archive_cmds_CXX='$CC -xar -o $oldlib $oldobjs' + ;; + esac + ;; + esac + ;; + + lynxos*) + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + + m88k*) + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + + mvs*) + case $cc_basename in + cxx*) + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + *) + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + esac + ;; + + netbsd*) + if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then + archive_cmds_CXX='$LD -Bshareable -o $lib $predep_objects $libobjs $deplibs $postdep_objects $linker_flags' + wlarc= + hardcode_libdir_flag_spec_CXX='-R$libdir' + hardcode_direct_CXX=yes + hardcode_shlibpath_var_CXX=no + fi + # Workaround some broken pre-1.5 toolchains + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP conftest.$objext | $SED -e "s:-lgcc -lc -lgcc::"' + ;; + + *nto* | *qnx*) + ld_shlibs_CXX=yes + ;; + + openbsd2*) + # C++ shared libraries are fairly broken + ld_shlibs_CXX=no + ;; + + openbsd*) + if test -f /usr/libexec/ld.so; then + hardcode_direct_CXX=yes + hardcode_shlibpath_var_CXX=no + hardcode_direct_absolute_CXX=yes + archive_cmds_CXX='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' + hardcode_libdir_flag_spec_CXX='${wl}-rpath,$libdir' + if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + archive_expsym_cmds_CXX='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-retain-symbols-file,$export_symbols -o $lib' + export_dynamic_flag_spec_CXX='${wl}-E' + whole_archive_flag_spec_CXX="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' + fi + output_verbose_link_cmd=func_echo_all + else + ld_shlibs_CXX=no + fi + ;; + + osf3* | osf4* | osf5*) + case $cc_basename in + KCC*) + # Kuck and Associates, Inc. (KAI) C++ Compiler + + # KCC will only create a shared library if the output file + # ends with ".so" (or ".sl" for HP-UX), so rename the library + # to its proper name (with version) after linking. + archive_cmds_CXX='tempext=`echo $shared_ext | $SED -e '\''s/\([^()0-9A-Za-z{}]\)/\\\\\1/g'\''`; templib=`echo "$lib" | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' + + hardcode_libdir_flag_spec_CXX='${wl}-rpath,$libdir' + hardcode_libdir_separator_CXX=: + + # Archives containing C++ object files must be created using + # the KAI C++ compiler. + case $host in + osf3*) old_archive_cmds_CXX='$CC -Bstatic -o $oldlib $oldobjs' ;; + *) old_archive_cmds_CXX='$CC -o $oldlib $oldobjs' ;; + esac + ;; + RCC*) + # Rational C++ 2.4.1 + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + cxx*) + case $host in + osf3*) + allow_undefined_flag_CXX=' ${wl}-expect_unresolved ${wl}\*' + archive_cmds_CXX='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $soname `test -n "$verstring" && func_echo_all "${wl}-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' + hardcode_libdir_flag_spec_CXX='${wl}-rpath ${wl}$libdir' + ;; + *) + allow_undefined_flag_CXX=' -expect_unresolved \*' + archive_cmds_CXX='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' + archive_expsym_cmds_CXX='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done~ + echo "-hidden">> $lib.exp~ + $CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname ${wl}-input ${wl}$lib.exp `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib~ + $RM $lib.exp' + hardcode_libdir_flag_spec_CXX='-rpath $libdir' + ;; + esac + + hardcode_libdir_separator_CXX=: + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld" | $GREP -v "ld:"`; templist=`func_echo_all "$templist" | $SED "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' + ;; + *) + if test "$GXX" = yes && test "$with_gnu_ld" = no; then + allow_undefined_flag_CXX=' ${wl}-expect_unresolved ${wl}\*' + case $host in + osf3*) + archive_cmds_CXX='$CC -shared -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + ;; + *) + archive_cmds_CXX='$CC -shared $pic_flag -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + ;; + esac + + hardcode_libdir_flag_spec_CXX='${wl}-rpath ${wl}$libdir' + hardcode_libdir_separator_CXX=: + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' + + else + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + fi + ;; + esac + ;; + + psos*) + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + + sunos4*) + case $cc_basename in + CC*) + # Sun C++ 4.x + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + lcc*) + # Lucid + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + *) + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + esac + ;; + + solaris*) + case $cc_basename in + CC* | sunCC*) + # Sun C++ 4.2, 5.x and Centerline C++ + archive_cmds_need_lc_CXX=yes + no_undefined_flag_CXX=' -zdefs' + archive_cmds_CXX='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + archive_expsym_cmds_CXX='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $CC -G${allow_undefined_flag} ${wl}-M ${wl}$lib.exp -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' + + hardcode_libdir_flag_spec_CXX='-R$libdir' + hardcode_shlibpath_var_CXX=no + case $host_os in + solaris2.[0-5] | solaris2.[0-5].*) ;; + *) + # The compiler driver will combine and reorder linker options, + # but understands `-z linker_flag'. + # Supported since Solaris 2.6 (maybe 2.5.1?) + whole_archive_flag_spec_CXX='-z allextract$convenience -z defaultextract' + ;; + esac + link_all_deplibs_CXX=yes + + output_verbose_link_cmd='func_echo_all' + + # Archives containing C++ object files must be created using + # "CC -xar", where "CC" is the Sun C++ compiler. This is + # necessary to make sure instantiated templates are included + # in the archive. + old_archive_cmds_CXX='$CC -xar -o $oldlib $oldobjs' + ;; + gcx*) + # Green Hills C++ Compiler + archive_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' + + # The C++ compiler must be used to create the archive. + old_archive_cmds_CXX='$CC $LDFLAGS -archive -o $oldlib $oldobjs' + ;; + *) + # GNU C++ compiler with Solaris linker + if test "$GXX" = yes && test "$with_gnu_ld" = no; then + no_undefined_flag_CXX=' ${wl}-z ${wl}defs' + if $CC --version | $GREP -v '^2\.7' > /dev/null; then + archive_cmds_CXX='$CC -shared $pic_flag -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' + archive_expsym_cmds_CXX='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $CC -shared $pic_flag -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' + else + # g++ 2.7 appears to require `-G' NOT `-shared' on this + # platform. + archive_cmds_CXX='$CC -G -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' + archive_expsym_cmds_CXX='echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~echo "local: *; };" >> $lib.exp~ + $CC -G -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$RM $lib.exp' + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd='$CC -G $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' + fi + + hardcode_libdir_flag_spec_CXX='${wl}-R $wl$libdir' + case $host_os in + solaris2.[0-5] | solaris2.[0-5].*) ;; + *) + whole_archive_flag_spec_CXX='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract' + ;; + esac + fi + ;; + esac + ;; + + sysv4*uw2* | sysv5OpenUNIX* | sysv5UnixWare7.[01].[10]* | unixware7* | sco3.2v5.0.[024]*) + no_undefined_flag_CXX='${wl}-z,text' + archive_cmds_need_lc_CXX=no + hardcode_shlibpath_var_CXX=no + runpath_var='LD_RUN_PATH' + + case $cc_basename in + CC*) + archive_cmds_CXX='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds_CXX='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + archive_cmds_CXX='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds_CXX='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + ;; + + sysv5* | sco3.2v5* | sco5v6*) + # Note: We can NOT use -z defs as we might desire, because we do not + # link with -lc, and that would cause any symbols used from libc to + # always be unresolved, which means just about no library would + # ever link correctly. If we're not using GNU ld we use -z text + # though, which does catch some bad symbols but isn't as heavy-handed + # as -z defs. + no_undefined_flag_CXX='${wl}-z,text' + allow_undefined_flag_CXX='${wl}-z,nodefs' + archive_cmds_need_lc_CXX=no + hardcode_shlibpath_var_CXX=no + hardcode_libdir_flag_spec_CXX='${wl}-R,$libdir' + hardcode_libdir_separator_CXX=':' + link_all_deplibs_CXX=yes + export_dynamic_flag_spec_CXX='${wl}-Bexport' + runpath_var='LD_RUN_PATH' + + case $cc_basename in + CC*) + archive_cmds_CXX='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds_CXX='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + old_archive_cmds_CXX='$CC -Tprelink_objects $oldobjs~ + '"$old_archive_cmds_CXX" + reload_cmds_CXX='$CC -Tprelink_objects $reload_objs~ + '"$reload_cmds_CXX" + ;; + *) + archive_cmds_CXX='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds_CXX='$CC -shared ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + ;; + + tandem*) + case $cc_basename in + NCC*) + # NonStop-UX NCC 3.20 + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + *) + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + esac + ;; + + vxworks*) + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + + *) + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + esac + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ld_shlibs_CXX" >&5 +$as_echo "$ld_shlibs_CXX" >&6; } + test "$ld_shlibs_CXX" = no && can_build_shared=no + + GCC_CXX="$GXX" + LD_CXX="$LD" + + ## CAVEAT EMPTOR: + ## There is no encapsulation within the following macros, do not change + ## the running order or otherwise move them around unless you know exactly + ## what you are doing... + # Dependencies to place before and after the object being linked: +predep_objects_CXX= +postdep_objects_CXX= +predeps_CXX= +postdeps_CXX= +compiler_lib_search_path_CXX= + +cat > conftest.$ac_ext <<_LT_EOF +class Foo +{ +public: + Foo (void) { a = 0; } +private: + int a; +}; +_LT_EOF + + +_lt_libdeps_save_CFLAGS=$CFLAGS +case "$CC $CFLAGS " in #( +*\ -flto*\ *) CFLAGS="$CFLAGS -fno-lto" ;; +*\ -fwhopr*\ *) CFLAGS="$CFLAGS -fno-whopr" ;; +esac + +if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + # Parse the compiler output and extract the necessary + # objects, libraries and library flags. + + # Sentinel used to keep track of whether or not we are before + # the conftest object file. + pre_test_object_deps_done=no + + for p in `eval "$output_verbose_link_cmd"`; do + case ${prev}${p} in + + -L* | -R* | -l*) + # Some compilers place space between "-{L,R}" and the path. + # Remove the space. + if test $p = "-L" || + test $p = "-R"; then + prev=$p + continue + fi + + # Expand the sysroot to ease extracting the directories later. + if test -z "$prev"; then + case $p in + -L*) func_stripname_cnf '-L' '' "$p"; prev=-L; p=$func_stripname_result ;; + -R*) func_stripname_cnf '-R' '' "$p"; prev=-R; p=$func_stripname_result ;; + -l*) func_stripname_cnf '-l' '' "$p"; prev=-l; p=$func_stripname_result ;; + esac + fi + case $p in + =*) func_stripname_cnf '=' '' "$p"; p=$lt_sysroot$func_stripname_result ;; + esac + if test "$pre_test_object_deps_done" = no; then + case ${prev} in + -L | -R) + # Internal compiler library paths should come after those + # provided the user. The postdeps already come after the + # user supplied libs so there is no need to process them. + if test -z "$compiler_lib_search_path_CXX"; then + compiler_lib_search_path_CXX="${prev}${p}" + else + compiler_lib_search_path_CXX="${compiler_lib_search_path_CXX} ${prev}${p}" + fi + ;; + # The "-l" case would never come before the object being + # linked, so don't bother handling this case. + esac + else + if test -z "$postdeps_CXX"; then + postdeps_CXX="${prev}${p}" + else + postdeps_CXX="${postdeps_CXX} ${prev}${p}" + fi + fi + prev= + ;; + + *.lto.$objext) ;; # Ignore GCC LTO objects + *.$objext) + # This assumes that the test object file only shows up + # once in the compiler output. + if test "$p" = "conftest.$objext"; then + pre_test_object_deps_done=yes + continue + fi + + if test "$pre_test_object_deps_done" = no; then + if test -z "$predep_objects_CXX"; then + predep_objects_CXX="$p" + else + predep_objects_CXX="$predep_objects_CXX $p" + fi + else + if test -z "$postdep_objects_CXX"; then + postdep_objects_CXX="$p" + else + postdep_objects_CXX="$postdep_objects_CXX $p" + fi + fi + ;; + + *) ;; # Ignore the rest. + + esac + done + + # Clean up. + rm -f a.out a.exe +else + echo "libtool.m4: error: problem compiling CXX test program" +fi + +$RM -f confest.$objext +CFLAGS=$_lt_libdeps_save_CFLAGS + +# PORTME: override above test on systems where it is broken +case $host_os in +interix[3-9]*) + # Interix 3.5 installs completely hosed .la files for C++, so rather than + # hack all around it, let's just trust "g++" to DTRT. + predep_objects_CXX= + postdep_objects_CXX= + postdeps_CXX= + ;; + +linux*) + case `$CC -V 2>&1 | sed 5q` in + *Sun\ C*) + # Sun C++ 5.9 + + # The more standards-conforming stlport4 library is + # incompatible with the Cstd library. Avoid specifying + # it if it's in CXXFLAGS. Ignore libCrun as + # -library=stlport4 depends on it. + case " $CXX $CXXFLAGS " in + *" -library=stlport4 "*) + solaris_use_stlport4=yes + ;; + esac + + if test "$solaris_use_stlport4" != yes; then + postdeps_CXX='-library=Cstd -library=Crun' + fi + ;; + esac + ;; + +solaris*) + case $cc_basename in + CC* | sunCC*) + # The more standards-conforming stlport4 library is + # incompatible with the Cstd library. Avoid specifying + # it if it's in CXXFLAGS. Ignore libCrun as + # -library=stlport4 depends on it. + case " $CXX $CXXFLAGS " in + *" -library=stlport4 "*) + solaris_use_stlport4=yes + ;; + esac + + # Adding this requires a known-good setup of shared libraries for + # Sun compiler versions before 5.6, else PIC objects from an old + # archive will be linked into the output, leading to subtle bugs. + if test "$solaris_use_stlport4" != yes; then + postdeps_CXX='-library=Cstd -library=Crun' + fi + ;; + esac + ;; +esac + + +case " $postdeps_CXX " in +*" -lc "*) archive_cmds_need_lc_CXX=no ;; +esac + compiler_lib_search_dirs_CXX= +if test -n "${compiler_lib_search_path_CXX}"; then + compiler_lib_search_dirs_CXX=`echo " ${compiler_lib_search_path_CXX}" | ${SED} -e 's! -L! !g' -e 's!^ !!'` +fi + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + lt_prog_compiler_wl_CXX= +lt_prog_compiler_pic_CXX= +lt_prog_compiler_static_CXX= + + + # C++ specific cases for pic, static, wl, etc. + if test "$GXX" = yes; then + lt_prog_compiler_wl_CXX='-Wl,' + lt_prog_compiler_static_CXX='-static' + + case $host_os in + aix*) + # All AIX code is PIC. + if test "$host_cpu" = ia64; then + # AIX 5 now supports IA64 processor + lt_prog_compiler_static_CXX='-Bstatic' + fi + ;; + + amigaos*) + case $host_cpu in + powerpc) + # see comment about AmigaOS4 .so support + lt_prog_compiler_pic_CXX='-fPIC' + ;; + m68k) + # FIXME: we need at least 68020 code to build shared libraries, but + # adding the `-m68020' flag to GCC prevents building anything better, + # like `-m68040'. + lt_prog_compiler_pic_CXX='-m68020 -resident32 -malways-restore-a4' + ;; + esac + ;; + + beos* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) + # PIC is the default for these OSes. + ;; + mingw* | cygwin* | os2* | pw32* | cegcc*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + # Although the cygwin gcc ignores -fPIC, still need this for old-style + # (--disable-auto-import) libraries + lt_prog_compiler_pic_CXX='-DDLL_EXPORT' + ;; + darwin* | rhapsody*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + lt_prog_compiler_pic_CXX='-fno-common' + ;; + *djgpp*) + # DJGPP does not support shared libraries at all + lt_prog_compiler_pic_CXX= + ;; + haiku*) + # PIC is the default for Haiku. + # The "-static" flag exists, but is broken. + lt_prog_compiler_static_CXX= + ;; + interix[3-9]*) + # Interix 3.x gcc -fpic/-fPIC options generate broken code. + # Instead, we relocate shared libraries at runtime. + ;; + sysv4*MP*) + if test -d /usr/nec; then + lt_prog_compiler_pic_CXX=-Kconform_pic + fi + ;; + hpux*) + # PIC is the default for 64-bit PA HP-UX, but not for 32-bit + # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag + # sets the default TLS model and affects inlining. + case $host_cpu in + hppa*64*) + ;; + *) + lt_prog_compiler_pic_CXX='-fPIC' + ;; + esac + ;; + *qnx* | *nto*) + # QNX uses GNU C++, but need to define -shared option too, otherwise + # it will coredump. + lt_prog_compiler_pic_CXX='-fPIC -shared' + ;; + *) + lt_prog_compiler_pic_CXX='-fPIC' + ;; + esac + else + case $host_os in + aix[4-9]*) + # All AIX code is PIC. + if test "$host_cpu" = ia64; then + # AIX 5 now supports IA64 processor + lt_prog_compiler_static_CXX='-Bstatic' + else + lt_prog_compiler_static_CXX='-bnso -bI:/lib/syscalls.exp' + fi + ;; + chorus*) + case $cc_basename in + cxch68*) + # Green Hills C++ Compiler + # _LT_TAGVAR(lt_prog_compiler_static, CXX)="--no_auto_instantiation -u __main -u __premain -u _abort -r $COOL_DIR/lib/libOrb.a $MVME_DIR/lib/CC/libC.a $MVME_DIR/lib/classix/libcx.s.a" + ;; + esac + ;; + mingw* | cygwin* | os2* | pw32* | cegcc*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + lt_prog_compiler_pic_CXX='-DDLL_EXPORT' + ;; + dgux*) + case $cc_basename in + ec++*) + lt_prog_compiler_pic_CXX='-KPIC' + ;; + ghcx*) + # Green Hills C++ Compiler + lt_prog_compiler_pic_CXX='-pic' + ;; + *) + ;; + esac + ;; + freebsd* | dragonfly*) + # FreeBSD uses GNU C++ + ;; + hpux9* | hpux10* | hpux11*) + case $cc_basename in + CC*) + lt_prog_compiler_wl_CXX='-Wl,' + lt_prog_compiler_static_CXX='${wl}-a ${wl}archive' + if test "$host_cpu" != ia64; then + lt_prog_compiler_pic_CXX='+Z' + fi + ;; + aCC*) + lt_prog_compiler_wl_CXX='-Wl,' + lt_prog_compiler_static_CXX='${wl}-a ${wl}archive' + case $host_cpu in + hppa*64*|ia64*) + # +Z the default + ;; + *) + lt_prog_compiler_pic_CXX='+Z' + ;; + esac + ;; + *) + ;; + esac + ;; + interix*) + # This is c89, which is MS Visual C++ (no shared libs) + # Anyone wants to do a port? + ;; + irix5* | irix6* | nonstopux*) + case $cc_basename in + CC*) + lt_prog_compiler_wl_CXX='-Wl,' + lt_prog_compiler_static_CXX='-non_shared' + # CC pic flag -KPIC is the default. + ;; + *) + ;; + esac + ;; + linux* | k*bsd*-gnu | kopensolaris*-gnu) + case $cc_basename in + KCC*) + # KAI C++ Compiler + lt_prog_compiler_wl_CXX='--backend -Wl,' + lt_prog_compiler_pic_CXX='-fPIC' + ;; + ecpc* ) + # old Intel C++ for x86_64 which still supported -KPIC. + lt_prog_compiler_wl_CXX='-Wl,' + lt_prog_compiler_pic_CXX='-KPIC' + lt_prog_compiler_static_CXX='-static' + ;; + icpc* ) + # Intel C++, used to be incompatible with GCC. + # ICC 10 doesn't accept -KPIC any more. + lt_prog_compiler_wl_CXX='-Wl,' + lt_prog_compiler_pic_CXX='-fPIC' + lt_prog_compiler_static_CXX='-static' + ;; + pgCC* | pgcpp*) + # Portland Group C++ compiler + lt_prog_compiler_wl_CXX='-Wl,' + lt_prog_compiler_pic_CXX='-fpic' + lt_prog_compiler_static_CXX='-Bstatic' + ;; + cxx*) + # Compaq C++ + # Make sure the PIC flag is empty. It appears that all Alpha + # Linux and Compaq Tru64 Unix objects are PIC. + lt_prog_compiler_pic_CXX= + lt_prog_compiler_static_CXX='-non_shared' + ;; + xlc* | xlC* | bgxl[cC]* | mpixl[cC]*) + # IBM XL 8.0, 9.0 on PPC and BlueGene + lt_prog_compiler_wl_CXX='-Wl,' + lt_prog_compiler_pic_CXX='-qpic' + lt_prog_compiler_static_CXX='-qstaticlink' + ;; + *) + case `$CC -V 2>&1 | sed 5q` in + *Sun\ C*) + # Sun C++ 5.9 + lt_prog_compiler_pic_CXX='-KPIC' + lt_prog_compiler_static_CXX='-Bstatic' + lt_prog_compiler_wl_CXX='-Qoption ld ' + ;; + esac + ;; + esac + ;; + lynxos*) + ;; + m88k*) + ;; + mvs*) + case $cc_basename in + cxx*) + lt_prog_compiler_pic_CXX='-W c,exportall' + ;; + *) + ;; + esac + ;; + netbsd*) + ;; + *qnx* | *nto*) + # QNX uses GNU C++, but need to define -shared option too, otherwise + # it will coredump. + lt_prog_compiler_pic_CXX='-fPIC -shared' + ;; + osf3* | osf4* | osf5*) + case $cc_basename in + KCC*) + lt_prog_compiler_wl_CXX='--backend -Wl,' + ;; + RCC*) + # Rational C++ 2.4.1 + lt_prog_compiler_pic_CXX='-pic' + ;; + cxx*) + # Digital/Compaq C++ + lt_prog_compiler_wl_CXX='-Wl,' + # Make sure the PIC flag is empty. It appears that all Alpha + # Linux and Compaq Tru64 Unix objects are PIC. + lt_prog_compiler_pic_CXX= + lt_prog_compiler_static_CXX='-non_shared' + ;; + *) + ;; + esac + ;; + psos*) + ;; + solaris*) + case $cc_basename in + CC* | sunCC*) + # Sun C++ 4.2, 5.x and Centerline C++ + lt_prog_compiler_pic_CXX='-KPIC' + lt_prog_compiler_static_CXX='-Bstatic' + lt_prog_compiler_wl_CXX='-Qoption ld ' + ;; + gcx*) + # Green Hills C++ Compiler + lt_prog_compiler_pic_CXX='-PIC' + ;; + *) + ;; + esac + ;; + sunos4*) + case $cc_basename in + CC*) + # Sun C++ 4.x + lt_prog_compiler_pic_CXX='-pic' + lt_prog_compiler_static_CXX='-Bstatic' + ;; + lcc*) + # Lucid + lt_prog_compiler_pic_CXX='-pic' + ;; + *) + ;; + esac + ;; + sysv5* | unixware* | sco3.2v5* | sco5v6* | OpenUNIX*) + case $cc_basename in + CC*) + lt_prog_compiler_wl_CXX='-Wl,' + lt_prog_compiler_pic_CXX='-KPIC' + lt_prog_compiler_static_CXX='-Bstatic' + ;; + esac + ;; + tandem*) + case $cc_basename in + NCC*) + # NonStop-UX NCC 3.20 + lt_prog_compiler_pic_CXX='-KPIC' + ;; + *) + ;; + esac + ;; + vxworks*) + ;; + *) + lt_prog_compiler_can_build_shared_CXX=no + ;; + esac + fi + +case $host_os in + # For platforms which do not support PIC, -DPIC is meaningless: + *djgpp*) + lt_prog_compiler_pic_CXX= + ;; + *) + lt_prog_compiler_pic_CXX="$lt_prog_compiler_pic_CXX -DPIC" + ;; +esac + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $compiler option to produce PIC" >&5 +$as_echo_n "checking for $compiler option to produce PIC... " >&6; } +if ${lt_cv_prog_compiler_pic_CXX+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler_pic_CXX=$lt_prog_compiler_pic_CXX +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_pic_CXX" >&5 +$as_echo "$lt_cv_prog_compiler_pic_CXX" >&6; } +lt_prog_compiler_pic_CXX=$lt_cv_prog_compiler_pic_CXX + +# +# Check to make sure the PIC flag actually works. +# +if test -n "$lt_prog_compiler_pic_CXX"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler PIC flag $lt_prog_compiler_pic_CXX works" >&5 +$as_echo_n "checking if $compiler PIC flag $lt_prog_compiler_pic_CXX works... " >&6; } +if ${lt_cv_prog_compiler_pic_works_CXX+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler_pic_works_CXX=no + ac_outfile=conftest.$ac_objext + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + lt_compiler_flag="$lt_prog_compiler_pic_CXX -DPIC" + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + # The option is referenced via a variable to avoid confusing sed. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) + (eval "$lt_compile" 2>conftest.err) + ac_status=$? + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + if (exit $ac_status) && test -s "$ac_outfile"; then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings other than the usual output. + $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then + lt_cv_prog_compiler_pic_works_CXX=yes + fi + fi + $RM conftest* + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_pic_works_CXX" >&5 +$as_echo "$lt_cv_prog_compiler_pic_works_CXX" >&6; } + +if test x"$lt_cv_prog_compiler_pic_works_CXX" = xyes; then + case $lt_prog_compiler_pic_CXX in + "" | " "*) ;; + *) lt_prog_compiler_pic_CXX=" $lt_prog_compiler_pic_CXX" ;; + esac +else + lt_prog_compiler_pic_CXX= + lt_prog_compiler_can_build_shared_CXX=no +fi + +fi + + + + + +# +# Check to make sure the static flag actually works. +# +wl=$lt_prog_compiler_wl_CXX eval lt_tmp_static_flag=\"$lt_prog_compiler_static_CXX\" +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler static flag $lt_tmp_static_flag works" >&5 +$as_echo_n "checking if $compiler static flag $lt_tmp_static_flag works... " >&6; } +if ${lt_cv_prog_compiler_static_works_CXX+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler_static_works_CXX=no + save_LDFLAGS="$LDFLAGS" + LDFLAGS="$LDFLAGS $lt_tmp_static_flag" + echo "$lt_simple_link_test_code" > conftest.$ac_ext + if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then + # The linker can only warn and ignore the option if not recognized + # So say no if there are warnings + if test -s conftest.err; then + # Append any errors to the config.log. + cat conftest.err 1>&5 + $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if diff conftest.exp conftest.er2 >/dev/null; then + lt_cv_prog_compiler_static_works_CXX=yes + fi + else + lt_cv_prog_compiler_static_works_CXX=yes + fi + fi + $RM -r conftest* + LDFLAGS="$save_LDFLAGS" + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_static_works_CXX" >&5 +$as_echo "$lt_cv_prog_compiler_static_works_CXX" >&6; } + +if test x"$lt_cv_prog_compiler_static_works_CXX" = xyes; then + : +else + lt_prog_compiler_static_CXX= +fi + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5 +$as_echo_n "checking if $compiler supports -c -o file.$ac_objext... " >&6; } +if ${lt_cv_prog_compiler_c_o_CXX+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler_c_o_CXX=no + $RM -r conftest 2>/dev/null + mkdir conftest + cd conftest + mkdir out + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + + lt_compiler_flag="-o out/conftest2.$ac_objext" + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) + (eval "$lt_compile" 2>out/conftest.err) + ac_status=$? + cat out/conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + if (exit $ac_status) && test -s out/conftest2.$ac_objext + then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings + $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp + $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 + if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then + lt_cv_prog_compiler_c_o_CXX=yes + fi + fi + chmod u+w . 2>&5 + $RM conftest* + # SGI C++ compiler will create directory out/ii_files/ for + # template instantiation + test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files + $RM out/* && rmdir out + cd .. + $RM -r conftest + $RM conftest* + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o_CXX" >&5 +$as_echo "$lt_cv_prog_compiler_c_o_CXX" >&6; } + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -c -o file.$ac_objext" >&5 +$as_echo_n "checking if $compiler supports -c -o file.$ac_objext... " >&6; } +if ${lt_cv_prog_compiler_c_o_CXX+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler_c_o_CXX=no + $RM -r conftest 2>/dev/null + mkdir conftest + cd conftest + mkdir out + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + + lt_compiler_flag="-o out/conftest2.$ac_objext" + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ + -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) + (eval "$lt_compile" 2>out/conftest.err) + ac_status=$? + cat out/conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + if (exit $ac_status) && test -s out/conftest2.$ac_objext + then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings + $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp + $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 + if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then + lt_cv_prog_compiler_c_o_CXX=yes + fi + fi + chmod u+w . 2>&5 + $RM conftest* + # SGI C++ compiler will create directory out/ii_files/ for + # template instantiation + test -d out/ii_files && $RM out/ii_files/* && rmdir out/ii_files + $RM out/* && rmdir out + cd .. + $RM -r conftest + $RM conftest* + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler_c_o_CXX" >&5 +$as_echo "$lt_cv_prog_compiler_c_o_CXX" >&6; } + + + + +hard_links="nottested" +if test "$lt_cv_prog_compiler_c_o_CXX" = no && test "$need_locks" != no; then + # do not overwrite the value of need_locks provided by the user + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if we can lock with hard links" >&5 +$as_echo_n "checking if we can lock with hard links... " >&6; } + hard_links=yes + $RM conftest* + ln conftest.a conftest.b 2>/dev/null && hard_links=no + touch conftest.a + ln conftest.a conftest.b 2>&5 || hard_links=no + ln conftest.a conftest.b 2>/dev/null && hard_links=no + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $hard_links" >&5 +$as_echo "$hard_links" >&6; } + if test "$hard_links" = no; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&5 +$as_echo "$as_me: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&2;} + need_locks=warn + fi +else + need_locks=no +fi + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the $compiler linker ($LD) supports shared libraries" >&5 +$as_echo_n "checking whether the $compiler linker ($LD) supports shared libraries... " >&6; } + + export_symbols_cmds_CXX='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' + exclude_expsyms_CXX='_GLOBAL_OFFSET_TABLE_|_GLOBAL__F[ID]_.*' + case $host_os in + aix[4-9]*) + # If we're using GNU nm, then we don't want the "-C" option. + # -C means demangle to AIX nm, but means don't demangle with GNU nm + # Also, AIX nm treats weak defined symbols like other global defined + # symbols, whereas GNU nm marks them as "W". + if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then + export_symbols_cmds_CXX='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && (substr(\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' + else + export_symbols_cmds_CXX='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && (substr(\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' + fi + ;; + pw32*) + export_symbols_cmds_CXX="$ltdll_cmds" + ;; + cygwin* | mingw* | cegcc*) + case $cc_basename in + cl*) ;; + *) + export_symbols_cmds_CXX='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGRS][ ]/s/.*[ ]\([^ ]*\)/\1 DATA/;s/^.*[ ]__nm__\([^ ]*\)[ ][^ ]*/\1 DATA/;/^I[ ]/d;/^[AITW][ ]/s/.* //'\'' | sort | uniq > $export_symbols' + exclude_expsyms_CXX='[_]+GLOBAL_OFFSET_TABLE_|[_]+GLOBAL__[FID]_.*|[_]+head_[A-Za-z0-9_]+_dll|[A-Za-z0-9_]+_dll_iname' + ;; + esac + ;; + *) + export_symbols_cmds_CXX='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' + ;; + esac + +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ld_shlibs_CXX" >&5 +$as_echo "$ld_shlibs_CXX" >&6; } +test "$ld_shlibs_CXX" = no && can_build_shared=no + +with_gnu_ld_CXX=$with_gnu_ld + + + + + + +# +# Do we need to explicitly link libc? +# +case "x$archive_cmds_need_lc_CXX" in +x|xyes) + # Assume -lc should be added + archive_cmds_need_lc_CXX=yes + + if test "$enable_shared" = yes && test "$GCC" = yes; then + case $archive_cmds_CXX in + *'~'*) + # FIXME: we may have to deal with multi-command sequences. + ;; + '$CC '*) + # Test whether the compiler implicitly links with -lc since on some + # systems, -lgcc has to come before -lc. If gcc already passes -lc + # to ld, don't add -lc before -lgcc. + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether -lc should be explicitly linked in" >&5 +$as_echo_n "checking whether -lc should be explicitly linked in... " >&6; } +if ${lt_cv_archive_cmds_need_lc_CXX+:} false; then : + $as_echo_n "(cached) " >&6 +else + $RM conftest* + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } 2>conftest.err; then + soname=conftest + lib=conftest + libobjs=conftest.$ac_objext + deplibs= + wl=$lt_prog_compiler_wl_CXX + pic_flag=$lt_prog_compiler_pic_CXX + compiler_flags=-v + linker_flags=-v + verstring= + output_objdir=. + libname=conftest + lt_save_allow_undefined_flag=$allow_undefined_flag_CXX + allow_undefined_flag_CXX= + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$archive_cmds_CXX 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1\""; } >&5 + (eval $archive_cmds_CXX 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + then + lt_cv_archive_cmds_need_lc_CXX=no + else + lt_cv_archive_cmds_need_lc_CXX=yes + fi + allow_undefined_flag_CXX=$lt_save_allow_undefined_flag + else + cat conftest.err 1>&5 + fi + $RM conftest* + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_archive_cmds_need_lc_CXX" >&5 +$as_echo "$lt_cv_archive_cmds_need_lc_CXX" >&6; } + archive_cmds_need_lc_CXX=$lt_cv_archive_cmds_need_lc_CXX + ;; + esac + fi + ;; +esac + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking dynamic linker characteristics" >&5 +$as_echo_n "checking dynamic linker characteristics... " >&6; } + +library_names_spec= +libname_spec='lib$name' +soname_spec= +shrext_cmds=".so" +postinstall_cmds= +postuninstall_cmds= +finish_cmds= +finish_eval= +shlibpath_var= +shlibpath_overrides_runpath=unknown +version_type=none +dynamic_linker="$host_os ld.so" +sys_lib_dlsearch_path_spec="/lib /usr/lib" +need_lib_prefix=unknown +hardcode_into_libs=no + +# when you set need_version to no, make sure it does not cause -set_version +# flags to be left without arguments +need_version=unknown + +case $host_os in +aix3*) + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a' + shlibpath_var=LIBPATH + + # AIX 3 has no versioning support, so we append a major version to the name. + soname_spec='${libname}${release}${shared_ext}$major' + ;; + +aix[4-9]*) + version_type=linux + need_lib_prefix=no + need_version=no + hardcode_into_libs=yes + if test "$host_cpu" = ia64; then + # AIX 5 supports IA64 + library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + else + # With GCC up to 2.95.x, collect2 would create an import file + # for dependence libraries. The import file would start with + # the line `#! .'. This would cause the generated library to + # depend on `.', always an invalid library. This was fixed in + # development snapshots of GCC prior to 3.0. + case $host_os in + aix4 | aix4.[01] | aix4.[01].*) + if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' + echo ' yes ' + echo '#endif'; } | ${CC} -E - | $GREP yes > /dev/null; then + : + else + can_build_shared=no + fi + ;; + esac + # AIX (on Power*) has no versioning support, so currently we can not hardcode correct + # soname into executable. Probably we can add versioning support to + # collect2, so additional links can be useful in future. + if test "$aix_use_runtimelinking" = yes; then + # If using run time linking (on AIX 4.2 or later) use lib.so + # instead of lib.a to let people know that these are not + # typical AIX shared libraries. + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + else + # We preserve .a as extension for shared libraries through AIX4.2 + # and later when we are not doing run time linking. + library_names_spec='${libname}${release}.a $libname.a' + soname_spec='${libname}${release}${shared_ext}$major' + fi + shlibpath_var=LIBPATH + fi + ;; + +amigaos*) + case $host_cpu in + powerpc) + # Since July 2007 AmigaOS4 officially supports .so libraries. + # When compiling the executable, add -use-dynld -Lsobjs: to the compileline. + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + ;; + m68k) + library_names_spec='$libname.ixlibrary $libname.a' + # Create ${libname}_ixlibrary.a entries in /sys/libs. + finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`func_echo_all "$lib" | $SED '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; test $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' + ;; + esac + ;; + +beos*) + library_names_spec='${libname}${shared_ext}' + dynamic_linker="$host_os ld.so" + shlibpath_var=LIBRARY_PATH + ;; + +bsdi[45]*) + version_type=linux + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' + shlibpath_var=LD_LIBRARY_PATH + sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" + sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" + # the default ld.so.conf also contains /usr/contrib/lib and + # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow + # libtool to hard-code these into programs + ;; + +cygwin* | mingw* | pw32* | cegcc*) + version_type=windows + shrext_cmds=".dll" + need_version=no + need_lib_prefix=no + + case $GCC,$cc_basename in + yes,*) + # gcc + library_names_spec='$libname.dll.a' + # DLL is installed to $(libdir)/../bin by postinstall_cmds + postinstall_cmds='base_file=`basename \${file}`~ + dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i; echo \$dlname'\''`~ + dldir=$destdir/`dirname \$dlpath`~ + test -d \$dldir || mkdir -p \$dldir~ + $install_prog $dir/$dlname \$dldir/$dlname~ + chmod a+x \$dldir/$dlname~ + if test -n '\''$stripme'\'' && test -n '\''$striplib'\''; then + eval '\''$striplib \$dldir/$dlname'\'' || exit \$?; + fi' + postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ + dlpath=$dir/\$dldll~ + $RM \$dlpath' + shlibpath_overrides_runpath=yes + + case $host_os in + cygwin*) + # Cygwin DLLs use 'cyg' prefix rather than 'lib' + soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' + + ;; + mingw* | cegcc*) + # MinGW DLLs use traditional 'lib' prefix + soname_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' + ;; + pw32*) + # pw32 DLLs use 'pw' prefix rather than 'lib' + library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' + ;; + esac + dynamic_linker='Win32 ld.exe' + ;; + + *,cl*) + # Native MSVC + libname_spec='$name' + soname_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' + library_names_spec='${libname}.dll.lib' + + case $build_os in + mingw*) + sys_lib_search_path_spec= + lt_save_ifs=$IFS + IFS=';' + for lt_path in $LIB + do + IFS=$lt_save_ifs + # Let DOS variable expansion print the short 8.3 style file name. + lt_path=`cd "$lt_path" 2>/dev/null && cmd //C "for %i in (".") do @echo %~si"` + sys_lib_search_path_spec="$sys_lib_search_path_spec $lt_path" + done + IFS=$lt_save_ifs + # Convert to MSYS style. + sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | sed -e 's|\\\\|/|g' -e 's| \\([a-zA-Z]\\):| /\\1|g' -e 's|^ ||'` + ;; + cygwin*) + # Convert to unix form, then to dos form, then back to unix form + # but this time dos style (no spaces!) so that the unix form looks + # like /cygdrive/c/PROGRA~1:/cygdr... + sys_lib_search_path_spec=`cygpath --path --unix "$LIB"` + sys_lib_search_path_spec=`cygpath --path --dos "$sys_lib_search_path_spec" 2>/dev/null` + sys_lib_search_path_spec=`cygpath --path --unix "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` + ;; + *) + sys_lib_search_path_spec="$LIB" + if $ECHO "$sys_lib_search_path_spec" | $GREP ';[c-zC-Z]:/' >/dev/null; then + # It is most probably a Windows format PATH. + sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` + else + sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` + fi + # FIXME: find the short name or the path components, as spaces are + # common. (e.g. "Program Files" -> "PROGRA~1") + ;; + esac + + # DLL is installed to $(libdir)/../bin by postinstall_cmds + postinstall_cmds='base_file=`basename \${file}`~ + dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i; echo \$dlname'\''`~ + dldir=$destdir/`dirname \$dlpath`~ + test -d \$dldir || mkdir -p \$dldir~ + $install_prog $dir/$dlname \$dldir/$dlname' + postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ + dlpath=$dir/\$dldll~ + $RM \$dlpath' + shlibpath_overrides_runpath=yes + dynamic_linker='Win32 link.exe' + ;; + + *) + # Assume MSVC wrapper + library_names_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext} $libname.lib' + dynamic_linker='Win32 ld.exe' + ;; + esac + # FIXME: first we should search . and the directory the executable is in + shlibpath_var=PATH + ;; + +darwin* | rhapsody*) + dynamic_linker="$host_os dyld" + version_type=darwin + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${major}$shared_ext ${libname}$shared_ext' + soname_spec='${libname}${release}${major}$shared_ext' + shlibpath_overrides_runpath=yes + shlibpath_var=DYLD_LIBRARY_PATH + shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`' + + sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' + ;; + +dgux*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + +freebsd1*) + dynamic_linker=no + ;; + +freebsd* | dragonfly*) + # DragonFly does not have aout. When/if they implement a new + # versioning mechanism, adjust this. + if test -x /usr/bin/objformat; then + objformat=`/usr/bin/objformat` + else + case $host_os in + freebsd[123]*) objformat=aout ;; + *) objformat=elf ;; + esac + fi + version_type=freebsd-$objformat + case $version_type in + freebsd-elf*) + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' + need_version=no + need_lib_prefix=no + ;; + freebsd-*) + library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix' + need_version=yes + ;; + esac + shlibpath_var=LD_LIBRARY_PATH + case $host_os in + freebsd2*) + shlibpath_overrides_runpath=yes + ;; + freebsd3.[01]* | freebsdelf3.[01]*) + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + freebsd3.[2-9]* | freebsdelf3.[2-9]* | \ + freebsd4.[0-5] | freebsdelf4.[0-5] | freebsd4.1.1 | freebsdelf4.1.1) + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + *) # from 4.6 on, and DragonFly + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + esac + ;; + +gnu*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + hardcode_into_libs=yes + ;; + +haiku*) + version_type=linux + need_lib_prefix=no + need_version=no + dynamic_linker="$host_os runtime_loader" + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LIBRARY_PATH + shlibpath_overrides_runpath=yes + sys_lib_dlsearch_path_spec='/boot/home/config/lib /boot/common/lib /boot/system/lib' + hardcode_into_libs=yes + ;; + +hpux9* | hpux10* | hpux11*) + # Give a soname corresponding to the major version so that dld.sl refuses to + # link against other versions. + version_type=sunos + need_lib_prefix=no + need_version=no + case $host_cpu in + ia64*) + shrext_cmds='.so' + hardcode_into_libs=yes + dynamic_linker="$host_os dld.so" + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + if test "X$HPUX_IA64_MODE" = X32; then + sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" + else + sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" + fi + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + ;; + hppa*64*) + shrext_cmds='.sl' + hardcode_into_libs=yes + dynamic_linker="$host_os dld.sl" + shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH + shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + ;; + *) + shrext_cmds='.sl' + dynamic_linker="$host_os dld.sl" + shlibpath_var=SHLIB_PATH + shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + ;; + esac + # HP-UX runs *really* slowly unless shared libraries are mode 555, ... + postinstall_cmds='chmod 555 $lib' + # or fails outright, so override atomically: + install_override_mode=555 + ;; + +interix[3-9]*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + dynamic_linker='Interix 3.x ld.so.1 (PE, like ELF)' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + +irix5* | irix6* | nonstopux*) + case $host_os in + nonstopux*) version_type=nonstopux ;; + *) + if test "$lt_cv_prog_gnu_ld" = yes; then + version_type=linux + else + version_type=irix + fi ;; + esac + need_lib_prefix=no + need_version=no + soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}' + case $host_os in + irix5* | nonstopux*) + libsuff= shlibsuff= + ;; + *) + case $LD in # libtool.m4 will add one of these switches to LD + *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") + libsuff= shlibsuff= libmagic=32-bit;; + *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") + libsuff=32 shlibsuff=N32 libmagic=N32;; + *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") + libsuff=64 shlibsuff=64 libmagic=64-bit;; + *) libsuff= shlibsuff= libmagic=never-match;; + esac + ;; + esac + shlibpath_var=LD_LIBRARY${shlibsuff}_PATH + shlibpath_overrides_runpath=no + sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}" + sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}" + hardcode_into_libs=yes + ;; + +# No shared lib support for Linux oldld, aout, or coff. +linux*oldld* | linux*aout* | linux*coff*) + dynamic_linker=no + ;; + +# This must be Linux ELF. +linux* | k*bsd*-gnu | kopensolaris*-gnu) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + + # Some binutils ld are patched to set DT_RUNPATH + if ${lt_cv_shlibpath_overrides_runpath+:} false; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_shlibpath_overrides_runpath=no + save_LDFLAGS=$LDFLAGS + save_libdir=$libdir + eval "libdir=/foo; wl=\"$lt_prog_compiler_wl_CXX\"; \ + LDFLAGS=\"\$LDFLAGS $hardcode_libdir_flag_spec_CXX\"" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_link "$LINENO"; then : + if ($OBJDUMP -p conftest$ac_exeext) 2>/dev/null | grep "RUNPATH.*$libdir" >/dev/null; then : + lt_cv_shlibpath_overrides_runpath=yes +fi +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + LDFLAGS=$save_LDFLAGS + libdir=$save_libdir + +fi + + shlibpath_overrides_runpath=$lt_cv_shlibpath_overrides_runpath + + # This implies no fast_install, which is unacceptable. + # Some rework will be needed to allow for fast_install + # before this can be enabled. + hardcode_into_libs=yes + + # Append ld.so.conf contents to the search path + if test -f /etc/ld.so.conf; then + lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[ ]*hwcap[ ]/d;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;s/"//g;/^$/d' | tr '\n' ' '` + sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra" + fi + + # We used to test for /lib/ld.so.1 and disable shared libraries on + # powerpc, because MkLinux only supported shared libraries with the + # GNU dynamic linker. Since this was broken with cross compilers, + # most powerpc-linux boxes support dynamic linking these days and + # people can always --disable-shared, the test was removed, and we + # assume the GNU/Linux dynamic linker is in use. + dynamic_linker='GNU/Linux ld.so' + ;; + +netbsd*) + version_type=sunos + need_lib_prefix=no + need_version=no + if echo __ELF__ | $CC -E - | $GREP __ELF__ >/dev/null; then + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' + dynamic_linker='NetBSD (a.out) ld.so' + else + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + dynamic_linker='NetBSD ld.elf_so' + fi + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + +newsos6) + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + ;; + +*nto* | *qnx*) + version_type=qnx + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + dynamic_linker='ldqnx.so' + ;; + +openbsd*) + version_type=sunos + sys_lib_dlsearch_path_spec="/usr/lib" + need_lib_prefix=no + # Some older versions of OpenBSD (3.3 at least) *do* need versioned libs. + case $host_os in + openbsd3.3 | openbsd3.3.*) need_version=yes ;; + *) need_version=no ;; + esac + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' + shlibpath_var=LD_LIBRARY_PATH + if test -z "`echo __ELF__ | $CC -E - | $GREP __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + case $host_os in + openbsd2.[89] | openbsd2.[89].*) + shlibpath_overrides_runpath=no + ;; + *) + shlibpath_overrides_runpath=yes + ;; + esac + else + shlibpath_overrides_runpath=yes + fi + ;; + +os2*) + libname_spec='$name' + shrext_cmds=".dll" + need_lib_prefix=no + library_names_spec='$libname${shared_ext} $libname.a' + dynamic_linker='OS/2 ld.exe' + shlibpath_var=LIBPATH + ;; + +osf3* | osf4* | osf5*) + version_type=osf + need_lib_prefix=no + need_version=no + soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" + sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec" + ;; + +rdos*) + dynamic_linker=no + ;; + +solaris*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + # ldd complains unless libraries are executable + postinstall_cmds='chmod +x $lib' + ;; + +sunos4*) + version_type=sunos + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' + finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + if test "$with_gnu_ld" = yes; then + need_lib_prefix=no + fi + need_version=yes + ;; + +sysv4 | sysv4.3*) + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + case $host_vendor in + sni) + shlibpath_overrides_runpath=no + need_lib_prefix=no + runpath_var=LD_RUN_PATH + ;; + siemens) + need_lib_prefix=no + ;; + motorola) + need_lib_prefix=no + need_version=no + shlibpath_overrides_runpath=no + sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' + ;; + esac + ;; + +sysv4*MP*) + if test -d /usr/nec ;then + version_type=linux + library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}' + soname_spec='$libname${shared_ext}.$major' + shlibpath_var=LD_LIBRARY_PATH + fi + ;; + +sysv5* | sco3.2v5* | sco5v6* | unixware* | OpenUNIX* | sysv4*uw2*) + version_type=freebsd-elf + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + if test "$with_gnu_ld" = yes; then + sys_lib_search_path_spec='/usr/local/lib /usr/gnu/lib /usr/ccs/lib /usr/lib /lib' + else + sys_lib_search_path_spec='/usr/ccs/lib /usr/lib' + case $host_os in + sco3.2v5*) + sys_lib_search_path_spec="$sys_lib_search_path_spec /lib" + ;; + esac + fi + sys_lib_dlsearch_path_spec='/usr/lib' + ;; + +tpf*) + # TPF is a cross-target only. Preferred cross-host = GNU/Linux. + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + +uts4*) + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + +*) + dynamic_linker=no + ;; +esac +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $dynamic_linker" >&5 +$as_echo "$dynamic_linker" >&6; } +test "$dynamic_linker" = no && can_build_shared=no + +variables_saved_for_relink="PATH $shlibpath_var $runpath_var" +if test "$GCC" = yes; then + variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" +fi + +if test "${lt_cv_sys_lib_search_path_spec+set}" = set; then + sys_lib_search_path_spec="$lt_cv_sys_lib_search_path_spec" +fi +if test "${lt_cv_sys_lib_dlsearch_path_spec+set}" = set; then + sys_lib_dlsearch_path_spec="$lt_cv_sys_lib_dlsearch_path_spec" +fi + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking how to hardcode library paths into programs" >&5 +$as_echo_n "checking how to hardcode library paths into programs... " >&6; } +hardcode_action_CXX= +if test -n "$hardcode_libdir_flag_spec_CXX" || + test -n "$runpath_var_CXX" || + test "X$hardcode_automatic_CXX" = "Xyes" ; then + + # We can hardcode non-existent directories. + if test "$hardcode_direct_CXX" != no && + # If the only mechanism to avoid hardcoding is shlibpath_var, we + # have to relink, otherwise we might link with an installed library + # when we should be linking with a yet-to-be-installed one + ## test "$_LT_TAGVAR(hardcode_shlibpath_var, CXX)" != no && + test "$hardcode_minus_L_CXX" != no; then + # Linking always hardcodes the temporary library directory. + hardcode_action_CXX=relink + else + # We can link without hardcoding, and we can hardcode nonexisting dirs. + hardcode_action_CXX=immediate + fi +else + # We cannot hardcode anything, or else we can only hardcode existing + # directories. + hardcode_action_CXX=unsupported +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $hardcode_action_CXX" >&5 +$as_echo "$hardcode_action_CXX" >&6; } + +if test "$hardcode_action_CXX" = relink || + test "$inherit_rpath_CXX" = yes; then + # Fast installation is not supported + enable_fast_install=no +elif test "$shlibpath_overrides_runpath" = yes || + test "$enable_shared" = no; then + # Fast installation is not necessary + enable_fast_install=needless +fi + + + + + + + + fi # test -n "$compiler" + + CC=$lt_save_CC + CFLAGS=$lt_save_CFLAGS + LDCXX=$LD + LD=$lt_save_LD + GCC=$lt_save_GCC + with_gnu_ld=$lt_save_with_gnu_ld + lt_cv_path_LDCXX=$lt_cv_path_LD + lt_cv_path_LD=$lt_save_path_LD + lt_cv_prog_gnu_ldcxx=$lt_cv_prog_gnu_ld + lt_cv_prog_gnu_ld=$lt_save_with_gnu_ld +fi # test "$_lt_caught_CXX_error" != yes + +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 + + + + + + + + + + + + + + ac_config_commands="$ac_config_commands libtool" + + + + +# Only expand once: + + + +SOFLAGS="-rpath \$(libdir)" + +# Set SOSUFFIX and friends + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking SOSUFFIX from libtool" >&5 +$as_echo_n "checking SOSUFFIX from libtool... " >&6; } + module=no + + versuffix="" + release="" + libname=libfoo + eval _SOSUFFIX=\"$shrext_cmds\" + if test "$_SOSUFFIX" = "" ; then + _SOSUFFIX=".so" + if test "$enable_shared" != "yes"; then + if test "$_SOSUFFIX_MESSAGE" = ""; then + _SOSUFFIX_MESSAGE=yes + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: libtool may not know about this architecture." >&5 +$as_echo "$as_me: WARNING: libtool may not know about this architecture." >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: assuming $_SOSUFFIX suffix for dynamic libraries." >&5 +$as_echo "$as_me: WARNING: assuming $_SOSUFFIX suffix for dynamic libraries." >&2;} + fi + fi + fi + + SOSUFFIX=$_SOSUFFIX + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $SOSUFFIX" >&5 +$as_echo "$SOSUFFIX" >&6; } + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking MODSUFFIX from libtool" >&5 +$as_echo_n "checking MODSUFFIX from libtool... " >&6; } + module=yes + + versuffix="" + release="" + libname=libfoo + eval _SOSUFFIX=\"$shrext_cmds\" + if test "$_SOSUFFIX" = "" ; then + _SOSUFFIX=".so" + if test "$enable_shared" != "yes"; then + if test "$_SOSUFFIX_MESSAGE" = ""; then + _SOSUFFIX_MESSAGE=yes + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: libtool may not know about this architecture." >&5 +$as_echo "$as_me: WARNING: libtool may not know about this architecture." >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: assuming $_SOSUFFIX suffix for dynamic libraries." >&5 +$as_echo "$as_me: WARNING: assuming $_SOSUFFIX suffix for dynamic libraries." >&2;} + fi + fi + fi + + MODSUFFIX=$_SOSUFFIX + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MODSUFFIX" >&5 +$as_echo "$MODSUFFIX" >&6; } + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking JMODSUFFIX from libtool" >&5 +$as_echo_n "checking JMODSUFFIX from libtool... " >&6; } + module=yes + + versuffix="" + release="" + libname=libfoo + eval _SOSUFFIX=\"$shrext_cmds\" + if test "$_SOSUFFIX" = "" ; then + _SOSUFFIX=".so" + if test "$enable_shared" != "yes"; then + if test "$_SOSUFFIX_MESSAGE" = ""; then + _SOSUFFIX_MESSAGE=yes + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: libtool may not know about this architecture." >&5 +$as_echo "$as_me: WARNING: libtool may not know about this architecture." >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: assuming $_SOSUFFIX suffix for dynamic libraries." >&5 +$as_echo "$as_me: WARNING: assuming $_SOSUFFIX suffix for dynamic libraries." >&2;} + fi + fi + fi + + if test `uname` = "Darwin"; then + JMODSUFFIX=".jnilib" + else + JMODSUFFIX=$_SOSUFFIX + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $JMODSUFFIX" >&5 +$as_echo "$JMODSUFFIX" >&6; } + + + +LIBTOOL="./libtool" + +INSTALLER="\$(LIBTOOL) --mode=install cp -p" + +MAKEFILE_CC="\$(LIBTOOL) --mode=compile ${MAKEFILE_CC}" +MAKEFILE_SOLINK="\$(LIBTOOL) --mode=link ${MAKEFILE_CCLINK} -avoid-version" +MAKEFILE_CCLINK="\$(LIBTOOL) --mode=link ${MAKEFILE_CCLINK}" +MAKEFILE_CXX="\$(LIBTOOL) --mode=compile ${MAKEFILE_CXX}" +MAKEFILE_XSOLINK="\$(LIBTOOL) --mode=link ${MAKEFILE_CXXLINK} -avoid-version" +MAKEFILE_CXXLINK="\$(LIBTOOL) --mode=link ${MAKEFILE_CXXLINK}" + + +case "$host_os" in +cygwin* | mingw*) + MAKEFILE_SOLINK="$MAKEFILE_SOLINK -no-undefined" + MAKEFILE_XSOLINK="$MAKEFILE_XSOLINK -no-undefined";; +esac + +case "$host_os" in + darwin*) + LIBTSO_MODULE="" + LIBTSO_MODSUFFIX=".dylib";; + *qnx*) + LIBTSO_MODULE="" + LIBTSO_MODSUFFIX=$MODSUFFIX;; + *) + LIBTSO_MODULE="-module" + LIBTSO_MODSUFFIX=$MODSUFFIX;; +esac + +if test "$enable_static" = "yes"; then + test "$AR" = "false" && as_fn_error $? "No ar utility found." "$LINENO" 5 +fi + +# C API. +if test "$enable_shared" = "no"; then + DEFAULT_LIB="\$(libdb_version)" + POSTLINK=": " + o=".o" +else + DEFAULT_LIB="\$(libso_target)" + POSTLINK="\$(LIBTOOL) --mode=execute true" + o=".lo" +fi +INSTALL_LIBS="$DEFAULT_LIB" +if test "$enable_static" = "yes"; then + INSTALL_LIBS="$INSTALL_LIBS \$(libdb)" +fi + +# Optional C++ API. +if test "$db_cv_cxx" = "yes"; then + if test "$enable_shared" = "no"; then + DEFAULT_LIB_CXX="\$(libcxx_version)" + fi + if test "$enable_shared" = "yes"; then + DEFAULT_LIB_CXX="\$(libxso_target)" + fi + INSTALL_LIBS="$INSTALL_LIBS $DEFAULT_LIB_CXX" + if test "$enable_static" = "yes"; then + INSTALL_LIBS="$INSTALL_LIBS \$(libcxx)" + fi +fi + +# Optional Java API / JDBC. +if test "$db_cv_java" = "yes" -o "$db_cv_jdbc" = "yes"; then + # BDB Java API requires shared libraries. + if test "$db_cv_java" = "yes" -a "$enable_shared" = "no"; then + as_fn_error $? "Java requires shared libraries" "$LINENO" 5 + fi + + # A classpath that includes . is needed to check for Java + # Since Cygwin uses Windows' javac, we need Windows path separators + case "$host_os" in + cygwin*) CLASSPATH=".;$CLASSPATH";; + *) CLASSPATH=".:$CLASSPATH";; + esac + export CLASSPATH + + +if test "x$JAVAPREFIX" = x; then + test "x$JAVAC" = x && for ac_prog in javac$EXEEXT "gcj$EXEEXT -C" guavac$EXEEXT jikes$EXEEXT +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_JAVAC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$JAVAC"; then + ac_cv_prog_JAVAC="$JAVAC" # 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_JAVAC="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +JAVAC=$ac_cv_prog_JAVAC +if test -n "$JAVAC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $JAVAC" >&5 +$as_echo "$JAVAC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$JAVAC" && break +done + +else + test "x$JAVAC" = x && for ac_prog in javac$EXEEXT "gcj$EXEEXT -C" guavac$EXEEXT jikes$EXEEXT +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_JAVAC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$JAVAC"; then + ac_cv_prog_JAVAC="$JAVAC" # 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_JAVAC="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +JAVAC=$ac_cv_prog_JAVAC +if test -n "$JAVAC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $JAVAC" >&5 +$as_echo "$JAVAC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$JAVAC" && break +done +test -n "$JAVAC" || JAVAC="$JAVAPREFIX" + +fi +test "x$JAVAC" = x && as_fn_error $? "no acceptable Java compiler found in \$PATH" "$LINENO" 5 + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if $JAVAC works" >&5 +$as_echo_n "checking if $JAVAC works... " >&6; } +if ${ac_cv_prog_javac_works+:} false; then : + $as_echo_n "(cached) " >&6 +else + +JAVA_TEST=Test.java +CLASS_TEST=Test.class +cat << \EOF > $JAVA_TEST +/* #line 17944 "configure" */ +public class Test { +} +EOF +if { ac_try='$JAVAC $JAVACFLAGS $JAVA_TEST' + { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5 + (eval $ac_try) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; } >/dev/null 2>&1; then + ac_cv_prog_javac_works=yes +else + as_fn_error $? "The Java compiler $JAVAC failed (see config.log, check the CLASSPATH?)" "$LINENO" 5 + echo "configure: failed program was:" >&5 + cat $JAVA_TEST >&5 +fi +rm -f $JAVA_TEST $CLASS_TEST + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_javac_works" >&5 +$as_echo "$ac_cv_prog_javac_works" >&6; } + + + +if test "x$JAVAPREFIX" = x; then + test "x$JAR" = x && for ac_prog in jar$EXEEXT +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_JAR+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$JAR"; then + ac_cv_prog_JAR="$JAR" # 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_JAR="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +JAR=$ac_cv_prog_JAR +if test -n "$JAR"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $JAR" >&5 +$as_echo "$JAR" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$JAR" && break +done + +else + test "x$JAR" = x && for ac_prog in jar +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_JAR+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$JAR"; then + ac_cv_prog_JAR="$JAR" # 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_JAR="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +JAR=$ac_cv_prog_JAR +if test -n "$JAR"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $JAR" >&5 +$as_echo "$JAR" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$JAR" && break +done +test -n "$JAR" || JAR="$JAVAPREFIX" + +fi +test "x$JAR" = x && as_fn_error $? "no acceptable jar program found in \$PATH" "$LINENO" 5 + + +if test x$JAVAPREFIX = x; then + test x$JAVA = x && for ac_prog in java$EXEEXT kaffe$EXEEXT +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_JAVA+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$JAVA"; then + ac_cv_prog_JAVA="$JAVA" # 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_JAVA="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +JAVA=$ac_cv_prog_JAVA +if test -n "$JAVA"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $JAVA" >&5 +$as_echo "$JAVA" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$JAVA" && break +done + +else + test x$JAVA = x && for ac_prog in java$EXEEXT kaffe$EXEEXT +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_JAVA+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$JAVA"; then + ac_cv_prog_JAVA="$JAVA" # 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_JAVA="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +JAVA=$ac_cv_prog_JAVA +if test -n "$JAVA"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $JAVA" >&5 +$as_echo "$JAVA" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$JAVA" && break +done +test -n "$JAVA" || JAVA="$JAVAPREFIX" + +fi +test x$JAVA = x && as_fn_error $? "no acceptable Java virtual machine found in \$PATH" "$LINENO" 5 + +# Extract the first word of "uudecode$EXEEXT", so it can be a program name with args. +set dummy uudecode$EXEEXT; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_uudecode+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$uudecode"; then + ac_cv_prog_uudecode="$uudecode" # 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_uudecode="yes" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +uudecode=$ac_cv_prog_uudecode +if test -n "$uudecode"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $uudecode" >&5 +$as_echo "$uudecode" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +if test x$uudecode = xyes; then +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if uudecode can decode base 64 file" >&5 +$as_echo_n "checking if uudecode can decode base 64 file... " >&6; } +if ${ac_cv_prog_uudecode_base64+:} false; then : + $as_echo_n "(cached) " >&6 +else + +cat << \EOF > Test.uue +begin-base64 644 Test.class +yv66vgADAC0AFQcAAgEABFRlc3QHAAQBABBqYXZhL2xhbmcvT2JqZWN0AQAE +bWFpbgEAFihbTGphdmEvbGFuZy9TdHJpbmc7KVYBAARDb2RlAQAPTGluZU51 +bWJlclRhYmxlDAAKAAsBAARleGl0AQAEKEkpVgoADQAJBwAOAQAQamF2YS9s +YW5nL1N5c3RlbQEABjxpbml0PgEAAygpVgwADwAQCgADABEBAApTb3VyY2VG +aWxlAQAJVGVzdC5qYXZhACEAAQADAAAAAAACAAkABQAGAAEABwAAACEAAQAB +AAAABQO4AAyxAAAAAQAIAAAACgACAAAACgAEAAsAAQAPABAAAQAHAAAAIQAB +AAEAAAAFKrcAErEAAAABAAgAAAAKAAIAAAAEAAQABAABABMAAAACABQ= +==== +EOF +if uudecode$EXEEXT Test.uue; then + ac_cv_prog_uudecode_base64=yes +else + echo "configure: 18207: uudecode had trouble decoding base 64 file 'Test.uue'" >&5 + echo "configure: failed file was:" >&5 + cat Test.uue >&5 + ac_cv_prog_uudecode_base64=no +fi +rm -f Test.uue +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_uudecode_base64" >&5 +$as_echo "$ac_cv_prog_uudecode_base64" >&6; } +fi +if test x$ac_cv_prog_uudecode_base64 != xyes; then + rm -f Test.class + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: I have to compile Test.class from scratch" >&5 +$as_echo "$as_me: WARNING: I have to compile Test.class from scratch" >&2;} + if test x$ac_cv_prog_javac_works = xno; then + as_fn_error $? "Cannot compile java source. $JAVAC does not work properly" "$LINENO" 5 + fi + if test x$ac_cv_prog_javac_works = x; then + +if test "x$JAVAPREFIX" = x; then + test "x$JAVAC" = x && for ac_prog in javac$EXEEXT "gcj$EXEEXT -C" guavac$EXEEXT jikes$EXEEXT +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_JAVAC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$JAVAC"; then + ac_cv_prog_JAVAC="$JAVAC" # 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_JAVAC="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +JAVAC=$ac_cv_prog_JAVAC +if test -n "$JAVAC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $JAVAC" >&5 +$as_echo "$JAVAC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$JAVAC" && break +done + +else + test "x$JAVAC" = x && for ac_prog in javac$EXEEXT "gcj$EXEEXT -C" guavac$EXEEXT jikes$EXEEXT +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_JAVAC+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$JAVAC"; then + ac_cv_prog_JAVAC="$JAVAC" # 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_JAVAC="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +JAVAC=$ac_cv_prog_JAVAC +if test -n "$JAVAC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $JAVAC" >&5 +$as_echo "$JAVAC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$JAVAC" && break +done +test -n "$JAVAC" || JAVAC="$JAVAPREFIX" + +fi +test "x$JAVAC" = x && as_fn_error $? "no acceptable Java compiler found in \$PATH" "$LINENO" 5 + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if $JAVAC works" >&5 +$as_echo_n "checking if $JAVAC works... " >&6; } +if ${ac_cv_prog_javac_works+:} false; then : + $as_echo_n "(cached) " >&6 +else + +JAVA_TEST=Test.java +CLASS_TEST=Test.class +cat << \EOF > $JAVA_TEST +/* #line 18325 "configure" */ +public class Test { +} +EOF +if { ac_try='$JAVAC $JAVACFLAGS $JAVA_TEST' + { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5 + (eval $ac_try) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; } >/dev/null 2>&1; then + ac_cv_prog_javac_works=yes +else + as_fn_error $? "The Java compiler $JAVAC failed (see config.log, check the CLASSPATH?)" "$LINENO" 5 + echo "configure: failed program was:" >&5 + cat $JAVA_TEST >&5 +fi +rm -f $JAVA_TEST $CLASS_TEST + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_javac_works" >&5 +$as_echo "$ac_cv_prog_javac_works" >&6; } + + + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if $JAVA works" >&5 +$as_echo_n "checking if $JAVA works... " >&6; } +if ${ac_cv_prog_java_works+:} false; then : + $as_echo_n "(cached) " >&6 +else + +JAVA_TEST=Test.java +CLASS_TEST=Test.class +TEST=Test +cat << \EOF > $JAVA_TEST +/* [#]line 18360 "configure" */ +public class Test { +public static void main (String args[]) { + System.exit (0); +} } +EOF +if test x$ac_cv_prog_uudecode_base64 != xyes; then + if { ac_try='$JAVAC $JAVACFLAGS $JAVA_TEST' + { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5 + (eval $ac_try) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; } && test -s $CLASS_TEST; then + : + else + echo "configure: failed program was:" >&5 + cat $JAVA_TEST >&5 + as_fn_error $? "The Java compiler $JAVAC failed (see config.log, check the CLASSPATH?)" "$LINENO" 5 + fi +fi +if { ac_try='$JAVA $JAVAFLAGS $TEST' + { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5 + (eval $ac_try) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; } >/dev/null 2>&1; then + ac_cv_prog_java_works=yes +else + echo "configure: failed program was:" >&5 + cat $JAVA_TEST >&5 + as_fn_error $? "The Java VM $JAVA failed (see config.log, check the CLASSPATH?)" "$LINENO" 5 +fi +rm -fr $JAVA_TEST $CLASS_TEST Test.uue + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_java_works" >&5 +$as_echo "$ac_cv_prog_java_works" >&6; } + + + + + +JNI_INCLUDE_DIRS="" + +test "x$JAVAC" = x && as_fn_error $? "'$JAVAC' undefined" "$LINENO" 5 +# Extract the first word of "$JAVAC", so it can be a program name with args. +set dummy $JAVAC; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path__ACJNI_JAVAC+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $_ACJNI_JAVAC in + [\\/]* | ?:[\\/]*) + ac_cv_path__ACJNI_JAVAC="$_ACJNI_JAVAC" # Let the user override the test with a path. + ;; + *) + 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 { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_path__ACJNI_JAVAC="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + test -z "$ac_cv_path__ACJNI_JAVAC" && ac_cv_path__ACJNI_JAVAC="$JAVAC" + ;; +esac +fi +_ACJNI_JAVAC=$ac_cv_path__ACJNI_JAVAC +if test -n "$_ACJNI_JAVAC"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $_ACJNI_JAVAC" >&5 +$as_echo "$_ACJNI_JAVAC" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +test ! -x "$_ACJNI_JAVAC" && as_fn_error $? "$JAVAC could not be found in path" "$LINENO" 5 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking absolute path of $JAVAC" >&5 +$as_echo_n "checking absolute path of $JAVAC... " >&6; } +case "$_ACJNI_JAVAC" in +/*) { $as_echo "$as_me:${as_lineno-$LINENO}: result: $_ACJNI_JAVAC" >&5 +$as_echo "$_ACJNI_JAVAC" >&6; };; +*) as_fn_error $? "$_ACJNI_JAVAC is not an absolute path name" "$LINENO" 5;; +esac + + +# find the include directory relative to the javac executable +_cur=""$_ACJNI_JAVAC"" +while ls -ld "$_cur" 2>/dev/null | grep " -> " >/dev/null; do + { $as_echo "$as_me:${as_lineno-$LINENO}: checking symlink for $_cur" >&5 +$as_echo_n "checking symlink for $_cur... " >&6; } + _slink=`ls -ld "$_cur" | sed 's/.* -> //'` + case "$_slink" in + /*) _cur="$_slink";; + # 'X' avoids triggering unwanted echo options. + *) _cur=`echo "X$_cur" | sed -e 's/^X//' -e 's:[^/]*$::'`"$_slink";; + esac + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $_cur" >&5 +$as_echo "$_cur" >&6; } +done +_ACJNI_FOLLOWED="$_cur" + +_JTOPDIR=`echo "$_ACJNI_FOLLOWED" | sed -e 's://*:/:g' -e 's:/[^/]*$::'` +case "$host_os" in + darwin*) _JTOPDIR=`echo "$_JTOPDIR" | sed -e 's:/[^/]*$::'` + _JINC="$_JTOPDIR/Headers";; + *) _JINC="$_JTOPDIR/include";; +esac + +# If we find jni.h in /usr/include, then it's not a java-only tree, so +# don't add /usr/include or subdirectories to the list of includes. +# An extra -I/usr/include can foul things up with newer gcc's. +# +# If we don't find jni.h, just keep going. Hopefully javac knows where +# to find its include files, even if we can't. +if test -r "$_JINC/jni.h"; then + if test "$_JINC" != "/usr/include"; then + JNI_INCLUDE_DIRS="$JNI_INCLUDE_DIRS $_JINC" + fi +else + _JTOPDIR=`echo "$_JTOPDIR" | sed -e 's:/[^/]*$::'` + if test -r "$_JTOPDIR/include/jni.h"; then + if test "$_JTOPDIR" != "/usr"; then + JNI_INCLUDE_DIRS="$JNI_INCLUDE_DIRS $_JTOPDIR/include" + fi + fi +fi + +# get the likely subdirectories for system specific java includes +if test "$_JTOPDIR" != "/usr"; then + case "$host_os" in + aix*) _JNI_INC_SUBDIRS="aix";; + bsdi*) _JNI_INC_SUBDIRS="bsdos";; + cygwin*) _JNI_INC_SUBDIRS="win32";; + freebsd*) _JNI_INC_SUBDIRS="freebsd";; + hp*) _JNI_INC_SUBDIRS="hp-ux";; + linux*) _JNI_INC_SUBDIRS="linux genunix";; + osf*) _JNI_INC_SUBDIRS="alpha";; + solaris*) _JNI_INC_SUBDIRS="solaris";; + *) _JNI_INC_SUBDIRS="genunix";; + esac +fi + +# add any subdirectories that are present +for _JINCSUBDIR in $_JNI_INC_SUBDIRS +do + if test -d "$_JTOPDIR/include/$_JINCSUBDIR"; then + JNI_INCLUDE_DIRS="$JNI_INCLUDE_DIRS $_JTOPDIR/include/$_JINCSUBDIR" + fi +done + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking java version" >&5 +$as_echo_n "checking java version... " >&6; } + case "$JAVA" in + *kaffe* ) + JAVA_VERSION=`$JAVA -version 2>&1 | + sed -e '/Java Version:/!d' -e 's/.*Java Version: \([^ ]*\)[ ]*/\1/'` ;; + * ) JAVA_VERSION=`$JAVA -version 2>&1 | + sed -e '/ version /!d' -e 's/.*"\(.*\)".*/\1/'` ;; + esac + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $JAVA_VERSION" >&5 +$as_echo "$JAVA_VERSION" >&6; } + case "$JAVA_VERSION" in + 1.[3456789]* | 1.[1-9][0-9]* | [23456789]* ) ;; + * ) + as_fn_error $? "Java version 1.3 or higher required, got $JAVA_VERSION" "$LINENO" 5 ;; + esac + + # Because of the code that SWIG generates to cast between pointers and + # integers, we need to add the flag "-fno-strict-aliasing" to the gcc + # command line when compiling the JNI code. This is documented in + # [#14953] and at http://www.swig.org/Doc1.3/Java.html + if test "${GCC}" = "yes"; then + SWIGCFLAGS="-fno-strict-aliasing" + fi + + for JNI_INCLUDE_DIR in $JNI_INCLUDE_DIRS + do + CPPFLAGS="$CPPFLAGS -I$JNI_INCLUDE_DIR" + done + + if test "$db_cv_java" = "yes"; then + ADDITIONAL_LANG="$ADDITIONAL_LANG java" + INSTALL_LIBS="$INSTALL_LIBS \$(libjso_target)" + fi +else + JAVAC=nojavac +fi + +# MinGW support. +if test "$db_cv_mingw" = "yes"; then + OSDIR=os_windows + PATH_SEPARATOR="\\\\/:" + + $as_echo "#define DB_WIN32 1" >>confdefs.h + + $as_echo "#define STDC_HEADERS 1" >>confdefs.h + +else + OSDIR=os + PATH_SEPARATOR="/" + $as_echo "#define HAVE_SYSTEM_INCLUDE_FILES 1" >>confdefs.h + +fi + +# Optional SQL API. +if test "$db_cv_sql" = "yes"; then + ADDITIONAL_INCS="$ADDITIONAL_INCS dbsql.h" + ADDITIONAL_PROGS="$ADDITIONAL_PROGS dbsql" + + # Link against libdl, if found. It is only needed for the load + # extension, but shouldn't hurt. + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for main in -ldl" >&5 +$as_echo_n "checking for main in -ldl... " >&6; } +if ${ac_cv_lib_dl_main+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-ldl $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + + +int +main () +{ +return main (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_dl_main=yes +else + ac_cv_lib_dl_main=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_main" >&5 +$as_echo "$ac_cv_lib_dl_main" >&6; } +if test "x$ac_cv_lib_dl_main" = xyes; then : + SQL_LIBS="$SQL_LIBS -ldl" +fi +ac_cv_lib_dl=ac_cv_lib_dl_main + + + # Link against libedit or readline for command-line editing. + if test x"$with_readline" != xno; then + header=readline.h + for rl_lib in edit readline; do + found="yes" + save_LIBS="" + LIBS="" + { ac_cv_search_tgetent=; unset ac_cv_search_tgetent;} + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing tgetent" >&5 +$as_echo_n "checking for library containing tgetent... " >&6; } +if ${ac_cv_search_tgetent+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_func_search_save_LIBS=$LIBS +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char tgetent (); +int +main () +{ +return tgetent (); + ; + return 0; +} +_ACEOF +for ac_lib in '' $rl_lib ncurses curses termcap; do + if test -z "$ac_lib"; then + ac_res="none required" + else + ac_res=-l$ac_lib + LIBS="-l$ac_lib $ac_func_search_save_LIBS" + fi + if ac_fn_c_try_link "$LINENO"; then : + ac_cv_search_tgetent=$ac_res +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext + if ${ac_cv_search_tgetent+:} false; then : + break +fi +done +if ${ac_cv_search_tgetent+:} false; then : + +else + ac_cv_search_tgetent=no +fi +rm conftest.$ac_ext +LIBS=$ac_func_search_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_tgetent" >&5 +$as_echo "$ac_cv_search_tgetent" >&6; } +ac_res=$ac_cv_search_tgetent +if test "$ac_res" != no; then : + test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" + term_LIBS="$LIBS" +else + term_LIBS="" +fi + + as_ac_Lib=`$as_echo "ac_cv_lib_$rl_lib''_readline" | $as_tr_sh` +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for readline in -l$rl_lib" >&5 +$as_echo_n "checking for readline in -l$rl_lib... " >&6; } +if eval \${$as_ac_Lib+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-l$rl_lib $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char readline (); +int +main () +{ +return readline (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + eval "$as_ac_Lib=yes" +else + eval "$as_ac_Lib=no" +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +eval ac_res=\$$as_ac_Lib + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } +if eval test \"x\$"$as_ac_Lib"\" = x"yes"; then : + SQL_LIBS="$SQL_LIBS -l$rl_lib $term_LIBS" +else + found="no" +fi + + LIBS="$save_LIBS" + test "$found" = "yes" && break + done + + if test x"$rl_lib" = xedit; then + header="editline/readline.h" + fi + + if test "$found" = "yes"; then + as_ac_Header=`$as_echo "ac_cv_header_$header" | $as_tr_sh` +ac_fn_c_check_header_mongrel "$LINENO" "$header" "$as_ac_Header" "$ac_includes_default" +if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : + found="yes" +else + + found="no" + if test "$cross_compiling" != yes; then + for dir in /usr /usr/local /usr/local/readline /usr/contrib /mingw; do + for subdir in include include/readline; do + as_ac_File=`$as_echo "ac_cv_file_$dir/$subdir/$header" | $as_tr_sh` +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $dir/$subdir/$header" >&5 +$as_echo_n "checking for $dir/$subdir/$header... " >&6; } +if eval \${$as_ac_File+:} false; then : + $as_echo_n "(cached) " >&6 +else + test "$cross_compiling" = yes && + as_fn_error $? "cannot check for file existence when cross compiling" "$LINENO" 5 +if test -r "$dir/$subdir/$header"; then + eval "$as_ac_File=yes" +else + eval "$as_ac_File=no" +fi +fi +eval ac_res=\$$as_ac_File + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } +if eval test \"x\$"$as_ac_File"\" = x"yes"; then : + found=yes +fi + + if test "$found" = "yes"; then + SQL_FLAGS="$SQL_FLAGS -I$dir/$subdir" + break + fi + done + test "$found" = "yes" && break + done + fi +fi + + + fi + fi + + if test "$enable_shared" = "no"; then + DEFAULT_LIB_SQL="\$(libsql_version)" + else + DEFAULT_LIB_SQL="\$(libsqlso_target)" + fi + INSTALL_LIBS="$INSTALL_LIBS $DEFAULT_LIB_SQL" + if test "$enable_static" = "yes"; then + INSTALL_LIBS="$INSTALL_LIBS \$(libsql)" + fi + + if test "$db_cv_test" = "yes"; then + subdirs="$subdirs sql" + ADDITIONAL_LANG="$ADDITIONAL_LANG sql-test" + fi + + if test "$db_cv_jdbc" = "yes"; then + subdirs="$subdirs jdbc" + ADDITIONAL_LANG="$ADDITIONAL_LANG jdbc" + fi + + if test "$db_cv_debug" = "yes"; then + SQL_FLAGS="$SQL_FLAGS -DSQLITE_DEBUG=1" + fi + + if test "$db_cv_build_cryptography" = "yes"; then + SQL_FLAGS="$SQL_FLAGS -DSQLITE_HAS_CODEC=1" + fi +fi + +if test "$db_cv_sql_compat" = "yes"; then + if test "$enable_shared" = "no"; then + DEFAULT_LIB_SQLITE="\$(libsqlite)" + else + DEFAULT_LIB_SQLITE="\$(libsqliteso_target)" + fi + + ADDITIONAL_INCS="$ADDITIONAL_INCS \$(langdir)/sql/generated/sqlite3.h" + ADDITIONAL_PROGS="$ADDITIONAL_PROGS sqlite3" + INSTALL_LIBS="$INSTALL_LIBS $DEFAULT_LIB_SQLITE" + + # This is different to the other libraries: we need to be very + # careful not to delete an existing installation of SQLite unless + # we are installing over it. + if test "$enable_shared" = "yes"; then + INSTALL_LIBS_EXTRA="$INSTALL_LIBS_EXTRA \$(libsqliteso)" + fi + if test "$enable_static" = "yes"; then + INSTALL_LIBS="$INSTALL_LIBS \$(libsqlite)" + fi +fi + +# Optional SQL code generation tool. +if test "$db_cv_sql_codegen" = "yes"; then + ADDITIONAL_PROGS="$ADDITIONAL_PROGS db_sql_codegen" +fi + +# Optional STL API. +if test "$db_cv_stl" = "yes"; then + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C++ compiler supports templates for STL" >&5 +$as_echo_n "checking whether the C++ compiler supports templates for STL... " >&6; } + +ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu + +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include +#include + +using std::string; +using std::vector; +namespace dbstl_configure_test { + +template +class MyClass +{ +public: + explicit MyClass(int i) { imem = i;} + + MyClass(const T1& t1, const T2& t2, int i) + { + mem1 = t1; + mem2 = t2; + imem = i; + } + + template + T2 templ_mem_func(T1 t1, T3 t3) + { + mem2 = t1; + T3 t32 = t3; + T2 t2; + return t2; + } + + double templ_mem_func(T1 t1, double t3) + { + mem1 = t1; + double t32 = t3; + return t3; + } + + template + ReturnType templ_mem_func(T7, T8); + + operator T1() const {return mem1;} +private: + T1 mem1; + T2 mem2; + int imem; +}; + +template +template +ReturnType MyClass::templ_mem_func(T7, T8) +{ + ReturnType rt; + return rt; +} + +template<> +class MyClass +{ +public: + explicit MyClass(int i) { imem = i;} + + MyClass(const double& t1, const float& t2, int i) + { + mem1 = t1; + mem2 = t2; + imem = i; + } + + template + float templ_mem_func(double t1, T3 t3) + { + mem2 = t1; + T3 t32 = t3; + float t2; + return t2; + } + + double templ_mem_func(double t1, double t3) + { + mem1 = t1; + double t32 = t3; + return t3; + } + + template + ReturnType templ_mem_func(T7, T8); + + operator double() const {return mem1;} +private: + double mem1; + float mem2; + int imem; +}; + +template +ReturnType MyClass::templ_mem_func(T7, T8) +{ + ReturnType rt; + return rt; +} + +template +class MyClass2 { +public: + MyClass2(const T1& t1, const T2&t2){} +}; + +// partial specialization: both template parameters have same type +template +class MyClass2 { +public: + MyClass2(const T& t1, const T&t2){} +}; + +// partial specialization: second type is int +template +class MyClass2 { +public: + MyClass2(const T& t1, const int&t2){} +}; + +// partial specialization: both template parameters are pointer types +template +class MyClass2 { +public: + MyClass2(const T1* t1, const T2*t2){} +}; + +template +class MyClass2 { +public: + MyClass2(const T* t1, const T*t2){} +}; + +template +int part_spec_func(T4 t4, T5 t5) +{ + // Zero Initialization should work. + T4 t44 = T4(); + T5 t55 = T5(); + + t44 = t4; + t55 = t5; +} + +template +int part_spec_func(T4 t4, std::vector t55) +{ + T4 t44 = t4; + std::vector abc = t55; +} + +// maximum of two int values +inline int const& max (int const& a, int const& b) +{ + return a +inline T2 const max (T1 const& a, T2 const& b) +{ + return a +inline T const& max (T const& a, T const& b) +{ + return a +inline T const& max (T const& a, T const& b, T const& c) +{ + return max (max(a,b), c); +} + +template +class Base { +public: + void exit2(){} + Base(){} +}; + +template +class Derived : public Base { +public: + // Call Base() explicitly here, otherwise can't access it. + // Kind of like this->. + Derived() : Base(){} + + void foo() { + this->exit2(); + } +}; + +} // dbstl_configure_test + +using namespace dbstl_configure_test; +int +main () +{ + + char cc = 'a'; + int i = 4; + double pi = 3.14; + float gold = 0.618; + + MyClass2 mif(i, gold); // uses MyClass2 + MyClass2 mff(gold, gold); // uses MyClass2 + MyClass2 mfi(gold, i); // uses MyClass2 + MyClass2 mp(&i, &gold); // uses MyClass2 + MyClass2 m(&i, &i); // uses MyClass2 + + MyClass obj1(i); + obj1.templ_mem_func(cc, pi); + obj1.templ_mem_func(cc, gold); + obj1.templ_mem_func(i, pi); + obj1.templ_mem_func(cc, cc); + char ch = (char)obj1; + + string str1("abc"), str2("def"); + MyClass obj2(str1.c_str(), str2, i); + obj2.templ_mem_func("klm", str2); + obj2.templ_mem_func("hij", pi); + + // Use j to help distinguish, otherwise unable to use the one defined + // outside of class body. + int j = obj2.templ_mem_func(cc, cc); + // Call explicitly. + obj2.templ_mem_func(gold, pi); + const char *pch = (const char*)obj2; + + MyClass obj3(pi, gold, i); + obj3.templ_mem_func(pi, i); + obj3.templ_mem_func(pi, str1); + obj3.templ_mem_func(pi, pi); + obj3.templ_mem_func(cc, pi); + obj3.templ_mem_func(cc, cc); + double tmpd = (double)obj3; + + MyClass obj4(i); + obj4.templ_mem_func(pi, i); + obj4.templ_mem_func(pi, str1); + obj4.templ_mem_func(pi, pi); + obj4.templ_mem_func(gold, pi); + tmpd = (double)obj4; + + // Function template partial specialization. + part_spec_func(pi, gold); + part_spec_func(gold, i); + part_spec_func(str1, str2); + std::vector strv; + part_spec_func(str1, strv); + std::vector dblv; + part_spec_func(pi, dblv); + + // Function template overloads and explicit call and deduction. + dbstl_configure_test::max(7, 42, 68); // calls the template for three arguments + dbstl_configure_test::max(7.0, 42.0); // calls max (by argument deduction) + dbstl_configure_test::max('a', 'b'); // calls max (by argument deduction) + dbstl_configure_test::max(7, 42.0); + dbstl_configure_test::max(4,4.2); // instantiate T as double + dbstl_configure_test::max(7, 42); // calls the nontemplate for two ints + dbstl_configure_test::max<>(7, 42); // calls max (by argument deduction) + dbstl_configure_test::max(7, 42); // calls max (no argument deduction) + dbstl_configure_test::max('a', 42.7); // calls the nontemplate for two ints + + Base bobj; + bobj.exit2(); + // Using this-> to access base class members. + Derived dobj; + dobj.foo(); + dobj.exit2(); + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +else + as_fn_error $? "no" "$LINENO" 5 +fi +rm -f core 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 + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether C++ supports the wstring class" >&5 +$as_echo_n "checking whether C++ supports the wstring class... " >&6; } + +ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu + +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + std::wstring ws; ws.find_first_of(ws); +int +main () +{ + + ; + return 0; +}, + WSTRING_decl="#define HAVE_WSTRING 1" ; AC_MSG_RESULT(yes), + WSTRING_decl="#undef HAVE_WSTRING" ; AC_MSG_RESULT(no) +_ACEOF +if ac_fn_cxx_try_link "$LINENO"; then : + +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext 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 + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for thread local storage (TLS) class" >&5 +$as_echo_n "checking for thread local storage (TLS) class... " >&6; } + + + ac_cv_tls=none + + ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu + + ax_tls_keywords="__thread __declspec(thread) __declspec(__thread)" + for ax_tls_decl_keyword in $ax_tls_keywords ""; do + for ax_tls_defn_keyword in $ax_tls_keywords ""; do + test -z "$ax_tls_decl_keyword" && + test -z "$ax_tls_defn_keyword" && continue + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +template class TLSClass { + public: static $ax_tls_decl_keyword T *tlsvar; + }; + class TLSClass2 { + public: static $ax_tls_decl_keyword int tlsvar; + }; + template $ax_tls_defn_keyword T* TLSClass::tlsvar = NULL; + $ax_tls_defn_keyword int TLSClass2::tlsvar = 1; + static $ax_tls_decl_keyword int x = 0; +int +main () +{ +TLSClass::tlsvar = NULL; TLSClass2::tlsvar = 1; + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + ac_cv_tls=modifier ; break +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + done + test "$ac_cv_tls" = none || break + done + 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 "$ac_cv_tls" = "none" ; then + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + #include + + static pthread_once_t once_control_ = PTHREAD_ONCE_INIT; + static pthread_key_t key; + + static void init_once(void) { + pthread_key_create(&key, NULL); + } + static void *get_tls() { + return (void *)pthread_getspecific(&key); + } + static void set_tls(void *p) { + pthread_setspecific(&key, p); + } +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_tls=pthread +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + fi + + case "$ac_cv_tls" in + none) break ;; + pthread) + TLS_decl="#define HAVE_PTHREAD_TLS" + TLS_defn="" ;; + modifier) + TLS_decl="#define TLS_DECL_MODIFIER $ax_tls_decl_keyword" + TLS_defn="#define TLS_DEFN_MODIFIER $ax_tls_defn_keyword" ;; + esac + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_tls" >&5 +$as_echo "$ac_cv_tls" >&6; } + + if test "$enable_shared" = "no"; then + DEFAULT_LIB_STL="\$(libstl_version)" + fi + if test "$enable_shared" = "yes"; then + DEFAULT_LIB_STL="\$(libstlso_target)" + fi + ADDITIONAL_INCS="$ADDITIONAL_INCS dbstl_common.h" + for f in dbstl_set.h dbstl_vector.h dbstl_exception.h dbstl_map.h dbstl_utility.h dbstl_dbc.h dbstl_dbt.h dbstl_base_iterator.h dbstl_container.h dbstl_element_ref.h dbstl_inner_utility.h dbstl_resource_manager.h ; do + ADDITIONAL_INCS="$ADDITIONAL_INCS \$(topdir)/lang/cxx/stl/$f" + done + INSTALL_LIBS="$INSTALL_LIBS $DEFAULT_LIB_STL" + if test "$enable_static" = "yes"; then + INSTALL_LIBS="$INSTALL_LIBS \$(libstl)" + fi +fi + +# Checks for include files, structures, C types. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether stat file-mode macros are broken" >&5 +$as_echo_n "checking whether stat file-mode macros are broken... " >&6; } +if ${ac_cv_header_stat_broken+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include + +#if defined S_ISBLK && defined S_IFDIR +extern char c1[S_ISBLK (S_IFDIR) ? -1 : 1]; +#endif + +#if defined S_ISBLK && defined S_IFCHR +extern char c2[S_ISBLK (S_IFCHR) ? -1 : 1]; +#endif + +#if defined S_ISLNK && defined S_IFREG +extern char c3[S_ISLNK (S_IFREG) ? -1 : 1]; +#endif + +#if defined S_ISSOCK && defined S_IFREG +extern char c4[S_ISSOCK (S_IFREG) ? -1 : 1]; +#endif + +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_header_stat_broken=no +else + ac_cv_header_stat_broken=yes +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stat_broken" >&5 +$as_echo "$ac_cv_header_stat_broken" >&6; } +if test $ac_cv_header_stat_broken = yes; then + +$as_echo "#define STAT_MACROS_BROKEN 1" >>confdefs.h + +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether time.h and sys/time.h may both be included" >&5 +$as_echo_n "checking whether time.h and sys/time.h may both be included... " >&6; } +if ${ac_cv_header_time+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include +#include + +int +main () +{ +if ((struct tm *) 0) +return 0; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_header_time=yes +else + ac_cv_header_time=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_time" >&5 +$as_echo "$ac_cv_header_time" >&6; } +if test $ac_cv_header_time = yes; then + +$as_echo "#define TIME_WITH_SYS_TIME 1" >>confdefs.h + +fi + +ac_header_dirent=no +for ac_hdr in dirent.h sys/ndir.h sys/dir.h ndir.h; do + as_ac_Header=`$as_echo "ac_cv_header_dirent_$ac_hdr" | $as_tr_sh` +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_hdr that defines DIR" >&5 +$as_echo_n "checking for $ac_hdr that defines DIR... " >&6; } +if eval \${$as_ac_Header+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include <$ac_hdr> + +int +main () +{ +if ((DIR *) 0) +return 0; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + eval "$as_ac_Header=yes" +else + eval "$as_ac_Header=no" +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +eval ac_res=\$$as_ac_Header + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } +if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_hdr" | $as_tr_cpp` 1 +_ACEOF + +ac_header_dirent=$ac_hdr; break +fi + +done +# Two versions of opendir et al. are in -ldir and -lx on SCO Xenix. +if test $ac_header_dirent = dirent.h; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing opendir" >&5 +$as_echo_n "checking for library containing opendir... " >&6; } +if ${ac_cv_search_opendir+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_func_search_save_LIBS=$LIBS +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char opendir (); +int +main () +{ +return opendir (); + ; + return 0; +} +_ACEOF +for ac_lib in '' dir; do + if test -z "$ac_lib"; then + ac_res="none required" + else + ac_res=-l$ac_lib + LIBS="-l$ac_lib $ac_func_search_save_LIBS" + fi + if ac_fn_c_try_link "$LINENO"; then : + ac_cv_search_opendir=$ac_res +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext + if ${ac_cv_search_opendir+:} false; then : + break +fi +done +if ${ac_cv_search_opendir+:} false; then : + +else + ac_cv_search_opendir=no +fi +rm conftest.$ac_ext +LIBS=$ac_func_search_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_opendir" >&5 +$as_echo "$ac_cv_search_opendir" >&6; } +ac_res=$ac_cv_search_opendir +if test "$ac_res" != no; then : + test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" + +fi + +else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing opendir" >&5 +$as_echo_n "checking for library containing opendir... " >&6; } +if ${ac_cv_search_opendir+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_func_search_save_LIBS=$LIBS +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char opendir (); +int +main () +{ +return opendir (); + ; + return 0; +} +_ACEOF +for ac_lib in '' x; do + if test -z "$ac_lib"; then + ac_res="none required" + else + ac_res=-l$ac_lib + LIBS="-l$ac_lib $ac_func_search_save_LIBS" + fi + if ac_fn_c_try_link "$LINENO"; then : + ac_cv_search_opendir=$ac_res +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext + if ${ac_cv_search_opendir+:} false; then : + break +fi +done +if ${ac_cv_search_opendir+:} false; then : + +else + ac_cv_search_opendir=no +fi +rm conftest.$ac_ext +LIBS=$ac_func_search_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_opendir" >&5 +$as_echo "$ac_cv_search_opendir" >&6; } +ac_res=$ac_cv_search_opendir +if test "$ac_res" != no; then : + test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" + +fi + +fi + +for ac_header in execinfo.h sys/select.h sys/socket.h sys/time.h +do : + as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` +ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default" +if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + +ac_fn_c_check_member "$LINENO" "struct stat" "st_blksize" "ac_cv_member_struct_stat_st_blksize" "$ac_includes_default" +if test "x$ac_cv_member_struct_stat_st_blksize" = xyes; then : + +cat >>confdefs.h <<_ACEOF +#define HAVE_STRUCT_STAT_ST_BLKSIZE 1 +_ACEOF + + +fi + + + +# db.h includes and , not the other default includes +# autoconf usually includes. For that reason, we specify a set of includes +# for all type checking tests. [#5060] +# +# C99 says types should be in ; include if it exists. +# +# Some systems have types in ; include if it exists. +# +# IBM's OS/390 and z/OS releases have types in not also found +# in ; include if it exists. +db_includes="#include " + +ac_fn_c_check_header_mongrel "$LINENO" "inttypes.h" "ac_cv_header_inttypes_h" "$ac_includes_default" +if test "x$ac_cv_header_inttypes_h" = xyes; then : + + db_includes="$db_includes +#include " + inttypes_h_decl="#include " +fi + + + +# IRIX has stdint.h that is only available when using c99 (i.e. __c99 +# is defined). Problem with having it in a public header is that a c++ +# compiler cannot #include if db.h #includes stdint.h, so we +# need to check that stdint.h is available for all cases. Also the +# IRIX compiler does not exit with a non-zero exit code when it sees +# #error, so we actually need to use the header for the compiler to fail. + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for stdint.h" >&5 +$as_echo_n "checking for stdint.h... " >&6; } +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#include + int main() { + uint_least8_t x=0; + return x; + } +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +if test "$db_cv_cxx" = "yes"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if stdint.h can be used by C++" >&5 +$as_echo_n "checking if stdint.h can be used by C++... " >&6; } + ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu + + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + int main() { + uint_least8_t x=0; + return x; + } +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + stdint_h_decl="#include " + db_includes="$db_includes +#include " + +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + stdint_h_decl="#ifndef __cplusplus +#include +#endif" + db_includes="$db_includes +#ifndef __cplusplus +#include +#endif" + +fi +rm -f core 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 + +else + stdint_h_decl="#include " + db_includes="$db_includes +#include " +fi +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + + +ac_fn_c_check_header_mongrel "$LINENO" "stddef.h" "ac_cv_header_stddef_h" "$ac_includes_default" +if test "x$ac_cv_header_stddef_h" = xyes; then : + + db_includes="$db_includes +#include " + stddef_h_decl="#include " +fi + + + +ac_fn_c_check_header_mongrel "$LINENO" "unistd.h" "ac_cv_header_unistd_h" "$ac_includes_default" +if test "x$ac_cv_header_unistd_h" = xyes; then : + + db_includes="$db_includes +#include " + unistd_h_decl="#include " +fi + + +db_includes="$db_includes +#include " + +# We need to know the sizes of various objects on this system. +# The cast to long int works around a bug in the HP C Compiler +# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects +# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'. +# This bug is HP SR number 8606223364. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of char" >&5 +$as_echo_n "checking size of char... " >&6; } +if ${ac_cv_sizeof_char+:} false; then : + $as_echo_n "(cached) " >&6 +else + if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (char))" "ac_cv_sizeof_char" "$db_includes +"; then : + +else + if test "$ac_cv_type_char" = yes; then + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error 77 "cannot compute sizeof (char) +See \`config.log' for more details" "$LINENO" 5; } + else + ac_cv_sizeof_char=0 + fi +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_char" >&5 +$as_echo "$ac_cv_sizeof_char" >&6; } + + + +cat >>confdefs.h <<_ACEOF +#define SIZEOF_CHAR $ac_cv_sizeof_char +_ACEOF + + +# The cast to long int works around a bug in the HP C Compiler +# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects +# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'. +# This bug is HP SR number 8606223364. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of unsigned char" >&5 +$as_echo_n "checking size of unsigned char... " >&6; } +if ${ac_cv_sizeof_unsigned_char+:} false; then : + $as_echo_n "(cached) " >&6 +else + if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (unsigned char))" "ac_cv_sizeof_unsigned_char" "$db_includes +"; then : + +else + if test "$ac_cv_type_unsigned_char" = yes; then + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error 77 "cannot compute sizeof (unsigned char) +See \`config.log' for more details" "$LINENO" 5; } + else + ac_cv_sizeof_unsigned_char=0 + fi +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_unsigned_char" >&5 +$as_echo "$ac_cv_sizeof_unsigned_char" >&6; } + + + +cat >>confdefs.h <<_ACEOF +#define SIZEOF_UNSIGNED_CHAR $ac_cv_sizeof_unsigned_char +_ACEOF + + +# The cast to long int works around a bug in the HP C Compiler +# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects +# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'. +# This bug is HP SR number 8606223364. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of short" >&5 +$as_echo_n "checking size of short... " >&6; } +if ${ac_cv_sizeof_short+:} false; then : + $as_echo_n "(cached) " >&6 +else + if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (short))" "ac_cv_sizeof_short" "$db_includes +"; then : + +else + if test "$ac_cv_type_short" = yes; then + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error 77 "cannot compute sizeof (short) +See \`config.log' for more details" "$LINENO" 5; } + else + ac_cv_sizeof_short=0 + fi +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_short" >&5 +$as_echo "$ac_cv_sizeof_short" >&6; } + + + +cat >>confdefs.h <<_ACEOF +#define SIZEOF_SHORT $ac_cv_sizeof_short +_ACEOF + + +# The cast to long int works around a bug in the HP C Compiler +# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects +# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'. +# This bug is HP SR number 8606223364. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of unsigned short" >&5 +$as_echo_n "checking size of unsigned short... " >&6; } +if ${ac_cv_sizeof_unsigned_short+:} false; then : + $as_echo_n "(cached) " >&6 +else + if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (unsigned short))" "ac_cv_sizeof_unsigned_short" "$db_includes +"; then : + +else + if test "$ac_cv_type_unsigned_short" = yes; then + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error 77 "cannot compute sizeof (unsigned short) +See \`config.log' for more details" "$LINENO" 5; } + else + ac_cv_sizeof_unsigned_short=0 + fi +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_unsigned_short" >&5 +$as_echo "$ac_cv_sizeof_unsigned_short" >&6; } + + + +cat >>confdefs.h <<_ACEOF +#define SIZEOF_UNSIGNED_SHORT $ac_cv_sizeof_unsigned_short +_ACEOF + + +# The cast to long int works around a bug in the HP C Compiler +# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects +# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'. +# This bug is HP SR number 8606223364. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of int" >&5 +$as_echo_n "checking size of int... " >&6; } +if ${ac_cv_sizeof_int+:} false; then : + $as_echo_n "(cached) " >&6 +else + if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (int))" "ac_cv_sizeof_int" "$db_includes +"; then : + +else + if test "$ac_cv_type_int" = yes; then + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error 77 "cannot compute sizeof (int) +See \`config.log' for more details" "$LINENO" 5; } + else + ac_cv_sizeof_int=0 + fi +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_int" >&5 +$as_echo "$ac_cv_sizeof_int" >&6; } + + + +cat >>confdefs.h <<_ACEOF +#define SIZEOF_INT $ac_cv_sizeof_int +_ACEOF + + +# The cast to long int works around a bug in the HP C Compiler +# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects +# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'. +# This bug is HP SR number 8606223364. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of unsigned int" >&5 +$as_echo_n "checking size of unsigned int... " >&6; } +if ${ac_cv_sizeof_unsigned_int+:} false; then : + $as_echo_n "(cached) " >&6 +else + if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (unsigned int))" "ac_cv_sizeof_unsigned_int" "$db_includes +"; then : + +else + if test "$ac_cv_type_unsigned_int" = yes; then + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error 77 "cannot compute sizeof (unsigned int) +See \`config.log' for more details" "$LINENO" 5; } + else + ac_cv_sizeof_unsigned_int=0 + fi +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_unsigned_int" >&5 +$as_echo "$ac_cv_sizeof_unsigned_int" >&6; } + + + +cat >>confdefs.h <<_ACEOF +#define SIZEOF_UNSIGNED_INT $ac_cv_sizeof_unsigned_int +_ACEOF + + +# The cast to long int works around a bug in the HP C Compiler +# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects +# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'. +# This bug is HP SR number 8606223364. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of long" >&5 +$as_echo_n "checking size of long... " >&6; } +if ${ac_cv_sizeof_long+:} false; then : + $as_echo_n "(cached) " >&6 +else + if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (long))" "ac_cv_sizeof_long" "$db_includes +"; then : + +else + if test "$ac_cv_type_long" = yes; then + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error 77 "cannot compute sizeof (long) +See \`config.log' for more details" "$LINENO" 5; } + else + ac_cv_sizeof_long=0 + fi +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_long" >&5 +$as_echo "$ac_cv_sizeof_long" >&6; } + + + +cat >>confdefs.h <<_ACEOF +#define SIZEOF_LONG $ac_cv_sizeof_long +_ACEOF + + +# The cast to long int works around a bug in the HP C Compiler +# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects +# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'. +# This bug is HP SR number 8606223364. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of unsigned long" >&5 +$as_echo_n "checking size of unsigned long... " >&6; } +if ${ac_cv_sizeof_unsigned_long+:} false; then : + $as_echo_n "(cached) " >&6 +else + if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (unsigned long))" "ac_cv_sizeof_unsigned_long" "$db_includes +"; then : + +else + if test "$ac_cv_type_unsigned_long" = yes; then + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error 77 "cannot compute sizeof (unsigned long) +See \`config.log' for more details" "$LINENO" 5; } + else + ac_cv_sizeof_unsigned_long=0 + fi +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_unsigned_long" >&5 +$as_echo "$ac_cv_sizeof_unsigned_long" >&6; } + + + +cat >>confdefs.h <<_ACEOF +#define SIZEOF_UNSIGNED_LONG $ac_cv_sizeof_unsigned_long +_ACEOF + + +# The cast to long int works around a bug in the HP C Compiler +# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects +# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'. +# This bug is HP SR number 8606223364. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of long long" >&5 +$as_echo_n "checking size of long long... " >&6; } +if ${ac_cv_sizeof_long_long+:} false; then : + $as_echo_n "(cached) " >&6 +else + if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (long long))" "ac_cv_sizeof_long_long" "$db_includes +"; then : + +else + if test "$ac_cv_type_long_long" = yes; then + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error 77 "cannot compute sizeof (long long) +See \`config.log' for more details" "$LINENO" 5; } + else + ac_cv_sizeof_long_long=0 + fi +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_long_long" >&5 +$as_echo "$ac_cv_sizeof_long_long" >&6; } + + + +cat >>confdefs.h <<_ACEOF +#define SIZEOF_LONG_LONG $ac_cv_sizeof_long_long +_ACEOF + + +# The cast to long int works around a bug in the HP C Compiler +# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects +# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'. +# This bug is HP SR number 8606223364. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of unsigned long long" >&5 +$as_echo_n "checking size of unsigned long long... " >&6; } +if ${ac_cv_sizeof_unsigned_long_long+:} false; then : + $as_echo_n "(cached) " >&6 +else + if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (unsigned long long))" "ac_cv_sizeof_unsigned_long_long" "$db_includes +"; then : + +else + if test "$ac_cv_type_unsigned_long_long" = yes; then + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error 77 "cannot compute sizeof (unsigned long long) +See \`config.log' for more details" "$LINENO" 5; } + else + ac_cv_sizeof_unsigned_long_long=0 + fi +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_unsigned_long_long" >&5 +$as_echo "$ac_cv_sizeof_unsigned_long_long" >&6; } + + + +cat >>confdefs.h <<_ACEOF +#define SIZEOF_UNSIGNED_LONG_LONG $ac_cv_sizeof_unsigned_long_long +_ACEOF + + +# The cast to long int works around a bug in the HP C Compiler +# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects +# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'. +# This bug is HP SR number 8606223364. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of char *" >&5 +$as_echo_n "checking size of char *... " >&6; } +if ${ac_cv_sizeof_char_p+:} false; then : + $as_echo_n "(cached) " >&6 +else + if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (char *))" "ac_cv_sizeof_char_p" "$db_includes +"; then : + +else + if test "$ac_cv_type_char_p" = yes; then + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error 77 "cannot compute sizeof (char *) +See \`config.log' for more details" "$LINENO" 5; } + else + ac_cv_sizeof_char_p=0 + fi +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_char_p" >&5 +$as_echo "$ac_cv_sizeof_char_p" >&6; } + + + +cat >>confdefs.h <<_ACEOF +#define SIZEOF_CHAR_P $ac_cv_sizeof_char_p +_ACEOF + + + +# We look for u_char, u_short, u_int, u_long -- if we can't find them, +# we create our own. + +ac_fn_c_check_type "$LINENO" "u_char" "ac_cv_type_u_char" "$db_includes +" +if test "x$ac_cv_type_u_char" = xyes; then : + +else + u_char_decl="typedef unsigned char u_char;" +fi + + + +ac_fn_c_check_type "$LINENO" "u_short" "ac_cv_type_u_short" "$db_includes +" +if test "x$ac_cv_type_u_short" = xyes; then : + +else + u_short_decl="typedef unsigned short u_short;" +fi + + + +ac_fn_c_check_type "$LINENO" "u_int" "ac_cv_type_u_int" "$db_includes +" +if test "x$ac_cv_type_u_int" = xyes; then : + +else + u_int_decl="typedef unsigned int u_int;" +fi + + + +ac_fn_c_check_type "$LINENO" "u_long" "ac_cv_type_u_long" "$db_includes +" +if test "x$ac_cv_type_u_long" = xyes; then : + +else + u_long_decl="typedef unsigned long u_long;" +fi + + +# We look for fixed-size variants of u_char, u_short, u_int, u_long as well. + +ac_fn_c_check_type "$LINENO" "u_int8_t" "ac_cv_type_u_int8_t" "$db_includes +" +if test "x$ac_cv_type_u_int8_t" = xyes; then : + +else + + case "1" in + "$ac_cv_sizeof_unsigned_int") + u_int8_decl="typedef unsigned int u_int8_t;";; + "$ac_cv_sizeof_unsigned_char") + u_int8_decl="typedef unsigned char u_int8_t;";; + "$ac_cv_sizeof_unsigned_short") + u_int8_decl="typedef unsigned short u_int8_t;";; + "$ac_cv_sizeof_unsigned_long") + u_int8_decl="typedef unsigned long u_int8_t;";; + "$ac_cv_sizeof_unsigned_long_long") + u_int8_decl="typedef unsigned long long u_int8_t;";; + *) + if test "" != "notfatal"; then + as_fn_error $? "No unsigned 1-byte integral type" "$LINENO" 5 + fi;; + esac +fi + + + +ac_fn_c_check_type "$LINENO" "u_int16_t" "ac_cv_type_u_int16_t" "$db_includes +" +if test "x$ac_cv_type_u_int16_t" = xyes; then : + +else + + case "2" in + "$ac_cv_sizeof_unsigned_int") + u_int16_decl="typedef unsigned int u_int16_t;";; + "$ac_cv_sizeof_unsigned_char") + u_int16_decl="typedef unsigned char u_int16_t;";; + "$ac_cv_sizeof_unsigned_short") + u_int16_decl="typedef unsigned short u_int16_t;";; + "$ac_cv_sizeof_unsigned_long") + u_int16_decl="typedef unsigned long u_int16_t;";; + "$ac_cv_sizeof_unsigned_long_long") + u_int16_decl="typedef unsigned long long u_int16_t;";; + *) + if test "" != "notfatal"; then + as_fn_error $? "No unsigned 2-byte integral type" "$LINENO" 5 + fi;; + esac +fi + + + +ac_fn_c_check_type "$LINENO" "int16_t" "ac_cv_type_int16_t" "$db_includes +" +if test "x$ac_cv_type_int16_t" = xyes; then : + +else + + case "2" in + "$ac_cv_sizeof_int") + int16_decl="typedef int int16_t;";; + "$ac_cv_sizeof_char") + int16_decl="typedef char int16_t;";; + "$ac_cv_sizeof_short") + int16_decl="typedef short int16_t;";; + "$ac_cv_sizeof_long") + int16_decl="typedef long int16_t;";; + "$ac_cv_sizeof_long_long") + int16_decl="typedef long long int16_t;";; + *) + if test "" != "notfatal"; then + as_fn_error $? "No signed 2-byte integral type" "$LINENO" 5 + fi;; + esac +fi + + + +ac_fn_c_check_type "$LINENO" "u_int32_t" "ac_cv_type_u_int32_t" "$db_includes +" +if test "x$ac_cv_type_u_int32_t" = xyes; then : + +else + + case "4" in + "$ac_cv_sizeof_unsigned_int") + u_int32_decl="typedef unsigned int u_int32_t;";; + "$ac_cv_sizeof_unsigned_char") + u_int32_decl="typedef unsigned char u_int32_t;";; + "$ac_cv_sizeof_unsigned_short") + u_int32_decl="typedef unsigned short u_int32_t;";; + "$ac_cv_sizeof_unsigned_long") + u_int32_decl="typedef unsigned long u_int32_t;";; + "$ac_cv_sizeof_unsigned_long_long") + u_int32_decl="typedef unsigned long long u_int32_t;";; + *) + if test "" != "notfatal"; then + as_fn_error $? "No unsigned 4-byte integral type" "$LINENO" 5 + fi;; + esac +fi + + + +ac_fn_c_check_type "$LINENO" "int32_t" "ac_cv_type_int32_t" "$db_includes +" +if test "x$ac_cv_type_int32_t" = xyes; then : + +else + + case "4" in + "$ac_cv_sizeof_int") + int32_decl="typedef int int32_t;";; + "$ac_cv_sizeof_char") + int32_decl="typedef char int32_t;";; + "$ac_cv_sizeof_short") + int32_decl="typedef short int32_t;";; + "$ac_cv_sizeof_long") + int32_decl="typedef long int32_t;";; + "$ac_cv_sizeof_long_long") + int32_decl="typedef long long int32_t;";; + *) + if test "" != "notfatal"; then + as_fn_error $? "No signed 4-byte integral type" "$LINENO" 5 + fi;; + esac +fi + + + +ac_fn_c_check_type "$LINENO" "u_int64_t" "ac_cv_type_u_int64_t" "$db_includes +" +if test "x$ac_cv_type_u_int64_t" = xyes; then : + +else + + case "8" in + "$ac_cv_sizeof_unsigned_int") + u_int64_decl="typedef unsigned int u_int64_t;";; + "$ac_cv_sizeof_unsigned_char") + u_int64_decl="typedef unsigned char u_int64_t;";; + "$ac_cv_sizeof_unsigned_short") + u_int64_decl="typedef unsigned short u_int64_t;";; + "$ac_cv_sizeof_unsigned_long") + u_int64_decl="typedef unsigned long u_int64_t;";; + "$ac_cv_sizeof_unsigned_long_long") + u_int64_decl="typedef unsigned long long u_int64_t;";; + *) + if test "notfatal" != "notfatal"; then + as_fn_error $? "No unsigned 8-byte integral type" "$LINENO" 5 + fi;; + esac +fi + + + +ac_fn_c_check_type "$LINENO" "int64_t" "ac_cv_type_int64_t" "$db_includes +" +if test "x$ac_cv_type_int64_t" = xyes; then : + +else + + case "8" in + "$ac_cv_sizeof_int") + int64_decl="typedef int int64_t;";; + "$ac_cv_sizeof_char") + int64_decl="typedef char int64_t;";; + "$ac_cv_sizeof_short") + int64_decl="typedef short int64_t;";; + "$ac_cv_sizeof_long") + int64_decl="typedef long int64_t;";; + "$ac_cv_sizeof_long_long") + int64_decl="typedef long long int64_t;";; + *) + if test "notfatal" != "notfatal"; then + as_fn_error $? "No signed 8-byte integral type" "$LINENO" 5 + fi;; + esac +fi + + +# No currently autoconf'd systems lack FILE, off_t pid_t, size_t, time_t. +# +# We require them, we don't try to substitute our own if we can't find them. + +as_ac_Type=`$as_echo "ac_cv_type_FILE *" | $as_tr_sh` +ac_fn_c_check_type "$LINENO" "FILE *" "$as_ac_Type" "$db_includes +" +if eval test \"x\$"$as_ac_Type"\" = x"yes"; then : + +else + as_fn_error $? "No FILE type." "$LINENO" 5 +fi + + +ac_fn_c_check_type "$LINENO" "off_t" "ac_cv_type_off_t" "$db_includes +" +if test "x$ac_cv_type_off_t" = xyes; then : + +else + as_fn_error $? "No off_t type." "$LINENO" 5 +fi + + +ac_fn_c_check_type "$LINENO" "pid_t" "ac_cv_type_pid_t" "$db_includes +" +if test "x$ac_cv_type_pid_t" = xyes; then : + +else + as_fn_error $? "No pid_t type." "$LINENO" 5 +fi + + +ac_fn_c_check_type "$LINENO" "size_t" "ac_cv_type_size_t" "$db_includes +" +if test "x$ac_cv_type_size_t" = xyes; then : + +else + as_fn_error $? "No size_t type." "$LINENO" 5 +fi + + +ac_fn_c_check_type "$LINENO" "time_t" "ac_cv_type_time_t" "$db_includes +" +if test "x$ac_cv_type_time_t" = xyes; then : + +else + as_fn_error $? "No time_t type." "$LINENO" 5 +fi + + +# Check for ssize_t -- if none exists, find a signed integral type that's +# the same size as a size_t. +# The cast to long int works around a bug in the HP C Compiler +# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects +# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'. +# This bug is HP SR number 8606223364. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of size_t" >&5 +$as_echo_n "checking size of size_t... " >&6; } +if ${ac_cv_sizeof_size_t+:} false; then : + $as_echo_n "(cached) " >&6 +else + if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (size_t))" "ac_cv_sizeof_size_t" "$db_includes +"; then : + +else + if test "$ac_cv_type_size_t" = yes; then + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error 77 "cannot compute sizeof (size_t) +See \`config.log' for more details" "$LINENO" 5; } + else + ac_cv_sizeof_size_t=0 + fi +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_size_t" >&5 +$as_echo "$ac_cv_sizeof_size_t" >&6; } + + + +cat >>confdefs.h <<_ACEOF +#define SIZEOF_SIZE_T $ac_cv_sizeof_size_t +_ACEOF + + + +ac_fn_c_check_type "$LINENO" "ssize_t" "ac_cv_type_ssize_t" "$db_includes +" +if test "x$ac_cv_type_ssize_t" = xyes; then : + +else + + case "$ac_cv_sizeof_size_t" in + "$ac_cv_sizeof_int") + ssize_t_decl="typedef int ssize_t;";; + "$ac_cv_sizeof_char") + ssize_t_decl="typedef char ssize_t;";; + "$ac_cv_sizeof_short") + ssize_t_decl="typedef short ssize_t;";; + "$ac_cv_sizeof_long") + ssize_t_decl="typedef long ssize_t;";; + "$ac_cv_sizeof_long_long") + ssize_t_decl="typedef long long ssize_t;";; + *) + if test "" != "notfatal"; then + as_fn_error $? "No signed $ac_cv_sizeof_size_t-byte integral type" "$LINENO" 5 + fi;; + esac +fi + + +# Check for uintmax_t -- if none exists, find the largest unsigned integral +# type available. + +ac_fn_c_check_type "$LINENO" "uintmax_t" "ac_cv_type_uintmax_t" "$ac_includes_default" +if test "x$ac_cv_type_uintmax_t" = xyes; then : + +else + ac_fn_c_check_type "$LINENO" "unsigned long long" "ac_cv_type_unsigned_long_long" "$db_includes +" +if test "x$ac_cv_type_unsigned_long_long" = xyes; then : + uintmax_t_decl="typedef unsigned long long uintmax_t;" +else + uintmax_t_decl="typedef unsigned long uintmax_t;" +fi + +fi + + +# Check for uintptr_t -- if none exists, find an integral type which is +# the same size as a pointer. + +ac_fn_c_check_type "$LINENO" "uintptr_t" "ac_cv_type_uintptr_t" "$ac_includes_default" +if test "x$ac_cv_type_uintptr_t" = xyes; then : + +else + + case "$ac_cv_sizeof_char_p" in + "$ac_cv_sizeof_unsigned_int") + uintptr_t_decl="typedef unsigned int uintptr_t;";; + "$ac_cv_sizeof_unsigned_char") + uintptr_t_decl="typedef unsigned char uintptr_t;";; + "$ac_cv_sizeof_unsigned_short") + uintptr_t_decl="typedef unsigned short uintptr_t;";; + "$ac_cv_sizeof_unsigned_long") + uintptr_t_decl="typedef unsigned long uintptr_t;";; + "$ac_cv_sizeof_unsigned_long_long") + uintptr_t_decl="typedef unsigned long long uintptr_t;";; + *) + if test "" != "notfatal"; then + as_fn_error $? "No unsigned $ac_cv_sizeof_char_p-byte integral type" "$LINENO" 5 + fi;; + esac +fi + + + + ac_fn_c_check_type "$LINENO" "socklen_t" "ac_cv_type_socklen_t" "$db_includes +#ifdef HAVE_SYS_SOCKET_H +#include +#endif +" +if test "x$ac_cv_type_socklen_t" = xyes; then : + +else + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for socklen_t equivalent" >&5 +$as_echo_n "checking for socklen_t equivalent... " >&6; } + if ${db_cv_socklen_t_equiv+:} false; then : + $as_echo_n "(cached) " >&6 +else + # Systems have either "struct sockaddr *" or + # "void *" as the second argument to getpeername + db_cv_socklen_t_equiv= + for arg2 in "struct sockaddr" void; do + for t in int size_t "unsigned int" "long int" "unsigned long int"; do + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$db_includes +#ifdef HAVE_SYS_SOCKET_H +#include +#endif + int getpeername (int, $arg2 *, $t *); +int +main () +{ +$t len; + getpeername (0, 0, &len); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + db_cv_socklen_t_equiv="$t" +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + test "$db_cv_socklen_t_equiv" != "" && break + done + test "$db_cv_socklen_t_equiv" != "" && break + done + +fi + + if test "$db_cv_socklen_t_equiv" = ""; then + as_fn_error $? "Cannot find a type to use in place of socklen_t" "$LINENO" 5 + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $db_cv_socklen_t_equiv" >&5 +$as_echo "$db_cv_socklen_t_equiv" >&6; } + +cat >>confdefs.h <<_ACEOF +#define socklen_t $db_cv_socklen_t_equiv +_ACEOF + +fi + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C exit success/failure values" >&5 +$as_echo_n "checking for ANSI C exit success/failure values... " >&6; } +if ${db_cv_exit_defines+:} false; then : + $as_echo_n "(cached) " >&6 +else + +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +int +main () +{ +return (EXIT_SUCCESS); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + db_cv_exit_defines=yes +else + db_cv_exit_defines=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $db_cv_exit_defines" >&5 +$as_echo "$db_cv_exit_defines" >&6; } +if test "$db_cv_exit_defines" = "yes"; then + $as_echo "#define HAVE_EXIT_SUCCESS 1" >>confdefs.h + + +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for getopt optreset variable" >&5 +$as_echo_n "checking for getopt optreset variable... " >&6; } +if ${db_cv_optreset+:} false; then : + $as_echo_n "(cached) " >&6 +else + +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +int +main () +{ +extern int optreset; optreset = 1; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + db_cv_optreset=yes +else + db_cv_optreset=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $db_cv_optreset" >&5 +$as_echo "$db_cv_optreset" >&6; } +if test "$db_cv_optreset" = "yes"; then + $as_echo "#define HAVE_GETOPT_OPTRESET 1" >>confdefs.h + + +fi + +# Check for mutexes. +# We do this first because it changes $LIBSO_LIBS. + + +# Mutexes we don't test for, but want the #defines to exist for other ports. + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for mutexes" >&5 +$as_echo_n "checking for mutexes... " >&6; } +if ${db_cv_mutex+:} false; then : + $as_echo_n "(cached) " >&6 +else + + +orig_libs=$LIBS + +db_cv_mutex=no + +# Mutexes can be disabled. +if test "$db_cv_build_mutexsupport" = no; then + db_cv_mutex=disabled; +fi + +# User-specified Win32 mutexes (MinGW build) +if test "$db_cv_mingw" = yes; then + db_cv_mutex=win32/gcc +fi + +if test "$db_cv_mutex" = no; then + # Check for the availability of POSIX or UI mutexes; also check + # whether the user has specified POSIX with --enable-posixmutexes. + # + # There are two different reasons to specify mutexes: First, the + # application is already using one type of mutex and doesn't want + # to mix-and-match (for example, on Solaris, which has POSIX, UI + # and LWP mutexes). Second, the application's POSIX pthreads + # mutexes don't support inter-process locking, but the application + # wants to use them anyway (for example, some Linux and *BSD systems). + # + # Test for POSIX threads before testing for UI/LWP threads, they are + # the Sun-recommended choice on Solaris. Also, there are Linux systems + # that support a UI compatibility mode, and applications are more + # likely to be written for POSIX threads than UI threads. + if test "$db_cv_posixmutexes" = yes; then + db_cv_mutex=posix_only; + fi + if test "$db_cv_uimutexes" = yes; then + db_cv_mutex=ui_only; + fi + + # POSIX.1 pthreads: pthread_XXX + # + # If we find POSIX pthreads mutexes but not the full interface, + # try to configure for just intra-process support. + case "$host_os" in + darwin*) + # Mac OS 10.7 Lion has broken pthread_*_setpshared() calls. + # Most BSD-like operating systems have pointers in their mutex + # and condition variables, and cannot be shared between + # proceses. Earlier Mac OS releases correctly returned EINVAL + # from *_setpshared(PTHREAD_PROCESS_SHARED), but 10.7 returns + # success. Since we can't trust those calls anymore we now + # avoid these probes for multiprocess pthreads. + ;; + *) + if test "$db_cv_mutex" = no -o "$db_cv_mutex" = posix_only; then + LIBS="$LIBS -lpthread" + +if test "$cross_compiling" = yes; then : + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#include +#include +int +main () +{ + + pthread_cond_t cond; + pthread_mutex_t mutex; + pthread_condattr_t condattr; + pthread_mutexattr_t mutexattr; + exit ( + pthread_condattr_init(&condattr) || + pthread_condattr_setpshared(&condattr, PTHREAD_PROCESS_SHARED) || + pthread_mutexattr_init(&mutexattr) || + pthread_mutexattr_setpshared(&mutexattr, PTHREAD_PROCESS_SHARED) || + pthread_cond_init(&cond, &condattr) || + pthread_mutex_init(&mutex, &mutexattr) || + pthread_mutex_lock(&mutex) || + pthread_mutex_unlock(&mutex) || + pthread_mutex_destroy(&mutex) || + pthread_cond_destroy(&cond) || + pthread_condattr_destroy(&condattr) || + pthread_mutexattr_destroy(&mutexattr)); + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + db_cv_mutex="POSIX/pthreads/library" +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#include +#include +main() { + pthread_cond_t cond; + pthread_mutex_t mutex; + pthread_condattr_t condattr; + pthread_mutexattr_t mutexattr; + exit ( + pthread_condattr_init(&condattr) || + pthread_condattr_setpshared(&condattr, PTHREAD_PROCESS_SHARED) || + pthread_mutexattr_init(&mutexattr) || + pthread_mutexattr_setpshared(&mutexattr, PTHREAD_PROCESS_SHARED) || + pthread_cond_init(&cond, &condattr) || + pthread_mutex_init(&mutex, &mutexattr) || + pthread_mutex_lock(&mutex) || + pthread_mutex_unlock(&mutex) || + pthread_mutex_destroy(&mutex) || + pthread_cond_destroy(&cond) || + pthread_condattr_destroy(&condattr) || + pthread_mutexattr_destroy(&mutexattr)); +} +_ACEOF +if ac_fn_c_try_run "$LINENO"; then : + db_cv_mutex="POSIX/pthreads/library" +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + + +if test "$cross_compiling" = yes; then : + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#include +#include +int +main () +{ + + pthread_cond_t cond; + pthread_condattr_t condattr; + exit(pthread_condattr_init(&condattr) || + pthread_cond_init(&cond, &condattr)); + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + db_cv_pthread_condinit_dupgood="yes" +else + db_cv_pthread_condinit_dupgood="no" +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#include +#include +main() { + pthread_cond_t cond; + pthread_condattr_t condattr; + exit(pthread_condattr_init(&condattr) || + pthread_cond_init(&cond, &condattr) || + pthread_cond_init(&cond, &condattr)); +} +_ACEOF +if ac_fn_c_try_run "$LINENO"; then : + db_cv_pthread_condinit_dupgood="yes" +else + db_cv_pthread_condinit_dupgood="no" +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + + +if test "$cross_compiling" = yes; then : + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#include +#include +int +main () +{ + + pthread_rwlock_t rwlock; + pthread_rwlockattr_t rwlockattr; + exit(pthread_rwlockattr_init(&rwlockattr) || + pthread_rwlock_init(&rwlock, &rwlockattr)); + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + db_cv_pthread_rwlockinit_dupgood="yes" +else + db_cv_pthread_rwlockinit_dupgood="no" +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#include +#include +main() { + pthread_rwlock_t rwlock; + pthread_rwlockattr_t rwlockattr; + exit(pthread_rwlockattr_init(&rwlockattr) || + pthread_rwlock_init(&rwlock, &rwlockattr) || + pthread_rwlock_init(&rwlock, &rwlockattr)); +} +_ACEOF +if ac_fn_c_try_run "$LINENO"; then : + db_cv_pthread_rwlockinit_dupgood="yes" +else + db_cv_pthread_rwlockinit_dupgood="no" +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + + LIBS="$orig_libs" + fi + if test "$db_cv_mutex" = no -o "$db_cv_mutex" = posix_only; then + +if test "$cross_compiling" = yes; then : + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#include +#include +int +main () +{ + + pthread_cond_t cond; + pthread_mutex_t mutex; + pthread_condattr_t condattr; + pthread_mutexattr_t mutexattr; + exit ( + pthread_condattr_init(&condattr) || + pthread_condattr_setpshared(&condattr, PTHREAD_PROCESS_SHARED) || + pthread_mutexattr_init(&mutexattr) || + pthread_mutexattr_setpshared(&mutexattr, PTHREAD_PROCESS_SHARED) || + pthread_cond_init(&cond, &condattr) || + pthread_mutex_init(&mutex, &mutexattr) || + pthread_mutex_lock(&mutex) || + pthread_mutex_unlock(&mutex) || + pthread_mutex_destroy(&mutex) || + pthread_cond_destroy(&cond) || + pthread_condattr_destroy(&condattr) || + pthread_mutexattr_destroy(&mutexattr)); + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + db_cv_mutex="POSIX/pthreads" +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#include +#include +main() { + pthread_cond_t cond; + pthread_mutex_t mutex; + pthread_condattr_t condattr; + pthread_mutexattr_t mutexattr; + exit ( + pthread_condattr_init(&condattr) || + pthread_condattr_setpshared(&condattr, PTHREAD_PROCESS_SHARED) || + pthread_mutexattr_init(&mutexattr) || + pthread_mutexattr_setpshared(&mutexattr, PTHREAD_PROCESS_SHARED) || + pthread_cond_init(&cond, &condattr) || + pthread_mutex_init(&mutex, &mutexattr) || + pthread_mutex_lock(&mutex) || + pthread_mutex_unlock(&mutex) || + pthread_mutex_destroy(&mutex) || + pthread_cond_destroy(&cond) || + pthread_condattr_destroy(&condattr) || + pthread_mutexattr_destroy(&mutexattr)); +} +_ACEOF +if ac_fn_c_try_run "$LINENO"; then : + db_cv_mutex="POSIX/pthreads" +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + + +if test "$cross_compiling" = yes; then : + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#include +#include +int +main () +{ + + pthread_cond_t cond; + pthread_condattr_t condattr; + exit(pthread_condattr_init(&condattr) || + pthread_cond_init(&cond, &condattr)); + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + db_cv_pthread_condinit_dupgood="yes" +else + db_cv_pthread_condinit_dupgood="no" +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#include +#include +main() { + pthread_cond_t cond; + pthread_condattr_t condattr; + exit(pthread_condattr_init(&condattr) || + pthread_cond_init(&cond, &condattr) || + pthread_cond_init(&cond, &condattr)); +} +_ACEOF +if ac_fn_c_try_run "$LINENO"; then : + db_cv_pthread_condinit_dupgood="yes" +else + db_cv_pthread_condinit_dupgood="no" +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + + +if test "$cross_compiling" = yes; then : + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#include +#include +int +main () +{ + + pthread_rwlock_t rwlock; + pthread_rwlockattr_t rwlockattr; + exit(pthread_rwlockattr_init(&rwlockattr) || + pthread_rwlock_init(&rwlock, &rwlockattr)); + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + db_cv_pthread_rwlockinit_dupgood="yes" +else + db_cv_pthread_rwlockinit_dupgood="no" +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#include +#include +main() { + pthread_rwlock_t rwlock; + pthread_rwlockattr_t rwlockattr; + exit(pthread_rwlockattr_init(&rwlockattr) || + pthread_rwlock_init(&rwlock, &rwlockattr) || + pthread_rwlock_init(&rwlock, &rwlockattr)); +} +_ACEOF +if ac_fn_c_try_run "$LINENO"; then : + db_cv_pthread_rwlockinit_dupgood="yes" +else + db_cv_pthread_rwlockinit_dupgood="no" +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + + fi + ;; + esac + # We probe for private pthreads only when the user has asked for posix + # mutexes and we don't have a multiprocess pthreads library available. + if test "$db_cv_mutex" = posix_only; then + +if test "$cross_compiling" = yes; then : + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#include +#include +int +main () +{ + + pthread_cond_t cond; + pthread_mutex_t mutex; + pthread_condattr_t condattr; + pthread_mutexattr_t mutexattr; + exit ( + pthread_condattr_init(&condattr) || + pthread_mutexattr_init(&mutexattr) || + pthread_cond_init(&cond, &condattr) || + pthread_mutex_init(&mutex, &mutexattr) || + pthread_mutex_lock(&mutex) || + pthread_mutex_unlock(&mutex) || + pthread_mutex_destroy(&mutex) || + pthread_cond_destroy(&cond) || + pthread_condattr_destroy(&condattr) || + pthread_mutexattr_destroy(&mutexattr)); + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + db_cv_mutex="POSIX/pthreads/private" +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#include +#include +main() { + pthread_cond_t cond; + pthread_mutex_t mutex; + pthread_condattr_t condattr; + pthread_mutexattr_t mutexattr; + exit ( + pthread_condattr_init(&condattr) || + pthread_mutexattr_init(&mutexattr) || + pthread_cond_init(&cond, &condattr) || + pthread_mutex_init(&mutex, &mutexattr) || + pthread_mutex_lock(&mutex) || + pthread_mutex_unlock(&mutex) || + pthread_mutex_destroy(&mutex) || + pthread_cond_destroy(&cond) || + pthread_condattr_destroy(&condattr) || + pthread_mutexattr_destroy(&mutexattr)); +} +_ACEOF +if ac_fn_c_try_run "$LINENO"; then : + db_cv_mutex="POSIX/pthreads/private" +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + + +if test "$cross_compiling" = yes; then : + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#include +#include +int +main () +{ + + pthread_cond_t cond; + pthread_condattr_t condattr; + exit(pthread_condattr_init(&condattr) || + pthread_cond_init(&cond, &condattr)); + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + db_cv_pthread_condinit_dupgood="yes" +else + db_cv_pthread_condinit_dupgood="no" +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#include +#include +main() { + pthread_cond_t cond; + pthread_condattr_t condattr; + exit(pthread_condattr_init(&condattr) || + pthread_cond_init(&cond, &condattr) || + pthread_cond_init(&cond, &condattr)); +} +_ACEOF +if ac_fn_c_try_run "$LINENO"; then : + db_cv_pthread_condinit_dupgood="yes" +else + db_cv_pthread_condinit_dupgood="no" +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + + +if test "$cross_compiling" = yes; then : + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#include +#include +int +main () +{ + + pthread_rwlock_t rwlock; + pthread_rwlockattr_t rwlockattr; + exit(pthread_rwlockattr_init(&rwlockattr) || + pthread_rwlock_init(&rwlock, &rwlockattr)); + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + db_cv_pthread_rwlockinit_dupgood="yes" +else + db_cv_pthread_rwlockinit_dupgood="no" +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#include +#include +main() { + pthread_rwlock_t rwlock; + pthread_rwlockattr_t rwlockattr; + exit(pthread_rwlockattr_init(&rwlockattr) || + pthread_rwlock_init(&rwlock, &rwlockattr) || + pthread_rwlock_init(&rwlock, &rwlockattr)); +} +_ACEOF +if ac_fn_c_try_run "$LINENO"; then : + db_cv_pthread_rwlockinit_dupgood="yes" +else + db_cv_pthread_rwlockinit_dupgood="no" +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + + fi + if test "$db_cv_mutex" = posix_only; then + LIBS="$LIBS -lpthread" + +if test "$cross_compiling" = yes; then : + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#include +#include +int +main () +{ + + pthread_cond_t cond; + pthread_mutex_t mutex; + pthread_condattr_t condattr; + pthread_mutexattr_t mutexattr; + exit ( + pthread_condattr_init(&condattr) || + pthread_mutexattr_init(&mutexattr) || + pthread_cond_init(&cond, &condattr) || + pthread_mutex_init(&mutex, &mutexattr) || + pthread_mutex_lock(&mutex) || + pthread_mutex_unlock(&mutex) || + pthread_mutex_destroy(&mutex) || + pthread_cond_destroy(&cond) || + pthread_condattr_destroy(&condattr) || + pthread_mutexattr_destroy(&mutexattr)); + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + db_cv_mutex="POSIX/pthreads/library/private" +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#include +#include +main() { + pthread_cond_t cond; + pthread_mutex_t mutex; + pthread_condattr_t condattr; + pthread_mutexattr_t mutexattr; + exit ( + pthread_condattr_init(&condattr) || + pthread_mutexattr_init(&mutexattr) || + pthread_cond_init(&cond, &condattr) || + pthread_mutex_init(&mutex, &mutexattr) || + pthread_mutex_lock(&mutex) || + pthread_mutex_unlock(&mutex) || + pthread_mutex_destroy(&mutex) || + pthread_cond_destroy(&cond) || + pthread_condattr_destroy(&condattr) || + pthread_mutexattr_destroy(&mutexattr)); +} +_ACEOF +if ac_fn_c_try_run "$LINENO"; then : + db_cv_mutex="POSIX/pthreads/library/private" +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + + +if test "$cross_compiling" = yes; then : + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#include +#include +int +main () +{ + + pthread_cond_t cond; + pthread_condattr_t condattr; + exit(pthread_condattr_init(&condattr) || + pthread_cond_init(&cond, &condattr)); + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + db_cv_pthread_condinit_dupgood="yes" +else + db_cv_pthread_condinit_dupgood="no" +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#include +#include +main() { + pthread_cond_t cond; + pthread_condattr_t condattr; + exit(pthread_condattr_init(&condattr) || + pthread_cond_init(&cond, &condattr) || + pthread_cond_init(&cond, &condattr)); +} +_ACEOF +if ac_fn_c_try_run "$LINENO"; then : + db_cv_pthread_condinit_dupgood="yes" +else + db_cv_pthread_condinit_dupgood="no" +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + + +if test "$cross_compiling" = yes; then : + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#include +#include +int +main () +{ + + pthread_rwlock_t rwlock; + pthread_rwlockattr_t rwlockattr; + exit(pthread_rwlockattr_init(&rwlockattr) || + pthread_rwlock_init(&rwlock, &rwlockattr)); + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + db_cv_pthread_rwlockinit_dupgood="yes" +else + db_cv_pthread_rwlockinit_dupgood="no" +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#include +#include +main() { + pthread_rwlock_t rwlock; + pthread_rwlockattr_t rwlockattr; + exit(pthread_rwlockattr_init(&rwlockattr) || + pthread_rwlock_init(&rwlock, &rwlockattr) || + pthread_rwlock_init(&rwlock, &rwlockattr)); +} +_ACEOF +if ac_fn_c_try_run "$LINENO"; then : + db_cv_pthread_rwlockinit_dupgood="yes" +else + db_cv_pthread_rwlockinit_dupgood="no" +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + + LIBS="$orig_libs" + fi + if test "$db_cv_mutex" = posix_only; then + as_fn_error $? "unable to find POSIX 1003.1 mutex interfaces" "$LINENO" 5 + fi + + # LWP threads: _lwp_XXX + if test "$db_cv_mutex" = no; then + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + + #include +int +main () +{ + + static lwp_mutex_t mi = SHAREDMUTEX; + static lwp_cond_t ci = SHAREDCV; + lwp_mutex_t mutex = mi; + lwp_cond_t cond = ci; + exit ( + _lwp_mutex_lock(&mutex) || + _lwp_mutex_unlock(&mutex)); + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + db_cv_mutex=Solaris/lwp +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + fi + + # UI threads: thr_XXX + if test "$db_cv_mutex" = no -o "$db_cv_mutex" = ui_only; then + LIBS="$LIBS -lthread" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + + #include + #include +int +main () +{ + + mutex_t mutex; + cond_t cond; + int type = USYNC_PROCESS; + exit ( + mutex_init(&mutex, type, NULL) || + cond_init(&cond, type, NULL) || + mutex_lock(&mutex) || + mutex_unlock(&mutex)); + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + db_cv_mutex=UI/threads/library +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + LIBS="$orig_libs" + fi + if test "$db_cv_mutex" = no -o "$db_cv_mutex" = ui_only; then + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + + #include + #include +int +main () +{ + + mutex_t mutex; + cond_t cond; + int type = USYNC_PROCESS; + exit ( + mutex_init(&mutex, type, NULL) || + cond_init(&cond, type, NULL) || + mutex_lock(&mutex) || + mutex_unlock(&mutex)); + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + db_cv_mutex=UI/threads +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + fi + if test "$db_cv_mutex" = ui_only; then + as_fn_error $? "unable to find UI mutex interfaces" "$LINENO" 5 + fi + + # We're done testing for pthreads-style mutexes. Next, check for + # test-and-set mutexes. Check first for hybrid implementations, + # because we check for them even if we've already found a + # pthreads-style mutex and they're the most common architectures + # anyway. + # + # x86/gcc: FreeBSD, NetBSD, BSD/OS, Linux + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + #if (defined(i386) || defined(__i386__)) && defined(__GNUC__) + exit(0); + #else + FAIL TO COMPILE/LINK + #endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + db_cv_mutex="$db_cv_mutex/x86/gcc-assembly" +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + + # x86_64/gcc: FreeBSD, NetBSD, BSD/OS, Linux + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + #if (defined(x86_64) || defined(__x86_64__)) && defined(__GNUC__) + exit(0); + #else + FAIL TO COMPILE/LINK + #endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + db_cv_mutex="$db_cv_mutex/x86_64/gcc-assembly" +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + + # Solaris is one of the systems where we can configure hybrid mutexes. + # However, we require the membar_enter function for that, and only newer + # Solaris releases have it. Check to see if we can configure hybrids. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + + #include + #include +int +main () +{ + + typedef lock_t tsl_t; + lock_t x; + _lock_try(&x); + _lock_clear(&x); + membar_enter(); + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + db_cv_mutex="$db_cv_mutex/Solaris/_lock_try/membar" +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + + # Sparc/gcc: SunOS, Solaris, ultrasparc assembler support + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + #if defined(__sparc__) && defined(__GNUC__) + asm volatile ("membar #StoreStore|#StoreLoad|#LoadStore"); + exit(0); + #else + FAIL TO COMPILE/LINK + #endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + db_cv_mutex="$db_cv_mutex/Sparc/gcc-assembly" +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + + # We're done testing for any hybrid mutex implementations. If we did + # not find a pthreads-style mutex, but did find a test-and-set mutex, + # we set db_cv_mutex to "no/XXX" -- clean that up. + db_cv_mutex=`echo $db_cv_mutex | sed 's/^no\///'` +fi + +# If we still don't have a mutex implementation yet, continue testing for a +# test-and-set mutex implementation. + +# _lock_try/_lock_clear: Solaris +# On Solaris systems without other mutex interfaces, DB uses the undocumented +# _lock_try _lock_clear function calls instead of either the sema_trywait(3T) +# or sema_wait(3T) function calls. This is because of problems in those +# interfaces in some releases of the Solaris C library. +if test "$db_cv_mutex" = no; then +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#include +#include +int +main () +{ + + typedef lock_t tsl_t; + lock_t x; + _lock_try(&x); + _lock_clear(&x); + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + db_cv_mutex=Solaris/_lock_try +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi + +# msemaphore: HPPA only +# Try HPPA before general msem test, it needs special alignment. +if test "$db_cv_mutex" = no; then +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#include +int +main () +{ + +#if defined(__hppa) + typedef msemaphore tsl_t; + msemaphore x; + msem_init(&x, 0); + msem_lock(&x, 0); + msem_unlock(&x, 0); + exit(0); +#else + FAIL TO COMPILE/LINK +#endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + db_cv_mutex=HP/msem_init +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi + +# msemaphore: AIX, OSF/1 +if test "$db_cv_mutex" = no; then +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#include +#include +int +main () +{ + + typedef msemaphore tsl_t; + msemaphore x; + msem_init(&x, 0); + msem_lock(&x, 0); + msem_unlock(&x, 0); + exit(0); + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + db_cv_mutex=UNIX/msem_init +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi + +# ReliantUNIX +if test "$db_cv_mutex" = no; then +LIBS="$LIBS -lmproc" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#include +int +main () +{ + + typedef spinlock_t tsl_t; + spinlock_t x; + initspin(&x, 1); + cspinlock(&x); + spinunlock(&x); + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + db_cv_mutex=ReliantUNIX/initspin +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS="$orig_libs" +fi + +# SCO: UnixWare has threads in libthread, but OpenServer doesn't. +if test "$db_cv_mutex" = no; then +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + +#if defined(__USLC__) + exit(0); +#else + FAIL TO COMPILE/LINK +#endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + db_cv_mutex=SCO/x86/cc-assembly +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi + +# abilock_t: SGI +if test "$db_cv_mutex" = no; then +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#include +int +main () +{ + + typedef abilock_t tsl_t; + abilock_t x; + init_lock(&x); + acquire_lock(&x); + release_lock(&x); + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + db_cv_mutex=SGI/init_lock +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi + +# sema_t: Solaris +# The sema_XXX calls do not work on Solaris 5.5. I see no reason to ever +# turn this test on, unless we find some other platform that uses the old +# POSIX.1 interfaces. +if test "$db_cv_mutex" = DOESNT_WORK; then +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#include +int +main () +{ + + typedef sema_t tsl_t; + sema_t x; + sema_init(&x, 1, USYNC_PROCESS, NULL); + sema_wait(&x); + sema_post(&x); + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + db_cv_mutex=UNIX/sema_init +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi + +# _check_lock/_clear_lock: AIX +if test "$db_cv_mutex" = no; then +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#include +int +main () +{ + + int x; + _check_lock(&x,0,1); + _clear_lock(&x,0); + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + db_cv_mutex=AIX/_check_lock +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi + +# _spin_lock_try/_spin_unlock: Apple/Darwin +if test "$db_cv_mutex" = no; then +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + int x; + _spin_lock_try(&x); + _spin_unlock(&x); + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + db_cv_mutex=Darwin/_spin_lock_try +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi + +# Tru64/cc +if test "$db_cv_mutex" = no; then +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + +#if defined(__alpha) && defined(__DECC) + exit(0); +#else + FAIL TO COMPILE/LINK +#endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + db_cv_mutex=Tru64/cc-assembly +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi + +# Alpha/gcc +if test "$db_cv_mutex" = no; then +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + +#if defined(__alpha) && defined(__GNUC__) + exit(0); +#else + FAIL TO COMPILE/LINK +#endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + db_cv_mutex=ALPHA/gcc-assembly +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi + +# ARM/gcc: Linux +if test "$db_cv_mutex" = no; then +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + +#if defined(__arm__) && defined(__GNUC__) + exit(0); +#else + FAIL TO COMPILE/LINK +#endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + db_cv_mutex=ARM/gcc-assembly +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi + +# MIPS/gcc: Linux +if test "$db_cv_mutex" = no; then +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + +#if (defined(__mips) || defined(__mips__)) && defined(__GNUC__) + exit(0); +#else + FAIL TO COMPILE/LINK +#endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + db_cv_mutex=MIPS/gcc-assembly +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi + +# PaRisc/gcc: HP/UX +if test "$db_cv_mutex" = no; then +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + +#if (defined(__hppa) || defined(__hppa__)) && defined(__GNUC__) + exit(0); +#else + FAIL TO COMPILE/LINK +#endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + db_cv_mutex=HPPA/gcc-assembly +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi + +# PPC/gcc: +if test "$db_cv_mutex" = no; then +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + +#if (defined(__powerpc__) || defined(__ppc__)) && defined(__GNUC__) + exit(0); +#else + FAIL TO COMPILE/LINK +#endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + db_cv_mutex=PPC/gcc-assembly +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi + +# 68K/gcc: SunOS +if test "$db_cv_mutex" = no; then +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + +#if (defined(mc68020) || defined(sun3)) && defined(__GNUC__) + exit(0); +#else + FAIL TO COMPILE/LINK +#endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + db_cv_mutex=68K/gcc-assembly +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi + +# S390/cc: IBM OS/390 Unix +if test "$db_cv_mutex" = no; then +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + +#if defined(__MVS__) && defined(__IBMC__) + exit(0); +#else + FAIL TO COMPILE/LINK +#endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + db_cv_mutex=S390/cc-assembly +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi + +# S390/gcc: Linux +if test "$db_cv_mutex" = no; then +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + +#if defined(__s390__) && defined(__GNUC__) + exit(0); +#else + FAIL TO COMPILE/LINK +#endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + db_cv_mutex=S390/gcc-assembly +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi + +# ia64/gcc: Linux +if test "$db_cv_mutex" = no; then +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + +#if defined(__ia64) && defined(__GNUC__) + exit(0); +#else + FAIL TO COMPILE/LINK +#endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + db_cv_mutex=ia64/gcc-assembly +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi + +# uts/cc: UTS +if test "$db_cv_mutex" = no; then +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + +#if defined(_UTS) + exit(0); +#else + FAIL TO COMPILE/LINK +#endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + db_cv_mutex=UTS/cc-assembly +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi + +# UNIX fcntl system call mutexes. +# Note that fcntl mutexes are no longer supported as of 4.8. This code has been +# left in place in case there is some system that we are not aware of that +# only uses fcntl mutexes. In that case, contact Oracle for support. +if test "$db_cv_mutex" = no; then + db_cv_mutex=UNIX/fcntl +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#include +int +main () +{ + + struct flock l; + l.l_whence = SEEK_SET; + l.l_start = 10; + l.l_len = 1; + l.l_type = F_WRLCK; + fcntl(0, F_SETLK, &l); + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + db_cv_mutex=UNIX/fcntl +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $db_cv_mutex" >&5 +$as_echo "$db_cv_mutex" >&6; } + +# Configure a pthreads-style mutex implementation. +hybrid=pthread +case "$db_cv_mutex" in +POSIX/pthreads/private*)ADDITIONAL_OBJS="mut_pthread${o} $ADDITIONAL_OBJS" + $as_echo "#define HAVE_MUTEX_PTHREADS 1" >>confdefs.h + + if test "$db_cv_pthread_condinit_dupgood" = "yes"; then + $as_echo "#define HAVE_PTHREAD_COND_REINIT_OKAY 1" >>confdefs.h + + fi + if test "$db_cv_pthread_rwlockinit_dupgood" = "yes"; then + $as_echo "#define HAVE_PTHREAD_RWLOCK_REINIT_OKAY 1" >>confdefs.h + + fi + $as_echo "#define HAVE_MUTEX_THREAD_ONLY 1" >>confdefs.h + + ;; +POSIX/pthreads/library/private*) + ADDITIONAL_OBJS="mut_pthread${o} $ADDITIONAL_OBJS" + $as_echo "#define HAVE_MUTEX_PTHREADS 1" >>confdefs.h + + if test "$db_cv_pthread_condinit_dupgood" = "yes"; then + $as_echo "#define HAVE_PTHREAD_COND_REINIT_OKAY 1" >>confdefs.h + + fi + if test "$db_cv_pthread_rwlockinit_dupgood" = "yes"; then + $as_echo "#define HAVE_PTHREAD_RWLOCK_REINIT_OKAY 1" >>confdefs.h + + fi + $as_echo "#define HAVE_MUTEX_THREAD_ONLY 1" >>confdefs.h +;; +POSIX/pthreads/library*)ADDITIONAL_OBJS="mut_pthread${o} $ADDITIONAL_OBJS" + $as_echo "#define HAVE_MUTEX_PTHREADS 1" >>confdefs.h + + if test "$db_cv_pthread_condinit_dupgood" = "yes"; then + $as_echo "#define HAVE_PTHREAD_COND_REINIT_OKAY 1" >>confdefs.h + + fi + if test "$db_cv_pthread_rwlockinit_dupgood" = "yes"; then + $as_echo "#define HAVE_PTHREAD_RWLOCK_REINIT_OKAY 1" >>confdefs.h + + fi;; +POSIX/pthreads*) ADDITIONAL_OBJS="mut_pthread${o} $ADDITIONAL_OBJS" + $as_echo "#define HAVE_MUTEX_PTHREADS 1" >>confdefs.h + + + if test "$db_cv_pthread_condinit_dupgood" = "yes"; then + $as_echo "#define HAVE_PTHREAD_COND_REINIT_OKAY 1" >>confdefs.h + + fi + if test "$db_cv_pthread_rwlockinit_dupgood" = "yes"; then + $as_echo "#define HAVE_PTHREAD_RWLOCK_REINIT_OKAY 1" >>confdefs.h + + fi + + ;; +Solaris/lwp*) ADDITIONAL_OBJS="mut_pthread${o} $ADDITIONAL_OBJS" + $as_echo "#define HAVE_MUTEX_SOLARIS_LWP 1" >>confdefs.h + + ;; +UI/threads/library*) ADDITIONAL_OBJS="mut_pthread${o} $ADDITIONAL_OBJS" + $as_echo "#define HAVE_MUTEX_UI_THREADS 1" >>confdefs.h +;; +*) hybrid=no;; +UI/threads*) ADDITIONAL_OBJS="mut_pthread${o} $ADDITIONAL_OBJS" + $as_echo "#define HAVE_MUTEX_UI_THREADS 1" >>confdefs.h + + ;; +esac + +# Configure a test-and-set mutex implementation. +case "$db_cv_mutex" in +68K/gcc-assembly) ADDITIONAL_OBJS="mut_tas${o} $ADDITIONAL_OBJS" + $as_echo "#define HAVE_MUTEX_68K_GCC_ASSEMBLY 1" >>confdefs.h + + ;; +AIX/_check_lock) ADDITIONAL_OBJS="mut_tas${o} $ADDITIONAL_OBJS" + $as_echo "#define HAVE_MUTEX_AIX_CHECK_LOCK 1" >>confdefs.h + + ;; +Darwin/_spin_lock_try) ADDITIONAL_OBJS="mut_tas${o} $ADDITIONAL_OBJS" + $as_echo "#define HAVE_MUTEX_DARWIN_SPIN_LOCK_TRY 1" >>confdefs.h + + ;; +ALPHA/gcc-assembly) ADDITIONAL_OBJS="mut_tas${o} $ADDITIONAL_OBJS" + $as_echo "#define HAVE_MUTEX_ALPHA_GCC_ASSEMBLY 1" >>confdefs.h + + ;; +ARM/gcc-assembly) ADDITIONAL_OBJS="mut_tas${o} $ADDITIONAL_OBJS" + $as_echo "#define HAVE_MUTEX_ARM_GCC_ASSEMBLY 1" >>confdefs.h + + ;; +HP/msem_init) ADDITIONAL_OBJS="mut_tas${o} $ADDITIONAL_OBJS" + $as_echo "#define HAVE_MUTEX_HPPA_MSEM_INIT 1" >>confdefs.h + + ;; +HPPA/gcc-assembly) ADDITIONAL_OBJS="mut_tas${o} $ADDITIONAL_OBJS" + $as_echo "#define HAVE_MUTEX_HPPA_GCC_ASSEMBLY 1" >>confdefs.h + + ;; +ia64/gcc-assembly) ADDITIONAL_OBJS="mut_tas${o} $ADDITIONAL_OBJS" + $as_echo "#define HAVE_MUTEX_IA64_GCC_ASSEMBLY 1" >>confdefs.h + + ;; +MIPS/gcc-assembly) ADDITIONAL_OBJS="mut_tas${o} $ADDITIONAL_OBJS" + $as_echo "#define HAVE_MUTEX_MIPS_GCC_ASSEMBLY 1" >>confdefs.h + + ;; +PPC/gcc-assembly) + ADDITIONAL_OBJS="mut_tas${o} $ADDITIONAL_OBJS" + $as_echo "#define HAVE_MUTEX_PPC_GCC_ASSEMBLY 1" >>confdefs.h + + ;; +ReliantUNIX/initspin) LIBSO_LIBS="$LIBSO_LIBS -lmproc" + ADDITIONAL_OBJS="mut_tas${o} $ADDITIONAL_OBJS" + $as_echo "#define HAVE_MUTEX_RELIANTUNIX_INITSPIN 1" >>confdefs.h + + ;; +S390/cc-assembly) ADDITIONAL_OBJS="mut_tas${o} $ADDITIONAL_OBJS" + $as_echo "#define HAVE_MUTEX_S390_CC_ASSEMBLY 1" >>confdefs.h + + ;; +S390/gcc-assembly) ADDITIONAL_OBJS="mut_tas${o} $ADDITIONAL_OBJS" + $as_echo "#define HAVE_MUTEX_S390_GCC_ASSEMBLY 1" >>confdefs.h + + ;; +SCO/x86/cc-assembly) ADDITIONAL_OBJS="mut_tas${o} $ADDITIONAL_OBJS" + $as_echo "#define HAVE_MUTEX_SCO_X86_CC_ASSEMBLY 1" >>confdefs.h + + ;; +SGI/init_lock) ADDITIONAL_OBJS="mut_tas${o} $ADDITIONAL_OBJS" + $as_echo "#define HAVE_MUTEX_SGI_INIT_LOCK 1" >>confdefs.h + + ;; +Solaris/_lock_try) ADDITIONAL_OBJS="mut_tas${o} $ADDITIONAL_OBJS" + $as_echo "#define HAVE_MUTEX_SOLARIS_LOCK_TRY 1" >>confdefs.h + + ;; +*Solaris/_lock_try/membar) + hybrid="$hybrid/tas" + ADDITIONAL_OBJS="mut_tas${o} $ADDITIONAL_OBJS" + $as_echo "#define HAVE_MUTEX_SOLARIS_LOCK_TRY 1" >>confdefs.h + + ;; +*Sparc/gcc-assembly) hybrid="$hybrid/tas" + ADDITIONAL_OBJS="mut_tas${o} $ADDITIONAL_OBJS" + $as_echo "#define HAVE_MUTEX_SPARC_GCC_ASSEMBLY 1" >>confdefs.h + + ;; +Tru64/cc-assembly) ADDITIONAL_OBJS="mut_tas${o} $ADDITIONAL_OBJS" + $as_echo "#define HAVE_MUTEX_TRU64_CC_ASSEMBLY 1" >>confdefs.h + + ;; +UNIX/msem_init) ADDITIONAL_OBJS="mut_tas${o} $ADDITIONAL_OBJS" + $as_echo "#define HAVE_MUTEX_MSEM_INIT 1" >>confdefs.h + + ;; +UNIX/sema_init) ADDITIONAL_OBJS="mut_tas${o} $ADDITIONAL_OBJS" + $as_echo "#define HAVE_MUTEX_SEMA_INIT 1" >>confdefs.h + + ;; +UTS/cc-assembly) ADDITIONAL_OBJS="uts4.cc${o} $ADDITIONAL_OBJS" + $as_echo "#define HAVE_MUTEX_UTS_CC_ASSEMBLY 1" >>confdefs.h + + ;; +*x86/gcc-assembly) hybrid="$hybrid/tas" + ADDITIONAL_OBJS="mut_tas${o} $ADDITIONAL_OBJS" + $as_echo "#define HAVE_MUTEX_X86_GCC_ASSEMBLY 1" >>confdefs.h + + ;; +*x86_64/gcc-assembly) hybrid="$hybrid/tas" + ADDITIONAL_OBJS="mut_tas${o} $ADDITIONAL_OBJS" + $as_echo "#define HAVE_MUTEX_X86_64_GCC_ASSEMBLY 1" >>confdefs.h + + ;; +esac + +# Configure the remaining special cases. +case "$db_cv_mutex" in +UNIX/fcntl) as_fn_error $? "Support for FCNTL mutexes was removed in BDB 4.8." "$LINENO" 5 + ADDITIONAL_OBJS="mut_fcntl${o} $ADDITIONAL_OBJS" + $as_echo "#define HAVE_MUTEX_FCNTL 1" >>confdefs.h + + ;; +win32) ADDITIONAL_OBJS="mut_win32${o} $ADDITIONAL_OBJS" + $as_echo "#define HAVE_MUTEX_WIN32 1" >>confdefs.h + + ;; +win32/gcc) ADDITIONAL_OBJS="mut_win32${o} $ADDITIONAL_OBJS" + $as_echo "#define HAVE_MUTEX_WIN32_GCC 1" >>confdefs.h + + ;; +esac + +# Mutexes may not have been found, or may have been disabled. +case "$db_cv_mutex" in +disabled) + ;; +*) + # Test to see if mutexes have been found by checking the list of + # additional objects for a mutex implementation. + case "$ADDITIONAL_OBJS" in + *mut_pthread*|*mut_tas*|*mut_win32*) + $as_echo "#define HAVE_MUTEX_SUPPORT 1" >>confdefs.h + + + + # Shared latches are required in 4.8, and are implemented using + # mutexes if we don't have a native implementation. + # This macro may be removed in a future release. + + $as_echo "#define HAVE_SHARED_LATCHES 1" >>confdefs.h +;; + *) + as_fn_error $? "Unable to find a mutex implementation" "$LINENO" 5;; + esac +esac + +# We may have found both a pthreads-style mutex implementation as well as a +# test-and-set, in which case configure for the hybrid. +if test "$hybrid" = pthread/tas; then + $as_echo "#define HAVE_MUTEX_HYBRID 1" >>confdefs.h + + +fi + +# The mutex selection may require specific declarations -- we fill in most of +# them above, but here are the common ones. +# +# The mutex selection may tell us what kind of thread package we're using, +# which we use to figure out the thread type. +# +# If we're configured for the POSIX pthread API, then force the thread ID type +# and include function, regardless of the mutex selection. Ditto for the +# (default) Solaris lwp mutexes, because they don't have a way to return the +# thread ID. +# +# Try and link with a threads library if possible. The problem is the Solaris +# C library has UI/POSIX interface stubs, but they're broken, configuring them +# for inter-process mutexes doesn't return an error, but it doesn't work either. +# For that reason always add -lpthread if we're using pthread calls or mutexes +# and there's a pthread library. +# +# We can't depend on any specific call existing (pthread_create, for example), +# as it may be #defined in an include file -- OSF/1 (Tru64) has this problem. + + + +db_threadid_t_decl=notset + +case "$db_cv_mutex" in +UI/threads*) + thread_h_decl="#include " + db_threadid_t_decl="typedef thread_t db_threadid_t;" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for main in -lthread" >&5 +$as_echo_n "checking for main in -lthread... " >&6; } +if ${ac_cv_lib_thread_main+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lthread $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + + +int +main () +{ +return main (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_thread_main=yes +else + ac_cv_lib_thread_main=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_thread_main" >&5 +$as_echo "$ac_cv_lib_thread_main" >&6; } +if test "x$ac_cv_lib_thread_main" = xyes; then : + LIBSO_LIBS="$LIBSO_LIBS -lthread" +fi +ac_cv_lib_thread=ac_cv_lib_thread_main +;; +*) + ac_fn_c_check_header_mongrel "$LINENO" "pthread.h" "ac_cv_header_pthread_h" "$ac_includes_default" +if test "x$ac_cv_header_pthread_h" = xyes; then : + ac_cv_header_pthread_h=yes +fi + + + if test "$ac_cv_header_pthread_h" = "yes" ; then + thread_h_decl="#include " + db_threadid_t_decl="typedef pthread_t db_threadid_t;" + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for main in -lpthread" >&5 +$as_echo_n "checking for main in -lpthread... " >&6; } +if ${ac_cv_lib_pthread_main+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lpthread $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + + +int +main () +{ +return main (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_pthread_main=yes +else + ac_cv_lib_pthread_main=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_pthread_main" >&5 +$as_echo "$ac_cv_lib_pthread_main" >&6; } +if test "x$ac_cv_lib_pthread_main" = xyes; then : + LIBSO_LIBS="$LIBSO_LIBS -lpthread" +fi +ac_cv_lib_pthread=ac_cv_lib_pthread_main +;; +esac + +# We need to know if the thread ID type will fit into an integral type and we +# can compare it for equality and generally treat it like an int, or if it's a +# non-integral type and we have to treat it like a structure or other untyped +# block of bytes. For example, MVS typedef's pthread_t to a structure. + +if test "$db_threadid_t_decl" = notset; then + db_threadid_t_decl="typedef uintmax_t db_threadid_t;" + $as_echo "#define HAVE_SIMPLE_THREAD_TYPE 1" >>confdefs.h + +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + $thread_h_decl +int +main () +{ + + $db_threadid_t_decl + db_threadid_t a; + a = 0; + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + $as_echo "#define HAVE_SIMPLE_THREAD_TYPE 1" >>confdefs.h + +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi + +# There are 3 classes of mutexes: +# +# 1: Mutexes requiring no cleanup, for example, test-and-set mutexes. +# 2: Mutexes that must be destroyed, but which don't hold permanent system +# resources, for example, pthread mutexes on MVS aka OS/390 aka z/OS. +# 3: Mutexes that must be destroyed, even after the process is gone, for +# example, pthread mutexes on QNX and binary semaphores on VxWorks. +# +# DB cannot currently distinguish between #2 and #3 because DB does not know +# if the application is running environment recovery as part of startup and +# does not need to do cleanup, or if the environment is being removed and/or +# recovered in a loop in the application, and so does need to clean up. If +# we get it wrong, we're going to call the mutex destroy routine on a random +# piece of memory, which usually works, but just might drop core. For now, +# we group #2 and #3 into the HAVE_MUTEX_SYSTEM_RESOURCES define, until we +# have a better solution or reason to solve this in a general way -- so far, +# the places we've needed to handle this are few. + + +case "$host_os$db_cv_mutex" in +*qnx*POSIX/pthread*|openedition*POSIX/pthread*) + $as_echo "#define HAVE_MUTEX_SYSTEM_RESOURCES 1" >>confdefs.h +;; +esac + +# Check for native (system call or instruction set) support for +# atomic increment, decrement, and compare & exchange. + +# Probe for native atomic operations +# gcc/x86{,_64} inline asm +# solaris atomic_* library calls + + + + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for atomic operations" >&5 +$as_echo_n "checking for atomic operations... " >&6; } +if ${db_cv_atomic+:} false; then : + $as_echo_n "(cached) " >&6 +else + +db_cv_atomic=no +# atomic operations can be disabled via --disable-atomicsupport +if test "$db_cv_build_atomicsupport" = no; then + db_cv_atomic=disabled +fi + +# The MinGW build uses the Windows API for atomic operations +if test "$db_cv_mingw" = yes; then + db_cv_atomic=mingw +fi + +if test "$db_cv_atomic" = no; then + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + #if ((defined(i386) || defined(__i386__)) && defined(__GNUC__)) + exit(0); + #elif ((defined(x86_64) || defined(__x86_64__)) && defined(__GNUC__)) + exit(0); + #else + FAIL TO COMPILE/LINK + #endif + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + db_cv_atomic="x86/gcc-assembly" +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi + +if test "$db_cv_atomic" = no; then +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#include +int +main () +{ + + volatile unsigned val = 1; + exit (atomic_inc_uint_nv(&val) != 2 || + atomic_dec_uint_nv(&val) != 1 || + atomic_cas_32(&val, 1, 3) != 3); + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + db_cv_atomic="solaris/atomic" +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $db_cv_atomic" >&5 +$as_echo "$db_cv_atomic" >&6; } + +case "$db_cv_atomic" in + x86/gcc-assembly) + $as_echo "#define HAVE_ATOMIC_SUPPORT 1" >>confdefs.h + + $as_echo "#define HAVE_ATOMIC_X86_GCC_ASSEMBLY 1" >>confdefs.h + + ;; + + solaris/atomic) + $as_echo "#define HAVE_ATOMIC_SUPPORT 1" >>confdefs.h + + $as_echo "#define HAVE_ATOMIC_SOLARIS 1" >>confdefs.h + + ;; + mingw) + $as_echo "#define HAVE_ATOMIC_SUPPORT 1" >>confdefs.h + + ;; +esac + + +# Check for os-specific event support for performance monitoring such as +# DTrace or SystemTap. + + + + + + +if test "$db_cv_systemtap" = "yes" ; then + if test "$DTRACE" != "dtrace"; then + as_fn_error $? "The dtrace program is missing; is systemtap v1.1 or better installed?" "$LINENO" 5 + fi + db_cv_dtrace="yes" +fi +if test "$db_cv_dtrace" = "yes" ; then + db_cv_perfmon="yes" +fi + + +DTRACE_CPP=-C +if test "$db_cv_perfmon" = "yes" ; then + if test "$DTRACE" = "dtrace" ; then + for ac_header in sys/sdt.h +do : + ac_fn_c_check_header_mongrel "$LINENO" "sys/sdt.h" "ac_cv_header_sys_sdt_h" "$ac_includes_default" +if test "x$ac_cv_header_sys_sdt_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_SYS_SDT_H 1 +_ACEOF + +fi + +done + + # Generate the DTrace provider header file. This is duplicated + # in Makefile.in, to allow custom events to be added. + if test "$STAP" = "stap"; then + # Linux DTrace support may have a bug with dtrace -C -h + # The preprocessing isn't needed for -h on Linux, + # so skip the unnecessary preprocessing. + DTRACE_CPP= + fi + # The OS X version of dtrace prints a spurious line here. + if ! dtrace -h $DTRACE_CPP -I../util/dtrace -s ../dist/db_provider.d; then + as_fn_error $? "Could not build db_provider.d: dtrace -h failed" "$LINENO" 5 + fi + $RM db_provider.h.tmp + if ! mv db_provider.h db_provider.h.tmp ; then + as_fn_error $? "Could not build db_provider.d: mv failed" "$LINENO" 5 + elif ! sed -e \ +'/^#define[ ]*BDB_[A-Z_]*(.*)/y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/' \ +db_provider.h.tmp > db_provider.h ; then + as_fn_error $? "Could not build db_provider.d: sed failed" "$LINENO" 5 + fi + + # DTrace on Solaris needs to post-process .o files to both + # generate an additional .o as well as resolving the + # __dtrace___bdb___ symbols before putting them into + # libraries; Mac OS X does not. Treat a failing dtrace -G + # command as the indicator sign that dtrace -G is unnecessary. + # If it is needed then create an empty .c file to be a + # placeholder for the PIC & non-PIC versions of the dtrace -G + # output file. The root of this .c file must be the same as + # the root of the .d file -- i.e. db_provider -- for the + # dtrace -G lines at the end of Makefile.in to work correctly. + $RM db_provider.o + if dtrace -G $DTRACE_CPP -I../util/dtrace -s ../dist/db_provider.d 2> /dev/null && \ + test -f db_provider.o ; then + FINAL_OBJS="$FINAL_OBJS db_provider${o}" + rm -f db_provider.c + echo "" > db_provider.c + fi + $as_echo "#define HAVE_DTRACE 1" >>confdefs.h + + else + as_fn_error $? "No supported performance utility found." "$LINENO" 5 + fi + $as_echo "#define HAVE_PERFMON 1" >>confdefs.h + + if test "$db_cv_perfmon_statistics" != "no" ; then + $as_echo "#define HAVE_PERFMON_STATISTICS 1" >>confdefs.h + + fi + # The method by which probes are listed depends on the underlying + # implementation; Linux's emulation of DTrace still uses the stap + # command at runtime. + + + if test "$STAP" = "stap"; then + LISTPROBES_DEPENDENCY=.libs/libdb-$DB_VERSION_MAJOR.$DB_VERSION_MINOR$SOSUFFIX + LISTPROBES_COMMAND="stap -l 'process(\"$LISTPROBES_DEPENDENCY\").mark(\"*\")'" + elif test "$DTRACE" = "dtrace" ; then + LISTPROBES_DEPENDENCY=db_load + LISTPROBES_COMMAND=" # Run a simple command which uses the library without needing any setup. + sleep 1 | dtrace -l -n 'bdb\$\$target:::' -c '.libs/db_load dummy.db'" + fi +elif test "$db_cv_perfmon_statistics" = "yes" ; then + as_fn_error $? "Enabling perfmon statistics requires --enable-dtrace" "$LINENO" 5 +fi + + +# Test for various functions/libraries -- do tests that change library values +# first. +# +# Update LIBS, so we're testing against the current list of libraries. +LIBS="$LIBSO_LIBS" + +# The yield function on Solaris is almost certainly pthread_yield (LWP threads +# or POSIX pthreads), or thr_yield (UI threads). There's an outside chance it +# is sched_yield() though, only available in -lrt on Solaris. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing sched_yield" >&5 +$as_echo_n "checking for library containing sched_yield... " >&6; } +if ${ac_cv_search_sched_yield+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_func_search_save_LIBS=$LIBS +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char sched_yield (); +int +main () +{ +return sched_yield (); + ; + return 0; +} +_ACEOF +for ac_lib in '' rt; do + if test -z "$ac_lib"; then + ac_res="none required" + else + ac_res=-l$ac_lib + LIBS="-l$ac_lib $ac_func_search_save_LIBS" + fi + if ac_fn_c_try_link "$LINENO"; then : + ac_cv_search_sched_yield=$ac_res +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext + if ${ac_cv_search_sched_yield+:} false; then : + break +fi +done +if ${ac_cv_search_sched_yield+:} false; then : + +else + ac_cv_search_sched_yield=no +fi +rm conftest.$ac_ext +LIBS=$ac_func_search_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_sched_yield" >&5 +$as_echo "$ac_cv_search_sched_yield" >&6; } +ac_res=$ac_cv_search_sched_yield +if test "$ac_res" != no; then : + test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" + +fi + + +# The Berkeley DB library calls fdatasync, only available in -lrt on Solaris. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing fdatasync" >&5 +$as_echo_n "checking for library containing fdatasync... " >&6; } +if ${ac_cv_search_fdatasync+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_func_search_save_LIBS=$LIBS +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char fdatasync (); +int +main () +{ +return fdatasync (); + ; + return 0; +} +_ACEOF +for ac_lib in '' rt; do + if test -z "$ac_lib"; then + ac_res="none required" + else + ac_res=-l$ac_lib + LIBS="-l$ac_lib $ac_func_search_save_LIBS" + fi + if ac_fn_c_try_link "$LINENO"; then : + ac_cv_search_fdatasync=$ac_res +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext + if ${ac_cv_search_fdatasync+:} false; then : + break +fi +done +if ${ac_cv_search_fdatasync+:} false; then : + +else + ac_cv_search_fdatasync=no +fi +rm conftest.$ac_ext +LIBS=$ac_func_search_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_fdatasync" >&5 +$as_echo "$ac_cv_search_fdatasync" >&6; } +ac_res=$ac_cv_search_fdatasync +if test "$ac_res" != no; then : + test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" + +fi + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing getaddrinfo" >&5 +$as_echo_n "checking for library containing getaddrinfo... " >&6; } +if ${ac_cv_search_getaddrinfo+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_func_search_save_LIBS=$LIBS +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char getaddrinfo (); +int +main () +{ +return getaddrinfo (); + ; + return 0; +} +_ACEOF +for ac_lib in '' nsl socket; do + if test -z "$ac_lib"; then + ac_res="none required" + else + ac_res=-l$ac_lib + LIBS="-l$ac_lib $ac_func_search_save_LIBS" + fi + if ac_fn_c_try_link "$LINENO"; then : + ac_cv_search_getaddrinfo=$ac_res +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext + if ${ac_cv_search_getaddrinfo+:} false; then : + break +fi +done +if ${ac_cv_search_getaddrinfo+:} false; then : + +else + ac_cv_search_getaddrinfo=no +fi +rm conftest.$ac_ext +LIBS=$ac_func_search_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_getaddrinfo" >&5 +$as_echo "$ac_cv_search_getaddrinfo" >&6; } +ac_res=$ac_cv_search_getaddrinfo +if test "$ac_res" != no; then : + test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" + +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing hstrerror" >&5 +$as_echo_n "checking for library containing hstrerror... " >&6; } +if ${ac_cv_search_hstrerror+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_func_search_save_LIBS=$LIBS +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char hstrerror (); +int +main () +{ +return hstrerror (); + ; + return 0; +} +_ACEOF +for ac_lib in '' resolv; do + if test -z "$ac_lib"; then + ac_res="none required" + else + ac_res=-l$ac_lib + LIBS="-l$ac_lib $ac_func_search_save_LIBS" + fi + if ac_fn_c_try_link "$LINENO"; then : + ac_cv_search_hstrerror=$ac_res +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext + if ${ac_cv_search_hstrerror+:} false; then : + break +fi +done +if ${ac_cv_search_hstrerror+:} false; then : + +else + ac_cv_search_hstrerror=no +fi +rm conftest.$ac_ext +LIBS=$ac_func_search_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_hstrerror" >&5 +$as_echo "$ac_cv_search_hstrerror" >&6; } +ac_res=$ac_cv_search_hstrerror +if test "$ac_res" != no; then : + test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" + +fi + + +# Those tests updated LIBS, update our internal list. +LIBSO_LIBS="$LIBS" + +# !!! +# We could be more exact about whether these libraries are needed, but don't +# bother -- if they exist, we load them, it's only the test programs anyway. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for main in -lm" >&5 +$as_echo_n "checking for main in -lm... " >&6; } +if ${ac_cv_lib_m_main+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lm $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + + +int +main () +{ +return main (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_m_main=yes +else + ac_cv_lib_m_main=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_m_main" >&5 +$as_echo "$ac_cv_lib_m_main" >&6; } +if test "x$ac_cv_lib_m_main" = xyes; then : + TEST_LIBS="$TEST_LIBS -lm" +fi +ac_cv_lib_m=ac_cv_lib_m_main + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for main in -lnsl" >&5 +$as_echo_n "checking for main in -lnsl... " >&6; } +if ${ac_cv_lib_nsl_main+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lnsl $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + + +int +main () +{ +return main (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_nsl_main=yes +else + ac_cv_lib_nsl_main=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_nsl_main" >&5 +$as_echo "$ac_cv_lib_nsl_main" >&6; } +if test "x$ac_cv_lib_nsl_main" = xyes; then : + TEST_LIBS="$TEST_LIBS -lnsl" +fi +ac_cv_lib_nsl=ac_cv_lib_nsl_main + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for main in -lsocket" >&5 +$as_echo_n "checking for main in -lsocket... " >&6; } +if ${ac_cv_lib_socket_main+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lsocket $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + + +int +main () +{ +return main (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_socket_main=yes +else + ac_cv_lib_socket_main=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_socket_main" >&5 +$as_echo "$ac_cv_lib_socket_main" >&6; } +if test "x$ac_cv_lib_socket_main" = xyes; then : + TEST_LIBS="$TEST_LIBS -lsocket" +fi +ac_cv_lib_socket=ac_cv_lib_socket_main + + +# Checks for system functions for which we have replacements. +# +# The only portable getcwd call is getcwd(char *, size_t), where the +# buffer is non-NULL -- Solaris can't handle a NULL buffer, and they +# deleted getwd(). +ac_fn_c_check_func "$LINENO" "abort" "ac_cv_func_abort" +if test "x$ac_cv_func_abort" = xyes; then : + $as_echo "#define HAVE_ABORT 1" >>confdefs.h + +else + case " $LIBOBJS " in + *" abort.$ac_objext "* ) ;; + *) LIBOBJS="$LIBOBJS abort.$ac_objext" + ;; +esac + +fi + +ac_fn_c_check_func "$LINENO" "atoi" "ac_cv_func_atoi" +if test "x$ac_cv_func_atoi" = xyes; then : + $as_echo "#define HAVE_ATOI 1" >>confdefs.h + +else + case " $LIBOBJS " in + *" atoi.$ac_objext "* ) ;; + *) LIBOBJS="$LIBOBJS atoi.$ac_objext" + ;; +esac + +fi + +ac_fn_c_check_func "$LINENO" "atol" "ac_cv_func_atol" +if test "x$ac_cv_func_atol" = xyes; then : + $as_echo "#define HAVE_ATOL 1" >>confdefs.h + +else + case " $LIBOBJS " in + *" atol.$ac_objext "* ) ;; + *) LIBOBJS="$LIBOBJS atol.$ac_objext" + ;; +esac + +fi + +ac_fn_c_check_func "$LINENO" "bsearch" "ac_cv_func_bsearch" +if test "x$ac_cv_func_bsearch" = xyes; then : + $as_echo "#define HAVE_BSEARCH 1" >>confdefs.h + +else + case " $LIBOBJS " in + *" bsearch.$ac_objext "* ) ;; + *) LIBOBJS="$LIBOBJS bsearch.$ac_objext" + ;; +esac + +fi + +ac_fn_c_check_func "$LINENO" "getcwd" "ac_cv_func_getcwd" +if test "x$ac_cv_func_getcwd" = xyes; then : + $as_echo "#define HAVE_GETCWD 1" >>confdefs.h + +else + case " $LIBOBJS " in + *" getcwd.$ac_objext "* ) ;; + *) LIBOBJS="$LIBOBJS getcwd.$ac_objext" + ;; +esac + +fi + +ac_fn_c_check_func "$LINENO" "getenv" "ac_cv_func_getenv" +if test "x$ac_cv_func_getenv" = xyes; then : + $as_echo "#define HAVE_GETENV 1" >>confdefs.h + +else + case " $LIBOBJS " in + *" getenv.$ac_objext "* ) ;; + *) LIBOBJS="$LIBOBJS getenv.$ac_objext" + ;; +esac + +fi + +ac_fn_c_check_func "$LINENO" "getopt" "ac_cv_func_getopt" +if test "x$ac_cv_func_getopt" = xyes; then : + $as_echo "#define HAVE_GETOPT 1" >>confdefs.h + +else + case " $LIBOBJS " in + *" getopt.$ac_objext "* ) ;; + *) LIBOBJS="$LIBOBJS getopt.$ac_objext" + ;; +esac + +fi + +ac_fn_c_check_func "$LINENO" "isalpha" "ac_cv_func_isalpha" +if test "x$ac_cv_func_isalpha" = xyes; then : + $as_echo "#define HAVE_ISALPHA 1" >>confdefs.h + +else + case " $LIBOBJS " in + *" isalpha.$ac_objext "* ) ;; + *) LIBOBJS="$LIBOBJS isalpha.$ac_objext" + ;; +esac + +fi + +ac_fn_c_check_func "$LINENO" "isdigit" "ac_cv_func_isdigit" +if test "x$ac_cv_func_isdigit" = xyes; then : + $as_echo "#define HAVE_ISDIGIT 1" >>confdefs.h + +else + case " $LIBOBJS " in + *" isdigit.$ac_objext "* ) ;; + *) LIBOBJS="$LIBOBJS isdigit.$ac_objext" + ;; +esac + +fi + +ac_fn_c_check_func "$LINENO" "isprint" "ac_cv_func_isprint" +if test "x$ac_cv_func_isprint" = xyes; then : + $as_echo "#define HAVE_ISPRINT 1" >>confdefs.h + +else + case " $LIBOBJS " in + *" isprint.$ac_objext "* ) ;; + *) LIBOBJS="$LIBOBJS isprint.$ac_objext" + ;; +esac + +fi + +ac_fn_c_check_func "$LINENO" "isspace" "ac_cv_func_isspace" +if test "x$ac_cv_func_isspace" = xyes; then : + $as_echo "#define HAVE_ISSPACE 1" >>confdefs.h + +else + case " $LIBOBJS " in + *" isspace.$ac_objext "* ) ;; + *) LIBOBJS="$LIBOBJS isspace.$ac_objext" + ;; +esac + +fi + +ac_fn_c_check_func "$LINENO" "memcmp" "ac_cv_func_memcmp" +if test "x$ac_cv_func_memcmp" = xyes; then : + $as_echo "#define HAVE_MEMCMP 1" >>confdefs.h + +else + case " $LIBOBJS " in + *" memcmp.$ac_objext "* ) ;; + *) LIBOBJS="$LIBOBJS memcmp.$ac_objext" + ;; +esac + +fi + +ac_fn_c_check_func "$LINENO" "memcpy" "ac_cv_func_memcpy" +if test "x$ac_cv_func_memcpy" = xyes; then : + $as_echo "#define HAVE_MEMCPY 1" >>confdefs.h + +else + case " $LIBOBJS " in + *" memcpy.$ac_objext "* ) ;; + *) LIBOBJS="$LIBOBJS memcpy.$ac_objext" + ;; +esac + +fi + +ac_fn_c_check_func "$LINENO" "memmove" "ac_cv_func_memmove" +if test "x$ac_cv_func_memmove" = xyes; then : + $as_echo "#define HAVE_MEMMOVE 1" >>confdefs.h + +else + case " $LIBOBJS " in + *" memmove.$ac_objext "* ) ;; + *) LIBOBJS="$LIBOBJS memmove.$ac_objext" + ;; +esac + +fi + +ac_fn_c_check_func "$LINENO" "printf" "ac_cv_func_printf" +if test "x$ac_cv_func_printf" = xyes; then : + $as_echo "#define HAVE_PRINTF 1" >>confdefs.h + +else + case " $LIBOBJS " in + *" printf.$ac_objext "* ) ;; + *) LIBOBJS="$LIBOBJS printf.$ac_objext" + ;; +esac + +fi + +ac_fn_c_check_func "$LINENO" "qsort" "ac_cv_func_qsort" +if test "x$ac_cv_func_qsort" = xyes; then : + $as_echo "#define HAVE_QSORT 1" >>confdefs.h + +else + case " $LIBOBJS " in + *" qsort.$ac_objext "* ) ;; + *) LIBOBJS="$LIBOBJS qsort.$ac_objext" + ;; +esac + +fi + +ac_fn_c_check_func "$LINENO" "raise" "ac_cv_func_raise" +if test "x$ac_cv_func_raise" = xyes; then : + $as_echo "#define HAVE_RAISE 1" >>confdefs.h + +else + case " $LIBOBJS " in + *" raise.$ac_objext "* ) ;; + *) LIBOBJS="$LIBOBJS raise.$ac_objext" + ;; +esac + +fi + +ac_fn_c_check_func "$LINENO" "rand" "ac_cv_func_rand" +if test "x$ac_cv_func_rand" = xyes; then : + $as_echo "#define HAVE_RAND 1" >>confdefs.h + +else + case " $LIBOBJS " in + *" rand.$ac_objext "* ) ;; + *) LIBOBJS="$LIBOBJS rand.$ac_objext" + ;; +esac + +fi + +ac_fn_c_check_func "$LINENO" "strcasecmp" "ac_cv_func_strcasecmp" +if test "x$ac_cv_func_strcasecmp" = xyes; then : + $as_echo "#define HAVE_STRCASECMP 1" >>confdefs.h + +else + case " $LIBOBJS " in + *" strcasecmp.$ac_objext "* ) ;; + *) LIBOBJS="$LIBOBJS strcasecmp.$ac_objext" + ;; +esac + +fi + +ac_fn_c_check_func "$LINENO" "strcat" "ac_cv_func_strcat" +if test "x$ac_cv_func_strcat" = xyes; then : + $as_echo "#define HAVE_STRCAT 1" >>confdefs.h + +else + case " $LIBOBJS " in + *" strcat.$ac_objext "* ) ;; + *) LIBOBJS="$LIBOBJS strcat.$ac_objext" + ;; +esac + +fi + +ac_fn_c_check_func "$LINENO" "strchr" "ac_cv_func_strchr" +if test "x$ac_cv_func_strchr" = xyes; then : + $as_echo "#define HAVE_STRCHR 1" >>confdefs.h + +else + case " $LIBOBJS " in + *" strchr.$ac_objext "* ) ;; + *) LIBOBJS="$LIBOBJS strchr.$ac_objext" + ;; +esac + +fi + +ac_fn_c_check_func "$LINENO" "strdup" "ac_cv_func_strdup" +if test "x$ac_cv_func_strdup" = xyes; then : + $as_echo "#define HAVE_STRDUP 1" >>confdefs.h + +else + case " $LIBOBJS " in + *" strdup.$ac_objext "* ) ;; + *) LIBOBJS="$LIBOBJS strdup.$ac_objext" + ;; +esac + +fi + +ac_fn_c_check_func "$LINENO" "strerror" "ac_cv_func_strerror" +if test "x$ac_cv_func_strerror" = xyes; then : + $as_echo "#define HAVE_STRERROR 1" >>confdefs.h + +else + case " $LIBOBJS " in + *" strerror.$ac_objext "* ) ;; + *) LIBOBJS="$LIBOBJS strerror.$ac_objext" + ;; +esac + +fi + +ac_fn_c_check_func "$LINENO" "strncat" "ac_cv_func_strncat" +if test "x$ac_cv_func_strncat" = xyes; then : + $as_echo "#define HAVE_STRNCAT 1" >>confdefs.h + +else + case " $LIBOBJS " in + *" strncat.$ac_objext "* ) ;; + *) LIBOBJS="$LIBOBJS strncat.$ac_objext" + ;; +esac + +fi + +ac_fn_c_check_func "$LINENO" "strncmp" "ac_cv_func_strncmp" +if test "x$ac_cv_func_strncmp" = xyes; then : + $as_echo "#define HAVE_STRNCMP 1" >>confdefs.h + +else + case " $LIBOBJS " in + *" strncmp.$ac_objext "* ) ;; + *) LIBOBJS="$LIBOBJS strncmp.$ac_objext" + ;; +esac + +fi + +ac_fn_c_check_func "$LINENO" "strrchr" "ac_cv_func_strrchr" +if test "x$ac_cv_func_strrchr" = xyes; then : + $as_echo "#define HAVE_STRRCHR 1" >>confdefs.h + +else + case " $LIBOBJS " in + *" strrchr.$ac_objext "* ) ;; + *) LIBOBJS="$LIBOBJS strrchr.$ac_objext" + ;; +esac + +fi + +ac_fn_c_check_func "$LINENO" "strsep" "ac_cv_func_strsep" +if test "x$ac_cv_func_strsep" = xyes; then : + $as_echo "#define HAVE_STRSEP 1" >>confdefs.h + +else + case " $LIBOBJS " in + *" strsep.$ac_objext "* ) ;; + *) LIBOBJS="$LIBOBJS strsep.$ac_objext" + ;; +esac + +fi + +ac_fn_c_check_func "$LINENO" "strtol" "ac_cv_func_strtol" +if test "x$ac_cv_func_strtol" = xyes; then : + $as_echo "#define HAVE_STRTOL 1" >>confdefs.h + +else + case " $LIBOBJS " in + *" strtol.$ac_objext "* ) ;; + *) LIBOBJS="$LIBOBJS strtol.$ac_objext" + ;; +esac + +fi + +ac_fn_c_check_func "$LINENO" "strtoul" "ac_cv_func_strtoul" +if test "x$ac_cv_func_strtoul" = xyes; then : + $as_echo "#define HAVE_STRTOUL 1" >>confdefs.h + +else + case " $LIBOBJS " in + *" strtoul.$ac_objext "* ) ;; + *) LIBOBJS="$LIBOBJS strtoul.$ac_objext" + ;; +esac + +fi + + + +# Check for system functions we optionally use. +for ac_func in \ + _fstati64 backtrace backtrace_symbols directio fchmod fclose\ + fcntl fdatasync fgetc fgets fopen fwrite getgid\ + getrusage getuid hstrerror mprotect pstat_getdynamic\ + pthread_self pthread_yield random sched_yield select setgid setuid\ + sigaction snprintf stat sysconf vsnprintf yield +do : + as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` +ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" +if eval test \"x\$"$as_ac_var"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +fi +done + + + + +for ac_func in gettimeofday localtime time strftime +do : + as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` +ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" +if eval test \"x\$"$as_ac_var"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +fi +done + + +# AIX 4.3 will link applications with calls to clock_gettime, but the +# calls always fail. +case "$host_os" in +aix4.3.*) + ;; +*) + for ac_func in clock_gettime +do : + ac_fn_c_check_func "$LINENO" "clock_gettime" "ac_cv_func_clock_gettime" +if test "x$ac_cv_func_clock_gettime" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_CLOCK_GETTIME 1 +_ACEOF + +fi +done +;; +esac + +# clock_gettime -- monotonic clocks. +# Check to see if we can get a monotonic clock. We actually try and +# run the program if possible, because we don't trust the #define's +# existence to mean the clock really exists. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for clock_gettime monotonic clock" >&5 +$as_echo_n "checking for clock_gettime monotonic clock... " >&6; } +if ${db_cv_clock_monotonic+:} false; then : + $as_echo_n "(cached) " >&6 +else + +if test "$cross_compiling" = yes; then : + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#include +int +main () +{ + +struct timespec t; +clock_gettime(CLOCK_MONOTONIC, &t); + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + db_cv_clock_monotonic=yes +else + db_cv_clock_monotonic=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#include +main() { + struct timespec t; + return (clock_gettime(CLOCK_MONOTONIC, &t) != 0); +} +_ACEOF +if ac_fn_c_try_run "$LINENO"; then : + db_cv_clock_monotonic=yes +else + db_cv_clock_monotonic=no +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $db_cv_clock_monotonic" >&5 +$as_echo "$db_cv_clock_monotonic" >&6; } +if test "$db_cv_clock_monotonic" = "yes"; then + $as_echo "#define HAVE_CLOCK_MONOTONIC 1" >>confdefs.h + + +fi + +# ctime_r -- +# +# There are two versions of ctime_r, one of which takes a buffer length as a +# third argument, and one which only takes two arguments. (There is also a +# difference in return values and the type of the 3rd argument, but we handle +# those problems in the code itself.) +for ac_func in ctime_r +do : + ac_fn_c_check_func "$LINENO" "ctime_r" "ac_cv_func_ctime_r" +if test "x$ac_cv_func_ctime_r" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_CTIME_R 1 +_ACEOF + +fi +done + +if test "$ac_cv_func_ctime_r" = "yes"; then +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for 2 or 3 argument version of ctime_r" >&5 +$as_echo_n "checking for 2 or 3 argument version of ctime_r... " >&6; } +if ${db_cv_ctime_r_3arg+:} false; then : + $as_echo_n "(cached) " >&6 +else + +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#include +int +main () +{ + + ctime_r(NULL, NULL, 100); + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + db_cv_ctime_r_3arg="3-argument" +else + db_cv_ctime_r_3arg="2-argument" +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $db_cv_ctime_r_3arg" >&5 +$as_echo "$db_cv_ctime_r_3arg" >&6; } +fi +if test "$db_cv_ctime_r_3arg" = "3-argument"; then + $as_echo "#define HAVE_CTIME_R_3ARG 1" >>confdefs.h + + +fi + + +# Ftruncate. +# We've run into a problem with ftruncate on Alpha/Tru64, the issue is that +# after a truncate the last page of the file mmaps as all zeros. So just don't +# use ftruncate. +case "$host_os" in +osf*) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: ftruncate ignored on $host_os-$host_vendor." >&5 +$as_echo "$as_me: WARNING: ftruncate ignored on $host_os-$host_vendor." >&2;};; +*) + for ac_func in ftruncate +do : + ac_fn_c_check_func "$LINENO" "ftruncate" "ac_cv_func_ftruncate" +if test "x$ac_cv_func_ftruncate" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_FTRUNCATE 1 +_ACEOF + +fi +done +;; +esac + +# Pread/pwrite. +# HP-UX has pread/pwrite, but it doesn't work with largefile support. +# NCR's version of System V R 4.3 has pread/pwrite symbols, but no support. +case "$host_os-$host_vendor" in +hpux*|sysv4.3*-ncr) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: pread/pwrite interfaces ignored on $host_os-$host_vendor." >&5 +$as_echo "$as_me: WARNING: pread/pwrite interfaces ignored on $host_os-$host_vendor." >&2;};; +*) + for ac_func in pread pwrite +do : + as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` +ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" +if eval test \"x\$"$as_ac_var"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +fi +done +;; +esac + +# Check for getaddrinfo; do the test explicitly instead of using AC_CHECK_FUNCS +# because isn't a standard include file. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for getaddrinfo" >&5 +$as_echo_n "checking for getaddrinfo... " >&6; } +if ${db_cv_getaddrinfo+:} false; then : + $as_echo_n "(cached) " >&6 +else + +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#include +#include +int +main () +{ + + getaddrinfo(0, 0, 0, 0); + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + db_cv_getaddrinfo=yes +else + db_cv_getaddrinfo=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $db_cv_getaddrinfo" >&5 +$as_echo "$db_cv_getaddrinfo" >&6; } +if test "$db_cv_getaddrinfo" = "yes"; then + $as_echo "#define HAVE_GETADDRINFO 1" >>confdefs.h + + +fi + +# Check for the fcntl F_SETFD flag to deny child process access to file +# descriptors. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for fcntl/F_SETFD" >&5 +$as_echo_n "checking for fcntl/F_SETFD... " >&6; } +if ${db_cv_fcntl_f_setfd+:} false; then : + $as_echo_n "(cached) " >&6 +else + +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#include +#include +int +main () +{ + + fcntl(1, F_SETFD, 1); + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + db_cv_fcntl_f_setfd=yes +else + db_cv_fcntl_f_setfd=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $db_cv_fcntl_f_setfd" >&5 +$as_echo "$db_cv_fcntl_f_setfd" >&6; } +if test "$db_cv_fcntl_f_setfd" = "yes"; then + $as_echo "#define HAVE_FCNTL_F_SETFD 1" >>confdefs.h + + +fi + +# A/UX has a broken getopt(3). +case "$host_os" in +aux*) case " $LIBOBJS " in + *" getopt.$ac_objext "* ) ;; + *) LIBOBJS="$LIBOBJS getopt.$ac_objext" + ;; +esac +;; +esac + +# Linux has a broken O_DIRECT flag, but you can't detect it at configure time. +# Linux and SGI require buffer alignment we may not match, otherwise writes +# will fail. Default to not using the O_DIRECT flag. +if test "$db_cv_o_direct" = "yes"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for open/O_DIRECT" >&5 +$as_echo_n "checking for open/O_DIRECT... " >&6; } +if ${db_cv_open_o_direct+:} false; then : + $as_echo_n "(cached) " >&6 +else + + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + + #include + #include +int +main () +{ + + open("a", O_RDONLY | O_DIRECT, 0); + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + db_cv_open_o_direct=yes +else + db_cv_open_o_direct=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $db_cv_open_o_direct" >&5 +$as_echo "$db_cv_open_o_direct" >&6; } + if test \ + "$db_cv_o_direct" = "yes" -a "$db_cv_open_o_direct" = "yes"; then + $as_echo "#define HAVE_O_DIRECT 1" >>confdefs.h + + + fi +fi + +# Check for largefile support. +# Check whether --enable-largefile was given. +if test "${enable_largefile+set}" = set; then : + enableval=$enable_largefile; +fi + +if test "$enable_largefile" != no; then + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for special C compiler options needed for large files" >&5 +$as_echo_n "checking for special C compiler options needed for large files... " >&6; } +if ${ac_cv_sys_largefile_CC+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_cv_sys_largefile_CC=no + if test "$GCC" != yes; then + ac_save_CC=$CC + while :; do + # IRIX 6.2 and later do not support large files by default, + # so use the C compiler's -n32 option if that helps. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + /* Check that off_t can represent 2**63 - 1 correctly. + We can't simply define LARGE_OFF_T to be 9223372036854775807, + since some C++ compilers masquerading as C compilers + incorrectly reject 9223372036854775807. */ +#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62)) + int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721 + && LARGE_OFF_T % 2147483647 == 1) + ? 1 : -1]; +int +main () +{ + + ; + return 0; +} +_ACEOF + if ac_fn_c_try_compile "$LINENO"; then : + break +fi +rm -f core conftest.err conftest.$ac_objext + CC="$CC -n32" + if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_sys_largefile_CC=' -n32'; break +fi +rm -f core conftest.err conftest.$ac_objext + break + done + CC=$ac_save_CC + rm -f conftest.$ac_ext + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sys_largefile_CC" >&5 +$as_echo "$ac_cv_sys_largefile_CC" >&6; } + if test "$ac_cv_sys_largefile_CC" != no; then + CC=$CC$ac_cv_sys_largefile_CC + fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for _FILE_OFFSET_BITS value needed for large files" >&5 +$as_echo_n "checking for _FILE_OFFSET_BITS value needed for large files... " >&6; } +if ${ac_cv_sys_file_offset_bits+:} false; then : + $as_echo_n "(cached) " >&6 +else + while :; do + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + /* Check that off_t can represent 2**63 - 1 correctly. + We can't simply define LARGE_OFF_T to be 9223372036854775807, + since some C++ compilers masquerading as C compilers + incorrectly reject 9223372036854775807. */ +#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62)) + int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721 + && LARGE_OFF_T % 2147483647 == 1) + ? 1 : -1]; +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_sys_file_offset_bits=no; break +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#define _FILE_OFFSET_BITS 64 +#include + /* Check that off_t can represent 2**63 - 1 correctly. + We can't simply define LARGE_OFF_T to be 9223372036854775807, + since some C++ compilers masquerading as C compilers + incorrectly reject 9223372036854775807. */ +#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62)) + int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721 + && LARGE_OFF_T % 2147483647 == 1) + ? 1 : -1]; +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_sys_file_offset_bits=64; break +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + ac_cv_sys_file_offset_bits=unknown + break +done +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sys_file_offset_bits" >&5 +$as_echo "$ac_cv_sys_file_offset_bits" >&6; } +case $ac_cv_sys_file_offset_bits in #( + no | unknown) ;; + *) +cat >>confdefs.h <<_ACEOF +#define _FILE_OFFSET_BITS $ac_cv_sys_file_offset_bits +_ACEOF +;; +esac +rm -rf conftest* + if test $ac_cv_sys_file_offset_bits = unknown; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for _LARGE_FILES value needed for large files" >&5 +$as_echo_n "checking for _LARGE_FILES value needed for large files... " >&6; } +if ${ac_cv_sys_large_files+:} false; then : + $as_echo_n "(cached) " >&6 +else + while :; do + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + /* Check that off_t can represent 2**63 - 1 correctly. + We can't simply define LARGE_OFF_T to be 9223372036854775807, + since some C++ compilers masquerading as C compilers + incorrectly reject 9223372036854775807. */ +#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62)) + int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721 + && LARGE_OFF_T % 2147483647 == 1) + ? 1 : -1]; +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_sys_large_files=no; break +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#define _LARGE_FILES 1 +#include + /* Check that off_t can represent 2**63 - 1 correctly. + We can't simply define LARGE_OFF_T to be 9223372036854775807, + since some C++ compilers masquerading as C compilers + incorrectly reject 9223372036854775807. */ +#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62)) + int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721 + && LARGE_OFF_T % 2147483647 == 1) + ? 1 : -1]; +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_sys_large_files=1; break +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + ac_cv_sys_large_files=unknown + break +done +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sys_large_files" >&5 +$as_echo "$ac_cv_sys_large_files" >&6; } +case $ac_cv_sys_large_files in #( + no | unknown) ;; + *) +cat >>confdefs.h <<_ACEOF +#define _LARGE_FILES $ac_cv_sys_large_files +_ACEOF +;; +esac +rm -rf conftest* + fi +fi + + +# Figure out how to create shared regions. +# +# First, we look for mmap. +# +# BSD/OS has mlock(2), but it doesn't work until the 4.1 release. +# +# Nextstep (version 3.3) apparently supports mmap(2) (the mmap symbol +# is defined in the C library) but does not support munmap(2). Don't +# try to use mmap if we can't find munmap. +# +# Ultrix has mmap(2), but it doesn't work. +mmap_ok=no +case "$host_os" in +bsdi3*|bsdi4.0) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: mlock(2) interface ignored on $host_os-$host_vendor." >&5 +$as_echo "$as_me: WARNING: mlock(2) interface ignored on $host_os-$host_vendor." >&2;} + mmap_ok=yes + for ac_func in mmap munmap +do : + as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` +ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" +if eval test \"x\$"$as_ac_var"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +else + mmap_ok=no +fi +done +;; +ultrix*) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: mmap(2) interface ignored on $host_os-$host_vendor." >&5 +$as_echo "$as_me: WARNING: mmap(2) interface ignored on $host_os-$host_vendor." >&2;};; +*) + mmap_ok=yes + for ac_func in mlock munlock +do : + as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` +ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" +if eval test \"x\$"$as_ac_var"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +fi +done + + for ac_func in mmap munmap +do : + as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` +ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" +if eval test \"x\$"$as_ac_var"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 +_ACEOF + +else + mmap_ok=no +fi +done +;; +esac + +# Second, we look for shmget. +# +# SunOS has the shmget(2) interfaces, but there appears to be a missing +# #include file, so we ignore them. +shmget_ok=no +case "$host_os" in +sunos*) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: shmget(2) interface ignored on $host_os-$host_vendor." >&5 +$as_echo "$as_me: WARNING: shmget(2) interface ignored on $host_os-$host_vendor." >&2;};; +*) + shmget_ok=yes + for ac_func in shmget +do : + ac_fn_c_check_func "$LINENO" "shmget" "ac_cv_func_shmget" +if test "x$ac_cv_func_shmget" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_SHMGET 1 +_ACEOF + +else + shmget_ok=no +fi +done + + + # Check for shmctl to lock down shared memory segments. + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for shmctl" >&5 +$as_echo_n "checking for shmctl... " >&6; } +if ${db_cv_shmctl_shm_lock+:} false; then : + $as_echo_n "(cached) " >&6 +else + + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#include +#include +#include +#include +int +main () +{ + + shmctl(0, SHM_LOCK, NULL); + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + db_cv_shmctl_shm_lock=yes +else + db_cv_shmctl_shm_lock=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $db_cv_shmctl_shm_lock" >&5 +$as_echo "$db_cv_shmctl_shm_lock" >&6; } + if test "$db_cv_shmctl_shm_lock" = "yes"; then + $as_echo "#define HAVE_SHMCTL_SHM_LOCK 1" >>confdefs.h + + + fi;; +esac + +# We require either mmap/munmap(2) or shmget(2). +if test "$mmap_ok" = "no" -a "$shmget_ok" = "no"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Neither mmap/munmap(2) or shmget(2) library functions." >&5 +$as_echo "$as_me: WARNING: Neither mmap/munmap(2) or shmget(2) library functions." >&2;} +fi + +# Optional Tcl support. +if test "$db_cv_tcl" = "yes"; then + + + if ${ac_cv_c_tclconfig+:} false; then : + $as_echo_n "(cached) " >&6 +else + + + # First check to see if --with-tclconfig was specified. + if test "${with_tclconfig}" != no; then + if test -f "${with_tclconfig}/tclConfig.sh" ; then + ac_cv_c_tclconfig=`(cd ${with_tclconfig}; pwd)` + else + as_fn_error $? "${with_tclconfig} directory doesn't contain tclConfig.sh" "$LINENO" 5 + fi + fi + + # check in a few common install locations + if test x"${ac_cv_c_tclconfig}" = x ; then + for i in `ls -d /usr/local/lib 2>/dev/null` ; do + if test -f "$i/tclConfig.sh" ; then + ac_cv_c_tclconfig=`(cd $i; pwd)` + break + fi + done + fi + + +fi + + + if test x"${ac_cv_c_tclconfig}" = x ; then + TCL_BIN_DIR="# no Tcl configs found" + as_fn_error $? "can't find Tcl configuration definitions" "$LINENO" 5 + else + TCL_BIN_DIR=${ac_cv_c_tclconfig} + fi + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for existence of $TCL_BIN_DIR/tclConfig.sh" >&5 +$as_echo_n "checking for existence of $TCL_BIN_DIR/tclConfig.sh... " >&6; } + + if test -f "$TCL_BIN_DIR/tclConfig.sh" ; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: loading" >&5 +$as_echo "loading" >&6; } + . $TCL_BIN_DIR/tclConfig.sh + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: file not found" >&5 +$as_echo "file not found" >&6; } + fi + + # DB requires at least version 8.5. + if test ${TCL_MAJOR_VERSION} -lt 8 \ + -o ${TCL_MAJOR_VERSION} -eq 8 -a ${TCL_MINOR_VERSION} -lt 5; then + as_fn_error $? "Berkeley DB requires Tcl version 8.5 or better." "$LINENO" 5 + fi + + # The eval is required to do substitution (for example, the TCL_DBGX + # substitution in the TCL_LIB_FILE variable. + eval "TCL_INCLUDE_SPEC=\"${TCL_INCLUDE_SPEC}\"" + eval "TCL_LIB_FILE=\"${TCL_LIB_FILE}\"" + eval "TCL_LIB_FLAG=\"${TCL_LIB_FLAG}\"" + eval "TCL_LIB_SPEC=\"${TCL_LIB_SPEC}\"" + + # + # If the DB Tcl library isn't loaded with the Tcl spec and library + # flags on AIX, the resulting libdb_tcl-X.Y.so.0 will drop core at + # load time. [#4843] Furthermore, with Tcl 8.3, the link flags + # given by the Tcl spec are insufficient for our use. [#5779],[#17109] + # + case "$host_os" in + aix*) + LIBTSO_LIBS="$LIBTSO_LIBS $TCL_LIB_SPEC $TCL_LIB_FLAG" + LIBTSO_LIBS="$LIBTSO_LIBS -L$TCL_EXEC_PREFIX/lib -ltcl$TCL_VERSION";; + esac + + + + + + + TCL_TCLSH="${TCL_PREFIX}/bin/tclsh${TCL_VERSION}" + + + if test "$enable_shared" = "no"; then + DEFAULT_LIB_TCL="\$(libtcl_version)" + fi + if test "$enable_shared" = "yes"; then + DEFAULT_LIB_TCL="\$(libtso_target)" + fi + INSTALL_LIBS="$INSTALL_LIBS $DEFAULT_LIB_TCL" + if test "$enable_static" = "yes"; then + INSTALL_LIBS="$INSTALL_LIBS \$(libtcl)" + fi + TCL_ADDITIONAL_OBJS="\$(TCL_STD_OBJS)" + if test "$db_cv_rdsbuild" == "yes"; then + # The RDS build exludes most tcl support + TCL_ADDITIONAL_OBJS= + fi + +fi + +# Optional sequence code. + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for 64-bit integral type support for sequences" >&5 +$as_echo_n "checking for 64-bit integral type support for sequences... " >&6; } + + db_cv_build_sequence="yes" + + # Have to have found 64-bit types to support sequences. If we don't + # find the native types, we try and create our own. + if test "$ac_cv_type_int64_t" = "no" -a -z "$int64_decl"; then + db_cv_build_sequence="no" + fi + if test "$ac_cv_type_uint64_t" = "no" -a -z "$u_int64_decl"; then + db_cv_build_sequence="no" + fi + + # Figure out what type is the right size, and set the format. + + + db_cv_seq_type="no" + if test "$db_cv_build_sequence" = "yes" -a\ + "$ac_cv_sizeof_long" -eq "8"; then + db_cv_seq_type="long" + db_cv_seq_fmt='"%ld"' + db_cv_seq_ufmt='"%lu"' + INT64_FMT='#define INT64_FMT "%ld"' + UINT64_FMT='#define UINT64_FMT "%lu"' + else if test "$db_cv_build_sequence" = "yes" -a\ + "$ac_cv_sizeof_long_long" -eq "8"; then + db_cv_seq_type="long long" + db_cv_seq_fmt='"%lld"' + db_cv_seq_ufmt='"%llu"' + INT64_FMT='#define INT64_FMT "%lld"' + UINT64_FMT='#define UINT64_FMT "%llu"' + else + db_cv_build_sequence="no" + fi + fi + + # Test to see if we can declare variables of the appropriate size + # and format them. If we're cross-compiling, all we get is a link + # test, which won't test for the appropriate printf format strings. + if test "$db_cv_build_sequence" = "yes"; then + if test "$cross_compiling" = yes; then : + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + $db_cv_seq_type l; + unsigned $db_cv_seq_type u; + char buf[100]; + + buf[0] = 'a'; + l = 9223372036854775807LL; + (void)snprintf(buf, sizeof(buf), $db_cv_seq_fmt, l); + if (strcmp(buf, "9223372036854775807")) + return (1); + u = 18446744073709551615ULL; + (void)snprintf(buf, sizeof(buf), $db_cv_seq_ufmt, u); + if (strcmp(buf, "18446744073709551615")) + return (1); + return (0); + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + +else + db_cv_build_sequence="no" +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + + main() { + $db_cv_seq_type l; + unsigned $db_cv_seq_type u; + char buf[100]; + + buf[0] = 'a'; + l = 9223372036854775807LL; + (void)snprintf(buf, sizeof(buf), $db_cv_seq_fmt, l); + if (strcmp(buf, "9223372036854775807")) + return (1); + u = 18446744073709551615ULL; + (void)snprintf(buf, sizeof(buf), $db_cv_seq_ufmt, u); + if (strcmp(buf, "18446744073709551615")) + return (1); + return (0); + } +_ACEOF +if ac_fn_c_try_run "$LINENO"; then : + +else + db_cv_build_sequence="no" +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + + fi + if test "$db_cv_build_sequence" = "yes"; then + + db_seq_decl="typedef $db_cv_seq_type db_seq_t;"; + + $as_echo "#define HAVE_64BIT_TYPES 1" >>confdefs.h + + + else + # It still has to compile, but it won't run. + db_seq_decl="typedef int db_seq_t;"; + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $db_cv_build_sequence" >&5 +$as_echo "$db_cv_build_sequence" >&6; } + + +# Detect whether a large mmap() supports automatically extending the accessible +# region after growing the underlying file. + + + + + +if test "$mmap_ok" = "yes" ; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for growing a file under an mmap region" >&5 +$as_echo_n "checking for growing a file under an mmap region... " >&6; } + + db_cv_mmap_extend="no" + + if test "$cross_compiling" = yes; then : + db_cv_mmap_extend="no" +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + + /* + * Most mmap() implemenations allow you to map in a region which is much + * larger than the underlying file. Only the second less than the actual + * file size is accessible -- a SIGSEV typically results when attemping + * a memory reference between EOF and the end of the mapped region. + * One can extend the file to allow references into higher-addressed + * sections of the region. However this automatic extension of the + * addressible memory is beyond what POSIX requires. This function detects + * whether mmap supports this automatic extension. If not (e.g. cygwin) + * then the entire (hopefully sparse) file will need to be written before + * the first mmap. + */ + /* Not all these includes are needed, but the minimal set varies from + * system to system. + */ + #include + #include + #include + #include + #include + #include + #include + + #define TEST_MMAP_BUFSIZE (16 * 1024) + #define TEST_MMAP_EXTENDSIZE (16 * 1024 * 1024) + #ifndef MAP_FAILED + #define MAP_FAILED (-1) + #endif + + int catch_sig(sig) + int sig; + { + exit(1); + } + + main() { + const char *underlying; + unsigned gapsize; + char *base; + int count, fd, i, mode, open_flags, ret, total_size; + char buf[TEST_MMAP_BUFSIZE]; + + gapsize = 1024; + underlying = ".mmap_config"; + (void) unlink(underlying); + + open_flags = O_CREAT | O_TRUNC | O_RDWR; + mode = S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH; + + if ((fd = open(underlying, open_flags, mode)) < 0) { + perror("open"); + return (1); + } + + total_size = TEST_MMAP_EXTENDSIZE; + + memset(buf, 0, sizeof(buf)); + if ((count = write(fd, buf, sizeof(buf))) != sizeof(buf)) { + perror("initial write"); + return (2); + } + + if ((base = mmap(NULL, total_size, + PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0)) == MAP_FAILED) { + perror("mmap"); + return (3); + } + + /* Extend the file with just 1 byte */ + if (lseek(fd, total_size - 1, SEEK_SET) < 0 || + (count = write(fd, buf, 1)) != 1) { + perror("extending write"); + return (4); + } + + (void) signal(SIGSEGV, catch_sig); + (void) signal(SIGBUS, catch_sig); + + for (i = sizeof(buf); i < total_size; i += gapsize) + base[i] = 'A'; + + close(fd); + (void) unlink(underlying); + return (0); + } +_ACEOF +if ac_fn_c_try_run "$LINENO"; then : + db_cv_mmap_extend="yes" +else + db_cv_mmap_extend="no" +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + + + + if test "$db_cv_mmap_extend" = yes; then + $as_echo "#define HAVE_MMAP_EXTEND 1" >>confdefs.h + + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $db_cv_mmap_extend" >&5 +$as_echo "$db_cv_mmap_extend" >&6; } +fi + + +# Optional DB 1.85 compatibility API. +if test "$db_cv_compat185" = "yes"; then + ADDITIONAL_INCS="db_185.h $ADDITIONAL_INCS" + + ADDITIONAL_OBJS="db185${o} $ADDITIONAL_OBJS" +fi + +# Optional utilities. +if test "$db_cv_dump185" = "yes"; then + ADDITIONAL_PROGS="db_dump185 $ADDITIONAL_PROGS" +fi + +# Log checksums can be disabled to increase performance +if test "$db_cv_log_checksum" = "yes"; then + $as_echo "#define HAVE_LOG_CHECKSUM 1" >>confdefs.h + + +fi + +# You can disable pieces of functionality to save space. +# +# Btree is always configured: it is the standard method, and Hash off-page +# duplicates require it. + +# Compression can be disabled. +if test "$db_cv_build_compression" = "yes"; then + $as_echo "#define HAVE_COMPRESSION 1" >>confdefs.h + + +fi + +# Partitioning can be disabled. +if test "$db_cv_build_partition" = "yes"; then + $as_echo "#define HAVE_PARTITION 1" >>confdefs.h + + + ADDITIONAL_OBJS="$ADDITIONAL_OBJS \$(PARTITION_OBJS)" +else + ADDITIONAL_OBJS="$ADDITIONAL_OBJS partition_stub${o}" +fi + +# Hash can be disabled. +if test "$db_cv_build_hash" = "yes"; then + $as_echo "#define HAVE_HASH 1" >>confdefs.h + + + ADDITIONAL_OBJS="$ADDITIONAL_OBJS \$(HASH_OBJS)" + if test "$db_cv_build_verify" = "yes"; then + ADDITIONAL_OBJS="$ADDITIONAL_OBJS \$(HASH_VRFY_OBJS)" + fi +else + ADDITIONAL_OBJS="$ADDITIONAL_OBJS hash_stub${o}" +fi + +# Heap can be disabled. +if test "$db_cv_build_heap" = "yes"; then + $as_echo "#define HAVE_HEAP 1" >>confdefs.h + + + ADDITIONAL_OBJS="$ADDITIONAL_OBJS \$(HEAP_OBJS)" + if test "$db_cv_build_verify" = "yes"; then + ADDITIONAL_OBJS="$ADDITIONAL_OBJS \$(HEAP_VRFY_OBJS)" + fi +else + ADDITIONAL_OBJS="$ADDITIONAL_OBJS heap_stub${o}" +fi + +# Queue can be disabled. +if test "$db_cv_build_queue" = "yes"; then + $as_echo "#define HAVE_QUEUE 1" >>confdefs.h + + + ADDITIONAL_OBJS="$ADDITIONAL_OBJS \$(QUEUE_OBJS)" + if test "$db_cv_build_verify" = "yes"; then + ADDITIONAL_OBJS="$ADDITIONAL_OBJS \$(QUEUE_VRFY_OBJS)" + fi +else + ADDITIONAL_OBJS="$ADDITIONAL_OBJS qam_stub${o}" +fi + +# Replication can be disabled. +if test "$db_cv_build_replication" = "yes"; then + $as_echo "#define HAVE_REPLICATION 1" >>confdefs.h + + + ADDITIONAL_OBJS="$ADDITIONAL_OBJS \$(REP_OBJS)" + + # If we're building replication and detected POSIX threads, build the + # replication manager. + + + if test "$ac_cv_header_pthread_h" = yes -a "$db_cv_mingw" != "yes"; then + $as_echo "#define HAVE_REPLICATION_THREADS 1" >>confdefs.h + + + if test "$with_stacksize" != "no"; then + +cat >>confdefs.h <<_ACEOF +#define DB_STACKSIZE $with_stacksize +_ACEOF + + fi + + # Solaris requires the socket and nsl libraries to build the + # replication manager. Don't add nsl regardless of the OS, + # it causes RPC to fail on AIX 4.3.3. + case "$host_os" in + solaris*) + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for main in -lnsl" >&5 +$as_echo_n "checking for main in -lnsl... " >&6; } +if ${ac_cv_lib_nsl_main+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lnsl $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + + +int +main () +{ +return main (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_nsl_main=yes +else + ac_cv_lib_nsl_main=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_nsl_main" >&5 +$as_echo "$ac_cv_lib_nsl_main" >&6; } +if test "x$ac_cv_lib_nsl_main" = xyes; then : + LIBSO_LIBS="$LIBSO_LIBS -lnsl" +fi +ac_cv_lib_nsl=ac_cv_lib_nsl_main + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for main in -lsocket" >&5 +$as_echo_n "checking for main in -lsocket... " >&6; } +if ${ac_cv_lib_socket_main+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lsocket $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + + +int +main () +{ +return main (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_socket_main=yes +else + ac_cv_lib_socket_main=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_socket_main" >&5 +$as_echo "$ac_cv_lib_socket_main" >&6; } +if test "x$ac_cv_lib_socket_main" = xyes; then : + LIBSO_LIBS="$LIBSO_LIBS -lsocket" +fi +ac_cv_lib_socket=ac_cv_lib_socket_main +;; + esac + ADDITIONAL_OBJS="$ADDITIONAL_OBJS \$(REPMGR_OBJS)" + else + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Replication manager is not supported." >&5 +$as_echo "$as_me: WARNING: Replication manager is not supported." >&2;} + ADDITIONAL_OBJS="$ADDITIONAL_OBJS repmgr_stub${o}" + fi +else + ADDITIONAL_OBJS="$ADDITIONAL_OBJS rep_stub${o} repmgr_stub${o}" +fi + +# The statistics code can be disabled. +if test "$db_cv_build_statistics" = "yes"; then + $as_echo "#define HAVE_STATISTICS 1" >>confdefs.h + + +fi + +# The verification code can be disabled. +if test "$db_cv_build_verify" = "yes"; then + $as_echo "#define HAVE_VERIFY 1" >>confdefs.h + + + if test "$db_cv_rdsbuild" = "no"; then + ADDITIONAL_OBJS="$ADDITIONAL_OBJS \$(BTREE_VRFY_OBJS) \$(LOG_VRFY_OBJS)" + else + ADDITIONAL_OBJS="$ADDITIONAL_OBJS \$(BTREE_VRFY_OBJS) log_verify_stub${o}" + fi +else + ADDITIONAL_OBJS="$ADDITIONAL_OBJS db_vrfy_stub${o} log_verify_stub${o}" +fi + +# The crypto code can be disabled. +if test -d "$topdir/src/crypto" -a "$db_cv_build_cryptography" != "no"; then + $as_echo "#define HAVE_CRYPTO 1" >>confdefs.h + + + + CRYPTO_OBJS="\$(CRYPTO_OBJS)" + + if test "$db_cv_build_cryptography" = "ipp"; then + ac_fn_c_check_header_mongrel "$LINENO" "ippcp.h" "ac_cv_header_ippcp_h" "$ac_includes_default" +if test "x$ac_cv_header_ippcp_h" = xyes; then : + +else + as_fn_error $? "\ +The 'ippcp.h' header file required for IPP cryptography support was not found \ +in the configured include path." "$LINENO" 5 +fi + + + $as_echo "#define HAVE_CRYPTO_IPP 1" >>confdefs.h + + + fi +else + CRYPTO_OBJS="crypto_stub${o}" +fi + +# The mutex code can be disabled, and if there aren't any mutexes, then there's +# no reason to include the locking code. +if test "$db_cv_build_mutexsupport" = "yes"; then + ADDITIONAL_OBJS="$ADDITIONAL_OBJS \$(MUTEX_OBJS)" + db_cv_locking="yes" +else + db_cv_locking="no" + ADDITIONAL_OBJS="$ADDITIONAL_OBJS mut_stub${o}" +fi + +LOCALEXAMPLES="\$(exampledir)" +LOCALSRC="\$(srcdir)" +LOCALUTILS="\$(utildir)" +# The RDS build disables transactions and most features except DML and cursors. +# They are removed by appending rds_stubs instead of STD_OBJS to ADDITIONAL_OBJS. +if test "$db_cv_rdsbuild" = "no"; then + $as_echo "#define HAVE_TRANSACTIONS 1" >>confdefs.h + + + ADDITIONAL_OBJS="$ADDITIONAL_OBJS \$(STD_OBJS)" + ADDITIONAL_PROGS="$ADDITIONAL_PROGS \$(STD_PROGS)" +else + $as_echo "#define HAVE_RDS_BUILD 1" >>confdefs.h + + + ADDITIONAL_OBJS="$ADDITIONAL_OBJS rds_stub${o}" + db_cv_locking="no" + if test "$db_rdsbuild_default" = "no" ; then + # The normal db_load and db_stat utilities use non-RDS features. + # This modifies those source files such that they can work with + # with --enable-rdsbuild, + LOCALEXAMPLES="examples" + LOCALSRC="src" + LOCALUTILS="util" + # Apply all .patch files underneath the patches directory + # to local copies in the building directory. + for f in `grep -v '^#' $topdir/dist/rds/patchlist`; do + localdir=`dirname $f` + rm -f ./$f + test -d $localdir || mkdir -p $localdir || exit 1 + cp $topdir/$f $f && \ + patch $f $topdir/dist/rds/patches/$f.patch && \ + chmod 444 $f || exit 1 + done + fi +fi + +# AH_TEMPLATE(HAVE_LOCKING, [Define to 1 if building in locking support.]) +if test "$db_cv_locking" = "yes"; then +# AC_DEFINE(HAVE_LOCKING) + ADDITIONAL_OBJS="$ADDITIONAL_OBJS \$(LOCK_OBJS)" +else + ADDITIONAL_OBJS="$ADDITIONAL_OBJS lock_stub${o}" +fi + +# If DIAGNOSTIC is defined (but not RDS), include the log print routines in the +# library itself, various diagnostic modes use them. +if test "$db_cv_diagnostic" = "yes"; then + if test "$db_cv_rdsbuild" = "no"; then + ADDITIONAL_OBJS="$ADDITIONAL_OBJS \$(PRINT_OBJS)" + fi + PRINTLOG_OBJS="" +else + PRINTLOG_OBJS="\$(PRINT_OBJS)" +fi + +# If building for QNX, we need additional OS files. +if test "$qnx_build" = "yes"; then + ADDITIONAL_OBJS="$ADDITIONAL_OBJS os_qnx_fsync${o} os_qnx_open${o}" +fi + +# The DBM API can be disabled. +if test "$db_cv_dbm" = "yes"; then + $as_echo "#define HAVE_DBM 1" >>confdefs.h + + + ADDITIONAL_OBJS="$ADDITIONAL_OBJS dbm${o} hsearch${o}" +fi + +# The output and error messages can be stripped. +if test "$db_cv_stripped_messages" = "yes"; then + $as_echo "#define HAVE_STRIPPED_MESSAGES 1" >>confdefs.h + + +fi + +# The output and error messages can be localized. +if test "$db_cv_localization" = "yes"; then + $as_echo "#define HAVE_LOCALIZATION 1" >>confdefs.h + + +fi + +# We need to add the additional object files into the Makefile with the correct +# suffix. We can't use $LTLIBOBJS itself, because that variable has $U encoded +# in it for automake, and that's not what we want. See SR #7227 for additional +# information. +# +# XXX: I'm not sure this is correct. +REPLACEMENT_OBJS=`echo "$LIBOBJS" | + sed "s,\.[^.]* ,$o ,g;s,\.[^.]*$,$o,"` + +# This is necessary so that .o files in LIBOBJS are also built via +# the ANSI2KNR-filtering rules. +LIBOBJS=`echo "$LIBOBJS" | + sed 's,\.[^.]* ,$U&,g;s,\.[^.]*$,$U&,'` +LTLIBOBJS=`echo "$LIBOBJS" | + sed 's,\.[^.]* ,.lo ,g;s,\.[^.]*$,.lo,'` + + +# Initial output file list. +CREATE_LIST="Makefile + db_cxx.h:$topdir/src/dbinc/db_cxx.in + db_int.h:$topdir/src/dbinc/db_int.in + clib_port.h:$topdir/dist/clib_port.in" +if test "$db_cv_tcl" = "yes"; then +CREATE_LIST="$CREATE_LIST + include.tcl:$topdir/test/tcl/include.tcl" +fi + +# Create the db.h file from a source file, a list of global function +# prototypes, and, if configured for unique names, a list of #defines +# to do DB_VERSION_UNIQUE_NAME substitution. +if test "$db_cv_uniquename" = "yes"; then + CREATE_LIST="$CREATE_LIST + db.h:$topdir/src/dbinc/db.in:$topdir/src/dbinc_auto/api_flags.in:$topdir/src/dbinc_auto/ext_def.in:$topdir/src/dbinc_auto/ext_prot.in" +else + CREATE_LIST="$CREATE_LIST + db.h:$topdir/src/dbinc/db.in:$topdir/src/dbinc_auto/api_flags.in:$topdir/src/dbinc_auto/ext_prot.in" +fi + +# If configured for unique names, create the db_int_uext.h file (which +# does the DB_VERSION_UNIQUE_NAME substitution), which is included by +# the db_int.h file. +if test "$db_cv_uniquename" = "yes"; then + CREATE_LIST="$CREATE_LIST + db_int_def.h:$topdir/src/dbinc_auto/int_def.in" + db_int_def='#include "db_int_def.h"' +fi + +# Create the db_185.h and db185_int.h files from source files, a list of +# global function prototypes, and, if configured for unique names, a list +# of #defines to do DB_VERSION_UNIQUE_NAME substitution. +if test "$db_cv_compat185" = "yes"; then + if test "$db_cv_uniquename" = "yes"; then + CREATE_LIST="$CREATE_LIST + db_185.h:$topdir/src/dbinc/db_185.in:$topdir/src/dbinc_auto/ext_185_def.in:$topdir/src/dbinc_auto/ext_185_prot.in + db185_int.h:$topdir/lang/db185/db185_int.in:$topdir/src/dbinc_auto/ext_185_def.in:$topdir/src/dbinc_auto/ext_185_prot.in" + else + CREATE_LIST="$CREATE_LIST + db_185.h:$topdir/src/dbinc/db_185.in:$topdir/src/dbinc_auto/ext_185_prot.in + db185_int.h:$topdir/lang/db185/db185_int.in:$topdir/src/dbinc_auto/ext_185_prot.in" + fi +fi + +if test "$db_cv_stl" = "yes"; then + CREATE_LIST="$CREATE_LIST + dbstl_common.h:$topdir/lang/cxx/stl/dbstl_common.in" +fi + +if test "x$subdirs" != "x"; then + subdir_cmd="@for d in ${subdirs}; do (cd \$\$d && \${MAKE} \$@) ; done" +fi + +ac_config_files="$ac_config_files $CREATE_LIST" + +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, we kill variables containing newlines. +# 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. +( + for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do + eval ac_val=\$$ac_var + case $ac_val in #( + *${as_nl}*) + case $ac_var in #( + *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 +$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; + esac + case $ac_var in #( + _ | IFS | as_nl) ;; #( + BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( + *) { eval $ac_var=; unset $ac_var;} ;; + esac ;; + esac + done + + (set) 2>&1 | + case $as_nl`(ac_space=' '; set) 2>&1` in #( + *${as_nl}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 "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" + ;; + esac | + sort +) | + sed ' + /^ac_cv_env_/b end + t clear + :clear + s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ + t end + s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ + :end' >>confcache +if diff "$cache_file" confcache >/dev/null 2>&1; then :; else + if test -w "$cache_file"; then + if test "x$cache_file" != "x/dev/null"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5 +$as_echo "$as_me: updating cache $cache_file" >&6;} + if test ! -f "$cache_file" || test -h "$cache_file"; then + cat confcache >"$cache_file" + else + case $cache_file in #( + */* | ?:*) + mv -f confcache "$cache_file"$$ && + mv -f "$cache_file"$$ "$cache_file" ;; #( + *) + mv -f confcache "$cache_file" ;; + esac + fi + fi + else + { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5 +$as_echo "$as_me: not updating unwritable cache $cache_file" >&6;} + 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}' + +DEFS=-DHAVE_CONFIG_H + +ac_libobjs= +ac_ltlibobjs= +U= +for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue + # 1. Remove the extension, and $U if already installed. + ac_script='s/\$U\././;s/\.o$//;s/\.obj$//' + ac_i=`$as_echo "$ac_i" | sed "$ac_script"` + # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR + # will be set to the directory where LIBOBJS objects are built. + as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext" + as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo' +done +LIBOBJS=$ac_libobjs + +LTLIBOBJS=$ac_ltlibobjs + + + +: "${CONFIG_STATUS=./config.status}" +ac_write_fail=0 +ac_clean_files_save=$ac_clean_files +ac_clean_files="$ac_clean_files $CONFIG_STATUS" +{ $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5 +$as_echo "$as_me: creating $CONFIG_STATUS" >&6;} +as_write_fail=0 +cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1 +#! $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} +export SHELL +_ASEOF +cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1 +## -------------------- ## +## M4sh Initialization. ## +## -------------------- ## + +# Be more Bourne compatible +DUALCASE=1; export DUALCASE # for MKS sh +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : + emulate sh + NULLCMD=: + # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else + case `(set -o) 2>/dev/null` in #( + *posix*) : + set -o posix ;; #( + *) : + ;; +esac +fi + + +as_nl=' +' +export as_nl +# Printing a long string crashes Solaris 7 /usr/bin/printf. +as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo +# Prefer a ksh shell builtin over an external printf program on Solaris, +# but without wasting forks for bash or zsh. +if test -z "$BASH_VERSION$ZSH_VERSION" \ + && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='print -r --' + as_echo_n='print -rn --' +elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='printf %s\n' + as_echo_n='printf %s' +else + if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then + as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' + as_echo_n='/usr/ucb/echo -n' + else + as_echo_body='eval expr "X$1" : "X\\(.*\\)"' + as_echo_n_body='eval + arg=$1; + case $arg in #( + *"$as_nl"*) + expr "X$arg" : "X\\(.*\\)$as_nl"; + arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; + esac; + expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" + ' + export as_echo_n_body + as_echo_n='sh -c $as_echo_n_body as_echo' + fi + export as_echo_body + as_echo='sh -c $as_echo_body as_echo' +fi + +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + PATH_SEPARATOR=: + (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { + (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || + PATH_SEPARATOR=';' + } +fi + + +# IFS +# We need space, tab and new line, in precisely that order. Quoting is +# there to prevent editors from complaining about space-tab. +# (If _AS_PATH_WALK were called with IFS unset, it would disable word +# splitting by setting IFS to empty value.) +IFS=" "" $as_nl" + +# Find who we are. Look in the path if we contain no directory separator. +as_myself= +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 +IFS=$as_save_IFS + + ;; +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 + $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 + exit 1 +fi + +# Unset variables that we do not need and which cause bugs (e.g. in +# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" +# suppresses any "Segmentation fault" message there. '((' could +# trigger a bug in pdksh 5.2.14. +for as_var in BASH_ENV ENV MAIL MAILPATH +do eval test x\${$as_var+set} = xset \ + && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : +done +PS1='$ ' +PS2='> ' +PS4='+ ' + +# NLS nuisances. +LC_ALL=C +export LC_ALL +LANGUAGE=C +export LANGUAGE + +# CDPATH. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + + +# as_fn_error STATUS ERROR [LINENO LOG_FD] +# ---------------------------------------- +# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are +# provided, also output the error to LOG_FD, referencing LINENO. Then exit the +# script with STATUS, using 1 if that was 0. +as_fn_error () +{ + as_status=$1; test $as_status -eq 0 && as_status=1 + if test "$4"; then + as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 + fi + $as_echo "$as_me: error: $2" >&2 + as_fn_exit $as_status +} # as_fn_error + + +# as_fn_set_status STATUS +# ----------------------- +# Set $? to STATUS, without forking. +as_fn_set_status () +{ + return $1 +} # as_fn_set_status + +# as_fn_exit STATUS +# ----------------- +# Exit the shell with STATUS, even in a "trap 0" or "set -e" context. +as_fn_exit () +{ + set +e + as_fn_set_status $1 + exit $1 +} # as_fn_exit + +# as_fn_unset VAR +# --------------- +# Portably unset VAR. +as_fn_unset () +{ + { eval $1=; unset $1;} +} +as_unset=as_fn_unset +# as_fn_append VAR VALUE +# ---------------------- +# Append the text in VALUE to the end of the definition contained in VAR. Take +# advantage of any shell optimizations that allow amortized linear growth over +# repeated appends, instead of the typical quadratic growth present in naive +# implementations. +if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : + eval 'as_fn_append () + { + eval $1+=\$2 + }' +else + as_fn_append () + { + eval $1=\$$1\$2 + } +fi # as_fn_append + +# as_fn_arith ARG... +# ------------------ +# Perform arithmetic evaluation on the ARGs, and store the result in the +# global $as_val. Take advantage of shells that can avoid forks. The arguments +# must be portable across $(()) and expr. +if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : + eval 'as_fn_arith () + { + as_val=$(( $* )) + }' +else + as_fn_arith () + { + as_val=`expr "$@" || test $? -eq 1` + } +fi # as_fn_arith + + +if expr a : '\(a\)' >/dev/null 2>&1 && + test "X`expr 00001 : '.*\(...\)'`" = X001; 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 + +if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then + as_dirname=dirname +else + as_dirname=false +fi + +as_me=`$as_basename -- "$0" || +$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X/"$0" | + sed '/^.*\/\([^/][^/]*\)\/*$/{ + s//\1/ + q + } + /^X\/\(\/\/\)$/{ + s//\1/ + q + } + /^X\/\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + +# 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 + +ECHO_C= ECHO_N= ECHO_T= +case `echo -n x` in #((((( +-n*) + case `echo 'xy\c'` in + *c*) ECHO_T=' ';; # ECHO_T is single tab character. + xy) ECHO_C='\c';; + *) echo `echo ksh88 bug on AIX 6.1` > /dev/null + ECHO_T=' ';; + esac;; +*) + ECHO_N='-n';; +esac + +rm -f conf$$ conf$$.exe conf$$.file +if test -d conf$$.dir; then + rm -f conf$$.dir/conf$$.file +else + rm -f conf$$.dir + mkdir conf$$.dir 2>/dev/null +fi +if (echo >conf$$.file) 2>/dev/null; then + if ln -s conf$$.file conf$$ 2>/dev/null; then + as_ln_s='ln -s' + # ... but there are two gotchas: + # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. + # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. + # In both cases, we have to default to `cp -p'. + ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || + as_ln_s='cp -p' + elif ln conf$$.file conf$$ 2>/dev/null; then + as_ln_s=ln + else + as_ln_s='cp -p' + fi +else + as_ln_s='cp -p' +fi +rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file +rmdir conf$$.dir 2>/dev/null + + +# as_fn_mkdir_p +# ------------- +# Create "$as_dir" as a directory, including parents if necessary. +as_fn_mkdir_p () +{ + + case $as_dir in #( + -*) as_dir=./$as_dir;; + esac + test -d "$as_dir" || eval $as_mkdir_p || { + as_dirs= + while :; do + case $as_dir in #( + *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( + *) as_qdir=$as_dir;; + esac + as_dirs="'$as_qdir' $as_dirs" + as_dir=`$as_dirname -- "$as_dir" || +$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_dir" : 'X\(//\)[^/]' \| \ + X"$as_dir" : 'X\(//\)$' \| \ + X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$as_dir" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + test -d "$as_dir" && break + done + test -z "$as_dirs" || eval "mkdir $as_dirs" + } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" + + +} # as_fn_mkdir_p +if mkdir -p . 2>/dev/null; then + as_mkdir_p='mkdir -p "$as_dir"' +else + test -d ./-p && rmdir ./-p + as_mkdir_p=false +fi + +if test -x / >/dev/null 2>&1; then + as_test_x='test -x' +else + if ls -dL / >/dev/null 2>&1; then + as_ls_L_option=L + else + as_ls_L_option= + fi + as_test_x=' + eval sh -c '\'' + if test -d "$1"; then + test -d "$1/."; + else + case $1 in #( + -*)set "./$1";; + esac; + case `ls -ld'$as_ls_L_option' "$1" 2>/dev/null` in #(( + ???[sx]*):;;*)false;;esac;fi + '\'' sh + ' +fi +as_executable_p=$as_test_x + +# 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'" + + +exec 6>&1 +## ----------------------------------- ## +## Main body of $CONFIG_STATUS script. ## +## ----------------------------------- ## +_ASEOF +test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1 + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +# Save the log message, to keep $0 and so on meaningful, and to +# report actual input values of CONFIG_FILES etc. instead of their +# values after options handling. +ac_log=" +This file was extended by Berkeley DB $as_me 5.4.0, which was +generated by GNU Autoconf 2.68. Invocation command line was + + CONFIG_FILES = $CONFIG_FILES + CONFIG_HEADERS = $CONFIG_HEADERS + CONFIG_LINKS = $CONFIG_LINKS + CONFIG_COMMANDS = $CONFIG_COMMANDS + $ $0 $@ + +on `(hostname || uname -n) 2>/dev/null | sed 1q` +" + +_ACEOF + +case $ac_config_files in *" +"*) set x $ac_config_files; shift; ac_config_files=$*;; +esac + +case $ac_config_headers in *" +"*) set x $ac_config_headers; shift; ac_config_headers=$*;; +esac + + +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +# Files that config.status was made for. +config_files="$ac_config_files" +config_headers="$ac_config_headers" +config_commands="$ac_config_commands" + +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +ac_cs_usage="\ +\`$as_me' instantiates files and other configuration actions +from templates according to the current configuration. Unless the files +and actions are specified as TAGs, all are instantiated by default. + +Usage: $0 [OPTION]... [TAG]... + + -h, --help print this help, then exit + -V, --version print version number and configuration settings, then exit + --config print configuration, then exit + -q, --quiet, --silent + 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 + --header=FILE[:TEMPLATE] + instantiate the configuration header FILE + +Configuration files: +$config_files + +Configuration headers: +$config_headers + +Configuration commands: +$config_commands + +Report bugs to ." + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" +ac_cs_version="\\ +Berkeley DB config.status 5.4.0 +configured by $0, generated by GNU Autoconf 2.68, + with options \\"\$ac_cs_config\\" + +Copyright (C) 2010 Free Software Foundation, Inc. +This config.status script is free software; the Free Software Foundation +gives unlimited permission to copy, distribute and modify it." + +ac_pwd='$ac_pwd' +srcdir='$srcdir' +INSTALL='$INSTALL' +AWK='$AWK' +test -n "\$AWK" || AWK=awk +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +# The default lists apply if the user does not specify any file. +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=`expr "X$1" : 'X\([^=]*\)='` + ac_optarg= + ac_shift=: + ;; + *) + ac_option=$1 + ac_optarg=$2 + ac_shift=shift + ;; + esac + + case $ac_option in + # Handling of the options. + -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) + ac_cs_recheck=: ;; + --version | --versio | --versi | --vers | --ver | --ve | --v | -V ) + $as_echo "$ac_cs_version"; exit ;; + --config | --confi | --conf | --con | --co | --c ) + $as_echo "$ac_cs_config"; exit ;; + --debug | --debu | --deb | --de | --d | -d ) + debug=: ;; + --file | --fil | --fi | --f ) + $ac_shift + case $ac_optarg in + *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; + '') as_fn_error $? "missing file argument" ;; + esac + as_fn_append CONFIG_FILES " '$ac_optarg'" + ac_need_defaults=false;; + --header | --heade | --head | --hea ) + $ac_shift + case $ac_optarg in + *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; + esac + as_fn_append CONFIG_HEADERS " '$ac_optarg'" + ac_need_defaults=false;; + --he | --h) + # Conflict between --help and --header + as_fn_error $? "ambiguous option: \`$1' +Try \`$0 --help' for more information.";; + --help | --hel | -h ) + $as_echo "$ac_cs_usage"; exit ;; + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil | --si | --s) + ac_cs_silent=: ;; + + # This is an error. + -*) as_fn_error $? "unrecognized option: \`$1' +Try \`$0 --help' for more information." ;; + + *) as_fn_append ac_config_targets " $1" + ac_need_defaults=false ;; + + 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 || ac_write_fail=1 +if \$ac_cs_recheck; then + set X '$SHELL' '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion + shift + \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6 + CONFIG_SHELL='$SHELL' + export CONFIG_SHELL + exec "\$@" +fi + +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +exec 5>>config.log +{ + echo + sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX +## Running $as_me. ## +_ASBOX + $as_echo "$ac_log" +} >&5 + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +# +# INIT-COMMANDS +# + + +# The HP-UX ksh and POSIX shell print the target directory to stdout +# if CDPATH is set. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + +sed_quote_subst='$sed_quote_subst' +double_quote_subst='$double_quote_subst' +delay_variable_subst='$delay_variable_subst' +macro_version='`$ECHO "$macro_version" | $SED "$delay_single_quote_subst"`' +macro_revision='`$ECHO "$macro_revision" | $SED "$delay_single_quote_subst"`' +enable_shared='`$ECHO "$enable_shared" | $SED "$delay_single_quote_subst"`' +enable_static='`$ECHO "$enable_static" | $SED "$delay_single_quote_subst"`' +pic_mode='`$ECHO "$pic_mode" | $SED "$delay_single_quote_subst"`' +enable_fast_install='`$ECHO "$enable_fast_install" | $SED "$delay_single_quote_subst"`' +SHELL='`$ECHO "$SHELL" | $SED "$delay_single_quote_subst"`' +ECHO='`$ECHO "$ECHO" | $SED "$delay_single_quote_subst"`' +host_alias='`$ECHO "$host_alias" | $SED "$delay_single_quote_subst"`' +host='`$ECHO "$host" | $SED "$delay_single_quote_subst"`' +host_os='`$ECHO "$host_os" | $SED "$delay_single_quote_subst"`' +build_alias='`$ECHO "$build_alias" | $SED "$delay_single_quote_subst"`' +build='`$ECHO "$build" | $SED "$delay_single_quote_subst"`' +build_os='`$ECHO "$build_os" | $SED "$delay_single_quote_subst"`' +SED='`$ECHO "$SED" | $SED "$delay_single_quote_subst"`' +Xsed='`$ECHO "$Xsed" | $SED "$delay_single_quote_subst"`' +GREP='`$ECHO "$GREP" | $SED "$delay_single_quote_subst"`' +EGREP='`$ECHO "$EGREP" | $SED "$delay_single_quote_subst"`' +FGREP='`$ECHO "$FGREP" | $SED "$delay_single_quote_subst"`' +LD='`$ECHO "$LD" | $SED "$delay_single_quote_subst"`' +NM='`$ECHO "$NM" | $SED "$delay_single_quote_subst"`' +LN_S='`$ECHO "$LN_S" | $SED "$delay_single_quote_subst"`' +max_cmd_len='`$ECHO "$max_cmd_len" | $SED "$delay_single_quote_subst"`' +ac_objext='`$ECHO "$ac_objext" | $SED "$delay_single_quote_subst"`' +exeext='`$ECHO "$exeext" | $SED "$delay_single_quote_subst"`' +lt_unset='`$ECHO "$lt_unset" | $SED "$delay_single_quote_subst"`' +lt_SP2NL='`$ECHO "$lt_SP2NL" | $SED "$delay_single_quote_subst"`' +lt_NL2SP='`$ECHO "$lt_NL2SP" | $SED "$delay_single_quote_subst"`' +lt_cv_to_host_file_cmd='`$ECHO "$lt_cv_to_host_file_cmd" | $SED "$delay_single_quote_subst"`' +lt_cv_to_tool_file_cmd='`$ECHO "$lt_cv_to_tool_file_cmd" | $SED "$delay_single_quote_subst"`' +reload_flag='`$ECHO "$reload_flag" | $SED "$delay_single_quote_subst"`' +reload_cmds='`$ECHO "$reload_cmds" | $SED "$delay_single_quote_subst"`' +OBJDUMP='`$ECHO "$OBJDUMP" | $SED "$delay_single_quote_subst"`' +deplibs_check_method='`$ECHO "$deplibs_check_method" | $SED "$delay_single_quote_subst"`' +file_magic_cmd='`$ECHO "$file_magic_cmd" | $SED "$delay_single_quote_subst"`' +file_magic_glob='`$ECHO "$file_magic_glob" | $SED "$delay_single_quote_subst"`' +want_nocaseglob='`$ECHO "$want_nocaseglob" | $SED "$delay_single_quote_subst"`' +DLLTOOL='`$ECHO "$DLLTOOL" | $SED "$delay_single_quote_subst"`' +sharedlib_from_linklib_cmd='`$ECHO "$sharedlib_from_linklib_cmd" | $SED "$delay_single_quote_subst"`' +AR='`$ECHO "$AR" | $SED "$delay_single_quote_subst"`' +AR_FLAGS='`$ECHO "$AR_FLAGS" | $SED "$delay_single_quote_subst"`' +archiver_list_spec='`$ECHO "$archiver_list_spec" | $SED "$delay_single_quote_subst"`' +STRIP='`$ECHO "$STRIP" | $SED "$delay_single_quote_subst"`' +RANLIB='`$ECHO "$RANLIB" | $SED "$delay_single_quote_subst"`' +old_postinstall_cmds='`$ECHO "$old_postinstall_cmds" | $SED "$delay_single_quote_subst"`' +old_postuninstall_cmds='`$ECHO "$old_postuninstall_cmds" | $SED "$delay_single_quote_subst"`' +old_archive_cmds='`$ECHO "$old_archive_cmds" | $SED "$delay_single_quote_subst"`' +lock_old_archive_extraction='`$ECHO "$lock_old_archive_extraction" | $SED "$delay_single_quote_subst"`' +CC='`$ECHO "$CC" | $SED "$delay_single_quote_subst"`' +CFLAGS='`$ECHO "$CFLAGS" | $SED "$delay_single_quote_subst"`' +compiler='`$ECHO "$compiler" | $SED "$delay_single_quote_subst"`' +GCC='`$ECHO "$GCC" | $SED "$delay_single_quote_subst"`' +lt_cv_sys_global_symbol_pipe='`$ECHO "$lt_cv_sys_global_symbol_pipe" | $SED "$delay_single_quote_subst"`' +lt_cv_sys_global_symbol_to_cdecl='`$ECHO "$lt_cv_sys_global_symbol_to_cdecl" | $SED "$delay_single_quote_subst"`' +lt_cv_sys_global_symbol_to_c_name_address='`$ECHO "$lt_cv_sys_global_symbol_to_c_name_address" | $SED "$delay_single_quote_subst"`' +lt_cv_sys_global_symbol_to_c_name_address_lib_prefix='`$ECHO "$lt_cv_sys_global_symbol_to_c_name_address_lib_prefix" | $SED "$delay_single_quote_subst"`' +nm_file_list_spec='`$ECHO "$nm_file_list_spec" | $SED "$delay_single_quote_subst"`' +lt_sysroot='`$ECHO "$lt_sysroot" | $SED "$delay_single_quote_subst"`' +objdir='`$ECHO "$objdir" | $SED "$delay_single_quote_subst"`' +MAGIC_CMD='`$ECHO "$MAGIC_CMD" | $SED "$delay_single_quote_subst"`' +lt_prog_compiler_no_builtin_flag='`$ECHO "$lt_prog_compiler_no_builtin_flag" | $SED "$delay_single_quote_subst"`' +lt_prog_compiler_pic='`$ECHO "$lt_prog_compiler_pic" | $SED "$delay_single_quote_subst"`' +lt_prog_compiler_wl='`$ECHO "$lt_prog_compiler_wl" | $SED "$delay_single_quote_subst"`' +lt_prog_compiler_static='`$ECHO "$lt_prog_compiler_static" | $SED "$delay_single_quote_subst"`' +lt_cv_prog_compiler_c_o='`$ECHO "$lt_cv_prog_compiler_c_o" | $SED "$delay_single_quote_subst"`' +need_locks='`$ECHO "$need_locks" | $SED "$delay_single_quote_subst"`' +MANIFEST_TOOL='`$ECHO "$MANIFEST_TOOL" | $SED "$delay_single_quote_subst"`' +DSYMUTIL='`$ECHO "$DSYMUTIL" | $SED "$delay_single_quote_subst"`' +NMEDIT='`$ECHO "$NMEDIT" | $SED "$delay_single_quote_subst"`' +LIPO='`$ECHO "$LIPO" | $SED "$delay_single_quote_subst"`' +OTOOL='`$ECHO "$OTOOL" | $SED "$delay_single_quote_subst"`' +OTOOL64='`$ECHO "$OTOOL64" | $SED "$delay_single_quote_subst"`' +libext='`$ECHO "$libext" | $SED "$delay_single_quote_subst"`' +shrext_cmds='`$ECHO "$shrext_cmds" | $SED "$delay_single_quote_subst"`' +extract_expsyms_cmds='`$ECHO "$extract_expsyms_cmds" | $SED "$delay_single_quote_subst"`' +archive_cmds_need_lc='`$ECHO "$archive_cmds_need_lc" | $SED "$delay_single_quote_subst"`' +enable_shared_with_static_runtimes='`$ECHO "$enable_shared_with_static_runtimes" | $SED "$delay_single_quote_subst"`' +export_dynamic_flag_spec='`$ECHO "$export_dynamic_flag_spec" | $SED "$delay_single_quote_subst"`' +whole_archive_flag_spec='`$ECHO "$whole_archive_flag_spec" | $SED "$delay_single_quote_subst"`' +compiler_needs_object='`$ECHO "$compiler_needs_object" | $SED "$delay_single_quote_subst"`' +old_archive_from_new_cmds='`$ECHO "$old_archive_from_new_cmds" | $SED "$delay_single_quote_subst"`' +old_archive_from_expsyms_cmds='`$ECHO "$old_archive_from_expsyms_cmds" | $SED "$delay_single_quote_subst"`' +archive_cmds='`$ECHO "$archive_cmds" | $SED "$delay_single_quote_subst"`' +archive_expsym_cmds='`$ECHO "$archive_expsym_cmds" | $SED "$delay_single_quote_subst"`' +module_cmds='`$ECHO "$module_cmds" | $SED "$delay_single_quote_subst"`' +module_expsym_cmds='`$ECHO "$module_expsym_cmds" | $SED "$delay_single_quote_subst"`' +with_gnu_ld='`$ECHO "$with_gnu_ld" | $SED "$delay_single_quote_subst"`' +allow_undefined_flag='`$ECHO "$allow_undefined_flag" | $SED "$delay_single_quote_subst"`' +no_undefined_flag='`$ECHO "$no_undefined_flag" | $SED "$delay_single_quote_subst"`' +hardcode_libdir_flag_spec='`$ECHO "$hardcode_libdir_flag_spec" | $SED "$delay_single_quote_subst"`' +hardcode_libdir_flag_spec_ld='`$ECHO "$hardcode_libdir_flag_spec_ld" | $SED "$delay_single_quote_subst"`' +hardcode_libdir_separator='`$ECHO "$hardcode_libdir_separator" | $SED "$delay_single_quote_subst"`' +hardcode_direct='`$ECHO "$hardcode_direct" | $SED "$delay_single_quote_subst"`' +hardcode_direct_absolute='`$ECHO "$hardcode_direct_absolute" | $SED "$delay_single_quote_subst"`' +hardcode_minus_L='`$ECHO "$hardcode_minus_L" | $SED "$delay_single_quote_subst"`' +hardcode_shlibpath_var='`$ECHO "$hardcode_shlibpath_var" | $SED "$delay_single_quote_subst"`' +hardcode_automatic='`$ECHO "$hardcode_automatic" | $SED "$delay_single_quote_subst"`' +inherit_rpath='`$ECHO "$inherit_rpath" | $SED "$delay_single_quote_subst"`' +link_all_deplibs='`$ECHO "$link_all_deplibs" | $SED "$delay_single_quote_subst"`' +always_export_symbols='`$ECHO "$always_export_symbols" | $SED "$delay_single_quote_subst"`' +export_symbols_cmds='`$ECHO "$export_symbols_cmds" | $SED "$delay_single_quote_subst"`' +exclude_expsyms='`$ECHO "$exclude_expsyms" | $SED "$delay_single_quote_subst"`' +include_expsyms='`$ECHO "$include_expsyms" | $SED "$delay_single_quote_subst"`' +prelink_cmds='`$ECHO "$prelink_cmds" | $SED "$delay_single_quote_subst"`' +postlink_cmds='`$ECHO "$postlink_cmds" | $SED "$delay_single_quote_subst"`' +file_list_spec='`$ECHO "$file_list_spec" | $SED "$delay_single_quote_subst"`' +variables_saved_for_relink='`$ECHO "$variables_saved_for_relink" | $SED "$delay_single_quote_subst"`' +need_lib_prefix='`$ECHO "$need_lib_prefix" | $SED "$delay_single_quote_subst"`' +need_version='`$ECHO "$need_version" | $SED "$delay_single_quote_subst"`' +version_type='`$ECHO "$version_type" | $SED "$delay_single_quote_subst"`' +runpath_var='`$ECHO "$runpath_var" | $SED "$delay_single_quote_subst"`' +shlibpath_var='`$ECHO "$shlibpath_var" | $SED "$delay_single_quote_subst"`' +shlibpath_overrides_runpath='`$ECHO "$shlibpath_overrides_runpath" | $SED "$delay_single_quote_subst"`' +libname_spec='`$ECHO "$libname_spec" | $SED "$delay_single_quote_subst"`' +library_names_spec='`$ECHO "$library_names_spec" | $SED "$delay_single_quote_subst"`' +soname_spec='`$ECHO "$soname_spec" | $SED "$delay_single_quote_subst"`' +install_override_mode='`$ECHO "$install_override_mode" | $SED "$delay_single_quote_subst"`' +postinstall_cmds='`$ECHO "$postinstall_cmds" | $SED "$delay_single_quote_subst"`' +postuninstall_cmds='`$ECHO "$postuninstall_cmds" | $SED "$delay_single_quote_subst"`' +finish_cmds='`$ECHO "$finish_cmds" | $SED "$delay_single_quote_subst"`' +finish_eval='`$ECHO "$finish_eval" | $SED "$delay_single_quote_subst"`' +hardcode_into_libs='`$ECHO "$hardcode_into_libs" | $SED "$delay_single_quote_subst"`' +sys_lib_search_path_spec='`$ECHO "$sys_lib_search_path_spec" | $SED "$delay_single_quote_subst"`' +sys_lib_dlsearch_path_spec='`$ECHO "$sys_lib_dlsearch_path_spec" | $SED "$delay_single_quote_subst"`' +hardcode_action='`$ECHO "$hardcode_action" | $SED "$delay_single_quote_subst"`' +enable_dlopen='`$ECHO "$enable_dlopen" | $SED "$delay_single_quote_subst"`' +enable_dlopen_self='`$ECHO "$enable_dlopen_self" | $SED "$delay_single_quote_subst"`' +enable_dlopen_self_static='`$ECHO "$enable_dlopen_self_static" | $SED "$delay_single_quote_subst"`' +old_striplib='`$ECHO "$old_striplib" | $SED "$delay_single_quote_subst"`' +striplib='`$ECHO "$striplib" | $SED "$delay_single_quote_subst"`' +compiler_lib_search_dirs='`$ECHO "$compiler_lib_search_dirs" | $SED "$delay_single_quote_subst"`' +predep_objects='`$ECHO "$predep_objects" | $SED "$delay_single_quote_subst"`' +postdep_objects='`$ECHO "$postdep_objects" | $SED "$delay_single_quote_subst"`' +predeps='`$ECHO "$predeps" | $SED "$delay_single_quote_subst"`' +postdeps='`$ECHO "$postdeps" | $SED "$delay_single_quote_subst"`' +compiler_lib_search_path='`$ECHO "$compiler_lib_search_path" | $SED "$delay_single_quote_subst"`' +LD_CXX='`$ECHO "$LD_CXX" | $SED "$delay_single_quote_subst"`' +reload_flag_CXX='`$ECHO "$reload_flag_CXX" | $SED "$delay_single_quote_subst"`' +reload_cmds_CXX='`$ECHO "$reload_cmds_CXX" | $SED "$delay_single_quote_subst"`' +old_archive_cmds_CXX='`$ECHO "$old_archive_cmds_CXX" | $SED "$delay_single_quote_subst"`' +compiler_CXX='`$ECHO "$compiler_CXX" | $SED "$delay_single_quote_subst"`' +GCC_CXX='`$ECHO "$GCC_CXX" | $SED "$delay_single_quote_subst"`' +lt_prog_compiler_no_builtin_flag_CXX='`$ECHO "$lt_prog_compiler_no_builtin_flag_CXX" | $SED "$delay_single_quote_subst"`' +lt_prog_compiler_pic_CXX='`$ECHO "$lt_prog_compiler_pic_CXX" | $SED "$delay_single_quote_subst"`' +lt_prog_compiler_wl_CXX='`$ECHO "$lt_prog_compiler_wl_CXX" | $SED "$delay_single_quote_subst"`' +lt_prog_compiler_static_CXX='`$ECHO "$lt_prog_compiler_static_CXX" | $SED "$delay_single_quote_subst"`' +lt_cv_prog_compiler_c_o_CXX='`$ECHO "$lt_cv_prog_compiler_c_o_CXX" | $SED "$delay_single_quote_subst"`' +archive_cmds_need_lc_CXX='`$ECHO "$archive_cmds_need_lc_CXX" | $SED "$delay_single_quote_subst"`' +enable_shared_with_static_runtimes_CXX='`$ECHO "$enable_shared_with_static_runtimes_CXX" | $SED "$delay_single_quote_subst"`' +export_dynamic_flag_spec_CXX='`$ECHO "$export_dynamic_flag_spec_CXX" | $SED "$delay_single_quote_subst"`' +whole_archive_flag_spec_CXX='`$ECHO "$whole_archive_flag_spec_CXX" | $SED "$delay_single_quote_subst"`' +compiler_needs_object_CXX='`$ECHO "$compiler_needs_object_CXX" | $SED "$delay_single_quote_subst"`' +old_archive_from_new_cmds_CXX='`$ECHO "$old_archive_from_new_cmds_CXX" | $SED "$delay_single_quote_subst"`' +old_archive_from_expsyms_cmds_CXX='`$ECHO "$old_archive_from_expsyms_cmds_CXX" | $SED "$delay_single_quote_subst"`' +archive_cmds_CXX='`$ECHO "$archive_cmds_CXX" | $SED "$delay_single_quote_subst"`' +archive_expsym_cmds_CXX='`$ECHO "$archive_expsym_cmds_CXX" | $SED "$delay_single_quote_subst"`' +module_cmds_CXX='`$ECHO "$module_cmds_CXX" | $SED "$delay_single_quote_subst"`' +module_expsym_cmds_CXX='`$ECHO "$module_expsym_cmds_CXX" | $SED "$delay_single_quote_subst"`' +with_gnu_ld_CXX='`$ECHO "$with_gnu_ld_CXX" | $SED "$delay_single_quote_subst"`' +allow_undefined_flag_CXX='`$ECHO "$allow_undefined_flag_CXX" | $SED "$delay_single_quote_subst"`' +no_undefined_flag_CXX='`$ECHO "$no_undefined_flag_CXX" | $SED "$delay_single_quote_subst"`' +hardcode_libdir_flag_spec_CXX='`$ECHO "$hardcode_libdir_flag_spec_CXX" | $SED "$delay_single_quote_subst"`' +hardcode_libdir_flag_spec_ld_CXX='`$ECHO "$hardcode_libdir_flag_spec_ld_CXX" | $SED "$delay_single_quote_subst"`' +hardcode_libdir_separator_CXX='`$ECHO "$hardcode_libdir_separator_CXX" | $SED "$delay_single_quote_subst"`' +hardcode_direct_CXX='`$ECHO "$hardcode_direct_CXX" | $SED "$delay_single_quote_subst"`' +hardcode_direct_absolute_CXX='`$ECHO "$hardcode_direct_absolute_CXX" | $SED "$delay_single_quote_subst"`' +hardcode_minus_L_CXX='`$ECHO "$hardcode_minus_L_CXX" | $SED "$delay_single_quote_subst"`' +hardcode_shlibpath_var_CXX='`$ECHO "$hardcode_shlibpath_var_CXX" | $SED "$delay_single_quote_subst"`' +hardcode_automatic_CXX='`$ECHO "$hardcode_automatic_CXX" | $SED "$delay_single_quote_subst"`' +inherit_rpath_CXX='`$ECHO "$inherit_rpath_CXX" | $SED "$delay_single_quote_subst"`' +link_all_deplibs_CXX='`$ECHO "$link_all_deplibs_CXX" | $SED "$delay_single_quote_subst"`' +always_export_symbols_CXX='`$ECHO "$always_export_symbols_CXX" | $SED "$delay_single_quote_subst"`' +export_symbols_cmds_CXX='`$ECHO "$export_symbols_cmds_CXX" | $SED "$delay_single_quote_subst"`' +exclude_expsyms_CXX='`$ECHO "$exclude_expsyms_CXX" | $SED "$delay_single_quote_subst"`' +include_expsyms_CXX='`$ECHO "$include_expsyms_CXX" | $SED "$delay_single_quote_subst"`' +prelink_cmds_CXX='`$ECHO "$prelink_cmds_CXX" | $SED "$delay_single_quote_subst"`' +postlink_cmds_CXX='`$ECHO "$postlink_cmds_CXX" | $SED "$delay_single_quote_subst"`' +file_list_spec_CXX='`$ECHO "$file_list_spec_CXX" | $SED "$delay_single_quote_subst"`' +hardcode_action_CXX='`$ECHO "$hardcode_action_CXX" | $SED "$delay_single_quote_subst"`' +compiler_lib_search_dirs_CXX='`$ECHO "$compiler_lib_search_dirs_CXX" | $SED "$delay_single_quote_subst"`' +predep_objects_CXX='`$ECHO "$predep_objects_CXX" | $SED "$delay_single_quote_subst"`' +postdep_objects_CXX='`$ECHO "$postdep_objects_CXX" | $SED "$delay_single_quote_subst"`' +predeps_CXX='`$ECHO "$predeps_CXX" | $SED "$delay_single_quote_subst"`' +postdeps_CXX='`$ECHO "$postdeps_CXX" | $SED "$delay_single_quote_subst"`' +compiler_lib_search_path_CXX='`$ECHO "$compiler_lib_search_path_CXX" | $SED "$delay_single_quote_subst"`' + +LTCC='$LTCC' +LTCFLAGS='$LTCFLAGS' +compiler='$compiler_DEFAULT' + +# A function that is used when there is no print builtin or printf. +func_fallback_echo () +{ + eval 'cat <<_LTECHO_EOF +\$1 +_LTECHO_EOF' +} + +# Quote evaled strings. +for var in SHELL \ +ECHO \ +SED \ +GREP \ +EGREP \ +FGREP \ +LD \ +NM \ +LN_S \ +lt_SP2NL \ +lt_NL2SP \ +reload_flag \ +OBJDUMP \ +deplibs_check_method \ +file_magic_cmd \ +file_magic_glob \ +want_nocaseglob \ +DLLTOOL \ +sharedlib_from_linklib_cmd \ +AR \ +AR_FLAGS \ +archiver_list_spec \ +STRIP \ +RANLIB \ +CC \ +CFLAGS \ +compiler \ +lt_cv_sys_global_symbol_pipe \ +lt_cv_sys_global_symbol_to_cdecl \ +lt_cv_sys_global_symbol_to_c_name_address \ +lt_cv_sys_global_symbol_to_c_name_address_lib_prefix \ +nm_file_list_spec \ +lt_prog_compiler_no_builtin_flag \ +lt_prog_compiler_pic \ +lt_prog_compiler_wl \ +lt_prog_compiler_static \ +lt_cv_prog_compiler_c_o \ +need_locks \ +MANIFEST_TOOL \ +DSYMUTIL \ +NMEDIT \ +LIPO \ +OTOOL \ +OTOOL64 \ +shrext_cmds \ +export_dynamic_flag_spec \ +whole_archive_flag_spec \ +compiler_needs_object \ +with_gnu_ld \ +allow_undefined_flag \ +no_undefined_flag \ +hardcode_libdir_flag_spec \ +hardcode_libdir_flag_spec_ld \ +hardcode_libdir_separator \ +exclude_expsyms \ +include_expsyms \ +file_list_spec \ +variables_saved_for_relink \ +libname_spec \ +library_names_spec \ +soname_spec \ +install_override_mode \ +finish_eval \ +old_striplib \ +striplib \ +compiler_lib_search_dirs \ +predep_objects \ +postdep_objects \ +predeps \ +postdeps \ +compiler_lib_search_path \ +LD_CXX \ +reload_flag_CXX \ +compiler_CXX \ +lt_prog_compiler_no_builtin_flag_CXX \ +lt_prog_compiler_pic_CXX \ +lt_prog_compiler_wl_CXX \ +lt_prog_compiler_static_CXX \ +lt_cv_prog_compiler_c_o_CXX \ +export_dynamic_flag_spec_CXX \ +whole_archive_flag_spec_CXX \ +compiler_needs_object_CXX \ +with_gnu_ld_CXX \ +allow_undefined_flag_CXX \ +no_undefined_flag_CXX \ +hardcode_libdir_flag_spec_CXX \ +hardcode_libdir_flag_spec_ld_CXX \ +hardcode_libdir_separator_CXX \ +exclude_expsyms_CXX \ +include_expsyms_CXX \ +file_list_spec_CXX \ +compiler_lib_search_dirs_CXX \ +predep_objects_CXX \ +postdep_objects_CXX \ +predeps_CXX \ +postdeps_CXX \ +compiler_lib_search_path_CXX; do + case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in + *[\\\\\\\`\\"\\\$]*) + eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED \\"\\\$sed_quote_subst\\"\\\`\\\\\\"" + ;; + *) + eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" + ;; + esac +done + +# Double-quote double-evaled strings. +for var in reload_cmds \ +old_postinstall_cmds \ +old_postuninstall_cmds \ +old_archive_cmds \ +extract_expsyms_cmds \ +old_archive_from_new_cmds \ +old_archive_from_expsyms_cmds \ +archive_cmds \ +archive_expsym_cmds \ +module_cmds \ +module_expsym_cmds \ +export_symbols_cmds \ +prelink_cmds \ +postlink_cmds \ +postinstall_cmds \ +postuninstall_cmds \ +finish_cmds \ +sys_lib_search_path_spec \ +sys_lib_dlsearch_path_spec \ +reload_cmds_CXX \ +old_archive_cmds_CXX \ +old_archive_from_new_cmds_CXX \ +old_archive_from_expsyms_cmds_CXX \ +archive_cmds_CXX \ +archive_expsym_cmds_CXX \ +module_cmds_CXX \ +module_expsym_cmds_CXX \ +export_symbols_cmds_CXX \ +prelink_cmds_CXX \ +postlink_cmds_CXX; do + case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in + *[\\\\\\\`\\"\\\$]*) + eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED -e \\"\\\$double_quote_subst\\" -e \\"\\\$sed_quote_subst\\" -e \\"\\\$delay_variable_subst\\"\\\`\\\\\\"" + ;; + *) + eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" + ;; + esac +done + +ac_aux_dir='$ac_aux_dir' +xsi_shell='$xsi_shell' +lt_shell_append='$lt_shell_append' + +# See if we are running on zsh, and set the options which allow our +# commands through without removal of \ escapes INIT. +if test -n "\${ZSH_VERSION+set}" ; then + setopt NO_GLOB_SUBST +fi + + + PACKAGE='$PACKAGE' + VERSION='$VERSION' + TIMESTAMP='$TIMESTAMP' + RM='$RM' + ofile='$ofile' + + + + + + +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 + +# Handling of arguments. +for ac_config_target in $ac_config_targets +do + case $ac_config_target in + "db_config.h") CONFIG_HEADERS="$CONFIG_HEADERS db_config.h:config.hin" ;; + "libtool") CONFIG_COMMANDS="$CONFIG_COMMANDS libtool" ;; + "$CREATE_LIST") CONFIG_FILES="$CONFIG_FILES $CREATE_LIST" ;; + + *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;; + 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 + test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers + test "${CONFIG_COMMANDS+set}" = set || CONFIG_COMMANDS=$config_commands +fi + +# Have a temporary directory for convenience. Make it in the build tree +# simply because there is no reason against having it here, and in addition, +# creating and moving files from /tmp can sometimes cause problems. +# Hook for its removal unless debugging. +# Note that there is a small window in which the directory will not be cleaned: +# after its creation but before its name has been assigned to `$tmp'. +$debug || +{ + tmp= ac_tmp= + trap 'exit_status=$? + : "${ac_tmp:=$tmp}" + { test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status +' 0 + trap 'as_fn_exit 1' 1 2 13 15 +} +# Create a (secure) tmp directory for tmp files. + +{ + tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` && + test -d "$tmp" +} || +{ + tmp=./conf$$-$RANDOM + (umask 077 && mkdir "$tmp") +} || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5 +ac_tmp=$tmp + +# Set up the scripts for CONFIG_FILES section. +# No need to generate them if there are no CONFIG_FILES. +# This happens for instance with `./config.status config.h'. +if test -n "$CONFIG_FILES"; then + + +ac_cr=`echo X | tr X '\015'` +# On cygwin, bash can eat \r inside `` if the user requested igncr. +# But we know of no other shell where ac_cr would be empty at this +# point, so we can use a bashism as a fallback. +if test "x$ac_cr" = x; then + eval ac_cr=\$\'\\r\' +fi +ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' /dev/null` +if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then + ac_cs_awk_cr='\\r' +else + ac_cs_awk_cr=$ac_cr +fi + +echo 'BEGIN {' >"$ac_tmp/subs1.awk" && +_ACEOF + + +{ + echo "cat >conf$$subs.awk <<_ACEOF" && + echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' && + echo "_ACEOF" +} >conf$$subs.sh || + as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 +ac_delim_num=`echo "$ac_subst_vars" | grep -c '^'` +ac_delim='%!_!# ' +for ac_last_try in false false false false false :; do + . ./conf$$subs.sh || + as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 + + ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X` + if test $ac_delim_n = $ac_delim_num; then + break + elif $ac_last_try; then + as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 + else + ac_delim="$ac_delim!$ac_delim _$ac_delim!! " + fi +done +rm -f conf$$subs.sh + +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +cat >>"\$ac_tmp/subs1.awk" <<\\_ACAWK && +_ACEOF +sed -n ' +h +s/^/S["/; s/!.*/"]=/ +p +g +s/^[^!]*!// +:repl +t repl +s/'"$ac_delim"'$// +t delim +:nl +h +s/\(.\{148\}\)..*/\1/ +t more1 +s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/ +p +n +b repl +:more1 +s/["\\]/\\&/g; s/^/"/; s/$/"\\/ +p +g +s/.\{148\}// +t nl +:delim +h +s/\(.\{148\}\)..*/\1/ +t more2 +s/["\\]/\\&/g; s/^/"/; s/$/"/ +p +b +:more2 +s/["\\]/\\&/g; s/^/"/; s/$/"\\/ +p +g +s/.\{148\}// +t delim +' >$CONFIG_STATUS || ac_write_fail=1 +rm -f conf$$subs.awk +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +_ACAWK +cat >>"\$ac_tmp/subs1.awk" <<_ACAWK && + for (key in S) S_is_set[key] = 1 + FS = "" + +} +{ + line = $ 0 + nfields = split(line, field, "@") + substed = 0 + len = length(field[1]) + for (i = 2; i < nfields; i++) { + key = field[i] + keylen = length(key) + if (S_is_set[key]) { + value = S[key] + line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3) + len += length(value) + length(field[++i]) + substed = 1 + } else + len += 1 + keylen + } + + print line +} + +_ACAWK +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then + sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g" +else + cat +fi < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \ + || as_fn_error $? "could not setup config files machinery" "$LINENO" 5 +_ACEOF + +# VPATH may cause trouble with some makes, so we remove sole $(srcdir), +# ${srcdir} and @srcdir@ entries 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[ ]*=[ ]*/{ +h +s/// +s/^/:/ +s/[ ]*$/:/ +s/:\$(srcdir):/:/g +s/:\${srcdir}:/:/g +s/:@srcdir@:/:/g +s/^:*// +s/:*$// +x +s/\(=[ ]*\).*/\1/ +G +s/\n// +s/^[^=]*=[ ]*$// +}' +fi + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +fi # test -n "$CONFIG_FILES" + +# Set up the scripts for CONFIG_HEADERS section. +# No need to generate them if there are no CONFIG_HEADERS. +# This happens for instance with `./config.status Makefile'. +if test -n "$CONFIG_HEADERS"; then +cat >"$ac_tmp/defines.awk" <<\_ACAWK || +BEGIN { +_ACEOF + +# Transform confdefs.h into an awk script `defines.awk', embedded as +# here-document in config.status, that substitutes the proper values into +# config.h.in to produce config.h. + +# Create a delimiter string that does not exist in confdefs.h, to ease +# handling of long lines. +ac_delim='%!_!# ' +for ac_last_try in false false :; do + ac_tt=`sed -n "/$ac_delim/p" confdefs.h` + if test -z "$ac_tt"; then + break + elif $ac_last_try; then + as_fn_error $? "could not make $CONFIG_HEADERS" "$LINENO" 5 + else + ac_delim="$ac_delim!$ac_delim _$ac_delim!! " + fi +done + +# For the awk script, D is an array of macro values keyed by name, +# likewise P contains macro parameters if any. Preserve backslash +# newline sequences. + +ac_word_re=[_$as_cr_Letters][_$as_cr_alnum]* +sed -n ' +s/.\{148\}/&'"$ac_delim"'/g +t rset +:rset +s/^[ ]*#[ ]*define[ ][ ]*/ / +t def +d +:def +s/\\$// +t bsnl +s/["\\]/\\&/g +s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ +D["\1"]=" \3"/p +s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2"/p +d +:bsnl +s/["\\]/\\&/g +s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ +D["\1"]=" \3\\\\\\n"\\/p +t cont +s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2\\\\\\n"\\/p +t cont +d +:cont +n +s/.\{148\}/&'"$ac_delim"'/g +t clear +:clear +s/\\$// +t bsnlc +s/["\\]/\\&/g; s/^/"/; s/$/"/p +d +:bsnlc +s/["\\]/\\&/g; s/^/"/; s/$/\\\\\\n"\\/p +b cont +' >$CONFIG_STATUS || ac_write_fail=1 + +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 + for (key in D) D_is_set[key] = 1 + FS = "" +} +/^[\t ]*#[\t ]*(define|undef)[\t ]+$ac_word_re([\t (]|\$)/ { + line = \$ 0 + split(line, arg, " ") + if (arg[1] == "#") { + defundef = arg[2] + mac1 = arg[3] + } else { + defundef = substr(arg[1], 2) + mac1 = arg[2] + } + split(mac1, mac2, "(") #) + macro = mac2[1] + prefix = substr(line, 1, index(line, defundef) - 1) + if (D_is_set[macro]) { + # Preserve the white space surrounding the "#". + print prefix "define", macro P[macro] D[macro] + next + } else { + # Replace #undef with comments. This is necessary, for example, + # in the case of _POSIX_SOURCE, which is predefined and required + # on some systems where configure will not decide to define it. + if (defundef == "undef") { + print "/*", prefix defundef, macro, "*/" + next + } + } +} +{ print } +_ACAWK +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 + as_fn_error $? "could not setup config headers machinery" "$LINENO" 5 +fi # test -n "$CONFIG_HEADERS" + + +eval set X " :F $CONFIG_FILES :H $CONFIG_HEADERS :C $CONFIG_COMMANDS" +shift +for ac_tag +do + case $ac_tag in + :[FHLC]) ac_mode=$ac_tag; continue;; + esac + case $ac_mode$ac_tag in + :[FHL]*:*);; + :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5;; + :[FH]-) ac_tag=-:-;; + :[FH]*) ac_tag=$ac_tag:$ac_tag.in;; + esac + ac_save_IFS=$IFS + IFS=: + set x $ac_tag + IFS=$ac_save_IFS + shift + ac_file=$1 + shift + + case $ac_mode in + :L) ac_source=$1;; + :[FH]) + ac_file_inputs= + for ac_f + do + case $ac_f in + -) ac_f="$ac_tmp/stdin";; + *) # Look for the file first in the build tree, then in the source tree + # (if the path is not absolute). The absolute path cannot be DOS-style, + # because $ac_f cannot contain `:'. + test -f "$ac_f" || + case $ac_f in + [\\/$]*) false;; + *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";; + esac || + as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;; + esac + case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac + as_fn_append ac_file_inputs " '$ac_f'" + done + + # 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. */ + configure_input='Generated from '` + $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g' + `' by configure.' + if test x"$ac_file" != x-; then + configure_input="$ac_file. $configure_input" + { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5 +$as_echo "$as_me: creating $ac_file" >&6;} + fi + # Neutralize special characters interpreted by sed in replacement strings. + case $configure_input in #( + *\&* | *\|* | *\\* ) + ac_sed_conf_input=`$as_echo "$configure_input" | + sed 's/[\\\\&|]/\\\\&/g'`;; #( + *) ac_sed_conf_input=$configure_input;; + esac + + case $ac_tag in + *:-:* | *:-) cat >"$ac_tmp/stdin" \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; + esac + ;; + esac + + ac_dir=`$as_dirname -- "$ac_file" || +$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$ac_file" : 'X\(//\)[^/]' \| \ + X"$ac_file" : 'X\(//\)$' \| \ + X"$ac_file" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$ac_file" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + as_dir="$ac_dir"; as_fn_mkdir_p + ac_builddir=. + +case "$ac_dir" in +.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; +*) + ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` + # A ".." for each directory in $ac_dir_suffix. + ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` + case $ac_top_builddir_sub in + "") ac_top_builddir_sub=. ac_top_build_prefix= ;; + *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; + esac ;; +esac +ac_abs_top_builddir=$ac_pwd +ac_abs_builddir=$ac_pwd$ac_dir_suffix +# for backward compatibility: +ac_top_builddir=$ac_top_build_prefix + +case $srcdir in + .) # We are building in place. + ac_srcdir=. + ac_top_srcdir=$ac_top_builddir_sub + ac_abs_top_srcdir=$ac_pwd ;; + [\\/]* | ?:[\\/]* ) # Absolute name. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir + ac_abs_top_srcdir=$srcdir ;; + *) # Relative name. + ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_build_prefix$srcdir + ac_abs_top_srcdir=$ac_pwd/$srcdir ;; +esac +ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix + + + case $ac_mode in + :F) + # + # CONFIG_FILE + # + + case $INSTALL in + [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;; + *) ac_INSTALL=$ac_top_build_prefix$INSTALL ;; + esac +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +# If the template does not know about datarootdir, expand it. +# FIXME: This hack should be removed a few years after 2.60. +ac_datarootdir_hack=; ac_datarootdir_seen= +ac_sed_dataroot=' +/datarootdir/ { + p + q +} +/@datadir@/p +/@docdir@/p +/@infodir@/p +/@localedir@/p +/@mandir@/p' +case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in +*datarootdir*) ac_datarootdir_seen=yes;; +*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5 +$as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;} +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 + ac_datarootdir_hack=' + s&@datadir@&$datadir&g + s&@docdir@&$docdir&g + s&@infodir@&$infodir&g + s&@localedir@&$localedir&g + s&@mandir@&$mandir&g + s&\\\${datarootdir}&$datarootdir&g' ;; +esac +_ACEOF + +# Neutralize VPATH when `$srcdir' = `.'. +# Shell code in configure.ac might set extrasub. +# FIXME: do we really want to maintain this feature? +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +ac_sed_extra="$ac_vpsub +$extrasub +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +:t +/@[a-zA-Z_][a-zA-Z_0-9]*@/!b +s|@configure_input@|$ac_sed_conf_input|;t t +s&@top_builddir@&$ac_top_builddir_sub&;t t +s&@top_build_prefix@&$ac_top_build_prefix&;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&@abs_top_builddir@&$ac_abs_top_builddir&;t t +s&@INSTALL@&$ac_INSTALL&;t t +$ac_datarootdir_hack +" +eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \ + >$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + +test -z "$ac_datarootdir_hack$ac_datarootdir_seen" && + { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } && + { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' \ + "$ac_tmp/out"`; test -z "$ac_out"; } && + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir' +which seems to be undefined. Please make sure it is defined" >&5 +$as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir' +which seems to be undefined. Please make sure it is defined" >&2;} + + rm -f "$ac_tmp/stdin" + case $ac_file in + -) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";; + *) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";; + esac \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + ;; + :H) + # + # CONFIG_HEADER + # + if test x"$ac_file" != x-; then + { + $as_echo "/* $configure_input */" \ + && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" + } >"$ac_tmp/config.h" \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + if diff "$ac_file" "$ac_tmp/config.h" >/dev/null 2>&1; then + { $as_echo "$as_me:${as_lineno-$LINENO}: $ac_file is unchanged" >&5 +$as_echo "$as_me: $ac_file is unchanged" >&6;} + else + rm -f "$ac_file" + mv "$ac_tmp/config.h" "$ac_file" \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + fi + else + $as_echo "/* $configure_input */" \ + && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" \ + || as_fn_error $? "could not create -" "$LINENO" 5 + fi + ;; + + :C) { $as_echo "$as_me:${as_lineno-$LINENO}: executing $ac_file commands" >&5 +$as_echo "$as_me: executing $ac_file commands" >&6;} + ;; + esac + + + case $ac_file$ac_mode in + "libtool":C) + + # See if we are running on zsh, and set the options which allow our + # commands through without removal of \ escapes. + if test -n "${ZSH_VERSION+set}" ; then + setopt NO_GLOB_SUBST + fi + + cfgfile="${ofile}T" + trap "$RM \"$cfgfile\"; exit 1" 1 2 15 + $RM "$cfgfile" + + cat <<_LT_EOF >> "$cfgfile" +#! $SHELL + +# `$ECHO "$ofile" | sed 's%^.*/%%'` - Provide generalized library-building support services. +# Generated automatically by $as_me ($PACKAGE$TIMESTAMP) $VERSION +# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`: +# NOTE: Changes made to this file will be lost: look at ltmain.sh. +# +# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, +# 2006, 2007, 2008, 2009, 2010 Free Software Foundation, +# Inc. +# Written by Gordon Matzigkeit, 1996 +# +# This file is part of GNU Libtool. +# +# GNU Libtool is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation; either version 2 of +# the License, or (at your option) any later version. +# +# As a special exception to the GNU General Public License, +# if you distribute this file as part of a program or library that +# is built using GNU Libtool, you may include this file under the +# same distribution terms that you use for the rest of that program. +# +# GNU Libtool 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 General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Libtool; see the file COPYING. If not, a copy +# can be downloaded from http://www.gnu.org/licenses/gpl.html, or +# obtained by writing to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + +# The names of the tagged configurations supported by this script. +available_tags="CXX " + +# ### BEGIN LIBTOOL CONFIG + +# Which release of libtool.m4 was used? +macro_version=$macro_version +macro_revision=$macro_revision + +# Whether or not to build shared libraries. +build_libtool_libs=$enable_shared + +# Whether or not to build static libraries. +build_old_libs=$enable_static + +# What type of objects to build. +pic_mode=$pic_mode + +# Whether or not to optimize for fast installation. +fast_install=$enable_fast_install + +# Shell to use when invoking shell scripts. +SHELL=$lt_SHELL + +# An echo program that protects backslashes. +ECHO=$lt_ECHO + +# The host system. +host_alias=$host_alias +host=$host +host_os=$host_os + +# The build system. +build_alias=$build_alias +build=$build +build_os=$build_os + +# A sed program that does not truncate output. +SED=$lt_SED + +# Sed that helps us avoid accidentally triggering echo(1) options like -n. +Xsed="\$SED -e 1s/^X//" + +# A grep program that handles long lines. +GREP=$lt_GREP + +# An ERE matcher. +EGREP=$lt_EGREP + +# A literal string matcher. +FGREP=$lt_FGREP + +# A BSD- or MS-compatible name lister. +NM=$lt_NM + +# Whether we need soft or hard links. +LN_S=$lt_LN_S + +# What is the maximum length of a command? +max_cmd_len=$max_cmd_len + +# Object file suffix (normally "o"). +objext=$ac_objext + +# Executable file suffix (normally ""). +exeext=$exeext + +# whether the shell understands "unset". +lt_unset=$lt_unset + +# turn spaces into newlines. +SP2NL=$lt_lt_SP2NL + +# turn newlines into spaces. +NL2SP=$lt_lt_NL2SP + +# convert \$build file names to \$host format. +to_host_file_cmd=$lt_cv_to_host_file_cmd + +# convert \$build files to toolchain format. +to_tool_file_cmd=$lt_cv_to_tool_file_cmd + +# An object symbol dumper. +OBJDUMP=$lt_OBJDUMP + +# Method to check whether dependent libraries are shared objects. +deplibs_check_method=$lt_deplibs_check_method + +# Command to use when deplibs_check_method = "file_magic". +file_magic_cmd=$lt_file_magic_cmd + +# How to find potential files when deplibs_check_method = "file_magic". +file_magic_glob=$lt_file_magic_glob + +# Find potential files using nocaseglob when deplibs_check_method = "file_magic". +want_nocaseglob=$lt_want_nocaseglob + +# DLL creation program. +DLLTOOL=$lt_DLLTOOL + +# Command to associate shared and link libraries. +sharedlib_from_linklib_cmd=$lt_sharedlib_from_linklib_cmd + +# The archiver. +AR=$lt_AR + +# Flags to create an archive. +AR_FLAGS=$lt_AR_FLAGS + +# How to feed a file listing to the archiver. +archiver_list_spec=$lt_archiver_list_spec + +# A symbol stripping program. +STRIP=$lt_STRIP + +# Commands used to install an old-style archive. +RANLIB=$lt_RANLIB +old_postinstall_cmds=$lt_old_postinstall_cmds +old_postuninstall_cmds=$lt_old_postuninstall_cmds + +# Whether to use a lock for old archive extraction. +lock_old_archive_extraction=$lock_old_archive_extraction + +# A C compiler. +LTCC=$lt_CC + +# LTCC compiler flags. +LTCFLAGS=$lt_CFLAGS + +# Take the output of nm and produce a listing of raw symbols and C names. +global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe + +# Transform the output of nm in a proper C declaration. +global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl + +# Transform the output of nm in a C name address pair. +global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address + +# Transform the output of nm in a C name address pair when lib prefix is needed. +global_symbol_to_c_name_address_lib_prefix=$lt_lt_cv_sys_global_symbol_to_c_name_address_lib_prefix + +# Specify filename containing input files for \$NM. +nm_file_list_spec=$lt_nm_file_list_spec + +# The root where to search for dependent libraries,and in which our libraries should be installed. +lt_sysroot=$lt_sysroot + +# The name of the directory that contains temporary libtool files. +objdir=$objdir + +# Used to examine libraries when file_magic_cmd begins with "file". +MAGIC_CMD=$MAGIC_CMD + +# Must we lock files when doing compilation? +need_locks=$lt_need_locks + +# Manifest tool. +MANIFEST_TOOL=$lt_MANIFEST_TOOL + +# Tool to manipulate archived DWARF debug symbol files on Mac OS X. +DSYMUTIL=$lt_DSYMUTIL + +# Tool to change global to local symbols on Mac OS X. +NMEDIT=$lt_NMEDIT + +# Tool to manipulate fat objects and archives on Mac OS X. +LIPO=$lt_LIPO + +# ldd/readelf like tool for Mach-O binaries on Mac OS X. +OTOOL=$lt_OTOOL + +# ldd/readelf like tool for 64 bit Mach-O binaries on Mac OS X 10.4. +OTOOL64=$lt_OTOOL64 + +# Old archive suffix (normally "a"). +libext=$libext + +# Shared library suffix (normally ".so"). +shrext_cmds=$lt_shrext_cmds + +# The commands to extract the exported symbol list from a shared archive. +extract_expsyms_cmds=$lt_extract_expsyms_cmds + +# Variables whose values should be saved in libtool wrapper scripts and +# restored at link time. +variables_saved_for_relink=$lt_variables_saved_for_relink + +# Do we need the "lib" prefix for modules? +need_lib_prefix=$need_lib_prefix + +# Do we need a version for libraries? +need_version=$need_version + +# Library versioning type. +version_type=$version_type + +# Shared library runtime path variable. +runpath_var=$runpath_var + +# Shared library path variable. +shlibpath_var=$shlibpath_var + +# Is shlibpath searched before the hard-coded library search path? +shlibpath_overrides_runpath=$shlibpath_overrides_runpath + +# Format of library name prefix. +libname_spec=$lt_libname_spec + +# List of archive names. First name is the real one, the rest are links. +# The last name is the one that the linker finds with -lNAME +library_names_spec=$lt_library_names_spec + +# The coded name of the library, if different from the real name. +soname_spec=$lt_soname_spec + +# Permission mode override for installation of shared libraries. +install_override_mode=$lt_install_override_mode + +# Command to use after installation of a shared archive. +postinstall_cmds=$lt_postinstall_cmds + +# Command to use after uninstallation of a shared archive. +postuninstall_cmds=$lt_postuninstall_cmds + +# Commands used to finish a libtool library installation in a directory. +finish_cmds=$lt_finish_cmds + +# As "finish_cmds", except a single script fragment to be evaled but +# not shown. +finish_eval=$lt_finish_eval + +# Whether we should hardcode library paths into libraries. +hardcode_into_libs=$hardcode_into_libs + +# Compile-time system search path for libraries. +sys_lib_search_path_spec=$lt_sys_lib_search_path_spec + +# Run-time system search path for libraries. +sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec + +# Whether dlopen is supported. +dlopen_support=$enable_dlopen + +# Whether dlopen of programs is supported. +dlopen_self=$enable_dlopen_self + +# Whether dlopen of statically linked programs is supported. +dlopen_self_static=$enable_dlopen_self_static + +# Commands to strip libraries. +old_striplib=$lt_old_striplib +striplib=$lt_striplib + + +# The linker used to build libraries. +LD=$lt_LD + +# How to create reloadable object files. +reload_flag=$lt_reload_flag +reload_cmds=$lt_reload_cmds + +# Commands used to build an old-style archive. +old_archive_cmds=$lt_old_archive_cmds + +# A language specific compiler. +CC=$lt_compiler + +# Is the compiler the GNU compiler? +with_gcc=$GCC + +# Compiler flag to turn off builtin functions. +no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag + +# Additional compiler flags for building library objects. +pic_flag=$lt_lt_prog_compiler_pic + +# How to pass a linker flag through the compiler. +wl=$lt_lt_prog_compiler_wl + +# Compiler flag to prevent dynamic linking. +link_static_flag=$lt_lt_prog_compiler_static + +# Does compiler simultaneously support -c and -o options? +compiler_c_o=$lt_lt_cv_prog_compiler_c_o + +# Whether or not to add -lc for building shared libraries. +build_libtool_need_lc=$archive_cmds_need_lc + +# Whether or not to disallow shared libs when runtime libs are static. +allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes + +# Compiler flag to allow reflexive dlopens. +export_dynamic_flag_spec=$lt_export_dynamic_flag_spec + +# Compiler flag to generate shared objects directly from archives. +whole_archive_flag_spec=$lt_whole_archive_flag_spec + +# Whether the compiler copes with passing no objects directly. +compiler_needs_object=$lt_compiler_needs_object + +# Create an old-style archive from a shared archive. +old_archive_from_new_cmds=$lt_old_archive_from_new_cmds + +# Create a temporary old-style archive to link instead of a shared archive. +old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds + +# Commands used to build a shared archive. +archive_cmds=$lt_archive_cmds +archive_expsym_cmds=$lt_archive_expsym_cmds + +# Commands used to build a loadable module if different from building +# a shared archive. +module_cmds=$lt_module_cmds +module_expsym_cmds=$lt_module_expsym_cmds + +# Whether we are building with GNU ld or not. +with_gnu_ld=$lt_with_gnu_ld + +# Flag that allows shared libraries with undefined symbols to be built. +allow_undefined_flag=$lt_allow_undefined_flag + +# Flag that enforces no undefined symbols. +no_undefined_flag=$lt_no_undefined_flag + +# Flag to hardcode \$libdir into a binary during linking. +# This must work even if \$libdir does not exist +hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec + +# If ld is used when linking, flag to hardcode \$libdir into a binary +# during linking. This must work even if \$libdir does not exist. +hardcode_libdir_flag_spec_ld=$lt_hardcode_libdir_flag_spec_ld + +# Whether we need a single "-rpath" flag with a separated argument. +hardcode_libdir_separator=$lt_hardcode_libdir_separator + +# Set to "yes" if using DIR/libNAME\${shared_ext} during linking hardcodes +# DIR into the resulting binary. +hardcode_direct=$hardcode_direct + +# Set to "yes" if using DIR/libNAME\${shared_ext} during linking hardcodes +# DIR into the resulting binary and the resulting library dependency is +# "absolute",i.e impossible to change by setting \${shlibpath_var} if the +# library is relocated. +hardcode_direct_absolute=$hardcode_direct_absolute + +# Set to "yes" if using the -LDIR flag during linking hardcodes DIR +# into the resulting binary. +hardcode_minus_L=$hardcode_minus_L + +# Set to "yes" if using SHLIBPATH_VAR=DIR during linking hardcodes DIR +# into the resulting binary. +hardcode_shlibpath_var=$hardcode_shlibpath_var + +# Set to "yes" if building a shared library automatically hardcodes DIR +# into the library and all subsequent libraries and executables linked +# against it. +hardcode_automatic=$hardcode_automatic + +# Set to yes if linker adds runtime paths of dependent libraries +# to runtime path list. +inherit_rpath=$inherit_rpath + +# Whether libtool must link a program against all its dependency libraries. +link_all_deplibs=$link_all_deplibs + +# Set to "yes" if exported symbols are required. +always_export_symbols=$always_export_symbols + +# The commands to list exported symbols. +export_symbols_cmds=$lt_export_symbols_cmds + +# Symbols that should not be listed in the preloaded symbols. +exclude_expsyms=$lt_exclude_expsyms + +# Symbols that must always be exported. +include_expsyms=$lt_include_expsyms + +# Commands necessary for linking programs (against libraries) with templates. +prelink_cmds=$lt_prelink_cmds + +# Commands necessary for finishing linking programs. +postlink_cmds=$lt_postlink_cmds + +# Specify filename containing input files. +file_list_spec=$lt_file_list_spec + +# How to hardcode a shared library path into an executable. +hardcode_action=$hardcode_action + +# The directories searched by this compiler when creating a shared library. +compiler_lib_search_dirs=$lt_compiler_lib_search_dirs + +# Dependencies to place before and after the objects being linked to +# create a shared library. +predep_objects=$lt_predep_objects +postdep_objects=$lt_postdep_objects +predeps=$lt_predeps +postdeps=$lt_postdeps + +# The library search path used internally by the compiler when linking +# a shared library. +compiler_lib_search_path=$lt_compiler_lib_search_path + +# ### END LIBTOOL CONFIG + +_LT_EOF + + case $host_os in + aix3*) + cat <<\_LT_EOF >> "$cfgfile" +# AIX sometimes has problems with the GCC collect2 program. For some +# reason, if we set the COLLECT_NAMES environment variable, the problems +# vanish in a puff of smoke. +if test "X${COLLECT_NAMES+set}" != Xset; then + COLLECT_NAMES= + export COLLECT_NAMES +fi +_LT_EOF + ;; + esac + + +ltmain="$ac_aux_dir/ltmain.sh" + + + # We use sed instead of cat because bash on DJGPP gets confused if + # if finds mixed CR/LF and LF-only lines. Since sed operates in + # text mode, it properly converts lines to CR/LF. This bash problem + # is reportedly fixed, but why not run on old versions too? + sed '$q' "$ltmain" >> "$cfgfile" \ + || (rm -f "$cfgfile"; exit 1) + + if test x"$xsi_shell" = xyes; then + sed -e '/^func_dirname ()$/,/^} # func_dirname /c\ +func_dirname ()\ +{\ +\ case ${1} in\ +\ */*) func_dirname_result="${1%/*}${2}" ;;\ +\ * ) func_dirname_result="${3}" ;;\ +\ esac\ +} # Extended-shell func_dirname implementation' "$cfgfile" > $cfgfile.tmp \ + && mv -f "$cfgfile.tmp" "$cfgfile" \ + || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") +test 0 -eq $? || _lt_function_replace_fail=: + + + sed -e '/^func_basename ()$/,/^} # func_basename /c\ +func_basename ()\ +{\ +\ func_basename_result="${1##*/}"\ +} # Extended-shell func_basename implementation' "$cfgfile" > $cfgfile.tmp \ + && mv -f "$cfgfile.tmp" "$cfgfile" \ + || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") +test 0 -eq $? || _lt_function_replace_fail=: + + + sed -e '/^func_dirname_and_basename ()$/,/^} # func_dirname_and_basename /c\ +func_dirname_and_basename ()\ +{\ +\ case ${1} in\ +\ */*) func_dirname_result="${1%/*}${2}" ;;\ +\ * ) func_dirname_result="${3}" ;;\ +\ esac\ +\ func_basename_result="${1##*/}"\ +} # Extended-shell func_dirname_and_basename implementation' "$cfgfile" > $cfgfile.tmp \ + && mv -f "$cfgfile.tmp" "$cfgfile" \ + || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") +test 0 -eq $? || _lt_function_replace_fail=: + + + sed -e '/^func_stripname ()$/,/^} # func_stripname /c\ +func_stripname ()\ +{\ +\ # pdksh 5.2.14 does not do ${X%$Y} correctly if both X and Y are\ +\ # positional parameters, so assign one to ordinary parameter first.\ +\ func_stripname_result=${3}\ +\ func_stripname_result=${func_stripname_result#"${1}"}\ +\ func_stripname_result=${func_stripname_result%"${2}"}\ +} # Extended-shell func_stripname implementation' "$cfgfile" > $cfgfile.tmp \ + && mv -f "$cfgfile.tmp" "$cfgfile" \ + || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") +test 0 -eq $? || _lt_function_replace_fail=: + + + sed -e '/^func_split_long_opt ()$/,/^} # func_split_long_opt /c\ +func_split_long_opt ()\ +{\ +\ func_split_long_opt_name=${1%%=*}\ +\ func_split_long_opt_arg=${1#*=}\ +} # Extended-shell func_split_long_opt implementation' "$cfgfile" > $cfgfile.tmp \ + && mv -f "$cfgfile.tmp" "$cfgfile" \ + || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") +test 0 -eq $? || _lt_function_replace_fail=: + + + sed -e '/^func_split_short_opt ()$/,/^} # func_split_short_opt /c\ +func_split_short_opt ()\ +{\ +\ func_split_short_opt_arg=${1#??}\ +\ func_split_short_opt_name=${1%"$func_split_short_opt_arg"}\ +} # Extended-shell func_split_short_opt implementation' "$cfgfile" > $cfgfile.tmp \ + && mv -f "$cfgfile.tmp" "$cfgfile" \ + || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") +test 0 -eq $? || _lt_function_replace_fail=: + + + sed -e '/^func_lo2o ()$/,/^} # func_lo2o /c\ +func_lo2o ()\ +{\ +\ case ${1} in\ +\ *.lo) func_lo2o_result=${1%.lo}.${objext} ;;\ +\ *) func_lo2o_result=${1} ;;\ +\ esac\ +} # Extended-shell func_lo2o implementation' "$cfgfile" > $cfgfile.tmp \ + && mv -f "$cfgfile.tmp" "$cfgfile" \ + || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") +test 0 -eq $? || _lt_function_replace_fail=: + + + sed -e '/^func_xform ()$/,/^} # func_xform /c\ +func_xform ()\ +{\ + func_xform_result=${1%.*}.lo\ +} # Extended-shell func_xform implementation' "$cfgfile" > $cfgfile.tmp \ + && mv -f "$cfgfile.tmp" "$cfgfile" \ + || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") +test 0 -eq $? || _lt_function_replace_fail=: + + + sed -e '/^func_arith ()$/,/^} # func_arith /c\ +func_arith ()\ +{\ + func_arith_result=$(( $* ))\ +} # Extended-shell func_arith implementation' "$cfgfile" > $cfgfile.tmp \ + && mv -f "$cfgfile.tmp" "$cfgfile" \ + || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") +test 0 -eq $? || _lt_function_replace_fail=: + + + sed -e '/^func_len ()$/,/^} # func_len /c\ +func_len ()\ +{\ + func_len_result=${#1}\ +} # Extended-shell func_len implementation' "$cfgfile" > $cfgfile.tmp \ + && mv -f "$cfgfile.tmp" "$cfgfile" \ + || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") +test 0 -eq $? || _lt_function_replace_fail=: + +fi + +if test x"$lt_shell_append" = xyes; then + sed -e '/^func_append ()$/,/^} # func_append /c\ +func_append ()\ +{\ + eval "${1}+=\\${2}"\ +} # Extended-shell func_append implementation' "$cfgfile" > $cfgfile.tmp \ + && mv -f "$cfgfile.tmp" "$cfgfile" \ + || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") +test 0 -eq $? || _lt_function_replace_fail=: + + + sed -e '/^func_append_quoted ()$/,/^} # func_append_quoted /c\ +func_append_quoted ()\ +{\ +\ func_quote_for_eval "${2}"\ +\ eval "${1}+=\\\\ \\$func_quote_for_eval_result"\ +} # Extended-shell func_append_quoted implementation' "$cfgfile" > $cfgfile.tmp \ + && mv -f "$cfgfile.tmp" "$cfgfile" \ + || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") +test 0 -eq $? || _lt_function_replace_fail=: + + + # Save a `func_append' function call where possible by direct use of '+=' + sed -e 's%func_append \([a-zA-Z_]\{1,\}\) "%\1+="%g' $cfgfile > $cfgfile.tmp \ + && mv -f "$cfgfile.tmp" "$cfgfile" \ + || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") + test 0 -eq $? || _lt_function_replace_fail=: +else + # Save a `func_append' function call even when '+=' is not available + sed -e 's%func_append \([a-zA-Z_]\{1,\}\) "%\1="$\1%g' $cfgfile > $cfgfile.tmp \ + && mv -f "$cfgfile.tmp" "$cfgfile" \ + || (rm -f "$cfgfile" && cp "$cfgfile.tmp" "$cfgfile" && rm -f "$cfgfile.tmp") + test 0 -eq $? || _lt_function_replace_fail=: +fi + +if test x"$_lt_function_replace_fail" = x":"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Unable to substitute extended shell functions in $ofile" >&5 +$as_echo "$as_me: WARNING: Unable to substitute extended shell functions in $ofile" >&2;} +fi + + + mv -f "$cfgfile" "$ofile" || + (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile") + chmod +x "$ofile" + + + cat <<_LT_EOF >> "$ofile" + +# ### BEGIN LIBTOOL TAG CONFIG: CXX + +# The linker used to build libraries. +LD=$lt_LD_CXX + +# How to create reloadable object files. +reload_flag=$lt_reload_flag_CXX +reload_cmds=$lt_reload_cmds_CXX + +# Commands used to build an old-style archive. +old_archive_cmds=$lt_old_archive_cmds_CXX + +# A language specific compiler. +CC=$lt_compiler_CXX + +# Is the compiler the GNU compiler? +with_gcc=$GCC_CXX + +# Compiler flag to turn off builtin functions. +no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag_CXX + +# Additional compiler flags for building library objects. +pic_flag=$lt_lt_prog_compiler_pic_CXX + +# How to pass a linker flag through the compiler. +wl=$lt_lt_prog_compiler_wl_CXX + +# Compiler flag to prevent dynamic linking. +link_static_flag=$lt_lt_prog_compiler_static_CXX + +# Does compiler simultaneously support -c and -o options? +compiler_c_o=$lt_lt_cv_prog_compiler_c_o_CXX + +# Whether or not to add -lc for building shared libraries. +build_libtool_need_lc=$archive_cmds_need_lc_CXX + +# Whether or not to disallow shared libs when runtime libs are static. +allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes_CXX + +# Compiler flag to allow reflexive dlopens. +export_dynamic_flag_spec=$lt_export_dynamic_flag_spec_CXX + +# Compiler flag to generate shared objects directly from archives. +whole_archive_flag_spec=$lt_whole_archive_flag_spec_CXX + +# Whether the compiler copes with passing no objects directly. +compiler_needs_object=$lt_compiler_needs_object_CXX + +# Create an old-style archive from a shared archive. +old_archive_from_new_cmds=$lt_old_archive_from_new_cmds_CXX + +# Create a temporary old-style archive to link instead of a shared archive. +old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds_CXX + +# Commands used to build a shared archive. +archive_cmds=$lt_archive_cmds_CXX +archive_expsym_cmds=$lt_archive_expsym_cmds_CXX + +# Commands used to build a loadable module if different from building +# a shared archive. +module_cmds=$lt_module_cmds_CXX +module_expsym_cmds=$lt_module_expsym_cmds_CXX + +# Whether we are building with GNU ld or not. +with_gnu_ld=$lt_with_gnu_ld_CXX + +# Flag that allows shared libraries with undefined symbols to be built. +allow_undefined_flag=$lt_allow_undefined_flag_CXX + +# Flag that enforces no undefined symbols. +no_undefined_flag=$lt_no_undefined_flag_CXX + +# Flag to hardcode \$libdir into a binary during linking. +# This must work even if \$libdir does not exist +hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec_CXX + +# If ld is used when linking, flag to hardcode \$libdir into a binary +# during linking. This must work even if \$libdir does not exist. +hardcode_libdir_flag_spec_ld=$lt_hardcode_libdir_flag_spec_ld_CXX + +# Whether we need a single "-rpath" flag with a separated argument. +hardcode_libdir_separator=$lt_hardcode_libdir_separator_CXX + +# Set to "yes" if using DIR/libNAME\${shared_ext} during linking hardcodes +# DIR into the resulting binary. +hardcode_direct=$hardcode_direct_CXX + +# Set to "yes" if using DIR/libNAME\${shared_ext} during linking hardcodes +# DIR into the resulting binary and the resulting library dependency is +# "absolute",i.e impossible to change by setting \${shlibpath_var} if the +# library is relocated. +hardcode_direct_absolute=$hardcode_direct_absolute_CXX + +# Set to "yes" if using the -LDIR flag during linking hardcodes DIR +# into the resulting binary. +hardcode_minus_L=$hardcode_minus_L_CXX + +# Set to "yes" if using SHLIBPATH_VAR=DIR during linking hardcodes DIR +# into the resulting binary. +hardcode_shlibpath_var=$hardcode_shlibpath_var_CXX + +# Set to "yes" if building a shared library automatically hardcodes DIR +# into the library and all subsequent libraries and executables linked +# against it. +hardcode_automatic=$hardcode_automatic_CXX + +# Set to yes if linker adds runtime paths of dependent libraries +# to runtime path list. +inherit_rpath=$inherit_rpath_CXX + +# Whether libtool must link a program against all its dependency libraries. +link_all_deplibs=$link_all_deplibs_CXX + +# Set to "yes" if exported symbols are required. +always_export_symbols=$always_export_symbols_CXX + +# The commands to list exported symbols. +export_symbols_cmds=$lt_export_symbols_cmds_CXX + +# Symbols that should not be listed in the preloaded symbols. +exclude_expsyms=$lt_exclude_expsyms_CXX + +# Symbols that must always be exported. +include_expsyms=$lt_include_expsyms_CXX + +# Commands necessary for linking programs (against libraries) with templates. +prelink_cmds=$lt_prelink_cmds_CXX + +# Commands necessary for finishing linking programs. +postlink_cmds=$lt_postlink_cmds_CXX + +# Specify filename containing input files. +file_list_spec=$lt_file_list_spec_CXX + +# How to hardcode a shared library path into an executable. +hardcode_action=$hardcode_action_CXX + +# The directories searched by this compiler when creating a shared library. +compiler_lib_search_dirs=$lt_compiler_lib_search_dirs_CXX + +# Dependencies to place before and after the objects being linked to +# create a shared library. +predep_objects=$lt_predep_objects_CXX +postdep_objects=$lt_postdep_objects_CXX +predeps=$lt_predeps_CXX +postdeps=$lt_postdeps_CXX + +# The library search path used internally by the compiler when linking +# a shared library. +compiler_lib_search_path=$lt_compiler_lib_search_path_CXX + +# ### END LIBTOOL TAG CONFIG: CXX +_LT_EOF + + ;; + + esac +done # for ac_tag + + +as_fn_exit 0 +_ACEOF +ac_clean_files=$ac_clean_files_save + +test $ac_write_fail = 0 || + as_fn_error $? "write failure creating $CONFIG_STATUS" "$LINENO" 5 + + +# 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 || as_fn_exit 1 +fi +if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5 +$as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;} +fi + + +if test "$db_cv_rdsbuild" = "yes" -a "$db_rdsbuild_default" = "no" ; then + # Patch the resulting db.h to remove unsupported functions. + patch "db.h" "$topdir/dist/rds/patches/src/dbinc/db.in.patch" || exit 1 + patch "db_int.h" "$topdir/dist/rds/patches/src/dbinc/db_int.in.patch" || exit 1 +fi + +if test "$db_cv_sql" = "yes"; then + # This command runs the configure script from the SQL tree. + { $as_echo "$as_me:${as_lineno-$LINENO}: Configuring the SQL API" >&5 +$as_echo "$as_me: Configuring the SQL API" >&6;} + +# Setup the SQLite debug build. +mkdir -p sql +if test "$with_tclconfig" != "no"; then + db_cv_sql_config_tclconfig="--with-tcl=$with_tclconfig" +else + db_cv_sql_config_tclconfig= +fi + +# Whitespace in path names causes libtool to generate an invalid +# dependency_libs line in sql/libsqlite3.la. +# Work around this on cygwin, which commonly has spaces in path names. +case `pwd` in + *\ * | *\ *) + if cygpath -d "$PWD" > /dev/null 2>&1 ; then + cd `cygpath -d "$PWD"` + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Changing current directory to $PWD to hide whitespace from libtool" >&5 +$as_echo "$as_me: WARNING: Changing current directory to $PWD to hide whitespace from libtool" >&2;} + else + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Current bugs in libtool may prevent building the SQL API in \"$PWD\"; please use another working directory" >&5 +$as_echo "$as_me: WARNING: Current bugs in libtool may prevent building the SQL API in \"$PWD\"; please use another working directory" >&2;} + fi + ;; +esac + +# It would be nice to use AC_CONFIG_SUBDIRS here, but it does not allow for +# tweaking of command line options, so hard code things instead. +# +# !!! BEGIN COPIED from autoconf distribution +# Modified to not repeat CPPFLAGS or readline settings + + # Remove --cache-file, --srcdir, and --disable-option-checking arguments + # so they do not pile up. + ac_sub_configure_args= + ac_prev= + eval "set x $ac_configure_args" + shift + for ac_arg + do + if test -n "$ac_prev"; then + ac_prev= + continue + fi + case $ac_arg in + -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=*) + ;; + --config-cache | -C) + ;; + -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) + ac_prev=srcdir ;; + -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) + ;; + -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) + ac_prev=prefix ;; + -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) + ;; + --disable-option-checking) + ;; + CPPFLAGS=* | *readline*) + ;; + *) + case $ac_arg in + *\'*) ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; + esac + ac_sub_configure_args="$ac_sub_configure_args '$ac_arg'" ;; + esac + done + + # Always prepend --prefix to ensure using the same prefix + # in subdir configurations. + ac_arg="--prefix=$prefix" + case $ac_arg in + *\'*) ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; + esac + ac_sub_configure_args="'$ac_arg' $ac_sub_configure_args" + + # Pass --silent + if test "$silent" = yes; then + ac_sub_configure_args="--silent $ac_sub_configure_args" + fi + + # Always prepend --disable-option-checking to silence warnings, since + # different subdirs can have different --enable and --with options. + ac_sub_configure_args="--disable-option-checking $ac_sub_configure_args" + +# !!! END COPIED from autoconf distribution + +sqlite_dir=$srcdir/../lang/sql/sqlite +(cd sql && eval "\$SHELL ../$sqlite_dir/configure --disable-option-checking $ac_sub_configure_args CPPFLAGS=\"-I.. $CPPFLAGS\" --enable-amalgamation=$db_cv_sql_amalgamation --enable-readline=$with_readline" && cat build_config.h >> config.h) || exit 1 + +# Configure JDBC if --enable-jdbc +if test "$db_cv_jdbc" != "no"; then + + # Deal with user-defined jdbc source path + if test "$with_jdbc" != "no"; then + jdbc_path="$with_jdbc" + else + jdbc_path="$srcdir/../lang/sql/jdbc" + fi + + if test ! -d $jdbc_path; then + echo "Cannot find jdbc source in $jdbc_path." + echo "Please check that path or use --with-jdbc to specify the source directory" + exit 1 + fi + jdbc_dir=`cd $jdbc_path && /bin/pwd` + + # Transfer following setting to jdbc configure: + # . --prefix + # . --enable-shared/--disable-shared + # . --enable-static/--disable-static + # . CFLAGS, CPPFLAGS and LDFLAGS + jdbc_args="" + jdbc_flags="" + + test "$prefix" != "" && jdbc_args="--prefix=$prefix --with-jardir=$prefix/jar" + test "$enable_shared" != "" && jdbc_args="$jdbc_args --enable-shared=$enable_shared" + test "$enable_static" != "" && jdbc_args="$jdbc_args --enable-static=$enable_static" + + # 1. The build directory is build_unix/jdbc, so the include paths are relative + # to that. + # 2. The JDBC driver does not accept CPPFLAGS. So we move the CPPFLAGS options + # into CFLAGS for the JDBC driver. + jdbc_flags="$jdbc_flags CFLAGS=\"-I.. -I../../src/dbinc -I../sql \ + -DHAVE_ERRNO_H -D_HAVE_SQLITE_CONFIG_H -DHAVE_SQLITE3_MALLOC \ + $CFLAGS $CPPFLAGS\"" + # Set LDFLAGS for JDBC driver + test "$LDFLAGS" != "" && jdbc_flags="$jdbc_flags LDFLAGS=\"$LDFLAGS\"" + + # Copy ../lang/sql/jdbc to build_unix/ + test ! -d jdbc && cp -r $jdbc_dir . + + # Set DBSQL LIB for Makefile.in + BDB_LIB="..\/libdb-$DB_VERSION_MAJOR.$DB_VERSION_MINOR.la" + test $enable_shared != "yes" && BDB_LIB='..\/libdb.a' + + # Run the jdbc/configure + cd jdbc + test ! -e Makefile.in.tmp && mv Makefile.in Makefile.in.tmp + sed "s/@BDB_LIB@/$BDB_LIB/g" Makefile.in.tmp > Makefile.in + eval "\$SHELL ./configure --with-sqlite3=../../lang/sql/generated $jdbc_args $jdbc_flags" +fi + +fi diff -r 000000000000 -r a1985f14b030 dist/configure.ac --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dist/configure.ac Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,1210 @@ +# $Id$ +# Process this file with autoconf to produce a configure script. +# +# Copyright (c) 1996, 2012 Oracle and/or its affiliates. All rights reserved. +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. Oracle designates this +# particular file as subject to the "Classpath" exception as provided +# by Oracle in the LICENSE file that accompanied this code. +# +# This code 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 General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. + +PACKAGE=db +AC_INIT(Berkeley DB, __EDIT_DB_VERSION__, + [Oracle Technology Network Berkeley DB forum], + db-__EDIT_DB_VERSION__) +AC_CONFIG_SRCDIR([../src/db/db.c]) +AC_CONFIG_HEADERS([db_config.h:config.hin]) + +AC_CONFIG_MACRO_DIR([aclocal]) + +# We're going to pass options through to SQLite, don't check them first. +AC_DISABLE_OPTION_CHECKING() + +# Configure setup. +AC_CANONICAL_HOST() +AC_ARG_PROGRAM() + +# Don't build in the dist directory. +AC_MSG_CHECKING(if building in the top-level or dist directories) +if [ test -f configure.ac ] ; then + AC_MSG_RESULT(yes) + AC_MSG_ERROR([\ +Berkeley DB should not be built in the "dist" directory. \ +Change directory to the build_unix directory and run ../dist/configure \ +from there.]) +fi +AC_MSG_RESULT(no) + +topdir=`echo "$srcdir/.." | sed 's,/dist/\.\.,,'` +# Substitution variables. BDB additions need to be documented. +AC_SUBST(ADDITIONAL_INCS) +AC_SUBST(ADDITIONAL_LANG) +AC_SUBST(ADDITIONAL_OBJS) +AC_SUBST(ADDITIONAL_PROGS) +AC_SUBST(BUILD_TARGET) +AC_SUBST(CFLAGS) +AC_SUBST(CONFIGURATION_ARGS) +AC_SUBST(CONFIGURATION_PATH) +AC_SUBST(CPPFLAGS) +AC_SUBST(CRYPTO_OBJS) +AC_SUBST(CXX) +AC_SUBST(CXXFLAGS) +AC_SUBST(DB_CONST) +AC_SUBST(DB_PROTO1) +AC_SUBST(DB_PROTO2) +AC_SUBST(DB_STRUCT_ALIGN8) +AC_SUBST(DEFAULT_LIB) +AC_SUBST(DEFAULT_LIB_CXX) +AC_SUBST(DEFAULT_LIB_SQL) +AC_SUBST(DEFAULT_LIB_SQLITE) +AC_SUBST(DEFAULT_LIB_STL) +AC_SUBST(DEFAULT_LIB_TCL) +AC_SUBST(DTRACE) +AC_SUBST(FINAL_OBJS) +AC_SUBST(INSTALLER) +AC_SUBST(INSTALL_LIBS) +AC_SUBST(INSTALL_LIBS_EXTRA) +AC_SUBST(INSTALL_TARGET) +AC_SUBST(JAR) +AC_SUBST(JAVACFLAGS) +AC_SUBST(LDFLAGS) +AC_SUBST(LIBCSO_LIBS) +AC_SUBST(LIBJSO_LIBS) +AC_SUBST(LIBS) +AC_SUBST(LIBSO_LIBS) +AC_SUBST(LIBTOOL) +AC_SUBST(LIBTSO_LIBS) +AC_SUBST(LIBTSO_MODSUFFIX) +AC_SUBST(LIBTSO_MODULE) +AC_SUBST(LIBXSO_LIBS) +AC_SUBST(LOCALEXAMPLES) +AC_SUBST(LOCALSRC) +AC_SUBST(LOCALUTILS) +AC_SUBST(MAKEFILE_CC) +AC_SUBST(MAKEFILE_CCLINK) +AC_SUBST(MAKEFILE_CXX) +AC_SUBST(MAKEFILE_CXXLINK) +AC_SUBST(MAKEFILE_SOLINK) +AC_SUBST(MAKEFILE_XSOLINK) +AC_SUBST(OSDIR) +AC_SUBST(PATH_SEPARATOR) +AC_SUBST(POSTLINK) +AC_SUBST(PRINTLOG_OBJS) +AC_SUBST(REPLACEMENT_OBJS) +AC_SUBST(SOFLAGS) +AC_SUBST(SQL_FLAGS) +AC_SUBST(SQL_LIBS) +AC_SUBST(SWIGCFLAGS) +AC_SUBST(TCL_ADDITIONAL_OBJS) +AC_SUBST(TEST_LIBS) +AC_SUBST(db_int_def) +AC_SUBST(o) +AC_SUBST(subdir_cmd) +AC_SUBST(topdir) + +# The Windows public header has two extra symbols we need to remove. +AC_SUBST(platform_header) +AC_SUBST(platform_footer) + +# Set the default installation location. +AC_PREFIX_DEFAULT(/usr/local/BerkeleyDB.__EDIT_DB_VERSION_MAJOR__.__EDIT_DB_VERSION_MINOR__) + +# Configure the version information. +AC_SUBST(DB_VERSION_FAMILY) +DB_VERSION_FAMILY="__EDIT_DB_VERSION_FAMILY__" +AC_SUBST(DB_VERSION_RELEASE) +DB_VERSION_RELEASE="__EDIT_DB_VERSION_RELEASE__" +AC_SUBST(DB_VERSION_MAJOR) +DB_VERSION_MAJOR="__EDIT_DB_VERSION_MAJOR__" +AC_SUBST(DB_VERSION_MINOR) +DB_VERSION_MINOR="__EDIT_DB_VERSION_MINOR__" +AC_SUBST(DB_VERSION_PATCH) +DB_VERSION_PATCH="__EDIT_DB_VERSION_PATCH__" +AC_SUBST(DB_VERSION_STRING) +DB_VERSION_STRING='"__EDIT_DB_VERSION_STRING__"' +AC_SUBST(DB_VERSION_FULL_STRING) +DB_VERSION_FULL_STRING='"__EDIT_DB_VERSION_FULL_STRING__"' +AC_SUBST(DB_VERSION_UNIQUE_NAME) + +# Process all options before using them. +AM_OPTIONS_SET + +# Set some #defines based on configuration options. +if test "$db_cv_diagnostic" = "yes"; then + AC_DEFINE(DIAGNOSTIC) + AH_TEMPLATE(DIAGNOSTIC, + [Define to 1 if you want a version with run-time diagnostic checking.]) +fi +if test "$db_cv_debug_rop" = "yes"; then + AC_DEFINE(DEBUG_ROP) + AH_TEMPLATE(DEBUG_ROP, + [Define to 1 if you want a version that logs read operations.]) +fi +if test "$db_cv_debug_wop" = "yes"; then + AC_DEFINE(DEBUG_WOP) + AH_TEMPLATE(DEBUG_WOP, + [Define to 1 if you want a version that logs write operations.]) +fi +if test "$db_cv_umrw" = "yes"; then + AC_DEFINE(UMRW) + AH_TEMPLATE(UMRW, + [Define to 1 to mask harmless uninitialized memory read/writes.]) + +fi +if test "$db_cv_test" = "yes"; then + AC_DEFINE(CONFIG_TEST) + AH_TEMPLATE(CONFIG_TEST, + [Define to 1 if you want to build a version for running the test suite.]) +fi + +AH_TEMPLATE(HAVE_UPGRADE_SUPPORT, + [Define to 1 if port includes historic database upgrade support.]) +AC_DEFINE(HAVE_UPGRADE_SUPPORT) + +# Check for programs used in building and installation. +AM_PROGRAMS_SET +AC_PROG_INSTALL + +BUILD_TARGET="library_build" +INSTALL_TARGET="library_install" + +# Respect the environment LIBS settings +LIBSO_LIBS="$LIBS" + +# This is where we handle stuff that autoconf can't handle: compiler, +# preprocessor and load flags, libraries that the standard tests don't +# look for. +# +# There are additional libraries we need for some compiler/architecture +# combinations. +# +# Some architectures require DB to be compiled with special flags and/or +# libraries for threaded applications +# +# The makefile CC may be different than the CC used in config testing, +# because the makefile CC may be set to use $(LIBTOOL). +# +# Don't override anything if it's already set from the environment. +optimize_flag="-O" +extra_cflags="" + +case "$host_os" in +aix4.3.*|aix[[56]]*) + case "$host_os" in + aix4.3.*) + CPPFLAGS="$CPPFLAGS -D_LINUX_SOURCE_COMPAT";; + esac + # IBM's XLC compilers (at least versions 7/8/9) generate incorrect code + # when ordinary optimization is enabled because they make strong + # assumptions about the types held at each memory location, and some + # Berkeley DB code violates those assumptions. [#16141] + extra_cflags=" -qalias=noansi" + optimize_flag="-O2" + CC=${CC-"xlc_r"} + CPPFLAGS="$CPPFLAGS -D_THREAD_SAFE" + LDFLAGS="$LDFLAGS -Wl,-brtl";; +bsdi3*) CC=${CC-"shlicc2"} + LIBSO_LIBS="$LIBSO_LIBS -lipc";; +cygwin*) + CPPFLAGS="$CPPFLAGS -D_GNU_SOURCE -D_REENTRANT";; +freebsd*) + CPPFLAGS="$CPPFLAGS -D_THREAD_SAFE" + LDFLAGS="$LDFLAGS -pthread";; +gnu*|k*bsd*-gnu|linux*) + CPPFLAGS="$CPPFLAGS -D_GNU_SOURCE -D_REENTRANT";; +hpux*) CPPFLAGS="$CPPFLAGS -D_REENTRANT";; +irix*) optimize_flag="-O2" + CPPFLAGS="$CPPFLAGS -D_SGI_MP_SOURCE";; +mpeix*) CPPFLAGS="$CPPFLAGS -D_POSIX_SOURCE -D_SOCKET_SOURCE" + LIBSO_LIBS="$LIBSO_LIBS -lsocket -lsvipc";; +osf*) CPPFLAGS="$CPPFLAGS -pthread";; +*qnx*) qnx_build="yes" + AC_DEFINE(HAVE_QNX) + AH_TEMPLATE(HAVE_QNX, [Define to 1 if building on QNX.]);; +solaris*) + CPPFLAGS="$CPPFLAGS -D_REENTRANT -D_POSIX_PTHREAD_SEMANTICS ";; +esac + +# Set CFLAGS/CXXFLAGS. We MUST set the flags before we call autoconf +# compiler configuration macros, because if we don't, they set CFLAGS +# to no optimization and -g, which isn't what we want. +# +# If the user wants a debugging environment, add -g the their compiler flags +# and don't automatically optimize. If you want to compile with a different +# set of flags, specify CFLAGS in the environment before configuring. +if test "$db_cv_debug" = "yes"; then + AC_DEFINE(DEBUG) + AH_TEMPLATE(DEBUG, [Define to 1 if you want a debugging version.]) + + CFLAGS="-g $CFLAGS" +else + CFLAGS=${CFLAGS-$optimize_flag} +fi + +CFLAGS="$CFLAGS$extra_cflags" +CXXFLAGS=${CXXFLAGS-"$CFLAGS"} + +# The default compiler is cc (NOT gcc), the default CFLAGS is as specified +# above, NOT what is set by AC_PROG_CC, as it won't set optimization flags +# for any compiler other than gcc. +AC_PROG_CC(cc gcc) + +# We know what compiler we're going to use, now. Set per-compiler flags. +if test "$GCC" = "yes"; then + # Use -O3 if we're using gcc, unless we're doing a small build, in + # which case we use -Os alone. The code size for -O3 is quite a + # bit larger than -O2: a compromise is "-Os -finline-functions", + # it's smaller and explicitly inlining the functions helps Berkeley + # DB. + CFLAGS="$CFLAGS " + if test "$db_cv_smallbuild" = "yes" -o "$db_cv_rdsbuild" = "yes" ; then + CFLAGS=`echo "$CFLAGS" | sed 's/-O /-Os /g'` + else + CFLAGS=`echo "$CFLAGS" | sed 's/-O /-O3 /g'` + fi +else + case "$host_os" in + hpux11.0*) ;; + hpux11*) CPPFLAGS="$CPPFLAGS -mt" + test "$host_cpu" = "ia64" && + CFLAGS="$CFLAGS +u1";; + esac +fi + +# Check for "const" and "inline" keywords. +AC_C_CONST +AC_C_INLINE + +# We use prototypes and the keyword "const" in db.h which doesn't include +# db_config.h, so we have to figure out what to do there. +# +# There is an autoconf AC_C_PROTOTYPES macro, but as all it does is define +# db_config.h variables, it doesn't help us. +# +# We don't have much choice, we look at internal autoconf variables. +if test "$ac_cv_c_const" != "yes"; then + DB_CONST="#define const" +fi + +# We use alignment attributes in db.h - figure out if the compiler supports +# them. +AC_CACHE_CHECK([for GCC aligned attribute], db_cv_aligned_attribute, [ +AC_TRY_COMPILE(, __attribute__ ((aligned (8))) int i;, + [db_cv_aligned_attribute=yes], [db_cv_aligned_attribute=no])]) +if test "$db_cv_aligned_attribute" = "yes"; then + DB_STRUCT_ALIGN8="__attribute__ ((aligned (8)))" +fi + +# Clear __P, some other systems use it too. +DB_PROTO1="#undef __P" +if test "$ac_cv_prog_cc_c89" = "no"; then + DB_PROTO2="#define __P(protos) ()" +else + DB_PROTO2="#define __P(protos) protos" +fi + +# Because of shared library building, the ${CC} used for config tests +# may be different than the ${CC} we want to put in the Makefile. +# The latter is known as ${MAKEFILE_CC} in this script. +MAKEFILE_CC="${CC}" +MAKEFILE_CCLINK="${CC}" +MAKEFILE_CXX="nocxx" +MAKEFILE_CXXLINK="nocxx" + +# See if we need the C++ compiler at all. If so, we'd like to find one that +# interoperates with the C compiler we chose. Since we prefered cc over gcc, +# we'll also prefer the vendor's compiler over g++/gcc. If we're wrong, the +# user can set CC and CXX in their environment before running configure. +# +# AC_PROG_CXX sets CXX, but it uses $CXX and $CCC (in that order) as its +# first choices. +if test "$db_cv_cxx" = "yes"; then + if test "$GCC" != "yes"; then + case "$host_os" in + aix*) AC_CHECK_TOOL(CCC, xlC_r) + LIBXSO_LIBS="-lC_r $LIBXSO_LIBS" + LIBSO_LIBS="-lC_r $LIBSO_LIBS";; + hpux*) AC_CHECK_TOOL(CCC, aCC);; + irix*) AC_CHECK_TOOL(CCC, CC);; + osf*) AC_CHECK_TOOL(CCC, cxx) + CXXFLAGS="$CXXFLAGS -D__USE_STD_IOSTREAM" + test -d /usr/include.dtk && + CXXFLAGS="$CXXFLAGS -I/usr/include.dtk";; + solaris*) AC_CHECK_TOOL(CCC, CC);; + esac + fi + AC_PROG_CXX + ###### WORKAROUND: SEE SR #7938 + AC_PROG_CXXCPP + ############################### + AC_CXX_STDHEADERS + MAKEFILE_CXX="${CXX}" + MAKEFILE_CXXLINK="${CXX}" +fi + +# Do some gcc specific configuration. +AC_GCC_CONFIG1 + +# We need the -Kthread/-pthread flag when compiling on SCO/Caldera's UnixWare +# and OpenUNIX releases. We can't make the test until we know which compiler +# we're using. +case "$host_os" in +sysv5UnixWare*|sysv5OpenUNIX8*) + if test "$GCC" == "yes"; then + CPPFLAGS="$CPPFLAGS -pthread" + LDFLAGS="$LDFLAGS -pthread" + else + CPPFLAGS="$CPPFLAGS -Kthread" + LDFLAGS="$LDFLAGS -Kthread" + fi;; +esac + +# Export our compiler preferences for the libtool configuration. +export CC CCC +CCC=$CXX + +# Libtool configuration. +AC_PROG_LIBTOOL + +SOFLAGS="-rpath \$(libdir)" + +# Set SOSUFFIX and friends +SOSUFFIX_CONFIG +MODSUFFIX_CONFIG +JMODSUFFIX_CONFIG + +LIBTOOL="./libtool" + +INSTALLER="\$(LIBTOOL) --mode=install cp -p" + +MAKEFILE_CC="\$(LIBTOOL) --mode=compile ${MAKEFILE_CC}" +MAKEFILE_SOLINK="\$(LIBTOOL) --mode=link ${MAKEFILE_CCLINK} -avoid-version" +MAKEFILE_CCLINK="\$(LIBTOOL) --mode=link ${MAKEFILE_CCLINK}" +MAKEFILE_CXX="\$(LIBTOOL) --mode=compile ${MAKEFILE_CXX}" +MAKEFILE_XSOLINK="\$(LIBTOOL) --mode=link ${MAKEFILE_CXXLINK} -avoid-version" +MAKEFILE_CXXLINK="\$(LIBTOOL) --mode=link ${MAKEFILE_CXXLINK}" + + +case "$host_os" in +cygwin* | mingw*) + MAKEFILE_SOLINK="$MAKEFILE_SOLINK -no-undefined" + MAKEFILE_XSOLINK="$MAKEFILE_XSOLINK -no-undefined";; +esac + +case "$host_os" in + darwin*) + LIBTSO_MODULE="" + LIBTSO_MODSUFFIX=".dylib";; + *qnx*) + LIBTSO_MODULE="" + LIBTSO_MODSUFFIX=$MODSUFFIX;; + *) + LIBTSO_MODULE="-module" + LIBTSO_MODSUFFIX=$MODSUFFIX;; +esac + +if test "$enable_static" = "yes"; then + test "$AR" = "false" && AC_MSG_ERROR([No ar utility found.]) +fi + +# C API. +if test "$enable_shared" = "no"; then + DEFAULT_LIB="\$(libdb_version)" + POSTLINK=": " + o=".o" +else + DEFAULT_LIB="\$(libso_target)" + POSTLINK="\$(LIBTOOL) --mode=execute true" + o=".lo" +fi +INSTALL_LIBS="$DEFAULT_LIB" +if test "$enable_static" = "yes"; then + INSTALL_LIBS="$INSTALL_LIBS \$(libdb)" +fi + +# Optional C++ API. +if test "$db_cv_cxx" = "yes"; then + if test "$enable_shared" = "no"; then + DEFAULT_LIB_CXX="\$(libcxx_version)" + fi + if test "$enable_shared" = "yes"; then + DEFAULT_LIB_CXX="\$(libxso_target)" + fi + INSTALL_LIBS="$INSTALL_LIBS $DEFAULT_LIB_CXX" + if test "$enable_static" = "yes"; then + INSTALL_LIBS="$INSTALL_LIBS \$(libcxx)" + fi +fi + +# Optional Java API / JDBC. +if test "$db_cv_java" = "yes" -o "$db_cv_jdbc" = "yes"; then + # BDB Java API requires shared libraries. + if test "$db_cv_java" = "yes" -a "$enable_shared" = "no"; then + AC_MSG_ERROR([Java requires shared libraries]) + fi + + # A classpath that includes . is needed to check for Java + # Since Cygwin uses Windows' javac, we need Windows path separators + case "$host_os" in + cygwin*) CLASSPATH=".;$CLASSPATH";; + *) CLASSPATH=".:$CLASSPATH";; + esac + export CLASSPATH + AC_PROG_JAVAC + AC_PROG_JAR + AC_PROG_JAVA + AC_JNI_INCLUDE_DIR + + AC_MSG_CHECKING(java version) + case "$JAVA" in + *kaffe* ) + JAVA_VERSION=`$JAVA -version 2>&1 | + sed -e '/Java Version:/!d' -e 's/.*Java Version: \([[^ ]]*\)[[ ]]*/\1/'` ;; + * ) JAVA_VERSION=`$JAVA -version 2>&1 | + sed -e '/ version /!d' -e 's/.*"\(.*\)".*/\1/'` ;; + esac + AC_MSG_RESULT($JAVA_VERSION) + case "$JAVA_VERSION" in + 1.[[3456789]]* | 1.[[1-9]][[0-9]]* | [[23456789]]* ) ;; + * ) + AC_MSG_ERROR([Java version 1.3 or higher required, got $JAVA_VERSION]) ;; + esac + + # Because of the code that SWIG generates to cast between pointers and + # integers, we need to add the flag "-fno-strict-aliasing" to the gcc + # command line when compiling the JNI code. This is documented in + # [#14953] and at http://www.swig.org/Doc1.3/Java.html + if test "${GCC}" = "yes"; then + SWIGCFLAGS="-fno-strict-aliasing" + fi + + for JNI_INCLUDE_DIR in $JNI_INCLUDE_DIRS + do + CPPFLAGS="$CPPFLAGS -I$JNI_INCLUDE_DIR" + done + + if test "$db_cv_java" = "yes"; then + ADDITIONAL_LANG="$ADDITIONAL_LANG java" + INSTALL_LIBS="$INSTALL_LIBS \$(libjso_target)" + fi +else + JAVAC=nojavac +fi + +# MinGW support. +if test "$db_cv_mingw" = "yes"; then + OSDIR=os_windows + PATH_SEPARATOR="\\\\/:" + + AC_DEFINE(DB_WIN32) + AC_DEFINE(STDC_HEADERS) +else + OSDIR=os + PATH_SEPARATOR="/" + AC_DEFINE(HAVE_SYSTEM_INCLUDE_FILES) +fi + +# Optional SQL API. +if test "$db_cv_sql" = "yes"; then + ADDITIONAL_INCS="$ADDITIONAL_INCS dbsql.h" + ADDITIONAL_PROGS="$ADDITIONAL_PROGS dbsql" + + # Link against libdl, if found. It is only needed for the load + # extension, but shouldn't hurt. + AC_HAVE_LIBRARY(dl, SQL_LIBS="$SQL_LIBS -ldl") + + # Link against libedit or readline for command-line editing. + if test x"$with_readline" != xno; then + header=readline.h + for rl_lib in edit readline; do + found="yes" + save_LIBS="" + LIBS="" + AS_UNSET(ac_cv_search_tgetent) + AC_SEARCH_LIBS(tgetent, + [$rl_lib ncurses curses termcap], + [term_LIBS="$LIBS"], [term_LIBS=""]) + AC_CHECK_LIB([$rl_lib], [readline], + [SQL_LIBS="$SQL_LIBS -l$rl_lib $term_LIBS"], + [found="no"]) + LIBS="$save_LIBS" + test "$found" = "yes" && break + done + + if test x"$rl_lib" = xedit; then + header="editline/readline.h" + fi + + if test "$found" = "yes"; then + AC_CHECK_HEADER($header, [found="yes"], [ + found="no" + if test "$cross_compiling" != yes; then + for dir in /usr /usr/local /usr/local/readline /usr/contrib /mingw; do + for subdir in include include/readline; do + AC_CHECK_FILE($dir/$subdir/$header, found=yes) + if test "$found" = "yes"; then + SQL_FLAGS="$SQL_FLAGS -I$dir/$subdir" + break + fi + done + test "$found" = "yes" && break + done + fi]) + fi + fi + + if test "$enable_shared" = "no"; then + DEFAULT_LIB_SQL="\$(libsql_version)" + else + DEFAULT_LIB_SQL="\$(libsqlso_target)" + fi + INSTALL_LIBS="$INSTALL_LIBS $DEFAULT_LIB_SQL" + if test "$enable_static" = "yes"; then + INSTALL_LIBS="$INSTALL_LIBS \$(libsql)" + fi + + if test "$db_cv_test" = "yes"; then + subdirs="$subdirs sql" + ADDITIONAL_LANG="$ADDITIONAL_LANG sql-test" + fi + + if test "$db_cv_jdbc" = "yes"; then + subdirs="$subdirs jdbc" + ADDITIONAL_LANG="$ADDITIONAL_LANG jdbc" + fi + + if test "$db_cv_debug" = "yes"; then + SQL_FLAGS="$SQL_FLAGS -DSQLITE_DEBUG=1" + fi + + if test "$db_cv_build_cryptography" = "yes"; then + SQL_FLAGS="$SQL_FLAGS -DSQLITE_HAS_CODEC=1" + fi +fi + +if test "$db_cv_sql_compat" = "yes"; then + if test "$enable_shared" = "no"; then + DEFAULT_LIB_SQLITE="\$(libsqlite)" + else + DEFAULT_LIB_SQLITE="\$(libsqliteso_target)" + fi + + ADDITIONAL_INCS="$ADDITIONAL_INCS \$(langdir)/sql/generated/sqlite3.h" + ADDITIONAL_PROGS="$ADDITIONAL_PROGS sqlite3" + INSTALL_LIBS="$INSTALL_LIBS $DEFAULT_LIB_SQLITE" + + # This is different to the other libraries: we need to be very + # careful not to delete an existing installation of SQLite unless + # we are installing over it. + if test "$enable_shared" = "yes"; then + INSTALL_LIBS_EXTRA="$INSTALL_LIBS_EXTRA \$(libsqliteso)" + fi + if test "$enable_static" = "yes"; then + INSTALL_LIBS="$INSTALL_LIBS \$(libsqlite)" + fi +fi + +# Optional SQL code generation tool. +if test "$db_cv_sql_codegen" = "yes"; then + ADDITIONAL_PROGS="$ADDITIONAL_PROGS db_sql_codegen" +fi + +# Optional STL API. +if test "$db_cv_stl" = "yes"; then + AC_CXX_SUPPORTS_TEMPLATES + AC_CXX_WSTRING + AX_TLS + if test "$enable_shared" = "no"; then + DEFAULT_LIB_STL="\$(libstl_version)" + fi + if test "$enable_shared" = "yes"; then + DEFAULT_LIB_STL="\$(libstlso_target)" + fi + ADDITIONAL_INCS="$ADDITIONAL_INCS dbstl_common.h" + for f in dbstl_set.h dbstl_vector.h dbstl_exception.h dbstl_map.h dbstl_utility.h dbstl_dbc.h dbstl_dbt.h dbstl_base_iterator.h dbstl_container.h dbstl_element_ref.h dbstl_inner_utility.h dbstl_resource_manager.h ; do + ADDITIONAL_INCS="$ADDITIONAL_INCS \$(topdir)/lang/cxx/stl/$f" + done + INSTALL_LIBS="$INSTALL_LIBS $DEFAULT_LIB_STL" + if test "$enable_static" = "yes"; then + INSTALL_LIBS="$INSTALL_LIBS \$(libstl)" + fi +fi + +# Checks for include files, structures, C types. +AC_HEADER_STAT +AC_HEADER_TIME +AC_HEADER_DIRENT +AC_CHECK_HEADERS(execinfo.h sys/select.h sys/socket.h sys/time.h) +AC_CHECK_MEMBERS([struct stat.st_blksize]) +AM_TYPES + +AC_CACHE_CHECK([for ANSI C exit success/failure values], db_cv_exit_defines, [ +AC_TRY_COMPILE([#include ], return (EXIT_SUCCESS);, + [db_cv_exit_defines=yes], [db_cv_exit_defines=no])]) +if test "$db_cv_exit_defines" = "yes"; then + AC_DEFINE(HAVE_EXIT_SUCCESS) + AH_TEMPLATE(HAVE_EXIT_SUCCESS, + [Define to 1 if platform has EXIT_SUCCESS/EXIT_FAILURE #defines.]) +fi + +AC_CACHE_CHECK([for getopt optreset variable], db_cv_optreset, [ +AC_TRY_LINK([#include ], extern int optreset; optreset = 1;, + [db_cv_optreset=yes], [db_cv_optreset=no])]) +if test "$db_cv_optreset" = "yes"; then + AC_DEFINE(HAVE_GETOPT_OPTRESET) + AH_TEMPLATE(HAVE_GETOPT_OPTRESET, + [Define to 1 if getopt supports the optreset variable.]) +fi + +# Check for mutexes. +# We do this first because it changes $LIBSO_LIBS. +AM_DEFINE_MUTEXES + +# Check for native (system call or instruction set) support for +# atomic increment, decrement, and compare & exchange. +AM_DEFINE_ATOMIC + +# Check for os-specific event support for performance monitoring such as +# DTrace or SystemTap. +AM_DEFINE_PERFMON + +# Test for various functions/libraries -- do tests that change library values +# first. +# +# Update LIBS, so we're testing against the current list of libraries. +LIBS="$LIBSO_LIBS" + +# The yield function on Solaris is almost certainly pthread_yield (LWP threads +# or POSIX pthreads), or thr_yield (UI threads). There's an outside chance it +# is sched_yield() though, only available in -lrt on Solaris. +AC_SEARCH_LIBS(sched_yield, rt) + +# The Berkeley DB library calls fdatasync, only available in -lrt on Solaris. +AC_SEARCH_LIBS(fdatasync, rt) + +AC_SEARCH_LIBS(getaddrinfo, nsl socket) +AC_SEARCH_LIBS(hstrerror, resolv) + +# Those tests updated LIBS, update our internal list. +LIBSO_LIBS="$LIBS" + +# !!! +# We could be more exact about whether these libraries are needed, but don't +# bother -- if they exist, we load them, it's only the test programs anyway. +AC_HAVE_LIBRARY(m, TEST_LIBS="$TEST_LIBS -lm") +AC_HAVE_LIBRARY(nsl, TEST_LIBS="$TEST_LIBS -lnsl") +AC_HAVE_LIBRARY(socket, TEST_LIBS="$TEST_LIBS -lsocket") + +# Checks for system functions for which we have replacements. +# +# The only portable getcwd call is getcwd(char *, size_t), where the +# buffer is non-NULL -- Solaris can't handle a NULL buffer, and they +# deleted getwd(). +AC_REPLACE_FUNCS(\ + abort atoi atol bsearch getcwd getenv getopt isalpha isdigit isprint\ + isspace memcmp memcpy memmove printf qsort raise rand strcasecmp\ + strcat strchr strdup strerror strncat strncmp strrchr strsep\ + strtol strtoul) + +# Check for system functions we optionally use. +AC_CHECK_FUNCS(\ + _fstati64 backtrace backtrace_symbols directio fchmod fclose\ + fcntl fdatasync fgetc fgets fopen fwrite getgid\ + getrusage getuid hstrerror mprotect pstat_getdynamic\ + pthread_self pthread_yield random sched_yield select setgid setuid\ + sigaction snprintf stat sysconf vsnprintf yield) + +AC_TIMERS + +# Ftruncate. +# We've run into a problem with ftruncate on Alpha/Tru64, the issue is that +# after a truncate the last page of the file mmaps as all zeros. So just don't +# use ftruncate. +case "$host_os" in +osf*) + AC_MSG_WARN( + [ftruncate ignored on $host_os-$host_vendor.]);; +*) + AC_CHECK_FUNCS(ftruncate);; +esac + +# Pread/pwrite. +# HP-UX has pread/pwrite, but it doesn't work with largefile support. +# NCR's version of System V R 4.3 has pread/pwrite symbols, but no support. +case "$host_os-$host_vendor" in +hpux*|sysv4.3*-ncr) + AC_MSG_WARN( + [pread/pwrite interfaces ignored on $host_os-$host_vendor.]);; +*) + AC_CHECK_FUNCS(pread pwrite);; +esac + +# Check for getaddrinfo; do the test explicitly instead of using AC_CHECK_FUNCS +# because isn't a standard include file. +AC_CACHE_CHECK([for getaddrinfo], db_cv_getaddrinfo, [ +AC_TRY_LINK([ +#include +#include ], [ + getaddrinfo(0, 0, 0, 0); +], [db_cv_getaddrinfo=yes], [db_cv_getaddrinfo=no])]) +if test "$db_cv_getaddrinfo" = "yes"; then + AC_DEFINE(HAVE_GETADDRINFO) + AH_TEMPLATE(HAVE_GETADDRINFO, + [Define to 1 if you have the `getaddrinfo' function.]) +fi + +# Check for the fcntl F_SETFD flag to deny child process access to file +# descriptors. +AC_CACHE_CHECK([for fcntl/F_SETFD], db_cv_fcntl_f_setfd, [ +AC_TRY_LINK([ +#include +#include ], [ + fcntl(1, F_SETFD, 1); +], [db_cv_fcntl_f_setfd=yes], [db_cv_fcntl_f_setfd=no])]) +if test "$db_cv_fcntl_f_setfd" = "yes"; then + AC_DEFINE(HAVE_FCNTL_F_SETFD) + AH_TEMPLATE(HAVE_FCNTL_F_SETFD, + [Define to 1 if fcntl/F_SETFD denies child access to file descriptors.]) +fi + +# A/UX has a broken getopt(3). +case "$host_os" in +aux*) AC_LIBOBJ([getopt]);; +esac + +# Linux has a broken O_DIRECT flag, but you can't detect it at configure time. +# Linux and SGI require buffer alignment we may not match, otherwise writes +# will fail. Default to not using the O_DIRECT flag. +if test "$db_cv_o_direct" = "yes"; then + AC_CACHE_CHECK([for open/O_DIRECT], db_cv_open_o_direct, [ + AC_TRY_LINK([ + #include + #include ], [ + open("a", O_RDONLY | O_DIRECT, 0); + ], [db_cv_open_o_direct=yes], [db_cv_open_o_direct=no])]) + if test \ + "$db_cv_o_direct" = "yes" -a "$db_cv_open_o_direct" = "yes"; then + AC_DEFINE(HAVE_O_DIRECT) + AH_TEMPLATE(HAVE_O_DIRECT, + [Define to 1 if you have the O_DIRECT flag.]) + fi +fi + +# Check for largefile support. +AC_SYS_LARGEFILE + +# Figure out how to create shared regions. +# +# First, we look for mmap. +# +# BSD/OS has mlock(2), but it doesn't work until the 4.1 release. +# +# Nextstep (version 3.3) apparently supports mmap(2) (the mmap symbol +# is defined in the C library) but does not support munmap(2). Don't +# try to use mmap if we can't find munmap. +# +# Ultrix has mmap(2), but it doesn't work. +mmap_ok=no +case "$host_os" in +bsdi3*|bsdi4.0) + AC_MSG_WARN([mlock(2) interface ignored on $host_os-$host_vendor.]) + mmap_ok=yes + AC_CHECK_FUNCS(mmap munmap, , mmap_ok=no);; +ultrix*) + AC_MSG_WARN([mmap(2) interface ignored on $host_os-$host_vendor.]);; +*) + mmap_ok=yes + AC_CHECK_FUNCS(mlock munlock) + AC_CHECK_FUNCS(mmap munmap, , mmap_ok=no);; +esac + +# Second, we look for shmget. +# +# SunOS has the shmget(2) interfaces, but there appears to be a missing +# #include file, so we ignore them. +shmget_ok=no +case "$host_os" in +sunos*) + AC_MSG_WARN([shmget(2) interface ignored on $host_os-$host_vendor.]);; +*) + shmget_ok=yes + AC_CHECK_FUNCS(shmget, , shmget_ok=no) + + # Check for shmctl to lock down shared memory segments. + AC_CACHE_CHECK([for shmctl], db_cv_shmctl_shm_lock, [ + AC_TRY_LINK([ +#include +#include +#include +#include ], [ + shmctl(0, SHM_LOCK, NULL); + ], [db_cv_shmctl_shm_lock=yes], [db_cv_shmctl_shm_lock=no])]) + if test "$db_cv_shmctl_shm_lock" = "yes"; then + AC_DEFINE(HAVE_SHMCTL_SHM_LOCK) + AH_TEMPLATE(HAVE_SHMCTL_SHM_LOCK, + [Define to 1 if shmctl/SHM_LOCK locks down shared memory segments.]) + fi;; +esac + +# We require either mmap/munmap(2) or shmget(2). +if test "$mmap_ok" = "no" -a "$shmget_ok" = "no"; then + AC_MSG_WARN([Neither mmap/munmap(2) or shmget(2) library functions.]) +fi + +# Optional Tcl support. +if test "$db_cv_tcl" = "yes"; then + AM_TCL_LOAD +fi + +# Optional sequence code. +AM_SEQUENCE_CONFIGURE + +# Detect whether a large mmap() supports automatically extending the accessible +# region after growing the underlying file. +AM_MMAP_EXTEND + +# Optional DB 1.85 compatibility API. +if test "$db_cv_compat185" = "yes"; then + ADDITIONAL_INCS="db_185.h $ADDITIONAL_INCS" + + ADDITIONAL_OBJS="db185${o} $ADDITIONAL_OBJS" +fi + +# Optional utilities. +if test "$db_cv_dump185" = "yes"; then + ADDITIONAL_PROGS="db_dump185 $ADDITIONAL_PROGS" +fi + +# Log checksums can be disabled to increase performance +if test "$db_cv_log_checksum" = "yes"; then + AC_DEFINE(HAVE_LOG_CHECKSUM) + AH_TEMPLATE(HAVE_LOG_CHECKSUM, [Define to 1 if enabling checksums in log records.]) +fi + +# You can disable pieces of functionality to save space. +# +# Btree is always configured: it is the standard method, and Hash off-page +# duplicates require it. + +# Compression can be disabled. +if test "$db_cv_build_compression" = "yes"; then + AC_DEFINE(HAVE_COMPRESSION) + AH_TEMPLATE(HAVE_COMPRESSION, [Define to 1 if building compression support.]) +fi + +# Partitioning can be disabled. +if test "$db_cv_build_partition" = "yes"; then + AC_DEFINE(HAVE_PARTITION) + AH_TEMPLATE(HAVE_PARTITION, [Define to 1 if building partitioned database support.]) + ADDITIONAL_OBJS="$ADDITIONAL_OBJS \$(PARTITION_OBJS)" +else + ADDITIONAL_OBJS="$ADDITIONAL_OBJS partition_stub${o}" +fi + +# Hash can be disabled. +if test "$db_cv_build_hash" = "yes"; then + AC_DEFINE(HAVE_HASH) + AH_TEMPLATE(HAVE_HASH, [Define to 1 if building Hash access method.]) + ADDITIONAL_OBJS="$ADDITIONAL_OBJS \$(HASH_OBJS)" + if test "$db_cv_build_verify" = "yes"; then + ADDITIONAL_OBJS="$ADDITIONAL_OBJS \$(HASH_VRFY_OBJS)" + fi +else + ADDITIONAL_OBJS="$ADDITIONAL_OBJS hash_stub${o}" +fi + +# Heap can be disabled. +if test "$db_cv_build_heap" = "yes"; then + AC_DEFINE(HAVE_HEAP) + AH_TEMPLATE(HAVE_HEAP, [Define to 1 if building Heap access method.]) + ADDITIONAL_OBJS="$ADDITIONAL_OBJS \$(HEAP_OBJS)" + if test "$db_cv_build_verify" = "yes"; then + ADDITIONAL_OBJS="$ADDITIONAL_OBJS \$(HEAP_VRFY_OBJS)" + fi +else + ADDITIONAL_OBJS="$ADDITIONAL_OBJS heap_stub${o}" +fi + +# Queue can be disabled. +if test "$db_cv_build_queue" = "yes"; then + AC_DEFINE(HAVE_QUEUE) + AH_TEMPLATE(HAVE_QUEUE, [Define to 1 if building Queue access method.]) + ADDITIONAL_OBJS="$ADDITIONAL_OBJS \$(QUEUE_OBJS)" + if test "$db_cv_build_verify" = "yes"; then + ADDITIONAL_OBJS="$ADDITIONAL_OBJS \$(QUEUE_VRFY_OBJS)" + fi +else + ADDITIONAL_OBJS="$ADDITIONAL_OBJS qam_stub${o}" +fi + +# Replication can be disabled. +if test "$db_cv_build_replication" = "yes"; then + AC_DEFINE(HAVE_REPLICATION) + AH_TEMPLATE(HAVE_REPLICATION, + [Define to 1 if building replication support.]) + ADDITIONAL_OBJS="$ADDITIONAL_OBJS \$(REP_OBJS)" + + # If we're building replication and detected POSIX threads, build the + # replication manager. + AH_TEMPLATE(HAVE_REPLICATION_THREADS, + [Define to 1 if building the Berkeley DB replication framework.]) + + if test "$ac_cv_header_pthread_h" = yes -a "$db_cv_mingw" != "yes"; then + AC_DEFINE(HAVE_REPLICATION_THREADS) + + if test "$with_stacksize" != "no"; then + AC_DEFINE_UNQUOTED(DB_STACKSIZE, $with_stacksize, + [Defined to a size to limit the stack size of Berkeley DB threads.]) + fi + + # Solaris requires the socket and nsl libraries to build the + # replication manager. Don't add nsl regardless of the OS, + # it causes RPC to fail on AIX 4.3.3. + case "$host_os" in + solaris*) + AC_HAVE_LIBRARY(nsl, LIBSO_LIBS="$LIBSO_LIBS -lnsl") + AC_HAVE_LIBRARY(socket, + LIBSO_LIBS="$LIBSO_LIBS -lsocket");; + esac + ADDITIONAL_OBJS="$ADDITIONAL_OBJS \$(REPMGR_OBJS)" + else + AC_MSG_WARN([Replication manager is not supported.]) + ADDITIONAL_OBJS="$ADDITIONAL_OBJS repmgr_stub${o}" + fi +else + ADDITIONAL_OBJS="$ADDITIONAL_OBJS rep_stub${o} repmgr_stub${o}" +fi + +# The statistics code can be disabled. +if test "$db_cv_build_statistics" = "yes"; then + AC_DEFINE(HAVE_STATISTICS) + AH_TEMPLATE(HAVE_STATISTICS, + [Define to 1 if building statistics support.]) +fi + +# The verification code can be disabled. +if test "$db_cv_build_verify" = "yes"; then + AC_DEFINE(HAVE_VERIFY) + AH_TEMPLATE(HAVE_VERIFY, + [Define to 1 if building access method verification support.]) + if test "$db_cv_rdsbuild" = "no"; then + ADDITIONAL_OBJS="$ADDITIONAL_OBJS \$(BTREE_VRFY_OBJS) \$(LOG_VRFY_OBJS)" + else + ADDITIONAL_OBJS="$ADDITIONAL_OBJS \$(BTREE_VRFY_OBJS) log_verify_stub${o}" + fi +else + ADDITIONAL_OBJS="$ADDITIONAL_OBJS db_vrfy_stub${o} log_verify_stub${o}" +fi + +# The crypto code can be disabled. +if test -d "$topdir/src/crypto" -a "$db_cv_build_cryptography" != "no"; then + AC_DEFINE(HAVE_CRYPTO) + AH_TEMPLATE(HAVE_CRYPTO, + [Define to 1 if building cryptography support.]) + + CRYPTO_OBJS="\$(CRYPTO_OBJS)" + + if test "$db_cv_build_cryptography" = "ipp"; then + AC_CHECK_HEADER([ippcp.h], [], AC_MSG_ERROR([\ +The 'ippcp.h' header file required for IPP cryptography support was not found \ +in the configured include path.])) + AC_DEFINE(HAVE_CRYPTO_IPP) + AH_TEMPLATE(HAVE_CRYPTO_IPP, + [Define to 1 if using Intel IPP for cryptography.]) + fi +else + CRYPTO_OBJS="crypto_stub${o}" +fi + +# The mutex code can be disabled, and if there aren't any mutexes, then there's +# no reason to include the locking code. +if test "$db_cv_build_mutexsupport" = "yes"; then + ADDITIONAL_OBJS="$ADDITIONAL_OBJS \$(MUTEX_OBJS)" + db_cv_locking="yes" +else + db_cv_locking="no" + ADDITIONAL_OBJS="$ADDITIONAL_OBJS mut_stub${o}" +fi + +LOCALEXAMPLES="\$(exampledir)" +LOCALSRC="\$(srcdir)" +LOCALUTILS="\$(utildir)" +# The RDS build disables transactions and most features except DML and cursors. +# They are removed by appending rds_stubs instead of STD_OBJS to ADDITIONAL_OBJS. +if test "$db_cv_rdsbuild" = "no"; then + AC_DEFINE(HAVE_TRANSACTIONS) + AH_TEMPLATE(HAVE_TRANSACTIONS, [Define to 1 if building in transaction support.]) + ADDITIONAL_OBJS="$ADDITIONAL_OBJS \$(STD_OBJS)" + ADDITIONAL_PROGS="$ADDITIONAL_PROGS \$(STD_PROGS)" +else + AC_DEFINE(HAVE_RDS_BUILD) + AH_TEMPLATE(HAVE_RDS_BUILD, [Define to 1 if building only the most basic features.]) + ADDITIONAL_OBJS="$ADDITIONAL_OBJS rds_stub${o}" + db_cv_locking="no" + if test "$db_rdsbuild_default" = "no" ; then + # The normal db_load and db_stat utilities use non-RDS features. + # This modifies those source files such that they can work with + # with --enable-rdsbuild, + LOCALEXAMPLES="examples" + LOCALSRC="src" + LOCALUTILS="util" + # Apply all .patch files underneath the patches directory + # to local copies in the building directory. + for f in `grep -v '^#' $topdir/dist/rds/patchlist`; do + localdir=`dirname $f` + rm -f ./$f + test -d $localdir || mkdir -p $localdir || exit 1 + cp $topdir/$f $f && \ + patch $f $topdir/dist/rds/patches/$f.patch && \ + chmod 444 $f || exit 1 + done + fi +fi + +# AH_TEMPLATE(HAVE_LOCKING, [Define to 1 if building in locking support.]) +if test "$db_cv_locking" = "yes"; then +# AC_DEFINE(HAVE_LOCKING) + ADDITIONAL_OBJS="$ADDITIONAL_OBJS \$(LOCK_OBJS)" +else + ADDITIONAL_OBJS="$ADDITIONAL_OBJS lock_stub${o}" +fi + +# If DIAGNOSTIC is defined (but not RDS), include the log print routines in the +# library itself, various diagnostic modes use them. +if test "$db_cv_diagnostic" = "yes"; then + if test "$db_cv_rdsbuild" = "no"; then + ADDITIONAL_OBJS="$ADDITIONAL_OBJS \$(PRINT_OBJS)" + fi + PRINTLOG_OBJS="" +else + PRINTLOG_OBJS="\$(PRINT_OBJS)" +fi + +# If building for QNX, we need additional OS files. +if test "$qnx_build" = "yes"; then + ADDITIONAL_OBJS="$ADDITIONAL_OBJS os_qnx_fsync${o} os_qnx_open${o}" +fi + +# The DBM API can be disabled. +if test "$db_cv_dbm" = "yes"; then + AC_DEFINE(HAVE_DBM) + AH_TEMPLATE(HAVE_DBM, [Define to 1 if building the DBM API.]) + ADDITIONAL_OBJS="$ADDITIONAL_OBJS dbm${o} hsearch${o}" +fi + +# The output and error messages can be stripped. +if test "$db_cv_stripped_messages" = "yes"; then + AC_DEFINE(HAVE_STRIPPED_MESSAGES) + AH_TEMPLATE(HAVE_STRIPPED_MESSAGES, + [Define to 1 if building without output message content.]) +fi + +# The output and error messages can be localized. +if test "$db_cv_localization" = "yes"; then + AC_DEFINE(HAVE_LOCALIZATION) + AH_TEMPLATE(HAVE_LOCALIZATION, +[Define to 1 if you have localization function to support globalization.]) +fi + +# We need to add the additional object files into the Makefile with the correct +# suffix. We can't use $LTLIBOBJS itself, because that variable has $U encoded +# in it for automake, and that's not what we want. See SR #7227 for additional +# information. +# +# XXX: I'm not sure this is correct. +REPLACEMENT_OBJS=`echo "$LIB@&t@OBJS" | + sed "s,\.[[^.]]* ,$o ,g;s,\.[[^.]]*$,$o,"` + +# This is necessary so that .o files in LIBOBJS are also built via +# the ANSI2KNR-filtering rules. +LIB@&t@OBJS=`echo "$LIB@&t@OBJS" | + sed 's,\.[[^.]]* ,$U&,g;s,\.[[^.]]*$,$U&,'` +LTLIBOBJS=`echo "$LIB@&t@OBJS" | + sed 's,\.[[^.]]* ,.lo ,g;s,\.[[^.]]*$,.lo,'` +AC_SUBST(LTLIBOBJS) + +# Initial output file list. +CREATE_LIST="Makefile + db_cxx.h:$topdir/src/dbinc/db_cxx.in + db_int.h:$topdir/src/dbinc/db_int.in + clib_port.h:$topdir/dist/clib_port.in" +if test "$db_cv_tcl" = "yes"; then +CREATE_LIST="$CREATE_LIST + include.tcl:$topdir/test/tcl/include.tcl" +fi + +# Create the db.h file from a source file, a list of global function +# prototypes, and, if configured for unique names, a list of #defines +# to do DB_VERSION_UNIQUE_NAME substitution. +if test "$db_cv_uniquename" = "yes"; then + CREATE_LIST="$CREATE_LIST + db.h:$topdir/src/dbinc/db.in:$topdir/src/dbinc_auto/api_flags.in:$topdir/src/dbinc_auto/ext_def.in:$topdir/src/dbinc_auto/ext_prot.in" +else + CREATE_LIST="$CREATE_LIST + db.h:$topdir/src/dbinc/db.in:$topdir/src/dbinc_auto/api_flags.in:$topdir/src/dbinc_auto/ext_prot.in" +fi + +# If configured for unique names, create the db_int_uext.h file (which +# does the DB_VERSION_UNIQUE_NAME substitution), which is included by +# the db_int.h file. +if test "$db_cv_uniquename" = "yes"; then + CREATE_LIST="$CREATE_LIST + db_int_def.h:$topdir/src/dbinc_auto/int_def.in" + db_int_def='#include "db_int_def.h"' +fi + +# Create the db_185.h and db185_int.h files from source files, a list of +# global function prototypes, and, if configured for unique names, a list +# of #defines to do DB_VERSION_UNIQUE_NAME substitution. +if test "$db_cv_compat185" = "yes"; then + if test "$db_cv_uniquename" = "yes"; then + CREATE_LIST="$CREATE_LIST + db_185.h:$topdir/src/dbinc/db_185.in:$topdir/src/dbinc_auto/ext_185_def.in:$topdir/src/dbinc_auto/ext_185_prot.in + db185_int.h:$topdir/lang/db185/db185_int.in:$topdir/src/dbinc_auto/ext_185_def.in:$topdir/src/dbinc_auto/ext_185_prot.in" + else + CREATE_LIST="$CREATE_LIST + db_185.h:$topdir/src/dbinc/db_185.in:$topdir/src/dbinc_auto/ext_185_prot.in + db185_int.h:$topdir/lang/db185/db185_int.in:$topdir/src/dbinc_auto/ext_185_prot.in" + fi +fi + +if test "$db_cv_stl" = "yes"; then + CREATE_LIST="$CREATE_LIST + dbstl_common.h:$topdir/lang/cxx/stl/dbstl_common.in" +fi + +if test "x$subdirs" != "x"; then + subdir_cmd="@for d in ${subdirs}; do (cd \$\$d && \${MAKE} \$@) ; done" +fi + +AC_CONFIG_FILES($CREATE_LIST) +AC_OUTPUT + +if test "$db_cv_rdsbuild" = "yes" -a "$db_rdsbuild_default" = "no" ; then + # Patch the resulting db.h to remove unsupported functions. + patch "db.h" "$topdir/dist/rds/patches/src/dbinc/db.in.patch" || exit 1 + patch "db_int.h" "$topdir/dist/rds/patches/src/dbinc/db_int.in.patch" || exit 1 +fi + +if test "$db_cv_sql" = "yes"; then + # This command runs the configure script from the SQL tree. + AC_MSG_NOTICE([Configuring the SQL API]) + AC_SQL_CONFIG +fi diff -r 000000000000 -r a1985f14b030 dist/errno.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dist/errno.h Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,213 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 1996, 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +/* + * Copyright (c) 1982, 1986, 1989, 1993 + * The Regents of the University of California. All rights reserved. + * (c) UNIX System Laboratories, Inc. + * All or some portions of this file are derived from material licensed + * to the University of California by American Telephone and Telegraph + * Co. or Unix System Laboratories, Inc. and are reproduced herein with + * the permission of UNIX System Laboratories, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)errno.h 8.5 (Berkeley) 1/21/94 + * FreeBSD: /repoman/r/ncvs/src/sys/sys/errno.h,v 1.28 2005/04/02 12:33:28 das Exp $ + * + * $Id$ + */ + +#ifndef _SYS_ERRNO_H_ +#define _SYS_ERRNO_H_ + +#undef errno +#define errno DB_GLOBAL(db_errno) + +#define EPERM 1 /* Operation not permitted */ +#define ENOENT 2 /* No such file or directory */ +#define ESRCH 3 /* No such process */ +#define EINTR 4 /* Interrupted system call */ +#define EIO 5 /* Input/output error */ +#define ENXIO 6 /* Device not configured */ +#define E2BIG 7 /* Argument list too long */ +#define ENOEXEC 8 /* Exec format error */ +#define EBADF 9 /* Bad file descriptor */ +#define ECHILD 10 /* No child processes */ +#define EDEADLK 11 /* Resource deadlock avoided */ + /* 11 was EAGAIN */ +#define ENOMEM 12 /* Cannot allocate memory */ +#define EACCES 13 /* Permission denied */ +#define EFAULT 14 /* Bad address */ +#ifndef _POSIX_SOURCE +#define ENOTBLK 15 /* Block device required */ +#endif +#define EBUSY 16 /* Device busy */ +#define EEXIST 17 /* File exists */ +#define EXDEV 18 /* Cross-device link */ +#define ENODEV 19 /* Operation not supported by device */ +#define ENOTDIR 20 /* Not a directory */ +#define EISDIR 21 /* Is a directory */ +#define EINVAL 22 /* Invalid argument */ +#define ENFILE 23 /* Too many open files in system */ +#define EMFILE 24 /* Too many open files */ +#define ENOTTY 25 /* Inappropriate ioctl for device */ +#ifndef _POSIX_SOURCE +#define ETXTBSY 26 /* Text file busy */ +#endif +#define EFBIG 27 /* File too large */ +#define ENOSPC 28 /* No space left on device */ +#define ESPIPE 29 /* Illegal seek */ +#define EROFS 30 /* Read-only filesystem */ +#define EMLINK 31 /* Too many links */ +#define EPIPE 32 /* Broken pipe */ + +/* math software */ +#define EDOM 33 /* Numerical argument out of domain */ +#define ERANGE 34 /* Result too large */ + +/* non-blocking and interrupt i/o */ +#define EAGAIN 35 /* Resource temporarily unavailable */ +#ifndef _POSIX_SOURCE +#define EWOULDBLOCK EAGAIN /* Operation would block */ +#define EINPROGRESS 36 /* Operation now in progress */ + +#define EALREADY 37 /* Operation already in progress */ + +/* ipc/network software -- argument errors */ +#define ENOTSOCK 38 /* Socket operation on non-socket */ +#define EDESTADDRREQ 39 /* Destination address required */ +#define EMSGSIZE 40 /* Message too long */ +#define EPROTOTYPE 41 /* Protocol wrong type for socket */ +#define ENOPROTOOPT 42 /* Protocol not available */ +#define EPROTONOSUPPORT 43 /* Protocol not supported */ +#define ESOCKTNOSUPPORT 44 /* Socket type not supported */ +#define EOPNOTSUPP 45 /* Operation not supported */ +#define ENOTSUP EOPNOTSUPP /* Operation not supported */ +#define EPFNOSUPPORT 46 /* Protocol family not supported */ +#define EAFNOSUPPORT 47 /* Address family not supported by protocol family */ +#define EADDRINUSE 48 /* Address already in use */ +#define EADDRNOTAVAIL 49 /* Can't assign requested address */ + +/* ipc/network software -- operational errors */ +#define ENETDOWN 50 /* Network is down */ +#define ENETUNREACH 51 /* Network is unreachable */ +#define ENETRESET 52 /* Network dropped connection on reset */ +#define ECONNABORTED 53 /* Software caused connection abort */ +#define ECONNRESET 54 /* Connection reset by peer */ +#define ENOBUFS 55 /* No buffer space available */ +#define EISCONN 56 /* Socket is already connected */ +#define ENOTCONN 57 /* Socket is not connected */ +#define ESHUTDOWN 58 /* Can't send after socket shutdown */ +#define ETOOMANYREFS 59 /* Too many references: can't splice */ +#define ETIMEDOUT 60 /* Operation timed out */ +#define ECONNREFUSED 61 /* Connection refused */ + +#define ELOOP 62 /* Too many levels of symbolic links */ +#endif /* _POSIX_SOURCE */ +#define ENAMETOOLONG 63 /* File name too long */ + +/* should be rearranged */ +#ifndef _POSIX_SOURCE +#define EHOSTDOWN 64 /* Host is down */ +#define EHOSTUNREACH 65 /* No route to host */ +#endif /* _POSIX_SOURCE */ +#define ENOTEMPTY 66 /* Directory not empty */ + +/* quotas & mush */ +#ifndef _POSIX_SOURCE +#define EPROCLIM 67 /* Too many processes */ +#define EUSERS 68 /* Too many users */ +#define EDQUOT 69 /* Disc quota exceeded */ + +/* Network File System */ +#define ESTALE 70 /* Stale NFS file handle */ +#define EREMOTE 71 /* Too many levels of remote in path */ +#define EBADRPC 72 /* RPC struct is bad */ +#define ERPCMISMATCH 73 /* RPC version wrong */ +#define EPROGUNAVAIL 74 /* RPC prog. not avail */ +#define EPROGMISMATCH 75 /* Program version wrong */ +#define EPROCUNAVAIL 76 /* Bad procedure for program */ +#endif /* _POSIX_SOURCE */ + +#define ENOLCK 77 /* No locks available */ +#define ENOSYS 78 /* Function not implemented */ + +#ifndef _POSIX_SOURCE +#define EFTYPE 79 /* Inappropriate file type or format */ +#define EAUTH 80 /* Authentication error */ +#define ENEEDAUTH 81 /* Need authenticator */ +#define EIDRM 82 /* Identifier removed */ +#define ENOMSG 83 /* No message of desired type */ +#define EOVERFLOW 84 /* Value too large to be stored in data type */ +#define ECANCELED 85 /* Operation canceled */ +#define EILSEQ 86 /* Illegal byte sequence */ +#define ENOATTR 87 /* Attribute not found */ + +#define EDOOFUS 88 /* Programming error */ +#endif /* _POSIX_SOURCE */ + +#define EBADMSG 89 /* Bad message */ +#define EMULTIHOP 90 /* Multihop attempted */ +#define ENOLINK 91 /* Link has been severed */ +#define EPROTO 92 /* Protocol error */ + +#ifndef _POSIX_SOURCE +#define ELAST 92 /* Must be equal largest errno */ +#endif /* _POSIX_SOURCE */ + +#ifdef _KERNEL +/* pseudo-errors returned inside kernel to modify return to process */ +#define ERESTART (-1) /* restart syscall */ +#define EJUSTRETURN (-2) /* don't modify regs, just return */ +#define ENOIOCTL (-3) /* ioctl not handled by this layer */ +#define EDIRIOCTL (-4) /* do direct ioctl in GEOM */ +#endif + +#endif diff -r 000000000000 -r a1985f14b030 dist/gen_inc.awk --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dist/gen_inc.awk Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,94 @@ +# This awk script parses C input files looking for lines marked "PUBLIC:" +# "EXTERN:", and "DB_LOG_RECSPEC". (PUBLIC lines are DB internal function +# prototypes and #defines, EXTERN lines are DB external function prototypes +# and #defines, and DB_LOG_RECSPEC lines are the definition of log record +# templates.) +# +# PUBLIC lines are put into two versions of per-directory include files: +# one file that contains the prototypes, and one file that contains a +# #define for the name to be processed during configuration when creating +# unique names for every global C-language symbol in the DB library. +# +# The EXTERN lines are put into two files: one of which contains prototypes +# which are always appended to the db.h file, and one of which contains a +# #define list for use when creating unique symbol names. +# +# DB_LOG_RECSPEC lines are put into PUBLIC's internal #define file. +# +# Four arguments: +# e_dfile list of EXTERN #defines +# e_pfile include file that contains EXTERN prototypes +# i_dfile list of internal (PUBLIC) #defines +# i_pfile include file that contains internal (PUBLIC) prototypes +# +# Copyright (c) 1996, 2012 Oracle and/or its affiliates. All rights reserved. +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. Oracle designates this +# particular file as subject to the "Classpath" exception as provided +# by Oracle in the LICENSE file that accompanied this code. +# +# This code 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 General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. +# +/PUBLIC:/ { + sub(/^.*PUBLIC:[ ][ ]*/, "") + if ($0 ~ /^#if|^#ifdef|^#ifndef|^#else|^#endif/) { + print $0 >> i_pfile + print $0 >> i_dfile + next + } + pline = sprintf("%s %s", pline, $0) + if (pline ~ /\)\);/) { + sub(/^[ ]*/, "", pline) + print pline >> i_pfile + if (pline !~ db_version_unique_name) { + gsub(/[ ][ ]*__P.*/, "", pline) + sub(/^.*[ ][*]*/, "", pline) + printf("#define %s %s@DB_VERSION_UNIQUE_NAME@\n", + pline, pline) >> i_dfile + } + pline = "" + } +} + +/EXTERN:/ { + sub(/^.*EXTERN:[ ][ ]*/, "") + if ($0 ~ /^#if|^#ifdef|^#ifndef|^#else|^#endif/) { + print $0 >> e_pfile + print $0 >> e_dfile + next + } + eline = sprintf("%s %s", eline, $0) + if (eline ~ /\)\);/) { + sub(/^[ ]*/, "", eline) + print eline >> e_pfile + if (eline !~ db_version_unique_name) { + gsub(/[ ][ ]*__P.*/, "", eline) + sub(/^.*[ ][*]*/, "", eline) + printf("#define %s %s@DB_VERSION_UNIQUE_NAME@\n", + eline, eline) >> e_dfile + } + eline = "" + } +} + +/^DB_LOG_RECSPEC.*_desc\[\]/ { + sub(/DB_LOG_RECSPEC[ ]*/, ""); + sub(/\[][ ]*=[ ]*{.*$/, ""); + printf("#define\t%s %s@DB_VERSION_UNIQUE_NAME@\n", $0, $0) >> i_dfile +} diff -r 000000000000 -r a1985f14b030 dist/gen_msg.awk --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dist/gen_msg.awk Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,496 @@ +# +# See the file LICENSE for redistribution information. +# +# Copyright (c) 1996, 2012 Oracle and/or its affiliates. All rights reserved. +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. Oracle designates this +# particular file as subject to the "Classpath" exception as provided +# by Oracle in the LICENSE file that accompanied this code. +# +# This code 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 General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. +# +# $Id$ +# + +BEGIN { + if (source_file == "" || header_file == "") { + print "Usage: gen_msg.awk requires these variables to be set:"; + print "\theader_file\t-- the message #include file being created"; + print "\tsource_file\t-- the message source file being created"; + exit; + } + CFILE=source_file; + HFILE=header_file; + maxmsg = 0; +} +/^[ ]*PREFIX/ { + prefix = $2; + + # Start .c files. + printf("/* Do not edit: automatically built by gen_msg.awk.\n *\n") \ + > CFILE + printf(" * Copyright (c) 2012 Oracle and/or its affiliates. All rights reserved.")\ + >> CFILE + printf(" *\n */\n\n") >> CFILE + printf("#include \"db_config.h\"\n\n") >> CFILE + + # Start .h file, make the entire file conditional. + printf("/* Do not edit: automatically built by gen_msg.awk.\n *\n") \ + > HFILE + printf(" * Copyright (c) 2012 Oracle and/or its affiliates. All rights reserved.")\ + >> HFILE + printf(" *\n */\n\n") >> HFILE + printf("#ifndef\t%s_AUTOMSG_H\n#define\t%s_AUTOMSG_H\n\n", prefix, prefix) \ + >> HFILE; + printf("/*\n") >> HFILE; + printf(" * Message sizes are simply the sum of field sizes (not\n") \ + >> HFILE; + printf(" * counting variable size parts, when DBTs are present),\n") \ + >> HFILE; + printf(" * and may be different from struct sizes due to padding.\n") \ + >> HFILE; + printf(" */\n") >> HFILE; +} +/^[ ]*INCLUDE/ { + for (i = 2; i < NF; i++) + printf("%s ", $i) >> CFILE; + printf("%s\n", $i) >> CFILE; +} +/^[ ]*BEGIN_MSG/ { + if (in_begin) { + print "Invalid format: missing END statement"; + exit; + } + in_begin = 1; + nvars = 0; + thismsg = $2; + for (i = 2; i<= NF; i++) { + if ($i == "alloc") + alloc = 1; + else if ($i == "check_length") + check_length = 1; + else if ($i == "version") + version = 1; + } + + base_name = sprintf("%s_%s", prefix, thismsg); + typedef_name = sprintf("%s_args", base_name); + msg_size_name = toupper(sprintf("%s_SIZE", base_name)); + max_name = toupper(sprintf("%s_MAXMSG_SIZE", prefix)); +} +/^[ ]*ARG/ { + vars[nvars] = $2; + types[nvars] = $3; + if (types[nvars] == "DBT") + has_dbt = 1; + nvars++; +} +/^[ ]*END/ { + if (!in_begin) { + print "Invalid format: missing BEGIN statement"; + exit; + } + if (nvars == 0) { + printf("%s needs at least one field\n", thismsg); + exit; + } + + sum = 0; + for (i = 0; i < nvars; i++) + sum += type_length(types[i]); + printf("#define\t%s\t%d\n", msg_size_name, sum) >> HFILE; + if (sum > maxmsg) + maxmsg = sum; + + printf("typedef struct _%s {\n", typedef_name) >> HFILE; + for (i = 0; i < nvars; i++) { + if (types[i] == "DB_LSN" || types[i] == "DBT") + printf("\t%s\t\t%s;\n", types[i], vars[i]) >> HFILE; + else + printf("\t%s\t%s;\n", types[i], vars[i]) >> HFILE; + } + printf("} %s;\n\n", typedef_name) >> HFILE; + + emit_marshal(); + emit_unmarshal(); + + # Reinitialize variables for next time. + in_begin = 0; + alloc = 0; + check_length = 0; + version = 0; + has_dbt = 0; +} +END { + # End the conditional for the HFILE + printf("#define\t%s\t%d\n", max_name, maxmsg) >> HFILE; + printf("#endif\n") >> HFILE; +} + +# Length of fixed part of message. Does not count variable-length data portion +# of DBT. +# +function type_length(type) +{ + if (type == "DB_LSN") + return (8); + if (type == "DBT" || type == "u_int32_t" || type == "db_pgno_t") + return (4); + if (type == "u_int16_t") + return (2); + if (type == "u_int8_t") + return (1); + printf("unknown field type: %s", type); + exit(1); +} + +function emit_marshal() +{ + pi = 1; + if (check_length) + p[pi++] = "int "; + else + p[pi++] = "void "; + function_name = sprintf("%s_marshal", base_name); + p[pi++] = function_name; + p[pi++] = " __P((ENV *, "; + if (version) + p[pi++] = "u_int32_t, "; + p[pi++] = sprintf("%s *, u_int8_t *", typedef_name); + if (check_length) + p[pi++] = ", size_t, size_t *"; + p[pi++] = "));"; + proto_format(p, CFILE); + + if (check_length) + printf("int\n") >> CFILE; + else + printf("void\n") >> CFILE; + printf("%s(env", function_name) >> CFILE; + if (version) + printf(", version") >> CFILE; + printf(", argp, bp") >> CFILE; + if (check_length) + printf(", max, lenp") >> CFILE; + printf(")\n") >> CFILE; + + printf("\tENV *env;\n") >> CFILE; + if (version) + printf("\tu_int32_t version;\n") >> CFILE; + printf("\t%s *argp;\n", typedef_name) >> CFILE; + printf("\tu_int8_t *bp;\n") >> CFILE; + if (check_length) + printf("\tsize_t *lenp, max;\n") >> CFILE; + printf("{\n") >> CFILE; + + if (version) + printf("\tint copy_only;\n") >> CFILE; + if (check_length) { + printf("\tu_int8_t *start;\n\n") >> CFILE; + printf("\tif (max < %s", msg_size_name) >> CFILE; + for (i = 0; i < nvars; i++) + if (types[i] == "DBT") + printf("\n\t + (size_t)argp->%s.size", \ + vars[i]) >> CFILE; + # add in dbt sizes + printf(")\n") >> CFILE; + printf("\t\treturn (ENOMEM);\n") >> CFILE; + printf("\tstart = bp;\n\n") >> CFILE; + } + + if (version) { + printf("\tcopy_only = 0;\n") >> CFILE; + printf("\tif (version < DB_REPVERSION_47)\n") >> CFILE; + printf("\t\tcopy_only = 1;\n") >> CFILE; + } + for (i = 0; i < nvars; i++) { + if (types[i] == "u_int32_t" || types[i] == "db_pgno_t") { + if (version) { + printf("\tif (copy_only) {\n") >> CFILE; + printf(\ + "\t\tmemcpy(bp, &argp->%s, sizeof(u_int32_t));\n", vars[i]) >> CFILE; + printf(\ + "\t\tbp += sizeof(u_int32_t);\n") >> CFILE; + printf("\t} else\n\t") >> CFILE; + } + printf("\tDB_HTONL_COPYOUT(env, bp, argp->%s);\n", \ + vars[i]) >> CFILE; + } else if (types[i] == "u_int16_t") { + if (version) { + printf("\tif (copy_only) {\n") >> CFILE; + printf(\ + "\t\tmemcpy(bp, &argp->%s, sizeof(u_int16_t));\n", vars[i]) >> CFILE; + printf(\ + "\t\tbp += sizeof(u_int16_t);\n") >> CFILE; + printf("\t} else\n\t") >> CFILE; + } + printf("\tDB_HTONS_COPYOUT(env, bp, argp->%s);\n", \ + vars[i]) >> CFILE; + } else if (types[i] == "u_int8_t") { + printf(\ + "\t*bp++ = argp->%s;\n", vars[i]) >> CFILE; + } else if (types[i] == "DB_LSN") { + if (version) { + printf("\tif (copy_only) {\n") >> CFILE; + printf(\ + "\t\tmemcpy(bp, &argp->%s.file, sizeof(u_int32_t));\n", vars[i]) >> CFILE; + printf(\ + "\t\tbp += sizeof(u_int32_t);\n") >> CFILE; + printf(\ + "\t\tmemcpy(bp, &argp->%s.offset, sizeof(u_int32_t));\n", vars[i]) >> CFILE; + printf(\ + "\t\tbp += sizeof(u_int32_t);\n") >> CFILE; + printf("\t} else {\n\t") >> CFILE; + } + printf("\tDB_HTONL_COPYOUT(env, bp, argp->%s.file);\n",\ + vars[i]) >> CFILE; + if (version) + printf("\t") >> CFILE; + printf( \ + "\tDB_HTONL_COPYOUT(env, bp, argp->%s.offset);\n", \ + vars[i]) >> CFILE; + if (version) + printf("\t}\n") >> CFILE; + } else if (types[i] == "DBT") { + if (version) { + printf("\tif (copy_only) {\n") >> CFILE; + printf(\ + "\t\tmemcpy(bp, &argp->%s.size, sizeof(u_int32_t));\n", vars[i]) >> CFILE; + printf(\ + "\t\tbp += sizeof(u_int32_t);\n") >> CFILE; + printf("\t} else\n\t") >> CFILE; + } + printf("\tDB_HTONL_COPYOUT(env, bp, argp->%s.size);\n",\ + vars[i]) >> CFILE; + printf("\tif (argp->%s.size > 0) {\n", vars[i]) \ + >> CFILE; + printf( \ + "\t\tmemcpy(bp, argp->%s.data, argp->%s.size);\n", \ + vars[i], vars[i]) >> CFILE; + printf("\t\tbp += argp->%s.size;\n", vars[i]) >> CFILE; + printf("\t}\n") >> CFILE; + } else { + printf("unknown field type: %s", types[i]); + exit(1); + } + } + + if (check_length) { + printf("\n\t*lenp = (size_t)(bp - start);\n") >> CFILE; + printf("\treturn (0);\n") >> CFILE; + } + printf("}\n\n") >> CFILE; +} + +function emit_unmarshal() +{ + pi = 1; + p[pi++] = "int "; + function_name = sprintf("%s_unmarshal", base_name); + p[pi++] = function_name; + p[pi++] = " __P((ENV *, "; + if (version) + p[pi++] = sprintf("u_int32_t, "); + if (alloc) + p[pi++] = sprintf("%s **, u_int8_t *, ", typedef_name); + else + p[pi++] = sprintf("%s *, u_int8_t *, ", typedef_name); + p[pi++] = sprintf("size_t, u_int8_t **));"); + proto_format(p, CFILE); + + printf("int\n") >> CFILE; + if (alloc) + arg_name = "argpp"; + else + arg_name = "argp"; + printf("%s(env, ", function_name) >> CFILE; + if (version) + printf("version, ") >> CFILE; + printf("%s, bp, ", arg_name) >> CFILE; + printf("max, nextp)\n") >> CFILE; + printf("\tENV *env;\n") >> CFILE; + if (version) + printf("\tu_int32_t version;\n") >> CFILE; + if (alloc) + printf("\t%s **argpp;\n", typedef_name) >> CFILE; + else + printf("\t%s *argp;\n", typedef_name) >> CFILE; + printf("\tu_int8_t *bp;\n") >> CFILE; + printf("\tsize_t max;\n") >> CFILE; + printf("\tu_int8_t **nextp;\n") >> CFILE; + printf("{\n") >> CFILE; + has_locals = 0; + if (has_dbt) { + printf("\tsize_t needed;\n") >> CFILE; + has_locals = 1; + } + if (alloc) { + printf("\t%s *argp;\n", typedef_name) >> CFILE; + printf("\tint ret;\n") >> CFILE; + has_locals = 1; + } + if (version) { + printf("\tint copy_only;\n") >> CFILE; + has_locals = 1; + } + if (has_locals) + printf("\n") >> CFILE; + + # Check that input byte buffer is long enough. + # + if (has_dbt) { + printf("\tneeded = %s;\n", msg_size_name) >> CFILE; + printf("\tif (max < needed)\n") >> CFILE; + } else + printf("\tif (max < %s)\n", msg_size_name) >> CFILE; + printf("\t\tgoto too_few;\n") >> CFILE; + + if (alloc) { + printf( \ + "\tif ((ret = __os_malloc(env, sizeof(*argp), &argp)) != 0)\n") \ + >> CFILE; + printf("\t\treturn (ret);\n\n") >> CFILE; + } + if (version) { + printf("\tcopy_only = 0;\n") >> CFILE; + printf("\tif (version < DB_REPVERSION_47)\n") >> CFILE; + printf("\t\tcopy_only = 1;\n") >> CFILE; + } + + for (i = 0; i < nvars; i++) { + if (types[i] == "u_int32_t" || types[i] == "db_pgno_t") { + if (version) { + printf("\tif (copy_only) {\n") >> CFILE; + printf(\ + "\t\tmemcpy(&argp->%s, bp, sizeof(u_int32_t));\n", vars[i]) >> CFILE; + printf(\ + "\t\tbp += sizeof(u_int32_t);\n") >> CFILE; + printf("\t} else\n\t") >> CFILE; + } + printf("\tDB_NTOHL_COPYIN(env, argp->%s, bp);\n", \ + vars[i]) >> CFILE; + } else if (types[i] == "u_int16_t") { + if (version) { + printf("\tif (copy_only) {\n") >> CFILE; + printf(\ + "\t\tmemcpy(&argp->%s, bp, sizeof(u_int16_t));\n", vars[i]) >> CFILE; + printf(\ + "\t\tbp += sizeof(u_int16_t);\n") >> CFILE; + printf("\t} else\n\t") >> CFILE; + } + printf("\tDB_NTOHS_COPYIN(env, argp->%s, bp);\n", \ + vars[i]) >> CFILE; + } else if (types[i] == "u_int8_t") { + printf(\ + "\targp->%s = *bp++;\n", vars[i]) >> CFILE; + } else if (types[i] == "DB_LSN") { + if (version) { + printf("\tif (copy_only) {\n") >> CFILE; + printf(\ + "\t\tmemcpy(&argp->%s.file, bp, sizeof(u_int32_t));\n", vars[i]) >> CFILE; + printf(\ + "\t\tbp += sizeof(u_int32_t);\n") >> CFILE; + printf(\ + "\t\tmemcpy(&argp->%s.offset, bp, sizeof(u_int32_t));\n", vars[i]) >> CFILE; + printf(\ + "\t\tbp += sizeof(u_int32_t);\n") >> CFILE; + printf("\t} else {\n\t") >> CFILE; + } + printf("\tDB_NTOHL_COPYIN(env, argp->%s.file, bp);\n", \ + vars[i]) >> CFILE; + if (version) + printf("\t") >> CFILE; + printf( \ + "\tDB_NTOHL_COPYIN(env, argp->%s.offset, bp);\n", \ + vars[i]) >> CFILE; + if (version) + printf("\t}\n") >> CFILE; + } else if (types[i] == "DBT") { + if (version) { + printf("\tif (copy_only) {\n") >> CFILE; + printf(\ + "\t\tmemcpy(&argp->%s.size, bp, sizeof(u_int32_t));\n", vars[i]) >> CFILE; + printf(\ + "\t\tbp += sizeof(u_int32_t);\n") >> CFILE; + printf("\t} else\n\t") >> CFILE; + } + printf("\tDB_NTOHL_COPYIN(env, argp->%s.size, bp);\n", \ + vars[i]) >> CFILE; + printf("\tif (argp->%s.size == 0)\n", vars[i]) >> CFILE; + printf("\t\targp->%s.data = NULL;\n", vars[i]) >> CFILE; + printf("\telse\n") >> CFILE; + printf("\t\targp->%s.data = bp;\n", vars[i]) >> CFILE; + printf("\tneeded += (size_t)argp->%s.size;\n", \ + vars[i]) >> CFILE; + printf("\tif (max < needed)\n") >> CFILE; + printf("\t\tgoto too_few;\n") >> CFILE; + printf("\tbp += argp->%s.size;\n", vars[i]) >> CFILE; + } else { + printf("unknown field type: %s", types[i]); + exit(1); + } + } + + printf("\n\tif (nextp != NULL)\n") >> CFILE; + printf("\t\t*nextp = bp;\n") >> CFILE; + if (alloc) { + printf("\t*argpp = argp;\n") >> CFILE; + } + printf("\treturn (0);\n\n") >> CFILE; + + printf("too_few:\n") >> CFILE; + printf("\t__db_errx(env, DB_STR(\"3675\",\n") >> CFILE; + printf("\t \"Not enough input bytes to fill a %s message\"));\n", \ + base_name) >> CFILE; + printf("\treturn (EINVAL);\n") >> CFILE; + printf("}\n\n") >> CFILE; +} + +# proto_format -- +# Pretty-print a function prototype. +function proto_format(p, fp) +{ + printf("/*\n") >> fp; + + s = ""; + for (i = 1; i in p; ++i) + s = s p[i]; + + t = " * PUBLIC: " + if (length(s) + length(t) < 80) + printf("%s%s", t, s) >> fp; + else { + split(s, p, "__P"); + len = length(t) + length(p[1]); + printf("%s%s", t, p[1]) >> fp + + n = split(p[2], comma, ","); + comma[1] = "__P" comma[1]; + for (i = 1; i <= n; i++) { + if (len + length(comma[i]) > 70) { + printf("\n * PUBLIC: ") >> fp; + len = 0; + } + printf("%s%s", comma[i], i == n ? "" : ",") >> fp; + len += length(comma[i]) + 2; + } + } + printf("\n */\n") >> fp; + delete p; +} diff -r 000000000000 -r a1985f14b030 dist/install.sh --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dist/install.sh Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,26 @@ +#!/bin/sh +# +# Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. +# +# This code 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 General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. +# + +echo >&2 "No suitable 'install' command found.'" +exit 1 diff -r 000000000000 -r a1985f14b030 dist/ltmain.sh --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dist/ltmain.sh Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,9636 @@ + +# libtool (GNU libtool) 2.4 +# Written by Gordon Matzigkeit , 1996 + +# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, 2006, +# 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. +# This is free software; see the source for copying conditions. There is NO +# warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + +# GNU Libtool is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# As a special exception to the GNU General Public License, +# if you distribute this file as part of a program or library that +# is built using GNU Libtool, you may include this file under the +# same distribution terms that you use for the rest of that program. +# +# GNU Libtool 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 +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Libtool; see the file COPYING. If not, a copy +# can be downloaded from http://www.gnu.org/licenses/gpl.html, +# or obtained by writing to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +# Usage: $progname [OPTION]... [MODE-ARG]... +# +# Provide generalized library-building support services. +# +# --config show all configuration variables +# --debug enable verbose shell tracing +# -n, --dry-run display commands without modifying any files +# --features display basic configuration information and exit +# --mode=MODE use operation mode MODE +# --preserve-dup-deps don't remove duplicate dependency libraries +# --quiet, --silent don't print informational messages +# --no-quiet, --no-silent +# print informational messages (default) +# --tag=TAG use configuration variables from tag TAG +# -v, --verbose print more informational messages than default +# --no-verbose don't print the extra informational messages +# --version print version information +# -h, --help, --help-all print short, long, or detailed help message +# +# MODE must be one of the following: +# +# clean remove files from the build directory +# compile compile a source file into a libtool object +# execute automatically set library path, then run a program +# finish complete the installation of libtool libraries +# install install libraries or executables +# link create a library or an executable +# uninstall remove libraries from an installed directory +# +# MODE-ARGS vary depending on the MODE. When passed as first option, +# `--mode=MODE' may be abbreviated as `MODE' or a unique abbreviation of that. +# Try `$progname --help --mode=MODE' for a more detailed description of MODE. +# +# When reporting a bug, please describe a test case to reproduce it and +# include the following information: +# +# host-triplet: $host +# shell: $SHELL +# compiler: $LTCC +# compiler flags: $LTCFLAGS +# linker: $LD (gnu? $with_gnu_ld) +# $progname: (GNU libtool) 2.4 +# automake: $automake_version +# autoconf: $autoconf_version +# +# Report bugs to . +# GNU libtool home page: . +# General help using GNU software: . + +PROGRAM=libtool +PACKAGE=libtool +VERSION=2.4 +TIMESTAMP="" +package_revision=1.3293 + +# 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+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else + case `(set -o) 2>/dev/null` in *posix*) set -o posix;; esac +fi +BIN_SH=xpg4; export BIN_SH # for Tru64 +DUALCASE=1; export DUALCASE # for MKS sh + +# A function that is used when there is no print builtin or printf. +func_fallback_echo () +{ + eval 'cat <<_LTECHO_EOF +$1 +_LTECHO_EOF' +} + +# NLS nuisances: We save the old values to restore during execute mode. +lt_user_locale= +lt_safe_locale= +for lt_var in LANG LANGUAGE LC_ALL LC_CTYPE LC_COLLATE LC_MESSAGES +do + eval "if test \"\${$lt_var+set}\" = set; then + save_$lt_var=\$$lt_var + $lt_var=C + export $lt_var + lt_user_locale=\"$lt_var=\\\$save_\$lt_var; \$lt_user_locale\" + lt_safe_locale=\"$lt_var=C; \$lt_safe_locale\" + fi" +done +LC_ALL=C +LANGUAGE=C +export LANGUAGE LC_ALL + +$lt_unset CDPATH + + +# Work around backward compatibility issue on IRIX 6.5. On IRIX 6.4+, sh +# is ksh but when the shell is invoked as "sh" and the current value of +# the _XPG environment variable is not equal to 1 (one), the special +# positional parameter $0, within a function call, is the name of the +# function. +progpath="$0" + + + +: ${CP="cp -f"} +test "${ECHO+set}" = set || ECHO=${as_echo-'printf %s\n'} +: ${EGREP="grep -E"} +: ${FGREP="grep -F"} +: ${GREP="grep"} +: ${LN_S="ln -s"} +: ${MAKE="make"} +: ${MKDIR="mkdir"} +: ${MV="mv -f"} +: ${RM="rm -f"} +: ${SED="sed"} +: ${SHELL="${CONFIG_SHELL-/bin/sh}"} +: ${Xsed="$SED -e 1s/^X//"} + +# Global variables: +EXIT_SUCCESS=0 +EXIT_FAILURE=1 +EXIT_MISMATCH=63 # $? = 63 is used to indicate version mismatch to missing. +EXIT_SKIP=77 # $? = 77 is used to indicate a skipped test to automake. + +exit_status=$EXIT_SUCCESS + +# Make sure IFS has a sensible default +lt_nl=' +' +IFS=" $lt_nl" + +dirname="s,/[^/]*$,," +basename="s,^.*/,," + +# func_dirname file append nondir_replacement +# Compute the dirname of FILE. If nonempty, add APPEND to the result, +# otherwise set result to NONDIR_REPLACEMENT. +func_dirname () +{ + func_dirname_result=`$ECHO "${1}" | $SED "$dirname"` + if test "X$func_dirname_result" = "X${1}"; then + func_dirname_result="${3}" + else + func_dirname_result="$func_dirname_result${2}" + fi +} # func_dirname may be replaced by extended shell implementation + + +# func_basename file +func_basename () +{ + func_basename_result=`$ECHO "${1}" | $SED "$basename"` +} # func_basename may be replaced by extended shell implementation + + +# func_dirname_and_basename file append nondir_replacement +# perform func_basename and func_dirname in a single function +# call: +# dirname: Compute the dirname of FILE. If nonempty, +# add APPEND to the result, otherwise set result +# to NONDIR_REPLACEMENT. +# value returned in "$func_dirname_result" +# basename: Compute filename of FILE. +# value retuned in "$func_basename_result" +# Implementation must be kept synchronized with func_dirname +# and func_basename. For efficiency, we do not delegate to +# those functions but instead duplicate the functionality here. +func_dirname_and_basename () +{ + # Extract subdirectory from the argument. + func_dirname_result=`$ECHO "${1}" | $SED -e "$dirname"` + if test "X$func_dirname_result" = "X${1}"; then + func_dirname_result="${3}" + else + func_dirname_result="$func_dirname_result${2}" + fi + func_basename_result=`$ECHO "${1}" | $SED -e "$basename"` +} # func_dirname_and_basename may be replaced by extended shell implementation + + +# func_stripname prefix suffix name +# strip PREFIX and SUFFIX off of NAME. +# PREFIX and SUFFIX must not contain globbing or regex special +# characters, hashes, percent signs, but SUFFIX may contain a leading +# dot (in which case that matches only a dot). +# func_strip_suffix prefix name +func_stripname () +{ + case ${2} in + .*) func_stripname_result=`$ECHO "${3}" | $SED "s%^${1}%%; s%\\\\${2}\$%%"`;; + *) func_stripname_result=`$ECHO "${3}" | $SED "s%^${1}%%; s%${2}\$%%"`;; + esac +} # func_stripname may be replaced by extended shell implementation + + +# These SED scripts presuppose an absolute path with a trailing slash. +pathcar='s,^/\([^/]*\).*$,\1,' +pathcdr='s,^/[^/]*,,' +removedotparts=':dotsl + s@/\./@/@g + t dotsl + s,/\.$,/,' +collapseslashes='s@/\{1,\}@/@g' +finalslash='s,/*$,/,' + +# func_normal_abspath PATH +# Remove doubled-up and trailing slashes, "." path components, +# and cancel out any ".." path components in PATH after making +# it an absolute path. +# value returned in "$func_normal_abspath_result" +func_normal_abspath () +{ + # Start from root dir and reassemble the path. + func_normal_abspath_result= + func_normal_abspath_tpath=$1 + func_normal_abspath_altnamespace= + case $func_normal_abspath_tpath in + "") + # Empty path, that just means $cwd. + func_stripname '' '/' "`pwd`" + func_normal_abspath_result=$func_stripname_result + return + ;; + # The next three entries are used to spot a run of precisely + # two leading slashes without using negated character classes; + # we take advantage of case's first-match behaviour. + ///*) + # Unusual form of absolute path, do nothing. + ;; + //*) + # Not necessarily an ordinary path; POSIX reserves leading '//' + # and for example Cygwin uses it to access remote file shares + # over CIFS/SMB, so we conserve a leading double slash if found. + func_normal_abspath_altnamespace=/ + ;; + /*) + # Absolute path, do nothing. + ;; + *) + # Relative path, prepend $cwd. + func_normal_abspath_tpath=`pwd`/$func_normal_abspath_tpath + ;; + esac + # Cancel out all the simple stuff to save iterations. We also want + # the path to end with a slash for ease of parsing, so make sure + # there is one (and only one) here. + func_normal_abspath_tpath=`$ECHO "$func_normal_abspath_tpath" | $SED \ + -e "$removedotparts" -e "$collapseslashes" -e "$finalslash"` + while :; do + # Processed it all yet? + if test "$func_normal_abspath_tpath" = / ; then + # If we ascended to the root using ".." the result may be empty now. + if test -z "$func_normal_abspath_result" ; then + func_normal_abspath_result=/ + fi + break + fi + func_normal_abspath_tcomponent=`$ECHO "$func_normal_abspath_tpath" | $SED \ + -e "$pathcar"` + func_normal_abspath_tpath=`$ECHO "$func_normal_abspath_tpath" | $SED \ + -e "$pathcdr"` + # Figure out what to do with it + case $func_normal_abspath_tcomponent in + "") + # Trailing empty path component, ignore it. + ;; + ..) + # Parent dir; strip last assembled component from result. + func_dirname "$func_normal_abspath_result" + func_normal_abspath_result=$func_dirname_result + ;; + *) + # Actual path component, append it. + func_normal_abspath_result=$func_normal_abspath_result/$func_normal_abspath_tcomponent + ;; + esac + done + # Restore leading double-slash if one was found on entry. + func_normal_abspath_result=$func_normal_abspath_altnamespace$func_normal_abspath_result +} + +# func_relative_path SRCDIR DSTDIR +# generates a relative path from SRCDIR to DSTDIR, with a trailing +# slash if non-empty, suitable for immediately appending a filename +# without needing to append a separator. +# value returned in "$func_relative_path_result" +func_relative_path () +{ + func_relative_path_result= + func_normal_abspath "$1" + func_relative_path_tlibdir=$func_normal_abspath_result + func_normal_abspath "$2" + func_relative_path_tbindir=$func_normal_abspath_result + + # Ascend the tree starting from libdir + while :; do + # check if we have found a prefix of bindir + case $func_relative_path_tbindir in + $func_relative_path_tlibdir) + # found an exact match + func_relative_path_tcancelled= + break + ;; + $func_relative_path_tlibdir*) + # found a matching prefix + func_stripname "$func_relative_path_tlibdir" '' "$func_relative_path_tbindir" + func_relative_path_tcancelled=$func_stripname_result + if test -z "$func_relative_path_result"; then + func_relative_path_result=. + fi + break + ;; + *) + func_dirname $func_relative_path_tlibdir + func_relative_path_tlibdir=${func_dirname_result} + if test "x$func_relative_path_tlibdir" = x ; then + # Have to descend all the way to the root! + func_relative_path_result=../$func_relative_path_result + func_relative_path_tcancelled=$func_relative_path_tbindir + break + fi + func_relative_path_result=../$func_relative_path_result + ;; + esac + done + + # Now calculate path; take care to avoid doubling-up slashes. + func_stripname '' '/' "$func_relative_path_result" + func_relative_path_result=$func_stripname_result + func_stripname '/' '/' "$func_relative_path_tcancelled" + if test "x$func_stripname_result" != x ; then + func_relative_path_result=${func_relative_path_result}/${func_stripname_result} + fi + + # Normalisation. If bindir is libdir, return empty string, + # else relative path ending with a slash; either way, target + # file name can be directly appended. + if test ! -z "$func_relative_path_result"; then + func_stripname './' '' "$func_relative_path_result/" + func_relative_path_result=$func_stripname_result + fi +} + +# The name of this program: +func_dirname_and_basename "$progpath" +progname=$func_basename_result + +# Make sure we have an absolute path for reexecution: +case $progpath in + [\\/]*|[A-Za-z]:\\*) ;; + *[\\/]*) + progdir=$func_dirname_result + progdir=`cd "$progdir" && pwd` + progpath="$progdir/$progname" + ;; + *) + save_IFS="$IFS" + IFS=: + for progdir in $PATH; do + IFS="$save_IFS" + test -x "$progdir/$progname" && break + done + IFS="$save_IFS" + test -n "$progdir" || progdir=`pwd` + progpath="$progdir/$progname" + ;; +esac + +# Sed substitution that helps us do robust quoting. It backslashifies +# metacharacters that are still active within double-quoted strings. +Xsed="${SED}"' -e 1s/^X//' +sed_quote_subst='s/\([`"$\\]\)/\\\1/g' + +# Same as above, but do not quote variable references. +double_quote_subst='s/\(["`\\]\)/\\\1/g' + +# Sed substitution that turns a string into a regex matching for the +# string literally. +sed_make_literal_regex='s,[].[^$\\*\/],\\&,g' + +# Sed substitution that converts a w32 file name or path +# which contains forward slashes, into one that contains +# (escaped) backslashes. A very naive implementation. +lt_sed_naive_backslashify='s|\\\\*|\\|g;s|/|\\|g;s|\\|\\\\|g' + +# Re-`\' parameter expansions in output of double_quote_subst that were +# `\'-ed in input to the same. If an odd number of `\' preceded a '$' +# in input to double_quote_subst, that '$' was protected from expansion. +# Since each input `\' is now two `\'s, look for any number of runs of +# four `\'s followed by two `\'s and then a '$'. `\' that '$'. +bs='\\' +bs2='\\\\' +bs4='\\\\\\\\' +dollar='\$' +sed_double_backslash="\ + s/$bs4/&\\ +/g + s/^$bs2$dollar/$bs&/ + s/\\([^$bs]\\)$bs2$dollar/\\1$bs2$bs$dollar/g + s/\n//g" + +# Standard options: +opt_dry_run=false +opt_help=false +opt_quiet=false +opt_verbose=false +opt_warning=: + +# func_echo arg... +# Echo program name prefixed message, along with the current mode +# name if it has been set yet. +func_echo () +{ + $ECHO "$progname: ${opt_mode+$opt_mode: }$*" +} + +# func_verbose arg... +# Echo program name prefixed message in verbose mode only. +func_verbose () +{ + $opt_verbose && func_echo ${1+"$@"} + + # A bug in bash halts the script if the last line of a function + # fails when set -e is in force, so we need another command to + # work around that: + : +} + +# func_echo_all arg... +# Invoke $ECHO with all args, space-separated. +func_echo_all () +{ + $ECHO "$*" +} + +# func_error arg... +# Echo program name prefixed message to standard error. +func_error () +{ + $ECHO "$progname: ${opt_mode+$opt_mode: }"${1+"$@"} 1>&2 +} + +# func_warning arg... +# Echo program name prefixed warning message to standard error. +func_warning () +{ + $opt_warning && $ECHO "$progname: ${opt_mode+$opt_mode: }warning: "${1+"$@"} 1>&2 + + # bash bug again: + : +} + +# func_fatal_error arg... +# Echo program name prefixed message to standard error, and exit. +func_fatal_error () +{ + func_error ${1+"$@"} + exit $EXIT_FAILURE +} + +# func_fatal_help arg... +# Echo program name prefixed message to standard error, followed by +# a help hint, and exit. +func_fatal_help () +{ + func_error ${1+"$@"} + func_fatal_error "$help" +} +help="Try \`$progname --help' for more information." ## default + + +# func_grep expression filename +# Check whether EXPRESSION matches any line of FILENAME, without output. +func_grep () +{ + $GREP "$1" "$2" >/dev/null 2>&1 +} + + +# func_mkdir_p directory-path +# Make sure the entire path to DIRECTORY-PATH is available. +func_mkdir_p () +{ + my_directory_path="$1" + my_dir_list= + + if test -n "$my_directory_path" && test "$opt_dry_run" != ":"; then + + # Protect directory names starting with `-' + case $my_directory_path in + -*) my_directory_path="./$my_directory_path" ;; + esac + + # While some portion of DIR does not yet exist... + while test ! -d "$my_directory_path"; do + # ...make a list in topmost first order. Use a colon delimited + # list incase some portion of path contains whitespace. + my_dir_list="$my_directory_path:$my_dir_list" + + # If the last portion added has no slash in it, the list is done + case $my_directory_path in */*) ;; *) break ;; esac + + # ...otherwise throw away the child directory and loop + my_directory_path=`$ECHO "$my_directory_path" | $SED -e "$dirname"` + done + my_dir_list=`$ECHO "$my_dir_list" | $SED 's,:*$,,'` + + save_mkdir_p_IFS="$IFS"; IFS=':' + for my_dir in $my_dir_list; do + IFS="$save_mkdir_p_IFS" + # mkdir can fail with a `File exist' error if two processes + # try to create one of the directories concurrently. Don't + # stop in that case! + $MKDIR "$my_dir" 2>/dev/null || : + done + IFS="$save_mkdir_p_IFS" + + # Bail out if we (or some other process) failed to create a directory. + test -d "$my_directory_path" || \ + func_fatal_error "Failed to create \`$1'" + fi +} + + +# func_mktempdir [string] +# Make a temporary directory that won't clash with other running +# libtool processes, and avoids race conditions if possible. If +# given, STRING is the basename for that directory. +func_mktempdir () +{ + my_template="${TMPDIR-/tmp}/${1-$progname}" + + if test "$opt_dry_run" = ":"; then + # Return a directory name, but don't create it in dry-run mode + my_tmpdir="${my_template}-$$" + else + + # If mktemp works, use that first and foremost + my_tmpdir=`mktemp -d "${my_template}-XXXXXXXX" 2>/dev/null` + + if test ! -d "$my_tmpdir"; then + # Failing that, at least try and use $RANDOM to avoid a race + my_tmpdir="${my_template}-${RANDOM-0}$$" + + save_mktempdir_umask=`umask` + umask 0077 + $MKDIR "$my_tmpdir" + umask $save_mktempdir_umask + fi + + # If we're not in dry-run mode, bomb out on failure + test -d "$my_tmpdir" || \ + func_fatal_error "cannot create temporary directory \`$my_tmpdir'" + fi + + $ECHO "$my_tmpdir" +} + + +# func_quote_for_eval arg +# Aesthetically quote ARG to be evaled later. +# This function returns two values: FUNC_QUOTE_FOR_EVAL_RESULT +# is double-quoted, suitable for a subsequent eval, whereas +# FUNC_QUOTE_FOR_EVAL_UNQUOTED_RESULT has merely all characters +# which are still active within double quotes backslashified. +func_quote_for_eval () +{ + case $1 in + *[\\\`\"\$]*) + func_quote_for_eval_unquoted_result=`$ECHO "$1" | $SED "$sed_quote_subst"` ;; + *) + func_quote_for_eval_unquoted_result="$1" ;; + esac + + case $func_quote_for_eval_unquoted_result in + # Double-quote args containing shell metacharacters to delay + # word splitting, command substitution and and variable + # expansion for a subsequent eval. + # Many Bourne shells cannot handle close brackets correctly + # in scan sets, so we specify it separately. + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + func_quote_for_eval_result="\"$func_quote_for_eval_unquoted_result\"" + ;; + *) + func_quote_for_eval_result="$func_quote_for_eval_unquoted_result" + esac +} + + +# func_quote_for_expand arg +# Aesthetically quote ARG to be evaled later; same as above, +# but do not quote variable references. +func_quote_for_expand () +{ + case $1 in + *[\\\`\"]*) + my_arg=`$ECHO "$1" | $SED \ + -e "$double_quote_subst" -e "$sed_double_backslash"` ;; + *) + my_arg="$1" ;; + esac + + case $my_arg in + # Double-quote args containing shell metacharacters to delay + # word splitting and command substitution for a subsequent eval. + # Many Bourne shells cannot handle close brackets correctly + # in scan sets, so we specify it separately. + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + my_arg="\"$my_arg\"" + ;; + esac + + func_quote_for_expand_result="$my_arg" +} + + +# func_show_eval cmd [fail_exp] +# Unless opt_silent is true, then output CMD. Then, if opt_dryrun is +# not true, evaluate CMD. If the evaluation of CMD fails, and FAIL_EXP +# is given, then evaluate it. +func_show_eval () +{ + my_cmd="$1" + my_fail_exp="${2-:}" + + ${opt_silent-false} || { + func_quote_for_expand "$my_cmd" + eval "func_echo $func_quote_for_expand_result" + } + + if ${opt_dry_run-false}; then :; else + eval "$my_cmd" + my_status=$? + if test "$my_status" -eq 0; then :; else + eval "(exit $my_status); $my_fail_exp" + fi + fi +} + + +# func_show_eval_locale cmd [fail_exp] +# Unless opt_silent is true, then output CMD. Then, if opt_dryrun is +# not true, evaluate CMD. If the evaluation of CMD fails, and FAIL_EXP +# is given, then evaluate it. Use the saved locale for evaluation. +func_show_eval_locale () +{ + my_cmd="$1" + my_fail_exp="${2-:}" + + ${opt_silent-false} || { + func_quote_for_expand "$my_cmd" + eval "func_echo $func_quote_for_expand_result" + } + + if ${opt_dry_run-false}; then :; else + eval "$lt_user_locale + $my_cmd" + my_status=$? + eval "$lt_safe_locale" + if test "$my_status" -eq 0; then :; else + eval "(exit $my_status); $my_fail_exp" + fi + fi +} + +# func_tr_sh +# Turn $1 into a string suitable for a shell variable name. +# Result is stored in $func_tr_sh_result. All characters +# not in the set a-zA-Z0-9_ are replaced with '_'. Further, +# if $1 begins with a digit, a '_' is prepended as well. +func_tr_sh () +{ + case $1 in + [0-9]* | *[!a-zA-Z0-9_]*) + func_tr_sh_result=`$ECHO "$1" | $SED 's/^\([0-9]\)/_\1/; s/[^a-zA-Z0-9_]/_/g'` + ;; + * ) + func_tr_sh_result=$1 + ;; + esac +} + + +# func_version +# Echo version message to standard output and exit. +func_version () +{ + $opt_debug + + $SED -n '/(C)/!b go + :more + /\./!{ + N + s/\n# / / + b more + } + :go + /^# '$PROGRAM' (GNU /,/# warranty; / { + s/^# // + s/^# *$// + s/\((C)\)[ 0-9,-]*\( [1-9][0-9]*\)/\1\2/ + p + }' < "$progpath" + exit $? +} + +# func_usage +# Echo short help message to standard output and exit. +func_usage () +{ + $opt_debug + + $SED -n '/^# Usage:/,/^# *.*--help/ { + s/^# // + s/^# *$// + s/\$progname/'$progname'/ + p + }' < "$progpath" + echo + $ECHO "run \`$progname --help | more' for full usage" + exit $? +} + +# func_help [NOEXIT] +# Echo long help message to standard output and exit, +# unless 'noexit' is passed as argument. +func_help () +{ + $opt_debug + + $SED -n '/^# Usage:/,/# Report bugs to/ { + :print + s/^# // + s/^# *$// + s*\$progname*'$progname'* + s*\$host*'"$host"'* + s*\$SHELL*'"$SHELL"'* + s*\$LTCC*'"$LTCC"'* + s*\$LTCFLAGS*'"$LTCFLAGS"'* + s*\$LD*'"$LD"'* + s/\$with_gnu_ld/'"$with_gnu_ld"'/ + s/\$automake_version/'"`(automake --version) 2>/dev/null |$SED 1q`"'/ + s/\$autoconf_version/'"`(autoconf --version) 2>/dev/null |$SED 1q`"'/ + p + d + } + /^# .* home page:/b print + /^# General help using/b print + ' < "$progpath" + ret=$? + if test -z "$1"; then + exit $ret + fi +} + +# func_missing_arg argname +# Echo program name prefixed message to standard error and set global +# exit_cmd. +func_missing_arg () +{ + $opt_debug + + func_error "missing argument for $1." + exit_cmd=exit +} + + +# func_split_short_opt shortopt +# Set func_split_short_opt_name and func_split_short_opt_arg shell +# variables after splitting SHORTOPT after the 2nd character. +func_split_short_opt () +{ + my_sed_short_opt='1s/^\(..\).*$/\1/;q' + my_sed_short_rest='1s/^..\(.*\)$/\1/;q' + + func_split_short_opt_name=`$ECHO "$1" | $SED "$my_sed_short_opt"` + func_split_short_opt_arg=`$ECHO "$1" | $SED "$my_sed_short_rest"` +} # func_split_short_opt may be replaced by extended shell implementation + + +# func_split_long_opt longopt +# Set func_split_long_opt_name and func_split_long_opt_arg shell +# variables after splitting LONGOPT at the `=' sign. +func_split_long_opt () +{ + my_sed_long_opt='1s/^\(--[^=]*\)=.*/\1/;q' + my_sed_long_arg='1s/^--[^=]*=//' + + func_split_long_opt_name=`$ECHO "$1" | $SED "$my_sed_long_opt"` + func_split_long_opt_arg=`$ECHO "$1" | $SED "$my_sed_long_arg"` +} # func_split_long_opt may be replaced by extended shell implementation + +exit_cmd=: + + + + + +magic="%%%MAGIC variable%%%" +magic_exe="%%%MAGIC EXE variable%%%" + +# Global variables. +nonopt= +preserve_args= +lo2o="s/\\.lo\$/.${objext}/" +o2lo="s/\\.${objext}\$/.lo/" +extracted_archives= +extracted_serial=0 + +# If this variable is set in any of the actions, the command in it +# will be execed at the end. This prevents here-documents from being +# left over by shells. +exec_cmd= + +# func_append var value +# Append VALUE to the end of shell variable VAR. +func_append () +{ + eval "${1}=\$${1}\${2}" +} # func_append may be replaced by extended shell implementation + +# func_append_quoted var value +# Quote VALUE and append to the end of shell variable VAR, separated +# by a space. +func_append_quoted () +{ + func_quote_for_eval "${2}" + eval "${1}=\$${1}\\ \$func_quote_for_eval_result" +} # func_append_quoted may be replaced by extended shell implementation + + +# func_arith arithmetic-term... +func_arith () +{ + func_arith_result=`expr "${@}"` +} # func_arith may be replaced by extended shell implementation + + +# func_len string +# STRING may not start with a hyphen. +func_len () +{ + func_len_result=`expr "${1}" : ".*" 2>/dev/null || echo $max_cmd_len` +} # func_len may be replaced by extended shell implementation + + +# func_lo2o object +func_lo2o () +{ + func_lo2o_result=`$ECHO "${1}" | $SED "$lo2o"` +} # func_lo2o may be replaced by extended shell implementation + + +# func_xform libobj-or-source +func_xform () +{ + func_xform_result=`$ECHO "${1}" | $SED 's/\.[^.]*$/.lo/'` +} # func_xform may be replaced by extended shell implementation + + +# func_fatal_configuration arg... +# Echo program name prefixed message to standard error, followed by +# a configuration failure hint, and exit. +func_fatal_configuration () +{ + func_error ${1+"$@"} + func_error "See the $PACKAGE documentation for more information." + func_fatal_error "Fatal configuration error." +} + + +# func_config +# Display the configuration for all the tags in this script. +func_config () +{ + re_begincf='^# ### BEGIN LIBTOOL' + re_endcf='^# ### END LIBTOOL' + + # Default configuration. + $SED "1,/$re_begincf CONFIG/d;/$re_endcf CONFIG/,\$d" < "$progpath" + + # Now print the configurations for the tags. + for tagname in $taglist; do + $SED -n "/$re_begincf TAG CONFIG: $tagname\$/,/$re_endcf TAG CONFIG: $tagname\$/p" < "$progpath" + done + + exit $? +} + +# func_features +# Display the features supported by this script. +func_features () +{ + echo "host: $host" + if test "$build_libtool_libs" = yes; then + echo "enable shared libraries" + else + echo "disable shared libraries" + fi + if test "$build_old_libs" = yes; then + echo "enable static libraries" + else + echo "disable static libraries" + fi + + exit $? +} + +# func_enable_tag tagname +# Verify that TAGNAME is valid, and either flag an error and exit, or +# enable the TAGNAME tag. We also add TAGNAME to the global $taglist +# variable here. +func_enable_tag () +{ + # Global variable: + tagname="$1" + + re_begincf="^# ### BEGIN LIBTOOL TAG CONFIG: $tagname\$" + re_endcf="^# ### END LIBTOOL TAG CONFIG: $tagname\$" + sed_extractcf="/$re_begincf/,/$re_endcf/p" + + # Validate tagname. + case $tagname in + *[!-_A-Za-z0-9,/]*) + func_fatal_error "invalid tag name: $tagname" + ;; + esac + + # Don't test for the "default" C tag, as we know it's + # there but not specially marked. + case $tagname in + CC) ;; + *) + if $GREP "$re_begincf" "$progpath" >/dev/null 2>&1; then + taglist="$taglist $tagname" + + # Evaluate the configuration. Be careful to quote the path + # and the sed script, to avoid splitting on whitespace, but + # also don't use non-portable quotes within backquotes within + # quotes we have to do it in 2 steps: + extractedcf=`$SED -n -e "$sed_extractcf" < "$progpath"` + eval "$extractedcf" + else + func_error "ignoring unknown tag $tagname" + fi + ;; + esac +} + +# func_check_version_match +# Ensure that we are using m4 macros, and libtool script from the same +# release of libtool. +func_check_version_match () +{ + if test "$package_revision" != "$macro_revision"; then + if test "$VERSION" != "$macro_version"; then + if test -z "$macro_version"; then + cat >&2 <<_LT_EOF +$progname: Version mismatch error. This is $PACKAGE $VERSION, but the +$progname: definition of this LT_INIT comes from an older release. +$progname: You should recreate aclocal.m4 with macros from $PACKAGE $VERSION +$progname: and run autoconf again. +_LT_EOF + else + cat >&2 <<_LT_EOF +$progname: Version mismatch error. This is $PACKAGE $VERSION, but the +$progname: definition of this LT_INIT comes from $PACKAGE $macro_version. +$progname: You should recreate aclocal.m4 with macros from $PACKAGE $VERSION +$progname: and run autoconf again. +_LT_EOF + fi + else + cat >&2 <<_LT_EOF +$progname: Version mismatch error. This is $PACKAGE $VERSION, revision $package_revision, +$progname: but the definition of this LT_INIT comes from revision $macro_revision. +$progname: You should recreate aclocal.m4 with macros from revision $package_revision +$progname: of $PACKAGE $VERSION and run autoconf again. +_LT_EOF + fi + + exit $EXIT_MISMATCH + fi +} + + +# Shorthand for --mode=foo, only valid as the first argument +case $1 in +clean|clea|cle|cl) + shift; set dummy --mode clean ${1+"$@"}; shift + ;; +compile|compil|compi|comp|com|co|c) + shift; set dummy --mode compile ${1+"$@"}; shift + ;; +execute|execut|execu|exec|exe|ex|e) + shift; set dummy --mode execute ${1+"$@"}; shift + ;; +finish|finis|fini|fin|fi|f) + shift; set dummy --mode finish ${1+"$@"}; shift + ;; +install|instal|insta|inst|ins|in|i) + shift; set dummy --mode install ${1+"$@"}; shift + ;; +link|lin|li|l) + shift; set dummy --mode link ${1+"$@"}; shift + ;; +uninstall|uninstal|uninsta|uninst|unins|unin|uni|un|u) + shift; set dummy --mode uninstall ${1+"$@"}; shift + ;; +esac + + + +# Option defaults: +opt_debug=: +opt_dry_run=false +opt_config=false +opt_preserve_dup_deps=false +opt_features=false +opt_finish=false +opt_help=false +opt_help_all=false +opt_silent=: +opt_verbose=: +opt_silent=false +opt_verbose=false + + +# Parse options once, thoroughly. This comes as soon as possible in the +# script to make things like `--version' happen as quickly as we can. +{ + # this just eases exit handling + while test $# -gt 0; do + opt="$1" + shift + case $opt in + --debug|-x) opt_debug='set -x' + func_echo "enabling shell trace mode" + $opt_debug + ;; + --dry-run|--dryrun|-n) + opt_dry_run=: + ;; + --config) + opt_config=: +func_config + ;; + --dlopen|-dlopen) + optarg="$1" + opt_dlopen="${opt_dlopen+$opt_dlopen +}$optarg" + shift + ;; + --preserve-dup-deps) + opt_preserve_dup_deps=: + ;; + --features) + opt_features=: +func_features + ;; + --finish) + opt_finish=: +set dummy --mode finish ${1+"$@"}; shift + ;; + --help) + opt_help=: + ;; + --help-all) + opt_help_all=: +opt_help=': help-all' + ;; + --mode) + test $# = 0 && func_missing_arg $opt && break + optarg="$1" + opt_mode="$optarg" +case $optarg in + # Valid mode arguments: + clean|compile|execute|finish|install|link|relink|uninstall) ;; + + # Catch anything else as an error + *) func_error "invalid argument for $opt" + exit_cmd=exit + break + ;; +esac + shift + ;; + --no-silent|--no-quiet) + opt_silent=false +func_append preserve_args " $opt" + ;; + --no-verbose) + opt_verbose=false +func_append preserve_args " $opt" + ;; + --silent|--quiet) + opt_silent=: +func_append preserve_args " $opt" + opt_verbose=false + ;; + --verbose|-v) + opt_verbose=: +func_append preserve_args " $opt" +opt_silent=false + ;; + --tag) + test $# = 0 && func_missing_arg $opt && break + optarg="$1" + opt_tag="$optarg" +func_append preserve_args " $opt $optarg" +func_enable_tag "$optarg" + shift + ;; + + -\?|-h) func_usage ;; + --help) func_help ;; + --version) func_version ;; + + # Separate optargs to long options: + --*=*) + func_split_long_opt "$opt" + set dummy "$func_split_long_opt_name" "$func_split_long_opt_arg" ${1+"$@"} + shift + ;; + + # Separate non-argument short options: + -\?*|-h*|-n*|-v*) + func_split_short_opt "$opt" + set dummy "$func_split_short_opt_name" "-$func_split_short_opt_arg" ${1+"$@"} + shift + ;; + + --) break ;; + -*) func_fatal_help "unrecognized option \`$opt'" ;; + *) set dummy "$opt" ${1+"$@"}; shift; break ;; + esac + done + + # Validate options: + + # save first non-option argument + if test "$#" -gt 0; then + nonopt="$opt" + shift + fi + + # preserve --debug + test "$opt_debug" = : || func_append preserve_args " --debug" + + case $host in + *cygwin* | *mingw* | *pw32* | *cegcc*) + # don't eliminate duplications in $postdeps and $predeps + opt_duplicate_compiler_generated_deps=: + ;; + *) + opt_duplicate_compiler_generated_deps=$opt_preserve_dup_deps + ;; + esac + + $opt_help || { + # Sanity checks first: + func_check_version_match + + if test "$build_libtool_libs" != yes && test "$build_old_libs" != yes; then + func_fatal_configuration "not configured to build any kind of library" + fi + + # Darwin sucks + eval std_shrext=\"$shrext_cmds\" + + # Only execute mode is allowed to have -dlopen flags. + if test -n "$opt_dlopen" && test "$opt_mode" != execute; then + func_error "unrecognized option \`-dlopen'" + $ECHO "$help" 1>&2 + exit $EXIT_FAILURE + fi + + # Change the help message to a mode-specific one. + generic_help="$help" + help="Try \`$progname --help --mode=$opt_mode' for more information." + } + + + # Bail if the options were screwed + $exit_cmd $EXIT_FAILURE +} + + + + +## ----------- ## +## Main. ## +## ----------- ## + +# func_lalib_p file +# True iff FILE is a libtool `.la' library or `.lo' object file. +# This function is only a basic sanity check; it will hardly flush out +# determined imposters. +func_lalib_p () +{ + test -f "$1" && + $SED -e 4q "$1" 2>/dev/null \ + | $GREP "^# Generated by .*$PACKAGE" > /dev/null 2>&1 +} + +# func_lalib_unsafe_p file +# True iff FILE is a libtool `.la' library or `.lo' object file. +# This function implements the same check as func_lalib_p without +# resorting to external programs. To this end, it redirects stdin and +# closes it afterwards, without saving the original file descriptor. +# As a safety measure, use it only where a negative result would be +# fatal anyway. Works if `file' does not exist. +func_lalib_unsafe_p () +{ + lalib_p=no + if test -f "$1" && test -r "$1" && exec 5<&0 <"$1"; then + for lalib_p_l in 1 2 3 4 + do + read lalib_p_line + case "$lalib_p_line" in + \#\ Generated\ by\ *$PACKAGE* ) lalib_p=yes; break;; + esac + done + exec 0<&5 5<&- + fi + test "$lalib_p" = yes +} + +# func_ltwrapper_script_p file +# True iff FILE is a libtool wrapper script +# This function is only a basic sanity check; it will hardly flush out +# determined imposters. +func_ltwrapper_script_p () +{ + func_lalib_p "$1" +} + +# func_ltwrapper_executable_p file +# True iff FILE is a libtool wrapper executable +# This function is only a basic sanity check; it will hardly flush out +# determined imposters. +func_ltwrapper_executable_p () +{ + func_ltwrapper_exec_suffix= + case $1 in + *.exe) ;; + *) func_ltwrapper_exec_suffix=.exe ;; + esac + $GREP "$magic_exe" "$1$func_ltwrapper_exec_suffix" >/dev/null 2>&1 +} + +# func_ltwrapper_scriptname file +# Assumes file is an ltwrapper_executable +# uses $file to determine the appropriate filename for a +# temporary ltwrapper_script. +func_ltwrapper_scriptname () +{ + func_dirname_and_basename "$1" "" "." + func_stripname '' '.exe' "$func_basename_result" + func_ltwrapper_scriptname_result="$func_dirname_result/$objdir/${func_stripname_result}_ltshwrapper" +} + +# func_ltwrapper_p file +# True iff FILE is a libtool wrapper script or wrapper executable +# This function is only a basic sanity check; it will hardly flush out +# determined imposters. +func_ltwrapper_p () +{ + func_ltwrapper_script_p "$1" || func_ltwrapper_executable_p "$1" +} + + +# func_execute_cmds commands fail_cmd +# Execute tilde-delimited COMMANDS. +# If FAIL_CMD is given, eval that upon failure. +# FAIL_CMD may read-access the current command in variable CMD! +func_execute_cmds () +{ + $opt_debug + save_ifs=$IFS; IFS='~' + for cmd in $1; do + IFS=$save_ifs + eval cmd=\"$cmd\" + func_show_eval "$cmd" "${2-:}" + done + IFS=$save_ifs +} + + +# func_source file +# Source FILE, adding directory component if necessary. +# Note that it is not necessary on cygwin/mingw to append a dot to +# FILE even if both FILE and FILE.exe exist: automatic-append-.exe +# behavior happens only for exec(3), not for open(2)! Also, sourcing +# `FILE.' does not work on cygwin managed mounts. +func_source () +{ + $opt_debug + case $1 in + */* | *\\*) . "$1" ;; + *) . "./$1" ;; + esac +} + + +# func_resolve_sysroot PATH +# Replace a leading = in PATH with a sysroot. Store the result into +# func_resolve_sysroot_result +func_resolve_sysroot () +{ + func_resolve_sysroot_result=$1 + case $func_resolve_sysroot_result in + =*) + func_stripname '=' '' "$func_resolve_sysroot_result" + func_resolve_sysroot_result=$lt_sysroot$func_stripname_result + ;; + esac +} + +# func_replace_sysroot PATH +# If PATH begins with the sysroot, replace it with = and +# store the result into func_replace_sysroot_result. +func_replace_sysroot () +{ + case "$lt_sysroot:$1" in + ?*:"$lt_sysroot"*) + func_stripname "$lt_sysroot" '' "$1" + func_replace_sysroot_result="=$func_stripname_result" + ;; + *) + # Including no sysroot. + func_replace_sysroot_result=$1 + ;; + esac +} + +# func_infer_tag arg +# Infer tagged configuration to use if any are available and +# if one wasn't chosen via the "--tag" command line option. +# Only attempt this if the compiler in the base compile +# command doesn't match the default compiler. +# arg is usually of the form 'gcc ...' +func_infer_tag () +{ + $opt_debug + if test -n "$available_tags" && test -z "$tagname"; then + CC_quoted= + for arg in $CC; do + func_append_quoted CC_quoted "$arg" + done + CC_expanded=`func_echo_all $CC` + CC_quoted_expanded=`func_echo_all $CC_quoted` + case $@ in + # Blanks in the command may have been stripped by the calling shell, + # but not from the CC environment variable when configure was run. + " $CC "* | "$CC "* | " $CC_expanded "* | "$CC_expanded "* | \ + " $CC_quoted"* | "$CC_quoted "* | " $CC_quoted_expanded "* | "$CC_quoted_expanded "*) ;; + # Blanks at the start of $base_compile will cause this to fail + # if we don't check for them as well. + *) + for z in $available_tags; do + if $GREP "^# ### BEGIN LIBTOOL TAG CONFIG: $z$" < "$progpath" > /dev/null; then + # Evaluate the configuration. + eval "`${SED} -n -e '/^# ### BEGIN LIBTOOL TAG CONFIG: '$z'$/,/^# ### END LIBTOOL TAG CONFIG: '$z'$/p' < $progpath`" + CC_quoted= + for arg in $CC; do + # Double-quote args containing other shell metacharacters. + func_append_quoted CC_quoted "$arg" + done + CC_expanded=`func_echo_all $CC` + CC_quoted_expanded=`func_echo_all $CC_quoted` + case "$@ " in + " $CC "* | "$CC "* | " $CC_expanded "* | "$CC_expanded "* | \ + " $CC_quoted"* | "$CC_quoted "* | " $CC_quoted_expanded "* | "$CC_quoted_expanded "*) + # The compiler in the base compile command matches + # the one in the tagged configuration. + # Assume this is the tagged configuration we want. + tagname=$z + break + ;; + esac + fi + done + # If $tagname still isn't set, then no tagged configuration + # was found and let the user know that the "--tag" command + # line option must be used. + if test -z "$tagname"; then + func_echo "unable to infer tagged configuration" + func_fatal_error "specify a tag with \`--tag'" +# else +# func_verbose "using $tagname tagged configuration" + fi + ;; + esac + fi +} + + + +# func_write_libtool_object output_name pic_name nonpic_name +# Create a libtool object file (analogous to a ".la" file), +# but don't create it if we're doing a dry run. +func_write_libtool_object () +{ + write_libobj=${1} + if test "$build_libtool_libs" = yes; then + write_lobj=\'${2}\' + else + write_lobj=none + fi + + if test "$build_old_libs" = yes; then + write_oldobj=\'${3}\' + else + write_oldobj=none + fi + + $opt_dry_run || { + cat >${write_libobj}T </dev/null` + if test "$?" -eq 0 && test -n "${func_convert_core_file_wine_to_w32_tmp}"; then + func_convert_core_file_wine_to_w32_result=`$ECHO "$func_convert_core_file_wine_to_w32_tmp" | + $SED -e "$lt_sed_naive_backslashify"` + else + func_convert_core_file_wine_to_w32_result= + fi + fi +} +# end: func_convert_core_file_wine_to_w32 + + +# func_convert_core_path_wine_to_w32 ARG +# Helper function used by path conversion functions when $build is *nix, and +# $host is mingw, cygwin, or some other w32 environment. Relies on a correctly +# configured wine environment available, with the winepath program in $build's +# $PATH. Assumes ARG has no leading or trailing path separator characters. +# +# ARG is path to be converted from $build format to win32. +# Result is available in $func_convert_core_path_wine_to_w32_result. +# Unconvertible file (directory) names in ARG are skipped; if no directory names +# are convertible, then the result may be empty. +func_convert_core_path_wine_to_w32 () +{ + $opt_debug + # unfortunately, winepath doesn't convert paths, only file names + func_convert_core_path_wine_to_w32_result="" + if test -n "$1"; then + oldIFS=$IFS + IFS=: + for func_convert_core_path_wine_to_w32_f in $1; do + IFS=$oldIFS + func_convert_core_file_wine_to_w32 "$func_convert_core_path_wine_to_w32_f" + if test -n "$func_convert_core_file_wine_to_w32_result" ; then + if test -z "$func_convert_core_path_wine_to_w32_result"; then + func_convert_core_path_wine_to_w32_result="$func_convert_core_file_wine_to_w32_result" + else + func_append func_convert_core_path_wine_to_w32_result ";$func_convert_core_file_wine_to_w32_result" + fi + fi + done + IFS=$oldIFS + fi +} +# end: func_convert_core_path_wine_to_w32 + + +# func_cygpath ARGS... +# Wrapper around calling the cygpath program via LT_CYGPATH. This is used when +# when (1) $build is *nix and Cygwin is hosted via a wine environment; or (2) +# $build is MSYS and $host is Cygwin, or (3) $build is Cygwin. In case (1) or +# (2), returns the Cygwin file name or path in func_cygpath_result (input +# file name or path is assumed to be in w32 format, as previously converted +# from $build's *nix or MSYS format). In case (3), returns the w32 file name +# or path in func_cygpath_result (input file name or path is assumed to be in +# Cygwin format). Returns an empty string on error. +# +# ARGS are passed to cygpath, with the last one being the file name or path to +# be converted. +# +# Specify the absolute *nix (or w32) name to cygpath in the LT_CYGPATH +# environment variable; do not put it in $PATH. +func_cygpath () +{ + $opt_debug + if test -n "$LT_CYGPATH" && test -f "$LT_CYGPATH"; then + func_cygpath_result=`$LT_CYGPATH "$@" 2>/dev/null` + if test "$?" -ne 0; then + # on failure, ensure result is empty + func_cygpath_result= + fi + else + func_cygpath_result= + func_error "LT_CYGPATH is empty or specifies non-existent file: \`$LT_CYGPATH'" + fi +} +#end: func_cygpath + + +# func_convert_core_msys_to_w32 ARG +# Convert file name or path ARG from MSYS format to w32 format. Return +# result in func_convert_core_msys_to_w32_result. +func_convert_core_msys_to_w32 () +{ + $opt_debug + # awkward: cmd appends spaces to result + func_convert_core_msys_to_w32_result=`( cmd //c echo "$1" ) 2>/dev/null | + $SED -e 's/[ ]*$//' -e "$lt_sed_naive_backslashify"` +} +#end: func_convert_core_msys_to_w32 + + +# func_convert_file_check ARG1 ARG2 +# Verify that ARG1 (a file name in $build format) was converted to $host +# format in ARG2. Otherwise, emit an error message, but continue (resetting +# func_to_host_file_result to ARG1). +func_convert_file_check () +{ + $opt_debug + if test -z "$2" && test -n "$1" ; then + func_error "Could not determine host file name corresponding to" + func_error " \`$1'" + func_error "Continuing, but uninstalled executables may not work." + # Fallback: + func_to_host_file_result="$1" + fi +} +# end func_convert_file_check + + +# func_convert_path_check FROM_PATHSEP TO_PATHSEP FROM_PATH TO_PATH +# Verify that FROM_PATH (a path in $build format) was converted to $host +# format in TO_PATH. Otherwise, emit an error message, but continue, resetting +# func_to_host_file_result to a simplistic fallback value (see below). +func_convert_path_check () +{ + $opt_debug + if test -z "$4" && test -n "$3"; then + func_error "Could not determine the host path corresponding to" + func_error " \`$3'" + func_error "Continuing, but uninstalled executables may not work." + # Fallback. This is a deliberately simplistic "conversion" and + # should not be "improved". See libtool.info. + if test "x$1" != "x$2"; then + lt_replace_pathsep_chars="s|$1|$2|g" + func_to_host_path_result=`echo "$3" | + $SED -e "$lt_replace_pathsep_chars"` + else + func_to_host_path_result="$3" + fi + fi +} +# end func_convert_path_check + + +# func_convert_path_front_back_pathsep FRONTPAT BACKPAT REPL ORIG +# Modifies func_to_host_path_result by prepending REPL if ORIG matches FRONTPAT +# and appending REPL if ORIG matches BACKPAT. +func_convert_path_front_back_pathsep () +{ + $opt_debug + case $4 in + $1 ) func_to_host_path_result="$3$func_to_host_path_result" + ;; + esac + case $4 in + $2 ) func_append func_to_host_path_result "$3" + ;; + esac +} +# end func_convert_path_front_back_pathsep + + +################################################## +# $build to $host FILE NAME CONVERSION FUNCTIONS # +################################################## +# invoked via `$to_host_file_cmd ARG' +# +# In each case, ARG is the path to be converted from $build to $host format. +# Result will be available in $func_to_host_file_result. + + +# func_to_host_file ARG +# Converts the file name ARG from $build format to $host format. Return result +# in func_to_host_file_result. +func_to_host_file () +{ + $opt_debug + $to_host_file_cmd "$1" +} +# end func_to_host_file + + +# func_to_tool_file ARG LAZY +# converts the file name ARG from $build format to toolchain format. Return +# result in func_to_tool_file_result. If the conversion in use is listed +# in (the comma separated) LAZY, no conversion takes place. +func_to_tool_file () +{ + $opt_debug + case ,$2, in + *,"$to_tool_file_cmd",*) + func_to_tool_file_result=$1 + ;; + *) + $to_tool_file_cmd "$1" + func_to_tool_file_result=$func_to_host_file_result + ;; + esac +} +# end func_to_tool_file + + +# func_convert_file_noop ARG +# Copy ARG to func_to_host_file_result. +func_convert_file_noop () +{ + func_to_host_file_result="$1" +} +# end func_convert_file_noop + + +# func_convert_file_msys_to_w32 ARG +# Convert file name ARG from (mingw) MSYS to (mingw) w32 format; automatic +# conversion to w32 is not available inside the cwrapper. Returns result in +# func_to_host_file_result. +func_convert_file_msys_to_w32 () +{ + $opt_debug + func_to_host_file_result="$1" + if test -n "$1"; then + func_convert_core_msys_to_w32 "$1" + func_to_host_file_result="$func_convert_core_msys_to_w32_result" + fi + func_convert_file_check "$1" "$func_to_host_file_result" +} +# end func_convert_file_msys_to_w32 + + +# func_convert_file_cygwin_to_w32 ARG +# Convert file name ARG from Cygwin to w32 format. Returns result in +# func_to_host_file_result. +func_convert_file_cygwin_to_w32 () +{ + $opt_debug + func_to_host_file_result="$1" + if test -n "$1"; then + # because $build is cygwin, we call "the" cygpath in $PATH; no need to use + # LT_CYGPATH in this case. + func_to_host_file_result=`cygpath -m "$1"` + fi + func_convert_file_check "$1" "$func_to_host_file_result" +} +# end func_convert_file_cygwin_to_w32 + + +# func_convert_file_nix_to_w32 ARG +# Convert file name ARG from *nix to w32 format. Requires a wine environment +# and a working winepath. Returns result in func_to_host_file_result. +func_convert_file_nix_to_w32 () +{ + $opt_debug + func_to_host_file_result="$1" + if test -n "$1"; then + func_convert_core_file_wine_to_w32 "$1" + func_to_host_file_result="$func_convert_core_file_wine_to_w32_result" + fi + func_convert_file_check "$1" "$func_to_host_file_result" +} +# end func_convert_file_nix_to_w32 + + +# func_convert_file_msys_to_cygwin ARG +# Convert file name ARG from MSYS to Cygwin format. Requires LT_CYGPATH set. +# Returns result in func_to_host_file_result. +func_convert_file_msys_to_cygwin () +{ + $opt_debug + func_to_host_file_result="$1" + if test -n "$1"; then + func_convert_core_msys_to_w32 "$1" + func_cygpath -u "$func_convert_core_msys_to_w32_result" + func_to_host_file_result="$func_cygpath_result" + fi + func_convert_file_check "$1" "$func_to_host_file_result" +} +# end func_convert_file_msys_to_cygwin + + +# func_convert_file_nix_to_cygwin ARG +# Convert file name ARG from *nix to Cygwin format. Requires Cygwin installed +# in a wine environment, working winepath, and LT_CYGPATH set. Returns result +# in func_to_host_file_result. +func_convert_file_nix_to_cygwin () +{ + $opt_debug + func_to_host_file_result="$1" + if test -n "$1"; then + # convert from *nix to w32, then use cygpath to convert from w32 to cygwin. + func_convert_core_file_wine_to_w32 "$1" + func_cygpath -u "$func_convert_core_file_wine_to_w32_result" + func_to_host_file_result="$func_cygpath_result" + fi + func_convert_file_check "$1" "$func_to_host_file_result" +} +# end func_convert_file_nix_to_cygwin + + +############################################# +# $build to $host PATH CONVERSION FUNCTIONS # +############################################# +# invoked via `$to_host_path_cmd ARG' +# +# In each case, ARG is the path to be converted from $build to $host format. +# The result will be available in $func_to_host_path_result. +# +# Path separators are also converted from $build format to $host format. If +# ARG begins or ends with a path separator character, it is preserved (but +# converted to $host format) on output. +# +# All path conversion functions are named using the following convention: +# file name conversion function : func_convert_file_X_to_Y () +# path conversion function : func_convert_path_X_to_Y () +# where, for any given $build/$host combination the 'X_to_Y' value is the +# same. If conversion functions are added for new $build/$host combinations, +# the two new functions must follow this pattern, or func_init_to_host_path_cmd +# will break. + + +# func_init_to_host_path_cmd +# Ensures that function "pointer" variable $to_host_path_cmd is set to the +# appropriate value, based on the value of $to_host_file_cmd. +to_host_path_cmd= +func_init_to_host_path_cmd () +{ + $opt_debug + if test -z "$to_host_path_cmd"; then + func_stripname 'func_convert_file_' '' "$to_host_file_cmd" + to_host_path_cmd="func_convert_path_${func_stripname_result}" + fi +} + + +# func_to_host_path ARG +# Converts the path ARG from $build format to $host format. Return result +# in func_to_host_path_result. +func_to_host_path () +{ + $opt_debug + func_init_to_host_path_cmd + $to_host_path_cmd "$1" +} +# end func_to_host_path + + +# func_convert_path_noop ARG +# Copy ARG to func_to_host_path_result. +func_convert_path_noop () +{ + func_to_host_path_result="$1" +} +# end func_convert_path_noop + + +# func_convert_path_msys_to_w32 ARG +# Convert path ARG from (mingw) MSYS to (mingw) w32 format; automatic +# conversion to w32 is not available inside the cwrapper. Returns result in +# func_to_host_path_result. +func_convert_path_msys_to_w32 () +{ + $opt_debug + func_to_host_path_result="$1" + if test -n "$1"; then + # Remove leading and trailing path separator characters from ARG. MSYS + # behavior is inconsistent here; cygpath turns them into '.;' and ';.'; + # and winepath ignores them completely. + func_stripname : : "$1" + func_to_host_path_tmp1=$func_stripname_result + func_convert_core_msys_to_w32 "$func_to_host_path_tmp1" + func_to_host_path_result="$func_convert_core_msys_to_w32_result" + func_convert_path_check : ";" \ + "$func_to_host_path_tmp1" "$func_to_host_path_result" + func_convert_path_front_back_pathsep ":*" "*:" ";" "$1" + fi +} +# end func_convert_path_msys_to_w32 + + +# func_convert_path_cygwin_to_w32 ARG +# Convert path ARG from Cygwin to w32 format. Returns result in +# func_to_host_file_result. +func_convert_path_cygwin_to_w32 () +{ + $opt_debug + func_to_host_path_result="$1" + if test -n "$1"; then + # See func_convert_path_msys_to_w32: + func_stripname : : "$1" + func_to_host_path_tmp1=$func_stripname_result + func_to_host_path_result=`cygpath -m -p "$func_to_host_path_tmp1"` + func_convert_path_check : ";" \ + "$func_to_host_path_tmp1" "$func_to_host_path_result" + func_convert_path_front_back_pathsep ":*" "*:" ";" "$1" + fi +} +# end func_convert_path_cygwin_to_w32 + + +# func_convert_path_nix_to_w32 ARG +# Convert path ARG from *nix to w32 format. Requires a wine environment and +# a working winepath. Returns result in func_to_host_file_result. +func_convert_path_nix_to_w32 () +{ + $opt_debug + func_to_host_path_result="$1" + if test -n "$1"; then + # See func_convert_path_msys_to_w32: + func_stripname : : "$1" + func_to_host_path_tmp1=$func_stripname_result + func_convert_core_path_wine_to_w32 "$func_to_host_path_tmp1" + func_to_host_path_result="$func_convert_core_path_wine_to_w32_result" + func_convert_path_check : ";" \ + "$func_to_host_path_tmp1" "$func_to_host_path_result" + func_convert_path_front_back_pathsep ":*" "*:" ";" "$1" + fi +} +# end func_convert_path_nix_to_w32 + + +# func_convert_path_msys_to_cygwin ARG +# Convert path ARG from MSYS to Cygwin format. Requires LT_CYGPATH set. +# Returns result in func_to_host_file_result. +func_convert_path_msys_to_cygwin () +{ + $opt_debug + func_to_host_path_result="$1" + if test -n "$1"; then + # See func_convert_path_msys_to_w32: + func_stripname : : "$1" + func_to_host_path_tmp1=$func_stripname_result + func_convert_core_msys_to_w32 "$func_to_host_path_tmp1" + func_cygpath -u -p "$func_convert_core_msys_to_w32_result" + func_to_host_path_result="$func_cygpath_result" + func_convert_path_check : : \ + "$func_to_host_path_tmp1" "$func_to_host_path_result" + func_convert_path_front_back_pathsep ":*" "*:" : "$1" + fi +} +# end func_convert_path_msys_to_cygwin + + +# func_convert_path_nix_to_cygwin ARG +# Convert path ARG from *nix to Cygwin format. Requires Cygwin installed in a +# a wine environment, working winepath, and LT_CYGPATH set. Returns result in +# func_to_host_file_result. +func_convert_path_nix_to_cygwin () +{ + $opt_debug + func_to_host_path_result="$1" + if test -n "$1"; then + # Remove leading and trailing path separator characters from + # ARG. msys behavior is inconsistent here, cygpath turns them + # into '.;' and ';.', and winepath ignores them completely. + func_stripname : : "$1" + func_to_host_path_tmp1=$func_stripname_result + func_convert_core_path_wine_to_w32 "$func_to_host_path_tmp1" + func_cygpath -u -p "$func_convert_core_path_wine_to_w32_result" + func_to_host_path_result="$func_cygpath_result" + func_convert_path_check : : \ + "$func_to_host_path_tmp1" "$func_to_host_path_result" + func_convert_path_front_back_pathsep ":*" "*:" : "$1" + fi +} +# end func_convert_path_nix_to_cygwin + + +# func_mode_compile arg... +func_mode_compile () +{ + $opt_debug + # Get the compilation command and the source file. + base_compile= + srcfile="$nonopt" # always keep a non-empty value in "srcfile" + suppress_opt=yes + suppress_output= + arg_mode=normal + libobj= + later= + pie_flag= + + for arg + do + case $arg_mode in + arg ) + # do not "continue". Instead, add this to base_compile + lastarg="$arg" + arg_mode=normal + ;; + + target ) + libobj="$arg" + arg_mode=normal + continue + ;; + + normal ) + # Accept any command-line options. + case $arg in + -o) + test -n "$libobj" && \ + func_fatal_error "you cannot specify \`-o' more than once" + arg_mode=target + continue + ;; + + -pie | -fpie | -fPIE) + func_append pie_flag " $arg" + continue + ;; + + -shared | -static | -prefer-pic | -prefer-non-pic) + func_append later " $arg" + continue + ;; + + -no-suppress) + suppress_opt=no + continue + ;; + + -Xcompiler) + arg_mode=arg # the next one goes into the "base_compile" arg list + continue # The current "srcfile" will either be retained or + ;; # replaced later. I would guess that would be a bug. + + -Wc,*) + func_stripname '-Wc,' '' "$arg" + args=$func_stripname_result + lastarg= + save_ifs="$IFS"; IFS=',' + for arg in $args; do + IFS="$save_ifs" + func_append_quoted lastarg "$arg" + done + IFS="$save_ifs" + func_stripname ' ' '' "$lastarg" + lastarg=$func_stripname_result + + # Add the arguments to base_compile. + func_append base_compile " $lastarg" + continue + ;; + + *) + # Accept the current argument as the source file. + # The previous "srcfile" becomes the current argument. + # + lastarg="$srcfile" + srcfile="$arg" + ;; + esac # case $arg + ;; + esac # case $arg_mode + + # Aesthetically quote the previous argument. + func_append_quoted base_compile "$lastarg" + done # for arg + + case $arg_mode in + arg) + func_fatal_error "you must specify an argument for -Xcompile" + ;; + target) + func_fatal_error "you must specify a target with \`-o'" + ;; + *) + # Get the name of the library object. + test -z "$libobj" && { + func_basename "$srcfile" + libobj="$func_basename_result" + } + ;; + esac + + # Recognize several different file suffixes. + # If the user specifies -o file.o, it is replaced with file.lo + case $libobj in + *.[cCFSifmso] | \ + *.ada | *.adb | *.ads | *.asm | \ + *.c++ | *.cc | *.ii | *.class | *.cpp | *.cxx | \ + *.[fF][09]? | *.for | *.java | *.obj | *.sx | *.cu | *.cup) + func_xform "$libobj" + libobj=$func_xform_result + ;; + esac + + case $libobj in + *.lo) func_lo2o "$libobj"; obj=$func_lo2o_result ;; + *) + func_fatal_error "cannot determine name of library object from \`$libobj'" + ;; + esac + + func_infer_tag $base_compile + + for arg in $later; do + case $arg in + -shared) + test "$build_libtool_libs" != yes && \ + func_fatal_configuration "can not build a shared library" + build_old_libs=no + continue + ;; + + -static) + build_libtool_libs=no + build_old_libs=yes + continue + ;; + + -prefer-pic) + pic_mode=yes + continue + ;; + + -prefer-non-pic) + pic_mode=no + continue + ;; + esac + done + + func_quote_for_eval "$libobj" + test "X$libobj" != "X$func_quote_for_eval_result" \ + && $ECHO "X$libobj" | $GREP '[]~#^*{};<>?"'"'"' &()|`$[]' \ + && func_warning "libobj name \`$libobj' may not contain shell special characters." + func_dirname_and_basename "$obj" "/" "" + objname="$func_basename_result" + xdir="$func_dirname_result" + lobj=${xdir}$objdir/$objname + + test -z "$base_compile" && \ + func_fatal_help "you must specify a compilation command" + + # Delete any leftover library objects. + if test "$build_old_libs" = yes; then + removelist="$obj $lobj $libobj ${libobj}T" + else + removelist="$lobj $libobj ${libobj}T" + fi + + # On Cygwin there's no "real" PIC flag so we must build both object types + case $host_os in + cygwin* | mingw* | pw32* | os2* | cegcc*) + pic_mode=default + ;; + esac + if test "$pic_mode" = no && test "$deplibs_check_method" != pass_all; then + # non-PIC code in shared libraries is not supported + pic_mode=default + fi + + # Calculate the filename of the output object if compiler does + # not support -o with -c + if test "$compiler_c_o" = no; then + output_obj=`$ECHO "$srcfile" | $SED 's%^.*/%%; s%\.[^.]*$%%'`.${objext} + lockfile="$output_obj.lock" + else + output_obj= + need_locks=no + lockfile= + fi + + # Lock this critical section if it is needed + # We use this script file to make the link, it avoids creating a new file + if test "$need_locks" = yes; then + until $opt_dry_run || ln "$progpath" "$lockfile" 2>/dev/null; do + func_echo "Waiting for $lockfile to be removed" + sleep 2 + done + elif test "$need_locks" = warn; then + if test -f "$lockfile"; then + $ECHO "\ +*** ERROR, $lockfile exists and contains: +`cat $lockfile 2>/dev/null` + +This indicates that another process is trying to use the same +temporary object file, and libtool could not work around it because +your compiler does not support \`-c' and \`-o' together. If you +repeat this compilation, it may succeed, by chance, but you had better +avoid parallel builds (make -j) in this platform, or get a better +compiler." + + $opt_dry_run || $RM $removelist + exit $EXIT_FAILURE + fi + func_append removelist " $output_obj" + $ECHO "$srcfile" > "$lockfile" + fi + + $opt_dry_run || $RM $removelist + func_append removelist " $lockfile" + trap '$opt_dry_run || $RM $removelist; exit $EXIT_FAILURE' 1 2 15 + + func_to_tool_file "$srcfile" func_convert_file_msys_to_w32 + srcfile=$func_to_tool_file_result + func_quote_for_eval "$srcfile" + qsrcfile=$func_quote_for_eval_result + + # Only build a PIC object if we are building libtool libraries. + if test "$build_libtool_libs" = yes; then + # Without this assignment, base_compile gets emptied. + fbsd_hideous_sh_bug=$base_compile + + if test "$pic_mode" != no; then + command="$base_compile $qsrcfile $pic_flag" + else + # Don't build PIC code + command="$base_compile $qsrcfile" + fi + + func_mkdir_p "$xdir$objdir" + + if test -z "$output_obj"; then + # Place PIC objects in $objdir + func_append command " -o $lobj" + fi + + func_show_eval_locale "$command" \ + 'test -n "$output_obj" && $RM $removelist; exit $EXIT_FAILURE' + + if test "$need_locks" = warn && + test "X`cat $lockfile 2>/dev/null`" != "X$srcfile"; then + $ECHO "\ +*** ERROR, $lockfile contains: +`cat $lockfile 2>/dev/null` + +but it should contain: +$srcfile + +This indicates that another process is trying to use the same +temporary object file, and libtool could not work around it because +your compiler does not support \`-c' and \`-o' together. If you +repeat this compilation, it may succeed, by chance, but you had better +avoid parallel builds (make -j) in this platform, or get a better +compiler." + + $opt_dry_run || $RM $removelist + exit $EXIT_FAILURE + fi + + # Just move the object if needed, then go on to compile the next one + if test -n "$output_obj" && test "X$output_obj" != "X$lobj"; then + func_show_eval '$MV "$output_obj" "$lobj"' \ + 'error=$?; $opt_dry_run || $RM $removelist; exit $error' + fi + + # Allow error messages only from the first compilation. + if test "$suppress_opt" = yes; then + suppress_output=' >/dev/null 2>&1' + fi + fi + + # Only build a position-dependent object if we build old libraries. + if test "$build_old_libs" = yes; then + if test "$pic_mode" != yes; then + # Don't build PIC code + command="$base_compile $qsrcfile$pie_flag" + else + command="$base_compile $qsrcfile $pic_flag" + fi + if test "$compiler_c_o" = yes; then + func_append command " -o $obj" + fi + + # Suppress compiler output if we already did a PIC compilation. + func_append command "$suppress_output" + func_show_eval_locale "$command" \ + '$opt_dry_run || $RM $removelist; exit $EXIT_FAILURE' + + if test "$need_locks" = warn && + test "X`cat $lockfile 2>/dev/null`" != "X$srcfile"; then + $ECHO "\ +*** ERROR, $lockfile contains: +`cat $lockfile 2>/dev/null` + +but it should contain: +$srcfile + +This indicates that another process is trying to use the same +temporary object file, and libtool could not work around it because +your compiler does not support \`-c' and \`-o' together. If you +repeat this compilation, it may succeed, by chance, but you had better +avoid parallel builds (make -j) in this platform, or get a better +compiler." + + $opt_dry_run || $RM $removelist + exit $EXIT_FAILURE + fi + + # Just move the object if needed + if test -n "$output_obj" && test "X$output_obj" != "X$obj"; then + func_show_eval '$MV "$output_obj" "$obj"' \ + 'error=$?; $opt_dry_run || $RM $removelist; exit $error' + fi + fi + + $opt_dry_run || { + func_write_libtool_object "$libobj" "$objdir/$objname" "$objname" + + # Unlock the critical section if it was locked + if test "$need_locks" != no; then + removelist=$lockfile + $RM "$lockfile" + fi + } + + exit $EXIT_SUCCESS +} + +$opt_help || { + test "$opt_mode" = compile && func_mode_compile ${1+"$@"} +} + +func_mode_help () +{ + # We need to display help for each of the modes. + case $opt_mode in + "") + # Generic help is extracted from the usage comments + # at the start of this file. + func_help + ;; + + clean) + $ECHO \ +"Usage: $progname [OPTION]... --mode=clean RM [RM-OPTION]... FILE... + +Remove files from the build directory. + +RM is the name of the program to use to delete files associated with each FILE +(typically \`/bin/rm'). RM-OPTIONS are options (such as \`-f') to be passed +to RM. + +If FILE is a libtool library, object or program, all the files associated +with it are deleted. Otherwise, only FILE itself is deleted using RM." + ;; + + compile) + $ECHO \ +"Usage: $progname [OPTION]... --mode=compile COMPILE-COMMAND... SOURCEFILE + +Compile a source file into a libtool library object. + +This mode accepts the following additional options: + + -o OUTPUT-FILE set the output file name to OUTPUT-FILE + -no-suppress do not suppress compiler output for multiple passes + -prefer-pic try to build PIC objects only + -prefer-non-pic try to build non-PIC objects only + -shared do not build a \`.o' file suitable for static linking + -static only build a \`.o' file suitable for static linking + -Wc,FLAG pass FLAG directly to the compiler + +COMPILE-COMMAND is a command to be used in creating a \`standard' object file +from the given SOURCEFILE. + +The output file name is determined by removing the directory component from +SOURCEFILE, then substituting the C source code suffix \`.c' with the +library object suffix, \`.lo'." + ;; + + execute) + $ECHO \ +"Usage: $progname [OPTION]... --mode=execute COMMAND [ARGS]... + +Automatically set library path, then run a program. + +This mode accepts the following additional options: + + -dlopen FILE add the directory containing FILE to the library path + +This mode sets the library path environment variable according to \`-dlopen' +flags. + +If any of the ARGS are libtool executable wrappers, then they are translated +into their corresponding uninstalled binary, and any of their required library +directories are added to the library path. + +Then, COMMAND is executed, with ARGS as arguments." + ;; + + finish) + $ECHO \ +"Usage: $progname [OPTION]... --mode=finish [LIBDIR]... + +Complete the installation of libtool libraries. + +Each LIBDIR is a directory that contains libtool libraries. + +The commands that this mode executes may require superuser privileges. Use +the \`--dry-run' option if you just want to see what would be executed." + ;; + + install) + $ECHO \ +"Usage: $progname [OPTION]... --mode=install INSTALL-COMMAND... + +Install executables or libraries. + +INSTALL-COMMAND is the installation command. The first component should be +either the \`install' or \`cp' program. + +The following components of INSTALL-COMMAND are treated specially: + + -inst-prefix-dir PREFIX-DIR Use PREFIX-DIR as a staging area for installation + +The rest of the components are interpreted as arguments to that command (only +BSD-compatible install options are recognized)." + ;; + + link) + $ECHO \ +"Usage: $progname [OPTION]... --mode=link LINK-COMMAND... + +Link object files or libraries together to form another library, or to +create an executable program. + +LINK-COMMAND is a command using the C compiler that you would use to create +a program from several object files. + +The following components of LINK-COMMAND are treated specially: + + -all-static do not do any dynamic linking at all + -avoid-version do not add a version suffix if possible + -bindir BINDIR specify path to binaries directory (for systems where + libraries must be found in the PATH setting at runtime) + -dlopen FILE \`-dlpreopen' FILE if it cannot be dlopened at runtime + -dlpreopen FILE link in FILE and add its symbols to lt_preloaded_symbols + -export-dynamic allow symbols from OUTPUT-FILE to be resolved with dlsym(3) + -export-symbols SYMFILE + try to export only the symbols listed in SYMFILE + -export-symbols-regex REGEX + try to export only the symbols matching REGEX + -LLIBDIR search LIBDIR for required installed libraries + -lNAME OUTPUT-FILE requires the installed library libNAME + -module build a library that can dlopened + -no-fast-install disable the fast-install mode + -no-install link a not-installable executable + -no-undefined declare that a library does not refer to external symbols + -o OUTPUT-FILE create OUTPUT-FILE from the specified objects + -objectlist FILE Use a list of object files found in FILE to specify objects + -precious-files-regex REGEX + don't remove output files matching REGEX + -release RELEASE specify package release information + -rpath LIBDIR the created library will eventually be installed in LIBDIR + -R[ ]LIBDIR add LIBDIR to the runtime path of programs and libraries + -shared only do dynamic linking of libtool libraries + -shrext SUFFIX override the standard shared library file extension + -static do not do any dynamic linking of uninstalled libtool libraries + -static-libtool-libs + do not do any dynamic linking of libtool libraries + -version-info CURRENT[:REVISION[:AGE]] + specify library version info [each variable defaults to 0] + -weak LIBNAME declare that the target provides the LIBNAME interface + -Wc,FLAG + -Xcompiler FLAG pass linker-specific FLAG directly to the compiler + -Wl,FLAG + -Xlinker FLAG pass linker-specific FLAG directly to the linker + -XCClinker FLAG pass link-specific FLAG to the compiler driver (CC) + +All other options (arguments beginning with \`-') are ignored. + +Every other argument is treated as a filename. Files ending in \`.la' are +treated as uninstalled libtool libraries, other files are standard or library +object files. + +If the OUTPUT-FILE ends in \`.la', then a libtool library is created, +only library objects (\`.lo' files) may be specified, and \`-rpath' is +required, except when creating a convenience library. + +If OUTPUT-FILE ends in \`.a' or \`.lib', then a standard library is created +using \`ar' and \`ranlib', or on Windows using \`lib'. + +If OUTPUT-FILE ends in \`.lo' or \`.${objext}', then a reloadable object file +is created, otherwise an executable program is created." + ;; + + uninstall) + $ECHO \ +"Usage: $progname [OPTION]... --mode=uninstall RM [RM-OPTION]... FILE... + +Remove libraries from an installation directory. + +RM is the name of the program to use to delete files associated with each FILE +(typically \`/bin/rm'). RM-OPTIONS are options (such as \`-f') to be passed +to RM. + +If FILE is a libtool library, all the files associated with it are deleted. +Otherwise, only FILE itself is deleted using RM." + ;; + + *) + func_fatal_help "invalid operation mode \`$opt_mode'" + ;; + esac + + echo + $ECHO "Try \`$progname --help' for more information about other modes." +} + +# Now that we've collected a possible --mode arg, show help if necessary +if $opt_help; then + if test "$opt_help" = :; then + func_mode_help + else + { + func_help noexit + for opt_mode in compile link execute install finish uninstall clean; do + func_mode_help + done + } | sed -n '1p; 2,$s/^Usage:/ or: /p' + { + func_help noexit + for opt_mode in compile link execute install finish uninstall clean; do + echo + func_mode_help + done + } | + sed '1d + /^When reporting/,/^Report/{ + H + d + } + $x + /information about other modes/d + /more detailed .*MODE/d + s/^Usage:.*--mode=\([^ ]*\) .*/Description of \1 mode:/' + fi + exit $? +fi + + +# func_mode_execute arg... +func_mode_execute () +{ + $opt_debug + # The first argument is the command name. + cmd="$nonopt" + test -z "$cmd" && \ + func_fatal_help "you must specify a COMMAND" + + # Handle -dlopen flags immediately. + for file in $opt_dlopen; do + test -f "$file" \ + || func_fatal_help "\`$file' is not a file" + + dir= + case $file in + *.la) + func_resolve_sysroot "$file" + file=$func_resolve_sysroot_result + + # Check to see that this really is a libtool archive. + func_lalib_unsafe_p "$file" \ + || func_fatal_help "\`$lib' is not a valid libtool archive" + + # Read the libtool library. + dlname= + library_names= + func_source "$file" + + # Skip this library if it cannot be dlopened. + if test -z "$dlname"; then + # Warn if it was a shared library. + test -n "$library_names" && \ + func_warning "\`$file' was not linked with \`-export-dynamic'" + continue + fi + + func_dirname "$file" "" "." + dir="$func_dirname_result" + + if test -f "$dir/$objdir/$dlname"; then + func_append dir "/$objdir" + else + if test ! -f "$dir/$dlname"; then + func_fatal_error "cannot find \`$dlname' in \`$dir' or \`$dir/$objdir'" + fi + fi + ;; + + *.lo) + # Just add the directory containing the .lo file. + func_dirname "$file" "" "." + dir="$func_dirname_result" + ;; + + *) + func_warning "\`-dlopen' is ignored for non-libtool libraries and objects" + continue + ;; + esac + + # Get the absolute pathname. + absdir=`cd "$dir" && pwd` + test -n "$absdir" && dir="$absdir" + + # Now add the directory to shlibpath_var. + if eval "test -z \"\$$shlibpath_var\""; then + eval "$shlibpath_var=\"\$dir\"" + else + eval "$shlibpath_var=\"\$dir:\$$shlibpath_var\"" + fi + done + + # This variable tells wrapper scripts just to set shlibpath_var + # rather than running their programs. + libtool_execute_magic="$magic" + + # Check if any of the arguments is a wrapper script. + args= + for file + do + case $file in + -* | *.la | *.lo ) ;; + *) + # Do a test to see if this is really a libtool program. + if func_ltwrapper_script_p "$file"; then + func_source "$file" + # Transform arg to wrapped name. + file="$progdir/$program" + elif func_ltwrapper_executable_p "$file"; then + func_ltwrapper_scriptname "$file" + func_source "$func_ltwrapper_scriptname_result" + # Transform arg to wrapped name. + file="$progdir/$program" + fi + ;; + esac + # Quote arguments (to preserve shell metacharacters). + func_append_quoted args "$file" + done + + if test "X$opt_dry_run" = Xfalse; then + if test -n "$shlibpath_var"; then + # Export the shlibpath_var. + eval "export $shlibpath_var" + fi + + # Restore saved environment variables + for lt_var in LANG LANGUAGE LC_ALL LC_CTYPE LC_COLLATE LC_MESSAGES + do + eval "if test \"\${save_$lt_var+set}\" = set; then + $lt_var=\$save_$lt_var; export $lt_var + else + $lt_unset $lt_var + fi" + done + + # Now prepare to actually exec the command. + exec_cmd="\$cmd$args" + else + # Display what would be done. + if test -n "$shlibpath_var"; then + eval "\$ECHO \"\$shlibpath_var=\$$shlibpath_var\"" + echo "export $shlibpath_var" + fi + $ECHO "$cmd$args" + exit $EXIT_SUCCESS + fi +} + +test "$opt_mode" = execute && func_mode_execute ${1+"$@"} + + +# func_mode_finish arg... +func_mode_finish () +{ + $opt_debug + libs= + libdirs= + admincmds= + + for opt in "$nonopt" ${1+"$@"} + do + if test -d "$opt"; then + func_append libdirs " $opt" + + elif test -f "$opt"; then + if func_lalib_unsafe_p "$opt"; then + func_append libs " $opt" + else + func_warning "\`$opt' is not a valid libtool archive" + fi + + else + func_fatal_error "invalid argument \`$opt'" + fi + done + + if test -n "$libs"; then + if test -n "$lt_sysroot"; then + sysroot_regex=`$ECHO "$lt_sysroot" | $SED "$sed_make_literal_regex"` + sysroot_cmd="s/\([ ']\)$sysroot_regex/\1/g;" + else + sysroot_cmd= + fi + + # Remove sysroot references + if $opt_dry_run; then + for lib in $libs; do + echo "removing references to $lt_sysroot and \`=' prefixes from $lib" + done + else + tmpdir=`func_mktempdir` + for lib in $libs; do + sed -e "${sysroot_cmd} s/\([ ']-[LR]\)=/\1/g; s/\([ ']\)=/\1/g" $lib \ + > $tmpdir/tmp-la + mv -f $tmpdir/tmp-la $lib + done + ${RM}r "$tmpdir" + fi + fi + + if test -n "$finish_cmds$finish_eval" && test -n "$libdirs"; then + for libdir in $libdirs; do + if test -n "$finish_cmds"; then + # Do each command in the finish commands. + func_execute_cmds "$finish_cmds" 'admincmds="$admincmds +'"$cmd"'"' + fi + if test -n "$finish_eval"; then + # Do the single finish_eval. + eval cmds=\"$finish_eval\" + $opt_dry_run || eval "$cmds" || func_append admincmds " + $cmds" + fi + done + fi + + # Exit here if they wanted silent mode. + $opt_silent && exit $EXIT_SUCCESS + + if test -n "$finish_cmds$finish_eval" && test -n "$libdirs"; then + echo "----------------------------------------------------------------------" + echo "Libraries have been installed in:" + for libdir in $libdirs; do + $ECHO " $libdir" + done + echo + echo "If you ever happen to want to link against installed libraries" + echo "in a given directory, LIBDIR, you must either use libtool, and" + echo "specify the full pathname of the library, or use the \`-LLIBDIR'" + echo "flag during linking and do at least one of the following:" + if test -n "$shlibpath_var"; then + echo " - add LIBDIR to the \`$shlibpath_var' environment variable" + echo " during execution" + fi + if test -n "$runpath_var"; then + echo " - add LIBDIR to the \`$runpath_var' environment variable" + echo " during linking" + fi + if test -n "$hardcode_libdir_flag_spec"; then + libdir=LIBDIR + eval flag=\"$hardcode_libdir_flag_spec\" + + $ECHO " - use the \`$flag' linker flag" + fi + if test -n "$admincmds"; then + $ECHO " - have your system administrator run these commands:$admincmds" + fi + if test -f /etc/ld.so.conf; then + echo " - have your system administrator add LIBDIR to \`/etc/ld.so.conf'" + fi + echo + + echo "See any operating system documentation about shared libraries for" + case $host in + solaris2.[6789]|solaris2.1[0-9]) + echo "more information, such as the ld(1), crle(1) and ld.so(8) manual" + echo "pages." + ;; + *) + echo "more information, such as the ld(1) and ld.so(8) manual pages." + ;; + esac + echo "----------------------------------------------------------------------" + fi + exit $EXIT_SUCCESS +} + +test "$opt_mode" = finish && func_mode_finish ${1+"$@"} + + +# func_mode_install arg... +func_mode_install () +{ + $opt_debug + # There may be an optional sh(1) argument at the beginning of + # install_prog (especially on Windows NT). + if test "$nonopt" = "$SHELL" || test "$nonopt" = /bin/sh || + # Allow the use of GNU shtool's install command. + case $nonopt in *shtool*) :;; *) false;; esac; then + # Aesthetically quote it. + func_quote_for_eval "$nonopt" + install_prog="$func_quote_for_eval_result " + arg=$1 + shift + else + install_prog= + arg=$nonopt + fi + + # The real first argument should be the name of the installation program. + # Aesthetically quote it. + func_quote_for_eval "$arg" + func_append install_prog "$func_quote_for_eval_result" + install_shared_prog=$install_prog + case " $install_prog " in + *[\\\ /]cp\ *) install_cp=: ;; + *) install_cp=false ;; + esac + + # We need to accept at least all the BSD install flags. + dest= + files= + opts= + prev= + install_type= + isdir=no + stripme= + no_mode=: + for arg + do + arg2= + if test -n "$dest"; then + func_append files " $dest" + dest=$arg + continue + fi + + case $arg in + -d) isdir=yes ;; + -f) + if $install_cp; then :; else + prev=$arg + fi + ;; + -g | -m | -o) + prev=$arg + ;; + -s) + stripme=" -s" + continue + ;; + -*) + ;; + *) + # If the previous option needed an argument, then skip it. + if test -n "$prev"; then + if test "x$prev" = x-m && test -n "$install_override_mode"; then + arg2=$install_override_mode + no_mode=false + fi + prev= + else + dest=$arg + continue + fi + ;; + esac + + # Aesthetically quote the argument. + func_quote_for_eval "$arg" + func_append install_prog " $func_quote_for_eval_result" + if test -n "$arg2"; then + func_quote_for_eval "$arg2" + fi + func_append install_shared_prog " $func_quote_for_eval_result" + done + + test -z "$install_prog" && \ + func_fatal_help "you must specify an install program" + + test -n "$prev" && \ + func_fatal_help "the \`$prev' option requires an argument" + + if test -n "$install_override_mode" && $no_mode; then + if $install_cp; then :; else + func_quote_for_eval "$install_override_mode" + func_append install_shared_prog " -m $func_quote_for_eval_result" + fi + fi + + if test -z "$files"; then + if test -z "$dest"; then + func_fatal_help "no file or destination specified" + else + func_fatal_help "you must specify a destination" + fi + fi + + # Strip any trailing slash from the destination. + func_stripname '' '/' "$dest" + dest=$func_stripname_result + + # Check to see that the destination is a directory. + test -d "$dest" && isdir=yes + if test "$isdir" = yes; then + destdir="$dest" + destname= + else + func_dirname_and_basename "$dest" "" "." + destdir="$func_dirname_result" + destname="$func_basename_result" + + # Not a directory, so check to see that there is only one file specified. + set dummy $files; shift + test "$#" -gt 1 && \ + func_fatal_help "\`$dest' is not a directory" + fi + case $destdir in + [\\/]* | [A-Za-z]:[\\/]*) ;; + *) + for file in $files; do + case $file in + *.lo) ;; + *) + func_fatal_help "\`$destdir' must be an absolute directory name" + ;; + esac + done + ;; + esac + + # This variable tells wrapper scripts just to set variables rather + # than running their programs. + libtool_install_magic="$magic" + + staticlibs= + future_libdirs= + current_libdirs= + for file in $files; do + + # Do each installation. + case $file in + *.$libext) + # Do the static libraries later. + func_append staticlibs " $file" + ;; + + *.la) + func_resolve_sysroot "$file" + file=$func_resolve_sysroot_result + + # Check to see that this really is a libtool archive. + func_lalib_unsafe_p "$file" \ + || func_fatal_help "\`$file' is not a valid libtool archive" + + library_names= + old_library= + relink_command= + func_source "$file" + + # Add the libdir to current_libdirs if it is the destination. + if test "X$destdir" = "X$libdir"; then + case "$current_libdirs " in + *" $libdir "*) ;; + *) func_append current_libdirs " $libdir" ;; + esac + else + # Note the libdir as a future libdir. + case "$future_libdirs " in + *" $libdir "*) ;; + *) func_append future_libdirs " $libdir" ;; + esac + fi + + func_dirname "$file" "/" "" + dir="$func_dirname_result" + func_append dir "$objdir" + + if test -n "$relink_command"; then + # Determine the prefix the user has applied to our future dir. + inst_prefix_dir=`$ECHO "$destdir" | $SED -e "s%$libdir\$%%"` + + # Don't allow the user to place us outside of our expected + # location b/c this prevents finding dependent libraries that + # are installed to the same prefix. + # At present, this check doesn't affect windows .dll's that + # are installed into $libdir/../bin (currently, that works fine) + # but it's something to keep an eye on. + test "$inst_prefix_dir" = "$destdir" && \ + func_fatal_error "error: cannot install \`$file' to a directory not ending in $libdir" + + if test -n "$inst_prefix_dir"; then + # Stick the inst_prefix_dir data into the link command. + relink_command=`$ECHO "$relink_command" | $SED "s%@inst_prefix_dir@%-inst-prefix-dir $inst_prefix_dir%"` + else + relink_command=`$ECHO "$relink_command" | $SED "s%@inst_prefix_dir@%%"` + fi + + func_warning "relinking \`$file'" + func_show_eval "$relink_command" \ + 'func_fatal_error "error: relink \`$file'\'' with the above command before installing it"' + fi + + # See the names of the shared library. + set dummy $library_names; shift + if test -n "$1"; then + realname="$1" + shift + + srcname="$realname" + test -n "$relink_command" && srcname="$realname"T + + # Install the shared library and build the symlinks. + func_show_eval "$install_shared_prog $dir/$srcname $destdir/$realname" \ + 'exit $?' + tstripme="$stripme" + case $host_os in + cygwin* | mingw* | pw32* | cegcc*) + case $realname in + *.dll.a) + tstripme="" + ;; + esac + ;; + esac + if test -n "$tstripme" && test -n "$striplib"; then + func_show_eval "$striplib $destdir/$realname" 'exit $?' + fi + + if test "$#" -gt 0; then + # Delete the old symlinks, and create new ones. + # Try `ln -sf' first, because the `ln' binary might depend on + # the symlink we replace! Solaris /bin/ln does not understand -f, + # so we also need to try rm && ln -s. + for linkname + do + test "$linkname" != "$realname" \ + && func_show_eval "(cd $destdir && { $LN_S -f $realname $linkname || { $RM $linkname && $LN_S $realname $linkname; }; })" + done + fi + + # Do each command in the postinstall commands. + lib="$destdir/$realname" + func_execute_cmds "$postinstall_cmds" 'exit $?' + fi + + # Install the pseudo-library for information purposes. + func_basename "$file" + name="$func_basename_result" + instname="$dir/$name"i + func_show_eval "$install_prog $instname $destdir/$name" 'exit $?' + + # Maybe install the static library, too. + test -n "$old_library" && func_append staticlibs " $dir/$old_library" + ;; + + *.lo) + # Install (i.e. copy) a libtool object. + + # Figure out destination file name, if it wasn't already specified. + if test -n "$destname"; then + destfile="$destdir/$destname" + else + func_basename "$file" + destfile="$func_basename_result" + destfile="$destdir/$destfile" + fi + + # Deduce the name of the destination old-style object file. + case $destfile in + *.lo) + func_lo2o "$destfile" + staticdest=$func_lo2o_result + ;; + *.$objext) + staticdest="$destfile" + destfile= + ;; + *) + func_fatal_help "cannot copy a libtool object to \`$destfile'" + ;; + esac + + # Install the libtool object if requested. + test -n "$destfile" && \ + func_show_eval "$install_prog $file $destfile" 'exit $?' + + # Install the old object if enabled. + if test "$build_old_libs" = yes; then + # Deduce the name of the old-style object file. + func_lo2o "$file" + staticobj=$func_lo2o_result + func_show_eval "$install_prog \$staticobj \$staticdest" 'exit $?' + fi + exit $EXIT_SUCCESS + ;; + + *) + # Figure out destination file name, if it wasn't already specified. + if test -n "$destname"; then + destfile="$destdir/$destname" + else + func_basename "$file" + destfile="$func_basename_result" + destfile="$destdir/$destfile" + fi + + # If the file is missing, and there is a .exe on the end, strip it + # because it is most likely a libtool script we actually want to + # install + stripped_ext="" + case $file in + *.exe) + if test ! -f "$file"; then + func_stripname '' '.exe' "$file" + file=$func_stripname_result + stripped_ext=".exe" + fi + ;; + esac + + # Do a test to see if this is really a libtool program. + case $host in + *cygwin* | *mingw*) + if func_ltwrapper_executable_p "$file"; then + func_ltwrapper_scriptname "$file" + wrapper=$func_ltwrapper_scriptname_result + else + func_stripname '' '.exe' "$file" + wrapper=$func_stripname_result + fi + ;; + *) + wrapper=$file + ;; + esac + if func_ltwrapper_script_p "$wrapper"; then + notinst_deplibs= + relink_command= + + func_source "$wrapper" + + # Check the variables that should have been set. + test -z "$generated_by_libtool_version" && \ + func_fatal_error "invalid libtool wrapper script \`$wrapper'" + + finalize=yes + for lib in $notinst_deplibs; do + # Check to see that each library is installed. + libdir= + if test -f "$lib"; then + func_source "$lib" + fi + libfile="$libdir/"`$ECHO "$lib" | $SED 's%^.*/%%g'` ### testsuite: skip nested quoting test + if test -n "$libdir" && test ! -f "$libfile"; then + func_warning "\`$lib' has not been installed in \`$libdir'" + finalize=no + fi + done + + relink_command= + func_source "$wrapper" + + outputname= + if test "$fast_install" = no && test -n "$relink_command"; then + $opt_dry_run || { + if test "$finalize" = yes; then + tmpdir=`func_mktempdir` + func_basename "$file$stripped_ext" + file="$func_basename_result" + outputname="$tmpdir/$file" + # Replace the output file specification. + relink_command=`$ECHO "$relink_command" | $SED 's%@OUTPUT@%'"$outputname"'%g'` + + $opt_silent || { + func_quote_for_expand "$relink_command" + eval "func_echo $func_quote_for_expand_result" + } + if eval "$relink_command"; then : + else + func_error "error: relink \`$file' with the above command before installing it" + $opt_dry_run || ${RM}r "$tmpdir" + continue + fi + file="$outputname" + else + func_warning "cannot relink \`$file'" + fi + } + else + # Install the binary that we compiled earlier. + file=`$ECHO "$file$stripped_ext" | $SED "s%\([^/]*\)$%$objdir/\1%"` + fi + fi + + # remove .exe since cygwin /usr/bin/install will append another + # one anyway + case $install_prog,$host in + */usr/bin/install*,*cygwin*) + case $file:$destfile in + *.exe:*.exe) + # this is ok + ;; + *.exe:*) + destfile=$destfile.exe + ;; + *:*.exe) + func_stripname '' '.exe' "$destfile" + destfile=$func_stripname_result + ;; + esac + ;; + esac + func_show_eval "$install_prog\$stripme \$file \$destfile" 'exit $?' + $opt_dry_run || if test -n "$outputname"; then + ${RM}r "$tmpdir" + fi + ;; + esac + done + + for file in $staticlibs; do + func_basename "$file" + name="$func_basename_result" + + # Set up the ranlib parameters. + oldlib="$destdir/$name" + + func_show_eval "$install_prog \$file \$oldlib" 'exit $?' + + if test -n "$stripme" && test -n "$old_striplib"; then + func_show_eval "$old_striplib $oldlib" 'exit $?' + fi + + # Do each command in the postinstall commands. + func_execute_cmds "$old_postinstall_cmds" 'exit $?' + done + + test -n "$future_libdirs" && \ + func_warning "remember to run \`$progname --finish$future_libdirs'" + + if test -n "$current_libdirs"; then + # Maybe just do a dry run. + $opt_dry_run && current_libdirs=" -n$current_libdirs" + exec_cmd='$SHELL $progpath $preserve_args --finish$current_libdirs' + else + exit $EXIT_SUCCESS + fi +} + +test "$opt_mode" = install && func_mode_install ${1+"$@"} + + +# func_generate_dlsyms outputname originator pic_p +# Extract symbols from dlprefiles and create ${outputname}S.o with +# a dlpreopen symbol table. +func_generate_dlsyms () +{ + $opt_debug + my_outputname="$1" + my_originator="$2" + my_pic_p="${3-no}" + my_prefix=`$ECHO "$my_originator" | sed 's%[^a-zA-Z0-9]%_%g'` + my_dlsyms= + + if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then + if test -n "$NM" && test -n "$global_symbol_pipe"; then + my_dlsyms="${my_outputname}S.c" + else + func_error "not configured to extract global symbols from dlpreopened files" + fi + fi + + if test -n "$my_dlsyms"; then + case $my_dlsyms in + "") ;; + *.c) + # Discover the nlist of each of the dlfiles. + nlist="$output_objdir/${my_outputname}.nm" + + func_show_eval "$RM $nlist ${nlist}S ${nlist}T" + + # Parse the name list into a source file. + func_verbose "creating $output_objdir/$my_dlsyms" + + $opt_dry_run || $ECHO > "$output_objdir/$my_dlsyms" "\ +/* $my_dlsyms - symbol resolution table for \`$my_outputname' dlsym emulation. */ +/* Generated by $PROGRAM (GNU $PACKAGE$TIMESTAMP) $VERSION */ + +#ifdef __cplusplus +extern \"C\" { +#endif + +#if defined(__GNUC__) && (((__GNUC__ == 4) && (__GNUC_MINOR__ >= 4)) || (__GNUC__ > 4)) +#pragma GCC diagnostic ignored \"-Wstrict-prototypes\" +#endif + +/* Keep this code in sync between libtool.m4, ltmain, lt_system.h, and tests. */ +#if defined(_WIN32) || defined(__CYGWIN__) || defined(_WIN32_WCE) +/* DATA imports from DLLs on WIN32 con't be const, because runtime + relocations are performed -- see ld's documentation on pseudo-relocs. */ +# define LT_DLSYM_CONST +#elif defined(__osf__) +/* This system does not cope well with relocations in const data. */ +# define LT_DLSYM_CONST +#else +# define LT_DLSYM_CONST const +#endif + +/* External symbol declarations for the compiler. */\ +" + + if test "$dlself" = yes; then + func_verbose "generating symbol list for \`$output'" + + $opt_dry_run || echo ': @PROGRAM@ ' > "$nlist" + + # Add our own program objects to the symbol list. + progfiles=`$ECHO "$objs$old_deplibs" | $SP2NL | $SED "$lo2o" | $NL2SP` + for progfile in $progfiles; do + func_to_tool_file "$progfile" func_convert_file_msys_to_w32 + func_verbose "extracting global C symbols from \`$func_to_tool_file_result'" + $opt_dry_run || eval "$NM $func_to_tool_file_result | $global_symbol_pipe >> '$nlist'" + done + + if test -n "$exclude_expsyms"; then + $opt_dry_run || { + eval '$EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T' + eval '$MV "$nlist"T "$nlist"' + } + fi + + if test -n "$export_symbols_regex"; then + $opt_dry_run || { + eval '$EGREP -e "$export_symbols_regex" "$nlist" > "$nlist"T' + eval '$MV "$nlist"T "$nlist"' + } + fi + + # Prepare the list of exported symbols + if test -z "$export_symbols"; then + export_symbols="$output_objdir/$outputname.exp" + $opt_dry_run || { + $RM $export_symbols + eval "${SED} -n -e '/^: @PROGRAM@ $/d' -e 's/^.* \(.*\)$/\1/p' "'< "$nlist" > "$export_symbols"' + case $host in + *cygwin* | *mingw* | *cegcc* ) + eval "echo EXPORTS "'> "$output_objdir/$outputname.def"' + eval 'cat "$export_symbols" >> "$output_objdir/$outputname.def"' + ;; + esac + } + else + $opt_dry_run || { + eval "${SED} -e 's/\([].[*^$]\)/\\\\\1/g' -e 's/^/ /' -e 's/$/$/'"' < "$export_symbols" > "$output_objdir/$outputname.exp"' + eval '$GREP -f "$output_objdir/$outputname.exp" < "$nlist" > "$nlist"T' + eval '$MV "$nlist"T "$nlist"' + case $host in + *cygwin* | *mingw* | *cegcc* ) + eval "echo EXPORTS "'> "$output_objdir/$outputname.def"' + eval 'cat "$nlist" >> "$output_objdir/$outputname.def"' + ;; + esac + } + fi + fi + + for dlprefile in $dlprefiles; do + func_verbose "extracting global C symbols from \`$dlprefile'" + func_basename "$dlprefile" + name="$func_basename_result" + case $host in + *cygwin* | *mingw* | *cegcc* ) + # if an import library, we need to obtain dlname + if func_win32_import_lib_p "$dlprefile"; then + func_tr_sh "$dlprefile" + eval "curr_lafile=\$libfile_$func_tr_sh_result" + dlprefile_dlbasename="" + if test -n "$curr_lafile" && func_lalib_p "$curr_lafile"; then + # Use subshell, to avoid clobbering current variable values + dlprefile_dlname=`source "$curr_lafile" && echo "$dlname"` + if test -n "$dlprefile_dlname" ; then + func_basename "$dlprefile_dlname" + dlprefile_dlbasename="$func_basename_result" + else + # no lafile. user explicitly requested -dlpreopen . + $sharedlib_from_linklib_cmd "$dlprefile" + dlprefile_dlbasename=$sharedlib_from_linklib_result + fi + fi + $opt_dry_run || { + if test -n "$dlprefile_dlbasename" ; then + eval '$ECHO ": $dlprefile_dlbasename" >> "$nlist"' + else + func_warning "Could not compute DLL name from $name" + eval '$ECHO ": $name " >> "$nlist"' + fi + func_to_tool_file "$dlprefile" func_convert_file_msys_to_w32 + eval "$NM \"$func_to_tool_file_result\" 2>/dev/null | $global_symbol_pipe | + $SED -e '/I __imp/d' -e 's/I __nm_/D /;s/_nm__//' >> '$nlist'" + } + else # not an import lib + $opt_dry_run || { + eval '$ECHO ": $name " >> "$nlist"' + func_to_tool_file "$dlprefile" func_convert_file_msys_to_w32 + eval "$NM \"$func_to_tool_file_result\" 2>/dev/null | $global_symbol_pipe >> '$nlist'" + } + fi + ;; + *) + $opt_dry_run || { + eval '$ECHO ": $name " >> "$nlist"' + func_to_tool_file "$dlprefile" func_convert_file_msys_to_w32 + eval "$NM \"$func_to_tool_file_result\" 2>/dev/null | $global_symbol_pipe >> '$nlist'" + } + ;; + esac + done + + $opt_dry_run || { + # Make sure we have at least an empty file. + test -f "$nlist" || : > "$nlist" + + if test -n "$exclude_expsyms"; then + $EGREP -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T + $MV "$nlist"T "$nlist" + fi + + # Try sorting and uniquifying the output. + if $GREP -v "^: " < "$nlist" | + if sort -k 3 /dev/null 2>&1; then + sort -k 3 + else + sort +2 + fi | + uniq > "$nlist"S; then + : + else + $GREP -v "^: " < "$nlist" > "$nlist"S + fi + + if test -f "$nlist"S; then + eval "$global_symbol_to_cdecl"' < "$nlist"S >> "$output_objdir/$my_dlsyms"' + else + echo '/* NONE */' >> "$output_objdir/$my_dlsyms" + fi + + echo >> "$output_objdir/$my_dlsyms" "\ + +/* The mapping between symbol names and symbols. */ +typedef struct { + const char *name; + void *address; +} lt_dlsymlist; +extern LT_DLSYM_CONST lt_dlsymlist +lt_${my_prefix}_LTX_preloaded_symbols[]; +LT_DLSYM_CONST lt_dlsymlist +lt_${my_prefix}_LTX_preloaded_symbols[] = +{\ + { \"$my_originator\", (void *) 0 }," + + case $need_lib_prefix in + no) + eval "$global_symbol_to_c_name_address" < "$nlist" >> "$output_objdir/$my_dlsyms" + ;; + *) + eval "$global_symbol_to_c_name_address_lib_prefix" < "$nlist" >> "$output_objdir/$my_dlsyms" + ;; + esac + echo >> "$output_objdir/$my_dlsyms" "\ + {0, (void *) 0} +}; + +/* This works around a problem in FreeBSD linker */ +#ifdef FREEBSD_WORKAROUND +static const void *lt_preloaded_setup() { + return lt_${my_prefix}_LTX_preloaded_symbols; +} +#endif + +#ifdef __cplusplus +} +#endif\ +" + } # !$opt_dry_run + + pic_flag_for_symtable= + case "$compile_command " in + *" -static "*) ;; + *) + case $host in + # compiling the symbol table file with pic_flag works around + # a FreeBSD bug that causes programs to crash when -lm is + # linked before any other PIC object. But we must not use + # pic_flag when linking with -static. The problem exists in + # FreeBSD 2.2.6 and is fixed in FreeBSD 3.1. + *-*-freebsd2*|*-*-freebsd3.0*|*-*-freebsdelf3.0*) + pic_flag_for_symtable=" $pic_flag -DFREEBSD_WORKAROUND" ;; + *-*-hpux*) + pic_flag_for_symtable=" $pic_flag" ;; + *) + if test "X$my_pic_p" != Xno; then + pic_flag_for_symtable=" $pic_flag" + fi + ;; + esac + ;; + esac + symtab_cflags= + for arg in $LTCFLAGS; do + case $arg in + -pie | -fpie | -fPIE) ;; + *) func_append symtab_cflags " $arg" ;; + esac + done + + # Now compile the dynamic symbol file. + func_show_eval '(cd $output_objdir && $LTCC$symtab_cflags -c$no_builtin_flag$pic_flag_for_symtable "$my_dlsyms")' 'exit $?' + + # Clean up the generated files. + func_show_eval '$RM "$output_objdir/$my_dlsyms" "$nlist" "${nlist}S" "${nlist}T"' + + # Transform the symbol file into the correct name. + symfileobj="$output_objdir/${my_outputname}S.$objext" + case $host in + *cygwin* | *mingw* | *cegcc* ) + if test -f "$output_objdir/$my_outputname.def"; then + compile_command=`$ECHO "$compile_command" | $SED "s%@SYMFILE@%$output_objdir/$my_outputname.def $symfileobj%"` + finalize_command=`$ECHO "$finalize_command" | $SED "s%@SYMFILE@%$output_objdir/$my_outputname.def $symfileobj%"` + else + compile_command=`$ECHO "$compile_command" | $SED "s%@SYMFILE@%$symfileobj%"` + finalize_command=`$ECHO "$finalize_command" | $SED "s%@SYMFILE@%$symfileobj%"` + fi + ;; + *) + compile_command=`$ECHO "$compile_command" | $SED "s%@SYMFILE@%$symfileobj%"` + finalize_command=`$ECHO "$finalize_command" | $SED "s%@SYMFILE@%$symfileobj%"` + ;; + esac + ;; + *) + func_fatal_error "unknown suffix for \`$my_dlsyms'" + ;; + esac + else + # We keep going just in case the user didn't refer to + # lt_preloaded_symbols. The linker will fail if global_symbol_pipe + # really was required. + + # Nullify the symbol file. + compile_command=`$ECHO "$compile_command" | $SED "s% @SYMFILE@%%"` + finalize_command=`$ECHO "$finalize_command" | $SED "s% @SYMFILE@%%"` + fi +} + +# func_win32_libid arg +# return the library type of file 'arg' +# +# Need a lot of goo to handle *both* DLLs and import libs +# Has to be a shell function in order to 'eat' the argument +# that is supplied when $file_magic_command is called. +# Despite the name, also deal with 64 bit binaries. +func_win32_libid () +{ + $opt_debug + win32_libid_type="unknown" + win32_fileres=`file -L $1 2>/dev/null` + case $win32_fileres in + *ar\ archive\ import\ library*) # definitely import + win32_libid_type="x86 archive import" + ;; + *ar\ archive*) # could be an import, or static + # Keep the egrep pattern in sync with the one in _LT_CHECK_MAGIC_METHOD. + if eval $OBJDUMP -f $1 | $SED -e '10q' 2>/dev/null | + $EGREP 'file format (pei*-i386(.*architecture: i386)?|pe-arm-wince|pe-x86-64)' >/dev/null; then + func_to_tool_file "$1" func_convert_file_msys_to_w32 + win32_nmres=`eval $NM -f posix -A \"$func_to_tool_file_result\" | + $SED -n -e ' + 1,100{ + / I /{ + s,.*,import, + p + q + } + }'` + case $win32_nmres in + import*) win32_libid_type="x86 archive import";; + *) win32_libid_type="x86 archive static";; + esac + fi + ;; + *DLL*) + win32_libid_type="x86 DLL" + ;; + *executable*) # but shell scripts are "executable" too... + case $win32_fileres in + *MS\ Windows\ PE\ Intel*) + win32_libid_type="x86 DLL" + ;; + esac + ;; + esac + $ECHO "$win32_libid_type" +} + +# func_cygming_dll_for_implib ARG +# +# Platform-specific function to extract the +# name of the DLL associated with the specified +# import library ARG. +# Invoked by eval'ing the libtool variable +# $sharedlib_from_linklib_cmd +# Result is available in the variable +# $sharedlib_from_linklib_result +func_cygming_dll_for_implib () +{ + $opt_debug + sharedlib_from_linklib_result=`$DLLTOOL --identify-strict --identify "$1"` +} + +# func_cygming_dll_for_implib_fallback_core SECTION_NAME LIBNAMEs +# +# The is the core of a fallback implementation of a +# platform-specific function to extract the name of the +# DLL associated with the specified import library LIBNAME. +# +# SECTION_NAME is either .idata$6 or .idata$7, depending +# on the platform and compiler that created the implib. +# +# Echos the name of the DLL associated with the +# specified import library. +func_cygming_dll_for_implib_fallback_core () +{ + $opt_debug + match_literal=`$ECHO "$1" | $SED "$sed_make_literal_regex"` + $OBJDUMP -s --section "$1" "$2" 2>/dev/null | + $SED '/^Contents of section '"$match_literal"':/{ + # Place marker at beginning of archive member dllname section + s/.*/====MARK====/ + p + d + } + # These lines can sometimes be longer than 43 characters, but + # are always uninteresting + /:[ ]*file format pe[i]\{,1\}-/d + /^In archive [^:]*:/d + # Ensure marker is printed + /^====MARK====/p + # Remove all lines with less than 43 characters + /^.\{43\}/!d + # From remaining lines, remove first 43 characters + s/^.\{43\}//' | + $SED -n ' + # Join marker and all lines until next marker into a single line + /^====MARK====/ b para + H + $ b para + b + :para + x + s/\n//g + # Remove the marker + s/^====MARK====// + # Remove trailing dots and whitespace + s/[\. \t]*$// + # Print + /./p' | + # we now have a list, one entry per line, of the stringified + # contents of the appropriate section of all members of the + # archive which possess that section. Heuristic: eliminate + # all those which have a first or second character that is + # a '.' (that is, objdump's representation of an unprintable + # character.) This should work for all archives with less than + # 0x302f exports -- but will fail for DLLs whose name actually + # begins with a literal '.' or a single character followed by + # a '.'. + # + # Of those that remain, print the first one. + $SED -e '/^\./d;/^.\./d;q' +} + +# func_cygming_gnu_implib_p ARG +# This predicate returns with zero status (TRUE) if +# ARG is a GNU/binutils-style import library. Returns +# with nonzero status (FALSE) otherwise. +func_cygming_gnu_implib_p () +{ + $opt_debug + func_to_tool_file "$1" func_convert_file_msys_to_w32 + func_cygming_gnu_implib_tmp=`$NM "$func_to_tool_file_result" | eval "$global_symbol_pipe" | $EGREP ' (_head_[A-Za-z0-9_]+_[ad]l*|[A-Za-z0-9_]+_[ad]l*_iname)$'` + test -n "$func_cygming_gnu_implib_tmp" +} + +# func_cygming_ms_implib_p ARG +# This predicate returns with zero status (TRUE) if +# ARG is an MS-style import library. Returns +# with nonzero status (FALSE) otherwise. +func_cygming_ms_implib_p () +{ + $opt_debug + func_to_tool_file "$1" func_convert_file_msys_to_w32 + func_cygming_ms_implib_tmp=`$NM "$func_to_tool_file_result" | eval "$global_symbol_pipe" | $GREP '_NULL_IMPORT_DESCRIPTOR'` + test -n "$func_cygming_ms_implib_tmp" +} + +# func_cygming_dll_for_implib_fallback ARG +# Platform-specific function to extract the +# name of the DLL associated with the specified +# import library ARG. +# +# This fallback implementation is for use when $DLLTOOL +# does not support the --identify-strict option. +# Invoked by eval'ing the libtool variable +# $sharedlib_from_linklib_cmd +# Result is available in the variable +# $sharedlib_from_linklib_result +func_cygming_dll_for_implib_fallback () +{ + $opt_debug + if func_cygming_gnu_implib_p "$1" ; then + # binutils import library + sharedlib_from_linklib_result=`func_cygming_dll_for_implib_fallback_core '.idata$7' "$1"` + elif func_cygming_ms_implib_p "$1" ; then + # ms-generated import library + sharedlib_from_linklib_result=`func_cygming_dll_for_implib_fallback_core '.idata$6' "$1"` + else + # unknown + sharedlib_from_linklib_result="" + fi +} + + +# func_extract_an_archive dir oldlib +func_extract_an_archive () +{ + $opt_debug + f_ex_an_ar_dir="$1"; shift + f_ex_an_ar_oldlib="$1" + if test "$lock_old_archive_extraction" = yes; then + lockfile=$f_ex_an_ar_oldlib.lock + until $opt_dry_run || ln "$progpath" "$lockfile" 2>/dev/null; do + func_echo "Waiting for $lockfile to be removed" + sleep 2 + done + fi + func_show_eval "(cd \$f_ex_an_ar_dir && $AR x \"\$f_ex_an_ar_oldlib\")" \ + 'stat=$?; rm -f "$lockfile"; exit $stat' + if test "$lock_old_archive_extraction" = yes; then + $opt_dry_run || rm -f "$lockfile" + fi + if ($AR t "$f_ex_an_ar_oldlib" | sort | sort -uc >/dev/null 2>&1); then + : + else + func_fatal_error "object name conflicts in archive: $f_ex_an_ar_dir/$f_ex_an_ar_oldlib" + fi +} + + +# func_extract_archives gentop oldlib ... +func_extract_archives () +{ + $opt_debug + my_gentop="$1"; shift + my_oldlibs=${1+"$@"} + my_oldobjs="" + my_xlib="" + my_xabs="" + my_xdir="" + + for my_xlib in $my_oldlibs; do + # Extract the objects. + case $my_xlib in + [\\/]* | [A-Za-z]:[\\/]*) my_xabs="$my_xlib" ;; + *) my_xabs=`pwd`"/$my_xlib" ;; + esac + func_basename "$my_xlib" + my_xlib="$func_basename_result" + my_xlib_u=$my_xlib + while :; do + case " $extracted_archives " in + *" $my_xlib_u "*) + func_arith $extracted_serial + 1 + extracted_serial=$func_arith_result + my_xlib_u=lt$extracted_serial-$my_xlib ;; + *) break ;; + esac + done + extracted_archives="$extracted_archives $my_xlib_u" + my_xdir="$my_gentop/$my_xlib_u" + + func_mkdir_p "$my_xdir" + + case $host in + *-darwin*) + func_verbose "Extracting $my_xabs" + # Do not bother doing anything if just a dry run + $opt_dry_run || { + darwin_orig_dir=`pwd` + cd $my_xdir || exit $? + darwin_archive=$my_xabs + darwin_curdir=`pwd` + darwin_base_archive=`basename "$darwin_archive"` + darwin_arches=`$LIPO -info "$darwin_archive" 2>/dev/null | $GREP Architectures 2>/dev/null || true` + if test -n "$darwin_arches"; then + darwin_arches=`$ECHO "$darwin_arches" | $SED -e 's/.*are://'` + darwin_arch= + func_verbose "$darwin_base_archive has multiple architectures $darwin_arches" + for darwin_arch in $darwin_arches ; do + func_mkdir_p "unfat-$$/${darwin_base_archive}-${darwin_arch}" + $LIPO -thin $darwin_arch -output "unfat-$$/${darwin_base_archive}-${darwin_arch}/${darwin_base_archive}" "${darwin_archive}" + cd "unfat-$$/${darwin_base_archive}-${darwin_arch}" + func_extract_an_archive "`pwd`" "${darwin_base_archive}" + cd "$darwin_curdir" + $RM "unfat-$$/${darwin_base_archive}-${darwin_arch}/${darwin_base_archive}" + done # $darwin_arches + ## Okay now we've a bunch of thin objects, gotta fatten them up :) + darwin_filelist=`find unfat-$$ -type f -name \*.o -print -o -name \*.lo -print | $SED -e "$basename" | sort -u` + darwin_file= + darwin_files= + for darwin_file in $darwin_filelist; do + darwin_files=`find unfat-$$ -name $darwin_file -print | sort | $NL2SP` + $LIPO -create -output "$darwin_file" $darwin_files + done # $darwin_filelist + $RM -rf unfat-$$ + cd "$darwin_orig_dir" + else + cd $darwin_orig_dir + func_extract_an_archive "$my_xdir" "$my_xabs" + fi # $darwin_arches + } # !$opt_dry_run + ;; + *) + func_extract_an_archive "$my_xdir" "$my_xabs" + ;; + esac + my_oldobjs="$my_oldobjs "`find $my_xdir -name \*.$objext -print -o -name \*.lo -print | sort | $NL2SP` + done + + func_extract_archives_result="$my_oldobjs" +} + + +# func_emit_wrapper [arg=no] +# +# Emit a libtool wrapper script on stdout. +# Don't directly open a file because we may want to +# incorporate the script contents within a cygwin/mingw +# wrapper executable. Must ONLY be called from within +# func_mode_link because it depends on a number of variables +# set therein. +# +# ARG is the value that the WRAPPER_SCRIPT_BELONGS_IN_OBJDIR +# variable will take. If 'yes', then the emitted script +# will assume that the directory in which it is stored is +# the $objdir directory. This is a cygwin/mingw-specific +# behavior. +func_emit_wrapper () +{ + func_emit_wrapper_arg1=${1-no} + + $ECHO "\ +#! $SHELL + +# $output - temporary wrapper script for $objdir/$outputname +# Generated by $PROGRAM (GNU $PACKAGE$TIMESTAMP) $VERSION +# +# The $output program cannot be directly executed until all the libtool +# libraries that it depends on are installed. +# +# This wrapper script should never be moved out of the build directory. +# If it is, it will not operate correctly. + +# Sed substitution that helps us do robust quoting. It backslashifies +# metacharacters that are still active within double-quoted strings. +sed_quote_subst='$sed_quote_subst' + +# 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+\"\$@\"}'='\"\$@\"' + setopt NO_GLOB_SUBST +else + case \`(set -o) 2>/dev/null\` in *posix*) set -o posix;; esac +fi +BIN_SH=xpg4; export BIN_SH # for Tru64 +DUALCASE=1; export DUALCASE # for MKS sh + +# The HP-UX ksh and POSIX shell print the target directory to stdout +# if CDPATH is set. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + +relink_command=\"$relink_command\" + +# This environment variable determines our operation mode. +if test \"\$libtool_install_magic\" = \"$magic\"; then + # install mode needs the following variables: + generated_by_libtool_version='$macro_version' + notinst_deplibs='$notinst_deplibs' +else + # When we are sourced in execute mode, \$file and \$ECHO are already set. + if test \"\$libtool_execute_magic\" != \"$magic\"; then + file=\"\$0\"" + + qECHO=`$ECHO "$ECHO" | $SED "$sed_quote_subst"` + $ECHO "\ + +# A function that is used when there is no print builtin or printf. +func_fallback_echo () +{ + eval 'cat <<_LTECHO_EOF +\$1 +_LTECHO_EOF' +} + ECHO=\"$qECHO\" + fi + +# Very basic option parsing. These options are (a) specific to +# the libtool wrapper, (b) are identical between the wrapper +# /script/ and the wrapper /executable/ which is used only on +# windows platforms, and (c) all begin with the string "--lt-" +# (application programs are unlikely to have options which match +# this pattern). +# +# There are only two supported options: --lt-debug and +# --lt-dump-script. There is, deliberately, no --lt-help. +# +# The first argument to this parsing function should be the +# script's $0 value, followed by "$@". +lt_option_debug= +func_parse_lt_options () +{ + lt_script_arg0=\$0 + shift + for lt_opt + do + case \"\$lt_opt\" in + --lt-debug) lt_option_debug=1 ;; + --lt-dump-script) + lt_dump_D=\`\$ECHO \"X\$lt_script_arg0\" | $SED -e 's/^X//' -e 's%/[^/]*$%%'\` + test \"X\$lt_dump_D\" = \"X\$lt_script_arg0\" && lt_dump_D=. + lt_dump_F=\`\$ECHO \"X\$lt_script_arg0\" | $SED -e 's/^X//' -e 's%^.*/%%'\` + cat \"\$lt_dump_D/\$lt_dump_F\" + exit 0 + ;; + --lt-*) + \$ECHO \"Unrecognized --lt- option: '\$lt_opt'\" 1>&2 + exit 1 + ;; + esac + done + + # Print the debug banner immediately: + if test -n \"\$lt_option_debug\"; then + echo \"${outputname}:${output}:\${LINENO}: libtool wrapper (GNU $PACKAGE$TIMESTAMP) $VERSION\" 1>&2 + fi +} + +# Used when --lt-debug. Prints its arguments to stdout +# (redirection is the responsibility of the caller) +func_lt_dump_args () +{ + lt_dump_args_N=1; + for lt_arg + do + \$ECHO \"${outputname}:${output}:\${LINENO}: newargv[\$lt_dump_args_N]: \$lt_arg\" + lt_dump_args_N=\`expr \$lt_dump_args_N + 1\` + done +} + +# Core function for launching the target application +func_exec_program_core () +{ +" + case $host in + # Backslashes separate directories on plain windows + *-*-mingw | *-*-os2* | *-cegcc*) + $ECHO "\ + if test -n \"\$lt_option_debug\"; then + \$ECHO \"${outputname}:${output}:\${LINENO}: newargv[0]: \$progdir\\\\\$program\" 1>&2 + func_lt_dump_args \${1+\"\$@\"} 1>&2 + fi + exec \"\$progdir\\\\\$program\" \${1+\"\$@\"} +" + ;; + + *) + $ECHO "\ + if test -n \"\$lt_option_debug\"; then + \$ECHO \"${outputname}:${output}:\${LINENO}: newargv[0]: \$progdir/\$program\" 1>&2 + func_lt_dump_args \${1+\"\$@\"} 1>&2 + fi + exec \"\$progdir/\$program\" \${1+\"\$@\"} +" + ;; + esac + $ECHO "\ + \$ECHO \"\$0: cannot exec \$program \$*\" 1>&2 + exit 1 +} + +# A function to encapsulate launching the target application +# Strips options in the --lt-* namespace from \$@ and +# launches target application with the remaining arguments. +func_exec_program () +{ + for lt_wr_arg + do + case \$lt_wr_arg in + --lt-*) ;; + *) set x \"\$@\" \"\$lt_wr_arg\"; shift;; + esac + shift + done + func_exec_program_core \${1+\"\$@\"} +} + + # Parse options + func_parse_lt_options \"\$0\" \${1+\"\$@\"} + + # Find the directory that this script lives in. + thisdir=\`\$ECHO \"\$file\" | $SED 's%/[^/]*$%%'\` + test \"x\$thisdir\" = \"x\$file\" && thisdir=. + + # Follow symbolic links until we get to the real thisdir. + file=\`ls -ld \"\$file\" | $SED -n 's/.*-> //p'\` + while test -n \"\$file\"; do + destdir=\`\$ECHO \"\$file\" | $SED 's%/[^/]*\$%%'\` + + # If there was a directory component, then change thisdir. + if test \"x\$destdir\" != \"x\$file\"; then + case \"\$destdir\" in + [\\\\/]* | [A-Za-z]:[\\\\/]*) thisdir=\"\$destdir\" ;; + *) thisdir=\"\$thisdir/\$destdir\" ;; + esac + fi + + file=\`\$ECHO \"\$file\" | $SED 's%^.*/%%'\` + file=\`ls -ld \"\$thisdir/\$file\" | $SED -n 's/.*-> //p'\` + done + + # Usually 'no', except on cygwin/mingw when embedded into + # the cwrapper. + WRAPPER_SCRIPT_BELONGS_IN_OBJDIR=$func_emit_wrapper_arg1 + if test \"\$WRAPPER_SCRIPT_BELONGS_IN_OBJDIR\" = \"yes\"; then + # special case for '.' + if test \"\$thisdir\" = \".\"; then + thisdir=\`pwd\` + fi + # remove .libs from thisdir + case \"\$thisdir\" in + *[\\\\/]$objdir ) thisdir=\`\$ECHO \"\$thisdir\" | $SED 's%[\\\\/][^\\\\/]*$%%'\` ;; + $objdir ) thisdir=. ;; + esac + fi + + # Try to get the absolute directory name. + absdir=\`cd \"\$thisdir\" && pwd\` + test -n \"\$absdir\" && thisdir=\"\$absdir\" +" + + if test "$fast_install" = yes; then + $ECHO "\ + program=lt-'$outputname'$exeext + progdir=\"\$thisdir/$objdir\" + + if test ! -f \"\$progdir/\$program\" || + { file=\`ls -1dt \"\$progdir/\$program\" \"\$progdir/../\$program\" 2>/dev/null | ${SED} 1q\`; \\ + test \"X\$file\" != \"X\$progdir/\$program\"; }; then + + file=\"\$\$-\$program\" + + if test ! -d \"\$progdir\"; then + $MKDIR \"\$progdir\" + else + $RM \"\$progdir/\$file\" + fi" + + $ECHO "\ + + # relink executable if necessary + if test -n \"\$relink_command\"; then + if relink_command_output=\`eval \$relink_command 2>&1\`; then : + else + $ECHO \"\$relink_command_output\" >&2 + $RM \"\$progdir/\$file\" + exit 1 + fi + fi + + $MV \"\$progdir/\$file\" \"\$progdir/\$program\" 2>/dev/null || + { $RM \"\$progdir/\$program\"; + $MV \"\$progdir/\$file\" \"\$progdir/\$program\"; } + $RM \"\$progdir/\$file\" + fi" + else + $ECHO "\ + program='$outputname' + progdir=\"\$thisdir/$objdir\" +" + fi + + $ECHO "\ + + if test -f \"\$progdir/\$program\"; then" + + # fixup the dll searchpath if we need to. + # + # Fix the DLL searchpath if we need to. Do this before prepending + # to shlibpath, because on Windows, both are PATH and uninstalled + # libraries must come first. + if test -n "$dllsearchpath"; then + $ECHO "\ + # Add the dll search path components to the executable PATH + PATH=$dllsearchpath:\$PATH +" + fi + + # Export our shlibpath_var if we have one. + if test "$shlibpath_overrides_runpath" = yes && test -n "$shlibpath_var" && test -n "$temp_rpath"; then + $ECHO "\ + # Add our own library path to $shlibpath_var + $shlibpath_var=\"$temp_rpath\$$shlibpath_var\" + + # Some systems cannot cope with colon-terminated $shlibpath_var + # The second colon is a workaround for a bug in BeOS R4 sed + $shlibpath_var=\`\$ECHO \"\$$shlibpath_var\" | $SED 's/::*\$//'\` + + export $shlibpath_var +" + fi + + $ECHO "\ + if test \"\$libtool_execute_magic\" != \"$magic\"; then + # Run the actual program with our arguments. + func_exec_program \${1+\"\$@\"} + fi + else + # The program doesn't exist. + \$ECHO \"\$0: error: \\\`\$progdir/\$program' does not exist\" 1>&2 + \$ECHO \"This script is just a wrapper for \$program.\" 1>&2 + \$ECHO \"See the $PACKAGE documentation for more information.\" 1>&2 + exit 1 + fi +fi\ +" +} + + +# func_emit_cwrapperexe_src +# emit the source code for a wrapper executable on stdout +# Must ONLY be called from within func_mode_link because +# it depends on a number of variable set therein. +func_emit_cwrapperexe_src () +{ + cat < +#include +#ifdef _MSC_VER +# include +# include +# include +#else +# include +# include +# ifdef __CYGWIN__ +# include +# endif +#endif +#include +#include +#include +#include +#include +#include +#include +#include + +/* declarations of non-ANSI functions */ +#if defined(__MINGW32__) +# ifdef __STRICT_ANSI__ +int _putenv (const char *); +# endif +#elif defined(__CYGWIN__) +# ifdef __STRICT_ANSI__ +char *realpath (const char *, char *); +int putenv (char *); +int setenv (const char *, const char *, int); +# endif +/* #elif defined (other platforms) ... */ +#endif + +/* portability defines, excluding path handling macros */ +#if defined(_MSC_VER) +# define setmode _setmode +# define stat _stat +# define chmod _chmod +# define getcwd _getcwd +# define putenv _putenv +# define S_IXUSR _S_IEXEC +# ifndef _INTPTR_T_DEFINED +# define _INTPTR_T_DEFINED +# define intptr_t int +# endif +#elif defined(__MINGW32__) +# define setmode _setmode +# define stat _stat +# define chmod _chmod +# define getcwd _getcwd +# define putenv _putenv +#elif defined(__CYGWIN__) +# define HAVE_SETENV +# define FOPEN_WB "wb" +/* #elif defined (other platforms) ... */ +#endif + +#if defined(PATH_MAX) +# define LT_PATHMAX PATH_MAX +#elif defined(MAXPATHLEN) +# define LT_PATHMAX MAXPATHLEN +#else +# define LT_PATHMAX 1024 +#endif + +#ifndef S_IXOTH +# define S_IXOTH 0 +#endif +#ifndef S_IXGRP +# define S_IXGRP 0 +#endif + +/* path handling portability macros */ +#ifndef DIR_SEPARATOR +# define DIR_SEPARATOR '/' +# define PATH_SEPARATOR ':' +#endif + +#if defined (_WIN32) || defined (__MSDOS__) || defined (__DJGPP__) || \ + defined (__OS2__) +# define HAVE_DOS_BASED_FILE_SYSTEM +# define FOPEN_WB "wb" +# ifndef DIR_SEPARATOR_2 +# define DIR_SEPARATOR_2 '\\' +# endif +# ifndef PATH_SEPARATOR_2 +# define PATH_SEPARATOR_2 ';' +# endif +#endif + +#ifndef DIR_SEPARATOR_2 +# define IS_DIR_SEPARATOR(ch) ((ch) == DIR_SEPARATOR) +#else /* DIR_SEPARATOR_2 */ +# define IS_DIR_SEPARATOR(ch) \ + (((ch) == DIR_SEPARATOR) || ((ch) == DIR_SEPARATOR_2)) +#endif /* DIR_SEPARATOR_2 */ + +#ifndef PATH_SEPARATOR_2 +# define IS_PATH_SEPARATOR(ch) ((ch) == PATH_SEPARATOR) +#else /* PATH_SEPARATOR_2 */ +# define IS_PATH_SEPARATOR(ch) ((ch) == PATH_SEPARATOR_2) +#endif /* PATH_SEPARATOR_2 */ + +#ifndef FOPEN_WB +# define FOPEN_WB "w" +#endif +#ifndef _O_BINARY +# define _O_BINARY 0 +#endif + +#define XMALLOC(type, num) ((type *) xmalloc ((num) * sizeof(type))) +#define XFREE(stale) do { \ + if (stale) { free ((void *) stale); stale = 0; } \ +} while (0) + +#if defined(LT_DEBUGWRAPPER) +static int lt_debug = 1; +#else +static int lt_debug = 0; +#endif + +const char *program_name = "libtool-wrapper"; /* in case xstrdup fails */ + +void *xmalloc (size_t num); +char *xstrdup (const char *string); +const char *base_name (const char *name); +char *find_executable (const char *wrapper); +char *chase_symlinks (const char *pathspec); +int make_executable (const char *path); +int check_executable (const char *path); +char *strendzap (char *str, const char *pat); +void lt_debugprintf (const char *file, int line, const char *fmt, ...); +void lt_fatal (const char *file, int line, const char *message, ...); +static const char *nonnull (const char *s); +static const char *nonempty (const char *s); +void lt_setenv (const char *name, const char *value); +char *lt_extend_str (const char *orig_value, const char *add, int to_end); +void lt_update_exe_path (const char *name, const char *value); +void lt_update_lib_path (const char *name, const char *value); +char **prepare_spawn (char **argv); +void lt_dump_script (FILE *f); +EOF + + cat <= 0) + && (st.st_mode & (S_IXUSR | S_IXGRP | S_IXOTH))) + return 1; + else + return 0; +} + +int +make_executable (const char *path) +{ + int rval = 0; + struct stat st; + + lt_debugprintf (__FILE__, __LINE__, "(make_executable): %s\n", + nonempty (path)); + if ((!path) || (!*path)) + return 0; + + if (stat (path, &st) >= 0) + { + rval = chmod (path, st.st_mode | S_IXOTH | S_IXGRP | S_IXUSR); + } + return rval; +} + +/* Searches for the full path of the wrapper. Returns + newly allocated full path name if found, NULL otherwise + Does not chase symlinks, even on platforms that support them. +*/ +char * +find_executable (const char *wrapper) +{ + int has_slash = 0; + const char *p; + const char *p_next; + /* static buffer for getcwd */ + char tmp[LT_PATHMAX + 1]; + int tmp_len; + char *concat_name; + + lt_debugprintf (__FILE__, __LINE__, "(find_executable): %s\n", + nonempty (wrapper)); + + if ((wrapper == NULL) || (*wrapper == '\0')) + return NULL; + + /* Absolute path? */ +#if defined (HAVE_DOS_BASED_FILE_SYSTEM) + if (isalpha ((unsigned char) wrapper[0]) && wrapper[1] == ':') + { + concat_name = xstrdup (wrapper); + if (check_executable (concat_name)) + return concat_name; + XFREE (concat_name); + } + else + { +#endif + if (IS_DIR_SEPARATOR (wrapper[0])) + { + concat_name = xstrdup (wrapper); + if (check_executable (concat_name)) + return concat_name; + XFREE (concat_name); + } +#if defined (HAVE_DOS_BASED_FILE_SYSTEM) + } +#endif + + for (p = wrapper; *p; p++) + if (*p == '/') + { + has_slash = 1; + break; + } + if (!has_slash) + { + /* no slashes; search PATH */ + const char *path = getenv ("PATH"); + if (path != NULL) + { + for (p = path; *p; p = p_next) + { + const char *q; + size_t p_len; + for (q = p; *q; q++) + if (IS_PATH_SEPARATOR (*q)) + break; + p_len = q - p; + p_next = (*q == '\0' ? q : q + 1); + if (p_len == 0) + { + /* empty path: current directory */ + if (getcwd (tmp, LT_PATHMAX) == NULL) + lt_fatal (__FILE__, __LINE__, "getcwd failed: %s", + nonnull (strerror (errno))); + tmp_len = strlen (tmp); + concat_name = + XMALLOC (char, tmp_len + 1 + strlen (wrapper) + 1); + memcpy (concat_name, tmp, tmp_len); + concat_name[tmp_len] = '/'; + strcpy (concat_name + tmp_len + 1, wrapper); + } + else + { + concat_name = + XMALLOC (char, p_len + 1 + strlen (wrapper) + 1); + memcpy (concat_name, p, p_len); + concat_name[p_len] = '/'; + strcpy (concat_name + p_len + 1, wrapper); + } + if (check_executable (concat_name)) + return concat_name; + XFREE (concat_name); + } + } + /* not found in PATH; assume curdir */ + } + /* Relative path | not found in path: prepend cwd */ + if (getcwd (tmp, LT_PATHMAX) == NULL) + lt_fatal (__FILE__, __LINE__, "getcwd failed: %s", + nonnull (strerror (errno))); + tmp_len = strlen (tmp); + concat_name = XMALLOC (char, tmp_len + 1 + strlen (wrapper) + 1); + memcpy (concat_name, tmp, tmp_len); + concat_name[tmp_len] = '/'; + strcpy (concat_name + tmp_len + 1, wrapper); + + if (check_executable (concat_name)) + return concat_name; + XFREE (concat_name); + return NULL; +} + +char * +chase_symlinks (const char *pathspec) +{ +#ifndef S_ISLNK + return xstrdup (pathspec); +#else + char buf[LT_PATHMAX]; + struct stat s; + char *tmp_pathspec = xstrdup (pathspec); + char *p; + int has_symlinks = 0; + while (strlen (tmp_pathspec) && !has_symlinks) + { + lt_debugprintf (__FILE__, __LINE__, + "checking path component for symlinks: %s\n", + tmp_pathspec); + if (lstat (tmp_pathspec, &s) == 0) + { + if (S_ISLNK (s.st_mode) != 0) + { + has_symlinks = 1; + break; + } + + /* search backwards for last DIR_SEPARATOR */ + p = tmp_pathspec + strlen (tmp_pathspec) - 1; + while ((p > tmp_pathspec) && (!IS_DIR_SEPARATOR (*p))) + p--; + if ((p == tmp_pathspec) && (!IS_DIR_SEPARATOR (*p))) + { + /* no more DIR_SEPARATORS left */ + break; + } + *p = '\0'; + } + else + { + lt_fatal (__FILE__, __LINE__, + "error accessing file \"%s\": %s", + tmp_pathspec, nonnull (strerror (errno))); + } + } + XFREE (tmp_pathspec); + + if (!has_symlinks) + { + return xstrdup (pathspec); + } + + tmp_pathspec = realpath (pathspec, buf); + if (tmp_pathspec == 0) + { + lt_fatal (__FILE__, __LINE__, + "could not follow symlinks for %s", pathspec); + } + return xstrdup (tmp_pathspec); +#endif +} + +char * +strendzap (char *str, const char *pat) +{ + size_t len, patlen; + + assert (str != NULL); + assert (pat != NULL); + + len = strlen (str); + patlen = strlen (pat); + + if (patlen <= len) + { + str += len - patlen; + if (strcmp (str, pat) == 0) + *str = '\0'; + } + return str; +} + +void +lt_debugprintf (const char *file, int line, const char *fmt, ...) +{ + va_list args; + if (lt_debug) + { + (void) fprintf (stderr, "%s:%s:%d: ", program_name, file, line); + va_start (args, fmt); + (void) vfprintf (stderr, fmt, args); + va_end (args); + } +} + +static void +lt_error_core (int exit_status, const char *file, + int line, const char *mode, + const char *message, va_list ap) +{ + fprintf (stderr, "%s:%s:%d: %s: ", program_name, file, line, mode); + vfprintf (stderr, message, ap); + fprintf (stderr, ".\n"); + + if (exit_status >= 0) + exit (exit_status); +} + +void +lt_fatal (const char *file, int line, const char *message, ...) +{ + va_list ap; + va_start (ap, message); + lt_error_core (EXIT_FAILURE, file, line, "FATAL", message, ap); + va_end (ap); +} + +static const char * +nonnull (const char *s) +{ + return s ? s : "(null)"; +} + +static const char * +nonempty (const char *s) +{ + return (s && !*s) ? "(empty)" : nonnull (s); +} + +void +lt_setenv (const char *name, const char *value) +{ + lt_debugprintf (__FILE__, __LINE__, + "(lt_setenv) setting '%s' to '%s'\n", + nonnull (name), nonnull (value)); + { +#ifdef HAVE_SETENV + /* always make a copy, for consistency with !HAVE_SETENV */ + char *str = xstrdup (value); + setenv (name, str, 1); +#else + int len = strlen (name) + 1 + strlen (value) + 1; + char *str = XMALLOC (char, len); + sprintf (str, "%s=%s", name, value); + if (putenv (str) != EXIT_SUCCESS) + { + XFREE (str); + } +#endif + } +} + +char * +lt_extend_str (const char *orig_value, const char *add, int to_end) +{ + char *new_value; + if (orig_value && *orig_value) + { + int orig_value_len = strlen (orig_value); + int add_len = strlen (add); + new_value = XMALLOC (char, add_len + orig_value_len + 1); + if (to_end) + { + strcpy (new_value, orig_value); + strcpy (new_value + orig_value_len, add); + } + else + { + strcpy (new_value, add); + strcpy (new_value + add_len, orig_value); + } + } + else + { + new_value = xstrdup (add); + } + return new_value; +} + +void +lt_update_exe_path (const char *name, const char *value) +{ + lt_debugprintf (__FILE__, __LINE__, + "(lt_update_exe_path) modifying '%s' by prepending '%s'\n", + nonnull (name), nonnull (value)); + + if (name && *name && value && *value) + { + char *new_value = lt_extend_str (getenv (name), value, 0); + /* some systems can't cope with a ':'-terminated path #' */ + int len = strlen (new_value); + while (((len = strlen (new_value)) > 0) && IS_PATH_SEPARATOR (new_value[len-1])) + { + new_value[len-1] = '\0'; + } + lt_setenv (name, new_value); + XFREE (new_value); + } +} + +void +lt_update_lib_path (const char *name, const char *value) +{ + lt_debugprintf (__FILE__, __LINE__, + "(lt_update_lib_path) modifying '%s' by prepending '%s'\n", + nonnull (name), nonnull (value)); + + if (name && *name && value && *value) + { + char *new_value = lt_extend_str (getenv (name), value, 0); + lt_setenv (name, new_value); + XFREE (new_value); + } +} + +EOF + case $host_os in + mingw*) + cat <<"EOF" + +/* Prepares an argument vector before calling spawn(). + Note that spawn() does not by itself call the command interpreter + (getenv ("COMSPEC") != NULL ? getenv ("COMSPEC") : + ({ OSVERSIONINFO v; v.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); + GetVersionEx(&v); + v.dwPlatformId == VER_PLATFORM_WIN32_NT; + }) ? "cmd.exe" : "command.com"). + Instead it simply concatenates the arguments, separated by ' ', and calls + CreateProcess(). We must quote the arguments since Win32 CreateProcess() + interprets characters like ' ', '\t', '\\', '"' (but not '<' and '>') in a + special way: + - Space and tab are interpreted as delimiters. They are not treated as + delimiters if they are surrounded by double quotes: "...". + - Unescaped double quotes are removed from the input. Their only effect is + that within double quotes, space and tab are treated like normal + characters. + - Backslashes not followed by double quotes are not special. + - But 2*n+1 backslashes followed by a double quote become + n backslashes followed by a double quote (n >= 0): + \" -> " + \\\" -> \" + \\\\\" -> \\" + */ +#define SHELL_SPECIAL_CHARS "\"\\ \001\002\003\004\005\006\007\010\011\012\013\014\015\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037" +#define SHELL_SPACE_CHARS " \001\002\003\004\005\006\007\010\011\012\013\014\015\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037" +char ** +prepare_spawn (char **argv) +{ + size_t argc; + char **new_argv; + size_t i; + + /* Count number of arguments. */ + for (argc = 0; argv[argc] != NULL; argc++) + ; + + /* Allocate new argument vector. */ + new_argv = XMALLOC (char *, argc + 1); + + /* Put quoted arguments into the new argument vector. */ + for (i = 0; i < argc; i++) + { + const char *string = argv[i]; + + if (string[0] == '\0') + new_argv[i] = xstrdup ("\"\""); + else if (strpbrk (string, SHELL_SPECIAL_CHARS) != NULL) + { + int quote_around = (strpbrk (string, SHELL_SPACE_CHARS) != NULL); + size_t length; + unsigned int backslashes; + const char *s; + char *quoted_string; + char *p; + + length = 0; + backslashes = 0; + if (quote_around) + length++; + for (s = string; *s != '\0'; s++) + { + char c = *s; + if (c == '"') + length += backslashes + 1; + length++; + if (c == '\\') + backslashes++; + else + backslashes = 0; + } + if (quote_around) + length += backslashes + 1; + + quoted_string = XMALLOC (char, length + 1); + + p = quoted_string; + backslashes = 0; + if (quote_around) + *p++ = '"'; + for (s = string; *s != '\0'; s++) + { + char c = *s; + if (c == '"') + { + unsigned int j; + for (j = backslashes + 1; j > 0; j--) + *p++ = '\\'; + } + *p++ = c; + if (c == '\\') + backslashes++; + else + backslashes = 0; + } + if (quote_around) + { + unsigned int j; + for (j = backslashes; j > 0; j--) + *p++ = '\\'; + *p++ = '"'; + } + *p = '\0'; + + new_argv[i] = quoted_string; + } + else + new_argv[i] = (char *) string; + } + new_argv[argc] = NULL; + + return new_argv; +} +EOF + ;; + esac + + cat <<"EOF" +void lt_dump_script (FILE* f) +{ +EOF + func_emit_wrapper yes | + $SED -e 's/\([\\"]\)/\\\1/g' \ + -e 's/^/ fputs ("/' -e 's/$/\\n", f);/' + + cat <<"EOF" +} +EOF +} +# end: func_emit_cwrapperexe_src + +# func_win32_import_lib_p ARG +# True if ARG is an import lib, as indicated by $file_magic_cmd +func_win32_import_lib_p () +{ + $opt_debug + case `eval $file_magic_cmd \"\$1\" 2>/dev/null | $SED -e 10q` in + *import*) : ;; + *) false ;; + esac +} + +# func_mode_link arg... +func_mode_link () +{ + $opt_debug + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*) + # It is impossible to link a dll without this setting, and + # we shouldn't force the makefile maintainer to figure out + # which system we are compiling for in order to pass an extra + # flag for every libtool invocation. + # allow_undefined=no + + # FIXME: Unfortunately, there are problems with the above when trying + # to make a dll which has undefined symbols, in which case not + # even a static library is built. For now, we need to specify + # -no-undefined on the libtool link line when we can be certain + # that all symbols are satisfied, otherwise we get a static library. + allow_undefined=yes + ;; + *) + allow_undefined=yes + ;; + esac + libtool_args=$nonopt + base_compile="$nonopt $@" + compile_command=$nonopt + finalize_command=$nonopt + + compile_rpath= + finalize_rpath= + compile_shlibpath= + finalize_shlibpath= + convenience= + old_convenience= + deplibs= + old_deplibs= + compiler_flags= + linker_flags= + dllsearchpath= + lib_search_path=`pwd` + inst_prefix_dir= + new_inherited_linker_flags= + + avoid_version=no + bindir= + dlfiles= + dlprefiles= + dlself=no + export_dynamic=no + export_symbols= + export_symbols_regex= + generated= + libobjs= + ltlibs= + module=no + no_install=no + objs= + non_pic_objects= + precious_files_regex= + prefer_static_libs=no + preload=no + prev= + prevarg= + release= + rpath= + xrpath= + perm_rpath= + temp_rpath= + thread_safe=no + vinfo= + vinfo_number=no + weak_libs= + single_module="${wl}-single_module" + func_infer_tag $base_compile + + # We need to know -static, to get the right output filenames. + for arg + do + case $arg in + -shared) + test "$build_libtool_libs" != yes && \ + func_fatal_configuration "can not build a shared library" + build_old_libs=no + break + ;; + -all-static | -static | -static-libtool-libs) + case $arg in + -all-static) + if test "$build_libtool_libs" = yes && test -z "$link_static_flag"; then + func_warning "complete static linking is impossible in this configuration" + fi + if test -n "$link_static_flag"; then + dlopen_self=$dlopen_self_static + fi + prefer_static_libs=yes + ;; + -static) + if test -z "$pic_flag" && test -n "$link_static_flag"; then + dlopen_self=$dlopen_self_static + fi + prefer_static_libs=built + ;; + -static-libtool-libs) + if test -z "$pic_flag" && test -n "$link_static_flag"; then + dlopen_self=$dlopen_self_static + fi + prefer_static_libs=yes + ;; + esac + build_libtool_libs=no + build_old_libs=yes + break + ;; + esac + done + + # See if our shared archives depend on static archives. + test -n "$old_archive_from_new_cmds" && build_old_libs=yes + + # Go through the arguments, transforming them on the way. + while test "$#" -gt 0; do + arg="$1" + shift + func_quote_for_eval "$arg" + qarg=$func_quote_for_eval_unquoted_result + func_append libtool_args " $func_quote_for_eval_result" + + # If the previous option needs an argument, assign it. + if test -n "$prev"; then + case $prev in + output) + func_append compile_command " @OUTPUT@" + func_append finalize_command " @OUTPUT@" + ;; + esac + + case $prev in + bindir) + bindir="$arg" + prev= + continue + ;; + dlfiles|dlprefiles) + if test "$preload" = no; then + # Add the symbol object into the linking commands. + func_append compile_command " @SYMFILE@" + func_append finalize_command " @SYMFILE@" + preload=yes + fi + case $arg in + *.la | *.lo) ;; # We handle these cases below. + force) + if test "$dlself" = no; then + dlself=needless + export_dynamic=yes + fi + prev= + continue + ;; + self) + if test "$prev" = dlprefiles; then + dlself=yes + elif test "$prev" = dlfiles && test "$dlopen_self" != yes; then + dlself=yes + else + dlself=needless + export_dynamic=yes + fi + prev= + continue + ;; + *) + if test "$prev" = dlfiles; then + func_append dlfiles " $arg" + else + func_append dlprefiles " $arg" + fi + prev= + continue + ;; + esac + ;; + expsyms) + export_symbols="$arg" + test -f "$arg" \ + || func_fatal_error "symbol file \`$arg' does not exist" + prev= + continue + ;; + expsyms_regex) + export_symbols_regex="$arg" + prev= + continue + ;; + framework) + case $host in + *-*-darwin*) + case "$deplibs " in + *" $qarg.ltframework "*) ;; + *) func_append deplibs " $qarg.ltframework" # this is fixed later + ;; + esac + ;; + esac + prev= + continue + ;; + inst_prefix) + inst_prefix_dir="$arg" + prev= + continue + ;; + objectlist) + if test -f "$arg"; then + save_arg=$arg + moreargs= + for fil in `cat "$save_arg"` + do +# func_append moreargs " $fil" + arg=$fil + # A libtool-controlled object. + + # Check to see that this really is a libtool object. + if func_lalib_unsafe_p "$arg"; then + pic_object= + non_pic_object= + + # Read the .lo file + func_source "$arg" + + if test -z "$pic_object" || + test -z "$non_pic_object" || + test "$pic_object" = none && + test "$non_pic_object" = none; then + func_fatal_error "cannot find name of object for \`$arg'" + fi + + # Extract subdirectory from the argument. + func_dirname "$arg" "/" "" + xdir="$func_dirname_result" + + if test "$pic_object" != none; then + # Prepend the subdirectory the object is found in. + pic_object="$xdir$pic_object" + + if test "$prev" = dlfiles; then + if test "$build_libtool_libs" = yes && test "$dlopen_support" = yes; then + func_append dlfiles " $pic_object" + prev= + continue + else + # If libtool objects are unsupported, then we need to preload. + prev=dlprefiles + fi + fi + + # CHECK ME: I think I busted this. -Ossama + if test "$prev" = dlprefiles; then + # Preload the old-style object. + func_append dlprefiles " $pic_object" + prev= + fi + + # A PIC object. + func_append libobjs " $pic_object" + arg="$pic_object" + fi + + # Non-PIC object. + if test "$non_pic_object" != none; then + # Prepend the subdirectory the object is found in. + non_pic_object="$xdir$non_pic_object" + + # A standard non-PIC object + func_append non_pic_objects " $non_pic_object" + if test -z "$pic_object" || test "$pic_object" = none ; then + arg="$non_pic_object" + fi + else + # If the PIC object exists, use it instead. + # $xdir was prepended to $pic_object above. + non_pic_object="$pic_object" + func_append non_pic_objects " $non_pic_object" + fi + else + # Only an error if not doing a dry-run. + if $opt_dry_run; then + # Extract subdirectory from the argument. + func_dirname "$arg" "/" "" + xdir="$func_dirname_result" + + func_lo2o "$arg" + pic_object=$xdir$objdir/$func_lo2o_result + non_pic_object=$xdir$func_lo2o_result + func_append libobjs " $pic_object" + func_append non_pic_objects " $non_pic_object" + else + func_fatal_error "\`$arg' is not a valid libtool object" + fi + fi + done + else + func_fatal_error "link input file \`$arg' does not exist" + fi + arg=$save_arg + prev= + continue + ;; + precious_regex) + precious_files_regex="$arg" + prev= + continue + ;; + release) + release="-$arg" + prev= + continue + ;; + rpath | xrpath) + # We need an absolute path. + case $arg in + [\\/]* | [A-Za-z]:[\\/]*) ;; + *) + func_fatal_error "only absolute run-paths are allowed" + ;; + esac + if test "$prev" = rpath; then + case "$rpath " in + *" $arg "*) ;; + *) func_append rpath " $arg" ;; + esac + else + case "$xrpath " in + *" $arg "*) ;; + *) func_append xrpath " $arg" ;; + esac + fi + prev= + continue + ;; + shrext) + shrext_cmds="$arg" + prev= + continue + ;; + weak) + func_append weak_libs " $arg" + prev= + continue + ;; + xcclinker) + func_append linker_flags " $qarg" + func_append compiler_flags " $qarg" + prev= + func_append compile_command " $qarg" + func_append finalize_command " $qarg" + continue + ;; + xcompiler) + func_append compiler_flags " $qarg" + prev= + func_append compile_command " $qarg" + func_append finalize_command " $qarg" + continue + ;; + xlinker) + func_append linker_flags " $qarg" + func_append compiler_flags " $wl$qarg" + prev= + func_append compile_command " $wl$qarg" + func_append finalize_command " $wl$qarg" + continue + ;; + *) + eval "$prev=\"\$arg\"" + prev= + continue + ;; + esac + fi # test -n "$prev" + + prevarg="$arg" + + case $arg in + -all-static) + if test -n "$link_static_flag"; then + # See comment for -static flag below, for more details. + func_append compile_command " $link_static_flag" + func_append finalize_command " $link_static_flag" + fi + continue + ;; + + -allow-undefined) + # FIXME: remove this flag sometime in the future. + func_fatal_error "\`-allow-undefined' must not be used because it is the default" + ;; + + -avoid-version) + avoid_version=yes + continue + ;; + + -bindir) + prev=bindir + continue + ;; + + -dlopen) + prev=dlfiles + continue + ;; + + -dlpreopen) + prev=dlprefiles + continue + ;; + + -export-dynamic) + export_dynamic=yes + continue + ;; + + -export-symbols | -export-symbols-regex) + if test -n "$export_symbols" || test -n "$export_symbols_regex"; then + func_fatal_error "more than one -exported-symbols argument is not allowed" + fi + if test "X$arg" = "X-export-symbols"; then + prev=expsyms + else + prev=expsyms_regex + fi + continue + ;; + + -framework) + prev=framework + continue + ;; + + -inst-prefix-dir) + prev=inst_prefix + continue + ;; + + # The native IRIX linker understands -LANG:*, -LIST:* and -LNO:* + # so, if we see these flags be careful not to treat them like -L + -L[A-Z][A-Z]*:*) + case $with_gcc/$host in + no/*-*-irix* | /*-*-irix*) + func_append compile_command " $arg" + func_append finalize_command " $arg" + ;; + esac + continue + ;; + + -L*) + func_stripname "-L" '' "$arg" + if test -z "$func_stripname_result"; then + if test "$#" -gt 0; then + func_fatal_error "require no space between \`-L' and \`$1'" + else + func_fatal_error "need path for \`-L' option" + fi + fi + func_resolve_sysroot "$func_stripname_result" + dir=$func_resolve_sysroot_result + # We need an absolute path. + case $dir in + [\\/]* | [A-Za-z]:[\\/]*) ;; + *) + absdir=`cd "$dir" && pwd` + test -z "$absdir" && \ + func_fatal_error "cannot determine absolute directory name of \`$dir'" + dir="$absdir" + ;; + esac + case "$deplibs " in + *" -L$dir "* | *" $arg "*) + # Will only happen for absolute or sysroot arguments + ;; + *) + # Preserve sysroot, but never include relative directories + case $dir in + [\\/]* | [A-Za-z]:[\\/]* | =*) func_append deplibs " $arg" ;; + *) func_append deplibs " -L$dir" ;; + esac + func_append lib_search_path " $dir" + ;; + esac + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*) + testbindir=`$ECHO "$dir" | $SED 's*/lib$*/bin*'` + case :$dllsearchpath: in + *":$dir:"*) ;; + ::) dllsearchpath=$dir;; + *) func_append dllsearchpath ":$dir";; + esac + case :$dllsearchpath: in + *":$testbindir:"*) ;; + ::) dllsearchpath=$testbindir;; + *) func_append dllsearchpath ":$testbindir";; + esac + ;; + esac + continue + ;; + + -l*) + if test "X$arg" = "X-lc" || test "X$arg" = "X-lm"; then + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-beos* | *-cegcc* | *-*-haiku*) + # These systems don't actually have a C or math library (as such) + continue + ;; + *-*-os2*) + # These systems don't actually have a C library (as such) + test "X$arg" = "X-lc" && continue + ;; + *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*) + # Do not include libc due to us having libc/libc_r. + test "X$arg" = "X-lc" && continue + ;; + *-*-rhapsody* | *-*-darwin1.[012]) + # Rhapsody C and math libraries are in the System framework + func_append deplibs " System.ltframework" + continue + ;; + *-*-sco3.2v5* | *-*-sco5v6*) + # Causes problems with __ctype + test "X$arg" = "X-lc" && continue + ;; + *-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*) + # Compiler inserts libc in the correct place for threads to work + test "X$arg" = "X-lc" && continue + ;; + esac + elif test "X$arg" = "X-lc_r"; then + case $host in + *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*) + # Do not include libc_r directly, use -pthread flag. + continue + ;; + esac + fi + func_append deplibs " $arg" + continue + ;; + + -module) + module=yes + continue + ;; + + # Tru64 UNIX uses -model [arg] to determine the layout of C++ + # classes, name mangling, and exception handling. + # Darwin uses the -arch flag to determine output architecture. + -model|-arch|-isysroot|--sysroot) + func_append compiler_flags " $arg" + func_append compile_command " $arg" + func_append finalize_command " $arg" + prev=xcompiler + continue + ;; + + -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe|-threads) + func_append compiler_flags " $arg" + func_append compile_command " $arg" + func_append finalize_command " $arg" + case "$new_inherited_linker_flags " in + *" $arg "*) ;; + * ) func_append new_inherited_linker_flags " $arg" ;; + esac + continue + ;; + + -multi_module) + single_module="${wl}-multi_module" + continue + ;; + + -no-fast-install) + fast_install=no + continue + ;; + + -no-install) + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-darwin* | *-cegcc*) + # The PATH hackery in wrapper scripts is required on Windows + # and Darwin in order for the loader to find any dlls it needs. + func_warning "\`-no-install' is ignored for $host" + func_warning "assuming \`-no-fast-install' instead" + fast_install=no + ;; + *) no_install=yes ;; + esac + continue + ;; + + -no-undefined) + allow_undefined=no + continue + ;; + + -objectlist) + prev=objectlist + continue + ;; + + -o) prev=output ;; + + -precious-files-regex) + prev=precious_regex + continue + ;; + + -release) + prev=release + continue + ;; + + -rpath) + prev=rpath + continue + ;; + + -R) + prev=xrpath + continue + ;; + + -R*) + func_stripname '-R' '' "$arg" + dir=$func_stripname_result + # We need an absolute path. + case $dir in + [\\/]* | [A-Za-z]:[\\/]*) ;; + =*) + func_stripname '=' '' "$dir" + dir=$lt_sysroot$func_stripname_result + ;; + *) + func_fatal_error "only absolute run-paths are allowed" + ;; + esac + case "$xrpath " in + *" $dir "*) ;; + *) func_append xrpath " $dir" ;; + esac + continue + ;; + + -shared) + # The effects of -shared are defined in a previous loop. + continue + ;; + + -shrext) + prev=shrext + continue + ;; + + -static | -static-libtool-libs) + # The effects of -static are defined in a previous loop. + # We used to do the same as -all-static on platforms that + # didn't have a PIC flag, but the assumption that the effects + # would be equivalent was wrong. It would break on at least + # Digital Unix and AIX. + continue + ;; + + -thread-safe) + thread_safe=yes + continue + ;; + + -version-info) + prev=vinfo + continue + ;; + + -version-number) + prev=vinfo + vinfo_number=yes + continue + ;; + + -weak) + prev=weak + continue + ;; + + -Wc,*) + func_stripname '-Wc,' '' "$arg" + args=$func_stripname_result + arg= + save_ifs="$IFS"; IFS=',' + for flag in $args; do + IFS="$save_ifs" + func_quote_for_eval "$flag" + func_append arg " $func_quote_for_eval_result" + func_append compiler_flags " $func_quote_for_eval_result" + done + IFS="$save_ifs" + func_stripname ' ' '' "$arg" + arg=$func_stripname_result + ;; + + -Wl,*) + func_stripname '-Wl,' '' "$arg" + args=$func_stripname_result + arg= + save_ifs="$IFS"; IFS=',' + for flag in $args; do + IFS="$save_ifs" + func_quote_for_eval "$flag" + func_append arg " $wl$func_quote_for_eval_result" + func_append compiler_flags " $wl$func_quote_for_eval_result" + func_append linker_flags " $func_quote_for_eval_result" + done + IFS="$save_ifs" + func_stripname ' ' '' "$arg" + arg=$func_stripname_result + ;; + + -Xcompiler) + prev=xcompiler + continue + ;; + + -Xlinker) + prev=xlinker + continue + ;; + + -XCClinker) + prev=xcclinker + continue + ;; + + # -msg_* for osf cc + -msg_*) + func_quote_for_eval "$arg" + arg="$func_quote_for_eval_result" + ;; + + # Flags to be passed through unchanged, with rationale: + # -64, -mips[0-9] enable 64-bit mode for the SGI compiler + # -r[0-9][0-9]* specify processor for the SGI compiler + # -xarch=*, -xtarget=* enable 64-bit mode for the Sun compiler + # +DA*, +DD* enable 64-bit mode for the HP compiler + # -q* compiler args for the IBM compiler + # -m*, -t[45]*, -txscale* architecture-specific flags for GCC + # -F/path path to uninstalled frameworks, gcc on darwin + # -p, -pg, --coverage, -fprofile-* profiling flags for GCC + # @file GCC response files + # -tp=* Portland pgcc target processor selection + # --sysroot=* for sysroot support + # -O*, -flto*, -fwhopr*, -fuse-linker-plugin GCC link-time optimization + -64|-mips[0-9]|-r[0-9][0-9]*|-xarch=*|-xtarget=*|+DA*|+DD*|-q*|-m*| \ + -t[45]*|-txscale*|-p|-pg|--coverage|-fprofile-*|-F*|@*|-tp=*|--sysroot=*| \ + -O*|-flto*|-fwhopr*|-fuse-linker-plugin) + func_quote_for_eval "$arg" + arg="$func_quote_for_eval_result" + func_append compile_command " $arg" + func_append finalize_command " $arg" + func_append compiler_flags " $arg" + continue + ;; + + # Some other compiler flag. + -* | +*) + func_quote_for_eval "$arg" + arg="$func_quote_for_eval_result" + ;; + + *.$objext) + # A standard object. + func_append objs " $arg" + ;; + + *.lo) + # A libtool-controlled object. + + # Check to see that this really is a libtool object. + if func_lalib_unsafe_p "$arg"; then + pic_object= + non_pic_object= + + # Read the .lo file + func_source "$arg" + + if test -z "$pic_object" || + test -z "$non_pic_object" || + test "$pic_object" = none && + test "$non_pic_object" = none; then + func_fatal_error "cannot find name of object for \`$arg'" + fi + + # Extract subdirectory from the argument. + func_dirname "$arg" "/" "" + xdir="$func_dirname_result" + + if test "$pic_object" != none; then + # Prepend the subdirectory the object is found in. + pic_object="$xdir$pic_object" + + if test "$prev" = dlfiles; then + if test "$build_libtool_libs" = yes && test "$dlopen_support" = yes; then + func_append dlfiles " $pic_object" + prev= + continue + else + # If libtool objects are unsupported, then we need to preload. + prev=dlprefiles + fi + fi + + # CHECK ME: I think I busted this. -Ossama + if test "$prev" = dlprefiles; then + # Preload the old-style object. + func_append dlprefiles " $pic_object" + prev= + fi + + # A PIC object. + func_append libobjs " $pic_object" + arg="$pic_object" + fi + + # Non-PIC object. + if test "$non_pic_object" != none; then + # Prepend the subdirectory the object is found in. + non_pic_object="$xdir$non_pic_object" + + # A standard non-PIC object + func_append non_pic_objects " $non_pic_object" + if test -z "$pic_object" || test "$pic_object" = none ; then + arg="$non_pic_object" + fi + else + # If the PIC object exists, use it instead. + # $xdir was prepended to $pic_object above. + non_pic_object="$pic_object" + func_append non_pic_objects " $non_pic_object" + fi + else + # Only an error if not doing a dry-run. + if $opt_dry_run; then + # Extract subdirectory from the argument. + func_dirname "$arg" "/" "" + xdir="$func_dirname_result" + + func_lo2o "$arg" + pic_object=$xdir$objdir/$func_lo2o_result + non_pic_object=$xdir$func_lo2o_result + func_append libobjs " $pic_object" + func_append non_pic_objects " $non_pic_object" + else + func_fatal_error "\`$arg' is not a valid libtool object" + fi + fi + ;; + + *.$libext) + # An archive. + func_append deplibs " $arg" + func_append old_deplibs " $arg" + continue + ;; + + *.la) + # A libtool-controlled library. + + func_resolve_sysroot "$arg" + if test "$prev" = dlfiles; then + # This library was specified with -dlopen. + func_append dlfiles " $func_resolve_sysroot_result" + prev= + elif test "$prev" = dlprefiles; then + # The library was specified with -dlpreopen. + func_append dlprefiles " $func_resolve_sysroot_result" + prev= + else + func_append deplibs " $func_resolve_sysroot_result" + fi + continue + ;; + + # Some other compiler argument. + *) + # Unknown arguments in both finalize_command and compile_command need + # to be aesthetically quoted because they are evaled later. + func_quote_for_eval "$arg" + arg="$func_quote_for_eval_result" + ;; + esac # arg + + # Now actually substitute the argument into the commands. + if test -n "$arg"; then + func_append compile_command " $arg" + func_append finalize_command " $arg" + fi + done # argument parsing loop + + test -n "$prev" && \ + func_fatal_help "the \`$prevarg' option requires an argument" + + if test "$export_dynamic" = yes && test -n "$export_dynamic_flag_spec"; then + eval arg=\"$export_dynamic_flag_spec\" + func_append compile_command " $arg" + func_append finalize_command " $arg" + fi + + oldlibs= + # calculate the name of the file, without its directory + func_basename "$output" + outputname="$func_basename_result" + libobjs_save="$libobjs" + + if test -n "$shlibpath_var"; then + # get the directories listed in $shlibpath_var + eval shlib_search_path=\`\$ECHO \"\${$shlibpath_var}\" \| \$SED \'s/:/ /g\'\` + else + shlib_search_path= + fi + eval sys_lib_search_path=\"$sys_lib_search_path_spec\" + eval sys_lib_dlsearch_path=\"$sys_lib_dlsearch_path_spec\" + + func_dirname "$output" "/" "" + output_objdir="$func_dirname_result$objdir" + func_to_tool_file "$output_objdir/" + tool_output_objdir=$func_to_tool_file_result + # Create the object directory. + func_mkdir_p "$output_objdir" + + # Determine the type of output + case $output in + "") + func_fatal_help "you must specify an output file" + ;; + *.$libext) linkmode=oldlib ;; + *.lo | *.$objext) linkmode=obj ;; + *.la) linkmode=lib ;; + *) linkmode=prog ;; # Anything else should be a program. + esac + + specialdeplibs= + + libs= + # Find all interdependent deplibs by searching for libraries + # that are linked more than once (e.g. -la -lb -la) + for deplib in $deplibs; do + if $opt_preserve_dup_deps ; then + case "$libs " in + *" $deplib "*) func_append specialdeplibs " $deplib" ;; + esac + fi + func_append libs " $deplib" + done + + if test "$linkmode" = lib; then + libs="$predeps $libs $compiler_lib_search_path $postdeps" + + # Compute libraries that are listed more than once in $predeps + # $postdeps and mark them as special (i.e., whose duplicates are + # not to be eliminated). + pre_post_deps= + if $opt_duplicate_compiler_generated_deps; then + for pre_post_dep in $predeps $postdeps; do + case "$pre_post_deps " in + *" $pre_post_dep "*) func_append specialdeplibs " $pre_post_deps" ;; + esac + func_append pre_post_deps " $pre_post_dep" + done + fi + pre_post_deps= + fi + + deplibs= + newdependency_libs= + newlib_search_path= + need_relink=no # whether we're linking any uninstalled libtool libraries + notinst_deplibs= # not-installed libtool libraries + notinst_path= # paths that contain not-installed libtool libraries + + case $linkmode in + lib) + passes="conv dlpreopen link" + for file in $dlfiles $dlprefiles; do + case $file in + *.la) ;; + *) + func_fatal_help "libraries can \`-dlopen' only libtool libraries: $file" + ;; + esac + done + ;; + prog) + compile_deplibs= + finalize_deplibs= + alldeplibs=no + newdlfiles= + newdlprefiles= + passes="conv scan dlopen dlpreopen link" + ;; + *) passes="conv" + ;; + esac + + for pass in $passes; do + # The preopen pass in lib mode reverses $deplibs; put it back here + # so that -L comes before libs that need it for instance... + if test "$linkmode,$pass" = "lib,link"; then + ## FIXME: Find the place where the list is rebuilt in the wrong + ## order, and fix it there properly + tmp_deplibs= + for deplib in $deplibs; do + tmp_deplibs="$deplib $tmp_deplibs" + done + deplibs="$tmp_deplibs" + fi + + if test "$linkmode,$pass" = "lib,link" || + test "$linkmode,$pass" = "prog,scan"; then + libs="$deplibs" + deplibs= + fi + if test "$linkmode" = prog; then + case $pass in + dlopen) libs="$dlfiles" ;; + dlpreopen) libs="$dlprefiles" ;; + link) libs="$deplibs %DEPLIBS% $dependency_libs" ;; + esac + fi + if test "$linkmode,$pass" = "lib,dlpreopen"; then + # Collect and forward deplibs of preopened libtool libs + for lib in $dlprefiles; do + # Ignore non-libtool-libs + dependency_libs= + func_resolve_sysroot "$lib" + case $lib in + *.la) func_source "$func_resolve_sysroot_result" ;; + esac + + # Collect preopened libtool deplibs, except any this library + # has declared as weak libs + for deplib in $dependency_libs; do + func_basename "$deplib" + deplib_base=$func_basename_result + case " $weak_libs " in + *" $deplib_base "*) ;; + *) func_append deplibs " $deplib" ;; + esac + done + done + libs="$dlprefiles" + fi + if test "$pass" = dlopen; then + # Collect dlpreopened libraries + save_deplibs="$deplibs" + deplibs= + fi + + for deplib in $libs; do + lib= + found=no + case $deplib in + -mt|-mthreads|-kthread|-Kthread|-pthread|-pthreads|--thread-safe|-threads) + if test "$linkmode,$pass" = "prog,link"; then + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + else + func_append compiler_flags " $deplib" + if test "$linkmode" = lib ; then + case "$new_inherited_linker_flags " in + *" $deplib "*) ;; + * ) func_append new_inherited_linker_flags " $deplib" ;; + esac + fi + fi + continue + ;; + -l*) + if test "$linkmode" != lib && test "$linkmode" != prog; then + func_warning "\`-l' is ignored for archives/objects" + continue + fi + func_stripname '-l' '' "$deplib" + name=$func_stripname_result + if test "$linkmode" = lib; then + searchdirs="$newlib_search_path $lib_search_path $compiler_lib_search_dirs $sys_lib_search_path $shlib_search_path" + else + searchdirs="$newlib_search_path $lib_search_path $sys_lib_search_path $shlib_search_path" + fi + for searchdir in $searchdirs; do + for search_ext in .la $std_shrext .so .a; do + # Search the libtool library + lib="$searchdir/lib${name}${search_ext}" + if test -f "$lib"; then + if test "$search_ext" = ".la"; then + found=yes + else + found=no + fi + break 2 + fi + done + done + if test "$found" != yes; then + # deplib doesn't seem to be a libtool library + if test "$linkmode,$pass" = "prog,link"; then + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + else + deplibs="$deplib $deplibs" + test "$linkmode" = lib && newdependency_libs="$deplib $newdependency_libs" + fi + continue + else # deplib is a libtool library + # If $allow_libtool_libs_with_static_runtimes && $deplib is a stdlib, + # We need to do some special things here, and not later. + if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then + case " $predeps $postdeps " in + *" $deplib "*) + if func_lalib_p "$lib"; then + library_names= + old_library= + func_source "$lib" + for l in $old_library $library_names; do + ll="$l" + done + if test "X$ll" = "X$old_library" ; then # only static version available + found=no + func_dirname "$lib" "" "." + ladir="$func_dirname_result" + lib=$ladir/$old_library + if test "$linkmode,$pass" = "prog,link"; then + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + else + deplibs="$deplib $deplibs" + test "$linkmode" = lib && newdependency_libs="$deplib $newdependency_libs" + fi + continue + fi + fi + ;; + *) ;; + esac + fi + fi + ;; # -l + *.ltframework) + if test "$linkmode,$pass" = "prog,link"; then + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + else + deplibs="$deplib $deplibs" + if test "$linkmode" = lib ; then + case "$new_inherited_linker_flags " in + *" $deplib "*) ;; + * ) func_append new_inherited_linker_flags " $deplib" ;; + esac + fi + fi + continue + ;; + -L*) + case $linkmode in + lib) + deplibs="$deplib $deplibs" + test "$pass" = conv && continue + newdependency_libs="$deplib $newdependency_libs" + func_stripname '-L' '' "$deplib" + func_resolve_sysroot "$func_stripname_result" + func_append newlib_search_path " $func_resolve_sysroot_result" + ;; + prog) + if test "$pass" = conv; then + deplibs="$deplib $deplibs" + continue + fi + if test "$pass" = scan; then + deplibs="$deplib $deplibs" + else + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + fi + func_stripname '-L' '' "$deplib" + func_resolve_sysroot "$func_stripname_result" + func_append newlib_search_path " $func_resolve_sysroot_result" + ;; + *) + func_warning "\`-L' is ignored for archives/objects" + ;; + esac # linkmode + continue + ;; # -L + -R*) + if test "$pass" = link; then + func_stripname '-R' '' "$deplib" + func_resolve_sysroot "$func_stripname_result" + dir=$func_resolve_sysroot_result + # Make sure the xrpath contains only unique directories. + case "$xrpath " in + *" $dir "*) ;; + *) func_append xrpath " $dir" ;; + esac + fi + deplibs="$deplib $deplibs" + continue + ;; + *.la) + func_resolve_sysroot "$deplib" + lib=$func_resolve_sysroot_result + ;; + *.$libext) + if test "$pass" = conv; then + deplibs="$deplib $deplibs" + continue + fi + case $linkmode in + lib) + # Linking convenience modules into shared libraries is allowed, + # but linking other static libraries is non-portable. + case " $dlpreconveniencelibs " in + *" $deplib "*) ;; + *) + valid_a_lib=no + case $deplibs_check_method in + match_pattern*) + set dummy $deplibs_check_method; shift + match_pattern_regex=`expr "$deplibs_check_method" : "$1 \(.*\)"` + if eval "\$ECHO \"$deplib\"" 2>/dev/null | $SED 10q \ + | $EGREP "$match_pattern_regex" > /dev/null; then + valid_a_lib=yes + fi + ;; + pass_all) + valid_a_lib=yes + ;; + esac + if test "$valid_a_lib" != yes; then + echo + $ECHO "*** Warning: Trying to link with static lib archive $deplib." + echo "*** I have the capability to make that library automatically link in when" + echo "*** you link to this library. But I can only do this if you have a" + echo "*** shared version of the library, which you do not appear to have" + echo "*** because the file extensions .$libext of this argument makes me believe" + echo "*** that it is just a static archive that I should not use here." + else + echo + $ECHO "*** Warning: Linking the shared library $output against the" + $ECHO "*** static library $deplib is not portable!" + deplibs="$deplib $deplibs" + fi + ;; + esac + continue + ;; + prog) + if test "$pass" != link; then + deplibs="$deplib $deplibs" + else + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + fi + continue + ;; + esac # linkmode + ;; # *.$libext + *.lo | *.$objext) + if test "$pass" = conv; then + deplibs="$deplib $deplibs" + elif test "$linkmode" = prog; then + if test "$pass" = dlpreopen || test "$dlopen_support" != yes || test "$build_libtool_libs" = no; then + # If there is no dlopen support or we're linking statically, + # we need to preload. + func_append newdlprefiles " $deplib" + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + else + func_append newdlfiles " $deplib" + fi + fi + continue + ;; + %DEPLIBS%) + alldeplibs=yes + continue + ;; + esac # case $deplib + + if test "$found" = yes || test -f "$lib"; then : + else + func_fatal_error "cannot find the library \`$lib' or unhandled argument \`$deplib'" + fi + + # Check to see that this really is a libtool archive. + func_lalib_unsafe_p "$lib" \ + || func_fatal_error "\`$lib' is not a valid libtool archive" + + func_dirname "$lib" "" "." + ladir="$func_dirname_result" + + dlname= + dlopen= + dlpreopen= + libdir= + library_names= + old_library= + inherited_linker_flags= + # If the library was installed with an old release of libtool, + # it will not redefine variables installed, or shouldnotlink + installed=yes + shouldnotlink=no + avoidtemprpath= + + + # Read the .la file + func_source "$lib" + + # Convert "-framework foo" to "foo.ltframework" + if test -n "$inherited_linker_flags"; then + tmp_inherited_linker_flags=`$ECHO "$inherited_linker_flags" | $SED 's/-framework \([^ $]*\)/\1.ltframework/g'` + for tmp_inherited_linker_flag in $tmp_inherited_linker_flags; do + case " $new_inherited_linker_flags " in + *" $tmp_inherited_linker_flag "*) ;; + *) func_append new_inherited_linker_flags " $tmp_inherited_linker_flag";; + esac + done + fi + dependency_libs=`$ECHO " $dependency_libs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` + if test "$linkmode,$pass" = "lib,link" || + test "$linkmode,$pass" = "prog,scan" || + { test "$linkmode" != prog && test "$linkmode" != lib; }; then + test -n "$dlopen" && func_append dlfiles " $dlopen" + test -n "$dlpreopen" && func_append dlprefiles " $dlpreopen" + fi + + if test "$pass" = conv; then + # Only check for convenience libraries + deplibs="$lib $deplibs" + if test -z "$libdir"; then + if test -z "$old_library"; then + func_fatal_error "cannot find name of link library for \`$lib'" + fi + # It is a libtool convenience library, so add in its objects. + func_append convenience " $ladir/$objdir/$old_library" + func_append old_convenience " $ladir/$objdir/$old_library" + elif test "$linkmode" != prog && test "$linkmode" != lib; then + func_fatal_error "\`$lib' is not a convenience library" + fi + tmp_libs= + for deplib in $dependency_libs; do + deplibs="$deplib $deplibs" + if $opt_preserve_dup_deps ; then + case "$tmp_libs " in + *" $deplib "*) func_append specialdeplibs " $deplib" ;; + esac + fi + func_append tmp_libs " $deplib" + done + continue + fi # $pass = conv + + + # Get the name of the library we link against. + linklib= + if test -n "$old_library" && + { test "$prefer_static_libs" = yes || + test "$prefer_static_libs,$installed" = "built,no"; }; then + linklib=$old_library + else + for l in $old_library $library_names; do + linklib="$l" + done + fi + if test -z "$linklib"; then + func_fatal_error "cannot find name of link library for \`$lib'" + fi + + # This library was specified with -dlopen. + if test "$pass" = dlopen; then + if test -z "$libdir"; then + func_fatal_error "cannot -dlopen a convenience library: \`$lib'" + fi + if test -z "$dlname" || + test "$dlopen_support" != yes || + test "$build_libtool_libs" = no; then + # If there is no dlname, no dlopen support or we're linking + # statically, we need to preload. We also need to preload any + # dependent libraries so libltdl's deplib preloader doesn't + # bomb out in the load deplibs phase. + func_append dlprefiles " $lib $dependency_libs" + else + func_append newdlfiles " $lib" + fi + continue + fi # $pass = dlopen + + # We need an absolute path. + case $ladir in + [\\/]* | [A-Za-z]:[\\/]*) abs_ladir="$ladir" ;; + *) + abs_ladir=`cd "$ladir" && pwd` + if test -z "$abs_ladir"; then + func_warning "cannot determine absolute directory name of \`$ladir'" + func_warning "passing it literally to the linker, although it might fail" + abs_ladir="$ladir" + fi + ;; + esac + func_basename "$lib" + laname="$func_basename_result" + + # Find the relevant object directory and library name. + if test "X$installed" = Xyes; then + if test ! -f "$lt_sysroot$libdir/$linklib" && test -f "$abs_ladir/$linklib"; then + func_warning "library \`$lib' was moved." + dir="$ladir" + absdir="$abs_ladir" + libdir="$abs_ladir" + else + dir="$lt_sysroot$libdir" + absdir="$lt_sysroot$libdir" + fi + test "X$hardcode_automatic" = Xyes && avoidtemprpath=yes + else + if test ! -f "$ladir/$objdir/$linklib" && test -f "$abs_ladir/$linklib"; then + dir="$ladir" + absdir="$abs_ladir" + # Remove this search path later + func_append notinst_path " $abs_ladir" + else + dir="$ladir/$objdir" + absdir="$abs_ladir/$objdir" + # Remove this search path later + func_append notinst_path " $abs_ladir" + fi + fi # $installed = yes + func_stripname 'lib' '.la' "$laname" + name=$func_stripname_result + + # This library was specified with -dlpreopen. + if test "$pass" = dlpreopen; then + if test -z "$libdir" && test "$linkmode" = prog; then + func_fatal_error "only libraries may -dlpreopen a convenience library: \`$lib'" + fi + case "$host" in + # special handling for platforms with PE-DLLs. + *cygwin* | *mingw* | *cegcc* ) + # Linker will automatically link against shared library if both + # static and shared are present. Therefore, ensure we extract + # symbols from the import library if a shared library is present + # (otherwise, the dlopen module name will be incorrect). We do + # this by putting the import library name into $newdlprefiles. + # We recover the dlopen module name by 'saving' the la file + # name in a special purpose variable, and (later) extracting the + # dlname from the la file. + if test -n "$dlname"; then + func_tr_sh "$dir/$linklib" + eval "libfile_$func_tr_sh_result=\$abs_ladir/\$laname" + func_append newdlprefiles " $dir/$linklib" + else + func_append newdlprefiles " $dir/$old_library" + # Keep a list of preopened convenience libraries to check + # that they are being used correctly in the link pass. + test -z "$libdir" && \ + func_append dlpreconveniencelibs " $dir/$old_library" + fi + ;; + * ) + # Prefer using a static library (so that no silly _DYNAMIC symbols + # are required to link). + if test -n "$old_library"; then + func_append newdlprefiles " $dir/$old_library" + # Keep a list of preopened convenience libraries to check + # that they are being used correctly in the link pass. + test -z "$libdir" && \ + func_append dlpreconveniencelibs " $dir/$old_library" + # Otherwise, use the dlname, so that lt_dlopen finds it. + elif test -n "$dlname"; then + func_append newdlprefiles " $dir/$dlname" + else + func_append newdlprefiles " $dir/$linklib" + fi + ;; + esac + fi # $pass = dlpreopen + + if test -z "$libdir"; then + # Link the convenience library + if test "$linkmode" = lib; then + deplibs="$dir/$old_library $deplibs" + elif test "$linkmode,$pass" = "prog,link"; then + compile_deplibs="$dir/$old_library $compile_deplibs" + finalize_deplibs="$dir/$old_library $finalize_deplibs" + else + deplibs="$lib $deplibs" # used for prog,scan pass + fi + continue + fi + + + if test "$linkmode" = prog && test "$pass" != link; then + func_append newlib_search_path " $ladir" + deplibs="$lib $deplibs" + + linkalldeplibs=no + if test "$link_all_deplibs" != no || test -z "$library_names" || + test "$build_libtool_libs" = no; then + linkalldeplibs=yes + fi + + tmp_libs= + for deplib in $dependency_libs; do + case $deplib in + -L*) func_stripname '-L' '' "$deplib" + func_resolve_sysroot "$func_stripname_result" + func_append newlib_search_path " $func_resolve_sysroot_result" + ;; + esac + # Need to link against all dependency_libs? + if test "$linkalldeplibs" = yes; then + deplibs="$deplib $deplibs" + else + # Need to hardcode shared library paths + # or/and link against static libraries + newdependency_libs="$deplib $newdependency_libs" + fi + if $opt_preserve_dup_deps ; then + case "$tmp_libs " in + *" $deplib "*) func_append specialdeplibs " $deplib" ;; + esac + fi + func_append tmp_libs " $deplib" + done # for deplib + continue + fi # $linkmode = prog... + + if test "$linkmode,$pass" = "prog,link"; then + if test -n "$library_names" && + { { test "$prefer_static_libs" = no || + test "$prefer_static_libs,$installed" = "built,yes"; } || + test -z "$old_library"; }; then + # We need to hardcode the library path + if test -n "$shlibpath_var" && test -z "$avoidtemprpath" ; then + # Make sure the rpath contains only unique directories. + case "$temp_rpath:" in + *"$absdir:"*) ;; + *) func_append temp_rpath "$absdir:" ;; + esac + fi + + # Hardcode the library path. + # Skip directories that are in the system default run-time + # search path. + case " $sys_lib_dlsearch_path " in + *" $absdir "*) ;; + *) + case "$compile_rpath " in + *" $absdir "*) ;; + *) func_append compile_rpath " $absdir" ;; + esac + ;; + esac + case " $sys_lib_dlsearch_path " in + *" $libdir "*) ;; + *) + case "$finalize_rpath " in + *" $libdir "*) ;; + *) func_append finalize_rpath " $libdir" ;; + esac + ;; + esac + fi # $linkmode,$pass = prog,link... + + if test "$alldeplibs" = yes && + { test "$deplibs_check_method" = pass_all || + { test "$build_libtool_libs" = yes && + test -n "$library_names"; }; }; then + # We only need to search for static libraries + continue + fi + fi + + link_static=no # Whether the deplib will be linked statically + use_static_libs=$prefer_static_libs + if test "$use_static_libs" = built && test "$installed" = yes; then + use_static_libs=no + fi + if test -n "$library_names" && + { test "$use_static_libs" = no || test -z "$old_library"; }; then + case $host in + *cygwin* | *mingw* | *cegcc*) + # No point in relinking DLLs because paths are not encoded + func_append notinst_deplibs " $lib" + need_relink=no + ;; + *) + if test "$installed" = no; then + func_append notinst_deplibs " $lib" + need_relink=yes + fi + ;; + esac + # This is a shared library + + # Warn about portability, can't link against -module's on some + # systems (darwin). Don't bleat about dlopened modules though! + dlopenmodule="" + for dlpremoduletest in $dlprefiles; do + if test "X$dlpremoduletest" = "X$lib"; then + dlopenmodule="$dlpremoduletest" + break + fi + done + if test -z "$dlopenmodule" && test "$shouldnotlink" = yes && test "$pass" = link; then + echo + if test "$linkmode" = prog; then + $ECHO "*** Warning: Linking the executable $output against the loadable module" + else + $ECHO "*** Warning: Linking the shared library $output against the loadable module" + fi + $ECHO "*** $linklib is not portable!" + fi + if test "$linkmode" = lib && + test "$hardcode_into_libs" = yes; then + # Hardcode the library path. + # Skip directories that are in the system default run-time + # search path. + case " $sys_lib_dlsearch_path " in + *" $absdir "*) ;; + *) + case "$compile_rpath " in + *" $absdir "*) ;; + *) func_append compile_rpath " $absdir" ;; + esac + ;; + esac + case " $sys_lib_dlsearch_path " in + *" $libdir "*) ;; + *) + case "$finalize_rpath " in + *" $libdir "*) ;; + *) func_append finalize_rpath " $libdir" ;; + esac + ;; + esac + fi + + if test -n "$old_archive_from_expsyms_cmds"; then + # figure out the soname + set dummy $library_names + shift + realname="$1" + shift + libname=`eval "\\$ECHO \"$libname_spec\""` + # use dlname if we got it. it's perfectly good, no? + if test -n "$dlname"; then + soname="$dlname" + elif test -n "$soname_spec"; then + # bleh windows + case $host in + *cygwin* | mingw* | *cegcc*) + func_arith $current - $age + major=$func_arith_result + versuffix="-$major" + ;; + esac + eval soname=\"$soname_spec\" + else + soname="$realname" + fi + + # Make a new name for the extract_expsyms_cmds to use + soroot="$soname" + func_basename "$soroot" + soname="$func_basename_result" + func_stripname 'lib' '.dll' "$soname" + newlib=libimp-$func_stripname_result.a + + # If the library has no export list, then create one now + if test -f "$output_objdir/$soname-def"; then : + else + func_verbose "extracting exported symbol list from \`$soname'" + func_execute_cmds "$extract_expsyms_cmds" 'exit $?' + fi + + # Create $newlib + if test -f "$output_objdir/$newlib"; then :; else + func_verbose "generating import library for \`$soname'" + func_execute_cmds "$old_archive_from_expsyms_cmds" 'exit $?' + fi + # make sure the library variables are pointing to the new library + dir=$output_objdir + linklib=$newlib + fi # test -n "$old_archive_from_expsyms_cmds" + + if test "$linkmode" = prog || test "$opt_mode" != relink; then + add_shlibpath= + add_dir= + add= + lib_linked=yes + case $hardcode_action in + immediate | unsupported) + if test "$hardcode_direct" = no; then + add="$dir/$linklib" + case $host in + *-*-sco3.2v5.0.[024]*) add_dir="-L$dir" ;; + *-*-sysv4*uw2*) add_dir="-L$dir" ;; + *-*-sysv5OpenUNIX* | *-*-sysv5UnixWare7.[01].[10]* | \ + *-*-unixware7*) add_dir="-L$dir" ;; + *-*-darwin* ) + # if the lib is a (non-dlopened) module then we can not + # link against it, someone is ignoring the earlier warnings + if /usr/bin/file -L $add 2> /dev/null | + $GREP ": [^:]* bundle" >/dev/null ; then + if test "X$dlopenmodule" != "X$lib"; then + $ECHO "*** Warning: lib $linklib is a module, not a shared library" + if test -z "$old_library" ; then + echo + echo "*** And there doesn't seem to be a static archive available" + echo "*** The link will probably fail, sorry" + else + add="$dir/$old_library" + fi + elif test -n "$old_library"; then + add="$dir/$old_library" + fi + fi + esac + elif test "$hardcode_minus_L" = no; then + case $host in + *-*-sunos*) add_shlibpath="$dir" ;; + esac + add_dir="-L$dir" + add="-l$name" + elif test "$hardcode_shlibpath_var" = no; then + add_shlibpath="$dir" + add="-l$name" + else + lib_linked=no + fi + ;; + relink) + if test "$hardcode_direct" = yes && + test "$hardcode_direct_absolute" = no; then + add="$dir/$linklib" + elif test "$hardcode_minus_L" = yes; then + add_dir="-L$dir" + # Try looking first in the location we're being installed to. + if test -n "$inst_prefix_dir"; then + case $libdir in + [\\/]*) + func_append add_dir " -L$inst_prefix_dir$libdir" + ;; + esac + fi + add="-l$name" + elif test "$hardcode_shlibpath_var" = yes; then + add_shlibpath="$dir" + add="-l$name" + else + lib_linked=no + fi + ;; + *) lib_linked=no ;; + esac + + if test "$lib_linked" != yes; then + func_fatal_configuration "unsupported hardcode properties" + fi + + if test -n "$add_shlibpath"; then + case :$compile_shlibpath: in + *":$add_shlibpath:"*) ;; + *) func_append compile_shlibpath "$add_shlibpath:" ;; + esac + fi + if test "$linkmode" = prog; then + test -n "$add_dir" && compile_deplibs="$add_dir $compile_deplibs" + test -n "$add" && compile_deplibs="$add $compile_deplibs" + else + test -n "$add_dir" && deplibs="$add_dir $deplibs" + test -n "$add" && deplibs="$add $deplibs" + if test "$hardcode_direct" != yes && + test "$hardcode_minus_L" != yes && + test "$hardcode_shlibpath_var" = yes; then + case :$finalize_shlibpath: in + *":$libdir:"*) ;; + *) func_append finalize_shlibpath "$libdir:" ;; + esac + fi + fi + fi + + if test "$linkmode" = prog || test "$opt_mode" = relink; then + add_shlibpath= + add_dir= + add= + # Finalize command for both is simple: just hardcode it. + if test "$hardcode_direct" = yes && + test "$hardcode_direct_absolute" = no; then + add="$libdir/$linklib" + elif test "$hardcode_minus_L" = yes; then + add_dir="-L$libdir" + add="-l$name" + elif test "$hardcode_shlibpath_var" = yes; then + case :$finalize_shlibpath: in + *":$libdir:"*) ;; + *) func_append finalize_shlibpath "$libdir:" ;; + esac + add="-l$name" + elif test "$hardcode_automatic" = yes; then + if test -n "$inst_prefix_dir" && + test -f "$inst_prefix_dir$libdir/$linklib" ; then + add="$inst_prefix_dir$libdir/$linklib" + else + add="$libdir/$linklib" + fi + else + # We cannot seem to hardcode it, guess we'll fake it. + add_dir="-L$libdir" + # Try looking first in the location we're being installed to. + if test -n "$inst_prefix_dir"; then + case $libdir in + [\\/]*) + func_append add_dir " -L$inst_prefix_dir$libdir" + ;; + esac + fi + add="-l$name" + fi + + if test "$linkmode" = prog; then + test -n "$add_dir" && finalize_deplibs="$add_dir $finalize_deplibs" + test -n "$add" && finalize_deplibs="$add $finalize_deplibs" + else + test -n "$add_dir" && deplibs="$add_dir $deplibs" + test -n "$add" && deplibs="$add $deplibs" + fi + fi + elif test "$linkmode" = prog; then + # Here we assume that one of hardcode_direct or hardcode_minus_L + # is not unsupported. This is valid on all known static and + # shared platforms. + if test "$hardcode_direct" != unsupported; then + test -n "$old_library" && linklib="$old_library" + compile_deplibs="$dir/$linklib $compile_deplibs" + finalize_deplibs="$dir/$linklib $finalize_deplibs" + else + compile_deplibs="-l$name -L$dir $compile_deplibs" + finalize_deplibs="-l$name -L$dir $finalize_deplibs" + fi + elif test "$build_libtool_libs" = yes; then + # Not a shared library + if test "$deplibs_check_method" != pass_all; then + # We're trying link a shared library against a static one + # but the system doesn't support it. + + # Just print a warning and add the library to dependency_libs so + # that the program can be linked against the static library. + echo + $ECHO "*** Warning: This system can not link to static lib archive $lib." + echo "*** I have the capability to make that library automatically link in when" + echo "*** you link to this library. But I can only do this if you have a" + echo "*** shared version of the library, which you do not appear to have." + if test "$module" = yes; then + echo "*** But as you try to build a module library, libtool will still create " + echo "*** a static module, that should work as long as the dlopening application" + echo "*** is linked with the -dlopen flag to resolve symbols at runtime." + if test -z "$global_symbol_pipe"; then + echo + echo "*** However, this would only work if libtool was able to extract symbol" + echo "*** lists from a program, using \`nm' or equivalent, but libtool could" + echo "*** not find such a program. So, this module is probably useless." + echo "*** \`nm' from GNU binutils and a full rebuild may help." + fi + if test "$build_old_libs" = no; then + build_libtool_libs=module + build_old_libs=yes + else + build_libtool_libs=no + fi + fi + else + deplibs="$dir/$old_library $deplibs" + link_static=yes + fi + fi # link shared/static library? + + if test "$linkmode" = lib; then + if test -n "$dependency_libs" && + { test "$hardcode_into_libs" != yes || + test "$build_old_libs" = yes || + test "$link_static" = yes; }; then + # Extract -R from dependency_libs + temp_deplibs= + for libdir in $dependency_libs; do + case $libdir in + -R*) func_stripname '-R' '' "$libdir" + temp_xrpath=$func_stripname_result + case " $xrpath " in + *" $temp_xrpath "*) ;; + *) func_append xrpath " $temp_xrpath";; + esac;; + *) func_append temp_deplibs " $libdir";; + esac + done + dependency_libs="$temp_deplibs" + fi + + func_append newlib_search_path " $absdir" + # Link against this library + test "$link_static" = no && newdependency_libs="$abs_ladir/$laname $newdependency_libs" + # ... and its dependency_libs + tmp_libs= + for deplib in $dependency_libs; do + newdependency_libs="$deplib $newdependency_libs" + case $deplib in + -L*) func_stripname '-L' '' "$deplib" + func_resolve_sysroot "$func_stripname_result";; + *) func_resolve_sysroot "$deplib" ;; + esac + if $opt_preserve_dup_deps ; then + case "$tmp_libs " in + *" $func_resolve_sysroot_result "*) + func_append specialdeplibs " $func_resolve_sysroot_result" ;; + esac + fi + func_append tmp_libs " $func_resolve_sysroot_result" + done + + if test "$link_all_deplibs" != no; then + # Add the search paths of all dependency libraries + for deplib in $dependency_libs; do + path= + case $deplib in + -L*) path="$deplib" ;; + *.la) + func_resolve_sysroot "$deplib" + deplib=$func_resolve_sysroot_result + func_dirname "$deplib" "" "." + dir=$func_dirname_result + # We need an absolute path. + case $dir in + [\\/]* | [A-Za-z]:[\\/]*) absdir="$dir" ;; + *) + absdir=`cd "$dir" && pwd` + if test -z "$absdir"; then + func_warning "cannot determine absolute directory name of \`$dir'" + absdir="$dir" + fi + ;; + esac + if $GREP "^installed=no" $deplib > /dev/null; then + case $host in + *-*-darwin*) + depdepl= + eval deplibrary_names=`${SED} -n -e 's/^library_names=\(.*\)$/\1/p' $deplib` + if test -n "$deplibrary_names" ; then + for tmp in $deplibrary_names ; do + depdepl=$tmp + done + if test -f "$absdir/$objdir/$depdepl" ; then + depdepl="$absdir/$objdir/$depdepl" + darwin_install_name=`${OTOOL} -L $depdepl | awk '{if (NR == 2) {print $1;exit}}'` + if test -z "$darwin_install_name"; then + darwin_install_name=`${OTOOL64} -L $depdepl | awk '{if (NR == 2) {print $1;exit}}'` + fi + func_append compiler_flags " ${wl}-dylib_file ${wl}${darwin_install_name}:${depdepl}" + func_append linker_flags " -dylib_file ${darwin_install_name}:${depdepl}" + path= + fi + fi + ;; + *) + path="-L$absdir/$objdir" + ;; + esac + else + eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $deplib` + test -z "$libdir" && \ + func_fatal_error "\`$deplib' is not a valid libtool archive" + test "$absdir" != "$libdir" && \ + func_warning "\`$deplib' seems to be moved" + + path="-L$absdir" + fi + ;; + esac + case " $deplibs " in + *" $path "*) ;; + *) deplibs="$path $deplibs" ;; + esac + done + fi # link_all_deplibs != no + fi # linkmode = lib + done # for deplib in $libs + if test "$pass" = link; then + if test "$linkmode" = "prog"; then + compile_deplibs="$new_inherited_linker_flags $compile_deplibs" + finalize_deplibs="$new_inherited_linker_flags $finalize_deplibs" + else + compiler_flags="$compiler_flags "`$ECHO " $new_inherited_linker_flags" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` + fi + fi + dependency_libs="$newdependency_libs" + if test "$pass" = dlpreopen; then + # Link the dlpreopened libraries before other libraries + for deplib in $save_deplibs; do + deplibs="$deplib $deplibs" + done + fi + if test "$pass" != dlopen; then + if test "$pass" != conv; then + # Make sure lib_search_path contains only unique directories. + lib_search_path= + for dir in $newlib_search_path; do + case "$lib_search_path " in + *" $dir "*) ;; + *) func_append lib_search_path " $dir" ;; + esac + done + newlib_search_path= + fi + + if test "$linkmode,$pass" != "prog,link"; then + vars="deplibs" + else + vars="compile_deplibs finalize_deplibs" + fi + for var in $vars dependency_libs; do + # Add libraries to $var in reverse order + eval tmp_libs=\"\$$var\" + new_libs= + for deplib in $tmp_libs; do + # FIXME: Pedantically, this is the right thing to do, so + # that some nasty dependency loop isn't accidentally + # broken: + #new_libs="$deplib $new_libs" + # Pragmatically, this seems to cause very few problems in + # practice: + case $deplib in + -L*) new_libs="$deplib $new_libs" ;; + -R*) ;; + *) + # And here is the reason: when a library appears more + # than once as an explicit dependence of a library, or + # is implicitly linked in more than once by the + # compiler, it is considered special, and multiple + # occurrences thereof are not removed. Compare this + # with having the same library being listed as a + # dependency of multiple other libraries: in this case, + # we know (pedantically, we assume) the library does not + # need to be listed more than once, so we keep only the + # last copy. This is not always right, but it is rare + # enough that we require users that really mean to play + # such unportable linking tricks to link the library + # using -Wl,-lname, so that libtool does not consider it + # for duplicate removal. + case " $specialdeplibs " in + *" $deplib "*) new_libs="$deplib $new_libs" ;; + *) + case " $new_libs " in + *" $deplib "*) ;; + *) new_libs="$deplib $new_libs" ;; + esac + ;; + esac + ;; + esac + done + tmp_libs= + for deplib in $new_libs; do + case $deplib in + -L*) + case " $tmp_libs " in + *" $deplib "*) ;; + *) func_append tmp_libs " $deplib" ;; + esac + ;; + *) func_append tmp_libs " $deplib" ;; + esac + done + eval $var=\"$tmp_libs\" + done # for var + fi + # Last step: remove runtime libs from dependency_libs + # (they stay in deplibs) + tmp_libs= + for i in $dependency_libs ; do + case " $predeps $postdeps $compiler_lib_search_path " in + *" $i "*) + i="" + ;; + esac + if test -n "$i" ; then + func_append tmp_libs " $i" + fi + done + dependency_libs=$tmp_libs + done # for pass + if test "$linkmode" = prog; then + dlfiles="$newdlfiles" + fi + if test "$linkmode" = prog || test "$linkmode" = lib; then + dlprefiles="$newdlprefiles" + fi + + case $linkmode in + oldlib) + if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then + func_warning "\`-dlopen' is ignored for archives" + fi + + case " $deplibs" in + *\ -l* | *\ -L*) + func_warning "\`-l' and \`-L' are ignored for archives" ;; + esac + + test -n "$rpath" && \ + func_warning "\`-rpath' is ignored for archives" + + test -n "$xrpath" && \ + func_warning "\`-R' is ignored for archives" + + test -n "$vinfo" && \ + func_warning "\`-version-info/-version-number' is ignored for archives" + + test -n "$release" && \ + func_warning "\`-release' is ignored for archives" + + test -n "$export_symbols$export_symbols_regex" && \ + func_warning "\`-export-symbols' is ignored for archives" + + # Now set the variables for building old libraries. + build_libtool_libs=no + oldlibs="$output" + func_append objs "$old_deplibs" + ;; + + lib) + # Make sure we only generate libraries of the form `libNAME.la'. + case $outputname in + lib*) + func_stripname 'lib' '.la' "$outputname" + name=$func_stripname_result + eval shared_ext=\"$shrext_cmds\" + eval libname=\"$libname_spec\" + ;; + *) + test "$module" = no && \ + func_fatal_help "libtool library \`$output' must begin with \`lib'" + + if test "$need_lib_prefix" != no; then + # Add the "lib" prefix for modules if required + func_stripname '' '.la' "$outputname" + name=$func_stripname_result + eval shared_ext=\"$shrext_cmds\" + eval libname=\"$libname_spec\" + else + func_stripname '' '.la' "$outputname" + libname=$func_stripname_result + fi + ;; + esac + + if test -n "$objs"; then + if test "$deplibs_check_method" != pass_all; then + func_fatal_error "cannot build libtool library \`$output' from non-libtool objects on this host:$objs" + else + echo + $ECHO "*** Warning: Linking the shared library $output against the non-libtool" + $ECHO "*** objects $objs is not portable!" + func_append libobjs " $objs" + fi + fi + + test "$dlself" != no && \ + func_warning "\`-dlopen self' is ignored for libtool libraries" + + set dummy $rpath + shift + test "$#" -gt 1 && \ + func_warning "ignoring multiple \`-rpath's for a libtool library" + + install_libdir="$1" + + oldlibs= + if test -z "$rpath"; then + if test "$build_libtool_libs" = yes; then + # Building a libtool convenience library. + # Some compilers have problems with a `.al' extension so + # convenience libraries should have the same extension an + # archive normally would. + oldlibs="$output_objdir/$libname.$libext $oldlibs" + build_libtool_libs=convenience + build_old_libs=yes + fi + + test -n "$vinfo" && \ + func_warning "\`-version-info/-version-number' is ignored for convenience libraries" + + test -n "$release" && \ + func_warning "\`-release' is ignored for convenience libraries" + else + + # Parse the version information argument. + save_ifs="$IFS"; IFS=':' + set dummy $vinfo 0 0 0 + shift + IFS="$save_ifs" + + test -n "$7" && \ + func_fatal_help "too many parameters to \`-version-info'" + + # convert absolute version numbers to libtool ages + # this retains compatibility with .la files and attempts + # to make the code below a bit more comprehensible + + case $vinfo_number in + yes) + number_major="$1" + number_minor="$2" + number_revision="$3" + # + # There are really only two kinds -- those that + # use the current revision as the major version + # and those that subtract age and use age as + # a minor version. But, then there is irix + # which has an extra 1 added just for fun + # + case $version_type in + darwin|linux|osf|windows|none) + func_arith $number_major + $number_minor + current=$func_arith_result + age="$number_minor" + revision="$number_revision" + ;; + freebsd-aout|freebsd-elf|qnx|sunos) + current="$number_major" + revision="$number_minor" + age="0" + ;; + irix|nonstopux) + func_arith $number_major + $number_minor + current=$func_arith_result + age="$number_minor" + revision="$number_minor" + lt_irix_increment=no + ;; + esac + ;; + no) + current="$1" + revision="$2" + age="$3" + ;; + esac + + # Check that each of the things are valid numbers. + case $current in + 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; + *) + func_error "CURRENT \`$current' must be a nonnegative integer" + func_fatal_error "\`$vinfo' is not valid version information" + ;; + esac + + case $revision in + 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; + *) + func_error "REVISION \`$revision' must be a nonnegative integer" + func_fatal_error "\`$vinfo' is not valid version information" + ;; + esac + + case $age in + 0|[1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-9][0-9][0-9][0-9][0-9]) ;; + *) + func_error "AGE \`$age' must be a nonnegative integer" + func_fatal_error "\`$vinfo' is not valid version information" + ;; + esac + + if test "$age" -gt "$current"; then + func_error "AGE \`$age' is greater than the current interface number \`$current'" + func_fatal_error "\`$vinfo' is not valid version information" + fi + + # Calculate the version variables. + major= + versuffix= + verstring= + case $version_type in + none) ;; + + darwin) + # Like Linux, but with the current version available in + # verstring for coding it into the library header + func_arith $current - $age + major=.$func_arith_result + versuffix="$major.$age.$revision" + # Darwin ld doesn't like 0 for these options... + func_arith $current + 1 + minor_current=$func_arith_result + xlcverstring="${wl}-compatibility_version ${wl}$minor_current ${wl}-current_version ${wl}$minor_current.$revision" + verstring="-compatibility_version $minor_current -current_version $minor_current.$revision" + ;; + + freebsd-aout) + major=".$current" + versuffix=".$current.$revision"; + ;; + + freebsd-elf) + major=".$current" + versuffix=".$current" + ;; + + irix | nonstopux) + if test "X$lt_irix_increment" = "Xno"; then + func_arith $current - $age + else + func_arith $current - $age + 1 + fi + major=$func_arith_result + + case $version_type in + nonstopux) verstring_prefix=nonstopux ;; + *) verstring_prefix=sgi ;; + esac + verstring="$verstring_prefix$major.$revision" + + # Add in all the interfaces that we are compatible with. + loop=$revision + while test "$loop" -ne 0; do + func_arith $revision - $loop + iface=$func_arith_result + func_arith $loop - 1 + loop=$func_arith_result + verstring="$verstring_prefix$major.$iface:$verstring" + done + + # Before this point, $major must not contain `.'. + major=.$major + versuffix="$major.$revision" + ;; + + linux) + func_arith $current - $age + major=.$func_arith_result + versuffix="$major.$age.$revision" + ;; + + osf) + func_arith $current - $age + major=.$func_arith_result + versuffix=".$current.$age.$revision" + verstring="$current.$age.$revision" + + # Add in all the interfaces that we are compatible with. + loop=$age + while test "$loop" -ne 0; do + func_arith $current - $loop + iface=$func_arith_result + func_arith $loop - 1 + loop=$func_arith_result + verstring="$verstring:${iface}.0" + done + + # Make executables depend on our current version. + func_append verstring ":${current}.0" + ;; + + qnx) + major=".$current" + versuffix=".$current" + ;; + + sunos) + major=".$current" + versuffix=".$current.$revision" + ;; + + windows) + # Use '-' rather than '.', since we only want one + # extension on DOS 8.3 filesystems. + func_arith $current - $age + major=$func_arith_result + versuffix="-$major" + ;; + + *) + func_fatal_configuration "unknown library version type \`$version_type'" + ;; + esac + + # Clear the version info if we defaulted, and they specified a release. + if test -z "$vinfo" && test -n "$release"; then + major= + case $version_type in + darwin) + # we can't check for "0.0" in archive_cmds due to quoting + # problems, so we reset it completely + verstring= + ;; + *) + verstring="0.0" + ;; + esac + if test "$need_version" = no; then + versuffix= + else + versuffix=".0.0" + fi + fi + + # Remove version info from name if versioning should be avoided + if test "$avoid_version" = yes && test "$need_version" = no; then + major= + versuffix= + verstring="" + fi + + # Check to see if the archive will have undefined symbols. + if test "$allow_undefined" = yes; then + if test "$allow_undefined_flag" = unsupported; then + func_warning "undefined symbols not allowed in $host shared libraries" + build_libtool_libs=no + build_old_libs=yes + fi + else + # Don't allow undefined symbols. + allow_undefined_flag="$no_undefined_flag" + fi + + fi + + func_generate_dlsyms "$libname" "$libname" "yes" + func_append libobjs " $symfileobj" + test "X$libobjs" = "X " && libobjs= + + if test "$opt_mode" != relink; then + # Remove our outputs, but don't remove object files since they + # may have been created when compiling PIC objects. + removelist= + tempremovelist=`$ECHO "$output_objdir/*"` + for p in $tempremovelist; do + case $p in + *.$objext | *.gcno) + ;; + $output_objdir/$outputname | $output_objdir/$libname.* | $output_objdir/${libname}${release}.*) + if test "X$precious_files_regex" != "X"; then + if $ECHO "$p" | $EGREP -e "$precious_files_regex" >/dev/null 2>&1 + then + continue + fi + fi + func_append removelist " $p" + ;; + *) ;; + esac + done + test -n "$removelist" && \ + func_show_eval "${RM}r \$removelist" + fi + + # Now set the variables for building old libraries. + if test "$build_old_libs" = yes && test "$build_libtool_libs" != convenience ; then + func_append oldlibs " $output_objdir/$libname.$libext" + + # Transform .lo files to .o files. + oldobjs="$objs "`$ECHO "$libobjs" | $SP2NL | $SED "/\.${libext}$/d; $lo2o" | $NL2SP` + fi + + # Eliminate all temporary directories. + #for path in $notinst_path; do + # lib_search_path=`$ECHO "$lib_search_path " | $SED "s% $path % %g"` + # deplibs=`$ECHO "$deplibs " | $SED "s% -L$path % %g"` + # dependency_libs=`$ECHO "$dependency_libs " | $SED "s% -L$path % %g"` + #done + + if test -n "$xrpath"; then + # If the user specified any rpath flags, then add them. + temp_xrpath= + for libdir in $xrpath; do + func_replace_sysroot "$libdir" + func_append temp_xrpath " -R$func_replace_sysroot_result" + case "$finalize_rpath " in + *" $libdir "*) ;; + *) func_append finalize_rpath " $libdir" ;; + esac + done + if test "$hardcode_into_libs" != yes || test "$build_old_libs" = yes; then + dependency_libs="$temp_xrpath $dependency_libs" + fi + fi + + # Make sure dlfiles contains only unique files that won't be dlpreopened + old_dlfiles="$dlfiles" + dlfiles= + for lib in $old_dlfiles; do + case " $dlprefiles $dlfiles " in + *" $lib "*) ;; + *) func_append dlfiles " $lib" ;; + esac + done + + # Make sure dlprefiles contains only unique files + old_dlprefiles="$dlprefiles" + dlprefiles= + for lib in $old_dlprefiles; do + case "$dlprefiles " in + *" $lib "*) ;; + *) func_append dlprefiles " $lib" ;; + esac + done + + if test "$build_libtool_libs" = yes; then + if test -n "$rpath"; then + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-beos* | *-cegcc* | *-*-haiku*) + # these systems don't actually have a c library (as such)! + ;; + *-*-rhapsody* | *-*-darwin1.[012]) + # Rhapsody C library is in the System framework + func_append deplibs " System.ltframework" + ;; + *-*-netbsd*) + # Don't link with libc until the a.out ld.so is fixed. + ;; + *-*-openbsd* | *-*-freebsd* | *-*-dragonfly*) + # Do not include libc due to us having libc/libc_r. + ;; + *-*-sco3.2v5* | *-*-sco5v6*) + # Causes problems with __ctype + ;; + *-*-sysv4.2uw2* | *-*-sysv5* | *-*-unixware* | *-*-OpenUNIX*) + # Compiler inserts libc in the correct place for threads to work + ;; + *) + # Add libc to deplibs on all other systems if necessary. + if test "$build_libtool_need_lc" = "yes"; then + func_append deplibs " -lc" + fi + ;; + esac + fi + + # Transform deplibs into only deplibs that can be linked in shared. + name_save=$name + libname_save=$libname + release_save=$release + versuffix_save=$versuffix + major_save=$major + # I'm not sure if I'm treating the release correctly. I think + # release should show up in the -l (ie -lgmp5) so we don't want to + # add it in twice. Is that correct? + release="" + versuffix="" + major="" + newdeplibs= + droppeddeps=no + case $deplibs_check_method in + pass_all) + # Don't check for shared/static. Everything works. + # This might be a little naive. We might want to check + # whether the library exists or not. But this is on + # osf3 & osf4 and I'm not really sure... Just + # implementing what was already the behavior. + newdeplibs=$deplibs + ;; + test_compile) + # This code stresses the "libraries are programs" paradigm to its + # limits. Maybe even breaks it. We compile a program, linking it + # against the deplibs as a proxy for the library. Then we can check + # whether they linked in statically or dynamically with ldd. + $opt_dry_run || $RM conftest.c + cat > conftest.c </dev/null` + $nocaseglob + else + potential_libs=`ls $i/$libnameglob[.-]* 2>/dev/null` + fi + for potent_lib in $potential_libs; do + # Follow soft links. + if ls -lLd "$potent_lib" 2>/dev/null | + $GREP " -> " >/dev/null; then + continue + fi + # The statement above tries to avoid entering an + # endless loop below, in case of cyclic links. + # We might still enter an endless loop, since a link + # loop can be closed while we follow links, + # but so what? + potlib="$potent_lib" + while test -h "$potlib" 2>/dev/null; do + potliblink=`ls -ld $potlib | ${SED} 's/.* -> //'` + case $potliblink in + [\\/]* | [A-Za-z]:[\\/]*) potlib="$potliblink";; + *) potlib=`$ECHO "$potlib" | $SED 's,[^/]*$,,'`"$potliblink";; + esac + done + if eval $file_magic_cmd \"\$potlib\" 2>/dev/null | + $SED -e 10q | + $EGREP "$file_magic_regex" > /dev/null; then + func_append newdeplibs " $a_deplib" + a_deplib="" + break 2 + fi + done + done + fi + if test -n "$a_deplib" ; then + droppeddeps=yes + echo + $ECHO "*** Warning: linker path does not have real file for library $a_deplib." + echo "*** I have the capability to make that library automatically link in when" + echo "*** you link to this library. But I can only do this if you have a" + echo "*** shared version of the library, which you do not appear to have" + echo "*** because I did check the linker path looking for a file starting" + if test -z "$potlib" ; then + $ECHO "*** with $libname but no candidates were found. (...for file magic test)" + else + $ECHO "*** with $libname and none of the candidates passed a file format test" + $ECHO "*** using a file magic. Last file checked: $potlib" + fi + fi + ;; + *) + # Add a -L argument. + func_append newdeplibs " $a_deplib" + ;; + esac + done # Gone through all deplibs. + ;; + match_pattern*) + set dummy $deplibs_check_method; shift + match_pattern_regex=`expr "$deplibs_check_method" : "$1 \(.*\)"` + for a_deplib in $deplibs; do + case $a_deplib in + -l*) + func_stripname -l '' "$a_deplib" + name=$func_stripname_result + if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then + case " $predeps $postdeps " in + *" $a_deplib "*) + func_append newdeplibs " $a_deplib" + a_deplib="" + ;; + esac + fi + if test -n "$a_deplib" ; then + libname=`eval "\\$ECHO \"$libname_spec\""` + for i in $lib_search_path $sys_lib_search_path $shlib_search_path; do + potential_libs=`ls $i/$libname[.-]* 2>/dev/null` + for potent_lib in $potential_libs; do + potlib="$potent_lib" # see symlink-check above in file_magic test + if eval "\$ECHO \"$potent_lib\"" 2>/dev/null | $SED 10q | \ + $EGREP "$match_pattern_regex" > /dev/null; then + func_append newdeplibs " $a_deplib" + a_deplib="" + break 2 + fi + done + done + fi + if test -n "$a_deplib" ; then + droppeddeps=yes + echo + $ECHO "*** Warning: linker path does not have real file for library $a_deplib." + echo "*** I have the capability to make that library automatically link in when" + echo "*** you link to this library. But I can only do this if you have a" + echo "*** shared version of the library, which you do not appear to have" + echo "*** because I did check the linker path looking for a file starting" + if test -z "$potlib" ; then + $ECHO "*** with $libname but no candidates were found. (...for regex pattern test)" + else + $ECHO "*** with $libname and none of the candidates passed a file format test" + $ECHO "*** using a regex pattern. Last file checked: $potlib" + fi + fi + ;; + *) + # Add a -L argument. + func_append newdeplibs " $a_deplib" + ;; + esac + done # Gone through all deplibs. + ;; + none | unknown | *) + newdeplibs="" + tmp_deplibs=`$ECHO " $deplibs" | $SED 's/ -lc$//; s/ -[LR][^ ]*//g'` + if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then + for i in $predeps $postdeps ; do + # can't use Xsed below, because $i might contain '/' + tmp_deplibs=`$ECHO " $tmp_deplibs" | $SED "s,$i,,"` + done + fi + case $tmp_deplibs in + *[!\ \ ]*) + echo + if test "X$deplibs_check_method" = "Xnone"; then + echo "*** Warning: inter-library dependencies are not supported in this platform." + else + echo "*** Warning: inter-library dependencies are not known to be supported." + fi + echo "*** All declared inter-library dependencies are being dropped." + droppeddeps=yes + ;; + esac + ;; + esac + versuffix=$versuffix_save + major=$major_save + release=$release_save + libname=$libname_save + name=$name_save + + case $host in + *-*-rhapsody* | *-*-darwin1.[012]) + # On Rhapsody replace the C library with the System framework + newdeplibs=`$ECHO " $newdeplibs" | $SED 's/ -lc / System.ltframework /'` + ;; + esac + + if test "$droppeddeps" = yes; then + if test "$module" = yes; then + echo + echo "*** Warning: libtool could not satisfy all declared inter-library" + $ECHO "*** dependencies of module $libname. Therefore, libtool will create" + echo "*** a static module, that should work as long as the dlopening" + echo "*** application is linked with the -dlopen flag." + if test -z "$global_symbol_pipe"; then + echo + echo "*** However, this would only work if libtool was able to extract symbol" + echo "*** lists from a program, using \`nm' or equivalent, but libtool could" + echo "*** not find such a program. So, this module is probably useless." + echo "*** \`nm' from GNU binutils and a full rebuild may help." + fi + if test "$build_old_libs" = no; then + oldlibs="$output_objdir/$libname.$libext" + build_libtool_libs=module + build_old_libs=yes + else + build_libtool_libs=no + fi + else + echo "*** The inter-library dependencies that have been dropped here will be" + echo "*** automatically added whenever a program is linked with this library" + echo "*** or is declared to -dlopen it." + + if test "$allow_undefined" = no; then + echo + echo "*** Since this library must not contain undefined symbols," + echo "*** because either the platform does not support them or" + echo "*** it was explicitly requested with -no-undefined," + echo "*** libtool will only create a static version of it." + if test "$build_old_libs" = no; then + oldlibs="$output_objdir/$libname.$libext" + build_libtool_libs=module + build_old_libs=yes + else + build_libtool_libs=no + fi + fi + fi + fi + # Done checking deplibs! + deplibs=$newdeplibs + fi + # Time to change all our "foo.ltframework" stuff back to "-framework foo" + case $host in + *-*-darwin*) + newdeplibs=`$ECHO " $newdeplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` + new_inherited_linker_flags=`$ECHO " $new_inherited_linker_flags" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` + deplibs=`$ECHO " $deplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` + ;; + esac + + # move library search paths that coincide with paths to not yet + # installed libraries to the beginning of the library search list + new_libs= + for path in $notinst_path; do + case " $new_libs " in + *" -L$path/$objdir "*) ;; + *) + case " $deplibs " in + *" -L$path/$objdir "*) + func_append new_libs " -L$path/$objdir" ;; + esac + ;; + esac + done + for deplib in $deplibs; do + case $deplib in + -L*) + case " $new_libs " in + *" $deplib "*) ;; + *) func_append new_libs " $deplib" ;; + esac + ;; + *) func_append new_libs " $deplib" ;; + esac + done + deplibs="$new_libs" + + # All the library-specific variables (install_libdir is set above). + library_names= + old_library= + dlname= + + # Test again, we may have decided not to build it any more + if test "$build_libtool_libs" = yes; then + if test "$hardcode_into_libs" = yes; then + # Hardcode the library paths + hardcode_libdirs= + dep_rpath= + rpath="$finalize_rpath" + test "$opt_mode" != relink && rpath="$compile_rpath$rpath" + for libdir in $rpath; do + if test -n "$hardcode_libdir_flag_spec"; then + if test -n "$hardcode_libdir_separator"; then + func_replace_sysroot "$libdir" + libdir=$func_replace_sysroot_result + if test -z "$hardcode_libdirs"; then + hardcode_libdirs="$libdir" + else + # Just accumulate the unique libdirs. + case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in + *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) + ;; + *) + func_append hardcode_libdirs "$hardcode_libdir_separator$libdir" + ;; + esac + fi + else + eval flag=\"$hardcode_libdir_flag_spec\" + func_append dep_rpath " $flag" + fi + elif test -n "$runpath_var"; then + case "$perm_rpath " in + *" $libdir "*) ;; + *) func_apped perm_rpath " $libdir" ;; + esac + fi + done + # Substitute the hardcoded libdirs into the rpath. + if test -n "$hardcode_libdir_separator" && + test -n "$hardcode_libdirs"; then + libdir="$hardcode_libdirs" + if test -n "$hardcode_libdir_flag_spec_ld"; then + eval dep_rpath=\"$hardcode_libdir_flag_spec_ld\" + else + eval dep_rpath=\"$hardcode_libdir_flag_spec\" + fi + fi + if test -n "$runpath_var" && test -n "$perm_rpath"; then + # We should set the runpath_var. + rpath= + for dir in $perm_rpath; do + func_append rpath "$dir:" + done + eval "$runpath_var='$rpath\$$runpath_var'; export $runpath_var" + fi + test -n "$dep_rpath" && deplibs="$dep_rpath $deplibs" + fi + + shlibpath="$finalize_shlibpath" + test "$opt_mode" != relink && shlibpath="$compile_shlibpath$shlibpath" + if test -n "$shlibpath"; then + eval "$shlibpath_var='$shlibpath\$$shlibpath_var'; export $shlibpath_var" + fi + + # Get the real and link names of the library. + eval shared_ext=\"$shrext_cmds\" + eval library_names=\"$library_names_spec\" + set dummy $library_names + shift + realname="$1" + shift + + if test -n "$soname_spec"; then + eval soname=\"$soname_spec\" + else + soname="$realname" + fi + if test -z "$dlname"; then + dlname=$soname + fi + + lib="$output_objdir/$realname" + linknames= + for link + do + func_append linknames " $link" + done + + # Use standard objects if they are pic + test -z "$pic_flag" && libobjs=`$ECHO "$libobjs" | $SP2NL | $SED "$lo2o" | $NL2SP` + test "X$libobjs" = "X " && libobjs= + + delfiles= + if test -n "$export_symbols" && test -n "$include_expsyms"; then + $opt_dry_run || cp "$export_symbols" "$output_objdir/$libname.uexp" + export_symbols="$output_objdir/$libname.uexp" + func_append delfiles " $export_symbols" + fi + + orig_export_symbols= + case $host_os in + cygwin* | mingw* | cegcc*) + if test -n "$export_symbols" && test -z "$export_symbols_regex"; then + # exporting using user supplied symfile + if test "x`$SED 1q $export_symbols`" != xEXPORTS; then + # and it's NOT already a .def file. Must figure out + # which of the given symbols are data symbols and tag + # them as such. So, trigger use of export_symbols_cmds. + # export_symbols gets reassigned inside the "prepare + # the list of exported symbols" if statement, so the + # include_expsyms logic still works. + orig_export_symbols="$export_symbols" + export_symbols= + always_export_symbols=yes + fi + fi + ;; + esac + + # Prepare the list of exported symbols + if test -z "$export_symbols"; then + if test "$always_export_symbols" = yes || test -n "$export_symbols_regex"; then + func_verbose "generating symbol list for \`$libname.la'" + export_symbols="$output_objdir/$libname.exp" + $opt_dry_run || $RM $export_symbols + cmds=$export_symbols_cmds + save_ifs="$IFS"; IFS='~' + for cmd1 in $cmds; do + IFS="$save_ifs" + # Take the normal branch if the nm_file_list_spec branch + # doesn't work or if tool conversion is not needed. + case $nm_file_list_spec~$to_tool_file_cmd in + *~func_convert_file_noop | *~func_convert_file_msys_to_w32 | ~*) + try_normal_branch=yes + eval cmd=\"$cmd1\" + func_len " $cmd" + len=$func_len_result + ;; + *) + try_normal_branch=no + ;; + esac + if test "$try_normal_branch" = yes \ + && { test "$len" -lt "$max_cmd_len" \ + || test "$max_cmd_len" -le -1; } + then + func_show_eval "$cmd" 'exit $?' + skipped_export=false + elif test -n "$nm_file_list_spec"; then + func_basename "$output" + output_la=$func_basename_result + save_libobjs=$libobjs + save_output=$output + output=${output_objdir}/${output_la}.nm + func_to_tool_file "$output" + libobjs=$nm_file_list_spec$func_to_tool_file_result + func_append delfiles " $output" + func_verbose "creating $NM input file list: $output" + for obj in $save_libobjs; do + func_to_tool_file "$obj" + $ECHO "$func_to_tool_file_result" + done > "$output" + eval cmd=\"$cmd1\" + func_show_eval "$cmd" 'exit $?' + output=$save_output + libobjs=$save_libobjs + skipped_export=false + else + # The command line is too long to execute in one step. + func_verbose "using reloadable object file for export list..." + skipped_export=: + # Break out early, otherwise skipped_export may be + # set to false by a later but shorter cmd. + break + fi + done + IFS="$save_ifs" + if test -n "$export_symbols_regex" && test "X$skipped_export" != "X:"; then + func_show_eval '$EGREP -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"' + func_show_eval '$MV "${export_symbols}T" "$export_symbols"' + fi + fi + fi + + if test -n "$export_symbols" && test -n "$include_expsyms"; then + tmp_export_symbols="$export_symbols" + test -n "$orig_export_symbols" && tmp_export_symbols="$orig_export_symbols" + $opt_dry_run || eval '$ECHO "$include_expsyms" | $SP2NL >> "$tmp_export_symbols"' + fi + + if test "X$skipped_export" != "X:" && test -n "$orig_export_symbols"; then + # The given exports_symbols file has to be filtered, so filter it. + func_verbose "filter symbol list for \`$libname.la' to tag DATA exports" + # FIXME: $output_objdir/$libname.filter potentially contains lots of + # 's' commands which not all seds can handle. GNU sed should be fine + # though. Also, the filter scales superlinearly with the number of + # global variables. join(1) would be nice here, but unfortunately + # isn't a blessed tool. + $opt_dry_run || $SED -e '/[ ,]DATA/!d;s,\(.*\)\([ \,].*\),s|^\1$|\1\2|,' < $export_symbols > $output_objdir/$libname.filter + func_append delfiles " $export_symbols $output_objdir/$libname.filter" + export_symbols=$output_objdir/$libname.def + $opt_dry_run || $SED -f $output_objdir/$libname.filter < $orig_export_symbols > $export_symbols + fi + + tmp_deplibs= + for test_deplib in $deplibs; do + case " $convenience " in + *" $test_deplib "*) ;; + *) + func_append tmp_deplibs " $test_deplib" + ;; + esac + done + deplibs="$tmp_deplibs" + + if test -n "$convenience"; then + if test -n "$whole_archive_flag_spec" && + test "$compiler_needs_object" = yes && + test -z "$libobjs"; then + # extract the archives, so we have objects to list. + # TODO: could optimize this to just extract one archive. + whole_archive_flag_spec= + fi + if test -n "$whole_archive_flag_spec"; then + save_libobjs=$libobjs + eval libobjs=\"\$libobjs $whole_archive_flag_spec\" + test "X$libobjs" = "X " && libobjs= + else + gentop="$output_objdir/${outputname}x" + func_append generated " $gentop" + + func_extract_archives $gentop $convenience + func_append libobjs " $func_extract_archives_result" + test "X$libobjs" = "X " && libobjs= + fi + fi + + if test "$thread_safe" = yes && test -n "$thread_safe_flag_spec"; then + eval flag=\"$thread_safe_flag_spec\" + func_append linker_flags " $flag" + fi + + # Make a backup of the uninstalled library when relinking + if test "$opt_mode" = relink; then + $opt_dry_run || eval '(cd $output_objdir && $RM ${realname}U && $MV $realname ${realname}U)' || exit $? + fi + + # Do each of the archive commands. + if test "$module" = yes && test -n "$module_cmds" ; then + if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then + eval test_cmds=\"$module_expsym_cmds\" + cmds=$module_expsym_cmds + else + eval test_cmds=\"$module_cmds\" + cmds=$module_cmds + fi + else + if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then + eval test_cmds=\"$archive_expsym_cmds\" + cmds=$archive_expsym_cmds + else + eval test_cmds=\"$archive_cmds\" + cmds=$archive_cmds + fi + fi + + if test "X$skipped_export" != "X:" && + func_len " $test_cmds" && + len=$func_len_result && + test "$len" -lt "$max_cmd_len" || test "$max_cmd_len" -le -1; then + : + else + # The command line is too long to link in one step, link piecewise + # or, if using GNU ld and skipped_export is not :, use a linker + # script. + + # Save the value of $output and $libobjs because we want to + # use them later. If we have whole_archive_flag_spec, we + # want to use save_libobjs as it was before + # whole_archive_flag_spec was expanded, because we can't + # assume the linker understands whole_archive_flag_spec. + # This may have to be revisited, in case too many + # convenience libraries get linked in and end up exceeding + # the spec. + if test -z "$convenience" || test -z "$whole_archive_flag_spec"; then + save_libobjs=$libobjs + fi + save_output=$output + func_basename "$output" + output_la=$func_basename_result + + # Clear the reloadable object creation command queue and + # initialize k to one. + test_cmds= + concat_cmds= + objlist= + last_robj= + k=1 + + if test -n "$save_libobjs" && test "X$skipped_export" != "X:" && test "$with_gnu_ld" = yes; then + output=${output_objdir}/${output_la}.lnkscript + func_verbose "creating GNU ld script: $output" + echo 'INPUT (' > $output + for obj in $save_libobjs + do + func_to_tool_file "$obj" + $ECHO "$func_to_tool_file_result" >> $output + done + echo ')' >> $output + func_append delfiles " $output" + func_to_tool_file "$output" + output=$func_to_tool_file_result + elif test -n "$save_libobjs" && test "X$skipped_export" != "X:" && test "X$file_list_spec" != X; then + output=${output_objdir}/${output_la}.lnk + func_verbose "creating linker input file list: $output" + : > $output + set x $save_libobjs + shift + firstobj= + if test "$compiler_needs_object" = yes; then + firstobj="$1 " + shift + fi + for obj + do + func_to_tool_file "$obj" + $ECHO "$func_to_tool_file_result" >> $output + done + func_append delfiles " $output" + func_to_tool_file "$output" + output=$firstobj\"$file_list_spec$func_to_tool_file_result\" + else + if test -n "$save_libobjs"; then + func_verbose "creating reloadable object files..." + output=$output_objdir/$output_la-${k}.$objext + eval test_cmds=\"$reload_cmds\" + func_len " $test_cmds" + len0=$func_len_result + len=$len0 + + # Loop over the list of objects to be linked. + for obj in $save_libobjs + do + func_len " $obj" + func_arith $len + $func_len_result + len=$func_arith_result + if test "X$objlist" = X || + test "$len" -lt "$max_cmd_len"; then + func_append objlist " $obj" + else + # The command $test_cmds is almost too long, add a + # command to the queue. + if test "$k" -eq 1 ; then + # The first file doesn't have a previous command to add. + reload_objs=$objlist + eval concat_cmds=\"$reload_cmds\" + else + # All subsequent reloadable object files will link in + # the last one created. + reload_objs="$objlist $last_robj" + eval concat_cmds=\"\$concat_cmds~$reload_cmds~\$RM $last_robj\" + fi + last_robj=$output_objdir/$output_la-${k}.$objext + func_arith $k + 1 + k=$func_arith_result + output=$output_objdir/$output_la-${k}.$objext + objlist=" $obj" + func_len " $last_robj" + func_arith $len0 + $func_len_result + len=$func_arith_result + fi + done + # Handle the remaining objects by creating one last + # reloadable object file. All subsequent reloadable object + # files will link in the last one created. + test -z "$concat_cmds" || concat_cmds=$concat_cmds~ + reload_objs="$objlist $last_robj" + eval concat_cmds=\"\${concat_cmds}$reload_cmds\" + if test -n "$last_robj"; then + eval concat_cmds=\"\${concat_cmds}~\$RM $last_robj\" + fi + func_append delfiles " $output" + + else + output= + fi + + if ${skipped_export-false}; then + func_verbose "generating symbol list for \`$libname.la'" + export_symbols="$output_objdir/$libname.exp" + $opt_dry_run || $RM $export_symbols + libobjs=$output + # Append the command to create the export file. + test -z "$concat_cmds" || concat_cmds=$concat_cmds~ + eval concat_cmds=\"\$concat_cmds$export_symbols_cmds\" + if test -n "$last_robj"; then + eval concat_cmds=\"\$concat_cmds~\$RM $last_robj\" + fi + fi + + test -n "$save_libobjs" && + func_verbose "creating a temporary reloadable object file: $output" + + # Loop through the commands generated above and execute them. + save_ifs="$IFS"; IFS='~' + for cmd in $concat_cmds; do + IFS="$save_ifs" + $opt_silent || { + func_quote_for_expand "$cmd" + eval "func_echo $func_quote_for_expand_result" + } + $opt_dry_run || eval "$cmd" || { + lt_exit=$? + + # Restore the uninstalled library and exit + if test "$opt_mode" = relink; then + ( cd "$output_objdir" && \ + $RM "${realname}T" && \ + $MV "${realname}U" "$realname" ) + fi + + exit $lt_exit + } + done + IFS="$save_ifs" + + if test -n "$export_symbols_regex" && ${skipped_export-false}; then + func_show_eval '$EGREP -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"' + func_show_eval '$MV "${export_symbols}T" "$export_symbols"' + fi + fi + + if ${skipped_export-false}; then + if test -n "$export_symbols" && test -n "$include_expsyms"; then + tmp_export_symbols="$export_symbols" + test -n "$orig_export_symbols" && tmp_export_symbols="$orig_export_symbols" + $opt_dry_run || eval '$ECHO "$include_expsyms" | $SP2NL >> "$tmp_export_symbols"' + fi + + if test -n "$orig_export_symbols"; then + # The given exports_symbols file has to be filtered, so filter it. + func_verbose "filter symbol list for \`$libname.la' to tag DATA exports" + # FIXME: $output_objdir/$libname.filter potentially contains lots of + # 's' commands which not all seds can handle. GNU sed should be fine + # though. Also, the filter scales superlinearly with the number of + # global variables. join(1) would be nice here, but unfortunately + # isn't a blessed tool. + $opt_dry_run || $SED -e '/[ ,]DATA/!d;s,\(.*\)\([ \,].*\),s|^\1$|\1\2|,' < $export_symbols > $output_objdir/$libname.filter + func_append delfiles " $export_symbols $output_objdir/$libname.filter" + export_symbols=$output_objdir/$libname.def + $opt_dry_run || $SED -f $output_objdir/$libname.filter < $orig_export_symbols > $export_symbols + fi + fi + + libobjs=$output + # Restore the value of output. + output=$save_output + + if test -n "$convenience" && test -n "$whole_archive_flag_spec"; then + eval libobjs=\"\$libobjs $whole_archive_flag_spec\" + test "X$libobjs" = "X " && libobjs= + fi + # Expand the library linking commands again to reset the + # value of $libobjs for piecewise linking. + + # Do each of the archive commands. + if test "$module" = yes && test -n "$module_cmds" ; then + if test -n "$export_symbols" && test -n "$module_expsym_cmds"; then + cmds=$module_expsym_cmds + else + cmds=$module_cmds + fi + else + if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then + cmds=$archive_expsym_cmds + else + cmds=$archive_cmds + fi + fi + fi + + if test -n "$delfiles"; then + # Append the command to remove temporary files to $cmds. + eval cmds=\"\$cmds~\$RM $delfiles\" + fi + + # Add any objects from preloaded convenience libraries + if test -n "$dlprefiles"; then + gentop="$output_objdir/${outputname}x" + func_append generated " $gentop" + + func_extract_archives $gentop $dlprefiles + func_append libobjs " $func_extract_archives_result" + test "X$libobjs" = "X " && libobjs= + fi + + save_ifs="$IFS"; IFS='~' + for cmd in $cmds; do + IFS="$save_ifs" + eval cmd=\"$cmd\" + $opt_silent || { + func_quote_for_expand "$cmd" + eval "func_echo $func_quote_for_expand_result" + } + $opt_dry_run || eval "$cmd" || { + lt_exit=$? + + # Restore the uninstalled library and exit + if test "$opt_mode" = relink; then + ( cd "$output_objdir" && \ + $RM "${realname}T" && \ + $MV "${realname}U" "$realname" ) + fi + + exit $lt_exit + } + done + IFS="$save_ifs" + + # Restore the uninstalled library and exit + if test "$opt_mode" = relink; then + $opt_dry_run || eval '(cd $output_objdir && $RM ${realname}T && $MV $realname ${realname}T && $MV ${realname}U $realname)' || exit $? + + if test -n "$convenience"; then + if test -z "$whole_archive_flag_spec"; then + func_show_eval '${RM}r "$gentop"' + fi + fi + + exit $EXIT_SUCCESS + fi + + # Create links to the real library. + for linkname in $linknames; do + if test "$realname" != "$linkname"; then + func_show_eval '(cd "$output_objdir" && $RM "$linkname" && $LN_S "$realname" "$linkname")' 'exit $?' + fi + done + + # If -module or -export-dynamic was specified, set the dlname. + if test "$module" = yes || test "$export_dynamic" = yes; then + # On all known operating systems, these are identical. + dlname="$soname" + fi + fi + ;; + + obj) + if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then + func_warning "\`-dlopen' is ignored for objects" + fi + + case " $deplibs" in + *\ -l* | *\ -L*) + func_warning "\`-l' and \`-L' are ignored for objects" ;; + esac + + test -n "$rpath" && \ + func_warning "\`-rpath' is ignored for objects" + + test -n "$xrpath" && \ + func_warning "\`-R' is ignored for objects" + + test -n "$vinfo" && \ + func_warning "\`-version-info' is ignored for objects" + + test -n "$release" && \ + func_warning "\`-release' is ignored for objects" + + case $output in + *.lo) + test -n "$objs$old_deplibs" && \ + func_fatal_error "cannot build library object \`$output' from non-libtool objects" + + libobj=$output + func_lo2o "$libobj" + obj=$func_lo2o_result + ;; + *) + libobj= + obj="$output" + ;; + esac + + # Delete the old objects. + $opt_dry_run || $RM $obj $libobj + + # Objects from convenience libraries. This assumes + # single-version convenience libraries. Whenever we create + # different ones for PIC/non-PIC, this we'll have to duplicate + # the extraction. + reload_conv_objs= + gentop= + # reload_cmds runs $LD directly, so let us get rid of + # -Wl from whole_archive_flag_spec and hope we can get by with + # turning comma into space.. + wl= + + if test -n "$convenience"; then + if test -n "$whole_archive_flag_spec"; then + eval tmp_whole_archive_flags=\"$whole_archive_flag_spec\" + reload_conv_objs=$reload_objs\ `$ECHO "$tmp_whole_archive_flags" | $SED 's|,| |g'` + else + gentop="$output_objdir/${obj}x" + func_append generated " $gentop" + + func_extract_archives $gentop $convenience + reload_conv_objs="$reload_objs $func_extract_archives_result" + fi + fi + + # If we're not building shared, we need to use non_pic_objs + test "$build_libtool_libs" != yes && libobjs="$non_pic_objects" + + # Create the old-style object. + reload_objs="$objs$old_deplibs "`$ECHO "$libobjs" | $SP2NL | $SED "/\.${libext}$/d; /\.lib$/d; $lo2o" | $NL2SP`" $reload_conv_objs" ### testsuite: skip nested quoting test + + output="$obj" + func_execute_cmds "$reload_cmds" 'exit $?' + + # Exit if we aren't doing a library object file. + if test -z "$libobj"; then + if test -n "$gentop"; then + func_show_eval '${RM}r "$gentop"' + fi + + exit $EXIT_SUCCESS + fi + + if test "$build_libtool_libs" != yes; then + if test -n "$gentop"; then + func_show_eval '${RM}r "$gentop"' + fi + + # Create an invalid libtool object if no PIC, so that we don't + # accidentally link it into a program. + # $show "echo timestamp > $libobj" + # $opt_dry_run || eval "echo timestamp > $libobj" || exit $? + exit $EXIT_SUCCESS + fi + + if test -n "$pic_flag" || test "$pic_mode" != default; then + # Only do commands if we really have different PIC objects. + reload_objs="$libobjs $reload_conv_objs" + output="$libobj" + func_execute_cmds "$reload_cmds" 'exit $?' + fi + + if test -n "$gentop"; then + func_show_eval '${RM}r "$gentop"' + fi + + exit $EXIT_SUCCESS + ;; + + prog) + case $host in + *cygwin*) func_stripname '' '.exe' "$output" + output=$func_stripname_result.exe;; + esac + test -n "$vinfo" && \ + func_warning "\`-version-info' is ignored for programs" + + test -n "$release" && \ + func_warning "\`-release' is ignored for programs" + + test "$preload" = yes \ + && test "$dlopen_support" = unknown \ + && test "$dlopen_self" = unknown \ + && test "$dlopen_self_static" = unknown && \ + func_warning "\`LT_INIT([dlopen])' not used. Assuming no dlopen support." + + case $host in + *-*-rhapsody* | *-*-darwin1.[012]) + # On Rhapsody replace the C library is the System framework + compile_deplibs=`$ECHO " $compile_deplibs" | $SED 's/ -lc / System.ltframework /'` + finalize_deplibs=`$ECHO " $finalize_deplibs" | $SED 's/ -lc / System.ltframework /'` + ;; + esac + + case $host in + *-*-darwin*) + # Don't allow lazy linking, it breaks C++ global constructors + # But is supposedly fixed on 10.4 or later (yay!). + if test "$tagname" = CXX ; then + case ${MACOSX_DEPLOYMENT_TARGET-10.0} in + 10.[0123]) + func_append compile_command " ${wl}-bind_at_load" + func_append finalize_command " ${wl}-bind_at_load" + ;; + esac + fi + # Time to change all our "foo.ltframework" stuff back to "-framework foo" + compile_deplibs=`$ECHO " $compile_deplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` + finalize_deplibs=`$ECHO " $finalize_deplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` + ;; + esac + + + # move library search paths that coincide with paths to not yet + # installed libraries to the beginning of the library search list + new_libs= + for path in $notinst_path; do + case " $new_libs " in + *" -L$path/$objdir "*) ;; + *) + case " $compile_deplibs " in + *" -L$path/$objdir "*) + func_append new_libs " -L$path/$objdir" ;; + esac + ;; + esac + done + for deplib in $compile_deplibs; do + case $deplib in + -L*) + case " $new_libs " in + *" $deplib "*) ;; + *) func_append new_libs " $deplib" ;; + esac + ;; + *) func_append new_libs " $deplib" ;; + esac + done + compile_deplibs="$new_libs" + + + func_append compile_command " $compile_deplibs" + func_append finalize_command " $finalize_deplibs" + + if test -n "$rpath$xrpath"; then + # If the user specified any rpath flags, then add them. + for libdir in $rpath $xrpath; do + # This is the magic to use -rpath. + case "$finalize_rpath " in + *" $libdir "*) ;; + *) func_append finalize_rpath " $libdir" ;; + esac + done + fi + + # Now hardcode the library paths + rpath= + hardcode_libdirs= + for libdir in $compile_rpath $finalize_rpath; do + if test -n "$hardcode_libdir_flag_spec"; then + if test -n "$hardcode_libdir_separator"; then + if test -z "$hardcode_libdirs"; then + hardcode_libdirs="$libdir" + else + # Just accumulate the unique libdirs. + case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in + *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) + ;; + *) + func_append hardcode_libdirs "$hardcode_libdir_separator$libdir" + ;; + esac + fi + else + eval flag=\"$hardcode_libdir_flag_spec\" + func_append rpath " $flag" + fi + elif test -n "$runpath_var"; then + case "$perm_rpath " in + *" $libdir "*) ;; + *) func_append perm_rpath " $libdir" ;; + esac + fi + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*) + testbindir=`${ECHO} "$libdir" | ${SED} -e 's*/lib$*/bin*'` + case :$dllsearchpath: in + *":$libdir:"*) ;; + ::) dllsearchpath=$libdir;; + *) func_append dllsearchpath ":$libdir";; + esac + case :$dllsearchpath: in + *":$testbindir:"*) ;; + ::) dllsearchpath=$testbindir;; + *) func_append dllsearchpath ":$testbindir";; + esac + ;; + esac + done + # Substitute the hardcoded libdirs into the rpath. + if test -n "$hardcode_libdir_separator" && + test -n "$hardcode_libdirs"; then + libdir="$hardcode_libdirs" + eval rpath=\" $hardcode_libdir_flag_spec\" + fi + compile_rpath="$rpath" + + rpath= + hardcode_libdirs= + for libdir in $finalize_rpath; do + if test -n "$hardcode_libdir_flag_spec"; then + if test -n "$hardcode_libdir_separator"; then + if test -z "$hardcode_libdirs"; then + hardcode_libdirs="$libdir" + else + # Just accumulate the unique libdirs. + case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in + *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) + ;; + *) + func_append hardcode_libdirs "$hardcode_libdir_separator$libdir" + ;; + esac + fi + else + eval flag=\"$hardcode_libdir_flag_spec\" + func_append rpath " $flag" + fi + elif test -n "$runpath_var"; then + case "$finalize_perm_rpath " in + *" $libdir "*) ;; + *) func_append finalize_perm_rpath " $libdir" ;; + esac + fi + done + # Substitute the hardcoded libdirs into the rpath. + if test -n "$hardcode_libdir_separator" && + test -n "$hardcode_libdirs"; then + libdir="$hardcode_libdirs" + eval rpath=\" $hardcode_libdir_flag_spec\" + fi + finalize_rpath="$rpath" + + if test -n "$libobjs" && test "$build_old_libs" = yes; then + # Transform all the library objects into standard objects. + compile_command=`$ECHO "$compile_command" | $SP2NL | $SED "$lo2o" | $NL2SP` + finalize_command=`$ECHO "$finalize_command" | $SP2NL | $SED "$lo2o" | $NL2SP` + fi + + func_generate_dlsyms "$outputname" "@PROGRAM@" "no" + + # template prelinking step + if test -n "$prelink_cmds"; then + func_execute_cmds "$prelink_cmds" 'exit $?' + fi + + wrappers_required=yes + case $host in + *cegcc* | *mingw32ce*) + # Disable wrappers for cegcc and mingw32ce hosts, we are cross compiling anyway. + wrappers_required=no + ;; + *cygwin* | *mingw* ) + if test "$build_libtool_libs" != yes; then + wrappers_required=no + fi + ;; + *) + if test "$need_relink" = no || test "$build_libtool_libs" != yes; then + wrappers_required=no + fi + ;; + esac + if test "$wrappers_required" = no; then + # Replace the output file specification. + compile_command=`$ECHO "$compile_command" | $SED 's%@OUTPUT@%'"$output"'%g'` + link_command="$compile_command$compile_rpath" + + # We have no uninstalled library dependencies, so finalize right now. + exit_status=0 + func_show_eval "$link_command" 'exit_status=$?' + + if test -n "$postlink_cmds"; then + func_to_tool_file "$output" + postlink_cmds=`func_echo_all "$postlink_cmds" | $SED -e 's%@OUTPUT@%'"$output"'%g' -e 's%@TOOL_OUTPUT@%'"$func_to_tool_file_result"'%g'` + func_execute_cmds "$postlink_cmds" 'exit $?' + fi + + # Delete the generated files. + if test -f "$output_objdir/${outputname}S.${objext}"; then + func_show_eval '$RM "$output_objdir/${outputname}S.${objext}"' + fi + + exit $exit_status + fi + + if test -n "$compile_shlibpath$finalize_shlibpath"; then + compile_command="$shlibpath_var=\"$compile_shlibpath$finalize_shlibpath\$$shlibpath_var\" $compile_command" + fi + if test -n "$finalize_shlibpath"; then + finalize_command="$shlibpath_var=\"$finalize_shlibpath\$$shlibpath_var\" $finalize_command" + fi + + compile_var= + finalize_var= + if test -n "$runpath_var"; then + if test -n "$perm_rpath"; then + # We should set the runpath_var. + rpath= + for dir in $perm_rpath; do + func_append rpath "$dir:" + done + compile_var="$runpath_var=\"$rpath\$$runpath_var\" " + fi + if test -n "$finalize_perm_rpath"; then + # We should set the runpath_var. + rpath= + for dir in $finalize_perm_rpath; do + func_append rpath "$dir:" + done + finalize_var="$runpath_var=\"$rpath\$$runpath_var\" " + fi + fi + + if test "$no_install" = yes; then + # We don't need to create a wrapper script. + link_command="$compile_var$compile_command$compile_rpath" + # Replace the output file specification. + link_command=`$ECHO "$link_command" | $SED 's%@OUTPUT@%'"$output"'%g'` + # Delete the old output file. + $opt_dry_run || $RM $output + # Link the executable and exit + func_show_eval "$link_command" 'exit $?' + + if test -n "$postlink_cmds"; then + func_to_tool_file "$output" + postlink_cmds=`func_echo_all "$postlink_cmds" | $SED -e 's%@OUTPUT@%'"$output"'%g' -e 's%@TOOL_OUTPUT@%'"$func_to_tool_file_result"'%g'` + func_execute_cmds "$postlink_cmds" 'exit $?' + fi + + exit $EXIT_SUCCESS + fi + + if test "$hardcode_action" = relink; then + # Fast installation is not supported + link_command="$compile_var$compile_command$compile_rpath" + relink_command="$finalize_var$finalize_command$finalize_rpath" + + func_warning "this platform does not like uninstalled shared libraries" + func_warning "\`$output' will be relinked during installation" + else + if test "$fast_install" != no; then + link_command="$finalize_var$compile_command$finalize_rpath" + if test "$fast_install" = yes; then + relink_command=`$ECHO "$compile_var$compile_command$compile_rpath" | $SED 's%@OUTPUT@%\$progdir/\$file%g'` + else + # fast_install is set to needless + relink_command= + fi + else + link_command="$compile_var$compile_command$compile_rpath" + relink_command="$finalize_var$finalize_command$finalize_rpath" + fi + fi + + # Replace the output file specification. + link_command=`$ECHO "$link_command" | $SED 's%@OUTPUT@%'"$output_objdir/$outputname"'%g'` + + # Delete the old output files. + $opt_dry_run || $RM $output $output_objdir/$outputname $output_objdir/lt-$outputname + + func_show_eval "$link_command" 'exit $?' + + if test -n "$postlink_cmds"; then + func_to_tool_file "$output_objdir/$outputname" + postlink_cmds=`func_echo_all "$postlink_cmds" | $SED -e 's%@OUTPUT@%'"$output_objdir/$outputname"'%g' -e 's%@TOOL_OUTPUT@%'"$func_to_tool_file_result"'%g'` + func_execute_cmds "$postlink_cmds" 'exit $?' + fi + + # Now create the wrapper script. + func_verbose "creating $output" + + # Quote the relink command for shipping. + if test -n "$relink_command"; then + # Preserve any variables that may affect compiler behavior + for var in $variables_saved_for_relink; do + if eval test -z \"\${$var+set}\"; then + relink_command="{ test -z \"\${$var+set}\" || $lt_unset $var || { $var=; export $var; }; }; $relink_command" + elif eval var_value=\$$var; test -z "$var_value"; then + relink_command="$var=; export $var; $relink_command" + else + func_quote_for_eval "$var_value" + relink_command="$var=$func_quote_for_eval_result; export $var; $relink_command" + fi + done + relink_command="(cd `pwd`; $relink_command)" + relink_command=`$ECHO "$relink_command" | $SED "$sed_quote_subst"` + fi + + # Only actually do things if not in dry run mode. + $opt_dry_run || { + # win32 will think the script is a binary if it has + # a .exe suffix, so we strip it off here. + case $output in + *.exe) func_stripname '' '.exe' "$output" + output=$func_stripname_result ;; + esac + # test for cygwin because mv fails w/o .exe extensions + case $host in + *cygwin*) + exeext=.exe + func_stripname '' '.exe' "$outputname" + outputname=$func_stripname_result ;; + *) exeext= ;; + esac + case $host in + *cygwin* | *mingw* ) + func_dirname_and_basename "$output" "" "." + output_name=$func_basename_result + output_path=$func_dirname_result + cwrappersource="$output_path/$objdir/lt-$output_name.c" + cwrapper="$output_path/$output_name.exe" + $RM $cwrappersource $cwrapper + trap "$RM $cwrappersource $cwrapper; exit $EXIT_FAILURE" 1 2 15 + + func_emit_cwrapperexe_src > $cwrappersource + + # The wrapper executable is built using the $host compiler, + # because it contains $host paths and files. If cross- + # compiling, it, like the target executable, must be + # executed on the $host or under an emulation environment. + $opt_dry_run || { + $LTCC $LTCFLAGS -o $cwrapper $cwrappersource + $STRIP $cwrapper + } + + # Now, create the wrapper script for func_source use: + func_ltwrapper_scriptname $cwrapper + $RM $func_ltwrapper_scriptname_result + trap "$RM $func_ltwrapper_scriptname_result; exit $EXIT_FAILURE" 1 2 15 + $opt_dry_run || { + # note: this script will not be executed, so do not chmod. + if test "x$build" = "x$host" ; then + $cwrapper --lt-dump-script > $func_ltwrapper_scriptname_result + else + func_emit_wrapper no > $func_ltwrapper_scriptname_result + fi + } + ;; + * ) + $RM $output + trap "$RM $output; exit $EXIT_FAILURE" 1 2 15 + + func_emit_wrapper no > $output + chmod +x $output + ;; + esac + } + exit $EXIT_SUCCESS + ;; + esac + + # See if we need to build an old-fashioned archive. + for oldlib in $oldlibs; do + + if test "$build_libtool_libs" = convenience; then + oldobjs="$libobjs_save $symfileobj" + addlibs="$convenience" + build_libtool_libs=no + else + if test "$build_libtool_libs" = module; then + oldobjs="$libobjs_save" + build_libtool_libs=no + else + oldobjs="$old_deplibs $non_pic_objects" + if test "$preload" = yes && test -f "$symfileobj"; then + func_append oldobjs " $symfileobj" + fi + fi + addlibs="$old_convenience" + fi + + if test -n "$addlibs"; then + gentop="$output_objdir/${outputname}x" + func_append generated " $gentop" + + func_extract_archives $gentop $addlibs + func_append oldobjs " $func_extract_archives_result" + fi + + # Do each command in the archive commands. + if test -n "$old_archive_from_new_cmds" && test "$build_libtool_libs" = yes; then + cmds=$old_archive_from_new_cmds + else + + # Add any objects from preloaded convenience libraries + if test -n "$dlprefiles"; then + gentop="$output_objdir/${outputname}x" + func_append generated " $gentop" + + func_extract_archives $gentop $dlprefiles + func_append oldobjs " $func_extract_archives_result" + fi + + # POSIX demands no paths to be encoded in archives. We have + # to avoid creating archives with duplicate basenames if we + # might have to extract them afterwards, e.g., when creating a + # static archive out of a convenience library, or when linking + # the entirety of a libtool archive into another (currently + # not supported by libtool). + if (for obj in $oldobjs + do + func_basename "$obj" + $ECHO "$func_basename_result" + done | sort | sort -uc >/dev/null 2>&1); then + : + else + echo "copying selected object files to avoid basename conflicts..." + gentop="$output_objdir/${outputname}x" + func_append generated " $gentop" + func_mkdir_p "$gentop" + save_oldobjs=$oldobjs + oldobjs= + counter=1 + for obj in $save_oldobjs + do + func_basename "$obj" + objbase="$func_basename_result" + case " $oldobjs " in + " ") oldobjs=$obj ;; + *[\ /]"$objbase "*) + while :; do + # Make sure we don't pick an alternate name that also + # overlaps. + newobj=lt$counter-$objbase + func_arith $counter + 1 + counter=$func_arith_result + case " $oldobjs " in + *[\ /]"$newobj "*) ;; + *) if test ! -f "$gentop/$newobj"; then break; fi ;; + esac + done + func_show_eval "ln $obj $gentop/$newobj || cp $obj $gentop/$newobj" + func_append oldobjs " $gentop/$newobj" + ;; + *) func_append oldobjs " $obj" ;; + esac + done + fi + eval cmds=\"$old_archive_cmds\" + + func_len " $cmds" + len=$func_len_result + if test "$len" -lt "$max_cmd_len" || test "$max_cmd_len" -le -1; then + cmds=$old_archive_cmds + elif test -n "$archiver_list_spec"; then + func_verbose "using command file archive linking..." + for obj in $oldobjs + do + func_to_tool_file "$obj" + $ECHO "$func_to_tool_file_result" + done > $output_objdir/$libname.libcmd + func_to_tool_file "$output_objdir/$libname.libcmd" + oldobjs=" $archiver_list_spec$func_to_tool_file_result" + cmds=$old_archive_cmds + else + # the command line is too long to link in one step, link in parts + func_verbose "using piecewise archive linking..." + save_RANLIB=$RANLIB + RANLIB=: + objlist= + concat_cmds= + save_oldobjs=$oldobjs + oldobjs= + # Is there a better way of finding the last object in the list? + for obj in $save_oldobjs + do + last_oldobj=$obj + done + eval test_cmds=\"$old_archive_cmds\" + func_len " $test_cmds" + len0=$func_len_result + len=$len0 + for obj in $save_oldobjs + do + func_len " $obj" + func_arith $len + $func_len_result + len=$func_arith_result + func_append objlist " $obj" + if test "$len" -lt "$max_cmd_len"; then + : + else + # the above command should be used before it gets too long + oldobjs=$objlist + if test "$obj" = "$last_oldobj" ; then + RANLIB=$save_RANLIB + fi + test -z "$concat_cmds" || concat_cmds=$concat_cmds~ + eval concat_cmds=\"\${concat_cmds}$old_archive_cmds\" + objlist= + len=$len0 + fi + done + RANLIB=$save_RANLIB + oldobjs=$objlist + if test "X$oldobjs" = "X" ; then + eval cmds=\"\$concat_cmds\" + else + eval cmds=\"\$concat_cmds~\$old_archive_cmds\" + fi + fi + fi + func_execute_cmds "$cmds" 'exit $?' + done + + test -n "$generated" && \ + func_show_eval "${RM}r$generated" + + # Now create the libtool archive. + case $output in + *.la) + old_library= + test "$build_old_libs" = yes && old_library="$libname.$libext" + func_verbose "creating $output" + + # Preserve any variables that may affect compiler behavior + for var in $variables_saved_for_relink; do + if eval test -z \"\${$var+set}\"; then + relink_command="{ test -z \"\${$var+set}\" || $lt_unset $var || { $var=; export $var; }; }; $relink_command" + elif eval var_value=\$$var; test -z "$var_value"; then + relink_command="$var=; export $var; $relink_command" + else + func_quote_for_eval "$var_value" + relink_command="$var=$func_quote_for_eval_result; export $var; $relink_command" + fi + done + # Quote the link command for shipping. + relink_command="(cd `pwd`; $SHELL $progpath $preserve_args --mode=relink $libtool_args @inst_prefix_dir@)" + relink_command=`$ECHO "$relink_command" | $SED "$sed_quote_subst"` + if test "$hardcode_automatic" = yes ; then + relink_command= + fi + + # Only create the output if not a dry run. + $opt_dry_run || { + for installed in no yes; do + if test "$installed" = yes; then + if test -z "$install_libdir"; then + break + fi + output="$output_objdir/$outputname"i + # Replace all uninstalled libtool libraries with the installed ones + newdependency_libs= + for deplib in $dependency_libs; do + case $deplib in + *.la) + func_basename "$deplib" + name="$func_basename_result" + eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $deplib` + test -z "$libdir" && \ + func_fatal_error "\`$deplib' is not a valid libtool archive" + func_append newdependency_libs " ${lt_sysroot:+=}$libdir/$name" + ;; + -L*) + func_stripname -L '' "$deplib" + func_replace_sysroot "$func_stripname_result" + func_append newdependency_libs " -L$func_replace_sysroot_result" + ;; + -R*) + func_stripname -R '' "$deplib" + func_replace_sysroot "$func_stripname_result" + func_append newdependency_libs " -R$func_replace_sysroot_result" + ;; + *) func_append newdependency_libs " $deplib" ;; + esac + done + dependency_libs="$newdependency_libs" + newdlfiles= + + for lib in $dlfiles; do + case $lib in + *.la) + func_basename "$lib" + name="$func_basename_result" + eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $lib` + test -z "$libdir" && \ + func_fatal_error "\`$lib' is not a valid libtool archive" + func_append newdlfiles " ${lt_sysroot:+=}$libdir/$name" + ;; + *) func_append newdlfiles " $lib" ;; + esac + done + dlfiles="$newdlfiles" + newdlprefiles= + for lib in $dlprefiles; do + case $lib in + *.la) + # Only pass preopened files to the pseudo-archive (for + # eventual linking with the app. that links it) if we + # didn't already link the preopened objects directly into + # the library: + func_basename "$lib" + name="$func_basename_result" + eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $lib` + test -z "$libdir" && \ + func_fatal_error "\`$lib' is not a valid libtool archive" + func_append newdlprefiles " ${lt_sysroot:+=}$libdir/$name" + ;; + esac + done + dlprefiles="$newdlprefiles" + else + newdlfiles= + for lib in $dlfiles; do + case $lib in + [\\/]* | [A-Za-z]:[\\/]*) abs="$lib" ;; + *) abs=`pwd`"/$lib" ;; + esac + func_append newdlfiles " $abs" + done + dlfiles="$newdlfiles" + newdlprefiles= + for lib in $dlprefiles; do + case $lib in + [\\/]* | [A-Za-z]:[\\/]*) abs="$lib" ;; + *) abs=`pwd`"/$lib" ;; + esac + func_append newdlprefiles " $abs" + done + dlprefiles="$newdlprefiles" + fi + $RM $output + # place dlname in correct position for cygwin + # In fact, it would be nice if we could use this code for all target + # systems that can't hard-code library paths into their executables + # and that have no shared library path variable independent of PATH, + # but it turns out we can't easily determine that from inspecting + # libtool variables, so we have to hard-code the OSs to which it + # applies here; at the moment, that means platforms that use the PE + # object format with DLL files. See the long comment at the top of + # tests/bindir.at for full details. + tdlname=$dlname + case $host,$output,$installed,$module,$dlname in + *cygwin*,*lai,yes,no,*.dll | *mingw*,*lai,yes,no,*.dll | *cegcc*,*lai,yes,no,*.dll) + # If a -bindir argument was supplied, place the dll there. + if test "x$bindir" != x ; + then + func_relative_path "$install_libdir" "$bindir" + tdlname=$func_relative_path_result$dlname + else + # Otherwise fall back on heuristic. + tdlname=../bin/$dlname + fi + ;; + esac + $ECHO > $output "\ +# $outputname - a libtool library file +# Generated by $PROGRAM (GNU $PACKAGE$TIMESTAMP) $VERSION +# +# Please DO NOT delete this file! +# It is necessary for linking the library. + +# The name that we can dlopen(3). +dlname='$tdlname' + +# Names of this library. +library_names='$library_names' + +# The name of the static archive. +old_library='$old_library' + +# Linker flags that can not go in dependency_libs. +inherited_linker_flags='$new_inherited_linker_flags' + +# Libraries that this one depends upon. +dependency_libs='$dependency_libs' + +# Names of additional weak libraries provided by this library +weak_library_names='$weak_libs' + +# Version information for $libname. +current=$current +age=$age +revision=$revision + +# Is this an already installed library? +installed=$installed + +# Should we warn about portability when linking against -modules? +shouldnotlink=$module + +# Files to dlopen/dlpreopen +dlopen='$dlfiles' +dlpreopen='$dlprefiles' + +# Directory that this library needs to be installed in: +libdir='$install_libdir'" + if test "$installed" = no && test "$need_relink" = yes; then + $ECHO >> $output "\ +relink_command=\"$relink_command\"" + fi + done + } + + # Do a symbolic link so that the libtool archive can be found in + # LD_LIBRARY_PATH before the program is installed. + func_show_eval '( cd "$output_objdir" && $RM "$outputname" && $LN_S "../$outputname" "$outputname" )' 'exit $?' + ;; + esac + exit $EXIT_SUCCESS +} + +{ test "$opt_mode" = link || test "$opt_mode" = relink; } && + func_mode_link ${1+"$@"} + + +# func_mode_uninstall arg... +func_mode_uninstall () +{ + $opt_debug + RM="$nonopt" + files= + rmforce= + exit_status=0 + + # This variable tells wrapper scripts just to set variables rather + # than running their programs. + libtool_install_magic="$magic" + + for arg + do + case $arg in + -f) func_append RM " $arg"; rmforce=yes ;; + -*) func_append RM " $arg" ;; + *) func_append files " $arg" ;; + esac + done + + test -z "$RM" && \ + func_fatal_help "you must specify an RM program" + + rmdirs= + + for file in $files; do + func_dirname "$file" "" "." + dir="$func_dirname_result" + if test "X$dir" = X.; then + odir="$objdir" + else + odir="$dir/$objdir" + fi + func_basename "$file" + name="$func_basename_result" + test "$opt_mode" = uninstall && odir="$dir" + + # Remember odir for removal later, being careful to avoid duplicates + if test "$opt_mode" = clean; then + case " $rmdirs " in + *" $odir "*) ;; + *) func_append rmdirs " $odir" ;; + esac + fi + + # Don't error if the file doesn't exist and rm -f was used. + if { test -L "$file"; } >/dev/null 2>&1 || + { test -h "$file"; } >/dev/null 2>&1 || + test -f "$file"; then + : + elif test -d "$file"; then + exit_status=1 + continue + elif test "$rmforce" = yes; then + continue + fi + + rmfiles="$file" + + case $name in + *.la) + # Possibly a libtool archive, so verify it. + if func_lalib_p "$file"; then + func_source $dir/$name + + # Delete the libtool libraries and symlinks. + for n in $library_names; do + func_append rmfiles " $odir/$n" + done + test -n "$old_library" && func_append rmfiles " $odir/$old_library" + + case "$opt_mode" in + clean) + case " $library_names " in + *" $dlname "*) ;; + *) test -n "$dlname" && func_append rmfiles " $odir/$dlname" ;; + esac + test -n "$libdir" && func_append rmfiles " $odir/$name $odir/${name}i" + ;; + uninstall) + if test -n "$library_names"; then + # Do each command in the postuninstall commands. + func_execute_cmds "$postuninstall_cmds" 'test "$rmforce" = yes || exit_status=1' + fi + + if test -n "$old_library"; then + # Do each command in the old_postuninstall commands. + func_execute_cmds "$old_postuninstall_cmds" 'test "$rmforce" = yes || exit_status=1' + fi + # FIXME: should reinstall the best remaining shared library. + ;; + esac + fi + ;; + + *.lo) + # Possibly a libtool object, so verify it. + if func_lalib_p "$file"; then + + # Read the .lo file + func_source $dir/$name + + # Add PIC object to the list of files to remove. + if test -n "$pic_object" && + test "$pic_object" != none; then + func_append rmfiles " $dir/$pic_object" + fi + + # Add non-PIC object to the list of files to remove. + if test -n "$non_pic_object" && + test "$non_pic_object" != none; then + func_append rmfiles " $dir/$non_pic_object" + fi + fi + ;; + + *) + if test "$opt_mode" = clean ; then + noexename=$name + case $file in + *.exe) + func_stripname '' '.exe' "$file" + file=$func_stripname_result + func_stripname '' '.exe' "$name" + noexename=$func_stripname_result + # $file with .exe has already been added to rmfiles, + # add $file without .exe + func_append rmfiles " $file" + ;; + esac + # Do a test to see if this is a libtool program. + if func_ltwrapper_p "$file"; then + if func_ltwrapper_executable_p "$file"; then + func_ltwrapper_scriptname "$file" + relink_command= + func_source $func_ltwrapper_scriptname_result + func_append rmfiles " $func_ltwrapper_scriptname_result" + else + relink_command= + func_source $dir/$noexename + fi + + # note $name still contains .exe if it was in $file originally + # as does the version of $file that was added into $rmfiles + func_append rmfiles " $odir/$name $odir/${name}S.${objext}" + if test "$fast_install" = yes && test -n "$relink_command"; then + func_append rmfiles " $odir/lt-$name" + fi + if test "X$noexename" != "X$name" ; then + func_append rmfiles " $odir/lt-${noexename}.c" + fi + fi + fi + ;; + esac + func_show_eval "$RM $rmfiles" 'exit_status=1' + done + + # Try to remove the ${objdir}s in the directories where we deleted files + for dir in $rmdirs; do + if test -d "$dir"; then + func_show_eval "rmdir $dir >/dev/null 2>&1" + fi + done + + exit $exit_status +} + +{ test "$opt_mode" = uninstall || test "$opt_mode" = clean; } && + func_mode_uninstall ${1+"$@"} + +test -z "$opt_mode" && { + help="$generic_help" + func_fatal_help "you must specify a MODE" +} + +test -z "$exec_cmd" && \ + func_fatal_help "invalid operation mode \`$opt_mode'" + +if test -n "$exec_cmd"; then + eval exec "$exec_cmd" + exit $EXIT_FAILURE +fi + +exit $exit_status + + +# The TAGs below are defined such that we never get into a situation +# in which we disable both kinds of libraries. Given conflicting +# choices, we go for a static library, that is the most portable, +# since we can't tell whether shared libraries were disabled because +# the user asked for that or because the platform doesn't support +# them. This is particularly important on AIX, because we don't +# support having both static and shared libraries enabled at the same +# time on that platform, so we default to a shared-only configuration. +# If a disable-shared tag is given, we'll fallback to a static-only +# configuration. But we'll never go from static-only to shared-only. + +# ### BEGIN LIBTOOL TAG CONFIG: disable-shared +build_libtool_libs=no +build_old_libs=yes +# ### END LIBTOOL TAG CONFIG: disable-shared + +# ### BEGIN LIBTOOL TAG CONFIG: disable-static +build_old_libs=`case $build_libtool_libs in yes) echo no;; *) echo yes;; esac` +# ### END LIBTOOL TAG CONFIG: disable-static + +# Local Variables: +# mode:shell-script +# sh-indentation:2 +# End: +# vi:sw=2 + diff -r 000000000000 -r a1985f14b030 dist/pubdef.in --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dist/pubdef.in Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,585 @@ +# $Id: pubdef.in,v 4d4a04145f28 2010/07/28 15:20:45 ben $ +# +# Copyright (c) 2001, 2012 Oracle and/or its affiliates. All rights reserved. +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. Oracle designates this +# particular file as subject to the "Classpath" exception as provided +# by Oracle in the LICENSE file that accompanied this code. +# +# This code 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 General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. +# +# Name +# D == documentation +# I == include file +# J == Java constant +# N == wrapped by the Java native layer +# C == C# constant +DB_AFTER D I J C +DB_AGGRESSIVE D I J C +DB_ALIGN8 * I * * +DB_ALREADY_ABORTED * I * * +DB_AM_CHKSUM * I * * +DB_AM_COMPENSATE * I * * +DB_AM_COMPRESS * I * * +DB_AM_CREATED * I * * +DB_AM_CREATED_MSTR * I * * +DB_AM_DBM_ERROR * I * * +DB_AM_DELIMITER * I * * +DB_AM_DISCARD * I * * +DB_AM_DUP * I * * +DB_AM_DUPSORT * I * * +DB_AM_ENCRYPT * I * * +DB_AM_FIXEDLEN * I * * +DB_AM_INMEM * I * * +DB_AM_INORDER * I * * +DB_AM_IN_RENAME * I * * +DB_AM_NOT_DURABLE * I * * +DB_AM_OPEN_CALLED * I * * +DB_AM_PAD * I * * +DB_AM_PARTDB * I * * +DB_AM_PGDEF * I * * +DB_AM_RDONLY * I * * +DB_AM_READ_UNCOMMITTED * I * * +DB_AM_RECNUM * I * * +DB_AM_RECOVER * I * * +DB_AM_RENUMBER * I * * +DB_AM_REVSPLITOFF * I * * +DB_AM_SECONDARY * I * * +DB_AM_SNAPSHOT * I * * +DB_AM_SUBDB * I * * +DB_AM_SWAP * I * * +DB_AM_TXN * I * * +DB_AM_VERIFYING * I * * +DB_APPEND D I J C +DB_ARCH_ABS D I J C +DB_ARCH_DATA D I J C +DB_ARCH_LOG D I J C +DB_ARCH_REMOVE D I J C +DB_ASSOC_IMMUTABLE_KEY * I J C +DB_ASSOC_CREATE * I J C +DB_AUTO_COMMIT D I J C +DB_BACKUP_CLEAN D I J C +DB_BACKUP_FILES D I J C +DB_BACKUP_NO_LOGS D I J C +DB_BACKUP_READ_COUNT D I J C +DB_BACKUP_READ_SLEEP D I J C +DB_BACKUP_SINGLE_DIR D I J C +DB_BACKUP_SIZE D I J C +DB_BACKUP_UPDATE D I J C +DB_BACKUP_WRITE_DIRECT D I J C +DB_BEFORE D I J C +DB_BOOTSTRAP_HELPER D I J C +DB_BTREE D I J C +DB_BTREEMAGIC * I * * +DB_BTREEOLDVER * I * * +DB_BTREEVERSION * I * * +DB_BUFFER_SMALL D I J C +DB_CDB_ALLDB D I J C +DB_CHKSUM D I J C +DB_CKP_INTERNAL * I * * +DB_CONFIG D * * * +DB_CONSUME D I J C +DB_CONSUME_WAIT D I J C +DB_CREATE D I J C +DB_CURRENT D I J C +DB_CURSOR_BULK D I J C +DB_CURSOR_TRANSIENT * I * * +DB_CXX_NO_EXCEPTIONS D I * * +DB_DATABASE_LOCK * I * * +DB_DATABASE_LOCKING * I * * +DB_DBM_HSEARCH * I * * +DB_DBT_APPMALLOC D I N C +DB_DBT_BULK D I J C +DB_DBT_DUPOK * I * * +DB_DBT_ISSET * I * * +DB_DBT_MALLOC D I J C +DB_DBT_MULTIPLE D I N C +DB_DBT_PARTIAL D I J C +DB_DBT_READONLY D I J C +DB_DBT_REALLOC D I N C +DB_DBT_STREAMING D I * * +DB_DBT_USERCOPY * I N C +DB_DBT_USERMEM D I J C +DB_DEGREE_2 * I * * +DB_DELETED * I * * +DB_DIRECT D I * * +DB_DIRECT_DB D I J C +DB_DIRTY_READ * I * * +DB_DONOTINDEX D I N C +DB_DSYNC_DB D I J C +DB_DUP D I J C +DB_DUPSORT D I J C +DB_DURABLE_UNKNOWN * I * * +DB_EID_BROADCAST D I J C +DB_EID_INVALID D I J C +DB_EID_MASTER D I J C +DB_ENCRYPT D I J C +DB_ENCRYPT_AES D I J C +DB_ENV_AUTO_COMMIT * I * * +DB_ENV_CDB_ALLDB * I * * +DB_ENV_DATABASE_LOCKING * I * * +DB_ENV_DIRECT_DB * I * * +DB_ENV_DSYNC_DB * I * * +DB_ENV_FAILCHK * I * * +DB_ENV_MULTIVERSION * I * * +DB_ENV_NOLOCKING * I * * +DB_ENV_NOMMAP * I * * +DB_ENV_NOPANIC * I * * +DB_ENV_OVERWRITE * I * * +DB_ENV_REGION_INIT * I * * +DB_ENV_TIME_NOTGRANTED * I * * +DB_ENV_TXN_NOSYNC * I * * +DB_ENV_TXN_NOWAIT * I * * +DB_ENV_TXN_SNAPSHOT * I * * +DB_ENV_TXN_WRITE_NOSYNC * I * * +DB_ENV_YIELDCPU * I * * +DB_EVENT_NOT_HANDLED * I * * +DB_EVENT_NO_SUCH_EVENT * I * * +DB_EVENT_PANIC D I N C +DB_EVENT_REG_ALIVE D I * * +DB_EVENT_REG_PANIC D I * * +DB_EVENT_REP_CLIENT D I N C +DB_EVENT_REP_CONNECT_BROKEN D I N C +DB_EVENT_REP_CONNECT_ESTD D I N C +DB_EVENT_REP_CONNECT_TRY_FAILED D I N C +DB_EVENT_REP_DUPMASTER D I N C +DB_EVENT_REP_ELECTED D I N C +DB_EVENT_REP_ELECTION_FAILED D I N C +DB_EVENT_REP_INIT_DONE D I N C +DB_EVENT_REP_JOIN_FAILURE D I N C +DB_EVENT_REP_LOCAL_SITE_REMOVED D I N C +DB_EVENT_REP_MASTER D I N C +DB_EVENT_REP_MASTER_FAILURE D I N C +DB_EVENT_REP_NEWMASTER D I N C +DB_EVENT_REP_PERM_FAILED D I N C +DB_EVENT_REP_SITE_ADDED D I N C +DB_EVENT_REP_SITE_REMOVED D I N C +DB_EVENT_REP_STARTUPDONE D I N C +DB_EVENT_REP_WOULD_ROLLBACK * I * * +DB_EVENT_WRITE_FAILED D I N C +DB_EXCL D I J C +DB_EXTENT * I * * +DB_FAILCHK D I * * +DB_FAILCHK_ISALIVE * I * * +DB_FAST_STAT D I J C +DB_FCNTL_LOCKING * I * * +DB_FILE_ID_LEN * I * * +DB_FIRST D I J C +DB_FLUSH D I J C +DB_FORCE D I J C +DB_FORCESYNC D I J C +DB_FOREIGN_ABORT * I J C +DB_FOREIGN_CASCADE * I J C +DB_FOREIGN_CONFLICT * I * C +DB_FOREIGN_NULLIFY * I J C +DB_FREELIST_ONLY D I J C +DB_FREE_SPACE D I J C +DB_GET_BOTH D I J C +DB_GET_BOTHC * I * * +DB_GET_BOTH_LTE D I * * +DB_GET_BOTH_RANGE D I J C +DB_GET_RECNO D I J C +DB_GID_SIZE * I N C +DB_GROUP_CREATOR D I J C +DB_HANDLE_LOCK * I * * +DB_HASH D I J C +DB_HASHMAGIC * I * * +DB_HASHOLDVER * I * * +DB_HASHVERSION * I * * +DB_HEAP D I J C +DB_HEAPMAGIC * I * * +DB_HEAPOLDVER * I * * +DB_HEAPVERSION * I * * +DB_HEAP_FULL D I J C +DB_HEAP_RID_SZ D I * * +DB_HOME D * * * +DB_HOTBACKUP_IN_PROGRESS D I J C +DB_IGNORE_LEASE D I J C +DB_IMMUTABLE_KEY D I J C +DB_INIT_CDB D I J C +DB_INIT_LOCK D I J C +DB_INIT_LOG D I J C +DB_INIT_MPOOL D I J C +DB_INIT_MUTEX * I * * +DB_INIT_REP D I J C +DB_INIT_TXN D I J C +DB_INORDER D I J C +DB_INTERNAL_PERSISTENT_DB * I * * +DB_INTERNAL_TEMPORARY_DB * I * * +DB_JOINENV * I J C +DB_JOIN_ITEM D I J C +DB_JOIN_NOSORT D I J C +DB_KEYEMPTY D I J C +DB_KEYEXIST D I J C +DB_KEYFIRST D I J C +DB_KEYLAST D I J C +DB_LAST D I J C +DB_LEGACY D I J C +DB_LOCAL_SITE D I J C +DB_LOCKDOWN D I J C +DB_LOCKVERSION * I * * +DB_LOCK_CHECK * I * * +DB_LOCK_DEADLOCK D I N C +DB_LOCK_DEFAULT D I J C +DB_LOCK_DUMP * I * * +DB_LOCK_EXPIRE D I J C +DB_LOCK_GET D I J C +DB_LOCK_GET_TIMEOUT D I J C +DB_LOCK_IGNORE_REC * I * * +DB_LOCK_INHERIT * I * * +DB_LOCK_IREAD D I J C +DB_LOCK_IWR D I J C +DB_LOCK_IWRITE D I J C +DB_LOCK_MAXLOCKS D I J C +DB_LOCK_MAXWRITE D I J C +DB_LOCK_MINLOCKS D I J C +DB_LOCK_MINWRITE D I J C +DB_LOCK_NG * I * * +DB_LOCK_NORUN * I * * +DB_LOCK_NOTGRANTED D I J C +DB_LOCK_NOWAIT D I J C +DB_LOCK_OLDEST D I J C +DB_LOCK_PUT D I J C +DB_LOCK_PUT_ALL D I J C +DB_LOCK_PUT_OBJ D I J C +DB_LOCK_PUT_READ * I * * +DB_LOCK_RANDOM D I J C +DB_LOCK_READ D I J C +DB_LOCK_READ_UNCOMMITTED * I * * +DB_LOCK_RECORD * I * * +DB_LOCK_SET_TIMEOUT * I * * +DB_LOCK_SWITCH * I * * +DB_LOCK_TIMEOUT D I J C +DB_LOCK_TRADE * I * * +DB_LOCK_UPGRADE * I * * +DB_LOCK_UPGRADE_WRITE * I * * +DB_LOCK_WAIT * I * * +DB_LOCK_WRITE D I J C +DB_LOCK_WWRITE * I * * +DB_LOCK_YOUNGEST D I J C +DB_LOGCHKSUM D I * * +DB_LOGFILEID_INVALID * I * * +DB_LOGMAGIC * I * * +DB_LOGOLDVER * I * * +DB_LOGVERSION * I * * +DB_LOGVERSION_LATCHING D I * * +DB_LOG_AUTO_REMOVE D I J C +DB_LOG_BUFFER_FULL D I * C +DB_LOG_CHKPNT * I * * +DB_LOG_COMMIT * I * * +DB_LOG_DIRECT D I J C +DB_LOG_DISK * I * * +DB_LOG_DSYNC D I J C +DB_LOG_IN_MEMORY D I J C +DB_LOG_LOCKED * I * * +DB_LOG_NOCOPY * I * * +DB_LOG_NO_DATA * I * * +DB_LOG_NOT_DURABLE * I * * +DB_LOG_SILENT_ERR * I * * +DB_LOG_WRNOSYNC * I * * +DB_LOG_VERIFY_BAD D I * * +DB_LOG_VERIFY_CAF D I * * +DB_LOG_VERIFY_ERR D I * * +DB_LOG_VERIFY_PARTIAL * I * * +DB_LOG_VERIFY_DBFILE * I * * +DB_LOG_VERIFY_FORWARD * I * * +DB_LOG_VERIFY_INTERR D I * * +DB_LOG_VERIFY_WARNING D I * * +DB_LOG_VERIFY_VERBOSE D I * * +DB_LOG_ZERO D I J C +DB_LSTAT_ABORTED * I * * +DB_LSTAT_EXPIRED * I * * +DB_LSTAT_FREE * I * * +DB_LSTAT_HELD * I * * +DB_LSTAT_PENDING * I * * +DB_LSTAT_WAITING * I * * +DB_MAX_PAGES * I * * +DB_MAX_RECORDS * I * * +DB_MEM_LOCK D I J C +DB_MEM_LOCKOBJECT D I J C +DB_MEM_LOCKER D I J C +DB_MEM_LOGID D I J C +DB_MEM_TRANSACTION D I J C +DB_MEM_THREAD D I J C +DB_MPOOL_CREATE D I * * +DB_MPOOL_DIRTY D I * * +DB_MPOOL_TRY D I * * +DB_MPOOL_DISCARD * I * * +DB_MPOOL_EDIT D I * * +DB_MPOOL_FREE * I * * +DB_MPOOL_LAST D I * * +DB_MPOOL_NEW D I * * +DB_MPOOL_NOFILE D I J C +DB_MPOOL_NOLOCK * I * * +DB_MPOOL_UNLINK D I J C +DB_MULTIPLE D I J C +DB_MULTIPLE_INIT D I * * +DB_MULTIPLE_KEY D I J C +DB_MULTIPLE_KEY_NEXT D I * * +DB_MULTIPLE_KEY_RESERVE_NEXT D I * * +DB_MULTIPLE_KEY_WRITE_NEXT D I * * +DB_MULTIPLE_NEXT D I * * +DB_MULTIPLE_RECNO_NEXT D I * * +DB_MULTIPLE_RECNO_RESERVE_NEXT D I * * +DB_MULTIPLE_RECNO_WRITE_INIT D I * * +DB_MULTIPLE_RECNO_WRITE_NEXT D I * * +DB_MULTIPLE_RESERVE_NEXT D I * * +DB_MULTIPLE_WRITE_INIT D I * * +DB_MULTIPLE_WRITE_NEXT D I * * +DB_MULTIVERSION D I J C +DB_MUTEX_ALLOCATED * I * * +DB_MUTEX_LOCKED * I * * +DB_MUTEX_LOGICAL_LOCK * I * * +DB_MUTEX_PROCESS_ONLY D I * C +DB_MUTEX_SELF_BLOCK D I * C +DB_MUTEX_SHARED D I * * +DB_NEEDSPLIT * I * * +DB_NEXT D I J C +DB_NEXT_DUP D I J C +DB_NEXT_NODUP D I J C +DB_NODUPDATA D I J C +DB_NOERROR * I * * +DB_NOFLUSH * I * * +DB_NOLOCKING D I J C +DB_NOMMAP D I J C +DB_NOORDERCHK D I J C +DB_NOOVERWRITE D I J C +DB_NOPANIC D I J C +DB_NOSERVER D I * C +DB_NOSYNC D I J C +DB_NOTFOUND D I J C +DB_NO_AUTO_COMMIT * I * * +DB_NO_CHECKPOINT * I * * +DB_ODDFILESIZE D I * * +DB_OK_BTREE * I * * +DB_OK_HASH * I * * +DB_OK_HEAP * I * * +DB_OK_QUEUE * I * * +DB_OK_RECNO * I * * +DB_OLD_VERSION D I * C +DB_OPFLAGS_MASK * I * * +DB_ORDERCHKONLY D I J C +DB_OVERWRITE D I J C +DB_OVERWRITE_DUP D I * * +DB_PAGE_LOCK * I * * +DB_PAGE_NOTFOUND D I * C +DB_PANIC_ENVIRONMENT D I J C +DB_POSITION D I J C +DB_PREV D I J C +DB_PREV_DUP D I J C +DB_PREV_NODUP D I J C +DB_PRINTABLE D I J C +DB_PRIORITY_DEFAULT D I J C +DB_PRIORITY_HIGH D I J C +DB_PRIORITY_LOW D I J C +DB_PRIORITY_UNCHANGED D I * * +DB_PRIORITY_VERY_HIGH D I J C +DB_PRIORITY_VERY_LOW D I J C +DB_PRIVATE D I J C +DB_PR_PAGE * I * * +DB_PR_RECOVERYTEST * I * * +DB_QAMMAGIC * I * * +DB_QAMOLDVER * I * * +DB_QAMVERSION * I * * +DB_QUEUE D I J C +DB_RDONLY D I J C +DB_RDWRMASTER * I * * +DB_READ_COMMITTED D I J C +DB_READ_UNCOMMITTED D I J C +DB_RECNO D I J C +DB_RECNUM D I J C +DB_RECORD_LOCK * I * * +DB_RECOVER D I J C +DB_RECOVER_FATAL D I J C +DB_REDO * I * * +DB_REGION_INIT D I J C +DB_REGION_MAGIC * I * * +DB_REGISTER D I J C +DB_RENAMEMAGIC * I * * +DB_RENUMBER D I J C +DB_REP_CONF_AUTOROLLBACK * I * * +DB_REP_WOULDROLLBACK * I * * +DB_REPMGR_ACKS_ALL D I J C +DB_REPMGR_ACKS_ALL_AVAILABLE D I J C +DB_REPMGR_ACKS_ALL_PEERS D I J C +DB_REPMGR_ACKS_NONE D I J C +DB_REPMGR_ACKS_ONE D I J C +DB_REPMGR_ACKS_ONE_PEER D I J C +DB_REPMGR_ACKS_QUORUM D I J C +DB_REPMGR_CONF_2SITE_STRICT D I J C +DB_REPMGR_CONF_ELECTIONS D I J C +DB_REPMGR_CONNECTED D I J C +DB_REPMGR_DISCONNECTED D I J C +DB_REPMGR_NEED_RESPONSE D I J C +DB_REPMGR_ISPEER D I J * +DB_REPMGR_PEER D I J C +DB_REP_ACK_TIMEOUT D I J C +DB_REP_ANYWHERE D I J C +DB_REP_BULKOVF * I * * +DB_REP_CHECKPOINT_DELAY D I J C +DB_REP_CLIENT D I J C +DB_REP_CONF_AUTOINIT D I J C +DB_REP_CONF_BULK D I J C +DB_REP_CONF_DELAYCLIENT D I J C +DB_REP_CONF_INMEM D I J C +DB_REP_CONF_LEASE D I J C +DB_REP_CONF_NOWAIT D I J C +DB_REP_CONNECTION_RETRY D I J C +DB_REP_DEFAULT_PRIORITY * I J C +DB_REP_DUPMASTER D I N C +DB_REP_ELECTION D I J C +DB_REP_ELECTION_RETRY D I J C +DB_REP_ELECTION_TIMEOUT D I J C +DB_REP_FULL_ELECTION_TIMEOUT D I J C +DB_REP_HANDLE_DEAD D I N C +DB_REP_HEARTBEAT_MONITOR D I J C +DB_REP_HEARTBEAT_SEND D I J C +DB_REP_HOLDELECTION D I N C +DB_REP_IGNORE D I J C +DB_REP_ISPERM D I J C +DB_REP_JOIN_FAILURE D I N C +DB_REP_LEASE_EXPIRED D I N C +DB_REP_LEASE_TIMEOUT D I J C +DB_REP_LOCKOUT D I N C +DB_REP_LOGREADY * I * * +DB_REP_MASTER D I J C +DB_REP_NEWMASTER * I * * +DB_REP_NEWSITE D I J C +DB_REP_NOBUFFER D I J C +DB_REP_NOTPERM D I J C +DB_REP_PAGEDONE * I * * +DB_REP_PERMANENT D I J C +DB_REP_REREQUEST D I J C +DB_REP_UNAVAIL D I N C +DB_REVSPLITOFF D I J C +DB_RMW D I J C +DB_RUNRECOVERY D I N C +DB_SALVAGE D I J C +DB_SA_SKIPFIRSTKEY * I * * +DB_SA_UNKNOWNKEY * I * * +DB_SECONDARY_BAD D I * C +DB_SEQUENCE_OLDVER * I * * +DB_SEQUENCE_VERSION * I * * +DB_SEQ_DEC D I J C +DB_SEQ_INC D I J C +DB_SEQ_RANGE_SET * I * * +DB_SEQ_WRAP D I J C +DB_SEQ_WRAPPED * I * * +DB_SET D I J C +DB_SET_LTE D I * * +DB_SET_LOCK_TIMEOUT D I J C +DB_SET_RANGE D I J C +DB_SET_REG_TIMEOUT D I * * +DB_SET_RECNO D I J C +DB_SET_TXN_LSNP * I * * +DB_SET_TXN_NOW * I * * +DB_SET_TXN_TIMEOUT D I J C +DB_SHALLOW_DUP * I * * +DB_SNAPSHOT D I J C +DB_STAT_ALL D I * C +DB_STAT_ALLOC * I * * +DB_STAT_CLEAR D I J C +DB_STAT_LOCK_CONF D I * C +DB_STAT_LOCK_LOCKERS D I * C +DB_STAT_LOCK_OBJECTS D I * C +DB_STAT_LOCK_PARAMS D I * C +DB_STAT_MEMP_HASH D I * C +DB_STAT_MEMP_NOERROR * I * * +DB_STAT_SUBSYSTEM D I * C +DB_STAT_SUMMARY * I * * +DB_ST_DUPOK * I * * +DB_ST_DUPSET * I * * +DB_ST_DUPSORT * I * * +DB_ST_IS_RECNO * I * * +DB_ST_OVFL_LEAF * I * * +DB_ST_RECNUM * I * * +DB_ST_RELEN * I * * +DB_ST_TOPLEVEL * I * * +DB_SURPRISE_KID * I * * +DB_SWAPBYTES * I * * +DB_SYSTEM_MEM D I J C +DB_THREAD D I J C +DB_THREADID_STRLEN D I * * +DB_TIMEOUT D I J C +DB_TIME_NOTGRANTED D I J C +DB_TRUNCATE D I J C +DB_TXNVERSION * I * * +DB_TXN_ABORT D I J C +DB_TXN_APPLY D I J C +DB_TXN_BACKWARD_ROLL D I J C +DB_TXN_BULK D I J C +DB_TXN_CKP * I * * +DB_TXN_FAMILY * I * * +DB_TXN_FORWARD_ROLL D I J C +DB_TXN_LOG_VERIFY D I * * +DB_TXN_NOSYNC D I J C +DB_TXN_NOT_DURABLE D I J C +DB_TXN_NOWAIT D I J C +DB_TXN_OPENFILES * I * * +DB_TXN_POPENFILES * I * * +DB_TXN_PRINT D I J C +DB_TXN_SNAPSHOT D I J C +DB_TXN_SYNC D I J C +DB_TXN_TOKEN_SIZE * I J C +DB_TXN_WAIT D I J C +DB_TXN_WRITE_NOSYNC D I J C +DB_UNDO * I * * +DB_UNKNOWN D I J C +DB_UNREF * I * * +DB_UPDATE_SECONDARY * I * * +DB_UPGRADE D I J C +DB_USE_ENVIRON D I J C +DB_USE_ENVIRON_ROOT D I J C +DB_VERB_BACKUP D I J C +DB_VERB_DEADLOCK D I J C +DB_VERB_FILEOPS D I J C +DB_VERB_FILEOPS_ALL D I J C +DB_VERB_RECOVERY D I J C +DB_VERB_REGISTER D I J C +DB_VERB_REPLICATION D I J C +DB_VERB_REPMGR_CONNFAIL D I J C +DB_VERB_REPMGR_MISC D I J C +DB_VERB_REP_ELECT D I J C +DB_VERB_REP_LEASE D I J C +DB_VERB_REP_MISC D I J C +DB_VERB_REP_MSGS D I J C +DB_VERB_REP_SYNC D I J C +DB_VERB_REP_SYSTEM D I J C +DB_VERB_REP_TEST D I J C +DB_VERB_WAITSFOR D I J C +DB_VERIFY D I J C +DB_VERIFY_BAD D I N C +DB_VERIFY_FATAL * I * * +DB_VERIFY_PARTITION D I * * +DB_VERSION_FAMILY * I N C +DB_VERSION_RELEASE * I N C +DB_VERSION_MAJOR * I J C +DB_VERSION_MINOR * I J C +DB_VERSION_MISMATCH D I N C +DB_VERSION_PATCH * I J C +DB_VERSION_STRING * I N C +DB_VERSION_FULL_STRING * I N C +DB_WRITECURSOR D I J C +DB_WRITELOCK * I * * +DB_WRITEOPEN * I * * +DB_XA_CREATE D I * * +DB_YIELDCPU D I J C +DB2_AM_EXCL * I * * +DB2_AM_INTEXCL * I * * +DB2_AM_NOWAIT * I * * diff -r 000000000000 -r a1985f14b030 dist/s_all --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dist/s_all Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,67 @@ +#!/bin/sh - +# +# Copyright (c) 2012 Oracle and/or its affiliates. All rights reserved. +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. Oracle designates this +# particular file as subject to the "Classpath" exception as provided +# by Oracle in the LICENSE file that accompanied this code. +# +# This code 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 General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. +# +# $Id$ + +LC_ALL=C +export LC_ALL + +sh s_readme # distribution README file. + +sh s_config # autoconf. +sh s_apiflags # API flags. +sh s_sig # Structure signature. +sh s_recover # logging/recovery files. +sh s_message # replication and repmgr message files. +sh s_message_id # generate message id. +sh s_sql # regenerate sqlite3.c +sh s_php # PHP config files + +############################################################# +# The following order is important, s_include must run after +# the other source files have been created. +############################################################# +sh s_include # standard include files. + +sh s_java # Java support. +sh s_csharp # Csharp support. +sh s_test # Test suite support. +#sh s_tags # Tags files. + +############################################################# +# We only build the Cscope file for releases, it's too big to +# commit into the CVS tree. +############################################################# +#sh s_cscope # Cscope files. + +############################################################# +# Create the build environments last, they use files created +# by previous steps. +############################################################# +sh s_vxworks # VxWorks support. +sh s_windows # Windows support. +sh s_windows_dsp # Windows support: build environment. +sh s_android # Android support: drop-in build environment. diff -r 000000000000 -r a1985f14b030 dist/s_apiflags --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dist/s_apiflags Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,77 @@ +#!/bin/sh - +# +# Copyright (c) 2012 Oracle and/or its affiliates. All rights reserved. +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. Oracle designates this +# particular file as subject to the "Classpath" exception as provided +# by Oracle in the LICENSE file that accompanied this code. +# +# This code 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 General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. +# +# $Id$ +# +# Build the automatically generated API flag #defines. + +msgc=`cat << EOMSG +/* DO NOT EDIT: automatically built by dist/s_include. + * + * Copyright (c) 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ +EOMSG` + +b=/tmp/api_flags_binary +t=/tmp/__db_a + +trap 'rm -f $b $t; exit 0' 0 +trap 'rm -f $b $t; exit 1' 1 2 3 13 15 + +cc api_flags.c -o $b || { + echo 's_apiflags: unable to compile api_flags.c' + exit 1 +} + +(echo "$msgc" + $b < api_flags) > $t + +f=../src/dbinc_auto/api_flags.in +cmp $f $t > /dev/null 2>&1 || + (echo "Building $f" && rm -f $f && cp $t $f) diff -r 000000000000 -r a1985f14b030 dist/s_config --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dist/s_config Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,62 @@ +#!/bin/sh - +# +# Copyright (c) 2012 Oracle and/or its affiliates. All rights reserved. +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. Oracle designates this +# particular file as subject to the "Classpath" exception as provided +# by Oracle in the LICENSE file that accompanied this code. +# +# This code 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 General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. +# +# $Id$ +# +# Build the autoconfiguration files. + +trap 'rm -f aclocal.m4 ; exit 0' 0 1 2 3 13 15 + +. ./RELEASE + +echo "autoconf: building aclocal.m4..." +cat aclocal/*.m4 aclocal_java/*.m4 > aclocal.m4 + +echo "autoconf: running autoheader to build config.hin..." +rm -f config.hin +autoheader +chmod 644 config.hin + +echo "autoconf: running autoconf to build configure" +rm -f configure +autoconf + +# Edit version information we couldn't pre-compute. +sed -e "s/__EDIT_DB_VERSION_FAMILY__/$DB_VERSION_FAMILY/g" \ + -e "s/__EDIT_DB_VERSION_RELEASE__/$DB_VERSION_RELEASE/g" \ + -e "s/__EDIT_DB_VERSION_MAJOR__/$DB_VERSION_MAJOR/g" \ + -e "s/__EDIT_DB_VERSION_MINOR__/$DB_VERSION_MINOR/g" \ + -e "s/__EDIT_DB_VERSION_PATCH__/$DB_VERSION_PATCH/g" \ + -e "s/__EDIT_DB_VERSION_STRING__/$DB_VERSION_STRING/g" \ + -e "s/__EDIT_DB_VERSION_FULL_STRING__/$DB_VERSION_FULL_STRING/g" \ + -e "s/__EDIT_DB_VERSION_UNIQUE_NAME__/$DB_VERSION_UNIQUE_NAME/g" \ + -e "s/__EDIT_DB_VERSION__/$DB_VERSION/g" configure > configure.version +mv configure.version configure + +rm -rf autom4te.cache +chmod 755 configure + +chmod 755 config.guess config.sub install-sh diff -r 000000000000 -r a1985f14b030 dist/s_docs --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dist/s_docs Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,144 @@ +#! /bin/sh +# +# Copyright (c) 2012 Oracle and/or its affiliates. All rights reserved. +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. Oracle designates this +# particular file as subject to the "Classpath" exception as provided +# by Oracle in the LICENSE file that accompanied this code. +# +# This code 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 General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. +# +# $Id$ +# +# Build the documentation from a docs_books repository. +# +# Optional input is a release tag number to be built. + +distdir=`pwd` +if [ `basename $distdir` != "dist" ]; then + echo "The s_docs script must be run from the dist dir." + exit 1 +fi + +tag=$1 +docs_dir=$2 + +rootdir=`(cd $distdir/../.. ; pwd)` + +# Create temporary space. +tmp_dir=$distdir/s_docs.tmp + +rm -rf $tmp_dir && mkdir $tmp_dir && mkdir $tmp_dir/logs + +if [ "$docs_dir" = "" ]; then + docs_dir=$rootdir/docs_books +fi + +# Verify that the docs_books repository is where we expect it. +if [ ! -d "$docs_dir" ]; then + echo "Script requires a doc repository at: $docs_dir" + exit 1 +fi + +# If a release tag is specified, ensure the docs_books is up to date. +if [ "$tag" != "" ]; then + cd $docs_dir + hg up -r $tag > /dev/null + if [ $? != 0 ]; then + echo "Failed to update docs_books repo to requested tag." >&2 + exit 1 + fi + cd $distdir +else + echo "No release tag specified, assuming docs_books repo already in required state." +fi + +# Set up env variables. +system=`uname | grep -i cygwin` +if [ "$system"x != x ]; then + DOCS_REPOSITORY=`cygpath -m $docs_dir`; export DOCS_REPOSITORY + DOCS_OUTPUT_DIR=`cygpath -m $tmp_dir`; export DOCS_OUTPUT_DIR + DOCS_TARGET_REPOSITORY=`cygpath -m $distdir/../docs`; export DOCS_TARGET_REPOSITORY +else + DOCS_REPOSITORY=$docs_dir; export DOCS_REPOSITORY + DOCS_OUTPUT_DIR=$tmp_dir; export DOCS_OUTPUT_DIR + DOCS_TARGET_REPOSITORY=$distdir/../docs; export DOCS_TARGET_REPOSITORY +fi + +if [ "$DOCS_PDF_BUILDER" = "" ]; then + fop_cmd=`which fop` + if [ "$fop_cmd" = "" ]; then + echo "Could not find a FOP install. Add it to your path, or +set DOCS_PDF_BUILDER environment directory. The FOP install package can be +found at s.o.c:/b/htdocs/documentation/sleepycat-fop095.zip" + exit 1; + fi + DOCS_PDF_BUILDER=$fop_cmd; export DOCS_PDF_BUILDER + echo "Found a fop command in the path. Using it's base dir as the FOP install." +fi +if [ "$DOCS_PARSER" = "" ]; then + xslt_cmd=`which xsltproc` + if [ "$xslt_cmd" = "" ]; then + echo "No xsltproc found. Install libxml2." + exit 1 + fi + DOCS_PARSER=$xslt_cmd; export DOCS_PARSER +fi + +################################################################### + +(`cd $distdir/../docs ; mkdir -p installation ; mkdir -p bdb-sql`) + +cd $docs_dir/tools/misc_doc_scripts + +./make_db_landing_page.py +./make_db_changelog.py + +cd $docs_dir/tools/buildBooks + +for book in DB_PROG_REF DB_REF_C DB_REF_CXX DB_REF_STL DB_REF_TCL \ + DB_GSG_C DB_GSG_CXX DB_GSG_JAVA DB_REP_C DB_REP_CXX \ + DB_REP_JAVA DB_COLLECTIONS DB_TXN_C DB_TXN_CXX DB_TXN_JAVA \ + DB_PORT DB_INSTALL DB_UPGRADE DB_SQL DB_SQL_ADO \ + core_inmem_app core_mssgtxt; do + + case $book in + DB_PROG_REF) + HTML_OPTS="-x" + PDF_OPTS= + ;; + core_*) + HTML_OPTS="-a" + PDF_OPTS="-a" + ;; + *) + HTML_OPTS= + PDF_OPTS= + ;; + esac + + DOCS_ERROR_FILE=$tmp_dir/${book}_err_htm.txt; export DOCS_ERROR_FILE + ./buildBooks.py $HTML_OPTS -t $book -h + DOCS_ERROR_FILE=$tmp_dir/${book}_err_pdf.txt; export DOCS_ERROR_FILE + ./buildBooks.py $PDF_OPTS -t $book -p +done + +# Cleanup after ourselves +rm -rf $tmp_dir + diff -r 000000000000 -r a1985f14b030 dist/s_include --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dist/s_include Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,228 @@ +#!/bin/sh - +# +# Copyright (c) 2012 Oracle and/or its affiliates. All rights reserved. +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. Oracle designates this +# particular file as subject to the "Classpath" exception as provided +# by Oracle in the LICENSE file that accompanied this code. +# +# This code 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 General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. +# +# $Id$ +# +# Build the automatically generated function prototype files. + +msgc=`cat << EOMSG +/* DO NOT EDIT: automatically built by dist/s_include. + * + * Copyright (c) 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ +EOMSG` + +. ./RELEASE + +AWK=${AWK:-awk} +head() +{ + defonly=0 + while : + do case "$1" in + space) + echo ""; shift;; + defonly) + defonly=1; shift;; + *) + name="$1"; break;; + esac + done + + echo "$msgc" + echo "#ifndef $name" + echo "#define $name" + echo "" + if [ $defonly -eq 0 ]; then + echo "#if defined(__cplusplus)" + echo "extern \"C\" {" + echo "#endif" + echo "" + fi +} + +tail() +{ + defonly=0 + while : + do case "$1" in + defonly) + defonly=1; shift;; + *) + name="$1"; break;; + esac + done + + echo "" + if [ $defonly -eq 0 ]; then + echo "#if defined(__cplusplus)" + echo "}" + echo "#endif" + fi + echo "#endif /* !$name */" +} + +# This script is run on a variety of systems. To avoid spurious changes, fix +# some variables that affect sort order of ls(1). +unset LANG +export LANG +LC_ALL="C" +export LC_ALL + +# We are building several files: +# 1 external #define file +# 1 external prototype file +# 1 internal #define file +# N internal prototype files +e_dfile=/tmp/__db_c.$$ +e_pfile=/tmp/__db_a.$$ +i_dfile=/tmp/__db_d.$$ +i_pfile=/tmp/__db_b.$$ +trap 'rm -f $e_dfile $e_pfile $i_dfile $i_pfile; exit 0' 0 1 2 3 13 15 + +head defonly space _DB_EXT_DEF_IN_ > $e_dfile +head space _DB_EXT_PROT_IN_ > $e_pfile +head defonly _DB_INT_DEF_IN_ > $i_dfile + +# Process the standard directories, creating per-directory prototype +# files and adding to the external prototype and #define files. +for i in db btree clib common crypto dbreg env fileops hash heap \ + hmac lock log mp mutex os qam rep repmgr sequence tcl txn xa; do + head "_${i}_ext_h_" > $i_pfile + + if [ $i = os ] ; then + f=`ls ../src/$i/*.c \ + ../src/os_qnx/*.c ../src/os_vxworks/*.c ../src/os_windows/*.c` + elif [ $i = crypto ] ; then + f=`ls ../src/$i/*.c ../src/$i/*/*.c` + elif [ $i = env ] ; then + f=`ls ../src/$i/*.c ../src/repmgr/repmgr_stub.c` + elif [ $i = tcl ] ; then + f=`ls ../lang/$i/*.c` + else + f=`ls ../src/$i/*.c` + fi + $AWK -f gen_inc.awk \ + -v db_version_unique_name=$DB_VERSION_UNIQUE_NAME \ + -v e_dfile=$e_dfile \ + -v e_pfile=$e_pfile \ + -v i_dfile=$i_dfile \ + -v i_pfile=$i_pfile $f + + tail "_${i}_ext_h_" >> $i_pfile + + f=../src/dbinc_auto/${i}_ext.h + cmp $i_pfile $f > /dev/null 2>&1 || + (echo "Building $f" && rm -f $f && cp $i_pfile $f) +done + +# Process directories which only add to the external prototype and #define +# files. +for i in dbm hsearch; do + f=`ls ../lang/$i/*.c` + $AWK -f gen_inc.awk \ + -v db_version_unique_name=$DB_VERSION_UNIQUE_NAME \ + -v e_dfile=$e_dfile \ + -v e_pfile=$e_pfile \ + -v i_dfile="" \ + -v i_pfile="" $f +done + +# There are a few global variables in DB -- add them to the external/internal +# #define files. +(echo "#define __db_global_values __db_global_values@DB_VERSION_UNIQUE_NAME@"; + echo "#define __repmgr_guesstimated_max __repmgr_guesstimated_max@DB_VERSION_UNIQUE_NAME@"; + echo "#define db_xa_switch db_xa_switch@DB_VERSION_UNIQUE_NAME@" + ) >> $i_dfile + +# Wrap up the external #defines/prototypes, and internal #defines. +tail defonly _DB_EXT_DEF_IN_ >> $e_dfile +f=../src/dbinc_auto/ext_def.in +cmp $e_dfile $f > /dev/null 2>&1 || + (echo "Building $f" && rm -f $f && cp $e_dfile $f) + +tail _DB_EXT_PROT_IN_ >> $e_pfile +f=../src/dbinc_auto/ext_prot.in +cmp $e_pfile $f > /dev/null 2>&1 || + (echo "Building $f" && rm -f $f && cp $e_pfile $f) + +tail defonly _DB_INT_DEF_IN_ >> $i_dfile +f=../src/dbinc_auto/int_def.in +cmp $i_dfile $f > /dev/null 2>&1 || + (echo "Building $f" && rm -f $f && cp $i_dfile $f) + +# DB185 compatibility support. +head space defonly _DB_EXT_185_DEF_IN_ > $e_dfile +head space _DB_EXT_185_PROT_IN_ > $e_pfile + +f=`ls ../lang/db185/*.c` +$AWK -f gen_inc.awk \ + -v db_version_unique_name=$DB_VERSION_UNIQUE_NAME \ + -v e_dfile=$e_dfile \ + -v e_pfile=$e_pfile \ + -v i_dfile="" \ + -v i_pfile="" $f + +tail defonly _DB_EXT_185_DEF_IN_ >> $e_dfile +f=../src/dbinc_auto/ext_185_def.in +cmp $e_dfile $f > /dev/null 2>&1 || + (echo "Building $f" && rm -f $f && cp $e_dfile $f) + +tail _DB_EXT_185_PROT_IN_ >> $e_pfile +f=../src/dbinc_auto/ext_185_prot.in +cmp $e_pfile $f > /dev/null 2>&1 || + (echo "Building $f" && rm -f $f && cp $e_pfile $f) + +# Make the DTrace provider description file from events.in +rm -f db_provider.d +(echo "/*"; \ + echo " * DO NOT EDIT: automatically built by dist/s_include."; \ + echo " * Oracle Berkeley DB DTrace Provider"; \ + echo " */"; \ +perl gen_provider.pl events.in) > db_provider.d diff -r 000000000000 -r a1985f14b030 dist/s_message --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dist/s_message Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,56 @@ +#!/bin/sh - +# +# Copyright (c) 2012 Oracle and/or its affiliates. All rights reserved. +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. Oracle designates this +# particular file as subject to the "Classpath" exception as provided +# by Oracle in the LICENSE file that accompanied this code. +# +# This code 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 General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. +# +# $Id$ +# +# Build the automatically generated rep & repmgr message files. + +header=/tmp/__db_a +source=/tmp/__db_b + +trap 'rm -f /tmp/__db_[ab]; exit 1' 1 2 3 13 15 +trap 'rm -f /tmp/__db_[ab]; exit 0' 0 + +DIR="rep repmgr" + +# Build DB's message marshaling/unmarshaling routines. +for i in $DIR; do + for f in ../src/$i/*.msg; do + subsystem=`basename $f .msg` + awk -f gen_msg.awk \ + -v header_file=$header \ + -v source_file=$source < $f + + f=../src/dbinc_auto/${subsystem}_automsg.h + cmp $header $f > /dev/null 2>&1 || + (echo "Building $f" && + rm -f $f && cp $header $f) + f=../src/$i/${subsystem}_automsg.c + cmp $source $f > /dev/null 2>&1 || + (echo "Building $f" && + rm -f $f && cp $source $f) + done +done diff -r 000000000000 -r a1985f14b030 dist/s_message_id --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dist/s_message_id Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,212 @@ +#!/bin/sh - +# +# Copyright (c) 2012 Oracle and/or its affiliates. All rights reserved. +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. Oracle designates this +# particular file as subject to the "Classpath" exception as provided +# by Oracle in the LICENSE file that accompanied this code. +# +# This code 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 General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. +# +# $Id$ +# +# Automatically generate message id. + +# Usage: A BDB#### would be replaced with an unused message id in: +# 1) DB_STR(BDB#### +# 2) DB_STR_A(BDB#### +# NOTE: Do not add whitespace between DB_STR( or DB_STR_A( and the message ID. + +# NOTE: Please update the MSG_DIRS if there is any new source dir. +MSG_DIRS="../src/ ../util/ ../lang/dbm/ ../dist/gen_msg.awk" + +# Environment Configuration +GREP_CMDS="grep ggrep" +for i in $GREP_CMDS; do + if [ "`which $i`" = "" ]; then + continue + fi + echo "s_message_id test" > s_message_id.tmp + $i "s_message_id test" s_message_id.tmp -o --include=*.tmp | \ + $i -v "s_message_id.txt" > s_message_id.tmp.out 2>&1 + if [ `$i "unrecognized option" s_message_id.tmp.out | wc -l` \ + -eq 0 ] && [ `$i "invalid option" s_message_id.tmp.out | \ + wc -l` -eq 0 ] && [ `$i "can't open" s_message_id.tmp.out | \ + wc -l` -eq 0 ]; then + GREP_CMD=$i + break + fi +done +rm -f s_message_id.tmp s_message_id.tmp.out +if [ "$GREP_CMD" = "" ]; then + echo "UNSUPPORTED COMMAND: (g)grep -o --include" + echo "Please try other platform" + exit +fi + +pref=MSG_INDX + +get_value() { + value=${1}${2} + eval "echo $`echo $value`" +} + +get_max() { + if [ ${1} -gt ${2} ] ; then + eval "echo ${1}" + else + eval "echo ${2}" + fi +} + +# Iterate source files and replace "BDB####" with the real message id. +for i in $MSG_DIRS; do + for f in `$GREP_CMD BDB#### -r $i -wl --include=*.c --include=*.h \ + --include=*.in --include=*.awk | \ + $GREP_CMD -v "../util/db_dump185.c" | \ + $GREP_CMD -v "../util/db_sql_codegen"`; do + IFS='/' + set $f + # There are 11 categories in the MSG_DIRS: + # 1) COMMON; 2) DB; 3) AM; 4) ENV; 5) LOCK; 6) LOG; + # 7) MPOOL; 8) REP; 9) SEQUENCE; 10) TXN; 11) UTIL. + # + # NOTE: Please add a new block (see below) and assign the values + # of cat_indx and cat_dirs if there is new group, or update the + # existing block if there is new source tree under the existing + # group. + if [ "$i" = "../util/" ] || [ "$i" = "../lang/dbm/" ]; then + cat_indx=10 + cat_dirs="../util/ ../lang/dbm/" + elif [ "$3" = "common" ] || [ "$3" = "crypto" ] || \ + [ "$3" = "fileops" ] || [ "$3" = "hmac" ] || \ + [ "$3" = "os" ] || [ "$3" = "os_qnx" ] || \ + [ "$3" = "os_vxworks" ] || [ "$3" = "os_windows" ]; then + cat_indx=0 + cat_dirs=$i"common "$i"crypto "$i"fileops " + cat_dirs=$cat_dirs$i"hmac "$i"os "$i"os_qnx " + cat_dirs=$cat_dirs$i"os_vxworks "$i"os_windows" + elif [ "$3" = "db" ] || [ "$3" = "dbinc" ] || \ + [ "$3" = "dbinc_auto" ]; then + cat_indx=1 + cat_dirs=$i"db "$i"dbinc "$i"dbinc_auto" + elif [ "$3" = "btree" ] || [ "$3" = "hash" ] || \ + [ "$3" = "heap" ] || [ "$3" = "qam" ]; then + cat_indx=2 + cat_dirs=$i"btree "$i"hash "$i"heap "$i"qam" + elif [ "$3" = "dbreg" ] || [ "$3" = "env" ] ; then + cat_indx=3 + cat_dirs=$i"dbreg "$i"env" + elif [ "$3" = "lock" ] || [ "$3" = "mutex" ]; then + cat_indx=4 + cat_dirs=$i"lock "$i"mutex" + elif [ "$3" = "log" ]; then + cat_indx=5 + cat_dirs=$i"log" + elif [ "$3" = "mp" ]; then + cat_indx=6 + cat_dirs=$i"mp" + elif [ "$3" = "rep" ] || [ "$3" = "repmgr" ] || \ + [ "$3" = "gen_msg.awk" ] ; then + cat_indx=7 + cat_dirs="../src/rep ../src/repmgr ../dist/gen_msg.awk" + elif [ "$3" = "sequence" ]; then + cat_indx=8 + cat_dirs=$i"sequence" + elif [ "$3" = "txn" ] || [ "$3" = "xa" ]; then + cat_indx=9 + cat_dirs=$i"txn "$i"xa" + else + echo "ERROR UNKNOWN PATH:" "$i""$3" + exit + fi + + unset IFS + + # Initialize MSG_INDX for each group if it is never initialized. + if [ "`get_value $pref $cat_indx`" = "" ]; then + # Get the start index, that is the next available number + # for the current group. If there is no existing message + # marked by DB_STR or DB_STR_A, the start index is the + # first available integer in its range. Unless, it is + # the next available integer in its range. + MSG_START_NUM=`expr $cat_indx \* 500 + 1` + DB_STR_NUM=`$GREP_CMD -E "DB_STR\(\"[0-9]{4}\"" -r \ + $cat_dirs | wc -l` + if [ $DB_STR_NUM -eq 0 ]; then + DB_STR_NUM=`expr 0 + $MSG_START_NUM` + else + DB_STR_NUM=`$GREP_CMD -E "DB_STR\(\"[0-9]{4}\"" -oh \ + -r $cat_dirs | sort | tail -n 1 | \ + sed -e "s/DB_STR(//g" | sed -e "s/\"//g"` + DB_STR_NUM=`expr 1 + $DB_STR_NUM` + fi + + DB_STR_A_NUM=`$GREP_CMD -E "DB_STR_A\(\"[0-9]{4}\"" -r \ + $cat_dirs | wc -l` + if [ $DB_STR_A_NUM -eq 0 ]; then + DB_STR_A_NUM=`expr 0 + $MSG_START_NUM` + else + DB_STR_A_NUM=`$GREP_CMD -E \ + "DB_STR_A\(\"[0-9]{4}\"" -oh -r $cat_dirs | \ + sort | tail -n 1 | \ + sed -e "s/DB_STR_A(//g" | sed -e "s/\"//g"` + DB_STR_A_NUM=`expr 1 + $DB_STR_A_NUM` + fi + + MSG_START_INDX=`get_max $DB_STR_NUM $DB_STR_A_NUM` + eval "$pref$cat_indx=$MSG_START_INDX" + fi + + cat $f | awk '{ + if(num"tmp.tmp" + }END{ + printf("%s", num)>"tmp.num"} + function fill(i) { + s="" + j=4-length(i) + while(j) { + s=0""s + j-- + } + return "\""s""i"\"" + }' num=`get_value $pref $cat_indx` \ + max=`expr \( $cat_indx + 1 \) \* 500` + cp tmp.tmp $f + eval "$pref$cat_indx=`sed 'q' tmp.num`" + if [ "$cat_indx" -lt 11 ]; then + if [ `get_value $pref $cat_indx` -ge \ + `expr \( $cat_indx + 1 \) \* 500` ]; then + echo "RANGE FULL" + fi + else + echo "ERROR CATEGORY NUMBER: " $cat_indx + fi + rm tmp.tmp tmp.num + done +done + +# Check if there is any remaining "BDB####". +# NOTE: If "BDB####" is not .c, .h, .in files, they won't be updated with the +# real message id. +if [ `$GREP_CMD "BDB####" -r $MSG_DIRS | wc -l` -gt 0 ]; then + echo "WARNING: There is remaining BDB####. Please check:" + $GREP_CMD "BDB####" -r $MSG_DIRS +fi diff -r 000000000000 -r a1985f14b030 dist/s_perm --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dist/s_perm Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,74 @@ +#!/bin/sh - +# +# Copyright (c) 2012 Oracle and/or its affiliates. All rights reserved. +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. Oracle designates this +# particular file as subject to the "Classpath" exception as provided +# by Oracle in the LICENSE file that accompanied this code. +# +# This code 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 General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. +# +# $Id$ +# +# This script is designed to be run while packaging up releases, not during +# other s_all processing. + +d=.. +echo 'Updating Berkeley DB source tree permissions for a release package' + +run() +{ + if [ -f "$d/$1" ]; then + chmod "$2" "$d/$1" + else + echo "$d/$1: no such file or directory" + exit 1 + fi +} + +# Ensure all files in the package have consistent permissions. +find $d -type d | xargs chmod 775 +find $d -type f | xargs chmod 644 + +# Assign execute permissions where necessary. +# ODBC and JDBC are only present in release packages. +if [ -d $d/lang/sql/odbc ]; then + chmod 755 $d/lang/sql/odbc/conf* +fi +if [ -d $d/lang/sql/jdbc ]; then + chmod 755 $d/lang/sql/jdbc/conf* +fi +chmod 755 $d/dist/s_* + +run dist/config.guess 755 +run dist/config.sub 755 +run dist/configure 755 +run dist/install-sh 755 +run dist/vx_buildcd 755 +run lang/perl/BerkeleyDB/dbinfo 755 +run lang/perl/BerkeleyDB/mkpod 755 +run lang/sql/sqlite/configure 755 + +for i in `cd $d && find build_vxworks \ + -name '*.wsp' -o -name '*.cdf' -o -name '*.wpj'`; do + chmod 775 $d/$i +done + +chmod 555 $d/util/dtrace/*.d +chmod 555 $d/util/systemtap/*.stp diff -r 000000000000 -r a1985f14b030 dist/s_readme --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dist/s_readme Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,50 @@ +#!/bin/sh - +# +# Copyright (c) 2012 Oracle and/or its affiliates. All rights reserved. +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. Oracle designates this +# particular file as subject to the "Classpath" exception as provided +# by Oracle in the LICENSE file that accompanied this code. +# +# This code 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 General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. +# +# $Id$ +# +# Build the README. + +echo 'Updating Berkeley DB README file...' + +d=.. + +t=/tmp/__t +trap 'rm -f $t; exit 0' 0 1 2 3 13 15 + +. ./RELEASE + +cat << END_OF_README>$t +$DB_VERSION_FULL_STRING + +This is Berkeley DB $DB_VERSION_FAMILY$DB_VERSION_LETTER Release $DB_VERSION_RELEASE from Oracle. To view release and +installation documentation, load the distribution file docs/index.html +into your web browser. +END_OF_README + +f=../README +cmp $t $f > /dev/null 2>&1 || + (echo "Building $f" && rm -f $f && cp $t $f) diff -r 000000000000 -r a1985f14b030 dist/s_sig --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dist/s_sig Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,168 @@ +#!/bin/sh - +# +# Copyright (c) 2012 Oracle and/or its affiliates. All rights reserved. +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. Oracle designates this +# particular file as subject to the "Classpath" exception as provided +# by Oracle in the LICENSE file that accompanied this code. +# +# This code 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 General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. +# +# $Id$ +# +# Build structure signature code. + +a=/tmp/__db_a.$$ +b=/tmp/__db_b.$$ +c=/tmp/__db_c.$$ +trap 'rm -f $a $b $c; exit 0' 0 1 2 3 13 15 + +cat ../src/dbinc/db.in ../src/dbinc/db_int.in ../src/dbinc/*.h | +sed -e '/.*struct.*mutex.*{[ ]*\/\* SHARED \*\/.*/i\ +#ifdef HAVE_MUTEX_SUPPORT' \ + -e '/.*struct.*mutex.*{[ ]*\/\* SHARED \*\/.*/a\ +#endif' \ + -e 's/.*[ ]*\(__[a-z_]*\)[ ]*{[ ]*\/\* SHARED \*\/.*/ __ADD(\1);/p' \ + -e d > $a + +cat ../src/dbinc/db.in ../src/dbinc/db_int.in ../src/dbinc/*.h | +sed -e '/__addrinfo/d' \ + -e '/__aes_cipher/d' \ + -e '/__cipher/d' \ + -e '/__channel/d' \ + -e '/__queued_output/d' \ + -e '/__repmgr_connection/d' \ + -e '/__repmgr_message/d' \ + -e '/__repmgr_response/d' \ + -e '/__repmgr_retry/d' \ + -e '/__repmgr_runnable/d' \ + -e '/__repmgr_site/d' \ + -e '/.*[ ]*\(__[a-z_]*\)[ ]*{[ ]*\/\* SHARED \*\/.*/d' \ + -e '/struct.*mutex.*{/i\ +#ifdef HAVE_MUTEX_SUPPORT' \ + -e '/struct.*mutex.*{/a\ +#endif' \ + -e 's/.*[ ]*struct[ ]*\(__[a-z_]*\)[ ]*{.*/ __ADD(\1);/p' \ + -e d > $c + +cnt1=`sed -e '$=' -e d $a` +cnt2=`sed -e '$=' -e d $c` + +cat << END_OF_TEXT > $b +/*- + * DO NOT EDIT: automatically built by dist/s_sig. + * + * Copyright (c) 1996, 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + * \$Id$ + */ + +#include "db_config.h" + +#include "db_int.h" + +#include "dbinc/db_page.h" +#include "dbinc/btree.h" +#include "dbinc/crypto.h" +#include "dbinc/db_join.h" +#include "dbinc/db_verify.h" +#include "dbinc/hash.h" +#include "dbinc/heap.h" +#include "dbinc/lock.h" +#include "dbinc/log_verify.h" +#include "dbinc/mp.h" +#include "dbinc/partition.h" +#include "dbinc/qam.h" +#include "dbinc/txn.h" + +END_OF_TEXT +cat << END_OF_TEXT >> $b +/* + * For a pure 32bit/64bit environment, we check all structures and calculate a + * signature. For compatible environment, we only check the structures in + * shared memory. + */ +END_OF_TEXT +echo "#ifdef HAVE_MIXED_SIZE_ADDRESSING" >> $b +echo "#define __STRUCTURE_COUNT $cnt1" >> $b +echo "#else" >> $b +echo "#define __STRUCTURE_COUNT ($cnt1 + $cnt2)" >> $b +echo "#endif" >> $b + +cat << END_OF_TEXT >> $b + +/* + * __env_struct_sig -- + * Compute signature of structures. + * + * PUBLIC: u_int32_t __env_struct_sig __P((void)); + */ +u_int32_t +__env_struct_sig() +{ + u_short t[__STRUCTURE_COUNT + 5]; + u_int i; + + i = 0; +#define __ADD(s) (t[i++] = sizeof(struct s)) + +END_OF_TEXT + +cat $a >> $b + +cat << END_OF_TEXT >> $b + +#ifndef HAVE_MIXED_SIZE_ADDRESSING +END_OF_TEXT + +cat $c >> $b + +echo "#endif" >> $b + +cat << END_OF_TEXT >> $b + + return (__ham_func5(NULL, t, i * sizeof(t[0]))); +} +END_OF_TEXT + +f=../src/env/env_sig.c +cmp $b $f > /dev/null 2>&1 || + (echo "Building $f" && rm -f $f && cp $b $f) diff -r 000000000000 -r a1985f14b030 dist/s_tags --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dist/s_tags Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,90 @@ +#!/bin/sh - +# +# Copyright (c) 2012 Oracle and/or its affiliates. All rights reserved. +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. Oracle designates this +# particular file as subject to the "Classpath" exception as provided +# by Oracle in the LICENSE file that accompanied this code. +# +# This code 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 General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. +# +# $Id$ +# +# Build tags files. + +cd tagdir +files=`echo ../../src/dbinc/*.h \ + ../../src/dbinc/*.in \ + ../../src/btree/*.[ch] \ + ../../src/clib/*.[ch] \ + ../../src/common/*.[ch] \ + ../../src/crypto/*.[ch] \ + ../../src/crypto/mersenne/*.[ch] \ + ../../src/crypto/rijndael/*.[ch] \ + ../../src/db/*.[ch] \ + ../../lang/db185/*.[ch] \ + ../../lang/dbm/*.[ch] \ + ../../src/dbreg/*.[ch] \ + ../../src/env/*.[ch] \ + ../../src/fileops/*.[ch] \ + ../../src/hash/*.[ch] \ + ../../src/heap/*.[ch] \ + ../../src/hmac/*.[ch] \ + ../../src/hsearch/*.[ch] \ + ../../src/lock/*.[ch] \ + ../../src/log/*.[ch] \ + ../../src/mp/*.[ch] \ + ../../src/mutex/*.[ch] \ + ../../src/os/*.[ch] \ + ../../src/os_qnx/*.[ch] \ + ../../src/qam/*.[ch] \ + ../../src/rep/*.[ch] \ + ../../src/repmgr/*.[ch] \ + ../../src/sequence/*.[ch] \ + ../../lang/tcl/*.[ch] \ + ../../src/txn/*.[ch] \ + ../../src/xa/*.[ch] \ + ../../lang/cxx/*.cpp \ + ../../lang/java/libdb_java/*.[ch] | sed 's/[^ ]*stub.c//g'` + +f=tags +echo "Building $f" +rm -f $f + +# Figure out what flags this ctags accepts. +flags="" +if ctags -d ../../src/db/db.c 2>/dev/null; then + flags="-d $flags" +fi +if ctags -t ../../src/db/db.c 2>/dev/null; then + flags="-t $flags" +fi +if ctags -w ../../src/db/db.c 2>/dev/null; then + flags="-w $flags" +fi + +ctags $flags $files 2>/dev/null + +for i in test/perf testrrepmgr testrserver; do + test -d ../../$i || continue + + f=../../$i/tags + echo "Building $f" + (cd ../../$i && ctags $flags *.[ch] 2>/dev/null) +done diff -r 000000000000 -r a1985f14b030 dist/s_test --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dist/s_test Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,136 @@ +#!/bin/sh - +# +# Copyright (c) 2012 Oracle and/or its affiliates. All rights reserved. +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. Oracle designates this +# particular file as subject to the "Classpath" exception as provided +# by Oracle in the LICENSE file that accompanied this code. +# +# This code 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 General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. +# +# $Id$ +# +# Build the Tcl test files. + +msg1="# Automatically built by dist/s_test; may require local editing." +msg2="# Automatically built by dist/s_test; may require local editing." + +t=/tmp/__t +trap 'rm -f $t; exit 0' 0 1 2 3 13 15 + +. ./RELEASE + +(echo "$msg1" && \ + echo "" && \ + echo "set tclsh_path @TCL_TCLSH@" && \ + echo "set tcllib .libs/libdb_tcl-@DB_VERSION_MAJOR@.@DB_VERSION_MINOR@@LIBTSO_MODSUFFIX@" && \ + echo "" && \ + echo "set src_root @srcdir@/.." && \ + echo "set test_path @srcdir@/../test/tcl" && \ + echo "set je_root @srcdir@/../../je" && \ + echo "set tcl_utils @srcdir@/../test/tcl_utils" && \ + echo "" && \ + echo "global testdir" && \ + echo "set testdir ./TESTDIR" && \ + echo "" && \ + echo "global dict" && \ + echo "global util_path" && \ + echo "" && \ + echo "global is_freebsd_test" && \ + echo "global is_hp_test" && \ + echo "global is_linux_test" && \ + echo "global is_osx_test" && \ + echo "global is_qnx_test" && \ + echo "global is_sunos_test" && \ + echo "global is_windows_test" && \ + echo "global is_windows9x_test" && \ + echo "" && \ + echo "global valid_methods" && \ + echo "global checking_valid_methods" && \ + echo "global test_recopts" && \ + echo "" && \ + echo "set KILL \"@KILL@\"") > $t + +f=../test/tcl/include.tcl +cmp $t $f > /dev/null 2>&1 || + (echo "Building $f" && rm -f $f && cp $t $f) + +(echo "$msg1" && \ + echo "" && \ + echo "set tclsh_path SET_YOUR_TCLSH_PATH" && \ + echo "set buildpath Win32/Debug" && \ + echo "set tcllib libdb_tcl${DB_VERSION_MAJOR}${DB_VERSION_MINOR}d.dll" && \ + echo "" && \ + echo "set src_root .." && \ + echo "set test_path ../test/tcl" && \ + echo "set je_root ../../je" && \ + echo "set tcl_utils ../test/tcl_utils" && \ + echo "" && \ + echo "global testdir" && \ + echo "set testdir ./TESTDIR" && \ + echo "" && \ + echo "global dict" && \ + echo "global util_path" && \ + echo "" && \ + echo "global is_freebsd_test" && \ + echo "global is_hp_test" && \ + echo "global is_linux_test" && \ + echo "global is_osx_test" && \ + echo "global is_qnx_test" && \ + echo "global is_sunos_test" && \ + echo "global is_windows_test" && \ + echo "global is_windows9x_test" && \ + echo "" && \ + echo "global valid_methods" && \ + echo "global checking_valid_methods" && \ + echo "global test_recopts" && \ + echo "" && \ + echo "set KILL dbkill.exe") > $t + +f=../build_windows/include.tcl +cmp $t $f > /dev/null 2>&1 || + (echo "Building $f" && rm -f $f && cp $t $f) + +# Build the test directory TESTS file. +(echo $msg2; +cat `egrep -l '^#[ ][ ]*TEST' ../test/tcl/*.tcl` | +sed -e '/^#[ ][ ]*TEST/!{' \ + -e 's/.*//' \ + -e '}' | +cat -s | +sed -e '/TEST/{' \ + -e 's/^#[ ][ ]*TEST[ ]*//' \ + -e 's/^ //' \ + -e 'H' \ + -e 'd' \ + -e '}' \ + -e 's/.*//' \ + -e x \ + -e 's/\n/__LINEBREAK__/g' | +LANG=C sort | +sed -e 's/__LINEBREAK__/\ +=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=\ +/' \ + -e 's/__LINEBREAK__/\ + /g' | +sed -e 's/^[ ][ ]*$//') > $t + +f=../test/tcl/TESTS +cmp $t $f > /dev/null 2>&1 || + (echo "Building $f" && rm -f $f && cp $t $f) diff -r 000000000000 -r a1985f14b030 dist/s_validate --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dist/s_validate Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,104 @@ +#!/bin/sh - +# +# Copyright (c) 2012 Oracle and/or its affiliates. All rights reserved. +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. Oracle designates this +# particular file as subject to the "Classpath" exception as provided +# by Oracle in the LICENSE file that accompanied this code. +# +# This code 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 General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. +# +# $Id$ +# +# This script runs the various validation tests in the validate directory. + +# Run everything, even those known to be invalid or useless. +all_tests=1 +# Run all tests, even those that require odd env setup or a long time. +full=0 +ignore_failures=0 +nocleanup=0 +verbose=1 +while [ $# -gt 0 ] +do + case "$1" in + -a*) # all + all_tests=1; full=1; shift;; + -c*) # continue + ignore_failures=1; shift;; + -f*) # full + full=1; shift;; + -nocleanup) + nocleanup=1; shift;; + -q*) + verbose=0; shift;; + *) + echo "Unrecognized option: $1, ignoring" + shift;; + esac +done + +# The set of full tests are those that have special env setup requirements +# or take a long time to run. They should be run at release time. +FULL_TESTS="s_chk_build_configs s_chk_vxworks" +EXCLUDE_TESTS="s_chk_logverify s_chk_srcfiles s_chk_java_samples" + +# Run all s_chk scripts, files with extensions are used by the script with +# the shorter name, they shouldn't be run directly. +for t in `(cd validate && ls s_chk_* | grep -v "\.")` +do + excluded=0 + for skip in $FULL_TESTS; do + if [ $full = 0 -a "$t" = "$skip" ]; then + echo "===!! Skipping $t ===" + echo "=== Add -full to the command line to enable ===" + excluded=1 + break; + fi + done + for skip in $EXCLUDE_TESTS; do + if [ $all_tests != 0 -a "$t" = "$skip" ]; then + echo "===!! Skipping $t ===" + echo "=== Add -all to the command line to enable ===" + excluded=1 + break; + fi + done + if [ $excluded != 0 ]; then + continue + fi + + echo "=== Running $t ===" + if [ "$verbose" = 1 ]; then + (cd validate && sh $t) + else + (cd validate && sh $t > /dev/null) + fi + ret_val=$? + if [ "$ret_val" != 0 ]; then + echo "=== Test $t reported a failure $ret_val." >&2 + if [ $ignore_failures = 0 ]; then + exit $ret_val + fi + else + echo "=== Test $t passed, $ret_val" + fi + rm -f validate/__? +done +echo "Finished running validate tests." diff -r 000000000000 -r a1985f14b030 dist/s_windows --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dist/s_windows Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,304 @@ +#!/bin/sh - +# +# Copyright (c) 2012 Oracle and/or its affiliates. All rights reserved. +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. Oracle designates this +# particular file as subject to the "Classpath" exception as provided +# by Oracle in the LICENSE file that accompanied this code. +# +# This code 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 General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. +# +# $Id$ +# +# Build Windows include files. + +msgc="/* DO NOT EDIT: automatically built by dist/s_windows. */" +msgw="; DO NOT EDIT: automatically built by dist/s_windows." + +. ./RELEASE + +s=/tmp/__db_a$$ +t=/tmp/__db_b$$ +rm -f $s $t + +trap 'rm -f $s $t ; exit 1' 1 2 3 13 15 + +# Build the Windows db.h +cat < $s +/@inttypes_h_decl@/d +/@stdint_h_decl@/d +s/@stddef_h_decl@/#include / +/@unistd_h_decl@/d +/@thread_h_decl@/d +s/@u_int8_decl@/typedef unsigned char u_int8_t;/ +s/@int16_decl@/typedef short int16_t;/ +s/@u_int16_decl@/typedef unsigned short u_int16_t;/ +s/@int32_decl@/typedef int int32_t;/ +s/@u_int32_decl@/typedef unsigned int u_int32_t;/ +s/@int64_decl@/typedef __int64 int64_t;/ +s/@u_int64_decl@/typedef unsigned __int64 u_int64_t;/ +s/@db_seq_decl@/typedef int64_t db_seq_t;/ +s/@db_threadid_t_decl@/typedef u_int32_t db_threadid_t;/ +s/@pid_t_decl@/typedef int32_t pid_t;/ +/@u_char_decl@/{ + i\\ +#ifndef _WINSOCKAPI_ + s/@u_char_decl@/typedef unsigned char u_char;/ +} +s/@u_short_decl@/typedef unsigned short u_short;/ +s/@u_int_decl@/typedef unsigned int u_int;/ +/@u_long_decl@/{ + s/@u_long_decl@/typedef unsigned long u_long;/ + a\\ +#endif +} +/@FILE_t_decl@/d +/@size_t_decl@/d +/@ssize_t_decl@/{ + i\\ +#ifdef _WIN64\\ +typedef int64_t ssize_t;\\ +#else\\ +typedef int32_t ssize_t;\\ +#endif + d + } + +/@time_t_decl@/d +/@uintmax_t_decl@/{ + i\\ +#if defined(_MSC_VER) && _MSC_VER < 1300\\ +typedef u_int32_t uintmax_t;\\ +#else\\ +typedef u_int64_t uintmax_t;\\ +#endif + d +} +/@uintptr_t_decl@/{ + i\\ +#ifdef _WIN64\\ +typedef u_int64_t uintptr_t;\\ +#else\\ +typedef u_int32_t uintptr_t;\\ +#endif + d +} +/@off_t_decl@/{ + i\\ +/*\\ +\ * Windows defines off_t to long (i.e., 32 bits). We need to pass 64-bit\\ +\ * file offsets, so we declare our own.\\ +\ */\\ +#define off_t __db_off_t\\ +typedef int64_t off_t; + d +} +/@platform_header@/{ + i\\ +/*\\ +\ * Turn off inappropriate compiler warnings\\ +\ */\\ +#ifdef _MSC_VER\\ +/*\\ +\ * This warning is explicitly disabled in Visual C++ by default.\\ +\ * It is necessary to explicitly enable the /Wall flag to generate this\\ +\ * warning.\\ +\ * Since this is a shared include file it should compile without warnings\\ +\ * at the highest warning level, so third party applications can use\\ +\ * higher warning levels cleanly.\\ +\ *\\ +\ * 4820: 'bytes' bytes padding added after member 'member'\\ +\ * The type and order of elements caused the compiler to\\ +\ * add padding to the end of a struct.\\ +\ */\\ +#pragma warning(push)\\ +#pragma warning(disable: 4820)\\ +#endif /* _MSC_VER */ + d +} +/@platform_footer@/{ + i\\ +/* Restore default compiler warnings */\\ +#ifdef _MSC_VER\\ +#pragma warning(pop)\\ +#endif + d +} +s/@DB_VERSION_FAMILY@/$DB_VERSION_FAMILY/ +s/@DB_VERSION_RELEASE@/$DB_VERSION_RELEASE/ +s/@DB_VERSION_MAJOR@/$DB_VERSION_MAJOR/ +s/@DB_VERSION_MINOR@/$DB_VERSION_MINOR/ +s/@DB_VERSION_PATCH@/$DB_VERSION_PATCH/ +s/@DB_VERSION_STRING@/"$DB_VERSION_STRING"/ +s/@DB_VERSION_FULL_STRING@/"$DB_VERSION_FULL_STRING"/ +s/@DB_VERSION_UNIQUE_NAME@// +s/@DB_CONST@// +s/@DB_PROTO1@/#undef __P/ +s/@DB_PROTO2@/#define __P(protos) protos/ +ENDOFSEDTEXT +# The db.h, db_int.h files are identical between Windows and WinCE. +# This may change in the future, for now have the script copy +# the headers into the build_wince directory. +# WinCE does not support the C++ API, so don't need to copy db_cxx.h + +(echo "$msgc" && + sed -f $s ../src/dbinc/db.in && + cat ../src/dbinc_auto/api_flags.in && + cat ../src/dbinc_auto/ext_prot.in) > $t +test `egrep '@.*@' $t` && { + egrep '@.*@' $t + echo 'Unexpanded autoconf variables found in Windows db.h.' + exit 1 +} +f=../build_windows/db.h +cmp $t $f > /dev/null 2>&1 || + (echo "Building $f" && rm -f $f && cp $t $f) +f=../build_wince/db.h +cmp $t $f > /dev/null 2>&1 || + (echo "Building $f" && rm -f $f && cp $t $f) + +# Build the Windows db_cxx.h. +cat < $s +s/@cxx_have_stdheaders@/#define HAVE_CXX_STDHEADERS 1/ +ENDOFSEDTEXT +(echo "$msgc" && sed -f $s ../src/dbinc/db_cxx.in) > $t +test `egrep '@.*@' $t` && { + egrep '@.*@' $t + echo 'Unexpanded autoconf variables found in Windows db_cxx.h.' + exit 1 +} +f=../build_windows/db_cxx.h +cmp $t $f > /dev/null 2>&1 || + (echo "Building $f" && rm -f $f && cp $t $f) + +# Build the Windows db_int.h. +cat < $s +s/@DB_STRUCT_ALIGN8@/__declspec(align(8))/ +s/@PATH_SEPARATOR@/\\\\\\\\\/:/ +s/@db_int_def@// +ENDOFSEDTEXT +(echo "$msgc" && sed -f $s ../src/dbinc/db_int.in) > $t +test `egrep '@.*@' $t` && { + egrep '@.*@' $t + echo 'Unexpanded autoconf variables found in Windows db_int.h.' + exit 1 +} +f=../build_windows/db_int.h +cmp $t $f > /dev/null 2>&1 || + (echo "Building $f" && rm -f $f && cp $t $f) +f=../build_wince/db_int.h +cmp $t $f > /dev/null 2>&1 || + (echo "Building $f" && rm -f $f && cp $t $f) + +# Build the Windows and WinCE db_config.h. +# We don't fail, but we complain if the win_config.in file isn't up-to-date. +check_config() +{ + egrep '^#undef' config.hin | awk '{print $2}' | sort -u > $s + (egrep '#undef' $1 | awk '{print $3}' + egrep '^#define' $1 | awk '{print $2}') | sed '/__STDC__/d' | sort -u > $t + cmp $s $t > /dev/null || { + echo "config.hin and $1 differ" + echo "<<< config.hin >>> $1" + diff $s $t + } +} +check_config win_config.in +f=../build_windows/db_config.h +(echo "$msgc" && sed "s/__EDIT_DB_VERSION__/$DB_VERSION/" win_config.in) > $t +cmp $t $f > /dev/null 2>&1 || + (echo "Building $f" && rm -f $f && cp $t $f) +check_config wince_config.in +f=../build_wince/db_config.h +(echo "$msgc" && sed "s/__EDIT_DB_VERSION__/$DB_VERSION/" wince_config.in) > $t +cmp $t $f > /dev/null 2>&1 || + (echo "Building $f" && rm -f $f && cp $t $f) + +# Build the Windows libdb.rc, libdb.def and libdb_small.def. +f=../build_windows/libdb.rc +cat < $s +s/%MAJOR%/$DB_VERSION_MAJOR/ +s/%MINOR%/$DB_VERSION_MINOR/ +s/%PATCH%/$DB_VERSION_PATCH/ +ENDOFSEDTEXT +sed -f $s ../build_windows/libdbrc.src > $t +cmp $t $f > /dev/null 2>&1 || + (echo "Building $f" && rm -f $f && cp $t $f) +f=../build_windows/libdb.def +(echo $msgw && + echo && + echo EXPORTS; +a=1 +for i in `sed -e '/^$/d' -e '/^#/d' win_exports.in | + egrep -w rds | + sed -e 's/[ ].*//'`; do + echo " $i @$a" + a=`expr $a + 1` +done) > $t +cmp $t $f > /dev/null 2>&1 || + (echo "Building $f" && rm -f $f && cp $t $f) +f=../build_windows/libdb_small.def +(echo $msgw && + echo && + echo EXPORTS; +a=1 +for i in `sed -e '/^$/d' -e '/^#/d' win_exports.in | + egrep -w db_small | + sed -e 's/[ ].*//'`; do + echo " $i @$a" + a=`expr $a + 1` +done) > $t +cmp $t $f > /dev/null 2>&1 || + (echo "Building $f" && rm -f $f && cp $t $f) + +# Build the Windows clib_port.h. +cat < $s +s/@INT64_FMT@/#define INT64_FMT "%I64d"/ +s/@UINT64_FMT@/#define UINT64_FMT "%I64u"/ +ENDOFSEDTEXT +sed -f $s clib_port.in > $t +test `egrep '@.*@' $t` && { + egrep '@.*@' $t + echo 'Unexpanded autoconf variables found in Windows clib_port.h.' + exit 1 +} +f=../build_windows/clib_port.h +cmp $t $f > /dev/null 2>&1 || + (echo "Building $f" && rm -f $f && cp $t $f) +f=../build_wince/clib_port.h +cmp $t $f > /dev/null 2>&1 || + (echo "Building $f" && rm -f $f && cp $t $f) + +# Build the Windows dbstl_common.h. +cat < $s +s/@WSTRING_decl@/#define HAVE_WSTRING 1/ +s/@TLS_decl@/#define TLS_DECL_MODIFIER __declspec(thread)/ +s/@TLS_defn@/#define TLS_DEFN_MODIFIER __declspec(thread)/ +ENDOFSEDTEXT +sed -f $s ../lang/cxx/stl/dbstl_common.in > $t +f=../build_windows/dbstl_common.h +cmp $t $f > /dev/null 2>&1 || + (echo "Building $f" && rm -f $f && cp $t $f) + +# Copy in errno.h. +f=../build_wince/errno.h +cmp errno.h $f > /dev/null 2>&1 || + (echo "Building $f" && rm -f $f && cp errno.h $f) + +rm -f $s $t diff -r 000000000000 -r a1985f14b030 dist/s_windows_dsp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dist/s_windows_dsp Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,216 @@ +#!/bin/bash - +# +# Copyright (c) 2012 Oracle and/or its affiliates. All rights reserved. +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. Oracle designates this +# particular file as subject to the "Classpath" exception as provided +# by Oracle in the LICENSE file that accompanied this code. +# +# This code 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 General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. +# +# $Id$ +# +# Build Windows CE .vcproj files +# Build Windows .vcproj files. + +. ./RELEASE + +create_projects() +{ + # project name list + PROJECTS=$1 + + # xquery script template + TEMPLATE=genproject.template + TEMPLATE_VS2010=vs2010.template + + # vs2010 common properties template + LIBTEMPLATE=library.props.template + APPTEMPLATE=application.props.template + + # temporary script, post-sed-replacement + TEMP_SCRIPT=genproject.script + + # temporary common properties for vs2010 + TEMP_LIB=library.props + TEMP_APP=application.props + + # xml document input template + CONFIG_INPUT=$2 + + # temporary xml document, post-sed-replacement + CONFIG_OUTPUT=projects.xml + + # location for output project files + PROJECT_OUTPUT_PARENT_DIR=$3 + + # judge Windows or Win CE for vs2010 + WinVersion=$4 + + if [ $WinVersion = "WinCE" ]; then + VLoop=VS8 + else + VLoop="VS8 VS10" + fi + + # for each project, substitute 2 variables in the XQuery script, then run it + # temporarily use only VS10 here to omit the generation of VS8 + for v in $VLoop + do + + if [ $v = "VS71" ]; then + VERSION="7.10" + elif [ $v = "VS8" ]; then + VERSION="8.00" + elif [ $v = "VS10" ]; then + VERSION="10.0" + fi + + PROJECT_OUTPUT_DIR="$PROJECT_OUTPUT_PARENT_DIR/$v" + + # substitute some variables in the XML document template + if [ $v = "VS10" ]; then + sed -e "s/@DB_VERSION_MAJOR@/$DB_VERSION_MAJOR/g" \ + -e "s/@DB_VERSION_MINOR@/$DB_VERSION_MINOR/g" \ + -e "s/$/ /" \ + < $LIBTEMPLATE > $TEMP_LIB + + sed -e "s/@DB_VERSION_MAJOR@/$DB_VERSION_MAJOR/g" \ + -e "s/@DB_VERSION_MINOR@/$DB_VERSION_MINOR/g" \ + -e "s/$/ /" \ + < $APPTEMPLATE > $TEMP_APP + + mv $TEMP_LIB $PROJECT_OUTPUT_DIR/$TEMP_LIB + mv $TEMP_APP $PROJECT_OUTPUT_DIR/$TEMP_APP + fi + sed -e "s/@DB_VERSION_MAJOR@/$DB_VERSION_MAJOR/g" \ + -e "s/@DB_VERSION_MINOR@/$DB_VERSION_MINOR/g" \ + < $CONFIG_INPUT > $CONFIG_OUTPUT + + + + echo "Building for Visual Studio version $VERSION" + + for i in `cat $PROJECTS` + do + if [ $v = "VS10" ]; then + sed -e "s!@PROJECT_NAME@!$i!g" -e "s!@PROJECT_INPUT@!$CONFIG_OUTPUT!g" -e "s!@VISUAL_STUDIO_VERSION@!$VERSION!g" < $TEMPLATE_VS2010 > $TEMP_SCRIPT + else + sed -e "s!@PROJECT_NAME@!$i!g" -e "s!@PROJECT_INPUT@!$CONFIG_OUTPUT!g" -e "s!@VISUAL_STUDIO_VERSION@!$VERSION!g" < $TEMPLATE > $TEMP_SCRIPT + fi + if [ $v = "VS7.1" ]; then + TMP=$PROJECT_OUTPUT_DIR/$i.tmp.vcproj + TARG=$PROJECT_OUTPUT_DIR/${i}_vs71.vcproj + elif [ $v = "VS8" ]; then + TMP=$PROJECT_OUTPUT_DIR/$i.tmp.vcproj + TARG=$PROJECT_OUTPUT_DIR/${i}.vcproj + else + TMP=$PROJECT_OUTPUT_DIR/$i.tmp.vcxproj + TARG=$PROJECT_OUTPUT_DIR/${i}.vcxproj + fi + xqilla -o $TMP $TEMP_SCRIPT + rm -f $TEMP_SCRIPT + chmod 644 $TMP + cmp $TMP $TARG > /dev/null 2>&1 || + (echo "Building $TARG" && rm -f $TARG && + cp $TMP $TARG) + rm -f $TMP + done + done + + # Cleanup. + rm -f $CONFIG_OUTPUT +} + +create_projects_csharp() +{ + # project name list + PROJECTS=$1 + + # xquery script template + TEMPLATE=genproject_csharp.template + + # temporary script, post-sed-replacement + TEMP_SCRIPT=genproject.script + + # xml document input template + CONFIG_INPUT=$2 + + # temporary xml document, post-sed-replacement + CONFIG_OUTPUT=projects.xml + + # substitute some variables in the XML document template + sed -e "s/@DB_VERSION_MAJOR@/$DB_VERSION_MAJOR/g" \ + -e "s/@DB_VERSION_MINOR@/$DB_VERSION_MINOR/g" \ + < $CONFIG_INPUT > $CONFIG_OUTPUT + + # for each project, substitute 2 variables in the XQuery script, then run it + for i in `cat $PROJECTS` + do + # Split project path into dir + basename + PROJECT_OUTPUT_DIR=`dirname $i` + i=`basename $i` + + sed -e "s!@PROJECT_NAME@!$i!g" -e "s!@PROJECT_INPUT@!$CONFIG_OUTPUT!g" -e "s!@VISUAL_STUDIO_VERSION@!$VERSION!g" < $TEMPLATE > $TEMP_SCRIPT + TMP=$PROJECT_OUTPUT_DIR/$i.tmp.csproj + TARG=$PROJECT_OUTPUT_DIR/${i}.csproj + xqilla -o $TMP $TEMP_SCRIPT + rm -f $TEMP_SCRIPT + chmod 644 $TMP + cmp $TMP $TARG > /dev/null 2>&1 || + (echo "Building $TARG" && rm -f $TARG && + cp $TMP $TARG) + rm -f $TMP + done + + # Cleanup. + rm -f $CONFIG_OUTPUT +} + +# Detect XQilla +which xqilla > /dev/null 2>&1 +if [ $? -ne 0 ]; then + echo "Can not find xqilla command." + exit 1 +fi + +cd win_projects + +# Create/Update Windows project files +echo "Building Visual Studio project files for Windows -- " +echo " output only for modified projects (this can take a while)" +create_projects db.projects projects.template.xml ../../build_windows Win + +echo "Building Visual Studio project files for Windows DB-RDS --" +echo " output only for modified projects (this can take a while)" +create_projects ../rds/db_rds.projects ../rds/projects_rds.template.xml ../rds/build_windows Win +ls -ltR ../rds/build_windows + +# Create/Update Windows CE project files +echo "Building Visual Studio project files for Windows CE -- " +echo " output only for modified projects (this can take a while)" +create_projects db_wince.projects projects_wince.template.xml ../../build_wince WinCE + +# Create/Update C Sharp project files +echo "Building C Sharp project files -- " +echo " output only for modified projects (this can take a while)" +create_projects_csharp db_csharp.projects projects_csharp.template.xml + +cd .. + diff -r 000000000000 -r a1985f14b030 dist/srcfiles.in --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dist/srcfiles.in Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,374 @@ +# $Id$ +# +# Copyright (c) 2000, 2012 Oracle and/or its affiliates. All rights reserved. +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. Oracle designates this +# particular file as subject to the "Classpath" exception as provided +# by Oracle in the LICENSE file that accompanied this code. +# +# This code 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 General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. +# +# This is an input file for the s_vxworks, s_android, and buildrds scripts. It +# lists the source files in the Berkeley DB tree and notes which are used to +# build the Android, VxWorks libraries. +# +# If you are adding a new file, putting the filename here in srcfiles.in and +# indicate which modules require the file. Also make sure to add the file to +# dist/win_projects/projects.template.xml for Windows, and +# dist/win_projects/projects_wince.template.xml for Windows CE. +# +# Please keep this list sorted alphabetically! +# +# Each non-blank, non-comment line is of the form +# filename module [ module ...] + +src/btree/bt_compact.c android vx vxsmall +src/btree/bt_compare.c android vx vxsmall rds +src/btree/bt_compress.c android vx vxsmall +src/btree/bt_conv.c android vx vxsmall rds +src/btree/bt_curadj.c android vx vxsmall rds +src/btree/bt_cursor.c android vx vxsmall rds +src/btree/bt_delete.c android vx vxsmall rds +src/btree/bt_method.c android vx vxsmall rds +src/btree/bt_open.c android vx vxsmall rds +src/btree/bt_put.c android vx vxsmall rds +src/btree/bt_rec.c android vx vxsmall +src/btree/bt_reclaim.c android vx vxsmall rds +src/btree/bt_recno.c android vx vxsmall rds +src/btree/bt_rsearch.c android vx vxsmall rds +src/btree/bt_search.c android vx vxsmall rds +src/btree/bt_split.c android vx vxsmall rds +src/btree/bt_stat.c android vx vxsmall rds +src/btree/bt_upgrade.c android vx vxsmall +src/btree/bt_verify.c vx rds +src/btree/btree_auto.c android vx vxsmall +src/btree/btree_autop.c vx6 +build_vxworks/util/db_archive.c vx6 +build_vxworks/util/db_checkpoint.c vx6 +build_vxworks/util/db_deadlock.c vx6 +build_vxworks/util/db_dump.c vx6 rds +build_vxworks/util/db_hotbackup.c vx6 +build_vxworks/util/db_load.c vx6 rds +build_vxworks/util/db_log_verify.c vx6 +build_vxworks/util/db_printlog.c vx6 +build_vxworks/util/db_recover.c vx6 +build_vxworks/util/db_stat.c vx6 rds +build_vxworks/util/db_tuner.c vx6 +build_vxworks/util/db_upgrade.c vx6 +build_vxworks/util/db_verify.c vx6 rds +build_vxworks/dbdemo/dbdemo.c vx6 +build_vxworks/test/micro/b_curalloc.c vx6 +build_vxworks/test/micro/b_curwalk.c vx6 +build_vxworks/test/micro/b_del.c vx6 +build_vxworks/test/micro/b_get.c vx6 +build_vxworks/test/micro/b_inmem.c vx6 +build_vxworks/test/micro/b_latch.c vx6 +build_vxworks/test/micro/b_load.c vx6 +build_vxworks/test/micro/b_open.c vx6 +build_vxworks/test/micro/b_put.c vx6 +build_vxworks/test/micro/b_recover.c vx6 +build_vxworks/test/micro/b_txn.c vx6 +build_vxworks/test/micro/b_txn_write.c vx6 +build_vxworks/test/micro/b_uname.c vx6 +build_vxworks/test/micro/b_util.c vx6 +build_vxworks/test/micro/b_workload.c vx6 +build_vxworks/test/micro/test_micro.c vx6 +src/clib/isalpha.c rds +src/clib/getopt.c vx vxsmall rds +src/clib/rand.c android +src/clib/snprintf.c android vx vxsmall rds +src/clib/strcasecmp.c vx vxsmall +src/clib/strdup.c vx vxsmall +src/clib/strsep.c vx vxsmall rds +src/common/clock.c android vx vxsmall rds +src/common/crypto_stub.c vxsmall rds +src/common/db_byteorder.c android vx vxsmall rds +src/common/db_compint.c android vx vxsmall +src/common/db_err.c android vx vxsmall rds +src/common/db_getlong.c android vx vxsmall rds +src/common/db_idspace.c android vx vxsmall rds +src/common/db_log2.c android vx vxsmall rds +src/common/db_shash.c android vx vxsmall rds +src/common/dbt.c android vx vxsmall rds +src/common/mkpath.c android vx vxsmall rds +src/common/os_method.c android vx vxsmall rds +src/common/rds_stub.c rds +src/common/util_arg.c vx vxsmall +src/common/util_cache.c vx vxsmall rds +src/common/util_log.c vx vxsmall rds +src/common/util_sig.c vx vxsmall rds +src/common/zerofill.c android vx vxsmall rds +src/crypto/aes_method.c vx +src/crypto/crypto.c vx +src/crypto/mersenne/mt19937db.c vx +src/crypto/rijndael/rijndael-alg-fst.c vx +src/crypto/rijndael/rijndael-api-fst.c vx +lang/cxx/cxx_channel.cpp vx6 +lang/cxx/cxx_db.cpp vx6 +lang/cxx/cxx_dbc.cpp vx6 +lang/cxx/cxx_dbt.cpp vx6 +lang/cxx/cxx_env.cpp vx6 +lang/cxx/cxx_except.cpp vx6 +lang/cxx/cxx_lock.cpp vx6 +lang/cxx/cxx_logc.cpp vx6 +lang/cxx/cxx_mpool.cpp vx6 +lang/cxx/cxx_multi.cpp vx6 +lang/cxx/cxx_seq.cpp vx6 +lang/cxx/cxx_site.cpp vx6 +lang/cxx/cxx_txn.cpp vx6 +src/db/crdel_auto.c android vx vxsmall +src/db/crdel_autop.c vx6 +src/db/crdel_rec.c android vx vxsmall +src/db/db.c android vx vxsmall rds +src/db/db_am.c android vx vxsmall rds +src/db/db_auto.c android vx vxsmall +src/db/db_autop.c vx6 +src/db/db_backup.c android vx vxsmall rds +src/db/db_cam.c android vx vxsmall rds +src/db/db_cds.c android vx vxsmall +src/db/db_compact.c android vx vxsmall +src/db/db_conv.c android vx vxsmall rds +src/db/db_copy.c android vx vxsmall rds +src/db/db_dispatch.c android vx vxsmall +src/db/db_dup.c android vx vxsmall rds +src/db/db_iface.c android vx vxsmall rds +src/db/db_join.c android vx vxsmall +src/db/db_meta.c android vx vxsmall rds +src/db/db_method.c android vx vxsmall rds +src/db/db_open.c android vx vxsmall rds +src/db/db_overflow.c android vx vxsmall rds +src/db/db_ovfl_vrfy.c vx rds +src/db/db_pr.c android vx vxsmall rds +src/db/db_rec.c android vx vxsmall +src/db/db_reclaim.c android vx vxsmall rds +src/db/db_remove.c android vx vxsmall rds +src/db/db_rename.c android vx vxsmall rds +src/db/db_ret.c android vx vxsmall rds +src/db/db_setid.c android vx vxsmall rds +src/db/db_setlsn.c android vx vxsmall rds +src/db/db_sort_multiple.c android vx vxsmall rds +src/db/db_stati.c android vx vxsmall rds +src/db/db_truncate.c android vx vxsmall rds +src/db/db_upg.c android vx vxsmall +src/db/db_upg_opd.c android vx vxsmall +src/db/db_vrfy.c vx rds +src/db/db_vrfy_stub.c android vxsmall rds +src/db/db_vrfyutil.c vx rds +src/db/partition.c android vx +src/db/partition_stub.c android vx rds +lang/db185/db185.c +src/dbreg/dbreg.c android vx vxsmall +src/dbreg/dbreg_auto.c android vx vxsmall +src/dbreg/dbreg_autop.c vx6 +src/dbreg/dbreg_rec.c android vx vxsmall +src/dbreg/dbreg_stat.c android vx vxsmall +src/dbreg/dbreg_util.c android vx vxsmall +src/env/env_alloc.c android vx vxsmall rds +src/env/env_backup.c android vx vxsmall +src/env/env_config.c android vx vxsmall rds +src/env/env_failchk.c android vx vxsmall +src/env/env_file.c android vx vxsmall rds +src/env/env_globals.c android vx vxsmall rds +src/env/env_method.c android vx vxsmall rds +src/env/env_name.c android vx vxsmall rds +src/env/env_open.c android vx vxsmall rds +src/env/env_recover.c android vx vxsmall +src/env/env_region.c android vx vxsmall rds +src/env/env_register.c android vx vxsmall +src/env/env_sig.c android vx vxsmall rds +src/env/env_stat.c android vx vxsmall rds +src/fileops/fileops_auto.c android vx vxsmall +src/fileops/fileops_autop.c vx6 +src/fileops/fop_basic.c android vx vxsmall rds +src/fileops/fop_rec.c android vx vxsmall +src/fileops/fop_util.c android vx vxsmall rds +src/hash/hash.c vx +src/hash/hash_auto.c vx +src/hash/hash_autop.c vx6 +src/hash/hash_compact.c vx +src/hash/hash_conv.c vx +src/hash/hash_dup.c vx +src/hash/hash_func.c android vx vxsmall rds +src/hash/hash_meta.c vx +src/hash/hash_method.c vx +src/hash/hash_open.c vx +src/hash/hash_page.c vx +src/hash/hash_rec.c vx +src/hash/hash_reclaim.c vx +src/hash/hash_stat.c vx +src/hash/hash_stub.c android vxsmall rds +src/hash/hash_upgrade.c vx +src/hash/hash_verify.c vx +src/heap/heap_auto.c vx +src/heap/heap_autop.c vx +src/heap/heap_backup.c vx +src/heap/heap.c vx +src/heap/heap_conv.c vx +src/heap/heap_method.c vx +src/heap/heap_open.c vx +src/heap/heap_rec.c vx +src/heap/heap_reclaim.c vx +src/heap/heap_stat.c vx +src/heap/heap_stub.c android vxsmall rds +src/heap/heap_verify.c vx +src/hmac/hmac.c android vx vxsmall +src/hmac/sha1.c android vx vxsmall +src/lock/db_lock.c android vx vxsmall +src/lock/lock.c android vx vxsmall +src/lock/lock_deadlock.c android vx vxsmall +src/lock/lock_failchk.c android vx vxsmall +src/lock/lock_id.c android vx vxsmall +src/lock/lock_list.c android vx vxsmall +src/lock/lock_method.c android vx vxsmall +src/lock/lock_region.c android vx vxsmall +src/lock/lock_stat.c android vx vxsmall +src/lock/lock_timer.c android vx vxsmall +src/lock/lock_util.c android vx vxsmall +src/lock/lock_stub.c rds +src/log/log.c android vx vxsmall +src/log/log_archive.c android vx vxsmall +src/log/log_compare.c android vx vxsmall +src/log/log_debug.c android vx vxsmall +src/log/log_get.c android vx vxsmall +src/log/log_method.c android vx vxsmall +src/log/log_print.c android vx vxsmall +src/log/log_put.c android vx vxsmall +src/log/log_stat.c android vx vxsmall +src/log/log_verify.c vx +src/log/log_verify_util.c vx +src/log/log_verify_auto.c vx +src/log/log_verify_int.c vx +src/log/log_verify_stub.c android vxsmall rds +src/mp/mp_alloc.c android vx vxsmall rds +src/mp/mp_backup.c android vx vxsmall +src/mp/mp_bh.c android vx vxsmall rds +src/mp/mp_fget.c android vx vxsmall rds +src/mp/mp_fmethod.c android vx vxsmall rds +src/mp/mp_fopen.c android vx vxsmall rds +src/mp/mp_fput.c android vx vxsmall rds +src/mp/mp_fset.c android vx vxsmall rds +src/mp/mp_method.c android vx vxsmall rds +src/mp/mp_mvcc.c android vx vxsmall +src/mp/mp_region.c android vx vxsmall rds +src/mp/mp_register.c android vx vxsmall rds +src/mp/mp_resize.c android vx vxsmall rds +src/mp/mp_stat.c android vx vxsmall rds +src/mp/mp_sync.c android vx vxsmall rds +src/mp/mp_trickle.c android vx vxsmall rds +src/mutex/mut_alloc.c android vx vxsmall rds +src/mutex/mut_failchk.c android vx vxsmall +src/mutex/mut_fcntl.c +src/mutex/mut_method.c android vx vxsmall rds +src/mutex/mut_pthread.c android vx vxsmall rds +src/mutex/mut_region.c android vx vxsmall rds +src/mutex/mut_stat.c android vx vxsmall rds +src/mutex/mut_tas.c android vx vxsmall rds +src/mutex/mut_win32.c ce_small rds +src/os/os_abort.c android vx vxsmall rds +src/os/os_abs.c android rds +src/os/os_addrinfo.c vx rds +src/os/os_alloc.c android vx vxsmall rds +src/os/os_clock.c android vx vxsmall rds +src/os/os_config.c android rds +src/os/os_cpu.c android vx vxsmall rds +src/os/os_ctime.c android vx vxsmall rds +src/os/os_dir.c android vx vxsmall rds +src/os/os_errno.c android vx vxsmall rds +src/os/os_fid.c android vx vxsmall rds +src/os/os_flock.c android vx vxsmall rds +src/os/os_fsync.c android vx vxsmall rds +src/os/os_getenv.c android vx vxsmall rds +src/os/os_handle.c android vx vxsmall rds +src/os/os_map.c android rds +src/os/os_mkdir.c android vx vxsmall rds +src/os/os_open.c android vx vxsmall rds +src/os/os_path.c android vx vxsmall rds +src/os/os_pid.c android vx vxsmall rds +src/os/os_rename.c android vx vxsmall rds +src/os/os_root.c android vx vxsmall rds +src/os/os_rpath.c android rds +src/os/os_rw.c android vx vxsmall rds +src/os/os_seek.c android vx vxsmall rds +src/os/os_stack.c android vx vxsmall rds +src/os/os_stat.c android vx vxsmall rds +src/os/os_tmpdir.c android vx vxsmall rds +src/os/os_truncate.c android vx vxsmall rds +src/os/os_uid.c android vx vxsmall rds +src/os/os_unlink.c android vx vxsmall rds +src/os/os_yield.c android rds +src/os_qnx/os_qnx_fsync.c +src/os_qnx/os_qnx_open.c +src/os_vxworks/os_vx_abs.c vx vxsmall +src/os_vxworks/os_vx_config.c vx vxsmall +src/os_vxworks/os_vx_map.c vx vxsmall +src/os_vxworks/os_vx_rpath.c vx vxsmall +src/os_vxworks/os_vx_yield.c vx vxsmall +src/qam/qam.c vx +src/qam/qam_auto.c vx +src/qam/qam_autop.c vx6 +src/qam/qam_conv.c vx +src/qam/qam_files.c vx +src/qam/qam_method.c vx +src/qam/qam_open.c vx +src/qam/qam_rec.c vx +src/qam/qam_stat.c vx +src/qam/qam_stub.c android vxsmall rds +src/qam/qam_upgrade.c vx +src/qam/qam_verify.c vx +src/rep/rep_automsg.c vx +src/rep/rep_backup.c vx +src/rep/rep_elect.c vx +src/rep/rep_lease.c vx +src/rep/rep_log.c vx +src/rep/rep_method.c vx +src/rep/rep_record.c vx +src/rep/rep_region.c vx +src/rep/rep_stat.c vx +src/rep/rep_stub.c android vxsmall rds +src/rep/rep_util.c vx +src/rep/rep_verify.c vx +src/repmgr/repmgr_auto.c vx +src/repmgr/repmgr_autop.c vx6 +src/repmgr/repmgr_automsg.c vx +src/repmgr/repmgr_elect.c vx +src/repmgr/repmgr_method.c vx +src/repmgr/repmgr_msg.c vx +src/repmgr/repmgr_net.c vx +src/repmgr/repmgr_posix.c vx +src/repmgr/repmgr_queue.c vx +src/repmgr/repmgr_rec.c vx +src/repmgr/repmgr_sel.c vx +src/repmgr/repmgr_stat.c vx +src/repmgr/repmgr_stub.c android vxsmall rds +src/repmgr/repmgr_util.c vx +src/sequence/seq_stat.c android vx6 +src/sequence/sequence.c android vx6 +src/txn/txn.c android vx vxsmall +src/txn/txn_auto.c android vx vxsmall +src/txn/txn_autop.c vx6 +src/txn/txn_chkpt.c android vx vxsmall +src/txn/txn_failchk.c android vx vxsmall +src/txn/txn_method.c android vx vxsmall +src/txn/txn_rec.c android vx vxsmall +src/txn/txn_recover.c android vx vxsmall +src/txn/txn_region.c android vx vxsmall +src/txn/txn_stat.c android vx vxsmall +src/txn/txn_util.c android vx vxsmall +src/xa/xa.c vx +src/xa/xa_map.c vx diff -r 000000000000 -r a1985f14b030 make/FILES_c.gmk --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/make/FILES_c.gmk Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,170 @@ +# +# Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. Oracle designates this +# particular file as subject to the "Classpath" exception as provided +# by Oracle in the LICENSE file that accompanied this code. +# +# This code 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 General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. +# + +FILES_c = \ + btree/bt_compare.c \ + btree/bt_conv.c \ + btree/bt_curadj.c \ + btree/bt_cursor.c \ + btree/bt_delete.c \ + btree/bt_method.c \ + btree/bt_open.c \ + btree/bt_put.c \ + btree/bt_reclaim.c \ + btree/bt_recno.c \ + btree/bt_rsearch.c \ + btree/bt_search.c \ + btree/bt_split.c \ + btree/bt_stat.c \ + btree/bt_verify.c \ +\ + clib/isalpha.c \ + clib/strsep.c \ +\ + common/clock.c \ + common/crypto_stub.c \ + common/db_byteorder.c \ + common/db_err.c \ + common/db_getlong.c \ + common/db_idspace.c \ + common/db_log2.c \ + common/db_shash.c \ + common/dbt.c \ + common/mkpath.c \ + common/os_method.c \ + common/util_cache.c \ + common/util_sig.c \ + common/zerofill.c \ +\ + db/db_am.c \ + db/db_backup.c \ + db/db_cam.c \ + db/db_conv.c \ + db/db_copy.c \ + db/db_dup.c \ + db/db_iface.c \ + db/db_meta.c \ + db/db_method.c \ + db/db_open.c \ + db/db_overflow.c \ + db/db_ovfl_vrfy.c \ + db/db_pr.c \ + db/db_reclaim.c \ + db/db_remove.c \ + db/db_rename.c \ + db/db_ret.c \ + db/db_setid.c \ + db/db_setlsn.c \ + db/db_sort_multiple.c \ + db/db_stati.c \ + db/db_truncate.c \ + db/db_vrfy.c \ + db/db_vrfyutil.c \ + db/db.c \ + db/partition_stub.c \ + db/rds_stub.c \ +\ + env/env_alloc.c \ + env/env_config.c \ + env/env_file.c \ + env/env_globals.c \ + env/env_method.c \ + env/env_name.c \ + env/env_open.c \ + env/env_region.c \ + env/env_sig.c \ + env/env_stat.c \ +\ + fileops/fop_basic.c \ + fileops/fop_util.c \ +\ + hash/hash_func.c \ + hash/hash_stub.c \ +\ + heap/heap_stub.c \ +\ + lock/lock_stub.c \ +\ + log/log_verify_stub.c \ +\ + mp/mp_alloc.c \ + mp/mp_bh.c \ + mp/mp_fget.c \ + mp/mp_fmethod.c \ + mp/mp_fopen.c \ + mp/mp_fput.c \ + mp/mp_fset.c \ + mp/mp_method.c \ + mp/mp_region.c \ + mp/mp_register.c \ + mp/mp_resize.c \ + mp/mp_stat.c \ + mp/mp_sync.c \ + mp/mp_trickle.c \ +\ + mutex/mut_alloc.c \ + mutex/mut_method.c \ + mutex/mut_region.c \ + mutex/mut_stat.c \ + mutex/mut_win32.c \ +\ + os_abort.c \ + os_abs.c \ + os_addrinfo.c \ + os_alloc.c \ + os_clock.c \ + os_config.c \ + os_cpu.c \ + os_ctime.c \ + os_dir.c \ + os_errno.c \ + os_fid.c \ + os_flock.c \ + os_fsync.c \ + os_getenv.c \ + os_handle.c \ + os_map.c \ + os_mkdir.c \ + os_open.c \ + os_path.c \ + os_pid.c \ + os_rename.c \ + os_root.c \ + os_rpath.c \ + os_rw.c \ + os_seek.c \ + os_stack.c \ + os_stat.c \ + os_tmpdir.c \ + os_truncate.c \ + os_uid.c \ + os_unlink.c \ + os_yield.c \ +\ + qam/qam_stub.c \ +\ + rep/rep_stub.c \ +\ + repmgr/repmgr_stub.c \ diff -r 000000000000 -r a1985f14b030 make/Makefile --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/make/Makefile Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,165 @@ +# +# Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. Oracle designates this +# particular file as subject to the "Classpath" exception as provided +# by Oracle in the LICENSE file that accompanied this code. +# +# This code 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 General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. +# + +# Makefile for building Berkeley DB-RDS ( Restricted Data Store ), +# a.k.a Ultrasmall build +# +# This library is currently used by org.openjdk.pmap.PersistentTreeMap. + +# For now dependency on JDK shared makefiles +BUILDDIR = . +PACKAGE = bdb + +ifndef BDB_TOPDIR + BDB_TOPDIR = $(BUILDDIR)/.. +endif +ifndef JDK_TOPDIR + JDK_TOPDIR=$(BDB_TOPDIR)/../jdk +endif +ifndef JDK_MAKE_SHARED_DIR + JDK_MAKE_SHARED_DIR=$(JDK_TOPDIR)/make/common/shared +endif +ifndef ALT_EXPORT_PATH + ALT_EXPORT_PATH = $(BDB_TOPDIR)/import +endif + +include $(JDK_MAKE_SHARED_DIR)/../Defs.gmk + +SRCDIR = $(BUILDDIR)/../src +DISTDIR = $(BUILDDIR)/../dist +EXPORTDIR = $(ALT_EXPORT_PATH) + +# Careful not to conflict with LIBRARY definition for Library.gmk +_LIBRARY = $(LIB_PREFIX)db-rds.$(LIBRARY_SUFFIX) + +GEN_HEADERS_DIR=$(GENNATIVESRCDIR)/bdb + +all: build + +ifeq ($(PLATFORM), windows) + LIBRARY = db-rds + VERSIONINFO_RESOURCE = libdb.rc + + include FILES_c.gmk + include $(JDK_MAKE_SHARED_DIR)/../Library.gmk + + # Find C source files + vpath %.c $(SRCDIR) + vpath %.c $(SRCDIR)/btree + vpath %.c $(SRCDIR)/db + vpath %.c $(SRCDIR)/dbreg + vpath %.c $(SRCDIR)/common + vpath %.c $(SRCDIR)/fileops + vpath %.c $(SRCDIR)/clib + vpath %.c $(SRCDIR)/hash + vpath %.c $(SRCDIR)/heap + vpath %.c $(SRCDIR)/log + vpath %.c $(SRCDIR)/mutex + vpath %.c $(SRCDIR)/qam + vpath %.c $(SRCDIR)/rep + vpath %.c $(SRCDIR)/repmgr + vpath %.c $(SRCDIR)/env + vpath %.c $(SRCDIR)/lock + vpath %.c $(SRCDIR)/mp + vpath %.c $(SRCDIR)/txn + vpath %.c $(SRCDIR)/hmac + vpath %.c $(SRCDIR)/os_windows + # search os after os_windows so any commonly named files + # will be found in os_windows first + vpath %.c $(SRCDIR)/os + + CFLAGS += -D_WINDOWS -DDB_CREATE_DLL -DHAVE_RDS_BUILD \ + -D_USRDLL -D_WINDLL -D_UNICODE -DUNICODE -D_MBCS + EXTRA_LFLAGS += /DEF:"libdb.def" + OTHER_LDLIBS += kernel32.lib user32.lib ws2_32.lib + + # do not link against libjava + JAVALIB = + + OTHER_INCLUDES += -I$(SRCDIR) + OTHER_INCLUDES += -I$(SRCDIR)/windows_incl + + $(EXPORTDIR)/header/db.h: $(SRCDIR)/windows_incl/db.h + $(install-file) + +else # NOT WINDOWS + SRCDIR_ABS:=$(call FullPath,$(SRCDIR)) + DISTDIR_ABS:=$(call FullPath,$(DISTDIR)) + BDB_OUTPUT_LIB=$(TEMPDIR)/.libs/libdb-5.4.$(LIBRARY_SUFFIX) + BDB_OUTPUT_HEADER=$(TEMPDIR)/db.h + BDB_CONFIG_OPTIONS=--disable-static CC=$(CC) LD=$(LD) + + # 64-bit Solaris compile needs to specify appropriate addressing model + ifeq ($(PLATFORM), solaris) + ifeq ($(ARCH_DATA_MODEL), 64) + BDB_CONFIG_OPTIONS+=CFLAGS=-m64 + endif + endif + + ifeq ($(CROSS_COMPILE_ARCH), arm) + BDB_CONFIG_OPTIONS+=--build=i686-pc-linux-gnu --host=arm-none-linux-gnueabi \ + cross_compiling=yes + endif + + define configure-bdb + $(CD) $(TEMPDIR) && \ + $(SH) $(DISTDIR_ABS)/configure $(BDB_CONFIG_OPTIONS) + endef + + define make-bdb + $(CD) $(TEMPDIR) && \ + $(MAKE) + endef + + $(BDB_OUTPUT_HEADER): + $(configure-bdb) + $(MKDIR) -p $(GEN_HEADERS_DIR) + $(CP) $(BDB_OUTPUT_HEADER) $(GEN_HEADERS_DIR) + + $(BDB_OUTPUT_LIB): $(BDB_OUTPUT_HEADER) + $(make-bdb) + + $(LIB_LOCATION)/$(_LIBRARY): $(BDB_OUTPUT_LIB) + $(install-file) + + $(EXPORTDIR)/header/db.h: $(GEN_HEADERS_DIR)/db.h + $(install-file) + +endif # NOT WINDOWS + +EXPORT_LIST = $(EXPORTDIR)/lib/$(LIBARCH)/$(_LIBRARY) +EXPORT_LIST += $(EXPORTDIR)/header/db.h + +build: $(LIB_LOCATION)/$(_LIBRARY) export + +export: $(EXPORT_LIST) + +$(EXPORTDIR)/lib/$(LIBARCH)/$(_LIBRARY): $(LIB_LOCATION)/$(_LIBRARY) + $(install-file) + +clobber:: + $(RM) -rf $(TEMPDIR) $(EXPORTDIR) + +.PHONY: clobber clean build all export $(EXPORTDIR)/lib/$(LIBARCH)/$(_LIBRARY) diff -r 000000000000 -r a1985f14b030 make/libdb.def --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/make/libdb.def Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,28 @@ +; +; Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. +; DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +; +; This code is free software; you can redistribute it and/or modify it +; under the terms of the GNU General Public License version 2 only, as +; published by the Free Software Foundation. Oracle designates this +; particular file as subject to the "Classpath" exception as provided +; by Oracle in the LICENSE file that accompanied this code. +; +; This code 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 General Public License +; version 2 for more details (a copy is included in the LICENSE file that +; accompanied this code). +; +; You should have received a copy of the GNU General Public License version +; 2 along with this work; if not, write to the Free Software Foundation, +; Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +; +; Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +; or visit www.oracle.com if you need additional information or have any +; questions. +; + +EXPORTS + db_create @1 + db_strerror @2 diff -r 000000000000 -r a1985f14b030 make/libdb.rc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/make/libdb.rc Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,56 @@ +// +// Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. +// DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +// +// This code is free software; you can redistribute it and/or modify it +// under the terms of the GNU General Public License version 2 only, as +// published by the Free Software Foundation. +// +// This code 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 General Public License +// version 2 for more details (a copy is included in the LICENSE file that +// accompanied this code). +// +// You should have received a copy of the GNU General Public License version +// 2 along with this work; if not, write to the Free Software Foundation, +// Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +// or visit www.oracle.com if you need additional information or have any +// questions. +// + +1 VERSIONINFO + FILEVERSION 5,0,4,0 + PRODUCTVERSION 5,0,4,0 + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x4L + FILETYPE 0x2L + FILESUBTYPE 0x0L + +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "CompanyName", "Oracle\0" + VALUE "FileDescription", "Berkeley DB 5.4 DLL\0" + VALUE "FileVersion", "5.4.0\0" + VALUE "InternalName", "libdb54.dll\0" + VALUE "LegalCopyright", "Copyright Oracle 1997-2009\0" + VALUE "OriginalFilename", "libdb54.dll\0" + VALUE "ProductName", "Oracle libdb\0" + VALUE "ProductVersion", "5.4.0\0" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END diff -r 000000000000 -r a1985f14b030 src/btree/bt_compare.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/btree/bt_compare.c Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,235 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 1996, 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +/* + * Copyright (c) 1990, 1993, 1994, 1995, 1996 + * Keith Bostic. All rights reserved. + */ +/* + * Copyright (c) 1990, 1993, 1994, 1995 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Mike Olson. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $Id$ + */ + +#include "db_config.h" + +#include "db_int.h" +#include "dbinc/db_page.h" +#include "dbinc/btree.h" + +/* + * __bam_cmp -- + * Compare a key to a given record. + * + * PUBLIC: int __bam_cmp __P((DBC *, const DBT *, PAGE *, u_int32_t, + * PUBLIC: int (*)(DB *, const DBT *, const DBT *), int *)); + */ +int +__bam_cmp(dbc, dbt, h, indx, func, cmpp) + DBC *dbc; + const DBT *dbt; + PAGE *h; + u_int32_t indx; + int (*func)__P((DB *, const DBT *, const DBT *)); + int *cmpp; +{ + BINTERNAL *bi; + BKEYDATA *bk; + BOVERFLOW *bo; + DB *dbp; + DBT pg_dbt; + + dbp = dbc->dbp; + + /* + * Returns: + * < 0 if dbt is < page record + * = 0 if dbt is = page record + * > 0 if dbt is > page record + * + * !!! + * We do not clear the pg_dbt DBT even though it's likely to contain + * random bits. That should be okay, because the app's comparison + * routine had better not be looking at fields other than data, size + * and app_data. We don't clear it because we go through this path a + * lot and it's expensive. + */ + switch (TYPE(h)) { + case P_LBTREE: + case P_LDUP: + case P_LRECNO: + bk = GET_BKEYDATA(dbp, h, indx); + if (B_TYPE(bk->type) == B_OVERFLOW) + bo = (BOVERFLOW *)bk; + else { + pg_dbt.app_data = NULL; + pg_dbt.data = bk->data; + pg_dbt.size = bk->len; + *cmpp = func(dbp, dbt, &pg_dbt); + return (0); + } + break; + case P_IBTREE: + /* + * The following code guarantees that the left-most key on an + * internal page at any place in the tree sorts less than any + * user-specified key. The reason is that if we have reached + * this internal page, we know the user key must sort greater + * than the key we're storing for this page in any internal + * pages at levels above us in the tree. It then follows that + * any user-specified key cannot sort less than the first page + * which we reference, and so there's no reason to call the + * comparison routine. While this may save us a comparison + * routine call or two, the real reason for this is because + * we don't maintain a copy of the smallest key in the tree, + * so that we don't have to update all the levels of the tree + * should the application store a new smallest key. And, so, + * we may not have a key to compare, which makes doing the + * comparison difficult and error prone. + */ + if (indx == 0) { + *cmpp = 1; + return (0); + } + + bi = GET_BINTERNAL(dbp, h, indx); + if (B_TYPE(bi->type) == B_OVERFLOW) + bo = (BOVERFLOW *)(bi->data); + else { + pg_dbt.app_data = NULL; + pg_dbt.data = bi->data; + pg_dbt.size = bi->len; + *cmpp = func(dbp, dbt, &pg_dbt); + return (0); + } + break; + default: + return (__db_pgfmt(dbp->env, PGNO(h))); + } + + /* + * Overflow. + */ + return (__db_moff(dbc, dbt, bo->pgno, bo->tlen, + func == __bam_defcmp ? NULL : func, cmpp)); +} + +/* + * __bam_defcmp -- + * Default comparison routine. + * + * PUBLIC: int __bam_defcmp __P((DB *, const DBT *, const DBT *)); + */ +int +__bam_defcmp(dbp, a, b) + DB *dbp; + const DBT *a, *b; +{ + size_t len; + u_int8_t *p1, *p2; + + COMPQUIET(dbp, NULL); + + /* + * Returns: + * < 0 if a is < b + * = 0 if a is = b + * > 0 if a is > b + * + * XXX + * If a size_t doesn't fit into a long, or if the difference between + * any two characters doesn't fit into an int, this routine can lose. + * What we need is a signed integral type that's guaranteed to be at + * least as large as a size_t, and there is no such thing. + */ + len = a->size > b->size ? b->size : a->size; + for (p1 = a->data, p2 = b->data; len--; ++p1, ++p2) + if (*p1 != *p2) + return ((long)*p1 - (long)*p2); + return ((long)a->size - (long)b->size); +} + +/* + * __bam_defpfx -- + * Default prefix routine. + * + * PUBLIC: size_t __bam_defpfx __P((DB *, const DBT *, const DBT *)); + */ +size_t +__bam_defpfx(dbp, a, b) + DB *dbp; + const DBT *a, *b; +{ + size_t cnt, len; + u_int8_t *p1, *p2; + + COMPQUIET(dbp, NULL); + + cnt = 1; + len = a->size > b->size ? b->size : a->size; + for (p1 = a->data, p2 = b->data; len--; ++p1, ++p2, ++cnt) + if (*p1 != *p2) + return (cnt); + + /* + * They match up to the smaller of the two sizes. + * Collate the longer after the shorter. + */ + if (a->size < b->size) + return (a->size + 1); + if (b->size < a->size) + return (b->size + 1); + return (b->size); +} diff -r 000000000000 -r a1985f14b030 src/btree/bt_conv.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/btree/bt_conv.c Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,117 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 1996, 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + * $Id$ + */ + +#include "db_config.h" + +#include "db_int.h" +#include "dbinc/db_page.h" +#include "dbinc/db_swap.h" +#include "dbinc/btree.h" + +/* + * __bam_pgin -- + * Convert host-specific page layout from the host-independent format + * stored on disk. + * + * PUBLIC: int __bam_pgin __P((DB *, db_pgno_t, void *, DBT *)); + */ +int +__bam_pgin(dbp, pg, pp, cookie) + DB *dbp; + db_pgno_t pg; + void *pp; + DBT *cookie; +{ + DB_PGINFO *pginfo; + PAGE *h; + + pginfo = (DB_PGINFO *)cookie->data; + if (!F_ISSET(pginfo, DB_AM_SWAP)) + return (0); + + h = pp; + return (TYPE(h) == P_BTREEMETA ? __bam_mswap(dbp->env, pp) : + __db_byteswap(dbp, pg, pp, pginfo->db_pagesize, 1)); +} + +/* + * __bam_pgout -- + * Convert host-specific page layout to the host-independent format + * stored on disk. + * + * PUBLIC: int __bam_pgout __P((DB *, db_pgno_t, void *, DBT *)); + */ +int +__bam_pgout(dbp, pg, pp, cookie) + DB *dbp; + db_pgno_t pg; + void *pp; + DBT *cookie; +{ + DB_PGINFO *pginfo; + PAGE *h; + + pginfo = (DB_PGINFO *)cookie->data; + if (!F_ISSET(pginfo, DB_AM_SWAP)) + return (0); + + h = pp; + return (TYPE(h) == P_BTREEMETA ? __bam_mswap(dbp->env, pp) : + __db_byteswap(dbp, pg, pp, pginfo->db_pagesize, 0)); +} + +/* + * __bam_mswap -- + * Swap the bytes on the btree metadata page. + * + * PUBLIC: int __bam_mswap __P((ENV *, PAGE *)); + */ +int +__bam_mswap(env, pg) + ENV *env; + PAGE *pg; +{ + u_int8_t *p; + + COMPQUIET(env, NULL); + + __db_metaswap(pg); + p = (u_int8_t *)pg + sizeof(DBMETA); + + p += sizeof(u_int32_t); /* unused */ + SWAP32(p); /* minkey */ + SWAP32(p); /* re_len */ + SWAP32(p); /* re_pad */ + SWAP32(p); /* root */ + p += 92 * sizeof(u_int32_t); /* unused */ + SWAP32(p); /* crypto_magic */ + + return (0); +} diff -r 000000000000 -r a1985f14b030 src/btree/bt_curadj.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/btree/bt_curadj.c Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,716 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 1996, 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + * $Id$ + */ + +#include "db_config.h" + +#include "db_int.h" +#include "dbinc/db_page.h" +#include "dbinc/btree.h" +#include "dbinc/mp.h" + +static int __bam_opd_cursor __P((DB *, DBC *, db_pgno_t, u_int32_t, u_int32_t)); +static int __bam_ca_delete_func + __P((DBC *, DBC *, u_int32_t *, db_pgno_t, u_int32_t, void *)); +static int __ram_ca_delete_func + __P((DBC *, DBC *, u_int32_t *, db_pgno_t, u_int32_t, void *)); +static int __bam_ca_di_func + __P((DBC *, DBC *, u_int32_t *, db_pgno_t, u_int32_t, void *)); +static int __bam_ca_dup_func + __P((DBC *, DBC *, u_int32_t *, db_pgno_t, u_int32_t, void *)); +static int __bam_ca_undodup_func + __P((DBC *, DBC *, u_int32_t *, db_pgno_t, u_int32_t, void *)); +static int __bam_ca_rsplit_func + __P((DBC *, DBC *, u_int32_t *, db_pgno_t, u_int32_t, void *)); +static int __bam_ca_split_func + __P((DBC *, DBC *, u_int32_t *, db_pgno_t, u_int32_t, void *)); +static int __bam_ca_undosplit_func + __P((DBC *, DBC *, u_int32_t *, db_pgno_t, u_int32_t, void *)); + +/* + * Cursor adjustments are logged if they are for subtransactions. This is + * because it's possible for a subtransaction to adjust cursors which will + * still be active after the subtransaction aborts, and so which must be + * restored to their previous locations. Cursors that can be both affected + * by our cursor adjustments and active after our transaction aborts can + * only be found in our parent transaction -- cursors in other transactions, + * including other child transactions of our parent, must have conflicting + * locker IDs, and so cannot be affected by adjustments in this transaction. + */ + + /* + * __bam_ca_delete_func + * Callback function for walking cursors to update them due to a delete. + */ + static int + __bam_ca_delete_func(dbc, my_dbc, countp, pgno, indx, args) + DBC *dbc, *my_dbc; + u_int32_t *countp; + db_pgno_t pgno; + u_int32_t indx; + void *args; +{ + BTREE_CURSOR *cp; + u_int32_t del; + + COMPQUIET(my_dbc, NULL); + del = *(u_int32_t *)args; + + cp = (BTREE_CURSOR *)dbc->internal; + if (cp->pgno == pgno && cp->indx == indx && + !MVCC_SKIP_CURADJ(dbc, pgno)) { + /* + * [#8032] This assert is checking for possible race + * conditions where we hold a cursor position without + * a lock. Unfortunately, there are paths in the + * Btree code that do not satisfy these conditions. + * None of them are known to be a problem, but this + * assert should be re-activated when the Btree stack + * code is re-written. + DB_ASSERT(env, !STD_LOCKING(dbc) || + cp->lock_mode != DB_LOCK_NG); + */ + if (del) { + F_SET(cp, C_DELETED); + /* + * If we're deleting the item, we can't + * keep a streaming offset cached. + */ + cp->stream_start_pgno = PGNO_INVALID; + } else + F_CLR(cp, C_DELETED); + +#ifdef HAVE_COMPRESSION + /* + * We also set the C_COMPRESS_MODIFIED flag, which + * prompts the compression code to look for it's + * current entry again if it needs to. + * + * The flag isn't cleared, because the compression + * code still needs to do that even for an entry that + * becomes undeleted. + * + * This flag also needs to be set if an entry is + * updated, but since the compression code always + * deletes before an update, setting it here is + * sufficient. + */ + F_SET(cp, C_COMPRESS_MODIFIED); +#endif + + ++(*countp); + } + return (0); +} + +/* + * __bam_ca_delete -- + * Update the cursors when items are deleted and when already deleted + * items are overwritten. Return the number of relevant cursors found. + * + * PUBLIC: int __bam_ca_delete __P((DB *, + * PUBLIC: db_pgno_t, u_int32_t, int, u_int32_t *)); + */ +int +__bam_ca_delete(dbp, pgno, indx, del, countp) + DB *dbp; + db_pgno_t pgno; + u_int32_t indx; + int del; + u_int32_t *countp; +{ + int ret; + u_int32_t count; + + /* + * Adjust the cursors. We have the page write locked, so the + * only other cursors that can be pointing at a page are + * those in the same thread of control. Unfortunately, we don't + * know that they're using the same DB handle, so traverse + * all matching DB handles in the same ENV, then all cursors + * on each matching DB handle. + * + * Each cursor is single-threaded, so we only need to lock the + * list of DBs and then the list of cursors in each DB. + */ + if ((ret = __db_walk_cursors(dbp, NULL, + __bam_ca_delete_func, &count, pgno, indx, &del)) != 0) + return (ret); + + if (countp != NULL) + *countp = count; + return (0); +} + +static int +__ram_ca_delete_func(dbc, my_dbc, countp, root_pgno, indx, args) + DBC *dbc, *my_dbc; + u_int32_t *countp; + db_pgno_t root_pgno; + u_int32_t indx; + void *args; +{ + COMPQUIET(indx, 0); + COMPQUIET(my_dbc, NULL); + COMPQUIET(args, NULL); + + if (dbc->internal->root == root_pgno && + !MVCC_SKIP_CURADJ(dbc, root_pgno)) { + (*countp)++; + return (EEXIST); + } + return (0); +} + +/* + * __ram_ca_delete -- + * Return if any relevant cursors found. + * + * PUBLIC: int __ram_ca_delete __P((DB *, db_pgno_t, u_int32_t *)); + */ +int +__ram_ca_delete(dbp, root_pgno, foundp) + DB *dbp; + db_pgno_t root_pgno; + u_int32_t *foundp; +{ + int ret; + + if ((ret = __db_walk_cursors(dbp, NULL, __ram_ca_delete_func, + foundp, root_pgno, 0, NULL)) != 0 && ret != EEXIST) + return (ret); + + return (0); +} + +struct __bam_ca_di_args { + int adjust; + DB_TXN *my_txn; +}; + +static int +__bam_ca_di_func(dbc, my_dbc, foundp, pgno, indx, vargs) + DBC *dbc, *my_dbc; + u_int32_t *foundp; + db_pgno_t pgno; + u_int32_t indx; + void *vargs; +{ + DBC_INTERNAL *cp; + struct __bam_ca_di_args *args; + + if (dbc->dbtype == DB_RECNO) + return (0); + + cp = dbc->internal; + args = vargs; + if (cp->pgno == pgno && cp->indx >= indx && + (dbc == my_dbc || !MVCC_SKIP_CURADJ(dbc, pgno))) { + /* Cursor indices should never be negative. */ + DB_ASSERT(dbc->dbp->env, cp->indx != 0 || args->adjust > 0); + /* [#8032] + DB_ASSERT(env, !STD_LOCKING(dbc) || + cp->lock_mode != DB_LOCK_NG); + */ + cp->indx += args->adjust; + if (args->my_txn != NULL && args->my_txn != dbc->txn) + *foundp = 1; + } + return (0); +} +/* + * __bam_ca_di -- + * Adjust the cursors during a delete or insert. + * + * PUBLIC: int __bam_ca_di __P((DBC *, db_pgno_t, u_int32_t, int)); + */ +int +__bam_ca_di(my_dbc, pgno, indx, adjust) + DBC *my_dbc; + db_pgno_t pgno; + u_int32_t indx; + int adjust; +{ + DB *dbp; + DB_LSN lsn; + int ret; + u_int32_t found; + struct __bam_ca_di_args args; + + dbp = my_dbc->dbp; + args.adjust = adjust; + args.my_txn = IS_SUBTRANSACTION(my_dbc->txn) ? my_dbc->txn : NULL; + + /* + * Adjust the cursors. See the comment in __bam_ca_delete(). + */ + if ((ret = __db_walk_cursors(dbp, my_dbc, __bam_ca_di_func, + &found, pgno, indx, &args)) != 0) + return (ret); + + if (found != 0 && DBC_LOGGING(my_dbc)) { + if ((ret = __bam_curadj_log(dbp, my_dbc->txn, &lsn, 0, + DB_CA_DI, pgno, 0, 0, (u_int32_t)adjust, indx, 0)) != 0) + return (ret); + } + + return (0); +} + +/* + * __bam_opd_cursor -- create a new opd cursor. + */ +static int +__bam_opd_cursor(dbp, dbc, first, tpgno, ti) + DB *dbp; + DBC *dbc; + db_pgno_t tpgno; + u_int32_t first, ti; +{ + BTREE_CURSOR *cp, *orig_cp; + DBC *dbc_nopd; + int ret; + + orig_cp = (BTREE_CURSOR *)dbc->internal; + dbc_nopd = NULL; + + /* + * Allocate a new cursor and create the stack. If duplicates + * are sorted, we've just created an off-page duplicate Btree. + * If duplicates aren't sorted, we've just created a Recno tree. + * + * Note that in order to get here at all, there shouldn't be + * an old off-page dup cursor--to augment the checking dbc_newopd + * will do, assert this. + */ + DB_ASSERT(dbp->env, orig_cp->opd == NULL); + if ((ret = __dbc_newopd(dbc, tpgno, orig_cp->opd, &dbc_nopd)) != 0) + return (ret); + + cp = (BTREE_CURSOR *)dbc_nopd->internal; + cp->pgno = tpgno; + cp->indx = ti; + + if (dbp->dup_compare == NULL) { + /* + * Converting to off-page Recno trees is tricky. The + * record number for the cursor is the index + 1 (to + * convert to 1-based record numbers). + */ + cp->recno = ti + 1; + } + + /* + * Transfer the deleted flag from the top-level cursor to the + * created one. + */ + if (F_ISSET(orig_cp, C_DELETED)) { + F_SET(cp, C_DELETED); + F_CLR(orig_cp, C_DELETED); + } + + /* Stack the cursors and reset the initial cursor's index. */ + orig_cp->opd = dbc_nopd; + orig_cp->indx = first; + return (0); +} + +struct __bam_ca_dup_args { + db_pgno_t tpgno; + db_indx_t first, ti; + DB_TXN *my_txn; +}; + +static int +__bam_ca_dup_func(dbc, my_dbc, foundp, fpgno, fi, vargs) + DBC *dbc; + DBC *my_dbc; + u_int32_t *foundp; + db_pgno_t fpgno; + u_int32_t fi; + void *vargs; +{ + BTREE_CURSOR *orig_cp; + DB *dbp; + int ret; + struct __bam_ca_dup_args *args; + + COMPQUIET(my_dbc, NULL); + + /* + * Since we rescan the list see if this is already + * converted. + */ + orig_cp = (BTREE_CURSOR *)dbc->internal; + if (orig_cp->opd != NULL) + return (0); + + /* Find cursors pointing to this record. */ + if (orig_cp->pgno != fpgno || orig_cp->indx != fi || + MVCC_SKIP_CURADJ(dbc, fpgno)) + return (0); + + dbp = dbc->dbp; + args = vargs; + + MUTEX_UNLOCK(dbp->env, dbp->mutex); + + if ((ret = __bam_opd_cursor(dbp, + dbc, args->first, args->tpgno, args->ti)) != 0) { + MUTEX_LOCK(dbp->env, dbp->mutex); + return (ret); + } + if (args->my_txn != NULL && args->my_txn != dbc->txn) + *foundp = 1; + /* We released the mutex to get a cursor, start over. */ + return (DB_LOCK_NOTGRANTED); +} + +/* + * __bam_ca_dup -- + * Adjust the cursors when moving items from a leaf page to a duplicates + * page. + * + * PUBLIC: int __bam_ca_dup __P((DBC *, + * PUBLIC: u_int32_t, db_pgno_t, u_int32_t, db_pgno_t, u_int32_t)); + */ +int +__bam_ca_dup(my_dbc, first, fpgno, fi, tpgno, ti) + DBC *my_dbc; + db_pgno_t fpgno, tpgno; + u_int32_t first, fi, ti; +{ + DB *dbp; + DB_LSN lsn; + int ret, t_ret; + u_int32_t found; + struct __bam_ca_dup_args args; + + dbp = my_dbc->dbp; + + args.first = first; + args.tpgno = tpgno; + args.ti = ti; + args.my_txn = IS_SUBTRANSACTION(my_dbc->txn) ? my_dbc->txn : NULL; + + if ((ret = __db_walk_cursors(dbp, + my_dbc, __bam_ca_dup_func, &found, fpgno, fi, &args)) != 0) + return (ret); + + if (found != 0 && DBC_LOGGING(my_dbc)) { + if ((t_ret = __bam_curadj_log(dbp, my_dbc->txn, + &lsn, 0, DB_CA_DUP, fpgno, tpgno, 0, first, fi, ti)) != 0 && + ret == 0) + ret = t_ret; + } + + return (ret); +} + +static int +__bam_ca_undodup_func(dbc, my_dbc, countp, fpgno, fi, vargs) + DBC *dbc; + DBC *my_dbc; + u_int32_t *countp; + db_pgno_t fpgno; + u_int32_t fi; + void *vargs; +{ + BTREE_CURSOR *orig_cp; + DB *dbp; + int ret; + struct __bam_ca_dup_args *args; + + COMPQUIET(my_dbc, NULL); + COMPQUIET(countp, NULL); + + orig_cp = (BTREE_CURSOR *)dbc->internal; + dbp = dbc->dbp; + args = vargs; + /* + * A note on the orig_cp->opd != NULL requirement here: + * it's possible that there's a cursor that refers to + * the same duplicate set, but which has no opd cursor, + * because it refers to a different item and we took + * care of it while processing a previous record. + */ + if (orig_cp->pgno != fpgno || + orig_cp->indx != args->first || + orig_cp->opd == NULL || ((BTREE_CURSOR *) + orig_cp->opd->internal)->indx != args->ti || + MVCC_SKIP_CURADJ(dbc, fpgno)) + return (0); + MUTEX_UNLOCK(dbp->env, dbp->mutex); + if ((ret = __dbc_close(orig_cp->opd)) != 0) { + MUTEX_LOCK(dbp->env, dbp->mutex); + return (ret); + } + orig_cp->opd = NULL; + orig_cp->indx = fi; + /* + * We released the mutex to free a cursor, + * start over. + */ + return (DB_LOCK_NOTGRANTED); +} + +/* + * __bam_ca_undodup -- + * Adjust the cursors when returning items to a leaf page + * from a duplicate page. + * Called only during undo processing. + * + * PUBLIC: int __bam_ca_undodup __P((DB *, + * PUBLIC: u_int32_t, db_pgno_t, u_int32_t, u_int32_t)); + */ +int +__bam_ca_undodup(dbp, first, fpgno, fi, ti) + DB *dbp; + db_pgno_t fpgno; + u_int32_t first, fi, ti; +{ + u_int32_t count; + struct __bam_ca_dup_args args; + + args.first = first; + args.ti = ti; + return (__db_walk_cursors(dbp, NULL, + __bam_ca_undodup_func, &count, fpgno, fi, &args)); + +} + +static int +__bam_ca_rsplit_func(dbc, my_dbc, foundp, fpgno, indx, args) + DBC *dbc; + DBC *my_dbc; + u_int32_t *foundp; + db_pgno_t fpgno; + u_int32_t indx; + void *args; +{ + db_pgno_t tpgno; + + COMPQUIET(indx, 0); + + if (dbc->dbtype == DB_RECNO) + return (0); + + tpgno = *(db_pgno_t *)args; + if (dbc->internal->pgno == fpgno && + !MVCC_SKIP_CURADJ(dbc, fpgno)) { + dbc->internal->pgno = tpgno; + /* [#8032] + DB_ASSERT(env, !STD_LOCKING(dbc) || + dbc->internal->lock_mode != DB_LOCK_NG); + */ + if (IS_SUBTRANSACTION(my_dbc->txn) && dbc->txn != my_dbc->txn) + *foundp = 1; + } + return (0); +} + +/* + * __bam_ca_rsplit -- + * Adjust the cursors when doing reverse splits. + * + * PUBLIC: int __bam_ca_rsplit __P((DBC *, db_pgno_t, db_pgno_t)); + */ +int +__bam_ca_rsplit(my_dbc, fpgno, tpgno) + DBC* my_dbc; + db_pgno_t fpgno, tpgno; +{ + DB *dbp; + DB_LSN lsn; + int ret; + u_int32_t found; + + dbp = my_dbc->dbp; + + if ((ret = __db_walk_cursors(dbp, my_dbc, + __bam_ca_rsplit_func, &found, fpgno, 0, &tpgno)) != 0) + return (ret); + + if (found != 0 && DBC_LOGGING(my_dbc)) { + if ((ret = __bam_curadj_log(dbp, my_dbc->txn, + &lsn, 0, DB_CA_RSPLIT, fpgno, tpgno, 0, 0, 0, 0)) != 0) + return (ret); + } + return (0); +} + +struct __bam_ca_split_args { + db_pgno_t lpgno, rpgno; + int cleft; + DB_TXN *my_txn; +}; + +static int +__bam_ca_split_func(dbc, my_dbc, foundp, ppgno, split_indx, vargs) + DBC *dbc; + DBC *my_dbc; + u_int32_t *foundp; + db_pgno_t ppgno; + u_int32_t split_indx; + void *vargs; +{ + DBC_INTERNAL *cp; + struct __bam_ca_split_args *args; + + COMPQUIET(my_dbc, NULL); + + if (dbc->dbtype == DB_RECNO) + return (0); + cp = dbc->internal; + args = vargs; + if (cp->pgno == ppgno && + !MVCC_SKIP_CURADJ(dbc, ppgno)) { + /* [#8032] + DB_ASSERT(env, !STD_LOCKING(dbc) || + cp->lock_mode != DB_LOCK_NG); + */ + if (args->my_txn != NULL && args->my_txn != dbc->txn) + *foundp = 1; + if (cp->indx < split_indx) { + if (args->cleft) + cp->pgno = args->lpgno; + } else { + cp->pgno = args->rpgno; + cp->indx -= split_indx; + } + } + return (0); +} + +/* + * __bam_ca_split -- + * Adjust the cursors when splitting a page. + * + * PUBLIC: int __bam_ca_split __P((DBC *, + * PUBLIC: db_pgno_t, db_pgno_t, db_pgno_t, u_int32_t, int)); + */ +int +__bam_ca_split(my_dbc, ppgno, lpgno, rpgno, split_indx, cleft) + DBC *my_dbc; + db_pgno_t ppgno, lpgno, rpgno; + u_int32_t split_indx; + int cleft; +{ + DB *dbp; + DB_LSN lsn; + int ret; + u_int32_t found; + struct __bam_ca_split_args args; + + dbp = my_dbc->dbp; + + /* + * If splitting the page that a cursor was on, the cursor has to be + * adjusted to point to the same record as before the split. Most + * of the time we don't adjust pointers to the left page, because + * we're going to copy its contents back over the original page. If + * the cursor is on the right page, it is decremented by the number of + * records split to the left page. + */ + args.lpgno = lpgno; + args.rpgno = rpgno; + args.cleft = cleft; + args.my_txn = IS_SUBTRANSACTION(my_dbc->txn) ? my_dbc->txn : NULL; + if ((ret = __db_walk_cursors(dbp, my_dbc, + __bam_ca_split_func, &found, ppgno, split_indx, &args)) != 0) + return (ret); + + if (found != 0 && DBC_LOGGING(my_dbc)) { + if ((ret = __bam_curadj_log(dbp, + my_dbc->txn, &lsn, 0, DB_CA_SPLIT, ppgno, rpgno, + cleft ? lpgno : PGNO_INVALID, 0, split_indx, 0)) != 0) + return (ret); + } + + return (0); +} + +static int +__bam_ca_undosplit_func(dbc, my_dbc, foundp, frompgno, split_indx, vargs) + DBC *dbc; + DBC *my_dbc; + u_int32_t *foundp; + db_pgno_t frompgno; + u_int32_t split_indx; + void *vargs; +{ + DBC_INTERNAL *cp; + struct __bam_ca_split_args *args; + + COMPQUIET(my_dbc, NULL); + COMPQUIET(foundp, NULL); + + if (dbc->dbtype == DB_RECNO) + return (0); + cp = dbc->internal; + args = vargs; + if (cp->pgno == args->rpgno && + !MVCC_SKIP_CURADJ(dbc, args->rpgno)) { + cp->pgno = frompgno; + cp->indx += split_indx; + } else if (cp->pgno == args->lpgno && + !MVCC_SKIP_CURADJ(dbc, args->lpgno)) + cp->pgno = frompgno; + + return (0); +} + +/* + * __bam_ca_undosplit -- + * Adjust the cursors when undoing a split of a page. + * If we grew a level we will execute this for both the + * left and the right pages. + * Called only during undo processing. + * + * PUBLIC: int __bam_ca_undosplit __P((DB *, + * PUBLIC: db_pgno_t, db_pgno_t, db_pgno_t, u_int32_t)); + */ +int +__bam_ca_undosplit(dbp, frompgno, topgno, lpgno, split_indx) + DB *dbp; + db_pgno_t frompgno, topgno, lpgno; + u_int32_t split_indx; +{ + u_int32_t count; + struct __bam_ca_split_args args; + + /* + * When backing out a split, we move the cursor back + * to the original offset and bump it by the split_indx. + */ + args.lpgno = lpgno; + args.rpgno = topgno; + return (__db_walk_cursors(dbp, NULL, + __bam_ca_undosplit_func, &count, frompgno, split_indx, &args)); +} diff -r 000000000000 -r a1985f14b030 src/btree/bt_cursor.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/btree/bt_cursor.c Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,3098 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 1996, 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + * $Id$ + */ + +#include "db_config.h" + +#include "db_int.h" +#include "dbinc/db_page.h" +#include "dbinc/btree.h" +#include "dbinc/lock.h" +#include "dbinc/mp.h" + +static int __bam_bulk __P((DBC *, DBT *, u_int32_t)); +static int __bamc_close __P((DBC *, db_pgno_t, int *)); +static int __bamc_del __P((DBC *, u_int32_t)); +static int __bamc_destroy __P((DBC *)); +static int __bamc_get __P((DBC *, DBT *, DBT *, u_int32_t, db_pgno_t *)); +static int __bamc_getstack __P((DBC *)); +static int __bamc_next __P((DBC *, int, int)); +static int __bamc_physdel __P((DBC *)); +static int __bamc_prev __P((DBC *)); +static int __bamc_put __P((DBC *, DBT *, DBT *, u_int32_t, db_pgno_t *)); +static int __bamc_search __P((DBC *, + db_pgno_t, const DBT *, u_int32_t, int *)); +static int __bamc_writelock __P((DBC *)); +static int __bam_getboth_finddatum __P((DBC *, DBT *, u_int32_t)); +static int __bam_getbothc __P((DBC *, DBT *)); +static int __bam_get_prev __P((DBC *)); +static int __bam_isopd __P((DBC *, db_pgno_t *)); +#ifdef HAVE_COMPRESSION +static int __bam_getlte __P((DBC *, DBT *, DBT *)); +#endif + +/* + * Acquire a new page/lock. If we hold a page/lock, discard the page, and + * lock-couple the lock. + * + * !!! + * We have to handle both where we have a lock to lock-couple and where we + * don't -- we don't duplicate locks when we duplicate cursors if we are + * running in a transaction environment as there's no point if locks are + * never discarded. This means that the cursor may or may not hold a lock. + * In the case where we are descending the tree we always want to unlock + * the held interior page so we use ACQUIRE_COUPLE. + */ +#undef ACQUIRE +#define ACQUIRE(dbc, mode, lpgno, lock, fpgno, pagep, flags, ret) do { \ + DB_MPOOLFILE *__mpf = (dbc)->dbp->mpf; \ + if ((pagep) != NULL) { \ + ret = __memp_fput(__mpf, \ + (dbc)->thread_info, pagep, dbc->priority); \ + pagep = NULL; \ + } else \ + ret = 0; \ + if ((ret) == 0 && STD_LOCKING(dbc)) \ + ret = __db_lget( \ + dbc, LCK_COUPLE, lpgno, mode, flags, &(lock)); \ + if ((ret) == 0) \ + ret = __memp_fget(__mpf, &(fpgno), \ + (dbc)->thread_info, (dbc)->txn, 0, &(pagep)); \ +} while (0) + +/* Acquire a new page/lock for a cursor. */ +#undef ACQUIRE_CUR +#define ACQUIRE_CUR(dbc, mode, p, flags, ret) do { \ + BTREE_CURSOR *__cp = (BTREE_CURSOR *)(dbc)->internal; \ + if (p != __cp->pgno) \ + __cp->pgno = PGNO_INVALID; \ + ACQUIRE(dbc, mode, p, __cp->lock, p, __cp->page, flags, ret); \ + if ((ret) == 0) { \ + __cp->pgno = p; \ + __cp->lock_mode = (mode); \ + } \ +} while (0) + +/* + * Acquire a write lock if we don't already have one. + * + * !!! + * See ACQUIRE macro on why we handle cursors that don't have locks. + */ +#undef ACQUIRE_WRITE_LOCK +#define ACQUIRE_WRITE_LOCK(dbc, ret) do { \ + BTREE_CURSOR *__cp = (BTREE_CURSOR *)(dbc)->internal; \ + DB_MPOOLFILE *__mpf = (dbc)->dbp->mpf; \ + int __get_page = 0; \ + ret = 0; \ + if (STD_LOCKING(dbc) && __cp->lock_mode != DB_LOCK_WRITE) { \ + if (__cp->page != NULL) { \ + (ret) = __memp_fput(__mpf, (dbc)->thread_info, \ + __cp->page, (dbc)->priority); \ + __cp->page = NULL; \ + __get_page = 1; \ + if ((ret) !=0) \ + break; \ + } \ + if (((ret) = __db_lget((dbc), \ + LOCK_ISSET(__cp->lock) ? LCK_COUPLE : 0, \ + __cp->pgno, DB_LOCK_WRITE, 0, &__cp->lock)) != 0) \ + break; \ + __cp->lock_mode = DB_LOCK_WRITE; \ + if (__get_page == 0) \ + break; \ + (ret) = __memp_fget(__mpf, &__cp->pgno, \ + (dbc)->thread_info, \ + (dbc)->txn, DB_MPOOL_DIRTY, &__cp->page); \ + } \ +} while (0) + +/* Discard the current page/lock for a cursor. */ +#undef DISCARD_CUR +#define DISCARD_CUR(dbc, ret) do { \ + BTREE_CURSOR *__cp = (BTREE_CURSOR *)(dbc)->internal; \ + DB_MPOOLFILE *__mpf = (dbc)->dbp->mpf; \ + int __t_ret; \ + if ((__cp->page) != NULL) { \ + __t_ret = __memp_fput(__mpf, \ + (dbc)->thread_info, __cp->page, dbc->priority);\ + __cp->page = NULL; \ + } else \ + __t_ret = 0; \ + if (__t_ret != 0 && (ret) == 0) \ + ret = __t_ret; \ + __t_ret = __TLPUT((dbc), __cp->lock); \ + if (__t_ret != 0 && (ret) == 0) \ + ret = __t_ret; \ + if ((ret) == 0 && !LOCK_ISSET(__cp->lock)) \ + __cp->lock_mode = DB_LOCK_NG; \ + __cp->stream_start_pgno = PGNO_INVALID; \ +} while (0) + +/* If on-page item is a deleted record. */ +#undef IS_DELETED +#define IS_DELETED(dbp, page, indx) \ + B_DISSET(GET_BKEYDATA(dbp, page, \ + (indx) + (TYPE(page) == P_LBTREE ? O_INDX : 0))->type) +#undef IS_CUR_DELETED +#define IS_CUR_DELETED(dbc) \ + IS_DELETED((dbc)->dbp, (dbc)->internal->page, (dbc)->internal->indx) + +/* + * Test to see if two cursors could point to duplicates of the same key. + * In the case of off-page duplicates they are they same, as the cursors + * will be in the same off-page duplicate tree. In the case of on-page + * duplicates, the key index offsets must be the same. For the last test, + * as the original cursor may not have a valid page pointer, we use the + * current cursor's. + */ +#undef IS_DUPLICATE +#define IS_DUPLICATE(dbc, i1, i2) \ + (P_INP((dbc)->dbp,((PAGE *)(dbc)->internal->page))[i1] == \ + P_INP((dbc)->dbp,((PAGE *)(dbc)->internal->page))[i2]) +#undef IS_CUR_DUPLICATE +#define IS_CUR_DUPLICATE(dbc, orig_pgno, orig_indx) \ + (F_ISSET(dbc, DBC_OPD) || \ + (orig_pgno == (dbc)->internal->pgno && \ + IS_DUPLICATE(dbc, (dbc)->internal->indx, orig_indx))) + +/* + * __bamc_init -- + * Initialize the access private portion of a cursor + * + * PUBLIC: int __bamc_init __P((DBC *, DBTYPE)); + */ +int +__bamc_init(dbc, dbtype) + DBC *dbc; + DBTYPE dbtype; +{ + ENV *env; + int ret; +#ifdef HAVE_COMPRESSION + BTREE_CURSOR *cp; +#endif + + env = dbc->env; + + /* Allocate/initialize the internal structure. */ + if (dbc->internal == NULL) { + if ((ret = __os_calloc( + env, 1, sizeof(BTREE_CURSOR), &dbc->internal)) != 0) + return (ret); + +#ifdef HAVE_COMPRESSION + cp = (BTREE_CURSOR*)dbc->internal; + cp->compressed.flags = DB_DBT_USERMEM; + cp->key1.flags = DB_DBT_USERMEM; + cp->key2.flags = DB_DBT_USERMEM; + cp->data1.flags = DB_DBT_USERMEM; + cp->data2.flags = DB_DBT_USERMEM; + cp->del_key.flags = DB_DBT_USERMEM; + cp->del_data.flags = DB_DBT_USERMEM; +#endif + } + + /* Initialize methods. */ + dbc->close = dbc->c_close = __dbc_close_pp; + dbc->cmp = __dbc_cmp_pp; + dbc->count = dbc->c_count = __dbc_count_pp; + dbc->del = dbc->c_del = __dbc_del_pp; + dbc->dup = dbc->c_dup = __dbc_dup_pp; + dbc->get = dbc->c_get = __dbc_get_pp; + dbc->pget = dbc->c_pget = __dbc_pget_pp; + dbc->put = dbc->c_put = __dbc_put_pp; + if (dbtype == DB_BTREE) { + dbc->am_bulk = __bam_bulk; + dbc->am_close = __bamc_close; + dbc->am_del = __bamc_del; + dbc->am_destroy = __bamc_destroy; + dbc->am_get = __bamc_get; + dbc->am_put = __bamc_put; + dbc->am_writelock = __bamc_writelock; + } else { + dbc->am_bulk = __bam_bulk; + dbc->am_close = __bamc_close; + dbc->am_del = __ramc_del; + dbc->am_destroy = __bamc_destroy; + dbc->am_get = __ramc_get; + dbc->am_put = __ramc_put; + dbc->am_writelock = __bamc_writelock; + } + + return (0); +} + +/* + * __bamc_refresh + * Set things up properly for cursor re-use. + * + * PUBLIC: int __bamc_refresh __P((DBC *)); + */ +int +__bamc_refresh(dbc) + DBC *dbc; +{ + BTREE *t; + BTREE_CURSOR *cp; + DB *dbp; + + dbp = dbc->dbp; + t = dbp->bt_internal; + cp = (BTREE_CURSOR *)dbc->internal; + + /* + * If our caller set the root page number, it's because the root was + * known. This is always the case for off page dup cursors. Else, + * pull it out of our internal information, unless this is a subdb. + */ + if (cp->root == PGNO_INVALID && t->bt_meta == PGNO_BASE_MD) + cp->root = t->bt_root; + + LOCK_INIT(cp->lock); + cp->lock_mode = DB_LOCK_NG; + + if (cp->sp == NULL) { + cp->sp = cp->stack; + cp->esp = cp->stack + sizeof(cp->stack) / sizeof(cp->stack[0]); + } + BT_STK_CLR(cp); + +#ifdef HAVE_COMPRESSION + /* Initialize compression */ + cp->prevKey = 0; + cp->prevData = 0; + cp->currentKey = 0; + cp->currentData = 0; + cp->compcursor = 0; + cp->compend = 0; + cp->prevcursor = 0; + cp->prev2cursor = 0; +#endif + + /* + * The btree leaf page data structures require that two key/data pairs + * (or four items) fit on a page, but other than that there's no fixed + * requirement. The btree off-page duplicates only require two items, + * to be exact, but requiring four for them as well seems reasonable. + * + * Recno uses the btree bt_ovflsize value -- it's close enough. + */ + cp->ovflsize = B_MINKEY_TO_OVFLSIZE( + dbp, F_ISSET(dbc, DBC_OPD) ? 2 : t->bt_minkey, dbp->pgsize); + + cp->recno = RECNO_OOB; + cp->order = INVALID_ORDER; + cp->flags = 0; + + /* Initialize for record numbers. */ + if (F_ISSET(dbc, DBC_OPD) || + dbc->dbtype == DB_RECNO || F_ISSET(dbp, DB_AM_RECNUM)) { + F_SET(cp, C_RECNUM); + + /* + * All btrees that support record numbers, optionally standard + * recno trees, and all off-page duplicate recno trees have + * mutable record numbers. + */ + if ((F_ISSET(dbc, DBC_OPD) && dbc->dbtype == DB_RECNO) || + F_ISSET(dbp, DB_AM_RECNUM | DB_AM_RENUMBER)) + F_SET(cp, C_RENUMBER); + } + + return (0); +} + +/* + * __bamc_close -- + * Close down the cursor. + */ +static int +__bamc_close(dbc, root_pgno, rmroot) + DBC *dbc; + db_pgno_t root_pgno; + int *rmroot; +{ + BTREE_CURSOR *cp, *cp_opd, *cp_c; + DB *dbp; + DBC *dbc_opd, *dbc_c; + DB_MPOOLFILE *mpf; + ENV *env; + PAGE *h; + int cdb_lock, ret; + u_int32_t count; + + dbp = dbc->dbp; + env = dbp->env; + mpf = dbp->mpf; + cp = (BTREE_CURSOR *)dbc->internal; + cp_opd = (dbc_opd = cp->opd) == NULL ? + NULL : (BTREE_CURSOR *)dbc_opd->internal; + cdb_lock = ret = 0; + + /* + * There are 3 ways this function is called: + * + * 1. Closing a primary cursor: we get called with a pointer to a + * primary cursor that has a NULL opd field. This happens when + * closing a btree/recno database cursor without an associated + * off-page duplicate tree. + * + * 2. Closing a primary and an off-page duplicate cursor stack: we + * get called with a pointer to the primary cursor which has a + * non-NULL opd field. This happens when closing a btree cursor + * into database with an associated off-page btree/recno duplicate + * tree. (It can't be a primary recno database, recno databases + * don't support duplicates.) + * + * 3. Closing an off-page duplicate cursor stack: we get called with + * a pointer to the off-page duplicate cursor. This happens when + * closing a non-btree database that has an associated off-page + * btree/recno duplicate tree or for a btree database when the + * opd tree is not empty (root_pgno == PGNO_INVALID). + * + * If either the primary or off-page duplicate cursor deleted a btree + * key/data pair, check to see if the item is still referenced by a + * different cursor. If it is, confirm that cursor's delete flag is + * set and leave it to that cursor to do the delete. + * + * NB: The test for == 0 below is correct. Our caller already removed + * our cursor argument from the active queue, we won't find it when we + * search the queue in __bam_ca_delete(). + * NB: It can't be true that both the primary and off-page duplicate + * cursors have deleted a btree key/data pair. Either the primary + * cursor may have deleted an item and there's no off-page duplicate + * cursor, or there's an off-page duplicate cursor and it may have + * deleted an item. + * + * Primary recno databases aren't an issue here. Recno keys are either + * deleted immediately or never deleted, and do not have to be handled + * here. + * + * Off-page duplicate recno databases are an issue here, cases #2 and + * #3 above can both be off-page recno databases. The problem is the + * same as the final problem for off-page duplicate btree databases. + * If we no longer need the off-page duplicate tree, we want to remove + * it. For off-page duplicate btrees, we are done with the tree when + * we delete the last item it contains, i.e., there can be no further + * references to it when it's empty. For off-page duplicate recnos, + * we remove items from the tree as the application calls the remove + * function, so we are done with the tree when we close the last cursor + * that references it. + * + * We optionally take the root page number from our caller. If the + * primary database is a btree, we can get it ourselves because dbc + * is the primary cursor. If the primary database is not a btree, + * the problem is that we may be dealing with a stack of pages. The + * cursor we're using to do the delete points at the bottom of that + * stack and we need the top of the stack. + */ + if (F_ISSET(cp, C_DELETED)) { + dbc_c = dbc; + switch (dbc->dbtype) { + case DB_BTREE: /* Case #1, #3. */ + if ((ret = __bam_ca_delete( + dbp, cp->pgno, cp->indx, 1, &count)) != 0) + goto err; + if (count == 0) + goto lock; + goto done; + case DB_RECNO: + if (!F_ISSET(dbc, DBC_OPD)) /* Case #1. */ + goto done; + /* Case #3. */ + if ((ret = __ram_ca_delete(dbp, cp->root, &count)) != 0) + goto err; + if (count == 0) + goto lock; + goto done; + case DB_HASH: + case DB_QUEUE: + case DB_UNKNOWN: + default: + ret = __db_unknown_type( + env, "DbCursor.close", dbc->dbtype); + goto err; + } + } + + if (dbc_opd == NULL) + goto done; + + if (F_ISSET(cp_opd, C_DELETED)) { /* Case #2. */ + /* + * We will not have been provided a root page number. Acquire + * one from the primary database. + */ + if ((h = cp->page) == NULL && (ret = __memp_fget(mpf, &cp->pgno, + dbc->thread_info, dbc->txn, 0, &h)) != 0) + goto err; + root_pgno = GET_BOVERFLOW(dbp, h, cp->indx + O_INDX)->pgno; + if ((ret = __memp_fput(mpf, + dbc->thread_info, h, dbc->priority)) != 0) + goto err; + cp->page = NULL; + + dbc_c = dbc_opd; + switch (dbc_opd->dbtype) { + case DB_BTREE: + if ((ret = __bam_ca_delete( + dbp, cp_opd->pgno, cp_opd->indx, 1, &count)) != 0) + goto err; + if (count == 0) + goto lock; + goto done; + case DB_RECNO: + if ((ret = + __ram_ca_delete(dbp, cp_opd->root, &count)) != 0) + goto err; + if (count == 0) + goto lock; + goto done; + case DB_HASH: + case DB_QUEUE: + case DB_UNKNOWN: + default: + ret = __db_unknown_type( + env, "DbCursor.close", dbc->dbtype); + goto err; + } + } + goto done; + +lock: cp_c = (BTREE_CURSOR *)dbc_c->internal; + + /* + * If this is CDB, upgrade the lock if necessary. While we acquired + * the write lock to logically delete the record, we released it when + * we returned from that call, and so may not be holding a write lock + * at the moment. + */ + if (CDB_LOCKING(env)) { + if (F_ISSET(dbc, DBC_WRITECURSOR)) { + if ((ret = __lock_get(env, + dbc->locker, DB_LOCK_UPGRADE, &dbc->lock_dbt, + DB_LOCK_WRITE, &dbc->mylock)) != 0) + goto err; + cdb_lock = 1; + } + goto do_del; + } + + /* + * The variable dbc_c has been initialized to reference the cursor in + * which we're going to do the delete. Initialize the cursor's lock + * structures as necessary. + * + * First, we may not need to acquire any locks. If we're in case #3, + * that is, the primary database isn't a btree database, our caller + * is responsible for acquiring any necessary locks before calling us. + */ + if (F_ISSET(dbc, DBC_OPD)) + goto do_del; + + /* + * Otherwise, acquire a write lock on the primary database's page. + * + * Lock the primary database page, regardless of whether we're deleting + * an item on a primary database page or an off-page duplicates page. + * + * If the cursor that did the initial logical deletion (and had a write + * lock) is not the same cursor doing the physical deletion (which may + * have only ever had a read lock on the item), we need to upgrade to a + * write lock. The confusion comes as follows: + * + * C1 created, acquires item read lock + * C2 dup C1, create C2, also has item read lock. + * C1 acquire write lock, delete item + * C1 close + * C2 close, needs a write lock to physically delete item. + * + * If we're in a TXN, we know that C2 will be able to acquire the write + * lock, because no locker other than the one shared by C1 and C2 can + * acquire a write lock -- the original write lock C1 acquired was never + * discarded. + * + * If we're not in a TXN, it's nastier. Other cursors might acquire + * read locks on the item after C1 closed, discarding its write lock, + * and such locks would prevent C2 from acquiring a read lock. That's + * OK, though, we'll simply wait until we can acquire a write lock, or + * we'll deadlock. (Which better not happen, since we're not in a TXN.) + * + * There are similar scenarios with dirty reads, where the cursor may + * have downgraded its write lock to a was-write lock. + */ + if (STD_LOCKING(dbc)) + if ((ret = __db_lget(dbc, + LCK_COUPLE, cp->pgno, DB_LOCK_WRITE, 0, &cp->lock)) != 0) + goto err; + +do_del: /* + * If the delete occurred in a Btree, we're going to look at the page + * to see if the item has to be physically deleted. Otherwise, we do + * not need the actual page (and it may not even exist, it might have + * been truncated from the file after an allocation aborted). + * + * Delete the on-page physical item referenced by the cursor. + */ + if (F_ISSET(dbc_c, DBC_OPD)) + LOCK_CHECK_OFF(dbc_c->thread_info); + if (dbc_c->dbtype == DB_BTREE) { + if ((ret = __memp_fget(mpf, &cp_c->pgno, dbc->thread_info, + dbc->txn, DB_MPOOL_DIRTY, &cp_c->page)) != 0) + goto err_c; + if ((ret = __bamc_physdel(dbc_c)) != 0) + goto err_c; + } + + /* + * If we're not working in an off-page duplicate tree, then we're + * done. + */ + if (!F_ISSET(dbc_c, DBC_OPD) || root_pgno == PGNO_INVALID) + goto done; + + /* + * We may have just deleted the last element in the off-page duplicate + * tree, and closed the last cursor in the tree. For an off-page btree + * there are no other cursors in the tree by definition, if the tree is + * empty. For an off-page recno we know we have closed the last cursor + * in the tree because the __ram_ca_delete call above returned 0 only + * in that case. So, if the off-page duplicate tree is empty at this + * point, we want to remove it. + */ + if (((h = dbc_c->internal->page) == NULL || h->pgno != root_pgno) && + (ret = __memp_fget(mpf, + &root_pgno, dbc->thread_info, dbc->txn, 0, &h)) != 0) + goto err_c; + if ((count = NUM_ENT(h)) == 0) { + if (h != dbc_c->internal->page) + DISCARD_CUR(dbc_c, ret); + else + dbc_c->internal->page = NULL; + if (ret == 0) + ret = __db_free(dbc, h, 0); + } else if (h != dbc_c->internal->page) + ret = __memp_fput(mpf, dbc->thread_info, h, dbc->priority); + +err_c: if (F_ISSET(dbc_c, DBC_OPD)) + LOCK_CHECK_ON(dbc_c->thread_info); + if (ret != 0) + goto err; + + if (count != 0) + goto done; + + /* + * When removing the tree, we have to do one of two things. If this is + * case #2, that is, the primary tree is a btree, delete the key that's + * associated with the tree from the btree leaf page. We know we are + * the only reference to it and we already have the correct lock. We + * detect this case because the cursor that was passed to us references + * an off-page duplicate cursor. + * + * If this is case #3, that is, the primary tree isn't a btree, pass + * the information back to our caller, it's their job to do cleanup on + * the primary page. + */ + if (dbc_opd != NULL) { + if ((ret = __memp_fget(mpf, &cp->pgno, dbc->thread_info, + dbc->txn, DB_MPOOL_DIRTY, &cp->page)) != 0) + goto err; + if ((ret = __bamc_physdel(dbc)) != 0) + goto err; + } else + *rmroot = 1; +err: +done: /* + * Discard the page references and locks, and confirm that the stack + * has been emptied. + */ + if (dbc_opd != NULL) + DISCARD_CUR(dbc_opd, ret); + DISCARD_CUR(dbc, ret); + + /* Downgrade any CDB lock we acquired. */ + if (cdb_lock) + (void)__lock_downgrade(env, &dbc->mylock, DB_LOCK_IWRITE, 0); + + return (ret); +} + +/* + * __bamc_cmp -- + * Compare two btree cursors for equality. + * + * This function is only called with two cursors that point to the same item. + * It only distinguishes cursors pointing to deleted and undeleted items at + * the same location. + * + * PUBLIC: int __bamc_cmp __P((DBC *, DBC *, int *)); + */ +int +__bamc_cmp(dbc, other_dbc, result) + DBC *dbc, *other_dbc; + int *result; +{ + ENV *env; + BTREE_CURSOR *bcp, *obcp; + + env = dbc->env; + bcp = (BTREE_CURSOR *)dbc->internal; + obcp = (BTREE_CURSOR *)other_dbc->internal; + + DB_ASSERT (env, bcp->pgno == obcp->pgno); + DB_ASSERT (env, bcp->indx == obcp->indx); + + /* Check to see if both cursors have the same deleted flag. */ + *result = + ((F_ISSET(bcp, C_DELETED)) == F_ISSET(obcp, C_DELETED)) ? 0 : 1; + return (0); +} + +/* + * __bamc_destroy -- + * Close a single cursor -- internal version. + */ +static int +__bamc_destroy(dbc) + DBC *dbc; +{ + BTREE_CURSOR *cp; + ENV *env; + + cp = (BTREE_CURSOR *)dbc->internal; + env = dbc->env; + + /* Discard the structures. */ + if (cp->sp != cp->stack) + __os_free(env, cp->sp); + +#ifdef HAVE_COMPRESSION + /* Free the memory used for compression */ + __os_free(env, cp->compressed.data); + __os_free(env, cp->key1.data); + __os_free(env, cp->key2.data); + __os_free(env, cp->data1.data); + __os_free(env, cp->data2.data); + __os_free(env, cp->del_key.data); + __os_free(env, cp->del_data.data); +#endif + + __os_free(env, cp); + + return (0); +} + +/* + * __bamc_count -- + * Return a count of on and off-page duplicates. + * + * PUBLIC: int __bamc_count __P((DBC *, db_recno_t *)); + */ +int +__bamc_count(dbc, recnop) + DBC *dbc; + db_recno_t *recnop; +{ + BTREE_CURSOR *cp; + DB *dbp; + DB_MPOOLFILE *mpf; + db_indx_t indx, top; + db_recno_t recno; + int ret; + + dbp = dbc->dbp; + mpf = dbp->mpf; + cp = (BTREE_CURSOR *)dbc->internal; + + /* + * Called with the top-level cursor that may reference an off-page + * duplicates tree. We don't have to acquire any new locks, we have + * to have a read lock to even get here. + */ + if (cp->opd == NULL) { + /* + * On-page duplicates, get the page and count. + */ + DB_ASSERT(dbp->env, cp->page == NULL); + if ((ret = __memp_fget(mpf, &cp->pgno, + dbc->thread_info, dbc->txn, 0, &cp->page)) != 0) + return (ret); + + /* + * Move back to the beginning of the set of duplicates and + * then count forward. + */ + for (indx = cp->indx;; indx -= P_INDX) + if (indx == 0 || + !IS_DUPLICATE(dbc, indx, indx - P_INDX)) + break; + for (recno = 0, + top = NUM_ENT(cp->page) - P_INDX;; indx += P_INDX) { + if (!IS_DELETED(dbp, cp->page, indx)) + ++recno; + if (indx == top || + !IS_DUPLICATE(dbc, indx, indx + P_INDX)) + break; + } + } else { + /* + * Off-page duplicates tree, get the root page of the off-page + * duplicate tree. + */ + if ((ret = __memp_fget(mpf, &cp->opd->internal->root, + dbc->thread_info, dbc->txn, 0, &cp->page)) != 0) + return (ret); + + /* + * If the page is an internal page use the page's count as it's + * up-to-date and reflects the status of cursors in the tree. + * If the page is a leaf page for unsorted duplicates, use the + * page's count as cursors don't mark items deleted on the page + * and wait, cursor delete items immediately. + * If the page is a leaf page for sorted duplicates, there may + * be cursors on the page marking deleted items -- count. + */ + if (TYPE(cp->page) == P_LDUP) + for (recno = 0, indx = 0, + top = NUM_ENT(cp->page) - O_INDX;; indx += O_INDX) { + if (!IS_DELETED(dbp, cp->page, indx)) + ++recno; + if (indx == top) + break; + } + else + recno = RE_NREC(cp->page); + } + + *recnop = recno; + + ret = __memp_fput(mpf, dbc->thread_info, cp->page, dbc->priority); + cp->page = NULL; + + return (ret); +} + +/* + * __bamc_del -- + * Delete using a cursor. + */ +static int +__bamc_del(dbc, flags) + DBC *dbc; + u_int32_t flags; +{ + BTREE_CURSOR *cp; + DB *dbp; + DB_MPOOLFILE *mpf; + int ret, t_ret; + u_int32_t count; + + dbp = dbc->dbp; + mpf = dbp->mpf; + cp = (BTREE_CURSOR *)dbc->internal; + ret = 0; + COMPQUIET(flags, 0); + + /* If the item was already deleted, return failure. */ + if (F_ISSET(cp, C_DELETED)) + return (DB_KEYEMPTY); + + /* + * This code is always called with a page lock but no page. + */ + DB_ASSERT(dbp->env, cp->page == NULL); + + if (F_ISSET(dbc, DBC_OPD)) + LOCK_CHECK_OFF(dbc->thread_info); + + /* + * We don't physically delete the record until the cursor moves, so + * we have to have a long-lived write lock on the page instead of a + * a long-lived read lock. Note, we have to have a read lock to even + * get here. + * + * If we're maintaining record numbers, we lock the entire tree, else + * we lock the single page. + */ + if (F_ISSET(cp, C_RECNUM)) { + if ((ret = __bamc_getstack(dbc)) != 0) + goto err; + cp->page = cp->csp->page; + } else { + ACQUIRE_CUR(dbc, DB_LOCK_WRITE, cp->pgno, 0, ret); + if (ret != 0) + goto err; + } + + /* Mark the page dirty. */ + if ((ret = __memp_dirty(mpf, + &cp->page, dbc->thread_info, dbc->txn, dbc->priority, 0)) != 0) + goto err; + + /* Log the change. */ + if (DBC_LOGGING(dbc)) { + if ((ret = __bam_cdel_log(dbp, dbc->txn, &LSN(cp->page), 0, + PGNO(cp->page), &LSN(cp->page), cp->indx)) != 0) + goto err; + } else + LSN_NOT_LOGGED(LSN(cp->page)); + + /* Set the intent-to-delete flag on the page. */ + if (TYPE(cp->page) == P_LBTREE) + B_DSET(GET_BKEYDATA(dbp, cp->page, cp->indx + O_INDX)->type); + else + B_DSET(GET_BKEYDATA(dbp, cp->page, cp->indx)->type); + +err: /* + * If we've been successful so far and the tree has record numbers, + * adjust the record counts. Either way, release acquired page(s). + */ + if (F_ISSET(cp, C_RECNUM)) { + cp->csp->page = cp->page; + if (ret == 0) + ret = __bam_adjust(dbc, -1); + (void)__bam_stkrel(dbc, 0); + } else + if (cp->page != NULL && + (t_ret = __memp_fput(mpf, dbc->thread_info, + cp->page, dbc->priority)) != 0 && ret == 0) + ret = t_ret; + + cp->page = NULL; + + /* + * Update the cursors last, after all chance of recoverable failure + * is past. + */ + if (ret == 0) + ret = __bam_ca_delete(dbp, cp->pgno, cp->indx, 1, &count); + + if (F_ISSET(dbc, DBC_OPD)) + LOCK_CHECK_ON(dbc->thread_info); + return (ret); +} + +/* + * __bamc_dup -- + * Duplicate a btree cursor, such that the new one holds appropriate + * locks for the position of the original. + * + * PUBLIC: int __bamc_dup __P((DBC *, DBC *, u_int32_t)); + */ +int +__bamc_dup(orig_dbc, new_dbc, flags) + DBC *orig_dbc, *new_dbc; + u_int32_t flags; +{ + BTREE_CURSOR *orig, *new; + + orig = (BTREE_CURSOR *)orig_dbc->internal; + new = (BTREE_CURSOR *)new_dbc->internal; + + new->ovflsize = orig->ovflsize; + new->recno = orig->recno; + new->flags = orig->flags; + +#ifdef HAVE_COMPRESSION + /* Copy the compression state */ + return (__bamc_compress_dup(orig_dbc, new_dbc, flags)); +#else + COMPQUIET(flags, 0); + + return (0); +#endif +} + +/* + * __bamc_get -- + * Get using a cursor (btree). + */ +static int +__bamc_get(dbc, key, data, flags, pgnop) + DBC *dbc; + DBT *key, *data; + u_int32_t flags; + db_pgno_t *pgnop; +{ + BTREE_CURSOR *cp; + DB *dbp; + DB_MPOOLFILE *mpf; + db_pgno_t orig_pgno; + db_indx_t orig_indx; + int exact, newopd, ret; + + dbp = dbc->dbp; + mpf = dbp->mpf; + cp = (BTREE_CURSOR *)dbc->internal; + orig_pgno = cp->pgno; + orig_indx = cp->indx; + + newopd = 0; + switch (flags) { + case DB_CURRENT: + /* It's not possible to return a deleted record. */ + if (F_ISSET(cp, C_DELETED)) { + ret = DB_KEYEMPTY; + goto err; + } + + /* + * Acquire the current page. We have at least a read-lock + * already. The caller may have set DB_RMW asking for a + * write lock, but upgrading to a write lock has no better + * chance of succeeding now instead of later, so don't try. + */ + if ((ret = __memp_fget(mpf, &cp->pgno, + dbc->thread_info, dbc->txn, 0, &cp->page)) != 0) + goto err; + break; + case DB_FIRST: + newopd = 1; + if ((ret = __bamc_search(dbc, + PGNO_INVALID, NULL, flags, &exact)) != 0) + goto err; + break; + case DB_GET_BOTH: + case DB_GET_BOTH_RANGE: + /* + * There are two ways to get here based on DBcursor->get + * with the DB_GET_BOTH/DB_GET_BOTH_RANGE flags set: + * + * 1. Searching a sorted off-page duplicate tree: do a tree + * search. + * + * 2. Searching btree: do a tree search. If it returns a + * reference to off-page duplicate tree, return immediately + * and let our caller deal with it. If the search doesn't + * return a reference to off-page duplicate tree, continue + * with an on-page search. + */ + if (F_ISSET(dbc, DBC_OPD)) { + if ((ret = __bamc_search( + dbc, PGNO_INVALID, data, flags, &exact)) != 0) + goto err; + if (flags == DB_GET_BOTH) { + if (!exact) { + ret = DB_NOTFOUND; + goto err; + } + break; + } + + /* + * We didn't require an exact match, so the search may + * may have returned an entry past the end of the page, + * or we may be referencing a deleted record. If so, + * move to the next entry. + */ + if ((cp->indx == NUM_ENT(cp->page) || + IS_CUR_DELETED(dbc)) && + (ret = __bamc_next(dbc, 1, 0)) != 0) + goto err; + } else { + if ((ret = __bamc_search( + dbc, PGNO_INVALID, key, flags, &exact)) != 0) + return (ret); + if (!exact) { + ret = DB_NOTFOUND; + goto err; + } + + if (pgnop != NULL && __bam_isopd(dbc, pgnop)) { + newopd = 1; + break; + } + if ((ret = + __bam_getboth_finddatum(dbc, data, flags)) != 0) + goto err; + } + break; +#ifdef HAVE_COMPRESSION + case DB_SET_LTE: + if ((ret = __bam_getlte(dbc, key, NULL)) != 0) + goto err; + break; + case DB_GET_BOTH_LTE: + if ((ret = __bam_getlte(dbc, key, data)) != 0) + goto err; + break; +#endif + case DB_GET_BOTHC: + if ((ret = __bam_getbothc(dbc, data)) != 0) + goto err; + break; + case DB_LAST: + newopd = 1; + if ((ret = __bamc_search(dbc, + PGNO_INVALID, NULL, flags, &exact)) != 0) + goto err; + break; + case DB_NEXT: + newopd = 1; + if (cp->pgno == PGNO_INVALID) { + if ((ret = __bamc_search(dbc, + PGNO_INVALID, NULL, DB_FIRST, &exact)) != 0) + goto err; + } else + if ((ret = __bamc_next(dbc, 1, 0)) != 0) + goto err; + break; + case DB_NEXT_DUP: + if ((ret = __bamc_next(dbc, 1, 0)) != 0) + goto err; + if (!IS_CUR_DUPLICATE(dbc, orig_pgno, orig_indx)) { + ret = DB_NOTFOUND; + goto err; + } + break; + case DB_NEXT_NODUP: + newopd = 1; + if (cp->pgno == PGNO_INVALID) { + if ((ret = __bamc_search(dbc, + PGNO_INVALID, NULL, DB_FIRST, &exact)) != 0) + goto err; + } else + do { + if ((ret = __bamc_next(dbc, 1, 0)) != 0) + goto err; + } while (IS_CUR_DUPLICATE(dbc, orig_pgno, orig_indx)); + break; + case DB_PREV: + newopd = 1; + if (cp->pgno == PGNO_INVALID) { + if ((ret = __bamc_search(dbc, + PGNO_INVALID, NULL, DB_LAST, &exact)) != 0) + goto err; + } else + if ((ret = __bamc_prev(dbc)) != 0) + goto err; + break; + case DB_PREV_DUP: + if ((ret = __bamc_prev(dbc)) != 0) + goto err; + if (!IS_CUR_DUPLICATE(dbc, orig_pgno, orig_indx)) { + ret = DB_NOTFOUND; + goto err; + } + break; + case DB_PREV_NODUP: + newopd = 1; + if (cp->pgno == PGNO_INVALID) { + if ((ret = __bamc_search(dbc, + PGNO_INVALID, NULL, DB_LAST, &exact)) != 0) + goto err; + } else + do { + if ((ret = __bamc_prev(dbc)) != 0) + goto err; + } while (IS_CUR_DUPLICATE(dbc, orig_pgno, orig_indx)); + break; + case DB_SET: + case DB_SET_RECNO: + newopd = 1; + if ((ret = __bamc_search(dbc, + PGNO_INVALID, key, flags, &exact)) != 0) + goto err; + break; + case DB_SET_RANGE: + newopd = 1; + if ((ret = __bamc_search(dbc, + PGNO_INVALID, key, flags, &exact)) != 0) + goto err; + + /* + * As we didn't require an exact match, the search function + * may have returned an entry past the end of the page. Or, + * we may be referencing a deleted record. If so, move to + * the next entry. + */ + if (cp->indx == NUM_ENT(cp->page) || IS_CUR_DELETED(dbc)) + if ((ret = __bamc_next(dbc, 0, 0)) != 0) + goto err; + break; + default: + ret = __db_unknown_flag(dbp->env, "__bamc_get", flags); + goto err; + } + + /* + * We may have moved to an off-page duplicate tree. Return that + * information to our caller. + */ + if (newopd && pgnop != NULL) + (void)__bam_isopd(dbc, pgnop); + +err: /* + * Regardless of whether we were successful or not, if the cursor + * moved, clear the delete flag, DBcursor->get never references a + * deleted key, if it moved at all. + */ + if (F_ISSET(cp, C_DELETED) && + (cp->pgno != orig_pgno || cp->indx != orig_indx)) + F_CLR(cp, C_DELETED); + + return (ret); +} + +static int +__bam_get_prev(dbc) + DBC *dbc; +{ + BTREE_CURSOR *cp; + DBT key, data; + db_pgno_t pgno; + int ret; + + if ((ret = __bamc_prev(dbc)) != 0) + return (ret); + + if (__bam_isopd(dbc, &pgno)) { + cp = (BTREE_CURSOR *)dbc->internal; + if ((ret = __dbc_newopd(dbc, pgno, cp->opd, &cp->opd)) != 0) + return (ret); + if ((ret = cp->opd->am_get(cp->opd, + &key, &data, DB_LAST, NULL)) != 0) + return (ret); + } + + return (0); +} + +/* + * __bam_bulk -- Return bulk data from a btree. + */ +static int +__bam_bulk(dbc, data, flags) + DBC *dbc; + DBT *data; + u_int32_t flags; +{ + BKEYDATA *bk; + BOVERFLOW *bo; + BTREE_CURSOR *cp; + PAGE *pg; + db_indx_t *inp, indx, pg_keyoff; + int32_t *endp, key_off, *offp, *saveoffp; + u_int8_t *dbuf, *dp, *np; + u_int32_t key_size, pagesize, size, space; + int adj, is_key, need_pg, next_key, no_dup, rec_key, ret; + + ret = 0; + key_off = 0; + size = 0; + pagesize = dbc->dbp->pgsize; + cp = (BTREE_CURSOR *)dbc->internal; + + /* + * dp tracks the beginning of the page in the buffer. + * np is the next place to copy things into the buffer. + * dbuf always stays at the beginning of the buffer. + */ + dbuf = data->data; + np = dp = dbuf; + + /* Keep track of space that is left. There is a termination entry */ + space = data->ulen; + space -= sizeof(*offp); + + /* Build the offset/size table from the end up. */ + endp = (int32_t *)((u_int8_t *)dbuf + data->ulen); + endp--; + offp = endp; + + key_size = 0; + + /* + * Distinguish between BTREE and RECNO. + * There are no keys in RECNO. If MULTIPLE_KEY is specified + * then we return the record numbers. + * is_key indicates that multiple btree keys are returned. + * rec_key is set if we are returning record numbers. + * next_key is set if we are going after the next key rather than dup. + */ + if (dbc->dbtype == DB_BTREE) { + is_key = LF_ISSET(DB_MULTIPLE_KEY) ? 1: 0; + rec_key = 0; + next_key = is_key && LF_ISSET(DB_OPFLAGS_MASK) != DB_NEXT_DUP; + adj = 2; + } else { + is_key = 0; + rec_key = LF_ISSET(DB_MULTIPLE_KEY) ? 1 : 0; + next_key = LF_ISSET(DB_OPFLAGS_MASK) != DB_NEXT_DUP; + adj = 1; + } + no_dup = LF_ISSET(DB_OPFLAGS_MASK) == DB_NEXT_NODUP; + +next_pg: + indx = cp->indx; + pg = cp->page; + + inp = P_INP(dbc->dbp, pg); + /* The current page is not yet in the buffer. */ + need_pg = 1; + + /* + * Keep track of the offset of the current key on the page. + * If we are returning keys, set it to 0 first so we force + * the copy of the key to the buffer. + */ + pg_keyoff = 0; + if (is_key == 0) + pg_keyoff = inp[indx]; + + do { + if (IS_DELETED(dbc->dbp, pg, indx)) { + if (dbc->dbtype != DB_RECNO) + continue; + + cp->recno++; + /* + * If we are not returning recnos then we + * need to fill in every slot so the user + * can calculate the record numbers. + */ + if (rec_key != 0) + continue; + + space -= 2 * sizeof(*offp); + /* Check if space as underflowed. */ + if (space > data->ulen) + goto back_up; + + /* Just mark the empty recno slots. */ + *offp-- = 0; + *offp-- = 0; + continue; + } + + /* + * Check to see if we have a new key. + * If so, then see if we need to put the + * key on the page. If its already there + * then we just point to it. + */ + if (is_key && pg_keyoff != inp[indx]) { + bk = GET_BKEYDATA(dbc->dbp, pg, indx); + if (B_TYPE(bk->type) == B_OVERFLOW) { + bo = (BOVERFLOW *)bk; + size = key_size = bo->tlen; + if (key_size > space) + goto get_key_space; + if ((ret = __bam_bulk_overflow(dbc, + bo->tlen, bo->pgno, np)) != 0) + return (ret); + space -= key_size; + key_off = (int32_t)(np - dbuf); + np += key_size; + } else { + if (need_pg) { + dp = np; + size = pagesize - HOFFSET(pg); + if (space < size) { +get_key_space: + /* Nothing added, then error. */ + if (offp == endp) { + data->size = (u_int32_t) + DB_ALIGN(size + + pagesize, 1024); + return + (DB_BUFFER_SMALL); + } + /* + * We need to back up to the + * last record put into the + * buffer so that it is + * CURRENT. + */ + if (indx != 0) + indx -= P_INDX; + else { + if ((ret = + __bam_get_prev( + dbc)) != 0) + return (ret); + indx = cp->indx; + pg = cp->page; + } + break; + } + /* + * Move the data part of the page + * to the buffer. + */ + memcpy(dp, + (u_int8_t *)pg + HOFFSET(pg), size); + need_pg = 0; + space -= size; + np += size; + } + key_size = bk->len; + key_off = (int32_t)((inp[indx] - HOFFSET(pg)) + + (dp - dbuf) + SSZA(BKEYDATA, data)); + pg_keyoff = inp[indx]; + } + } + + /* + * Reserve space for the pointers and sizes. + * Either key/data pair or just for a data item. + */ + space -= (is_key ? 4 : 2) * sizeof(*offp); + if (rec_key) + space -= sizeof(*offp); + + /* Check to see if space has underflowed. */ + if (space > data->ulen) + goto back_up; + + /* + * Determine if the next record is in the + * buffer already or if it needs to be copied in. + * If we have an off page dup, then copy as many + * as will fit into the buffer. + */ + bk = GET_BKEYDATA(dbc->dbp, pg, indx + adj - 1); + if (B_TYPE(bk->type) == B_DUPLICATE) { + bo = (BOVERFLOW *)bk; + if (is_key) { + *offp-- = (int32_t)key_off; + *offp-- = (int32_t)key_size; + } + /* + * We pass the offset of the current key. + * On return we check to see if offp has + * moved to see if any data fit. + */ + saveoffp = offp; + if ((ret = __bam_bulk_duplicates(dbc, bo->pgno, + dbuf, is_key ? offp + P_INDX : NULL, + &offp, &np, &space, no_dup)) != 0) { + if (ret == DB_BUFFER_SMALL) { + size = space; + space = 0; + /* If nothing was added, then error. */ + if (offp == saveoffp) { + offp += 2; + goto back_up; + } + goto get_space; + } + return (ret); + } + } else if (B_TYPE(bk->type) == B_OVERFLOW) { + bo = (BOVERFLOW *)bk; + size = bo->tlen; + if (size > space) + goto back_up; + if ((ret = + __bam_bulk_overflow(dbc, + bo->tlen, bo->pgno, np)) != 0) + return (ret); + space -= size; + if (is_key) { + *offp-- = (int32_t)key_off; + *offp-- = (int32_t)key_size; + } else if (rec_key) + *offp-- = (int32_t)cp->recno; + *offp-- = (int32_t)(np - dbuf); + np += size; + *offp-- = (int32_t)size; + } else { + if (need_pg) { + dp = np; + size = pagesize - HOFFSET(pg); + if (space < size) { +back_up: + /* + * Back up the index so that the + * last record in the buffer is CURRENT + */ + if (indx >= adj) + indx -= adj; + else { + if ((ret = + __bam_get_prev(dbc)) != 0 && + ret != DB_NOTFOUND) + return (ret); + indx = cp->indx; + pg = cp->page; + } + if (dbc->dbtype == DB_RECNO) + cp->recno--; +get_space: + /* + * See if we put anything in the + * buffer or if we are doing a DBP->get + * did we get all of the data. + */ + if (offp >= + (is_key ? &endp[-1] : endp) || + F_ISSET(dbc, DBC_FROM_DB_GET)) { + data->size = (u_int32_t) + DB_ALIGN(size + + data->ulen - space, 1024); + return (DB_BUFFER_SMALL); + } + break; + } + memcpy(dp, (u_int8_t *)pg + HOFFSET(pg), size); + need_pg = 0; + space -= size; + np += size; + } + /* + * Add the offsets and sizes to the end of the buffer. + * First add the key info then the data info. + */ + if (is_key) { + *offp-- = (int32_t)key_off; + *offp-- = (int32_t)key_size; + } else if (rec_key) + *offp-- = (int32_t)cp->recno; + *offp-- = (int32_t)((inp[indx + adj - 1] - HOFFSET(pg)) + + (dp - dbuf) + SSZA(BKEYDATA, data)); + *offp-- = bk->len; + } + if (dbc->dbtype == DB_RECNO) + cp->recno++; + else if (no_dup) { + while (indx + adj < NUM_ENT(pg) && + pg_keyoff == inp[indx + adj]) + indx += adj; + } + /* + * Stop when we either run off the page or we move to the next key and + * we are not returning multiple keys. + */ + } while ((indx += adj) < NUM_ENT(pg) && + (next_key || pg_keyoff == inp[indx])); + + /* If we are off the page then try to the next page. */ + if (ret == 0 && next_key && indx >= NUM_ENT(pg)) { + cp->indx = indx; + ret = __bamc_next(dbc, 0, 1); + if (ret == 0) + goto next_pg; + if (ret != DB_NOTFOUND) + return (ret); + } + + /* + * If we did a DBP->get we must error if we did not return + * all the data for the current key because there is + * no way to know if we did not get it all, nor any + * interface to fetch the balance. + */ + + if (ret == 0 && indx < pg->entries && + F_ISSET(dbc, DBC_TRANSIENT) && pg_keyoff == inp[indx]) { + data->size = (data->ulen - space) + size; + return (DB_BUFFER_SMALL); + } + /* + * Must leave the index pointing at the last record fetched. + * If we are not fetching keys, we may have stepped to the + * next key. + */ + if (ret == DB_BUFFER_SMALL || next_key || pg_keyoff == inp[indx]) + cp->indx = indx; + else + cp->indx = indx - P_INDX; + + if (rec_key == 1) + *offp = RECNO_OOB; + else + *offp = -1; + return (0); +} + +/* + * __bam_bulk_overflow -- + * Dump overflow record into the buffer. + * The space requirements have already been checked. + * PUBLIC: int __bam_bulk_overflow + * PUBLIC: __P((DBC *, u_int32_t, db_pgno_t, u_int8_t *)); + */ +int +__bam_bulk_overflow(dbc, len, pgno, dp) + DBC *dbc; + u_int32_t len; + db_pgno_t pgno; + u_int8_t *dp; +{ + DBT dbt; + + memset(&dbt, 0, sizeof(dbt)); + F_SET(&dbt, DB_DBT_USERMEM); + dbt.ulen = len; + dbt.data = (void *)dp; + return (__db_goff(dbc, &dbt, len, pgno, NULL, NULL)); +} + +/* + * __bam_bulk_duplicates -- + * Put as many off page duplicates as will fit into the buffer. + * This routine will adjust the cursor to reflect the position in + * the overflow tree. + * PUBLIC: int __bam_bulk_duplicates __P((DBC *, + * PUBLIC: db_pgno_t, u_int8_t *, int32_t *, + * PUBLIC: int32_t **, u_int8_t **, u_int32_t *, int)); + */ +int +__bam_bulk_duplicates(dbc, pgno, dbuf, keyoff, offpp, dpp, spacep, no_dup) + DBC *dbc; + db_pgno_t pgno; + u_int8_t *dbuf; + int32_t *keyoff, **offpp; + u_int8_t **dpp; + u_int32_t *spacep; + int no_dup; +{ + BKEYDATA *bk; + BOVERFLOW *bo; + BTREE_CURSOR *cp; + DB *dbp; + DBC *opd; + DBT key, data; + PAGE *pg; + db_indx_t indx, *inp; + int32_t *offp; + u_int32_t pagesize, size, space; + u_int8_t *dp, *np; + int first, need_pg, ret, t_ret; + + ret = 0; + + dbp = dbc->dbp; + cp = (BTREE_CURSOR *)dbc->internal; + opd = cp->opd; + + if (opd == NULL) { + if ((ret = __dbc_newopd(dbc, pgno, NULL, &opd)) != 0) + return (ret); + cp->opd = opd; + if ((ret = opd->am_get(opd, + &key, &data, DB_FIRST, NULL)) != 0) + goto close_opd; + } + + pagesize = opd->dbp->pgsize; + cp = (BTREE_CURSOR *)opd->internal; + space = *spacep; + /* Get current offset slot. */ + offp = *offpp; + + /* + * np is the next place to put data. + * dp is the beginning of the current page in the buffer. + */ + np = dp = *dpp; + first = 1; + indx = cp->indx; + + do { + /* Fetch the current record. No initial move. */ + if ((ret = __bamc_next(opd, 0, 0)) != 0) + break; + pg = cp->page; + indx = cp->indx; + inp = P_INP(dbp, pg); + /* We need to copy the page to the buffer. */ + need_pg = 1; + + do { + if (IS_DELETED(dbp, pg, indx)) + goto contin; + bk = GET_BKEYDATA(dbp, pg, indx); + space -= 2 * sizeof(*offp); + /* Allocate space for key if needed. */ + if (first == 0 && keyoff != NULL) + space -= 2 * sizeof(*offp); + + /* Did space underflow? */ + if (space > *spacep) { + ret = DB_BUFFER_SMALL; + if (first == 1) { + /* Get the absolute value. */ + space = -(int32_t)space; + space = *spacep + space; + if (need_pg) + space += pagesize - HOFFSET(pg); + } + break; + } + if (B_TYPE(bk->type) == B_OVERFLOW) { + bo = (BOVERFLOW *)bk; + size = bo->tlen; + if (size > space) { + ret = DB_BUFFER_SMALL; + space = *spacep + size; + break; + } + if (first == 0 && keyoff != NULL) { + *offp-- = keyoff[0]; + *offp-- = keyoff[-1]; + } + if ((ret = __bam_bulk_overflow(dbc, + bo->tlen, bo->pgno, np)) != 0) + return (ret); + space -= size; + *offp-- = (int32_t)(np - dbuf); + np += size; + } else { + if (need_pg) { + dp = np; + size = pagesize - HOFFSET(pg); + if (space < size) { + ret = DB_BUFFER_SMALL; + /* Return space required. */ + space = *spacep + size; + break; + } + memcpy(dp, + (u_int8_t *)pg + HOFFSET(pg), size); + need_pg = 0; + space -= size; + np += size; + } + if (first == 0 && keyoff != NULL) { + *offp-- = keyoff[0]; + *offp-- = keyoff[-1]; + } + size = bk->len; + *offp-- = (int32_t)((inp[indx] - HOFFSET(pg)) + + (dp - dbuf) + SSZA(BKEYDATA, data)); + } + *offp-- = (int32_t)size; + first = 0; + if (no_dup) + break; +contin: + indx++; + if (opd->dbtype == DB_RECNO) + cp->recno++; + } while (indx < NUM_ENT(pg)); + if (no_dup) + break; + cp->indx = indx; + + } while (ret == 0); + + /* Return the updated information. */ + *spacep = space; + *offpp = offp; + *dpp = np; + + /* + * If we ran out of space back up the pointer. + * If we did not return any dups or reached the end, close the opd. + */ + if (ret == DB_BUFFER_SMALL) { + if (opd->dbtype == DB_RECNO) { + if (--cp->recno == 0) + goto close_opd; + } else if (indx != 0) + cp->indx--; + else { + t_ret = __bamc_prev(opd); + if (t_ret == DB_NOTFOUND) + goto close_opd; + if (t_ret != 0) + ret = t_ret; + } + } else if (keyoff == NULL && ret == DB_NOTFOUND) { + cp->indx--; + if (opd->dbtype == DB_RECNO) + --cp->recno; + } else if (indx == 0 || ret == DB_NOTFOUND) { +close_opd: + if (ret == DB_NOTFOUND) + ret = 0; + if ((t_ret = __dbc_close(opd)) != 0 && ret == 0) + ret = t_ret; + ((BTREE_CURSOR *)dbc->internal)->opd = NULL; + } + if (ret == DB_NOTFOUND) + ret = 0; + + return (ret); +} + +/* + * __bam_getbothc -- + * Search for a matching data item on a join. + */ +static int +__bam_getbothc(dbc, data) + DBC *dbc; + DBT *data; +{ + BTREE_CURSOR *cp; + DB *dbp; + DB_MPOOLFILE *mpf; + int cmp, exact, ret; + + dbp = dbc->dbp; + mpf = dbp->mpf; + cp = (BTREE_CURSOR *)dbc->internal; + + /* + * Acquire the current page. We have at least a read-lock + * already. The caller may have set DB_RMW asking for a + * write lock, but upgrading to a write lock has no better + * chance of succeeding now instead of later, so don't try. + */ + if ((ret = __memp_fget(mpf, &cp->pgno, + dbc->thread_info, dbc->txn, 0, &cp->page)) != 0) + return (ret); + + /* + * An off-page duplicate cursor. Search the remaining duplicates + * for one which matches (do a normal btree search, then verify + * that the retrieved record is greater than the original one). + */ + if (F_ISSET(dbc, DBC_OPD)) { + /* + * Check to make sure the desired item comes strictly after + * the current position; if it doesn't, return DB_NOTFOUND. + */ + if ((ret = __bam_cmp(dbc, data, cp->page, cp->indx, + dbp->dup_compare == NULL ? __bam_defcmp : dbp->dup_compare, + &cmp)) != 0) + return (ret); + + if (cmp <= 0) + return (DB_NOTFOUND); + + /* Discard the current page, we're going to do a full search. */ + if ((ret = __memp_fput(mpf, + dbc->thread_info, cp->page, dbc->priority)) != 0) + return (ret); + cp->page = NULL; + + return (__bamc_search(dbc, + PGNO_INVALID, data, DB_GET_BOTH, &exact)); + } + + /* + * We're doing a DBC->get(DB_GET_BOTHC) and we're already searching + * a set of on-page duplicates (either sorted or unsorted). Continue + * a linear search from after the current position. + * + * (Note that we could have just finished a "set" of one duplicate, + * i.e. not a duplicate at all, but the following check will always + * return DB_NOTFOUND in this case, which is the desired behavior.) + */ + if (cp->indx + P_INDX >= NUM_ENT(cp->page) || + !IS_DUPLICATE(dbc, cp->indx, cp->indx + P_INDX)) + return (DB_NOTFOUND); + cp->indx += P_INDX; + + return (__bam_getboth_finddatum(dbc, data, DB_GET_BOTH)); +} + +#ifdef HAVE_COMPRESSION +/* + * __bam_getlte -- + * Search for the largest entry <= key/data - used by compression. + * + * data == NULL indicates the DB_SET_LTE flag + * data != NULL indicates the DB_GET_BOTH_LTE flag + * + * Only works for a primary cursor - not an OPD cursor. Handles the + * OPD manipulation as well - no need to return to the caller to + * perform more OPD movements. + */ +static int +__bam_getlte(dbc, key, data) + DBC *dbc; + DBT *key, *data; +{ + BTREE_CURSOR *cp, *ocp; + DB *dbp; + db_pgno_t pgno; + int exact, ret; + + dbp = dbc->dbp; + cp = (BTREE_CURSOR *)dbc->internal; + + /* Begin by searching for the key */ + ret = __bamc_search(dbc, PGNO_INVALID, key, DB_SET_RANGE, &exact); + if (ret == DB_NOTFOUND) + goto find_last; + if (ret != 0) + goto end; + + if (cp->indx == NUM_ENT(cp->page) || IS_CUR_DELETED(dbc)) { + /* + * Move to the next entry if we're past the end of the + * page or on a deleted entry. + */ + ret = __bamc_next(dbc, 0, 0); + if (ret == DB_NOTFOUND) + goto find_last; + if (ret != 0) + goto end; + + /* Check if we're still on the correct key */ + if ((ret = __bam_cmp(dbc, key, cp->page, cp->indx, + ((BTREE*)dbp->bt_internal)->bt_compare, &exact)) != 0) + goto end; + exact = (exact == 0); + } + + if (exact == 0) { + ret = __bam_get_prev(dbc); + goto end; + } + + if (__bam_isopd(dbc, &pgno)) { + /* + * We want to do unusual things with off-page duplicates, so + * deal with them here rather than returning to handle them. + */ + if ((ret = __dbc_newopd(dbc, pgno, cp->opd, &cp->opd)) != 0) + goto end; + + /* Search for the correct duplicate */ + ret = __bamc_search(cp->opd, PGNO_INVALID, data, + data == NULL ? DB_FIRST : DB_SET_RANGE, &exact); + if (ret == DB_NOTFOUND) + goto find_last_dup; + if (ret != 0) + goto end; + + ocp = (BTREE_CURSOR *)cp->opd->internal; + if (ocp->indx == NUM_ENT(ocp->page) || + IS_CUR_DELETED(cp->opd)) { + /* + * Move to the next entry if we're past the end of the + * page or on a deleted entry. + */ + ret = __bamc_next(cp->opd, 0, 0); + if (ret == DB_NOTFOUND) + goto find_last_dup; + if (ret != 0) + goto end; + + if (data != NULL) { + /* Check if we're still on the correct data */ + if ((ret = __bam_cmp( + dbc, data, ocp->page, ocp->indx, + dbp->dup_compare, &exact)) != 0) + goto end; + exact = (exact == 0); + } else + exact = 1; + } + + if (exact == 0) { + /* Move to the previous entry */ + ret = __bamc_prev(cp->opd); + if (ret == DB_NOTFOUND) { + if ((ret = __dbc_close(cp->opd)) != 0) + goto end; + cp->opd = NULL; + ret = __bam_get_prev(dbc); + } + } + } else if (data != NULL) { + /* + * If we got an exact match with on-page duplicates, we need to + * search in them. + */ + ret = __bam_getboth_finddatum(dbc, data, DB_GET_BOTH_RANGE); + if (ret == DB_NOTFOUND) + exact = 0; + else if (ret != 0) + goto end; + else { + /* Check if we're still on the correct data */ + if ((ret = __bam_cmp(dbc, data, cp->page, + cp->indx + O_INDX, dbp->dup_compare, &exact)) != 0) + goto end; + exact = (exact == 0); + } + + if (exact == 0) { + ret = __bam_get_prev(dbc); + } + } + + end: + return (ret); + + find_last: + if ((ret = __bamc_search( + dbc, PGNO_INVALID, NULL, DB_LAST, &exact)) != 0) + return (ret); + + if (__bam_isopd(dbc, &pgno)) { + if ((ret = __dbc_newopd(dbc, pgno, cp->opd, &cp->opd)) != 0) + return (ret); + find_last_dup: + if ((ret = __bamc_search( + cp->opd, PGNO_INVALID, NULL, DB_LAST, &exact)) != 0) + return (ret); + } + + return (ret); +} +#endif + +/* + * __bam_getboth_finddatum -- + * Find a matching on-page data item. + */ +static int +__bam_getboth_finddatum(dbc, data, flags) + DBC *dbc; + DBT *data; + u_int32_t flags; +{ + BTREE_CURSOR *cp; + DB *dbp; + db_indx_t base, lim, top; + int cmp, ret; + + dbp = dbc->dbp; + cp = (BTREE_CURSOR *)dbc->internal; + + cmp = 0; + + /* + * Called (sometimes indirectly) from DBC->get to search on-page data + * item(s) for a matching value. If the original flag was DB_GET_BOTH + * or DB_GET_BOTH_RANGE, the cursor is set to the first undeleted data + * item for the key. If the original flag was DB_GET_BOTHC, the cursor + * argument is set to the first data item we can potentially return. + * In both cases, there may or may not be additional duplicate data + * items to search. + * + * If the duplicates are not sorted, do a linear search. + */ + if (dbp->dup_compare == NULL) { + for (;; cp->indx += P_INDX) { + if (!IS_CUR_DELETED(dbc)) { + if ((ret = __bam_cmp( + dbc, data, cp->page, cp->indx + O_INDX, + __bam_defcmp, &cmp)) != 0) + return (ret); + if (cmp == 0) + return (0); + } + + if (cp->indx + P_INDX >= NUM_ENT(cp->page) || + !IS_DUPLICATE(dbc, cp->indx, cp->indx + P_INDX)) + break; + } + return (DB_NOTFOUND); + } + + /* + * If the duplicates are sorted, do a binary search. The reason for + * this is that large pages and small key/data pairs result in large + * numbers of on-page duplicates before they get pushed off-page. + * + * Find the top and bottom of the duplicate set. Binary search + * requires at least two items, don't loop if there's only one. + */ + for (base = top = cp->indx; top < NUM_ENT(cp->page); top += P_INDX) + if (!IS_DUPLICATE(dbc, cp->indx, top)) + break; + if (base == (top - P_INDX)) { + if ((ret = __bam_cmp(dbc, data, cp->page, + cp->indx + O_INDX, dbp->dup_compare, &cmp)) != 0) + return (ret); + if (cmp == 0 || (cmp < 0 && flags == DB_GET_BOTH_RANGE)) + return (0); + cp->indx = top; + return DB_NOTFOUND; + } + + for (lim = (top - base) / (db_indx_t)P_INDX; lim != 0; lim >>= 1) { + cp->indx = base + ((lim >> 1) * P_INDX); + if ((ret = __bam_cmp(dbc, data, cp->page, + cp->indx + O_INDX, dbp->dup_compare, &cmp)) != 0) + return (ret); + if (cmp == 0) { + /* + * XXX + * No duplicate duplicates in sorted duplicate sets, + * so there can be only one. + */ + if (!IS_CUR_DELETED(dbc)) + return (0); + break; + } + if (cmp > 0) { + base = cp->indx + P_INDX; + --lim; + } + } + + /* No match found; if we're looking for an exact match, we're done. */ + if (flags == DB_GET_BOTH) + return (DB_NOTFOUND); + + /* + * Base is the smallest index greater than the data item, may be zero + * or a last + O_INDX index, and may be deleted. Find an undeleted + * item. + */ + cp->indx = base; + while (cp->indx < top && IS_CUR_DELETED(dbc)) + cp->indx += P_INDX; + return (cp->indx < top ? 0 : DB_NOTFOUND); +} + +/* + * __bamc_put -- + * Put using a cursor. + */ +static int +__bamc_put(dbc, key, data, flags, pgnop) + DBC *dbc; + DBT *key, *data; + u_int32_t flags; + db_pgno_t *pgnop; +{ + BTREE *t; + BTREE_CURSOR *cp; + DB *dbp; + DBT dbt; + DB_MPOOLFILE *mpf; + db_pgno_t root_pgno; + int cmp, exact, own, ret, stack; + u_int32_t iiop; + void *arg; + + dbp = dbc->dbp; + mpf = dbp->mpf; + cp = (BTREE_CURSOR *)dbc->internal; + root_pgno = cp->root; + +split: ret = stack = 0; + switch (flags) { + case DB_CURRENT: + if (F_ISSET(cp, C_DELETED)) + return (DB_NOTFOUND); + /* FALLTHROUGH */ + case DB_AFTER: + case DB_BEFORE: + iiop = flags; + own = 1; + + /* Acquire the current page with a write lock. */ + ACQUIRE_WRITE_LOCK(dbc, ret); + if (ret != 0) + goto err; + if (cp->page == NULL && (ret = __memp_fget(mpf, &cp->pgno, + dbc->thread_info, dbc->txn, 0, &cp->page)) != 0) + goto err; + break; + case DB_KEYFIRST: + case DB_KEYLAST: + case DB_NODUPDATA: + case DB_NOOVERWRITE: + case DB_OVERWRITE_DUP: + own = 0; + /* + * Searching off-page, sorted duplicate tree: do a tree search + * for the correct item; __bamc_search returns the smallest + * slot greater than the key, use it. + * + * See comment below regarding where we can start the search. + */ + if (F_ISSET(dbc, DBC_OPD)) { + if ((ret = __bamc_search(dbc, + F_ISSET(cp, C_RECNUM) ? cp->root : root_pgno, + data, flags, &exact)) != 0) + goto err; + stack = 1; + + /* Disallow "sorted" duplicate duplicates. */ + if (exact != 0) { + if (flags == DB_OVERWRITE_DUP || + IS_DELETED(dbp, cp->page, cp->indx)) { + iiop = DB_CURRENT; + break; + } + ret = __db_duperr(dbp, flags); + goto err; + } + iiop = DB_BEFORE; + break; + } + + /* + * Searching a btree. + * + * If we've done a split, we can start the search from the + * parent of the split page, which __bam_split returned + * for us in root_pgno, unless we're in a Btree with record + * numbering. In that case, we'll need the true root page + * in order to adjust the record count. + */ + if ((ret = __bamc_search(dbc, + F_ISSET(cp, C_RECNUM) ? cp->root : root_pgno, key, + flags == DB_KEYFIRST || dbp->dup_compare != NULL ? + DB_KEYFIRST : DB_KEYLAST, &exact)) != 0) + goto err; + stack = 1; + + /* + * If we don't have an exact match, __bamc_search returned + * the smallest slot greater than the key, use it. + */ + if (!exact) { + iiop = DB_KEYFIRST; + break; + + /* + * Check for NOOVERWRITE. It is possible that there + * is a key with an empty duplicate page attached. + */ + } else if (flags == DB_NOOVERWRITE && !IS_CUR_DELETED(dbc)) { + if (pgnop != NULL && __bam_isopd(dbc, pgnop)) + ret = __bam_opd_exists(dbc, *pgnop); + else + ret = DB_KEYEXIST; + if (ret != 0) + goto err; + } + + /* + * If duplicates aren't supported, replace the current item. + */ + if (!F_ISSET(dbp, DB_AM_DUP)) { + iiop = DB_CURRENT; + break; + } + + /* + * If we find a matching entry, it may be an off-page duplicate + * tree. Return the page number to our caller, we need a new + * cursor. + */ + if (pgnop != NULL && __bam_isopd(dbc, pgnop)) + goto done; + + /* If the duplicates aren't sorted, move to the right slot. */ + if (dbp->dup_compare == NULL) { + if (flags == DB_KEYFIRST) + iiop = DB_BEFORE; + else + for (;; cp->indx += P_INDX) + if (cp->indx + P_INDX >= + NUM_ENT(cp->page) || + !IS_DUPLICATE(dbc, cp->indx, + cp->indx + P_INDX)) { + iiop = DB_AFTER; + break; + } + break; + } + + /* + * We know that we're looking at the first of a set of sorted + * on-page duplicates. Walk the list to find the right slot. + */ + for (;; cp->indx += P_INDX) { + if ((ret = __bam_cmp(dbc, data, cp->page, + cp->indx + O_INDX, dbp->dup_compare, &cmp)) != 0) + goto err; + if (cmp < 0) { + iiop = DB_BEFORE; + break; + } + + /* Disallow "sorted" duplicate duplicates. */ + if (cmp == 0) { + if (flags == DB_OVERWRITE_DUP || + IS_DELETED(dbp, cp->page, cp->indx)) { + iiop = DB_CURRENT; + break; + } + ret = __db_duperr(dbp, flags); + goto err; + } + + if (cp->indx + P_INDX >= NUM_ENT(cp->page) || + P_INP(dbp, ((PAGE *)cp->page))[cp->indx] != + P_INP(dbp, ((PAGE *)cp->page))[cp->indx + P_INDX]) { + iiop = DB_AFTER; + break; + } + } + break; + default: + ret = __db_unknown_flag(dbp->env, "__bamc_put", flags); + goto err; + } + + switch (ret = __bam_iitem(dbc, key, data, iiop, 0)) { + case 0: + break; + case DB_NEEDSPLIT: + /* + * To split, we need a key for the page. Either use the key + * argument or get a copy of the key from the page. + */ + if (flags == DB_AFTER || + flags == DB_BEFORE || flags == DB_CURRENT) { + memset(&dbt, 0, sizeof(DBT)); + if ((ret = __db_ret(dbc, cp->page, 0, &dbt, + &dbc->my_rkey.data, &dbc->my_rkey.ulen)) != 0) + goto err; + arg = &dbt; + } else + arg = F_ISSET(dbc, DBC_OPD) ? data : key; + + /* + * Discard any locks and pinned pages (the locks are discarded + * even if we're running with transactions, as they lock pages + * that we're sorry we ever acquired). If stack is set and the + * cursor entries are valid, they point to the same entries as + * the stack, don't free them twice. + */ + if (stack) + ret = __bam_stkrel(dbc, STK_CLRDBC | STK_NOLOCK); + else + DISCARD_CUR(dbc, ret); + if (ret != 0) + goto err; + + /* + * SR [#6059] + * If we do not own a lock on the page any more, then clear the + * cursor so we don't point at it. Even if we call __bam_stkrel + * above we still may have entered the routine with the cursor + * positioned to a particular record. This is in the case + * where C_RECNUM is set. + */ + if (own == 0) { + cp->pgno = PGNO_INVALID; + cp->indx = 0; + } + + /* Split the tree. */ + if ((ret = __bam_split(dbc, arg, &root_pgno)) != 0) + return (ret); + + goto split; + default: + goto err; + } + +err: +done: /* + * If we inserted a key into the first or last slot of the tree, + * remember where it was so we can do it more quickly next time. + * If the tree has record numbers, we need a complete stack so + * that we can adjust the record counts, so skipping the tree search + * isn't possible. For subdatabases we need to be careful that the + * page does not move from one db to another, so we track its LSN. + * + * If there are duplicates and we are inserting into the last slot, + * the cursor will point _to_ the last item, not after it, which + * is why we subtract P_INDX below. + */ + + t = dbp->bt_internal; + if (ret == 0 && TYPE(cp->page) == P_LBTREE && + (flags == DB_KEYFIRST || flags == DB_KEYLAST) && + !F_ISSET(cp, C_RECNUM) && + (!F_ISSET(dbp, DB_AM_SUBDB) || + (LOGGING_ON(dbp->env) && !F_ISSET(dbp, DB_AM_NOT_DURABLE))) && + ((NEXT_PGNO(cp->page) == PGNO_INVALID && + cp->indx >= NUM_ENT(cp->page) - P_INDX) || + (PREV_PGNO(cp->page) == PGNO_INVALID && cp->indx == 0))) { + t->bt_lpgno = cp->pgno; + if (F_ISSET(dbp, DB_AM_SUBDB)) + t->bt_llsn = LSN(cp->page); + } else + t->bt_lpgno = PGNO_INVALID; + /* + * Discard any pages pinned in the tree and their locks, except for + * the leaf page. Note, the leaf page participated in any stack we + * acquired, and so we have to adjust the stack as necessary. If + * there was only a single page on the stack, we don't have to free + * further stack pages. + */ + if (stack && BT_STK_POP(cp) != NULL) + (void)__bam_stkrel(dbc, 0); + + /* + * Regardless of whether we were successful or not, clear the delete + * flag. If we're successful, we either moved the cursor or the item + * is no longer deleted. If we're not successful, then we're just a + * copy, no need to have the flag set. + * + * We may have instantiated off-page duplicate cursors during the put, + * so clear the deleted bit from the off-page duplicate cursor as well. + */ + F_CLR(cp, C_DELETED); + if (cp->opd != NULL) { + cp = (BTREE_CURSOR *)cp->opd->internal; + F_CLR(cp, C_DELETED); + } + + return (ret); +} + +/* + * __bamc_rget -- + * Return the record number for a cursor. + * + * PUBLIC: int __bamc_rget __P((DBC *, DBT *)); + */ +int +__bamc_rget(dbc, data) + DBC *dbc; + DBT *data; +{ + BTREE_CURSOR *cp; + DB *dbp; + DBT dbt; + DB_MPOOLFILE *mpf; + db_recno_t recno; + int exact, ret, t_ret; + + dbp = dbc->dbp; + mpf = dbp->mpf; + cp = (BTREE_CURSOR *)dbc->internal; + + /* + * Get the page with the current item on it. + * Get a copy of the key. + * Release the page, making sure we don't release it twice. + */ + if ((ret = __memp_fget(mpf, &cp->pgno, + dbc->thread_info, dbc->txn, 0, &cp->page)) != 0) + return (ret); + memset(&dbt, 0, sizeof(DBT)); + if ((ret = __db_ret(dbc, cp->page, cp->indx, &dbt, + &dbc->my_rkey.data, &dbc->my_rkey.ulen)) != 0) + goto err; + ret = __memp_fput(mpf, dbc->thread_info, cp->page, dbc->priority); + cp->page = NULL; + if (ret != 0) + return (ret); + + if ((ret = __bam_search(dbc, PGNO_INVALID, &dbt, + F_ISSET(dbc, DBC_RMW) ? SR_FIND_WR : SR_FIND, + 1, &recno, &exact)) != 0) + goto err; + + ret = __db_retcopy(dbc->env, data, + &recno, sizeof(recno), &dbc->rdata->data, &dbc->rdata->ulen); + + /* Release the stack. */ +err: if ((t_ret = __bam_stkrel(dbc, 0)) != 0 && ret == 0) + ret = t_ret; + + return (ret); +} + +/* + * __bamc_writelock -- + * Upgrade the cursor to a write lock. + */ +static int +__bamc_writelock(dbc) + DBC *dbc; +{ + BTREE_CURSOR *cp; + int ret; + + cp = (BTREE_CURSOR *)dbc->internal; + + if (cp->lock_mode == DB_LOCK_WRITE) + return (0); + + /* + * When writing to an off-page duplicate tree, we need to have the + * appropriate page in the primary tree locked. The general DBC + * code calls us first with the primary cursor so we can acquire the + * appropriate lock. + */ + ACQUIRE_WRITE_LOCK(dbc, ret); + return (ret); +} + +/* + * __bamc_next -- + * Move to the next record. + */ +static int +__bamc_next(dbc, initial_move, deleted_okay) + DBC *dbc; + int initial_move, deleted_okay; +{ + BTREE_CURSOR *cp; + db_indx_t adjust; + db_lockmode_t lock_mode; + db_pgno_t pgno; + int ret; + + cp = (BTREE_CURSOR *)dbc->internal; + ret = 0; + + /* + * We're either moving through a page of duplicates or a btree leaf + * page. + * + * !!! + * This code handles empty pages and pages with only deleted entries. + */ + if (F_ISSET(dbc, DBC_OPD)) { + adjust = O_INDX; + lock_mode = DB_LOCK_NG; + } else { + adjust = dbc->dbtype == DB_BTREE ? P_INDX : O_INDX; + lock_mode = + F_ISSET(dbc, DBC_RMW) ? DB_LOCK_WRITE : DB_LOCK_READ; + } + if (cp->page == NULL) { + ACQUIRE_CUR(dbc, lock_mode, cp->pgno, 0, ret); + if (ret != 0) + return (ret); + } + + if (initial_move) + cp->indx += adjust; + + for (;;) { + /* + * If at the end of the page, move to a subsequent page. + * + * !!! + * Check for >= NUM_ENT. If the original search landed us on + * NUM_ENT, we may have incremented indx before the test. + */ + if (cp->indx >= NUM_ENT(cp->page)) { + if ((pgno = NEXT_PGNO(cp->page)) == PGNO_INVALID) + return (DB_NOTFOUND); + + ACQUIRE_CUR(dbc, lock_mode, pgno, 0, ret); + if (ret != 0) + return (ret); + cp->indx = 0; + continue; + } + if (!deleted_okay && IS_CUR_DELETED(dbc)) { + cp->indx += adjust; + continue; + } + break; + } + return (0); +} + +/* + * __bamc_prev -- + * Move to the previous record. + */ +static int +__bamc_prev(dbc) + DBC *dbc; +{ + BTREE_CURSOR *cp; + db_indx_t adjust; + db_lockmode_t lock_mode; + db_pgno_t pgno; + int ret; + + cp = (BTREE_CURSOR *)dbc->internal; + ret = 0; + + /* + * We're either moving through a page of duplicates or a btree leaf + * page. + * + * !!! + * This code handles empty pages and pages with only deleted entries. + */ + if (F_ISSET(dbc, DBC_OPD)) { + adjust = O_INDX; + lock_mode = DB_LOCK_NG; + } else { + adjust = dbc->dbtype == DB_BTREE ? P_INDX : O_INDX; + lock_mode = + F_ISSET(dbc, DBC_RMW) ? DB_LOCK_WRITE : DB_LOCK_READ; + } + if (cp->page == NULL) { + ACQUIRE_CUR(dbc, lock_mode, cp->pgno, 0, ret); + if (ret != 0) + return (ret); + } + + for (;;) { + /* If at the beginning of the page, move to a previous one. */ + if (cp->indx == 0) { + if ((pgno = + PREV_PGNO(cp->page)) == PGNO_INVALID) + return (DB_NOTFOUND); + + ACQUIRE_CUR(dbc, lock_mode, pgno, 0, ret); + if (ret != 0) + return (ret); + + if ((cp->indx = NUM_ENT(cp->page)) == 0) + continue; + } + + /* Ignore deleted records. */ + cp->indx -= adjust; + if (IS_CUR_DELETED(dbc)) + continue; + + break; + } + return (0); +} + +/* + * __bamc_search -- + * Move to a specified record. + */ +static int +__bamc_search(dbc, root_pgno, key, flags, exactp) + DBC *dbc; + db_pgno_t root_pgno; + const DBT *key; + u_int32_t flags; + int *exactp; +{ + BTREE *t; + BTREE_CURSOR *cp; + DB *dbp; + PAGE *h; + db_indx_t base, indx, *inp, lim; + db_pgno_t bt_lpgno; + db_recno_t recno; + u_int32_t sflags; + int bulk, cmp, ret, t_ret; + + COMPQUIET(cmp, 0); + dbp = dbc->dbp; + cp = (BTREE_CURSOR *)dbc->internal; + t = dbp->bt_internal; + ret = 0; + bulk = (F_ISSET(dbc, DBC_BULK) && cp->pgno != PGNO_INVALID); + + /* + * Find an entry in the database. Discard any lock we currently hold, + * we're going to search the tree. + */ + DISCARD_CUR(dbc, ret); + if (ret != 0) + return (ret); + + switch (flags) { + case DB_FIRST: + sflags = (F_ISSET(dbc, DBC_RMW) ? SR_WRITE : SR_READ) | SR_MIN; + goto search; + case DB_LAST: + sflags = (F_ISSET(dbc, DBC_RMW) ? SR_WRITE : SR_READ) | SR_MAX; + goto search; + case DB_SET_RECNO: + if ((ret = __ram_getno(dbc, key, &recno, 0)) != 0) + return (ret); + sflags = + (F_ISSET(dbc, DBC_RMW) ? SR_FIND_WR : SR_FIND) | SR_EXACT; + if ((ret = __bam_rsearch(dbc, &recno, sflags, 1, exactp)) != 0) + return (ret); + goto done; + case DB_SET: + case DB_GET_BOTH: + sflags = + (F_ISSET(dbc, DBC_RMW) ? SR_FIND_WR : SR_FIND) | SR_EXACT; + if (bulk) + break; + goto search; + case DB_GET_BOTH_RANGE: + sflags = (F_ISSET(dbc, DBC_RMW) ? SR_FIND_WR : SR_FIND); + goto search; + case DB_SET_RANGE: + sflags = + (F_ISSET(dbc, DBC_RMW) ? SR_WRITE : SR_READ) | SR_DUPFIRST; + goto search; + case DB_KEYFIRST: + case DB_NOOVERWRITE: + sflags = SR_KEYFIRST; + break; + case DB_KEYLAST: + case DB_NODUPDATA: + case DB_OVERWRITE_DUP: + sflags = SR_KEYLAST; + break; + default: + return (__db_unknown_flag(dbp->env, "__bamc_search", flags)); + } + + /* + * If the application has a history of inserting into the first or last + * pages of the database, we check those pages first to avoid doing a + * full search. Similarly, if the cursor is configured as a bulk + * cursor, check whether this operation belongs on the same page as the + * last one. + */ + if (bulk) + bt_lpgno = cp->pgno; + else { + if (F_ISSET(dbc, DBC_OPD)) + goto search; + + /* + * !!! + * We do not mutex protect the t->bt_lpgno field, which means + * that it can only be used in an advisory manner. If we find + * page we can use, great. If we don't, we don't care, we do + * it the slow way instead. Regardless, copy it into a local + * variable, otherwise we might acquire a lock for a page and + * then read a different page because it changed underfoot. + */ + bt_lpgno = t->bt_lpgno; + } + + /* + * If the tree has no history of insertion, do it the slow way. + */ + if (bt_lpgno == PGNO_INVALID) + goto search; + + /* + * Lock and retrieve the page on which we last inserted. + * + * The page may not exist: if a transaction created the page + * and then aborted, the page might have been truncated from + * the end of the file. We don't want to wait on the lock. + * The page may not even be relevant to this search. + */ + h = NULL; + ACQUIRE_CUR(dbc, DB_LOCK_WRITE, bt_lpgno, DB_LOCK_NOWAIT, ret); + if (ret != 0) { + if (ret == DB_LOCK_DEADLOCK || + ret == DB_LOCK_NOTGRANTED || + ret == DB_PAGE_NOTFOUND) + ret = 0; + goto fast_miss; + } + + h = cp->page; + inp = P_INP(dbp, h); + + /* + * It's okay if the page type isn't right or it's empty, it + * just means that the world changed. + */ + if (TYPE(h) != P_LBTREE || NUM_ENT(h) == 0) + goto fast_miss; + + /* Verify that this page cannot have moved to another db. */ + if (F_ISSET(dbp, DB_AM_SUBDB) && + LOG_COMPARE(&t->bt_llsn, &LSN(h)) != 0) + goto fast_miss; + + /* + * What we do here is test to see if we're at the beginning or + * end of the tree and if the new item sorts before/after the + * first/last page entry. We only try to catch inserts into + * the middle of the tree for bulk cursors. + */ + if (h->next_pgno == PGNO_INVALID) { + indx = NUM_ENT(h) - P_INDX; + if ((ret = __bam_cmp(dbc, key, h, indx, + t->bt_compare, &cmp)) != 0) + goto fast_miss; + if (cmp > 0) { + if (FLD_ISSET(sflags, SR_EXACT)) + return (DB_NOTFOUND); + else + indx += P_INDX; + } + if (cmp >= 0) + goto fast_hit; + } + if (h->prev_pgno == PGNO_INVALID) { + indx = 0; + if ((ret = __bam_cmp(dbc, key, h, indx, + t->bt_compare, &cmp)) != 0) + goto fast_miss; + if (cmp < 0 && FLD_ISSET(sflags, SR_EXACT)) + return (DB_NOTFOUND); + if (cmp <= 0) + goto fast_hit; + } + if (bulk) { + DB_BINARY_SEARCH_FOR(base, lim, NUM_ENT(h), P_INDX) { + DB_BINARY_SEARCH_INCR(indx, base, lim, P_INDX); + if ((ret = __bam_cmp(dbc, key, h, indx, + t->bt_compare, &cmp)) != 0) + goto fast_miss; + + if (cmp == 0) + goto fast_hit; + if (cmp > 0) + DB_BINARY_SEARCH_SHIFT_BASE(indx, base, + lim, P_INDX); + } + /* + * No match found: base is the smallest index greater than + * the key and may be zero or NUM_ENT(h). + */ + indx = base; + if (indx > 0 && indx < NUM_ENT(h)) { + if (FLD_ISSET(sflags, SR_EXACT)) + return (DB_NOTFOUND); + goto fast_hit; + } + } + goto fast_miss; + +fast_hit: + if (cmp == 0) { + /* + * Found a duplicate. Deal with DB_KEYFIRST / DB_KEYLAST. + */ + if (FLD_ISSET(sflags, SR_DUPFIRST)) + while (indx > 0 && inp[indx - P_INDX] == inp[indx]) + indx -= P_INDX; + else if (FLD_ISSET(sflags, SR_DUPLAST)) + while (indx < (db_indx_t)(NUM_ENT(h) - P_INDX) && + inp[indx] == inp[indx + P_INDX]) + indx += P_INDX; + } + + /* Set the exact match flag, we may have found a duplicate. */ + *exactp = (cmp == 0); + + /* + * Insert the entry in the stack. (Our caller is likely to + * call __bam_stkrel() after our return.) + */ + BT_STK_CLR(cp); + BT_STK_ENTER(dbp->env, + cp, h, indx, cp->lock, cp->lock_mode, ret); + if (ret != 0) + return (ret); + goto done; + +fast_miss: + /* + * This was not the right page, so we do not need to retain + * the lock even in the presence of transactions. + * + * This is also an error path, so ret may have been set. + */ + DISCARD_CUR(dbc, ret); + cp->pgno = PGNO_INVALID; + if ((t_ret = __LPUT(dbc, cp->lock)) != 0 && ret == 0) + ret = t_ret; + if (ret != 0) + return (ret); + +search: + if ((ret = __bam_search(dbc, root_pgno, + key, sflags, 1, NULL, exactp)) != 0) + return (ret); + +done: /* Initialize the cursor from the stack. */ + cp->page = cp->csp->page; + cp->pgno = cp->csp->page->pgno; + cp->indx = cp->csp->indx; + cp->lock = cp->csp->lock; + cp->lock_mode = cp->csp->lock_mode; + + /* If on an empty page or a deleted record, move to the next one. */ + if (flags == DB_FIRST && + (NUM_ENT(cp->page) == 0 || IS_CUR_DELETED(dbc))) + if ((ret = __bamc_next(dbc, 0, 0)) != 0) + return (ret); + if (flags == DB_LAST && + (NUM_ENT(cp->page) == 0 || IS_CUR_DELETED(dbc))) + if ((ret = __bamc_prev(dbc)) != 0) + return (ret); + + return (0); +} + +/* + * __bamc_physdel -- + * Physically remove an item from the page. + */ +static int +__bamc_physdel(dbc) + DBC *dbc; +{ + BTREE_CURSOR *cp; + DB *dbp; + DBT key; + DB_LOCK next_lock, prev_lock; + db_pgno_t pgno; + int delete_page, empty_page, exact, ret; + + dbp = dbc->dbp; + memset(&key, 0, sizeof(DBT)); + cp = (BTREE_CURSOR *)dbc->internal; + delete_page = empty_page = ret = 0; + LOCK_INIT(next_lock); + LOCK_INIT(prev_lock); + + /* If the page is going to be emptied, consider deleting it. */ + delete_page = empty_page = + NUM_ENT(cp->page) == (TYPE(cp->page) == P_LBTREE ? 2 : 1); + + /* + * Check if the application turned off reverse splits. Applications + * can't turn off reverse splits in off-page duplicate trees, that + * space will never be reused unless the exact same key is specified. + */ + if (delete_page && + !F_ISSET(dbc, DBC_OPD) && F_ISSET(dbp, DB_AM_REVSPLITOFF)) + delete_page = 0; + + /* + * We never delete the last leaf page. (Not really true -- we delete + * the last leaf page of off-page duplicate trees, but that's handled + * by our caller, not down here.) + */ + if (delete_page && cp->pgno == BAM_ROOT_PGNO(dbc)) + delete_page = 0; + + /* + * To delete a leaf page other than an empty root page, we need a + * copy of a key from the page. Use the 0th page index since it's + * the last key the page held. + * + * !!! + * Note that because __bamc_physdel is always called from a cursor + * close, it should be safe to use the cursor's own "my_rkey" memory + * to temporarily hold this key. We shouldn't own any returned-data + * memory of interest--if we do, we're in trouble anyway. + */ + if (delete_page) { + if ((ret = __db_ret(dbc, cp->page, 0, &key, + &dbc->my_rkey.data, &dbc->my_rkey.ulen)) != 0) + goto err; + } + + /* + * Delete the items. If page isn't empty, we adjust the cursors. + * + * !!! + * The following operations to delete a page may deadlock. The easy + * scenario is if we're deleting an item because we're closing cursors + * because we've already deadlocked and want to call txn->abort. If + * we fail due to deadlock, we'll leave a locked, possibly empty page + * in the tree, which won't be empty long because we'll undo the delete + * when we undo the transaction's modifications. + * + * !!! + * Delete the key item first, otherwise the on-page duplicate checks + * in __bam_ditem() won't work! + */ + if ((ret = __memp_dirty(dbp->mpf, + &cp->page, dbc->thread_info, dbc->txn, dbc->priority, 0)) != 0) + goto err; + if (TYPE(cp->page) == P_LBTREE) { + if ((ret = __bam_ditem(dbc, cp->page, cp->indx)) != 0) + goto err; + if (!empty_page) + if ((ret = __bam_ca_di(dbc, + PGNO(cp->page), cp->indx, -1)) != 0) + goto err; + } + if ((ret = __bam_ditem(dbc, cp->page, cp->indx)) != 0) + goto err; + + /* Clear the deleted flag, the item is gone. */ + F_CLR(cp, C_DELETED); + + if (!empty_page) + if ((ret = __bam_ca_di(dbc, PGNO(cp->page), cp->indx, -1)) != 0) + goto err; + + /* + * Need to downgrade write locks here or non-txn locks will get stuck. + */ + if (F_ISSET(dbc->dbp, DB_AM_READ_UNCOMMITTED)) { + if ((ret = __TLPUT(dbc, cp->lock)) != 0) + goto err; + cp->lock_mode = DB_LOCK_WWRITE; + if (cp->page != NULL && + (ret = __memp_shared(dbp->mpf, cp->page)) != 0) + goto err; + } + /* If we're not going to try and delete the page, we're done. */ + if (!delete_page) + return (0); + + /* + * Lock the previous and next pages before latching the parent + * sub tree. + */ + if (STD_LOCKING(dbc)) { + if ((pgno = PREV_PGNO(cp->page)) != PGNO_INVALID && + (ret = __db_lget(dbc, + 0, pgno, DB_LOCK_WRITE, 0, &prev_lock)) != 0) + return (ret); + if ((pgno = NEXT_PGNO(cp->page)) != PGNO_INVALID && + (ret = __db_lget(dbc, + 0, pgno, DB_LOCK_WRITE, 0, &next_lock)) != 0) { + (void)__TLPUT(dbc, next_lock); + return (ret); + } + } + DISCARD_CUR(dbc, ret); + if (ret != 0) + goto err; + ret = __bam_search(dbc, PGNO_INVALID, &key, SR_DEL, 0, NULL, &exact); + + /* + * If everything worked, delete the stack, otherwise, release the + * stack and page locks without further damage. + */ + if (ret == 0) + ret = __bam_dpages(dbc, 1, BTD_RELINK); + else + (void)__bam_stkrel(dbc, 0); + +err: if (ret != 0) + F_SET(dbc, DBC_ERROR); + (void)__TLPUT(dbc, prev_lock); + (void)__TLPUT(dbc, next_lock); + return (ret); +} + +/* + * __bamc_getstack -- + * Acquire a full stack for a cursor. + */ +static int +__bamc_getstack(dbc) + DBC *dbc; +{ + BTREE_CURSOR *cp; + DB *dbp; + DBT dbt; + DB_MPOOLFILE *mpf; + PAGE *h; + int exact, ret, t_ret; + + dbp = dbc->dbp; + mpf = dbp->mpf; + cp = (BTREE_CURSOR *)dbc->internal; + + /* + * Get the page with the current item on it. The caller of this + * routine has to already hold a read lock on the page, so there + * is no additional lock to acquire. + */ + if ((ret = __memp_fget(mpf, &cp->pgno, + dbc->thread_info, dbc->txn, 0, &h)) != 0) + return (ret); + + /* Get a copy of a key from the page. */ + memset(&dbt, 0, sizeof(DBT)); + ret = __db_ret(dbc, h, 0, &dbt, + &dbc->my_rkey.data, &dbc->my_rkey.ulen); + if ((t_ret = __memp_fput(mpf, + dbc->thread_info, h, dbc->priority)) != 0 && ret == 0) + ret = t_ret; + if (ret != 0) + return (ret); + + /* Get a write-locked stack for the page. */ + exact = 0; + ret = __bam_search(dbc, PGNO_INVALID, + &dbt, SR_KEYFIRST, 1, NULL, &exact); + + return (ret); +} + +/* + * __bam_isopd -- + * Return if the cursor references an off-page duplicate tree via its + * page number. + */ +static int +__bam_isopd(dbc, pgnop) + DBC *dbc; + db_pgno_t *pgnop; +{ + BOVERFLOW *bo; + + if (TYPE(dbc->internal->page) != P_LBTREE) + return (0); + + bo = GET_BOVERFLOW(dbc->dbp, + dbc->internal->page, dbc->internal->indx + O_INDX); + if (B_TYPE(bo->type) == B_DUPLICATE) { + *pgnop = bo->pgno; + return (1); + } + return (0); +} + +/* + * __bam_opd_exists -- + * Return if the current position has any data. + * PUBLIC: int __bam_opd_exists __P((DBC *, db_pgno_t)); + */ +int +__bam_opd_exists(dbc, pgno) + DBC *dbc; + db_pgno_t pgno; +{ + PAGE *h; + int ret; + + if ((ret = __memp_fget(dbc->dbp->mpf, &pgno, + dbc->thread_info, dbc->txn, 0, &h)) != 0) + return (ret); + + /* + * We always collapse OPD trees so we only need to check + * the number of entries on the root. If there is a non-empty + * tree then there will be duplicates. + */ + if (NUM_ENT(h) == 0) + ret = 0; + else + ret = DB_KEYEXIST; + + (void)__memp_fput(dbc->dbp->mpf, dbc->thread_info, h, dbc->priority); + + return (ret); +} diff -r 000000000000 -r a1985f14b030 src/btree/bt_delete.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/btree/bt_delete.c Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,563 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 1996, 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +/* + * Copyright (c) 1990, 1993, 1994, 1995, 1996 + * Keith Bostic. All rights reserved. + */ +/* + * Copyright (c) 1990, 1993, 1994, 1995 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Mike Olson. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $Id$ + */ + +#include "db_config.h" + +#include "db_int.h" +#include "dbinc/db_page.h" +#include "dbinc/btree.h" +#include "dbinc/lock.h" +#include "dbinc/mp.h" + +/* + * __bam_ditem -- + * Delete one or more entries from a page. + * + * PUBLIC: int __bam_ditem __P((DBC *, PAGE *, u_int32_t)); + */ +int +__bam_ditem(dbc, h, indx) + DBC *dbc; + PAGE *h; + u_int32_t indx; +{ + BINTERNAL *bi; + BKEYDATA *bk; + DB *dbp; + u_int32_t nbytes; + int ret; + db_indx_t *inp; + + dbp = dbc->dbp; + inp = P_INP(dbp, h); + + /* The page should already have been dirtied by our caller. */ + DB_ASSERT(dbp->env, IS_DIRTY(h)); + + switch (TYPE(h)) { + case P_IBTREE: + bi = GET_BINTERNAL(dbp, h, indx); + switch (B_TYPE(bi->type)) { + case B_DUPLICATE: + case B_KEYDATA: + nbytes = BINTERNAL_SIZE(bi->len); + break; + case B_OVERFLOW: + nbytes = BINTERNAL_SIZE(bi->len); + if ((ret = + __db_doff(dbc, ((BOVERFLOW *)bi->data)->pgno)) != 0) + return (ret); + break; + default: + return (__db_pgfmt(dbp->env, PGNO(h))); + } + break; + case P_IRECNO: + nbytes = RINTERNAL_SIZE; + break; + case P_LBTREE: + /* + * If it's a duplicate key, discard the index and don't touch + * the actual page item. + * + * !!! + * This works because no data item can have an index matching + * any other index so even if the data item is in a key "slot", + * it won't match any other index. + */ + if ((indx % 2) == 0) { + /* + * Check for a duplicate after us on the page. NOTE: + * we have to delete the key item before deleting the + * data item, otherwise the "indx + P_INDX" calculation + * won't work! + */ + if (indx + P_INDX < (u_int32_t)NUM_ENT(h) && + inp[indx] == inp[indx + P_INDX]) + return (__bam_adjindx(dbc, + h, indx, indx + O_INDX, 0)); + /* + * Check for a duplicate before us on the page. It + * doesn't matter if we delete the key item before or + * after the data item for the purposes of this one. + */ + if (indx > 0 && inp[indx] == inp[indx - P_INDX]) + return (__bam_adjindx(dbc, + h, indx, indx - P_INDX, 0)); + } + /* FALLTHROUGH */ + case P_LDUP: + case P_LRECNO: + bk = GET_BKEYDATA(dbp, h, indx); + switch (B_TYPE(bk->type)) { + case B_DUPLICATE: + nbytes = BOVERFLOW_SIZE; + break; + case B_OVERFLOW: + nbytes = BOVERFLOW_SIZE; + if ((ret = __db_doff( + dbc, (GET_BOVERFLOW(dbp, h, indx))->pgno)) != 0) + return (ret); + break; + case B_KEYDATA: + nbytes = BKEYDATA_SIZE(bk->len); + break; + default: + return (__db_pgfmt(dbp->env, PGNO(h))); + } + break; + default: + return (__db_pgfmt(dbp->env, PGNO(h))); + } + + /* Delete the item and mark the page dirty. */ + if ((ret = __db_ditem(dbc, h, indx, nbytes)) != 0) + return (ret); + + return (0); +} + +/* + * __bam_adjindx -- + * Adjust an index on the page. + * + * PUBLIC: int __bam_adjindx __P((DBC *, PAGE *, u_int32_t, u_int32_t, int)); + */ +int +__bam_adjindx(dbc, h, indx, indx_copy, is_insert) + DBC *dbc; + PAGE *h; + u_int32_t indx, indx_copy; + int is_insert; +{ + DB *dbp; + db_indx_t copy, *inp; + int ret; + + dbp = dbc->dbp; + inp = P_INP(dbp, h); + + /* Log the change. */ + if (DBC_LOGGING(dbc)) { + if ((ret = __bam_adj_log(dbp, dbc->txn, &LSN(h), 0, + PGNO(h), &LSN(h), indx, indx_copy, (u_int32_t)is_insert)) != 0) + return (ret); + } else + LSN_NOT_LOGGED(LSN(h)); + + /* Shuffle the indices and mark the page dirty. */ + if (is_insert) { + copy = inp[indx_copy]; + if (indx != NUM_ENT(h)) + memmove(&inp[indx + O_INDX], &inp[indx], + sizeof(db_indx_t) * (NUM_ENT(h) - indx)); + inp[indx] = copy; + ++NUM_ENT(h); + } else { + --NUM_ENT(h); + if (indx != NUM_ENT(h)) + memmove(&inp[indx], &inp[indx + O_INDX], + sizeof(db_indx_t) * (NUM_ENT(h) - indx)); + } + + return (0); +} + +/* + * __bam_dpages -- + * Delete a set of locked pages. + * + * PUBLIC: int __bam_dpages __P((DBC *, int, int)); + */ +int +__bam_dpages(dbc, use_top, flags) + DBC *dbc; + int use_top; + int flags; +{ + BINTERNAL *bi; + BTREE_CURSOR *cp; + DB *dbp; + DBT a, b; + DB_LOCK c_lock, p_lock; + DB_MPOOLFILE *mpf; + EPG *epg, *save_sp, *stack_epg; + PAGE *child, *parent; + db_indx_t nitems; + db_pgno_t pgno, root_pgno; + db_recno_t rcnt; + int done, ret, t_ret; + + dbp = dbc->dbp; + mpf = dbp->mpf; + cp = (BTREE_CURSOR *)dbc->internal; + nitems = 0; + pgno = PGNO_INVALID; + + /* + * We have the entire stack of deletable pages locked. + * + * Btree calls us with the first page in the stack is to have a + * single item deleted, and the rest of the pages are to be removed. + * + * Recno always has a stack to the root and __bam_merge operations + * may have unneeded items in the sack. We find the lowest page + * in the stack that has more than one record in it and start there. + */ + ret = 0; + if (use_top) + stack_epg = cp->sp; + else + for (stack_epg = cp->csp; stack_epg > cp->sp; --stack_epg) + if (NUM_ENT(stack_epg->page) > 1) + break; + epg = stack_epg; + /* + * !!! + * There is an interesting deadlock situation here. We have to relink + * the leaf page chain around the leaf page being deleted. Consider + * a cursor walking through the leaf pages, that has the previous page + * read-locked and is waiting on a lock for the page we're deleting. + * It will deadlock here. Before we unlink the subtree, we relink the + * leaf page chain. + */ + if (LF_ISSET(BTD_RELINK) && LEVEL(cp->csp->page) == 1 && + (ret = __db_relink(dbc, cp->csp->page, NULL, PGNO_INVALID)) != 0) + goto discard; + + /* + * Delete the last item that references the underlying pages that are + * to be deleted, and adjust cursors that reference that page. Then, + * save that page's page number and item count and release it. If + * the application isn't retaining locks because it's running without + * transactions, this lets the rest of the tree get back to business + * immediately. + */ + if ((ret = __memp_dirty(mpf, + &epg->page, dbc->thread_info, dbc->txn, dbc->priority, 0)) != 0) + goto discard; + if ((ret = __bam_ditem(dbc, epg->page, epg->indx)) != 0) + goto discard; + if ((ret = __bam_ca_di(dbc, PGNO(epg->page), epg->indx, -1)) != 0) + goto discard; + + if (LF_ISSET(BTD_UPDATE) && epg->indx == 0) { + save_sp = cp->csp; + cp->csp = epg; + ret = __bam_pupdate(dbc, epg->page); + cp->csp = save_sp; + if (ret != 0) + goto discard; + } + + pgno = PGNO(epg->page); + nitems = NUM_ENT(epg->page); + + ret = __memp_fput(mpf, dbc->thread_info, epg->page, dbc->priority); + epg->page = NULL; + if ((t_ret = __TLPUT(dbc, epg->lock)) != 0 && ret == 0) + ret = t_ret; + if (ret != 0) + goto err_inc; + + /* Then, discard any pages that we don't care about. */ +discard: for (epg = cp->sp; epg < stack_epg; ++epg) { + if ((t_ret = __memp_fput(mpf, dbc->thread_info, + epg->page, dbc->priority)) != 0 && ret == 0) + ret = t_ret; + epg->page = NULL; + if ((t_ret = __TLPUT(dbc, epg->lock)) != 0 && ret == 0) + ret = t_ret; + } + if (ret != 0) + goto err; + + /* Free the rest of the pages in the stack. */ + while (++epg <= cp->csp) { + if ((ret = __memp_dirty(mpf, &epg->page, + dbc->thread_info, dbc->txn, dbc->priority, 0)) != 0) + goto err; + /* + * Delete page entries so they will be restored as part of + * recovery. We don't need to do cursor adjustment here as + * the pages are being emptied by definition and so cannot + * be referenced by a cursor. + */ + if (NUM_ENT(epg->page) != 0) { + DB_ASSERT(dbp->env, LEVEL(epg->page) != 1); + + if ((ret = __bam_ditem(dbc, epg->page, epg->indx)) != 0) + goto err; + /* + * Sheer paranoia: if we find any pages that aren't + * emptied by the delete, someone else added an item + * while we were walking the tree, and we discontinue + * the delete. Shouldn't be possible, but we check + * regardless. + */ + if (NUM_ENT(epg->page) != 0) + goto err; + } + + ret = __db_free(dbc, epg->page, 0); + if (cp->page == epg->page) + cp->page = NULL; + epg->page = NULL; + if ((t_ret = __TLPUT(dbc, epg->lock)) != 0 && ret == 0) + ret = t_ret; + if (ret != 0) + goto err_inc; + } + + if (0) { +err_inc: ++epg; +err: for (; epg <= cp->csp; ++epg) { + if (epg->page != NULL) { + (void)__memp_fput(mpf, dbc->thread_info, + epg->page, dbc->priority); + epg->page = NULL; + } + (void)__TLPUT(dbc, epg->lock); + } + BT_STK_CLR(cp); + return (ret); + } + BT_STK_CLR(cp); + + /* + * If we just deleted the next-to-last item from the root page, the + * tree can collapse one or more levels. While there remains only a + * single item on the root page, write lock the last page referenced + * by the root page and copy it over the root page. + * Note that if pgno is the root of a btree database then the root + * cannot change as we have it locked. + */ + if (nitems != 1) + return (0); + root_pgno = BAM_ROOT_PGNO(dbc); + if (pgno != root_pgno) + return (0); + + for (done = 0; !done;) { + /* Initialize. */ + parent = child = NULL; + LOCK_INIT(p_lock); + LOCK_INIT(c_lock); + + /* Get the root. */ + root_pgno = cp->root; + BAM_GET_ROOT(dbc, root_pgno, + parent, DB_MPOOL_DIRTY, DB_LOCK_WRITE, p_lock, ret); + + DB_ASSERT(dbp->env, parent != NULL); + if (ret != 0 || NUM_ENT(parent) != 1) + goto stop; + + switch (TYPE(parent)) { + case P_IBTREE: + /* + * If this is overflow, then try to delete it. + * The child may or may not still point at it. + */ + bi = GET_BINTERNAL(dbp, parent, 0); + if (B_TYPE(bi->type) == B_OVERFLOW) + if ((ret = __db_doff(dbc, + ((BOVERFLOW *)bi->data)->pgno)) != 0) + goto stop; + pgno = bi->pgno; + break; + case P_IRECNO: + pgno = GET_RINTERNAL(dbp, parent, 0)->pgno; + break; + default: + goto stop; + } + + /* Lock the child page. */ + if ((ret = + __db_lget(dbc, 0, pgno, DB_LOCK_WRITE, 0, &c_lock)) != 0) + goto stop; + if ((ret = __memp_fget(mpf, &pgno, dbc->thread_info, dbc->txn, + DB_MPOOL_DIRTY, &child)) != 0) + goto stop; + + /* Log the change. */ + if (DBC_LOGGING(dbc)) { + memset(&a, 0, sizeof(a)); + a.data = child; + a.size = dbp->pgsize; + memset(&b, 0, sizeof(b)); + b.data = P_ENTRY(dbp, parent, 0); + b.size = TYPE(parent) == P_IRECNO ? RINTERNAL_SIZE : + BINTERNAL_SIZE(((BINTERNAL *)b.data)->len); + if ((ret = __bam_rsplit_log(dbp, dbc->txn, + &child->lsn, 0, PGNO(child), &a, PGNO(parent), + RE_NREC(parent), &b, &parent->lsn)) != 0) + goto stop; + } else + LSN_NOT_LOGGED(child->lsn); + + /* + * Make the switch. + * + * One fixup -- internal pages below the top level do not store + * a record count, so we have to preserve it if we're not + * converting to a leaf page. Note also that we are about to + * overwrite the parent page, including its LSN. This is OK + * because the log message we wrote describing this update + * stores its LSN on the child page. When the child is copied + * onto the parent, the correct LSN is copied into place. + */ + COMPQUIET(rcnt, 0); + if (F_ISSET(cp, C_RECNUM) && LEVEL(child) > LEAFLEVEL) + rcnt = RE_NREC(parent); + memcpy(parent, child, dbp->pgsize); + PGNO(parent) = root_pgno; + if (F_ISSET(cp, C_RECNUM) && LEVEL(child) > LEAFLEVEL) + RE_NREC_SET(parent, rcnt); + + /* Adjust the cursors. */ + if ((ret = __bam_ca_rsplit(dbc, PGNO(child), root_pgno)) != 0) + goto stop; + + /* + * Free the page copied onto the root page and discard its + * lock. (The call to __db_free() discards our reference + * to the page.) + */ + if ((ret = __db_free(dbc, child, 0)) != 0) { + child = NULL; + goto stop; + } + child = NULL; + + if (0) { +stop: done = 1; + } + if ((t_ret = __TLPUT(dbc, p_lock)) != 0 && ret == 0) + ret = t_ret; + if (parent != NULL && + (t_ret = __memp_fput(mpf, dbc->thread_info, + parent, dbc->priority)) != 0 && ret == 0) + ret = t_ret; + if ((t_ret = __TLPUT(dbc, c_lock)) != 0 && ret == 0) + ret = t_ret; + if (child != NULL && + (t_ret = __memp_fput(mpf, dbc->thread_info, + child, dbc->priority)) != 0 && ret == 0) + ret = t_ret; + } + + return (ret); +} + +/* + * __bam_pupdate -- + * Update parent key pointers up the tree. + * + * PUBLIC: int __bam_pupdate __P((DBC *, PAGE *)); + */ +int +__bam_pupdate(dbc, lpg) + DBC *dbc; + PAGE *lpg; +{ + BTREE_CURSOR *cp; + ENV *env; + EPG *epg; + int ret; + + env = dbc->env; + cp = (BTREE_CURSOR *)dbc->internal; + ret = 0; + + /* + * Update the parents up the tree. __bam_pinsert only looks at the + * left child if is a leaf page, so we don't need to change it. We + * just do a delete and insert; a replace is possible but reusing + * pinsert is better. + */ + for (epg = &cp->csp[-1]; epg >= cp->sp; epg--) { + if ((ret = __memp_dirty(dbc->dbp->mpf, &epg->page, + dbc->thread_info, dbc->txn, dbc->priority, 0)) != 0) + return (ret); + epg->indx--; + if ((ret = __bam_pinsert(dbc, epg, 0, + lpg, epg[1].page, BPI_NORECNUM | BPI_REPLACE)) != 0) { + if (ret == DB_NEEDSPLIT) { + /* This should not happen. */ + __db_errx(env, DB_STR_A("1020", + "Not enough room in parent: %s: page %lu", + "%s %lu"), dbc->dbp->fname, + (u_long)PGNO(epg->page)); + ret = __env_panic(env, EINVAL); + } + epg->indx++; + return (ret); + } + epg->indx++; + } + return (ret); +} diff -r 000000000000 -r a1985f14b030 src/btree/bt_method.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/btree/bt_method.c Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,727 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 1999, 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + * $Id$ + */ + +#include "db_config.h" + +#include "db_int.h" +#include "dbinc/db_page.h" +#include "dbinc/btree.h" +#include "dbinc/qam.h" + +static int __bam_set_bt_minkey __P((DB *, u_int32_t)); +static int __bam_get_bt_compare + __P((DB *, int (**)(DB *, const DBT *, const DBT *))); +static int __bam_get_bt_prefix + __P((DB *, size_t(**)(DB *, const DBT *, const DBT *))); +static int __bam_set_bt_prefix + __P((DB *, size_t(*)(DB *, const DBT *, const DBT *))); +static int __ram_get_re_delim __P((DB *, int *)); +static int __ram_set_re_delim __P((DB *, int)); +static int __ram_set_re_len __P((DB *, u_int32_t)); +static int __ram_set_re_pad __P((DB *, int)); +static int __ram_get_re_source __P((DB *, const char **)); +static int __ram_set_re_source __P((DB *, const char *)); + +/* + * __bam_db_create -- + * Btree specific initialization of the DB structure. + * + * PUBLIC: int __bam_db_create __P((DB *)); + */ +int +__bam_db_create(dbp) + DB *dbp; +{ + BTREE *t; + int ret; + + /* Allocate and initialize the private btree structure. */ + if ((ret = __os_calloc(dbp->env, 1, sizeof(BTREE), &t)) != 0) + return (ret); + dbp->bt_internal = t; + + t->bt_minkey = DEFMINKEYPAGE; /* Btree */ + t->bt_compare = __bam_defcmp; + t->bt_prefix = __bam_defpfx; +#ifdef HAVE_COMPRESSION + t->bt_compress = NULL; + t->bt_decompress = NULL; + t->compress_dup_compare = NULL; + + /* + * DB_AM_COMPRESS may have been set in __bam_metachk before the + * bt_internal structure existed. + */ + if (F_ISSET(dbp, DB_AM_COMPRESS) && + (ret = __bam_set_bt_compress(dbp, NULL, NULL)) != 0) + return (ret); +#endif + + dbp->get_bt_compare = __bam_get_bt_compare; + dbp->set_bt_compare = __bam_set_bt_compare; + dbp->get_bt_minkey = __bam_get_bt_minkey; + dbp->set_bt_minkey = __bam_set_bt_minkey; + dbp->get_bt_prefix = __bam_get_bt_prefix; + dbp->set_bt_prefix = __bam_set_bt_prefix; + + t->re_pad = ' '; /* Recno */ + t->re_delim = '\n'; + t->re_eof = 1; + + dbp->get_re_delim = __ram_get_re_delim; + dbp->set_re_delim = __ram_set_re_delim; + dbp->get_re_len = __ram_get_re_len; + dbp->set_re_len = __ram_set_re_len; + dbp->get_re_pad = __ram_get_re_pad; + dbp->set_re_pad = __ram_set_re_pad; + dbp->get_re_source = __ram_get_re_source; + dbp->set_re_source = __ram_set_re_source; + + return (0); +} + +/* + * __bam_db_close -- + * Btree specific discard of the DB structure. + * + * PUBLIC: int __bam_db_close __P((DB *)); + */ +int +__bam_db_close(dbp) + DB *dbp; +{ + BTREE *t; + + if ((t = dbp->bt_internal) == NULL) + return (0); + /* Recno */ + /* Close any backing source file descriptor. */ + if (t->re_fp != NULL) + (void)fclose(t->re_fp); + + /* Free any backing source file name. */ + if (t->re_source != NULL) + __os_free(dbp->env, t->re_source); + + __os_free(dbp->env, t); + dbp->bt_internal = NULL; + + return (0); +} + +/* + * __bam_map_flags -- + * Map Btree specific flags from public to the internal values. + * + * PUBLIC: void __bam_map_flags __P((DB *, u_int32_t *, u_int32_t *)); + */ +void +__bam_map_flags(dbp, inflagsp, outflagsp) + DB *dbp; + u_int32_t *inflagsp, *outflagsp; +{ + COMPQUIET(dbp, NULL); + + if (FLD_ISSET(*inflagsp, DB_DUP)) { + FLD_SET(*outflagsp, DB_AM_DUP); + FLD_CLR(*inflagsp, DB_DUP); + } + if (FLD_ISSET(*inflagsp, DB_DUPSORT)) { + FLD_SET(*outflagsp, DB_AM_DUP | DB_AM_DUPSORT); + FLD_CLR(*inflagsp, DB_DUPSORT); + } + if (FLD_ISSET(*inflagsp, DB_RECNUM)) { + FLD_SET(*outflagsp, DB_AM_RECNUM); + FLD_CLR(*inflagsp, DB_RECNUM); + } + if (FLD_ISSET(*inflagsp, DB_REVSPLITOFF)) { + FLD_SET(*outflagsp, DB_AM_REVSPLITOFF); + FLD_CLR(*inflagsp, DB_REVSPLITOFF); + } +} + +/* + * __bam_set_flags -- + * Set Btree specific flags. + * + * PUBLIC: int __bam_set_flags __P((DB *, u_int32_t *flagsp)); + */ +int +__bam_set_flags(dbp, flagsp) + DB *dbp; + u_int32_t *flagsp; +{ + BTREE *t; + u_int32_t flags; + + t = dbp->bt_internal; + + flags = *flagsp; + if (LF_ISSET(DB_DUP | DB_DUPSORT | DB_RECNUM | DB_REVSPLITOFF)) + DB_ILLEGAL_AFTER_OPEN(dbp, "DB->set_flags"); + + /* + * The DB_DUP and DB_DUPSORT flags are shared by the Hash + * and Btree access methods. + */ + if (LF_ISSET(DB_DUP | DB_DUPSORT)) + DB_ILLEGAL_METHOD(dbp, DB_OK_BTREE | DB_OK_HASH); + + if (LF_ISSET(DB_RECNUM | DB_REVSPLITOFF)) + DB_ILLEGAL_METHOD(dbp, DB_OK_BTREE | DB_OK_HASH); + + /* DB_DUP/DB_DUPSORT is incompatible with DB_RECNUM. */ + if (LF_ISSET(DB_DUP | DB_DUPSORT) && F_ISSET(dbp, DB_AM_RECNUM)) + goto incompat; + + /* DB_RECNUM is incompatible with DB_DUP/DB_DUPSORT. */ + if (LF_ISSET(DB_RECNUM) && F_ISSET(dbp, DB_AM_DUP)) + goto incompat; + + /* DB_RECNUM is incompatible with DB_DUP/DB_DUPSORT. */ + if (LF_ISSET(DB_RECNUM) && LF_ISSET(DB_DUP | DB_DUPSORT)) + goto incompat; + +#ifdef HAVE_COMPRESSION + /* DB_RECNUM is incompatible with compression */ + if (LF_ISSET(DB_RECNUM) && DB_IS_COMPRESSED(dbp)) { + __db_errx(dbp->env, DB_STR("1024", + "DB_RECNUM cannot be used with compression")); + return (EINVAL); + } + + /* DB_DUP without DB_DUPSORT is incompatible with compression */ + if (LF_ISSET(DB_DUP) && !LF_ISSET(DB_DUPSORT) && + !F_ISSET(dbp, DB_AM_DUPSORT) && DB_IS_COMPRESSED(dbp)) { + __db_errx(dbp->env, DB_STR("1025", + "DB_DUP cannot be used with compression without DB_DUPSORT")); + return (EINVAL); + } +#endif + + if (LF_ISSET(DB_DUPSORT) && dbp->dup_compare == NULL) { +#ifdef HAVE_COMPRESSION + if (DB_IS_COMPRESSED(dbp)) { + dbp->dup_compare = __bam_compress_dupcmp; + t->compress_dup_compare = __bam_defcmp; + } else +#endif + dbp->dup_compare = __bam_defcmp; + } + + __bam_map_flags(dbp, flagsp, &dbp->flags); + return (0); + +incompat: + return (__db_ferr(dbp->env, "DB->set_flags", 1)); +} + +/* + * __bam_get_bt_compare -- + * Get the comparison function. + */ +static int +__bam_get_bt_compare(dbp, funcp) + DB *dbp; + int (**funcp) __P((DB *, const DBT *, const DBT *)); +{ + BTREE *t; + + DB_ILLEGAL_METHOD(dbp, DB_OK_BTREE); + + t = dbp->bt_internal; + + if (funcp != NULL) + *funcp = t->bt_compare; + + return (0); +} + +/* + * __bam_set_bt_compare -- + * Set the comparison function. + * + * PUBLIC: int __bam_set_bt_compare + * PUBLIC: __P((DB *, int (*)(DB *, const DBT *, const DBT *))); + */ +int +__bam_set_bt_compare(dbp, func) + DB *dbp; + int (*func) __P((DB *, const DBT *, const DBT *)); +{ + BTREE *t; + + DB_ILLEGAL_AFTER_OPEN(dbp, "DB->set_bt_compare"); + DB_ILLEGAL_METHOD(dbp, DB_OK_BTREE); + + t = dbp->bt_internal; + + /* + * Can't default the prefix routine if the user supplies a comparison + * routine; shortening the keys can break their comparison algorithm. + */ + t->bt_compare = func; + if (t->bt_prefix == __bam_defpfx) + t->bt_prefix = NULL; + + return (0); +} + +/* + * __bam_set_bt_compress -- + * Set the compression functions. + * + * PUBLIC: int __bam_set_bt_compress __P((DB *, + * PUBLIC: int (*)(DB *, const DBT *, const DBT *, + * PUBLIC: const DBT *, const DBT *, DBT *), + * PUBLIC: int (*)(DB *, const DBT *, const DBT *, DBT *, DBT *, DBT *))); + */ +int +__bam_set_bt_compress(dbp, compress, decompress) + DB *dbp; + int (*compress) __P((DB *, const DBT *, const DBT *, const DBT *, + const DBT *, DBT *)); + int (*decompress) __P((DB *, const DBT *, const DBT *, DBT *, DBT *, + DBT *)); +{ +#ifdef HAVE_COMPRESSION + BTREE *t; + + DB_ILLEGAL_AFTER_OPEN(dbp, "DB->set_bt_compress"); + DB_ILLEGAL_METHOD(dbp, DB_OK_BTREE); + + t = dbp->bt_internal; + + /* compression is incompatible with DB_RECNUM */ + if (F_ISSET(dbp, DB_AM_RECNUM)) { + __db_errx(dbp->env, DB_STR("1027", + "compression cannot be used with DB_RECNUM")); + return (EINVAL); + } + + /* compression is incompatible with DB_DUP without DB_DUPSORT */ + if (F_ISSET(dbp, DB_AM_DUP) && !F_ISSET(dbp, DB_AM_DUPSORT)) { + __db_errx(dbp->env, DB_STR("1028", + "compression cannot be used with DB_DUP without DB_DUPSORT")); + return (EINVAL); + } + + if (compress != 0 && decompress != 0) { + t->bt_compress = compress; + t->bt_decompress = decompress; + } else if (compress == 0 && decompress == 0) { + t->bt_compress = __bam_defcompress; + t->bt_decompress = __bam_defdecompress; + } else { + __db_errx(dbp->env, DB_STR("1029", + "to enable compression you need to supply both function arguments")); + return (EINVAL); + } + F_SET(dbp, DB_AM_COMPRESS); + + /* Copy dup_compare to compress_dup_compare, and use the compression + duplicate compare */ + if (F_ISSET(dbp, DB_AM_DUPSORT)) { + t->compress_dup_compare = dbp->dup_compare; + dbp->dup_compare = __bam_compress_dupcmp; + } + + return (0); +#else + COMPQUIET(compress, NULL); + COMPQUIET(decompress, NULL); + + __db_errx(dbp->env, DB_STR("1030", + "compression support has not been compiled in")); + return (EINVAL); +#endif +} + +/* + * __db_get_bt_minkey -- + * Get the minimum keys per page. + * + * PUBLIC: int __bam_get_bt_minkey __P((DB *, u_int32_t *)); + */ +int +__bam_get_bt_minkey(dbp, bt_minkeyp) + DB *dbp; + u_int32_t *bt_minkeyp; +{ + BTREE *t; + + DB_ILLEGAL_METHOD(dbp, DB_OK_BTREE); + + t = dbp->bt_internal; + *bt_minkeyp = t->bt_minkey; + return (0); +} + +/* + * __bam_set_bt_minkey -- + * Set the minimum keys per page. + */ +static int +__bam_set_bt_minkey(dbp, bt_minkey) + DB *dbp; + u_int32_t bt_minkey; +{ + BTREE *t; + + DB_ILLEGAL_AFTER_OPEN(dbp, "DB->set_bt_minkey"); + DB_ILLEGAL_METHOD(dbp, DB_OK_BTREE); + + t = dbp->bt_internal; + + if (bt_minkey < 2) { + __db_errx(dbp->env, DB_STR("1031", + "minimum bt_minkey value is 2")); + return (EINVAL); + } + + t->bt_minkey = bt_minkey; + return (0); +} + +/* + * __bam_get_bt_prefix -- + * Get the prefix function. + */ +static int +__bam_get_bt_prefix(dbp, funcp) + DB *dbp; + size_t (**funcp) __P((DB *, const DBT *, const DBT *)); +{ + BTREE *t; + + DB_ILLEGAL_METHOD(dbp, DB_OK_BTREE); + + t = dbp->bt_internal; + if (funcp != NULL) + *funcp = t->bt_prefix; + return (0); +} + +/* + * __bam_set_bt_prefix -- + * Set the prefix function. + */ +static int +__bam_set_bt_prefix(dbp, func) + DB *dbp; + size_t (*func) __P((DB *, const DBT *, const DBT *)); +{ + BTREE *t; + + DB_ILLEGAL_AFTER_OPEN(dbp, "DB->set_bt_prefix"); + DB_ILLEGAL_METHOD(dbp, DB_OK_BTREE); + + t = dbp->bt_internal; + + t->bt_prefix = func; + return (0); +} + +/* + * __bam_copy_config + * Copy the configuration of one DB handle to another. + * PUBLIC: void __bam_copy_config __P((DB *, DB*, u_int32_t)); + */ +void +__bam_copy_config(src, dst, nparts) + DB *src, *dst; + u_int32_t nparts; +{ + BTREE *s, *d; + + COMPQUIET(nparts, 0); + + s = src->bt_internal; + d = dst->bt_internal; + d->bt_compare = s->bt_compare; + d->bt_minkey = s->bt_minkey; + d->bt_minkey = s->bt_minkey; + d->bt_prefix = s->bt_prefix; +#ifdef HAVE_COMPRESSION + d->bt_compress = s->bt_compress; + d->bt_decompress = s->bt_decompress; + d->compress_dup_compare = s->compress_dup_compare; +#endif +} + +/* + * __ram_map_flags -- + * Map Recno specific flags from public to the internal values. + * + * PUBLIC: void __ram_map_flags __P((DB *, u_int32_t *, u_int32_t *)); + */ +void +__ram_map_flags(dbp, inflagsp, outflagsp) + DB *dbp; + u_int32_t *inflagsp, *outflagsp; +{ + COMPQUIET(dbp, NULL); + + if (FLD_ISSET(*inflagsp, DB_RENUMBER)) { + FLD_SET(*outflagsp, DB_AM_RENUMBER); + FLD_CLR(*inflagsp, DB_RENUMBER); + } + if (FLD_ISSET(*inflagsp, DB_SNAPSHOT)) { + FLD_SET(*outflagsp, DB_AM_SNAPSHOT); + FLD_CLR(*inflagsp, DB_SNAPSHOT); + } +} + +/* + * __ram_set_flags -- + * Set Recno specific flags. + * + * PUBLIC: int __ram_set_flags __P((DB *, u_int32_t *flagsp)); + */ +int +__ram_set_flags(dbp, flagsp) + DB *dbp; + u_int32_t *flagsp; +{ + u_int32_t flags; + + flags = *flagsp; + if (LF_ISSET(DB_RENUMBER | DB_SNAPSHOT)) { + DB_ILLEGAL_AFTER_OPEN(dbp, "DB->set_flags"); + DB_ILLEGAL_METHOD(dbp, DB_OK_RECNO); + } + + __ram_map_flags(dbp, flagsp, &dbp->flags); + return (0); +} + +/* + * __db_get_re_delim -- + * Get the variable-length input record delimiter. + */ +static int +__ram_get_re_delim(dbp, re_delimp) + DB *dbp; + int *re_delimp; +{ + BTREE *t; + + DB_ILLEGAL_METHOD(dbp, DB_OK_RECNO); + t = dbp->bt_internal; + *re_delimp = t->re_delim; + return (0); +} + +/* + * __ram_set_re_delim -- + * Set the variable-length input record delimiter. + */ +static int +__ram_set_re_delim(dbp, re_delim) + DB *dbp; + int re_delim; +{ + BTREE *t; + + DB_ILLEGAL_AFTER_OPEN(dbp, "DB->set_re_delim"); + DB_ILLEGAL_METHOD(dbp, DB_OK_RECNO); + + t = dbp->bt_internal; + + t->re_delim = re_delim; + F_SET(dbp, DB_AM_DELIMITER); + + return (0); +} + +/* + * __db_get_re_len -- + * Get the variable-length input record length. + * + * PUBLIC: int __ram_get_re_len __P((DB *, u_int32_t *)); + */ +int +__ram_get_re_len(dbp, re_lenp) + DB *dbp; + u_int32_t *re_lenp; +{ + BTREE *t; + QUEUE *q; + + DB_ILLEGAL_METHOD(dbp, DB_OK_QUEUE | DB_OK_RECNO); + + /* + * This has to work for all access methods, before or after opening the + * database. When the record length is set with __ram_set_re_len, the + * value in both the BTREE and QUEUE structs will be correct. + * Otherwise, this only makes sense after the database in opened, in + * which case we know the type. + */ + if (dbp->type == DB_QUEUE) { + q = dbp->q_internal; + *re_lenp = q->re_len; + } else { + t = dbp->bt_internal; + *re_lenp = t->re_len; + } + + return (0); +} + +/* + * __ram_set_re_len -- + * Set the variable-length input record length. + */ +static int +__ram_set_re_len(dbp, re_len) + DB *dbp; + u_int32_t re_len; +{ + BTREE *t; +#ifdef HAVE_QUEUE + QUEUE *q; +#endif + + DB_ILLEGAL_AFTER_OPEN(dbp, "DB->set_re_len"); + DB_ILLEGAL_METHOD(dbp, DB_OK_QUEUE | DB_OK_RECNO); + + t = dbp->bt_internal; + t->re_len = re_len; + +#ifdef HAVE_QUEUE + q = dbp->q_internal; + q->re_len = re_len; +#endif + + F_SET(dbp, DB_AM_FIXEDLEN); + + return (0); +} + +/* + * __db_get_re_pad -- + * Get the fixed-length record pad character. + * + * PUBLIC: int __ram_get_re_pad __P((DB *, int *)); + */ +int +__ram_get_re_pad(dbp, re_padp) + DB *dbp; + int *re_padp; +{ + BTREE *t; + QUEUE *q; + + DB_ILLEGAL_METHOD(dbp, DB_OK_QUEUE | DB_OK_RECNO); + + /* + * This has to work for all access methods, before or after opening the + * database. When the record length is set with __ram_set_re_pad, the + * value in both the BTREE and QUEUE structs will be correct. + * Otherwise, this only makes sense after the database in opened, in + * which case we know the type. + */ + if (dbp->type == DB_QUEUE) { + q = dbp->q_internal; + *re_padp = q->re_pad; + } else { + t = dbp->bt_internal; + *re_padp = t->re_pad; + } + + return (0); +} + +/* + * __ram_set_re_pad -- + * Set the fixed-length record pad character. + */ +static int +__ram_set_re_pad(dbp, re_pad) + DB *dbp; + int re_pad; +{ + BTREE *t; +#ifdef HAVE_QUEUE + QUEUE *q; +#endif + + DB_ILLEGAL_AFTER_OPEN(dbp, "DB->set_re_pad"); + DB_ILLEGAL_METHOD(dbp, DB_OK_QUEUE | DB_OK_RECNO); + + t = dbp->bt_internal; + t->re_pad = re_pad; + +#ifdef HAVE_QUEUE + q = dbp->q_internal; + q->re_pad = re_pad; +#endif + + F_SET(dbp, DB_AM_PAD); + + return (0); +} + +/* + * __db_get_re_source -- + * Get the backing source file name. + */ +static int +__ram_get_re_source(dbp, re_sourcep) + DB *dbp; + const char **re_sourcep; +{ + BTREE *t; + + DB_ILLEGAL_METHOD(dbp, DB_OK_RECNO); + + t = dbp->bt_internal; + *re_sourcep = t->re_source; + return (0); +} + +/* + * __ram_set_re_source -- + * Set the backing source file name. + */ +static int +__ram_set_re_source(dbp, re_source) + DB *dbp; + const char *re_source; +{ + BTREE *t; + + DB_ILLEGAL_AFTER_OPEN(dbp, "DB->set_re_source"); + DB_ILLEGAL_METHOD(dbp, DB_OK_RECNO); + + t = dbp->bt_internal; + + return (__os_strdup(dbp->env, re_source, &t->re_source)); +} diff -r 000000000000 -r a1985f14b030 src/btree/bt_open.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/btree/bt_open.c Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,699 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 1996, 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +/* + * Copyright (c) 1990, 1993, 1994, 1995, 1996 + * Keith Bostic. All rights reserved. + */ +/* + * Copyright (c) 1990, 1993, 1994, 1995 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Mike Olson. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $Id$ + */ + +#include "db_config.h" + +#include "db_int.h" +#include "dbinc/crypto.h" +#include "dbinc/db_page.h" +#include "dbinc/db_swap.h" +#include "dbinc/btree.h" +#include "dbinc/lock.h" +#include "dbinc/mp.h" +#include "dbinc/partition.h" +#include "dbinc/fop.h" + +static void __bam_init_meta __P((DB *, BTMETA *, db_pgno_t, DB_LSN *)); + +/* + * __bam_open -- + * Open a btree. + * + * PUBLIC: int __bam_open __P((DB *, DB_THREAD_INFO *, + * PUBLIC: DB_TXN *, const char *, db_pgno_t, u_int32_t)); + */ +int +__bam_open(dbp, ip, txn, name, base_pgno, flags) + DB *dbp; + DB_THREAD_INFO *ip; + DB_TXN *txn; + const char *name; + db_pgno_t base_pgno; + u_int32_t flags; +{ + BTREE *t; + + COMPQUIET(name, NULL); + t = dbp->bt_internal; + + /* + * We don't permit the user to specify a prefix routine if they didn't + * also specify a comparison routine, they can't know enough about our + * comparison routine to get it right. + */ + if (t->bt_compare == __bam_defcmp && t->bt_prefix != __bam_defpfx) { + __db_errx(dbp->env, DB_STR("1006", +"prefix comparison may not be specified for default comparison routine")); + return (EINVAL); + } + + /* + * Verify that the bt_minkey value specified won't cause the + * calculation of ovflsize to underflow [#2406] for this pagesize. + */ + if (B_MINKEY_TO_OVFLSIZE(dbp, t->bt_minkey, dbp->pgsize) > + B_MINKEY_TO_OVFLSIZE(dbp, DEFMINKEYPAGE, dbp->pgsize)) { + __db_errx(dbp->env, DB_STR_A("1007", + "bt_minkey value of %lu too high for page size of %lu", + "%lu %lu"), (u_long)t->bt_minkey, (u_long)dbp->pgsize); + return (EINVAL); + } + + /* Start up the tree. */ + return (__bam_read_root(dbp, ip, txn, base_pgno, flags)); +} + +/* + * __bam_metachk -- + * + * PUBLIC: int __bam_metachk __P((DB *, const char *, BTMETA *)); + */ +int +__bam_metachk(dbp, name, btm) + DB *dbp; + const char *name; + BTMETA *btm; +{ + ENV *env; + u_int32_t vers; + int ret; + + env = dbp->env; + + /* + * At this point, all we know is that the magic number is for a Btree. + * Check the version, the database may be out of date. + */ + vers = btm->dbmeta.version; + if (F_ISSET(dbp, DB_AM_SWAP)) + M_32_SWAP(vers); + switch (vers) { + case 6: + case 7: + __db_errx(env, DB_STR_A("1008", + "%s: btree version %lu requires a version upgrade", + "%s %lu"), name, (u_long)vers); + return (DB_OLD_VERSION); + case 8: + case 9: + break; + default: + __db_errx(env, DB_STR_A("1009", + "%s: unsupported btree version: %lu", "%s %lu"), + name, (u_long)vers); + return (EINVAL); + } + + /* Swap the page if we need to. */ + if (F_ISSET(dbp, DB_AM_SWAP) && + (ret = __bam_mswap(env, (PAGE *)btm)) != 0) + return (ret); + + /* + * Check application info against metadata info, and set info, flags, + * and type based on metadata info. + */ + if ((ret = + __db_fchk(env, "DB->open", btm->dbmeta.flags, BTM_MASK)) != 0) + return (ret); + + if (F_ISSET(&btm->dbmeta, BTM_RECNO)) { + if (dbp->type == DB_BTREE) + goto wrong_type; + dbp->type = DB_RECNO; + DB_ILLEGAL_METHOD(dbp, DB_OK_RECNO); + } else { + if (dbp->type == DB_RECNO) + goto wrong_type; + dbp->type = DB_BTREE; + DB_ILLEGAL_METHOD(dbp, DB_OK_BTREE); + } + + if (F_ISSET(&btm->dbmeta, BTM_DUP)) + F_SET(dbp, DB_AM_DUP); + else + if (F_ISSET(dbp, DB_AM_DUP)) { + __db_errx(env, DB_STR_A("1010", + "%s: DB_DUP specified to open method but not set in database", + "%s"), name); + return (EINVAL); + } + + if (F_ISSET(&btm->dbmeta, BTM_RECNUM)) { + if (dbp->type != DB_BTREE) + goto wrong_type; + F_SET(dbp, DB_AM_RECNUM); + + if ((ret = __db_fcchk(env, + "DB->open", dbp->flags, DB_AM_DUP, DB_AM_RECNUM)) != 0) + return (ret); + } else + if (F_ISSET(dbp, DB_AM_RECNUM)) { + __db_errx(env, DB_STR_A("1011", + "%s: DB_RECNUM specified to open method but not set in database", + "%s"), name); + return (EINVAL); + } + + if (F_ISSET(&btm->dbmeta, BTM_FIXEDLEN)) { + if (dbp->type != DB_RECNO) + goto wrong_type; + F_SET(dbp, DB_AM_FIXEDLEN); + } else + if (F_ISSET(dbp, DB_AM_FIXEDLEN)) { + __db_errx(env, DB_STR_A("1012", + "%s: DB_FIXEDLEN specified to open method but not set in database", + "%s"), name); + return (EINVAL); + } + + if (F_ISSET(&btm->dbmeta, BTM_RENUMBER)) { + if (dbp->type != DB_RECNO) + goto wrong_type; + F_SET(dbp, DB_AM_RENUMBER); + } else + if (F_ISSET(dbp, DB_AM_RENUMBER)) { + __db_errx(env, DB_STR_A("1013", + "%s: DB_RENUMBER specified to open method but not set in database", + "%s"), name); + return (EINVAL); + } + + if (F_ISSET(&btm->dbmeta, BTM_SUBDB)) + F_SET(dbp, DB_AM_SUBDB); + else + if (F_ISSET(dbp, DB_AM_SUBDB)) { + __db_errx(env, DB_STR_A("1014", + "%s: multiple databases specified but not supported by file", + "%s"), name); + return (EINVAL); + } + + if (F_ISSET(&btm->dbmeta, BTM_DUPSORT)) { + if (dbp->dup_compare == NULL) + dbp->dup_compare = __bam_defcmp; + F_SET(dbp, DB_AM_DUPSORT); + } else + if (dbp->dup_compare != NULL) { + __db_errx(env, DB_STR_A("1015", + "%s: duplicate sort specified but not supported in database", + "%s"), name); + return (EINVAL); + } + +#ifdef HAVE_COMPRESSION + if (F_ISSET(&btm->dbmeta, BTM_COMPRESS)) { + F_SET(dbp, DB_AM_COMPRESS); + if ((BTREE *)dbp->bt_internal != NULL && + !DB_IS_COMPRESSED(dbp) && + (ret = __bam_set_bt_compress(dbp, NULL, NULL)) != 0) + return (ret); + } else { + if ((BTREE *)dbp->bt_internal != NULL && + DB_IS_COMPRESSED(dbp)) { + __db_errx(env, DB_STR_A("1016", + "%s: compresssion specified to open method but not set in database", + "%s"), name); + return (EINVAL); + } + } +#else + if (F_ISSET(&btm->dbmeta, BTM_COMPRESS)) { + __db_errx(env, DB_STR_A("1017", + "%s: compression support has not been compiled in", "%s"), + name); + return (EINVAL); + } +#endif + + /* Set the page size. */ + dbp->pgsize = btm->dbmeta.pagesize; + + /* Copy the file's ID. */ + memcpy(dbp->fileid, btm->dbmeta.uid, DB_FILE_ID_LEN); + + return (0); + +wrong_type: + if (dbp->type == DB_BTREE) + __db_errx(env, DB_STR("1018", + "open method type is Btree, database type is Recno")); + else + __db_errx(env, DB_STR("1019", + "open method type is Recno, database type is Btree")); + return (EINVAL); +} + +/* + * __bam_read_root -- + * Read the root page and check a tree. + * + * PUBLIC: int __bam_read_root __P((DB *, + * PUBLIC: DB_THREAD_INFO *, DB_TXN *, db_pgno_t, u_int32_t)); + */ +int +__bam_read_root(dbp, ip, txn, base_pgno, flags) + DB *dbp; + DB_THREAD_INFO *ip; + DB_TXN *txn; + db_pgno_t base_pgno; + u_int32_t flags; +{ + BTMETA *meta; + BTREE *t; + DBC *dbc; + DB_LOCK metalock; + DB_MPOOLFILE *mpf; + int ret, t_ret; + + COMPQUIET(flags, 0); + + meta = NULL; + t = dbp->bt_internal; + LOCK_INIT(metalock); + mpf = dbp->mpf; + ret = 0; + + /* Get a cursor. */ + if ((ret = __db_cursor(dbp, ip, txn, &dbc, + F_ISSET(dbp, DB_AM_RECOVER) ? DB_RECOVER : 0)) != 0) + return (ret); + + /* Get the metadata page. */ + if ((ret = + __db_lget(dbc, 0, base_pgno, DB_LOCK_READ, 0, &metalock)) != 0) + goto err; + if ((ret = __memp_fget(mpf, &base_pgno, ip, dbc->txn, 0, &meta)) != 0) + goto err; + + /* + * If the magic number is set, the tree has been created. Correct + * any fields that may not be right. Note, all of the local flags + * were set by DB->open. + * + * Otherwise, we'd better be in recovery or abort, in which case the + * metadata page will be created/initialized elsewhere. + * + * Ignore the last_pgno on the metadata page for snapshot transactions: + * we may be reading an old version of the page, and we've already + * set last_pgno from the file size. The only time this would matter + * is if we don't have ftruncate and there are some free pages at the + * end of the file: we could end up with holes. + */ + if (meta->dbmeta.magic == DB_BTREEMAGIC) { + t->bt_minkey = meta->minkey; + t->re_pad = (int)meta->re_pad; + t->re_len = meta->re_len; + + t->bt_meta = base_pgno; + t->bt_root = meta->root; + t->revision = dbp->mpf->mfp->revision; + if (PGNO(meta) == PGNO_BASE_MD && + !F_ISSET(dbp, DB_AM_RECOVER) && + (txn == NULL || !F_ISSET(txn, TXN_SNAPSHOT)) && (ret = + __memp_set_last_pgno(mpf, meta->dbmeta.last_pgno)) != 0) + goto err; + } else { + DB_ASSERT(dbp->env, + IS_RECOVERING(dbp->env) || F_ISSET(dbp, DB_AM_RECOVER)); + } + + /* + * !!! + * If creating a subdatabase, we've already done an insert when + * we put the subdatabase's entry into the master database, so + * our last-page-inserted value is wrongly initialized for the + * master database, not the subdatabase we're creating. I'm not + * sure where the *right* place to clear this value is, it's not + * intuitively obvious that it belongs here. + */ + t->bt_lpgno = PGNO_INVALID; + +err: /* Put the metadata page back. */ + if (meta != NULL && (t_ret = __memp_fput(mpf, + ip, meta, dbc->priority)) != 0 && ret == 0) + ret = t_ret; + if ((t_ret = __LPUT(dbc, metalock)) != 0 && ret == 0) + ret = t_ret; + + if ((t_ret = __dbc_close(dbc)) != 0 && ret == 0) + ret = t_ret; + return (ret); +} + +/* + * __bam_init_meta -- + * + * Initialize a btree meta-data page. The following fields may need + * to be updated later: last_pgno, root. + */ +static void +__bam_init_meta(dbp, meta, pgno, lsnp) + DB *dbp; + BTMETA *meta; + db_pgno_t pgno; + DB_LSN *lsnp; +{ + BTREE *t; +#ifdef HAVE_PARTITION + DB_PARTITION *part; +#endif + ENV *env; + + env = dbp->env; + t = dbp->bt_internal; + + memset(meta, 0, sizeof(BTMETA)); + meta->dbmeta.lsn = *lsnp; + meta->dbmeta.pgno = pgno; + meta->dbmeta.magic = DB_BTREEMAGIC; + meta->dbmeta.version = DB_BTREEVERSION; + meta->dbmeta.pagesize = dbp->pgsize; + if (F_ISSET(dbp, DB_AM_CHKSUM)) + FLD_SET(meta->dbmeta.metaflags, DBMETA_CHKSUM); + if (F_ISSET(dbp, DB_AM_ENCRYPT)) { + meta->dbmeta.encrypt_alg = env->crypto_handle->alg; + DB_ASSERT(env, meta->dbmeta.encrypt_alg != 0); + meta->crypto_magic = meta->dbmeta.magic; + } + meta->dbmeta.type = P_BTREEMETA; + meta->dbmeta.free = PGNO_INVALID; + meta->dbmeta.last_pgno = pgno; + if (F_ISSET(dbp, DB_AM_DUP)) + F_SET(&meta->dbmeta, BTM_DUP); + if (F_ISSET(dbp, DB_AM_FIXEDLEN)) + F_SET(&meta->dbmeta, BTM_FIXEDLEN); + if (F_ISSET(dbp, DB_AM_RECNUM)) + F_SET(&meta->dbmeta, BTM_RECNUM); + if (F_ISSET(dbp, DB_AM_RENUMBER)) + F_SET(&meta->dbmeta, BTM_RENUMBER); + if (F_ISSET(dbp, DB_AM_SUBDB)) + F_SET(&meta->dbmeta, BTM_SUBDB); + if (dbp->dup_compare != NULL) + F_SET(&meta->dbmeta, BTM_DUPSORT); +#ifdef HAVE_COMPRESSION + if (DB_IS_COMPRESSED(dbp)) + F_SET(&meta->dbmeta, BTM_COMPRESS); +#endif + if (dbp->type == DB_RECNO) + F_SET(&meta->dbmeta, BTM_RECNO); + memcpy(meta->dbmeta.uid, dbp->fileid, DB_FILE_ID_LEN); + + meta->minkey = t->bt_minkey; + meta->re_len = t->re_len; + meta->re_pad = (u_int32_t)t->re_pad; + +#ifdef HAVE_PARTITION + if ((part = dbp->p_internal) != NULL) { + meta->dbmeta.nparts = part->nparts; + if (F_ISSET(part, PART_CALLBACK)) + FLD_SET(meta->dbmeta.metaflags, DBMETA_PART_CALLBACK); + if (F_ISSET(part, PART_RANGE)) + FLD_SET(meta->dbmeta.metaflags, DBMETA_PART_RANGE); + } +#endif +} + +/* + * __bam_new_file -- + * Create the necessary pages to begin a new database file. + * + * This code appears more complex than it is because of the two cases (named + * and unnamed). The way to read the code is that for each page being created, + * there are three parts: 1) a "get page" chunk (which either uses malloc'd + * memory or calls __memp_fget), 2) the initialization, and 3) the "put page" + * chunk which either does a fop write or an __memp_fput. + * + * PUBLIC: int __bam_new_file __P((DB *, + * PUBLIC: DB_THREAD_INFO *, DB_TXN *, DB_FH *, const char *)); + */ +int +__bam_new_file(dbp, ip, txn, fhp, name) + DB *dbp; + DB_THREAD_INFO *ip; + DB_TXN *txn; + DB_FH *fhp; + const char *name; +{ + BTMETA *meta; + DBT pdbt; + DB_LSN lsn; + DB_MPOOLFILE *mpf; + DB_PGINFO pginfo; + ENV *env; + PAGE *root; + db_pgno_t pgno; + int ret, t_ret; + void *buf; + + env = dbp->env; + mpf = dbp->mpf; + root = NULL; + meta = NULL; + buf = NULL; + + if (F_ISSET(dbp, DB_AM_INMEM)) { + /* Build the meta-data page. */ + pgno = PGNO_BASE_MD; + if ((ret = __memp_fget(mpf, &pgno, + ip, txn, DB_MPOOL_CREATE | DB_MPOOL_DIRTY, &meta)) != 0) + return (ret); + LSN_NOT_LOGGED(lsn); + __bam_init_meta(dbp, meta, PGNO_BASE_MD, &lsn); + meta->root = 1; + meta->dbmeta.last_pgno = 1; + if ((ret = + __db_log_page(dbp, txn, &lsn, pgno, (PAGE *)meta)) != 0) + goto err; + ret = __memp_fput(mpf, ip, meta, dbp->priority); + meta = NULL; + if (ret != 0) + goto err; + + /* Build the root page. */ + pgno = 1; + if ((ret = __memp_fget(mpf, &pgno, + ip, txn, DB_MPOOL_CREATE | DB_MPOOL_DIRTY, &root)) != 0) + goto err; + P_INIT(root, dbp->pgsize, 1, PGNO_INVALID, PGNO_INVALID, + LEAFLEVEL, dbp->type == DB_RECNO ? P_LRECNO : P_LBTREE); + LSN_NOT_LOGGED(root->lsn); + if ((ret = + __db_log_page(dbp, txn, &root->lsn, pgno, root)) != 0) + goto err; + ret = __memp_fput(mpf, ip, root, dbp->priority); + root = NULL; + if (ret != 0) + goto err; + } else { + memset(&pdbt, 0, sizeof(pdbt)); + + /* Build the meta-data page. */ + pginfo.db_pagesize = dbp->pgsize; + pginfo.flags = + F_ISSET(dbp, (DB_AM_CHKSUM | DB_AM_ENCRYPT | DB_AM_SWAP)); + pginfo.type = dbp->type; + pdbt.data = &pginfo; + pdbt.size = sizeof(pginfo); + if ((ret = __os_calloc(env, 1, dbp->pgsize, &buf)) != 0) + return (ret); + meta = (BTMETA *)buf; + LSN_NOT_LOGGED(lsn); + __bam_init_meta(dbp, meta, PGNO_BASE_MD, &lsn); + meta->root = 1; + meta->dbmeta.last_pgno = 1; + if ((ret = __db_pgout( + dbp->dbenv, PGNO_BASE_MD, meta, &pdbt)) != 0) + goto err; + if ((ret = __fop_write(env, txn, name, dbp->dirname, + DB_APP_DATA, fhp, + dbp->pgsize, 0, 0, buf, dbp->pgsize, 1, F_ISSET( + dbp, DB_AM_NOT_DURABLE) ? DB_LOG_NOT_DURABLE : 0)) != 0) + goto err; + meta = NULL; + + /* Build the root page. */ +#ifdef DIAGNOSTIC + memset(buf, CLEAR_BYTE, dbp->pgsize); +#endif + root = (PAGE *)buf; + P_INIT(root, dbp->pgsize, 1, PGNO_INVALID, PGNO_INVALID, + LEAFLEVEL, dbp->type == DB_RECNO ? P_LRECNO : P_LBTREE); + LSN_NOT_LOGGED(root->lsn); + if ((ret = + __db_pgout(dbp->dbenv, root->pgno, root, &pdbt)) != 0) + goto err; + if ((ret = + __fop_write(env, txn, name, dbp->dirname, DB_APP_DATA, + fhp, dbp->pgsize, 1, 0, buf, dbp->pgsize, 1, F_ISSET( + dbp, DB_AM_NOT_DURABLE) ? DB_LOG_NOT_DURABLE : 0)) != 0) + goto err; + root = NULL; + } + +err: if (buf != NULL) + __os_free(env, buf); + else { + if (meta != NULL && + (t_ret = __memp_fput(mpf, ip, + meta, dbp->priority)) != 0 && ret == 0) + ret = t_ret; + if (root != NULL && + (t_ret = __memp_fput(mpf, ip, + root, dbp->priority)) != 0 && ret == 0) + ret = t_ret; + } + return (ret); +} + +/* + * __bam_new_subdb -- + * Create a metadata page and a root page for a new btree. + * + * PUBLIC: int __bam_new_subdb __P((DB *, DB *, DB_THREAD_INFO *, DB_TXN *)); + */ +int +__bam_new_subdb(mdbp, dbp, ip, txn) + DB *mdbp, *dbp; + DB_THREAD_INFO *ip; + DB_TXN *txn; +{ + BTMETA *meta; + DBC *dbc; + DB_LOCK metalock; + DB_LSN lsn; + DB_MPOOLFILE *mpf; + ENV *env; + PAGE *root; + int ret, t_ret; + + env = mdbp->env; + mpf = mdbp->mpf; + dbc = NULL; + meta = NULL; + root = NULL; + + if ((ret = __db_cursor(mdbp, ip, txn, + &dbc, CDB_LOCKING(env) ? DB_WRITECURSOR : 0)) != 0) + return (ret); + + /* Get, and optionally create the metadata page. */ + if ((ret = __db_lget(dbc, + 0, dbp->meta_pgno, DB_LOCK_WRITE, 0, &metalock)) != 0) + goto err; + if ((ret = __memp_fget(mpf, &dbp->meta_pgno, + ip, txn, DB_MPOOL_CREATE | DB_MPOOL_DIRTY, &meta)) != 0) + goto err; + + /* Build meta-data page. */ + lsn = meta->dbmeta.lsn; + __bam_init_meta(dbp, meta, dbp->meta_pgno, &lsn); + if ((ret = __db_log_page(mdbp, + txn, &meta->dbmeta.lsn, dbp->meta_pgno, (PAGE *)meta)) != 0) + goto err; + + /* Create and initialize a root page. */ + if ((ret = __db_new(dbc, + dbp->type == DB_RECNO ? P_LRECNO : P_LBTREE, NULL, &root)) != 0) + goto err; + root->level = LEAFLEVEL; + + if (DBENV_LOGGING(env) && +#if !defined(DEBUG_WOP) + txn != NULL && +#endif + + (ret = __bam_root_log(mdbp, txn, &meta->dbmeta.lsn, 0, + meta->dbmeta.pgno, root->pgno, &meta->dbmeta.lsn)) != 0) + goto err; + + meta->root = root->pgno; + if ((ret = + __db_log_page(mdbp, txn, &root->lsn, root->pgno, root)) != 0) + goto err; + + /* Release the metadata and root pages. */ + if ((ret = __memp_fput(mpf, ip, meta, dbc->priority)) != 0) + goto err; + meta = NULL; + if ((ret = __memp_fput(mpf, ip, root, dbc->priority)) != 0) + goto err; + root = NULL; +err: + if (meta != NULL) + if ((t_ret = __memp_fput(mpf, ip, + meta, dbc->priority)) != 0 && ret == 0) + ret = t_ret; + if (root != NULL) + if ((t_ret = __memp_fput(mpf, ip, + root, dbc->priority)) != 0 && ret == 0) + ret = t_ret; + if ((t_ret = __LPUT(dbc, metalock)) != 0 && ret == 0) + ret = t_ret; + if (dbc != NULL) + if ((t_ret = __dbc_close(dbc)) != 0 && ret == 0) + ret = t_ret; + return (ret); +} diff -r 000000000000 -r a1985f14b030 src/btree/bt_put.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/btree/bt_put.c Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,1109 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 1996, 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +/* + * Copyright (c) 1990, 1993, 1994, 1995, 1996 + * Keith Bostic. All rights reserved. + */ +/* + * Copyright (c) 1990, 1993, 1994, 1995 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Mike Olson. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $Id$ + */ + +#include "db_config.h" + +#include "db_int.h" +#include "dbinc/db_page.h" +#include "dbinc/btree.h" +#include "dbinc/lock.h" +#include "dbinc/mp.h" + +static int __bam_build + __P((DBC *, u_int32_t, DBT *, PAGE *, u_int32_t, u_int32_t)); +static int __bam_dup_check __P((DBC *, u_int32_t, + PAGE *, u_int32_t, u_int32_t, db_indx_t *)); +static int __bam_dup_convert __P((DBC *, PAGE *, u_int32_t, u_int32_t)); +static int __bam_ovput + __P((DBC *, u_int32_t, db_pgno_t, PAGE *, u_int32_t, DBT *)); +static u_int32_t + __bam_partsize __P((DB *, u_int32_t, DBT *, PAGE *, u_int32_t)); + +/* + * __bam_iitem -- + * Insert an item into the tree. + * + * PUBLIC: int __bam_iitem __P((DBC *, DBT *, DBT *, u_int32_t, u_int32_t)); + */ +int +__bam_iitem(dbc, key, data, op, flags) + DBC *dbc; + DBT *key, *data; + u_int32_t op, flags; +{ + BKEYDATA *bk, bk_tmp; + BTREE *t; + BTREE_CURSOR *cp; + DB *dbp; + DBT bk_hdr, tdbt; + DB_MPOOLFILE *mpf; + ENV *env; + PAGE *h; + db_indx_t cnt, indx; + u_int32_t data_size, have_bytes, need_bytes, needed, pages, pagespace; + char tmp_ch; + int cmp, bigkey, bigdata, del, dupadjust; + int padrec, replace, ret, t_ret, was_deleted; + + COMPQUIET(cnt, 0); + + dbp = dbc->dbp; + env = dbp->env; + mpf = dbp->mpf; + cp = (BTREE_CURSOR *)dbc->internal; + t = dbp->bt_internal; + h = cp->page; + indx = cp->indx; + del = dupadjust = replace = was_deleted = 0; + + /* + * Fixed-length records with partial puts: it's an error to specify + * anything other simple overwrite. + */ + if (F_ISSET(dbp, DB_AM_FIXEDLEN) && + F_ISSET(data, DB_DBT_PARTIAL) && data->size != data->dlen) + return (__db_rec_repl(env, data->size, data->dlen)); + + /* + * Figure out how much space the data will take, including if it's a + * partial record. + * + * Fixed-length records: it's an error to specify a record that's + * longer than the fixed-length, and we never require less than + * the fixed-length record size. + */ + data_size = F_ISSET(data, DB_DBT_PARTIAL) ? + __bam_partsize(dbp, op, data, h, indx) : data->size; + padrec = 0; + if (F_ISSET(dbp, DB_AM_FIXEDLEN)) { + if (data_size > t->re_len) + return (__db_rec_toobig(env, data_size, t->re_len)); + + /* Records that are deleted anyway needn't be padded out. */ + if (!LF_ISSET(BI_DELETED) && data_size < t->re_len) { + padrec = 1; + data_size = t->re_len; + } + } + + /* + * Handle partial puts or short fixed-length records: check whether we + * can just append the data or else build the real record. We can't + * append if there are secondaries: we need the whole data item for the + * application's secondary callback. + */ + if (op == DB_CURRENT && dbp->dup_compare == NULL && + F_ISSET(data, DB_DBT_PARTIAL) && !DB_IS_PRIMARY(dbp)) { + bk = GET_BKEYDATA( + dbp, h, indx + (TYPE(h) == P_LBTREE ? O_INDX : 0)); + /* + * If the item is an overflow type, and the input DBT is + * partial, and begins at the length of the current item then + * it is an append. Avoid deleting and re-creating the entire + * offpage item. + */ + if (B_TYPE(bk->type) == B_OVERFLOW && + data->doff == ((BOVERFLOW *)bk)->tlen) { + /* + * If the cursor has not already cached the last page + * in the offpage chain. We need to walk the chain + * to be sure that the page has been read. + */ + if (cp->stream_start_pgno != ((BOVERFLOW *)bk)->pgno || + cp->stream_off > data->doff || data->doff > + cp->stream_off + P_MAXSPACE(dbp, dbp->pgsize)) { + memset(&tdbt, 0, sizeof(DBT)); + tdbt.doff = data->doff - 1; + /* + * Set the length to 1, to force __db_goff + * to do the traversal. + */ + tdbt.dlen = tdbt.ulen = 1; + tdbt.data = &tmp_ch; + tdbt.flags = DB_DBT_PARTIAL | DB_DBT_USERMEM; + + /* + * Read to the last page. It will be cached + * in the cursor. + */ + if ((ret = __db_goff( + dbc, &tdbt, ((BOVERFLOW *)bk)->tlen, + ((BOVERFLOW *)bk)->pgno, NULL, NULL)) != 0) + return (ret); + } + + /* + * Since this is an append, dlen is irrelevant (there + * are no bytes to overwrite). We need the caller's + * DBT size to end up with the total size of the item. + * From now on, use dlen as the length of the user's + * data that we are going to append. + * Don't futz with the caller's DBT any more than we + * have to in order to send back the size. + */ + tdbt = *data; + tdbt.dlen = data->size; + tdbt.size = data_size; + data = &tdbt; + F_SET(data, DB_DBT_STREAMING); + } + } + if (!F_ISSET(data, DB_DBT_STREAMING) && + (padrec || F_ISSET(data, DB_DBT_PARTIAL))) { + tdbt = *data; + if ((ret = + __bam_build(dbc, op, &tdbt, h, indx, data_size)) != 0) + return (ret); + data = &tdbt; + } + + /* + * If the user has specified a duplicate comparison function, return + * an error if DB_CURRENT was specified and the replacement data + * doesn't compare equal to the current data. This stops apps from + * screwing up the duplicate sort order. We have to do this after + * we build the real record so that we're comparing the real items. + */ + if (op == DB_CURRENT && dbp->dup_compare != NULL) { + if ((ret = __bam_cmp(dbc, data, h, + indx + (TYPE(h) == P_LBTREE ? O_INDX : 0), + dbp->dup_compare, &cmp)) != 0) + return (ret); + if (cmp != 0) { + __db_errx(env, DB_STR("1004", + "Existing data sorts differently from put data")); + return (EINVAL); + } + } + + /* + * If the key or data item won't fit on a page, we'll have to store + * them on overflow pages. + */ + needed = 0; + bigdata = data_size > cp->ovflsize; + switch (op) { + case DB_KEYFIRST: + /* We're adding a new key and data pair. */ + bigkey = key->size > cp->ovflsize; + if (bigkey) + needed += BOVERFLOW_PSIZE; + else + needed += BKEYDATA_PSIZE(key->size); + if (bigdata) + needed += BOVERFLOW_PSIZE; + else + needed += BKEYDATA_PSIZE(data_size); + break; + case DB_AFTER: + case DB_BEFORE: + case DB_CURRENT: + /* + * We're either overwriting the data item of a key/data pair + * or we're creating a new on-page duplicate and only adding + * a data item. + * + * !!! + * We're not currently correcting for space reclaimed from + * already deleted items, but I don't think it's worth the + * complexity. + */ + bigkey = 0; + if (op == DB_CURRENT) { + bk = GET_BKEYDATA(dbp, h, + indx + (TYPE(h) == P_LBTREE ? O_INDX : 0)); + if (B_TYPE(bk->type) == B_KEYDATA) + have_bytes = BKEYDATA_PSIZE(bk->len); + else + have_bytes = BOVERFLOW_PSIZE; + need_bytes = 0; + } else { + have_bytes = 0; + need_bytes = sizeof(db_indx_t); + } + if (bigdata) + need_bytes += BOVERFLOW_PSIZE; + else + need_bytes += BKEYDATA_PSIZE(data_size); + + if (have_bytes < need_bytes) + needed += need_bytes - have_bytes; + break; + default: + return (__db_unknown_flag(env, "DB->put", op)); + } + + /* Split the page if there's not enough room. */ + if (P_FREESPACE(dbp, h) < needed) + return (DB_NEEDSPLIT); + + /* + * Check to see if we will convert to off page duplicates -- if + * so, we'll need a page. + */ + if (F_ISSET(dbp, DB_AM_DUP) && + TYPE(h) == P_LBTREE && op != DB_KEYFIRST && + P_FREESPACE(dbp, h) - needed <= dbp->pgsize / 2 && + __bam_dup_check(dbc, op, h, indx, needed, &cnt)) { + pages = 1; + dupadjust = 1; + } else + pages = 0; + + /* + * If we are not using transactions and there is a page limit + * set on the file, then figure out if things will fit before + * taking action. + */ + if (dbc->txn == NULL && mpf->mfp->maxpgno != 0) { + pagespace = P_MAXSPACE(dbp, dbp->pgsize); + if (bigdata) + pages += ((data_size - 1) / pagespace) + 1; + if (bigkey) + pages += ((key->size - 1) / pagespace) + 1; + + if (pages > (mpf->mfp->maxpgno - mpf->mfp->last_pgno)) + return (__db_space_err(dbp)); + } + + if (F_ISSET(dbc, DBC_OPD)) + LOCK_CHECK_OFF(dbc->thread_info); + ret = __memp_dirty(mpf, &h, + dbc->thread_info, dbc->txn, dbc->priority, 0); + if (cp->csp->page == cp->page) + cp->csp->page = h; + cp->page = h; + if (F_ISSET(dbc, DBC_OPD)) + LOCK_CHECK_ON(dbc->thread_info); + if (ret != 0) + return (ret); + + /* + * The code breaks it up into five cases: + * + * 1. Insert a new key/data pair. + * 2. Append a new data item (a new duplicate). + * 3. Insert a new data item (a new duplicate). + * 4. Delete and re-add the data item (overflow item). + * 5. Overwrite the data item. + */ + switch (op) { + case DB_KEYFIRST: /* 1. Insert a new key/data pair. */ + if (bigkey) { + if ((ret = __bam_ovput(dbc, + B_OVERFLOW, PGNO_INVALID, h, indx, key)) != 0) + return (ret); + } else + if ((ret = __db_pitem(dbc, h, indx, + BKEYDATA_SIZE(key->size), NULL, key)) != 0) + return (ret); + + if ((ret = __bam_ca_di(dbc, PGNO(h), indx, 1)) != 0) + return (ret); + ++indx; + break; + case DB_AFTER: /* 2. Append a new data item. */ + if (TYPE(h) == P_LBTREE) { + /* Copy the key for the duplicate and adjust cursors. */ + if ((ret = + __bam_adjindx(dbc, h, indx + P_INDX, indx, 1)) != 0) + return (ret); + if ((ret = + __bam_ca_di(dbc, PGNO(h), indx + P_INDX, 1)) != 0) + return (ret); + + indx += 3; + + cp->indx += 2; + } else { + ++indx; + cp->indx += 1; + } + break; + case DB_BEFORE: /* 3. Insert a new data item. */ + if (TYPE(h) == P_LBTREE) { + /* Copy the key for the duplicate and adjust cursors. */ + if ((ret = __bam_adjindx(dbc, h, indx, indx, 1)) != 0) + return (ret); + if ((ret = __bam_ca_di(dbc, PGNO(h), indx, 1)) != 0) + return (ret); + + ++indx; + } + break; + case DB_CURRENT: + /* + * Clear the cursor's deleted flag. The problem is that if + * we deadlock or fail while deleting the overflow item or + * replacing the non-overflow item, a subsequent cursor close + * will try and remove the item because the cursor's delete + * flag is set. + */ + if ((ret = __bam_ca_delete(dbp, PGNO(h), indx, 0, NULL)) != 0) + return (ret); + + if (TYPE(h) == P_LBTREE) + ++indx; + bk = GET_BKEYDATA(dbp, h, indx); + + /* + * In a Btree deleted records aren't counted (deleted records + * are counted in a Recno because all accesses are based on + * record number). If it's a Btree and it's a DB_CURRENT + * operation overwriting a previously deleted record, increment + * the record count. + */ + if (TYPE(h) == P_LBTREE || TYPE(h) == P_LDUP) + was_deleted = B_DISSET(bk->type); + + /* + * 4. Delete and re-add the data item. + * + * If we're changing the type of the on-page structure, or we + * are referencing offpage items, we have to delete and then + * re-add the item. We do not do any cursor adjustments here + * because we're going to immediately re-add the item into the + * same slot. + */ + if (bigdata || B_TYPE(bk->type) != B_KEYDATA) { + /* + * If streaming, don't delete the overflow item, + * just delete the item pointing to the overflow item. + * It will be added back in later, with the new size. + * We can't simply adjust the size of the item on the + * page, because there is no easy way to log a + * modification. + */ + if (F_ISSET(data, DB_DBT_STREAMING)) { + if ((ret = __db_ditem( + dbc, h, indx, BOVERFLOW_SIZE)) != 0) + return (ret); + } else if ((ret = __bam_ditem(dbc, h, indx)) != 0) + return (ret); + del = 1; + break; + } + + /* 5. Overwrite the data item. */ + replace = 1; + break; + default: + return (__db_unknown_flag(env, "DB->put", op)); + } + + /* Add the data. */ + if (bigdata) { + /* + * We do not have to handle deleted (BI_DELETED) records + * in this case; the actual records should never be created. + */ + DB_ASSERT(env, !LF_ISSET(BI_DELETED)); + ret = __bam_ovput(dbc, + B_OVERFLOW, PGNO_INVALID, h, indx, data); + } else { + if (LF_ISSET(BI_DELETED)) { + B_TSET_DELETED(bk_tmp.type, B_KEYDATA); + bk_tmp.len = data->size; + bk_hdr.data = &bk_tmp; + bk_hdr.size = SSZA(BKEYDATA, data); + ret = __db_pitem(dbc, h, indx, + BKEYDATA_SIZE(data->size), &bk_hdr, data); + } else if (replace) + ret = __bam_ritem(dbc, h, indx, data, 0); + else + ret = __db_pitem(dbc, h, indx, + BKEYDATA_SIZE(data->size), NULL, data); + } + if (ret != 0) { + if (del == 1 && (t_ret = + __bam_ca_di(dbc, PGNO(h), indx + 1, -1)) != 0) { + __db_err(env, t_ret, DB_STR("1005", + "cursor adjustment after delete failed")); + return (__env_panic(env, t_ret)); + } + return (ret); + } + + /* + * Re-position the cursors if necessary and reset the current cursor + * to point to the new item. + */ + if (op != DB_CURRENT) { + if ((ret = __bam_ca_di(dbc, PGNO(h), indx, 1)) != 0) + return (ret); + cp->indx = TYPE(h) == P_LBTREE ? indx - O_INDX : indx; + } + + /* + * If we've changed the record count, update the tree. There's no + * need to adjust the count if the operation not performed on the + * current record or when the current record was previously deleted. + */ + if (F_ISSET(cp, C_RECNUM) && (op != DB_CURRENT || was_deleted)) + if ((ret = __bam_adjust(dbc, 1)) != 0) + return (ret); + + /* + * If a Btree leaf page is at least 50% full and we may have added or + * modified a duplicate data item, see if the set of duplicates takes + * up at least 25% of the space on the page. If it does, move it onto + * its own page. + */ + if (dupadjust && + (ret = __bam_dup_convert(dbc, h, indx - O_INDX, cnt)) != 0) + return (ret); + + /* If we've modified a recno file, set the flag. */ + if (dbc->dbtype == DB_RECNO) + t->re_modified = 1; + + return (ret); +} + +/* + * __bam_partsize -- + * Figure out how much space a partial data item is in total. + */ +static u_int32_t +__bam_partsize(dbp, op, data, h, indx) + DB *dbp; + u_int32_t op, indx; + DBT *data; + PAGE *h; +{ + BKEYDATA *bk; + u_int32_t nbytes; + + /* + * If the record doesn't already exist, it's simply the data we're + * provided. + */ + if (op != DB_CURRENT) + return (data->doff + data->size); + + /* + * Otherwise, it's the data provided plus any already existing data + * that we're not replacing. + */ + bk = GET_BKEYDATA(dbp, h, indx + (TYPE(h) == P_LBTREE ? O_INDX : 0)); + nbytes = + B_TYPE(bk->type) == B_OVERFLOW ? ((BOVERFLOW *)bk)->tlen : bk->len; + + return (__db_partsize(nbytes, data)); +} + +/* + * __bam_build -- + * Build the real record for a partial put, or short fixed-length record. + */ +static int +__bam_build(dbc, op, dbt, h, indx, nbytes) + DBC *dbc; + u_int32_t op, indx, nbytes; + DBT *dbt; + PAGE *h; +{ + BKEYDATA *bk, tbk; + BOVERFLOW *bo; + BTREE *t; + DB *dbp; + DBT copy, *rdata; + u_int32_t len, tlen; + u_int8_t *p; + int ret; + + COMPQUIET(bo, NULL); + + dbp = dbc->dbp; + t = dbp->bt_internal; + + /* We use the record data return memory, it's only a short-term use. */ + rdata = &dbc->my_rdata; + if (rdata->ulen < nbytes) { + if ((ret = __os_realloc(dbp->env, + nbytes, &rdata->data)) != 0) { + rdata->ulen = 0; + rdata->data = NULL; + return (ret); + } + rdata->ulen = nbytes; + } + + /* + * We use nul or pad bytes for any part of the record that isn't + * specified; get it over with. + */ + memset(rdata->data, + F_ISSET(dbp, DB_AM_FIXEDLEN) ? t->re_pad : 0, nbytes); + + /* + * In the next clauses, we need to do three things: a) set p to point + * to the place at which to copy the user's data, b) set tlen to the + * total length of the record, not including the bytes contributed by + * the user, and c) copy any valid data from an existing record. If + * it's not a partial put (this code is called for both partial puts + * and fixed-length record padding) or it's a new key, we can cut to + * the chase. + */ + if (!F_ISSET(dbt, DB_DBT_PARTIAL) || op != DB_CURRENT) { + p = (u_int8_t *)rdata->data + dbt->doff; + tlen = dbt->doff; + goto user_copy; + } + + /* Find the current record. */ + if (indx < NUM_ENT(h)) { + bk = GET_BKEYDATA(dbp, h, indx + (TYPE(h) == P_LBTREE ? + O_INDX : 0)); + bo = (BOVERFLOW *)bk; + } else { + bk = &tbk; + B_TSET(bk->type, B_KEYDATA); + bk->len = 0; + } + if (B_TYPE(bk->type) == B_OVERFLOW) { + /* + * In the case of an overflow record, we shift things around + * in the current record rather than allocate a separate copy. + */ + memset(©, 0, sizeof(copy)); + if ((ret = __db_goff(dbc, ©, bo->tlen, bo->pgno, + &rdata->data, &rdata->ulen)) != 0) + return (ret); + + /* Skip any leading data from the original record. */ + tlen = dbt->doff; + p = (u_int8_t *)rdata->data + dbt->doff; + + /* + * Copy in any trailing data from the original record. + * + * If the original record was larger than the original offset + * plus the bytes being deleted, there is trailing data in the + * original record we need to preserve. If we aren't deleting + * the same number of bytes as we're inserting, copy it up or + * down, into place. + * + * Use memmove(), the regions may overlap. + */ + if (bo->tlen > dbt->doff + dbt->dlen) { + len = bo->tlen - (dbt->doff + dbt->dlen); + if (dbt->dlen != dbt->size) + memmove(p + dbt->size, p + dbt->dlen, len); + tlen += len; + } + } else { + /* Copy in any leading data from the original record. */ + memcpy(rdata->data, + bk->data, dbt->doff > bk->len ? bk->len : dbt->doff); + tlen = dbt->doff; + p = (u_int8_t *)rdata->data + dbt->doff; + + /* Copy in any trailing data from the original record. */ + len = dbt->doff + dbt->dlen; + if (bk->len > len) { + memcpy(p + dbt->size, bk->data + len, bk->len - len); + tlen += bk->len - len; + } + } + +user_copy: + /* + * Copy in the application provided data -- p and tlen must have been + * initialized above. + */ + memcpy(p, dbt->data, dbt->size); + tlen += dbt->size; + + /* Set the DBT to reference our new record. */ + rdata->size = F_ISSET(dbp, DB_AM_FIXEDLEN) ? t->re_len : tlen; + rdata->dlen = 0; + rdata->doff = 0; + rdata->flags = 0; + *dbt = *rdata; + return (0); +} + +/* + * __bam_ritem -- + * Replace an item on a page. + * + * PUBLIC: int __bam_ritem __P((DBC *, PAGE *, u_int32_t, DBT *, u_int32_t)); + */ +int +__bam_ritem(dbc, h, indx, data, typeflag) + DBC *dbc; + PAGE *h; + u_int32_t indx; + DBT *data; + u_int32_t typeflag; +{ + BKEYDATA *bk; + DB *dbp; + DBT orig, repl; + db_indx_t min, prefix, suffix; + u_int32_t len; + int ret; + u_int8_t *dp, *p, *t, type; + + dbp = dbc->dbp; + + /* + * Replace a single item onto a page. The logic figuring out where + * to insert and whether it fits is handled in the caller. All we do + * here is manage the page shuffling. + */ + bk = GET_BKEYDATA(dbp, h, indx); + len = bk->len; + dp = bk->data; + type = bk->type; + typeflag = B_DISSET(type); + + /* Log the change. */ + if (DBC_LOGGING(dbc)) { + /* + * We might as well check to see if the two data items share + * a common prefix and suffix -- it can save us a lot of log + * message if they're large. + */ + min = data->size < len ? data->size : len; + for (prefix = 0, + p = dp, t = data->data; + prefix < min && *p == *t; ++prefix, ++p, ++t) + ; + + min -= prefix; + for (suffix = 0, + p = (u_int8_t *)dp + len - 1, + t = (u_int8_t *)data->data + data->size - 1; + suffix < min && *p == *t; ++suffix, --p, --t) + ; + + /* We only log the parts of the keys that have changed. */ + orig.data = (u_int8_t *)dp + prefix; + orig.size = len - (prefix + suffix); + repl.data = (u_int8_t *)data->data + prefix; + repl.size = data->size - (prefix + suffix); + if ((ret = __bam_repl_log(dbp, dbc->txn, &LSN(h), 0, PGNO(h), + &LSN(h), (u_int32_t)indx, typeflag, + &orig, &repl, (u_int32_t)prefix, (u_int32_t)suffix)) != 0) + return (ret); + } else + LSN_NOT_LOGGED(LSN(h)); + + return (__bam_ritem_nolog(dbc, h, indx, NULL, data, type)); +} + +/* + * __bam_ritem_nolog -- + * Replace an item on a page. + * + * PUBLIC: int __bam_ritem_nolog __P((DBC *, + * PUBLIC: PAGE *, u_int32_t, DBT *, DBT *, u_int32_t)); + */ +int +__bam_ritem_nolog(dbc, h, indx, hdr, data, type) + DBC *dbc; + PAGE *h; + u_int32_t indx; + DBT *hdr, *data; + u_int32_t type; +{ + BKEYDATA *bk; + BINTERNAL *bi; + DB *dbp; + db_indx_t cnt, off, lo, ln; + db_indx_t *inp; + int32_t nbytes; + u_int8_t *p, *t; + + dbp = dbc->dbp; + /* + * Set references to the first in-use byte on the page and the + * first byte of the item being replaced. + */ + inp = P_INP(dbp, h); + p = (u_int8_t *)h + HOFFSET(h); + if (TYPE(h) == P_IBTREE) { + bi = GET_BINTERNAL(dbp, h, indx); + t = (u_int8_t *)bi; + lo = (db_indx_t)BINTERNAL_SIZE(bi->len); + if (data == NULL) { + DB_ASSERT(dbp->env, hdr != NULL); + bi = (BINTERNAL*)hdr->data; + P_16_COPY(&bi->len, &cnt); + ln = (db_indx_t)BINTERNAL_SIZE(cnt); + } else + ln = (db_indx_t)BINTERNAL_SIZE(data->size); + } else { + bk = GET_BKEYDATA(dbp, h, indx); + t = (u_int8_t *)bk; + lo = (db_indx_t)BKEYDATA_SIZE(bk->len); + ln = (db_indx_t)BKEYDATA_SIZE(data->size); + } + + /* + * If the entry is growing in size, shift the beginning of the data + * part of the page down. If the entry is shrinking in size, shift + * the beginning of the data part of the page up. Use memmove(3), + * the regions overlap. + */ + if (lo != ln) { + nbytes = (int32_t)(lo - ln); /* Signed difference. */ + if (p == t) /* First index is fast. */ + inp[indx] += (u_int32_t)nbytes; + else { /* Else, shift the page. */ + memmove(p + nbytes, p, (size_t)(t - p)); + + /* Adjust the indices' offsets. */ + off = (u_int32_t)inp[indx]; + for (cnt = 0; cnt < NUM_ENT(h); ++cnt) + if (inp[cnt] <= off) + inp[cnt] += (u_int32_t)nbytes; + } + + /* Clean up the page and adjust the item's reference. */ + HOFFSET(h) += (u_int32_t)nbytes; + t += nbytes; + } + + /* Copy the new item onto the page. */ + if (TYPE(h) == P_IBTREE) { + DB_ASSERT(dbp->env, hdr != NULL); + memcpy(t, hdr->data, hdr->size); + bi = (BINTERNAL *)t; + if (data != NULL && data->size != 0) + memcpy(bi->data, data->data, data->size); + } else { + bk = (BKEYDATA *)t; + bk->len = data->size; + B_TSET(bk->type, type); + memcpy(bk->data, data->data, bk->len); + } + + return (0); +} + +/* + * __bam_irep -- + * Replace an item on an internal page. + * + * PUBLIC: int __bam_irep __P((DBC *, PAGE *, u_int32_t, DBT *, DBT *)); + */ +int +__bam_irep(dbc, h, indx, hdr, data) + DBC *dbc; + PAGE *h; + u_int32_t indx; + DBT *hdr; + DBT *data; +{ + BINTERNAL *bi, *bn; + DB *dbp; + DBT dbt; + int ret; + + dbp = dbc->dbp; + + bi = GET_BINTERNAL(dbp, h, indx); + bn = (BINTERNAL *) hdr->data; + + if (B_TYPE(bi->type) == B_OVERFLOW && + (ret = __db_doff(dbc, ((BOVERFLOW *)bi->data)->pgno)) != 0) + return (ret); + + if (DBC_LOGGING(dbc)) { + dbt.data = bi; + dbt.size = BINTERNAL_SIZE(bi->len); + if ((ret = __bam_irep_log(dbp, dbc->txn, &LSN(h), 0, PGNO(h), + &LSN(h), (u_int32_t)indx, TYPE(h), hdr, data, &dbt)) != 0) + return (ret); + } else + LSN_NOT_LOGGED(LSN(h)); + + return (__bam_ritem_nolog(dbc, h, indx, hdr, data, bn->type)); +} + +/* + * __bam_dup_check -- + * Check to see if the duplicate set at indx should have its own page. + */ +static int +__bam_dup_check(dbc, op, h, indx, sz, cntp) + DBC *dbc; + u_int32_t op; + PAGE *h; + u_int32_t indx, sz; + db_indx_t *cntp; +{ + BKEYDATA *bk; + DB *dbp; + db_indx_t cnt, first, *inp; + + dbp = dbc->dbp; + inp = P_INP(dbp, h); + + /* + * Count the duplicate records and calculate how much room they're + * using on the page. + */ + while (indx > 0 && inp[indx] == inp[indx - P_INDX]) + indx -= P_INDX; + + /* Count the key once. */ + bk = GET_BKEYDATA(dbp, h, indx); + sz += B_TYPE(bk->type) == B_KEYDATA ? + BKEYDATA_PSIZE(bk->len) : BOVERFLOW_PSIZE; + + /* + * Sum up all the data items. + * Account for the record being inserted. If we are replacing it, + * don't count it twice. + * + * We execute the loop with first == indx to get the size of the + * first record. + */ + cnt = op == DB_CURRENT ? 0 : 1; + for (first = indx; + indx < NUM_ENT(h) && inp[first] == inp[indx]; + ++cnt, indx += P_INDX) { + bk = GET_BKEYDATA(dbp, h, indx + O_INDX); + sz += B_TYPE(bk->type) == B_KEYDATA ? + BKEYDATA_PSIZE(bk->len) : BOVERFLOW_PSIZE; + } + + /* + * We have to do these checks when the user is replacing the cursor's + * data item -- if the application replaces a duplicate item with a + * larger data item, it can increase the amount of space used by the + * duplicates, requiring this check. But that means we may have done + * this check when it wasn't a duplicate item after all. + */ + if (cnt == 1) + return (0); + + /* + * If this set of duplicates is using more than 25% of the page, move + * them off. The choice of 25% is a WAG, but the value must be small + * enough that we can always split a page without putting duplicates + * on two different pages. + */ + if (sz < dbp->pgsize / 4) + return (0); + + *cntp = cnt; + return (1); +} + +/* + * __bam_dup_convert -- + * Move a set of duplicates off-page and into their own tree. + */ +static int +__bam_dup_convert(dbc, h, indx, cnt) + DBC *dbc; + PAGE *h; + u_int32_t indx, cnt; +{ + BKEYDATA *bk; + DB *dbp; + DBT hdr; + DB_LOCK lock; + DB_MPOOLFILE *mpf; + PAGE *dp; + db_indx_t cpindx, dindx, first, *inp; + int ret, t_ret; + + dbp = dbc->dbp; + mpf = dbp->mpf; + inp = P_INP(dbp, h); + + /* Move to the beginning of the dup set. */ + while (indx > 0 && inp[indx] == inp[indx - P_INDX]) + indx -= P_INDX; + + /* Get a new page. */ + if ((ret = __db_new(dbc, + dbp->dup_compare == NULL ? P_LRECNO : P_LDUP, &lock, &dp)) != 0) + return (ret); + P_INIT(dp, dbp->pgsize, dp->pgno, + PGNO_INVALID, PGNO_INVALID, LEAFLEVEL, TYPE(dp)); + + /* + * Move this set of duplicates off the page. First points to the first + * key of the first duplicate key/data pair, cnt is the number of pairs + * we're dealing with. + */ + memset(&hdr, 0, sizeof(hdr)); + first = indx; + dindx = indx; + cpindx = 0; + do { + /* Move cursors referencing the old entry to the new entry. */ + if ((ret = __bam_ca_dup(dbc, first, + PGNO(h), indx, PGNO(dp), cpindx)) != 0) + goto err; + + /* + * Copy the entry to the new page. If the off-duplicate page + * If the off-duplicate page is a Btree page (i.e. dup_compare + * will be non-NULL, we use Btree pages for sorted dups, + * and Recno pages for unsorted dups), move all entries + * normally, even deleted ones. If it's a Recno page, + * deleted entries are discarded (if the deleted entry is + * overflow, then free up those pages). + */ + bk = GET_BKEYDATA(dbp, h, dindx + 1); + hdr.data = bk; + hdr.size = B_TYPE(bk->type) == B_KEYDATA ? + BKEYDATA_SIZE(bk->len) : BOVERFLOW_SIZE; + if (dbp->dup_compare == NULL && B_DISSET(bk->type)) { + /* + * Unsorted dups, i.e. recno page, and we have + * a deleted entry, don't move it, but if it was + * an overflow entry, we need to free those pages. + */ + if (B_TYPE(bk->type) == B_OVERFLOW && + (ret = __db_doff(dbc, + (GET_BOVERFLOW(dbp, h, dindx + 1))->pgno)) != 0) + goto err; + } else { + if ((ret = __db_pitem( + dbc, dp, cpindx, hdr.size, &hdr, NULL)) != 0) + goto err; + ++cpindx; + } + /* Delete all but the last reference to the key. */ + if (cnt != 1) { + if ((ret = __bam_adjindx(dbc, + h, dindx, first + 1, 0)) != 0) + goto err; + } else + dindx++; + + /* Delete the data item. */ + if ((ret = __db_ditem(dbc, h, dindx, hdr.size)) != 0) + goto err; + indx += P_INDX; + } while (--cnt); + + /* Put in a new data item that points to the duplicates page. */ + if ((ret = __bam_ovput(dbc, + B_DUPLICATE, dp->pgno, h, first + 1, NULL)) != 0) + goto err; + + /* Adjust cursors for all the above movements. */ + ret = __bam_ca_di(dbc, + PGNO(h), first + P_INDX, (int)(first + P_INDX - indx)); + +err: if ((t_ret = __memp_fput(mpf, + dbc->thread_info, dp, dbc->priority)) != 0 && ret == 0) + ret = t_ret; + + (void)__TLPUT(dbc, lock); + return (ret); +} + +/* + * __bam_ovput -- + * Build an item for an off-page duplicates page or overflow page and + * insert it on the page. + */ +static int +__bam_ovput(dbc, type, pgno, h, indx, item) + DBC *dbc; + u_int32_t type, indx; + db_pgno_t pgno; + PAGE *h; + DBT *item; +{ + BOVERFLOW bo; + DBT hdr; + int ret; + + UMRW_SET(bo.unused1); + B_TSET(bo.type, type); + UMRW_SET(bo.unused2); + + /* + * If we're creating an overflow item, do so and acquire the page + * number for it. If we're creating an off-page duplicates tree, + * we are giving the page number as an argument. + */ + if (type == B_OVERFLOW) { + if ((ret = __db_poff(dbc, item, &bo.pgno)) != 0) + return (ret); + bo.tlen = item->size; + } else { + bo.pgno = pgno; + bo.tlen = 0; + } + + /* Store the new record on the page. */ + memset(&hdr, 0, sizeof(hdr)); + hdr.data = &bo; + hdr.size = BOVERFLOW_SIZE; + return (__db_pitem(dbc, h, indx, BOVERFLOW_SIZE, &hdr, NULL)); +} diff -r 000000000000 -r a1985f14b030 src/btree/bt_reclaim.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/btree/bt_reclaim.c Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,120 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 1998, 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + * $Id$ + */ + +#include "db_config.h" + +#include "db_int.h" +#include "dbinc/db_page.h" +#include "dbinc/btree.h" +#include "dbinc/lock.h" + +/* + * __bam_reclaim -- + * Free a database. + * + * PUBLIC: int __bam_reclaim __P((DB *, DB_THREAD_INFO *, DB_TXN *, u_int32_t)); + */ +int +__bam_reclaim(dbp, ip, txn, flags) + DB *dbp; + DB_THREAD_INFO *ip; + DB_TXN *txn; + u_int32_t flags; +{ + DBC *dbc; + DB_LOCK meta_lock; + int ret, t_ret; + + /* Acquire a cursor. */ + if ((ret = __db_cursor(dbp, ip, txn, &dbc, 0)) != 0) + return (ret); + + /* Write lock the metapage for deallocations. */ + if ((ret = __db_lget(dbc, + 0, PGNO_BASE_MD, DB_LOCK_WRITE, 0, &meta_lock)) != 0) + goto err; + + /* Avoid locking every page, we have the handle locked exclusive. */ + F_SET(dbc, DBC_DONTLOCK); + + /* Walk the tree, freeing pages. */ + ret = __bam_traverse(dbc, DB_LOCK_WRITE, + PGNO_INVALID, __db_reclaim_callback, &flags); + + if ((t_ret = __TLPUT(dbc, meta_lock)) != 0 && ret == 0) + ret = t_ret; + + /* Discard the cursor. */ +err: if ((t_ret = __dbc_close(dbc)) != 0 && ret == 0) + ret = t_ret; + + return (ret); +} + +/* + * __bam_truncate -- + * Truncate a database. + * + * PUBLIC: int __bam_truncate __P((DBC *, u_int32_t *)); + */ +int +__bam_truncate(dbc, countp) + DBC *dbc; + u_int32_t *countp; +{ + u_int32_t count; + int ret; + +#ifdef HAVE_COMPRESSION + u_int32_t comp_count; + + comp_count = 0; + if (DB_IS_COMPRESSED(dbc->dbp) && + (ret = __bam_compress_count(dbc, NULL, &comp_count)) != 0) + return (ret); +#endif + + count = 0; + + /* Walk the tree, freeing pages. */ + ret = __bam_traverse(dbc, + DB_LOCK_WRITE, PGNO_INVALID, __db_truncate_callback, &count); + +#ifdef HAVE_COMPRESSION + if (DB_IS_COMPRESSED(dbc->dbp)) { + if (countp != NULL) + *countp = comp_count; + } else +#endif + if (countp != NULL) + *countp = count; + + return (ret); +} diff -r 000000000000 -r a1985f14b030 src/btree/bt_recno.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/btree/bt_recno.c Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,1449 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 1997, 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + * $Id$ + */ + +#include "db_config.h" + +#include "db_int.h" +#include "dbinc/db_page.h" +#include "dbinc/btree.h" +#include "dbinc/lock.h" +#include "dbinc/mp.h" + +static int __ram_add __P((DBC *, db_recno_t *, DBT *, u_int32_t, u_int32_t)); +static int __ram_source __P((DB *)); +static int __ram_sread __P((DBC *, db_recno_t)); +static int __ram_update __P((DBC *, db_recno_t, int)); +static int __ram_ca_getorder + __P((DBC *, DBC *, u_int32_t *, db_pgno_t, u_int32_t, void *)); +static int __ram_ca_setorder + __P((DBC *, DBC *, u_int32_t *, db_pgno_t, u_int32_t, void *)); +/* + * In recno, there are two meanings to the on-page "deleted" flag. If we're + * re-numbering records, it means the record was implicitly created. We skip + * over implicitly created records if doing a cursor "next" or "prev", and + * return DB_KEYEMPTY if they're explicitly requested.. If not re-numbering + * records, it means that the record was implicitly created, or was deleted. + * We skip over implicitly created or deleted records if doing a cursor "next" + * or "prev", and return DB_KEYEMPTY if they're explicitly requested. + * + * If we're re-numbering records, then we have to detect in the cursor that + * a record was deleted, and adjust the cursor as necessary on the next get. + * If we're not re-numbering records, then we can detect that a record has + * been deleted by looking at the actual on-page record, so we completely + * ignore the cursor's delete flag. This is different from the B+tree code. + * It also maintains whether the cursor references a deleted record in the + * cursor, and it doesn't always check the on-page value. + */ +#define CD_SET(cp) { \ + if (F_ISSET(cp, C_RENUMBER)) \ + F_SET(cp, C_DELETED); \ +} +#define CD_CLR(cp) { \ + if (F_ISSET(cp, C_RENUMBER)) { \ + F_CLR(cp, C_DELETED); \ + cp->order = INVALID_ORDER; \ + } \ +} +#define CD_ISSET(cp) \ + (F_ISSET(cp, C_RENUMBER) && F_ISSET(cp, C_DELETED) ? 1 : 0) + +/* + * Macros for comparing the ordering of two cursors. + * cp1 comes before cp2 iff one of the following holds: + * cp1's recno is less than cp2's recno + * recnos are equal, both deleted, and cp1's order is less than cp2's + * recnos are equal, cp1 deleted, and cp2 not deleted + */ +#define C_LESSTHAN(cp1, cp2) \ + (((cp1)->recno < (cp2)->recno) || \ + (((cp1)->recno == (cp2)->recno) && \ + ((CD_ISSET((cp1)) && CD_ISSET((cp2)) && (cp1)->order < (cp2)->order) || \ + (CD_ISSET((cp1)) && !CD_ISSET((cp2)))))) + +/* + * cp1 is equal to cp2 iff their recnos and delete flags are identical, + * and if the delete flag is set their orders are also identical. + */ +#define C_EQUAL(cp1, cp2) \ + ((cp1)->recno == (cp2)->recno && CD_ISSET((cp1)) == CD_ISSET((cp2)) && \ + (!CD_ISSET((cp1)) || (cp1)->order == (cp2)->order)) + +/* + * Do we need to log the current cursor adjustment? + */ +#define CURADJ_LOG(dbc) \ + (DBC_LOGGING((dbc)) && (dbc)->txn != NULL && (dbc)->txn->parent != NULL) + +/* + * After a search, copy the found page into the cursor, discarding any + * currently held lock. + */ +#define STACK_TO_CURSOR(cp, ret) { \ + int __t_ret; \ + (cp)->page = (cp)->csp->page; \ + (cp)->pgno = (cp)->csp->page->pgno; \ + (cp)->indx = (cp)->csp->indx; \ + if ((__t_ret = __TLPUT(dbc, (cp)->lock)) != 0 && (ret) == 0) \ + ret = __t_ret; \ + (cp)->lock = (cp)->csp->lock; \ + (cp)->lock_mode = (cp)->csp->lock_mode; \ +} + +/* + * __ram_open -- + * Recno open function. + * + * PUBLIC: int __ram_open __P((DB *, DB_THREAD_INFO *, + * PUBLIC: DB_TXN *, const char *, db_pgno_t, u_int32_t)); + */ +int +__ram_open(dbp, ip, txn, name, base_pgno, flags) + DB *dbp; + DB_THREAD_INFO *ip; + DB_TXN *txn; + const char *name; + db_pgno_t base_pgno; + u_int32_t flags; +{ + BTREE *t; + DBC *dbc; + int ret, t_ret; + + COMPQUIET(name, NULL); + t = dbp->bt_internal; + + /* Start up the tree. */ + if ((ret = __bam_read_root(dbp, ip, txn, base_pgno, flags)) != 0) + return (ret); + + /* + * If the user specified a source tree, open it and map it in. + * + * !!! + * We don't complain if the user specified transactions or threads. + * It's possible to make it work, but you'd better know what you're + * doing! + */ + if (t->re_source != NULL && (ret = __ram_source(dbp)) != 0) + return (ret); + + /* If we're snapshotting an underlying source file, do it now. */ + if (F_ISSET(dbp, DB_AM_SNAPSHOT)) { + /* Allocate a cursor. */ + if ((ret = __db_cursor(dbp, ip, NULL, &dbc, 0)) != 0) + return (ret); + + /* Do the snapshot. */ + if ((ret = __ram_update(dbc, + DB_MAX_RECORDS, 0)) != 0 && ret == DB_NOTFOUND) + ret = 0; + + /* Discard the cursor. */ + if ((t_ret = __dbc_close(dbc)) != 0 && ret == 0) + ret = t_ret; + } + + return (ret); +} + +/* + * __ram_append -- + * Recno append function. + * + * PUBLIC: int __ram_append __P((DBC *, DBT *, DBT *)); + */ +int +__ram_append(dbc, key, data) + DBC *dbc; + DBT *key, *data; +{ + BTREE_CURSOR *cp; + int ret; + + cp = (BTREE_CURSOR *)dbc->internal; + + /* + * Make sure we've read in all of the backing source file. If + * we found the record or it simply didn't exist, add the + * user's record. + */ + ret = __ram_update(dbc, DB_MAX_RECORDS, 0); + if (ret == 0 || ret == DB_NOTFOUND) + ret = __ram_add(dbc, &cp->recno, data, DB_APPEND, 0); + + /* Return the record number. */ + if (ret == 0 && key != NULL) + ret = __db_retcopy(dbc->env, key, &cp->recno, + sizeof(cp->recno), &dbc->rkey->data, &dbc->rkey->ulen); + + if (!DB_RETOK_DBCPUT(ret)) + F_SET(dbc, DBC_ERROR); + return (ret); +} + +/* + * __ramc_del -- + * Recno DBC->del function. + * + * PUBLIC: int __ramc_del __P((DBC *, u_int32_t)); + */ +int +__ramc_del(dbc, flags) + DBC *dbc; + u_int32_t flags; +{ + BKEYDATA bk; + BTREE *t; + BTREE_CURSOR *cp; + DB *dbp; + DBT hdr, data; + DB_LOCK next_lock, prev_lock; + DB_LSN lsn; + db_pgno_t npgno, ppgno, save_npgno, save_ppgno; + int exact, nc, ret, stack, t_ret; + + dbp = dbc->dbp; + cp = (BTREE_CURSOR *)dbc->internal; + t = dbp->bt_internal; + stack = 0; + save_npgno = save_ppgno = PGNO_INVALID; + LOCK_INIT(next_lock); + LOCK_INIT(prev_lock); + COMPQUIET(flags, 0); + + /* + * The semantics of cursors during delete are as follows: in + * non-renumbering recnos, records are replaced with a marker + * containing a delete flag. If the record referenced by this cursor + * has already been deleted, we will detect that as part of the delete + * operation, and fail. + * + * In renumbering recnos, cursors which represent deleted items + * are flagged with the C_DELETED flag, and it is an error to + * call c_del a second time without an intervening cursor motion. + */ + if (CD_ISSET(cp)) + return (DB_KEYEMPTY); + + /* Search the tree for the key; delete only deletes exact matches. */ +retry: if ((ret = __bam_rsearch(dbc, &cp->recno, SR_DELETE, 1, &exact)) != 0) + goto err; + if (!exact) { + ret = DB_NOTFOUND; + goto err; + } + stack = 1; + + /* Copy the page into the cursor. */ + STACK_TO_CURSOR(cp, ret); + if (ret != 0) + goto err; + + /* + * If re-numbering records, the on-page deleted flag can only mean + * that this record was implicitly created. Applications aren't + * permitted to delete records they never created, return an error. + * + * If not re-numbering records, the on-page deleted flag means that + * this record was implicitly created, or, was deleted at some time. + * The former is an error because applications aren't permitted to + * delete records they never created, the latter is an error because + * if the record was "deleted", we could never have found it. + */ + if (B_DISSET(GET_BKEYDATA(dbp, cp->page, cp->indx)->type)) { + ret = DB_KEYEMPTY; + goto err; + } + + if (F_ISSET(cp, C_RENUMBER)) { + /* If we are going to drop the page, lock its neighbors. */ + if (STD_LOCKING(dbc) && NUM_ENT(cp->page) == 1 && + PGNO(cp->page) != BAM_ROOT_PGNO(dbc)) { + if ((npgno = NEXT_PGNO(cp->page)) != PGNO_INVALID) + TRY_LOCK(dbc, npgno, save_npgno, + next_lock, DB_LOCK_WRITE, retry); + if (ret != 0) + goto err; + if ((ppgno = PREV_PGNO(cp->page)) != PGNO_INVALID) + TRY_LOCK(dbc, ppgno, save_ppgno, + prev_lock, DB_LOCK_WRITE, retry); + if (ret != 0) + goto err; + } + /* Delete the item, adjust the counts, adjust the cursors. */ + if ((ret = __bam_ditem(dbc, cp->page, cp->indx)) != 0) + goto err; + if ((ret = __bam_adjust(dbc, -1)) != 0) + goto err; + if ((ret = __ram_ca(dbc, CA_DELETE, &nc)) != 0) + goto err; + if (nc > 0 && CURADJ_LOG(dbc) && + (ret = __bam_rcuradj_log(dbp, dbc->txn, &lsn, 0, + CA_DELETE, BAM_ROOT_PGNO(dbc), cp->recno, cp->order)) != 0) + goto err; + + /* + * If the page is empty, delete it. + * + * We never delete a root page. First, root pages of primary + * databases never go away, recno or otherwise. However, if + * it's the root page of an off-page duplicates database, then + * it can be deleted. We don't delete it here because we have + * no way of telling the primary database page holder (e.g., + * the hash access method) that its page element should cleaned + * up because the underlying tree is gone. So, we keep the page + * around until the last cursor referencing the empty tree is + * are closed, and then clean it up. + */ + if (NUM_ENT(cp->page) == 0 && + PGNO(cp->page) != BAM_ROOT_PGNO(dbc)) { + /* + * We want to delete a single item out of the last page + * that we're not deleting. + */ + if (F_ISSET(dbc, DBC_OPD)) + LOCK_CHECK_OFF(dbc->thread_info); + ret = __bam_dpages(dbc, 0, BTD_RELINK); + if (F_ISSET(dbc, DBC_OPD)) + LOCK_CHECK_ON(dbc->thread_info); + + /* + * Regardless of the return from __bam_dpages, it will + * discard our stack and pinned page. + */ + stack = 0; + cp->page = NULL; + LOCK_INIT(cp->lock); + cp->lock_mode = DB_LOCK_NG; + } + } else { + /* Use a delete/put pair to replace the record with a marker. */ + if ((ret = __bam_ditem(dbc, cp->page, cp->indx)) != 0) + goto err; + + B_TSET_DELETED(bk.type, B_KEYDATA); + bk.len = 0; + DB_INIT_DBT(hdr, &bk, SSZA(BKEYDATA, data)); + DB_INIT_DBT(data, "", 0); + if ((ret = __db_pitem(dbc, + cp->page, cp->indx, BKEYDATA_SIZE(0), &hdr, &data)) != 0) + goto err; + } + + t->re_modified = 1; + +err: if (!DB_RETOK_DBCDEL(ret)) + F_SET(dbc, DBC_ERROR); + if (stack && (t_ret = __bam_stkrel(dbc, STK_CLRDBC)) != 0 && ret == 0) + ret = t_ret; + if ((t_ret = __TLPUT(dbc, next_lock)) != 0 && ret == 0) + ret = t_ret; + if ((t_ret = __TLPUT(dbc, prev_lock)) != 0 && ret == 0) + ret = t_ret; + + return (ret); +} + +/* + * __ramc_get -- + * Recno DBC->get function. + * + * PUBLIC: int __ramc_get + * PUBLIC: __P((DBC *, DBT *, DBT *, u_int32_t, db_pgno_t *)); + */ +int +__ramc_get(dbc, key, data, flags, pgnop) + DBC *dbc; + DBT *key, *data; + u_int32_t flags; + db_pgno_t *pgnop; +{ + BTREE_CURSOR *cp; + DB *dbp; + int cmp, exact, ret; + + COMPQUIET(pgnop, NULL); + + dbp = dbc->dbp; + cp = (BTREE_CURSOR *)dbc->internal; + + LF_CLR(DB_MULTIPLE|DB_MULTIPLE_KEY); +retry: switch (flags) { + case DB_CURRENT: + /* + * If we're using mutable records and the deleted flag is + * set, the cursor is pointing at a nonexistent record; + * return an error. + */ + if (CD_ISSET(cp)) + return (DB_KEYEMPTY); + break; + case DB_NEXT_DUP: + /* + * If we're not in an off-page dup set, we know there's no + * next duplicate since recnos don't have them. If we + * are in an off-page dup set, the next item assuredly is + * a dup, so we set flags to DB_NEXT and keep going. + */ + if (!F_ISSET(dbc, DBC_OPD)) + return (DB_NOTFOUND); + /* FALLTHROUGH */ + case DB_NEXT_NODUP: + /* + * Recno databases don't have duplicates, set flags to DB_NEXT + * and keep going. + */ + /* FALLTHROUGH */ + case DB_NEXT: + flags = DB_NEXT; + /* + * If record numbers are mutable: if we just deleted a record, + * we have to avoid incrementing the record number so that we + * return the right record by virtue of renumbering the tree. + */ + if (CD_ISSET(cp)) { + /* + * Clear the flag, we've moved off the deleted record. + */ + CD_CLR(cp); + break; + } + + if (cp->recno != RECNO_OOB) { + ++cp->recno; + break; + } + /* FALLTHROUGH */ + case DB_FIRST: + flags = DB_NEXT; + cp->recno = 1; + break; + case DB_PREV_DUP: + /* + * If we're not in an off-page dup set, we know there's no + * previous duplicate since recnos don't have them. If we + * are in an off-page dup set, the previous item assuredly + * is a dup, so we set flags to DB_PREV and keep going. + */ + if (!F_ISSET(dbc, DBC_OPD)) + return (DB_NOTFOUND); + /* FALLTHROUGH */ + case DB_PREV_NODUP: + /* + * Recno databases don't have duplicates, set flags to DB_PREV + * and keep going. + */ + /* FALLTHROUGH */ + case DB_PREV: + flags = DB_PREV; + if (cp->recno != RECNO_OOB) { + if (cp->recno == 1) { + ret = DB_NOTFOUND; + goto err; + } + --cp->recno; + break; + } + /* FALLTHROUGH */ + case DB_LAST: + flags = DB_PREV; + if (((ret = __ram_update(dbc, + DB_MAX_RECORDS, 0)) != 0) && ret != DB_NOTFOUND) + goto err; + if ((ret = __bam_nrecs(dbc, &cp->recno)) != 0) + goto err; + if (cp->recno == 0) { + ret = DB_NOTFOUND; + goto err; + } + break; + case DB_GET_BOTHC: + /* + * If we're doing a join and these are offpage dups, + * we want to keep searching forward from after the + * current cursor position. Increment the recno by 1, + * then proceed as for a DB_SET. + * + * Otherwise, we know there are no additional matching + * data, as recnos don't have dups. return DB_NOTFOUND. + */ + if (F_ISSET(dbc, DBC_OPD)) { + cp->recno++; + break; + } + ret = DB_NOTFOUND; + goto err; + /* NOTREACHED */ + case DB_GET_BOTH: + case DB_GET_BOTH_RANGE: + /* + * If we're searching a set of off-page dups, we start + * a new linear search from the first record. Otherwise, + * we compare the single data item associated with the + * requested record for a match. + */ + if (F_ISSET(dbc, DBC_OPD)) { + cp->recno = 1; + break; + } + /* FALLTHROUGH */ + case DB_SET: + case DB_SET_RANGE: + if ((ret = __ram_getno(dbc, key, &cp->recno, 0)) != 0) + goto err; + break; + default: + ret = __db_unknown_flag(dbp->env, "__ramc_get", flags); + goto err; + } + + /* + * For DB_PREV, DB_LAST, DB_SET and DB_SET_RANGE, we have already + * called __ram_update() to make sure sufficient records have been + * read from the backing source file. Do it now for DB_CURRENT (if + * the current record was deleted we may need more records from the + * backing file for a DB_CURRENT operation), DB_FIRST and DB_NEXT. + * (We don't have to test for flags == DB_FIRST, because the switch + * statement above re-set flags to DB_NEXT in that case.) + */ + if ((flags == DB_NEXT || flags == DB_CURRENT) && ((ret = + __ram_update(dbc, cp->recno, 0)) != 0) && ret != DB_NOTFOUND) + goto err; + + for (;; ++cp->recno) { + /* Search the tree for the record. */ + if ((ret = __bam_rsearch(dbc, &cp->recno, + F_ISSET(dbc, DBC_RMW) ? SR_FIND_WR : SR_FIND, + 1, &exact)) != 0) + goto err; + if (!exact) { + ret = DB_NOTFOUND; + goto err; + } + + /* Copy the page into the cursor. */ + STACK_TO_CURSOR(cp, ret); + if (ret != 0) + goto err; + + /* + * If re-numbering records, the on-page deleted flag means this + * record was implicitly created. If not re-numbering records, + * the on-page deleted flag means this record was implicitly + * created, or, it was deleted at some time. Regardless, we + * skip such records if doing cursor next/prev operations or + * walking through off-page duplicates, and fail if they were + * requested explicitly by the application. + */ + if (B_DISSET(GET_BKEYDATA(dbp, cp->page, cp->indx)->type)) + switch (flags) { + case DB_NEXT: + case DB_PREV: + (void)__bam_stkrel(dbc, STK_CLRDBC); + PERFMON4(env, race, ramc_get, + dbp->fname, dbp->dname, cp->page, flags); + goto retry; + case DB_GET_BOTH: + case DB_GET_BOTH_RANGE: + /* + * If we're an OPD tree, we don't care about + * matching a record number on a DB_GET_BOTH + * -- everything belongs to the same tree. A + * normal recno should give up and return + * DB_NOTFOUND if the matching recno is deleted. + */ + if (F_ISSET(dbc, DBC_OPD)) { + (void)__bam_stkrel(dbc, STK_CLRDBC); + continue; + } + ret = DB_NOTFOUND; + goto err; + default: + ret = DB_KEYEMPTY; + goto err; + } + + if (flags == DB_GET_BOTH || + flags == DB_GET_BOTHC || flags == DB_GET_BOTH_RANGE) { + if ((ret = __bam_cmp(dbc, data, cp->page, cp->indx, + __bam_defcmp, &cmp)) != 0) + return (ret); + if (cmp == 0) + break; + if (!F_ISSET(dbc, DBC_OPD)) { + ret = DB_NOTFOUND; + goto err; + } + (void)__bam_stkrel(dbc, STK_CLRDBC); + } else + break; + } + + /* Return the key if the user didn't give us one. */ + if (!F_ISSET(dbc, DBC_OPD) && !F_ISSET(key, DB_DBT_ISSET)) { + ret = __db_retcopy(dbp->env, + key, &cp->recno, sizeof(cp->recno), + &dbc->rkey->data, &dbc->rkey->ulen); + F_SET(key, DB_DBT_ISSET); + } + + /* The cursor was reset, no further delete adjustment is necessary. */ +err: CD_CLR(cp); + + return (ret); +} + +/* + * __ramc_put -- + * Recno DBC->put function. + * + * PUBLIC: int __ramc_put __P((DBC *, DBT *, DBT *, u_int32_t, db_pgno_t *)); + */ +int +__ramc_put(dbc, key, data, flags, pgnop) + DBC *dbc; + DBT *key, *data; + u_int32_t flags; + db_pgno_t *pgnop; +{ + BTREE_CURSOR *cp; + DB *dbp; + DB_LSN lsn; + ENV *env; + u_int32_t iiflags; + int exact, nc, ret, t_ret; + void *arg; + + COMPQUIET(pgnop, NULL); + + dbp = dbc->dbp; + env = dbp->env; + cp = (BTREE_CURSOR *)dbc->internal; + + /* + * DB_KEYFIRST and DB_KEYLAST mean different things if they're + * used in an off-page duplicate tree. If we're an off-page + * duplicate tree, they really mean "put at the beginning of the + * tree" and "put at the end of the tree" respectively, so translate + * them to something else. + */ + if (F_ISSET(dbc, DBC_OPD)) + switch (flags) { + case DB_KEYFIRST: + cp->recno = 1; + flags = DB_BEFORE; + break; + case DB_KEYLAST: + if ((ret = __ram_add(dbc, + &cp->recno, data, DB_APPEND, 0)) != 0) + return (ret); + if (CURADJ_LOG(dbc) && + (ret = __bam_rcuradj_log(dbp, dbc->txn, + &lsn, 0, CA_ICURRENT, + BAM_ROOT_PGNO(dbc), cp->recno, cp->order)) != 0) + return (ret); + return (0); + default: + break; + } + + /* + * Handle normal DB_KEYFIRST/DB_KEYLAST; for a recno, which has + * no duplicates, these are identical and mean "put the given + * datum at the given recno". + */ + if (flags == DB_KEYFIRST || flags == DB_KEYLAST || + flags == DB_NOOVERWRITE || flags == DB_OVERWRITE_DUP) { + ret = __ram_getno(dbc, key, &cp->recno, 1); + if (ret == 0 || ret == DB_NOTFOUND) + ret = __ram_add(dbc, &cp->recno, data, flags, 0); + return (ret); + } + + /* + * If we're putting with a cursor that's marked C_DELETED, we need to + * take special care; the cursor doesn't "really" reference the item + * corresponding to its current recno, but instead is "between" that + * record and the current one. Translate the actual insert into + * DB_BEFORE, and let the __ram_ca work out the gory details of what + * should wind up pointing where. + */ + if (CD_ISSET(cp)) + iiflags = DB_BEFORE; + else + iiflags = flags; + +split: if ((ret = __bam_rsearch(dbc, &cp->recno, SR_INSERT, 1, &exact)) != 0) + goto err; + /* + * An inexact match is okay; it just means we're one record past the + * end, which is reasonable if we're marked deleted. + */ + DB_ASSERT(env, exact || CD_ISSET(cp)); + + /* Copy the page into the cursor. */ + STACK_TO_CURSOR(cp, ret); + if (ret != 0) + goto err; + + ret = __bam_iitem(dbc, key, data, iiflags, 0); + t_ret = __bam_stkrel(dbc, STK_CLRDBC); + + if (t_ret != 0 && (ret == 0 || ret == DB_NEEDSPLIT)) + ret = t_ret; + else if (ret == DB_NEEDSPLIT) { + arg = &cp->recno; + if ((ret = __bam_split(dbc, arg, NULL)) != 0) + goto err; + goto split; + } + if (ret != 0) + goto err; + + switch (flags) { /* Adjust the cursors. */ + case DB_AFTER: + if ((ret = __ram_ca(dbc, CA_IAFTER, &nc)) != 0) + goto err; + + /* + * We only need to adjust this cursor forward if we truly added + * the item after the current recno, rather than remapping it + * to DB_BEFORE. + */ + if (iiflags == DB_AFTER) + ++cp->recno; + + /* Only log if __ram_ca found any relevant cursors. */ + if (nc > 0 && CURADJ_LOG(dbc) && + (ret = __bam_rcuradj_log(dbp, dbc->txn, &lsn, 0, CA_IAFTER, + BAM_ROOT_PGNO(dbc), cp->recno, cp->order)) != 0) + goto err; + break; + case DB_BEFORE: + if ((ret = __ram_ca(dbc, CA_IBEFORE, &nc)) != 0) + goto err; + --cp->recno; + + /* Only log if __ram_ca found any relevant cursors. */ + if (nc > 0 && CURADJ_LOG(dbc) && + (ret = __bam_rcuradj_log(dbp, dbc->txn, &lsn, 0, CA_IBEFORE, + BAM_ROOT_PGNO(dbc), cp->recno, cp->order)) != 0) + goto err; + break; + case DB_CURRENT: + /* + * We only need to do an adjustment if we actually + * added an item, which we only would have done if the + * cursor was marked deleted. + */ + if (!CD_ISSET(cp)) + break; + + /* Only log if __ram_ca found any relevant cursors. */ + if ((ret = __ram_ca(dbc, CA_ICURRENT, &nc)) != 0) + goto err; + if (nc > 0 && CURADJ_LOG(dbc) && (ret = __bam_rcuradj_log(dbp, + dbc->txn, &lsn, 0, CA_ICURRENT, + BAM_ROOT_PGNO(dbc), cp->recno, cp->order)) != 0) + goto err; + break; + default: + break; + } + + /* Return the key if we've created a new record. */ + if (!F_ISSET(dbc, DBC_OPD) && + (flags == DB_AFTER || flags == DB_BEFORE) && key != NULL) + ret = __db_retcopy(env, key, &cp->recno, + sizeof(cp->recno), &dbc->rkey->data, &dbc->rkey->ulen); + + /* The cursor was reset, no further delete adjustment is necessary. */ +err: CD_CLR(cp); + + if (!DB_RETOK_DBCDEL(ret)) + F_SET(dbc, DBC_ERROR); + return (ret); +} + +static int +__ram_ca_getorder(dbc, my_dbc, orderp, root_pgno, recno, args) + DBC *dbc, *my_dbc; + u_int32_t *orderp; + db_pgno_t root_pgno; + u_int32_t recno; + void *args; +{ + BTREE_CURSOR *cp; + + COMPQUIET(my_dbc, NULL); + COMPQUIET(args, NULL); + + cp = (BTREE_CURSOR *)dbc->internal; + if (root_pgno == BAM_ROOT_PGNO(dbc) && + recno == cp->recno && CD_ISSET(cp) && + *orderp <= cp->order && + !MVCC_SKIP_CURADJ(dbc, BAM_ROOT_PGNO(dbc))) + *orderp = cp->order; + return (0); +} + +static int +__ram_ca_setorder(dbc, my_dbc, foundp, pgno, order, args) + DBC *dbc, *my_dbc; + u_int32_t *foundp; + db_pgno_t pgno; + u_int32_t order; + void *args; +{ + BTREE_CURSOR *cp, *cp_arg; + int adjusted; + ca_recno_arg op; + db_recno_t recno; + + COMPQUIET(pgno, 0); + + cp = (BTREE_CURSOR *)dbc->internal; + cp_arg = (BTREE_CURSOR *)my_dbc->internal; + op = *(ca_recno_arg *)args; + + if (cp_arg->root != cp->root || + MVCC_SKIP_CURADJ(dbc, BAM_ROOT_PGNO(dbc))) + return (0); + ++(*foundp); + adjusted = 0; + recno = cp_arg->recno; + switch (op) { + case CA_DELETE: + if (recno < cp->recno) { + --cp->recno; + /* + * If the adjustment made them equal, + * we have to merge the orders. + */ + if (recno == cp->recno && CD_ISSET(cp)) + cp->order += order; + } else if (recno == cp->recno && + !CD_ISSET(cp)) { + CD_SET(cp); + cp->order = order; + /* + * If we're deleting the item, we can't + * keep a streaming offset cached. + */ + cp->stream_start_pgno = PGNO_INVALID; + } + break; + case CA_IBEFORE: + /* + * IBEFORE is just like IAFTER, except that we + * adjust cursors on the current record too. + */ + if (C_EQUAL(cp_arg, cp)) { + ++cp->recno; + adjusted = 1; + } + goto iafter; + case CA_ICURRENT: + + /* + * If the original cursor wasn't deleted, we + * just did a replacement and so there's no + * need to adjust anything--we shouldn't have + * gotten this far. Otherwise, we behave + * much like an IAFTER, except that all + * cursors pointing to the current item get + * marked undeleted and point to the new + * item. + */ + DB_ASSERT(dbc->dbp->env, CD_ISSET(cp_arg)); + if (C_EQUAL(cp_arg, cp)) { + CD_CLR(cp); + break; + } + /* FALLTHROUGH */ + case CA_IAFTER: +iafter: if (!adjusted && C_LESSTHAN(cp_arg, cp)) { + ++cp->recno; + adjusted = 1; + } + if (recno == cp->recno && adjusted) + /* + * If we've moved this cursor's recno, + * split its order number--i.e., + * decrement it by enough so that + * the lowest cursor moved has order 1. + * cp_arg->order is the split point, + * so decrement by one less than that. + */ + cp->order -= (cp_arg->order - 1); + break; + } + return (0); +} + +/* + * __ram_ca -- + * Adjust cursors. Returns the number of relevant cursors. + * + * PUBLIC: int __ram_ca __P((DBC *, ca_recno_arg, int *)); + */ +int +__ram_ca(dbc_arg, op, foundp) + DBC *dbc_arg; + ca_recno_arg op; + int *foundp; +{ + BTREE_CURSOR *cp_arg; + DB *dbp; + ENV *env; + db_recno_t recno; + u_int32_t found, order; + int ret; + + dbp = dbc_arg->dbp; + env = dbp->env; + cp_arg = (BTREE_CURSOR *)dbc_arg->internal; + recno = cp_arg->recno; + + /* + * It only makes sense to adjust cursors if we're a renumbering + * recno; we should only be called if this is one. + */ + DB_ASSERT(env, F_ISSET(cp_arg, C_RENUMBER)); + + /* + * Adjust the cursors. See the comment in __bam_ca_delete(). + * + * If we're doing a delete, we need to find the highest + * order of any cursor currently pointing at this item, + * so we can assign a higher order to the newly deleted + * cursor. Unfortunately, this requires a second pass through + * the cursor list. + */ + if (op == CA_DELETE) { + if ((ret = __db_walk_cursors(dbp, NULL, __ram_ca_getorder, + &order, BAM_ROOT_PGNO(dbc_arg), recno, NULL)) != 0) + return (ret); + order++; + } else + order = INVALID_ORDER; + + if ((ret = __db_walk_cursors(dbp, dbc_arg, + __ram_ca_setorder, &found, 0, order, &op)) != 0) + return (ret); + if (foundp != NULL) + *foundp = (int)found; + return (0); +} + +/* + * __ram_getno -- + * Check the user's record number, and make sure we've seen it. + * + * PUBLIC: int __ram_getno __P((DBC *, const DBT *, db_recno_t *, int)); + */ +int +__ram_getno(dbc, key, rep, can_create) + DBC *dbc; + const DBT *key; + db_recno_t *rep; + int can_create; +{ + DB *dbp; + db_recno_t recno; + + dbp = dbc->dbp; + + /* If passed an empty DBT from Java, key->data may be NULL */ + if (key->size != sizeof(db_recno_t)) { + __db_errx(dbp->env, DB_STR("1001", + "illegal record number size")); + return (EINVAL); + } + + /* Check the user's record number. */ + if ((recno = *(db_recno_t *)key->data) == 0) { + __db_errx(dbp->env, DB_STR("1002", + "illegal record number of 0")); + return (EINVAL); + } + if (rep != NULL) + *rep = recno; + + /* + * Btree can neither create records nor read them in. Recno can + * do both, see if we can find the record. + */ + return (dbc->dbtype == DB_RECNO ? + __ram_update(dbc, recno, can_create) : 0); +} + +/* + * __ram_update -- + * Ensure the tree has records up to and including the specified one. + */ +static int +__ram_update(dbc, recno, can_create) + DBC *dbc; + db_recno_t recno; + int can_create; +{ + BTREE *t; + DB *dbp; + DBT *rdata; + db_recno_t nrecs; + int ret; + + dbp = dbc->dbp; + t = dbp->bt_internal; + + /* + * If we can't create records and we've read the entire backing input + * file, we're done. + */ + if (!can_create && t->re_eof) + return (0); + + /* + * If we haven't seen this record yet, try to get it from the original + * file. + */ + if ((ret = __bam_nrecs(dbc, &nrecs)) != 0) + return (ret); + if (!t->re_eof && recno > nrecs) { + if ((ret = __ram_sread(dbc, recno)) != 0 && ret != DB_NOTFOUND) + return (ret); + if ((ret = __bam_nrecs(dbc, &nrecs)) != 0) + return (ret); + } + + /* + * If we can create records, create empty ones up to the requested + * record. + */ + if (!can_create || recno <= nrecs + 1) + return (0); + + rdata = &dbc->my_rdata; + rdata->flags = 0; + rdata->size = 0; + + while (recno > ++nrecs) + if ((ret = __ram_add(dbc, + &nrecs, rdata, 0, BI_DELETED)) != 0) + return (ret); + return (0); +} + +/* + * __ram_source -- + * Load information about the backing file. + */ +static int +__ram_source(dbp) + DB *dbp; +{ + BTREE *t; + ENV *env; + char *source; + int ret; + + env = dbp->env; + t = dbp->bt_internal; + + /* Find the real name, and swap out the one we had before. */ + if ((ret = __db_appname(env, + DB_APP_DATA, t->re_source, NULL, &source)) != 0) + return (ret); + __os_free(env, t->re_source); + t->re_source = source; + + /* + * !!! + * It's possible that the backing source file is read-only. We don't + * much care other than we'll complain if there are any modifications + * when it comes time to write the database back to the source. + */ + if ((t->re_fp = fopen(t->re_source, "rb")) == NULL) { + ret = __os_get_errno(); + __db_err(env, ret, "%s", t->re_source); + return (ret); + } + + t->re_eof = 0; + return (0); +} + +/* + * __ram_writeback -- + * Rewrite the backing file. + * + * PUBLIC: int __ram_writeback __P((DB *)); + */ +int +__ram_writeback(dbp) + DB *dbp; +{ + BTREE *t; + DBC *dbc; + DBT key, data; + DB_THREAD_INFO *ip; + ENV *env; + FILE *fp; + db_recno_t keyno; + int ret, t_ret; + u_int8_t delim, *pad; + + t = dbp->bt_internal; + env = dbp->env; + fp = NULL; + pad = NULL; + + /* If the file wasn't modified, we're done. */ + if (!t->re_modified) + return (0); + + /* If there's no backing source file, we're done. */ + if (t->re_source == NULL) { + t->re_modified = 0; + return (0); + } + + /* + * We step through the records, writing each one out. Use the record + * number and the dbp->get() function, instead of a cursor, so we find + * and write out "deleted" or non-existent records. The DB handle may + * be threaded, so allocate memory as we go. + */ + memset(&key, 0, sizeof(key)); + key.size = sizeof(db_recno_t); + key.data = &keyno; + memset(&data, 0, sizeof(data)); + F_SET(&data, DB_DBT_REALLOC); + + /* Allocate a cursor. */ + ENV_GET_THREAD_INFO(env, ip); + if ((ret = __db_cursor(dbp, ip, NULL, &dbc, 0)) != 0) + return (ret); + + /* + * Read any remaining records into the tree. + * + * !!! + * This is why we can't support transactions when applications specify + * backing (re_source) files. At this point we have to read in the + * rest of the records from the file so that we can write all of the + * records back out again, which could modify a page for which we'd + * have to log changes and which we don't have locked. This could be + * partially fixed by taking a snapshot of the entire file during the + * DB->open as DB->open is transaction protected. But, if a checkpoint + * occurs then, the part of the log holding the copy of the file could + * be discarded, and that would make it impossible to recover in the + * face of disaster. This could all probably be fixed, but it would + * require transaction protecting the backing source file. + * + * XXX + * This could be made to work now that we have transactions protecting + * file operations. Margo has specifically asked for the privilege of + * doing this work. + */ + if ((ret = + __ram_update(dbc, DB_MAX_RECORDS, 0)) != 0 && ret != DB_NOTFOUND) + goto err; + + /* + * Close any existing file handle and re-open the file, truncating it. + */ + if (t->re_fp != NULL) { + if (fclose(t->re_fp) != 0) { + ret = __os_get_errno(); + __db_err(env, ret, "%s", t->re_source); + goto err; + } + t->re_fp = NULL; + } + if ((fp = fopen(t->re_source, "wb")) == NULL) { + ret = __os_get_errno(); + __db_err(env, ret, "%s", t->re_source); + goto err; + } + + /* + * We'll need the delimiter if we're doing variable-length records, + * and the pad character if we're doing fixed-length records. + */ + delim = t->re_delim; + for (keyno = 1;; ++keyno) { + switch (ret = __db_get(dbp, ip, NULL, &key, &data, 0)) { + case 0: + if (data.size != 0 && + fwrite(data.data, 1, data.size, fp) != data.size) + goto write_err; + break; + case DB_KEYEMPTY: + if (F_ISSET(dbp, DB_AM_FIXEDLEN)) { + if (pad == NULL) { + if ((ret = __os_malloc( + env, t->re_len, &pad)) != 0) + goto err; + memset(pad, t->re_pad, t->re_len); + } + if (fwrite(pad, 1, t->re_len, fp) != t->re_len) + goto write_err; + } + break; + case DB_NOTFOUND: + ret = 0; + goto done; + default: + goto err; + } + if (!F_ISSET(dbp, DB_AM_FIXEDLEN) && + fwrite(&delim, 1, 1, fp) != 1) { +write_err: ret = __os_get_errno(); + __db_err(env, ret, DB_STR_A("1003", + "%s: write failed to backing file", "%s"), + t->re_source); + goto err; + } + } + +err: +done: /* Close the file descriptor. */ + if (fp != NULL && fclose(fp) != 0) { + t_ret = __os_get_errno(); + __db_err(env, t_ret, "%s", t->re_source); + if (ret == 0) + ret = t_ret; + } + + /* Discard the cursor. */ + if ((t_ret = __dbc_close(dbc)) != 0 && ret == 0) + ret = t_ret; + + /* Discard memory allocated to hold the data items. */ + if (data.data != NULL) + __os_ufree(env, data.data); + if (pad != NULL) + __os_free(env, pad); + + if (ret == 0) + t->re_modified = 0; + + return (ret); +} + +/* + * __ram_sread -- + * Read records from a source file. + */ +static int +__ram_sread(dbc, top) + DBC *dbc; + db_recno_t top; +{ + BTREE *t; + DB *dbp; + DBT data, *rdata; + db_recno_t recno; + size_t len; + int ch, ret, was_modified; + + t = dbc->dbp->bt_internal; + dbp = dbc->dbp; + was_modified = t->re_modified; + + if ((ret = __bam_nrecs(dbc, &recno)) != 0) + return (ret); + + /* + * Use the record key return memory, it's only a short-term use. + * The record data return memory is used by __bam_iitem, which + * we'll indirectly call, so use the key so as not to collide. + */ + len = F_ISSET(dbp, DB_AM_FIXEDLEN) ? t->re_len : 256; + rdata = &dbc->my_rkey; + if (rdata->ulen < len) { + if ((ret = __os_realloc( + dbp->env, len, &rdata->data)) != 0) { + rdata->ulen = 0; + rdata->data = NULL; + return (ret); + } + rdata->ulen = (u_int32_t)len; + } + + memset(&data, 0, sizeof(data)); + while (recno < top) { + data.data = rdata->data; + data.size = 0; + if (F_ISSET(dbp, DB_AM_FIXEDLEN)) + for (len = t->re_len; len > 0; --len) { + if ((ch = fgetc(t->re_fp)) == EOF) { + if (data.size == 0) + goto eof; + break; + } + ((u_int8_t *)data.data)[data.size++] = ch; + } + else + for (;;) { + if ((ch = fgetc(t->re_fp)) == EOF) { + if (data.size == 0) + goto eof; + break; + } + if (ch == t->re_delim) + break; + + ((u_int8_t *)data.data)[data.size++] = ch; + if (data.size == rdata->ulen) { + if ((ret = __os_realloc(dbp->env, + rdata->ulen *= 2, + &rdata->data)) != 0) { + rdata->ulen = 0; + rdata->data = NULL; + return (ret); + } else + data.data = rdata->data; + } + } + + /* + * Another process may have read this record from the input + * file and stored it into the database already, in which + * case we don't need to repeat that operation. We detect + * this by checking if the last record we've read is greater + * or equal to the number of records in the database. + */ + if (t->re_last >= recno) { + ++recno; + if ((ret = __ram_add(dbc, &recno, &data, 0, 0)) != 0) + goto err; + } + ++t->re_last; + } + + if (0) { +eof: t->re_eof = 1; + ret = DB_NOTFOUND; + } +err: if (!was_modified) + t->re_modified = 0; + + return (ret); +} + +/* + * __ram_add -- + * Add records into the tree. + */ +static int +__ram_add(dbc, recnop, data, flags, bi_flags) + DBC *dbc; + db_recno_t *recnop; + DBT *data; + u_int32_t flags, bi_flags; +{ + BTREE_CURSOR *cp; + int exact, ret, stack, t_ret; + + cp = (BTREE_CURSOR *)dbc->internal; + +retry: /* Find the slot for insertion. */ + if ((ret = __bam_rsearch(dbc, recnop, + SR_INSERT | (flags == DB_APPEND ? SR_APPEND : 0), 1, &exact)) != 0) + return (ret); + stack = 1; + + /* Copy the page into the cursor. */ + STACK_TO_CURSOR(cp, ret); + if (ret != 0) + goto err; + + if (exact && flags == DB_NOOVERWRITE && !CD_ISSET(cp) && + !B_DISSET(GET_BKEYDATA(dbc->dbp, cp->page, cp->indx)->type)) { + ret = DB_KEYEXIST; + goto err; + } + + /* + * The application may modify the data based on the selected record + * number. + */ + if (flags == DB_APPEND && dbc->dbp->db_append_recno != NULL && + (ret = dbc->dbp->db_append_recno(dbc->dbp, data, *recnop)) != 0) + goto err; + + /* + * Select the arguments for __bam_iitem() and do the insert. If the + * key is an exact match, or we're replacing the data item with a + * new data item, replace the current item. If the key isn't an exact + * match, we're inserting a new key/data pair, before the search + * location. + */ + switch (ret = __bam_iitem(dbc, + NULL, data, exact ? DB_CURRENT : DB_BEFORE, bi_flags)) { + case 0: + /* + * Don't adjust anything. + * + * If we inserted a record, no cursors need adjusting because + * the only new record it's possible to insert is at the very + * end of the tree. The necessary adjustments to the internal + * page counts were made by __bam_iitem(). + * + * If we overwrote a record, no cursors need adjusting because + * future DBcursor->get calls will simply return the underlying + * record (there's no adjustment made for the DB_CURRENT flag + * when a cursor get operation immediately follows a cursor + * delete operation, and the normal adjustment for the DB_NEXT + * flag is still correct). + */ + break; + case DB_NEEDSPLIT: + /* Discard the stack of pages and split the page. */ + (void)__bam_stkrel(dbc, STK_CLRDBC); + stack = 0; + + if ((ret = __bam_split(dbc, recnop, NULL)) != 0) + goto err; + + goto retry; + /* NOTREACHED */ + default: + goto err; + } + +err: if (stack && (t_ret = __bam_stkrel(dbc, STK_CLRDBC)) != 0 && ret == 0) + ret = t_ret; + + return (ret); +} diff -r 000000000000 -r a1985f14b030 src/btree/bt_rsearch.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/btree/bt_rsearch.c Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,535 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 1996, 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +/* + * Copyright (c) 1990, 1993, 1994, 1995, 1996 + * Keith Bostic. All rights reserved. + */ +/* + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $Id$ + */ + +#include "db_config.h" + +#include "db_int.h" +#include "dbinc/db_page.h" +#include "dbinc/btree.h" +#include "dbinc/lock.h" +#include "dbinc/mp.h" + +/* + * __bam_rsearch -- + * Search a btree for a record number. + * + * PUBLIC: int __bam_rsearch __P((DBC *, db_recno_t *, u_int32_t, int, int *)); + */ +int +__bam_rsearch(dbc, recnop, flags, stop, exactp) + DBC *dbc; + db_recno_t *recnop; + u_int32_t flags; + int stop, *exactp; +{ + BINTERNAL *bi; + BTREE_CURSOR *cp; + DB *dbp; + DB_LOCK lock; + DB_MPOOLFILE *mpf; + ENV *env; + PAGE *h; + RINTERNAL *ri; + db_indx_t adjust, deloffset, indx, top; + db_lockmode_t lock_mode; + db_pgno_t pg; + db_recno_t recno, t_recno, total; + u_int32_t get_mode; + int ret, stack, t_ret; + + if (F_ISSET(dbc, DBC_OPD)) + LOCK_CHECK_OFF(dbc->thread_info); + + dbp = dbc->dbp; + env = dbp->env; + mpf = dbp->mpf; + cp = (BTREE_CURSOR *)dbc->internal; + h = NULL; + ret = 0; + + BT_STK_CLR(cp); + + /* + * There are several ways we search a btree tree. The flags argument + * specifies if we're acquiring read or write locks and if we are + * locking pairs of pages. In addition, if we're adding or deleting + * an item, we have to lock the entire tree, regardless. See btree.h + * for more details. + * + * If write-locking pages, we need to know whether or not to acquire a + * write lock on a page before getting it. This depends on how deep it + * is in tree, which we don't know until we acquire the root page. So, + * if we need to lock the root page we may have to upgrade it later, + * because we won't get the correct lock initially. + * + * Retrieve the root page. + */ + + if ((ret = __bam_get_root(dbc, PGNO_INVALID, stop, flags, &stack)) != 0) + goto done; + lock_mode = cp->csp->lock_mode; + get_mode = lock_mode == DB_LOCK_WRITE ? DB_MPOOL_DIRTY : 0; + lock = cp->csp->lock; + h = cp->csp->page; + + BT_STK_CLR(cp); + /* + * If appending to the tree, set the record number now -- we have the + * root page locked. + * + * Delete only deletes exact matches, read only returns exact matches. + * Note, this is different from __bam_search(), which returns non-exact + * matches for read. + * + * The record may not exist. We can only return the correct location + * for the record immediately after the last record in the tree, so do + * a fast check now. + */ + total = RE_NREC(h); + if (LF_ISSET(SR_APPEND)) { + *exactp = 0; + *recnop = recno = total + 1; + } else { + recno = *recnop; + if (recno <= total) + *exactp = 1; + else { + *exactp = 0; + if (!LF_ISSET(SR_PAST_EOF) || recno > total + 1) { + /* + * Keep the page locked for serializability. + * + * XXX + * This leaves the root page locked, which will + * eliminate any concurrency. A possible fix + * would be to lock the last leaf page instead. + */ + ret = __memp_fput(mpf, + dbc->thread_info, h, dbc->priority); + if ((t_ret = + __TLPUT(dbc, lock)) != 0 && ret == 0) + ret = t_ret; + if (ret == 0) + ret = DB_NOTFOUND; + goto done; + } + } + } + + /* + * !!! + * Record numbers in the tree are 0-based, but the recno is + * 1-based. All of the calculations below have to take this + * into account. + */ + for (total = 0;;) { + switch (TYPE(h)) { + case P_LBTREE: + if (LF_ISSET(SR_MAX)) { + indx = NUM_ENT(h) - 2; + goto enter; + } + /* FALLTHROUGH */ + case P_LDUP: + if (LF_ISSET(SR_MAX)) { + indx = NUM_ENT(h) - 1; + goto enter; + } + recno -= total; + /* + * There may be logically deleted records on the page. + * If there are enough, the record may not exist. + */ + if (TYPE(h) == P_LBTREE) { + adjust = P_INDX; + deloffset = O_INDX; + } else { + adjust = O_INDX; + deloffset = 0; + } + for (t_recno = 0, indx = 0;; indx += adjust) { + if (indx >= NUM_ENT(h)) { + *exactp = 0; + if (!LF_ISSET(SR_PAST_EOF) || + recno > t_recno + 1) { + ret = __memp_fput(mpf, + dbc->thread_info, + h, dbc->priority); + h = NULL; + if ((t_ret = __TLPUT(dbc, + lock)) != 0 && ret == 0) + ret = t_ret; + if (ret == 0) + ret = DB_NOTFOUND; + goto err; + } + } + if (!B_DISSET(GET_BKEYDATA(dbp, h, + indx + deloffset)->type) && + ++t_recno == recno) + break; + } + + BT_STK_ENTER(env, cp, h, indx, lock, lock_mode, ret); + if (ret != 0) + goto err; + if (LF_ISSET(SR_BOTH)) + goto get_prev; + goto done; + case P_IBTREE: + if (LF_ISSET(SR_MAX)) { + indx = NUM_ENT(h); + bi = GET_BINTERNAL(dbp, h, indx - 1); + } else for (indx = 0, top = NUM_ENT(h);;) { + bi = GET_BINTERNAL(dbp, h, indx); + if (++indx == top || total + bi->nrecs >= recno) + break; + total += bi->nrecs; + } + pg = bi->pgno; + break; + case P_LRECNO: + if (LF_ISSET(SR_MAX)) + recno = NUM_ENT(h); + else + recno -= total; + + /* Correct from 1-based to 0-based for a page offset. */ + --recno; +enter: BT_STK_ENTER(env, cp, h, recno, lock, lock_mode, ret); + if (ret != 0) + goto err; + if (LF_ISSET(SR_BOTH)) { +get_prev: DB_ASSERT(env, LF_ISSET(SR_NEXT)); + /* + * We have a NEXT tree, now add the sub tree + * that points gets to the previous page. + */ + cp->csp++; + indx = cp->sp->indx - 1; + h = cp->sp->page; + if (TYPE(h) == P_IRECNO) { + ri = GET_RINTERNAL(dbp, h, indx); + pg = ri->pgno; + } else { + DB_ASSERT(env, TYPE(h) == P_IBTREE); + bi = GET_BINTERNAL(dbp, h, indx); + pg = bi->pgno; + } + LF_CLR(SR_NEXT | SR_BOTH); + LF_SET(SR_MAX); + stack = 1; + h = NULL; + goto lock_next; + } + goto done; + case P_IRECNO: + if (LF_ISSET(SR_MAX)) { + indx = NUM_ENT(h); + ri = GET_RINTERNAL(dbp, h, indx - 1); + } else for (indx = 0, top = NUM_ENT(h);;) { + ri = GET_RINTERNAL(dbp, h, indx); + if (++indx == top || total + ri->nrecs >= recno) + break; + total += ri->nrecs; + } + pg = ri->pgno; + break; + default: + ret = __db_pgfmt(env, h->pgno); + goto done; + } + --indx; + + /* Return if this is the lowest page wanted. */ + if (stop == LEVEL(h)) { + BT_STK_ENTER(env, cp, h, indx, lock, lock_mode, ret); + if (ret != 0) + goto err; + goto done; + } + if (stack) { + BT_STK_PUSH(env, cp, h, indx, lock, lock_mode, ret); + if (ret != 0) + goto err; + h = NULL; + + lock_mode = DB_LOCK_WRITE; + get_mode = DB_MPOOL_DIRTY; + if ((ret = + __db_lget(dbc, 0, pg, lock_mode, 0, &lock)) != 0) + goto err; + } else if (LF_ISSET(SR_NEXT)) { + /* + * For RECNO if we are doing a NEXT search the + * search recno is the one we are looking for + * but we want to keep the stack from the spanning + * node on down. We only know we have the spanning + * node when its child's index is 0, so save + * each node and discard the tree when we find out + * its not needed. + */ + if (indx != 0 && cp->sp->page != NULL) { + BT_STK_POP(cp); + if ((ret = __bam_stkrel(dbc, STK_NOLOCK)) != 0) + goto err; + } + + BT_STK_PUSH(env, cp, h, indx, lock, lock_mode, ret); + h = NULL; + if (ret != 0) + goto err; +lock_next: if ((ret = + __db_lget(dbc, 0, pg, lock_mode, 0, &lock)) != 0) + goto err; + } else { + /* + * Decide if we want to return a pointer to the next + * page in the stack. If we do, write lock it and + * never unlock it. + */ + if ((LF_ISSET(SR_PARENT) && + (u_int8_t)(stop + 1) >= (u_int8_t)(LEVEL(h) - 1)) || + (LEVEL(h) - 1) == LEAFLEVEL) + stack = 1; + + if ((ret = __memp_fput(mpf, + dbc->thread_info, h, dbc->priority)) != 0) + goto err; + h = NULL; + + lock_mode = stack && + LF_ISSET(SR_WRITE) ? DB_LOCK_WRITE : DB_LOCK_READ; + if (lock_mode == DB_LOCK_WRITE) + get_mode = DB_MPOOL_DIRTY; + if ((ret = __db_lget(dbc, + LCK_COUPLE_ALWAYS, pg, lock_mode, 0, &lock)) != 0) { + /* + * If we fail, discard the lock we held. This + * is OK because this only happens when we are + * descending the tree holding read-locks. + */ + (void)__LPUT(dbc, lock); + goto err; + } + } + + if ((ret = __memp_fget(mpf, &pg, + dbc->thread_info, dbc->txn, get_mode, &h)) != 0) + goto err; + } + /* NOTREACHED */ + +err: if (h != NULL && (t_ret = __memp_fput(mpf, + dbc->thread_info, h, dbc->priority)) != 0 && ret == 0) + ret = t_ret; + + BT_STK_POP(cp); + (void)__bam_stkrel(dbc, 0); + +done: + if (F_ISSET(dbc, DBC_OPD)) + LOCK_CHECK_ON(dbc->thread_info); + return (ret); +} + +/* + * __bam_adjust -- + * Adjust the tree after adding or deleting a record. + * + * PUBLIC: int __bam_adjust __P((DBC *, int32_t)); + */ +int +__bam_adjust(dbc, adjust) + DBC *dbc; + int32_t adjust; +{ + BTREE_CURSOR *cp; + DB *dbp; + DB_MPOOLFILE *mpf; + EPG *epg; + PAGE *h; + db_pgno_t root_pgno; + int ret; + + dbp = dbc->dbp; + mpf = dbp->mpf; + cp = (BTREE_CURSOR *)dbc->internal; + root_pgno = BAM_ROOT_PGNO(dbc); + + /* Update the record counts for the tree. */ + for (epg = cp->sp; epg <= cp->csp; ++epg) { + h = epg->page; + if (TYPE(h) == P_IBTREE || TYPE(h) == P_IRECNO) { + ret = __memp_dirty(mpf, &h, + dbc->thread_info, dbc->txn, dbc->priority, 0); + epg->page = h; + if (ret != 0) + return (ret); + if (DBC_LOGGING(dbc)) { + if ((ret = __bam_cadjust_log(dbp, dbc->txn, + &LSN(h), 0, PGNO(h), &LSN(h), + (u_int32_t)epg->indx, adjust, + PGNO(h) == root_pgno ? + CAD_UPDATEROOT : 0)) != 0) + return (ret); + } else + LSN_NOT_LOGGED(LSN(h)); + + if (TYPE(h) == P_IBTREE) + GET_BINTERNAL(dbp, h, epg->indx)->nrecs += + adjust; + else + GET_RINTERNAL(dbp, h, epg->indx)->nrecs += + adjust; + + if (PGNO(h) == root_pgno) + RE_NREC_ADJ(h, adjust); + } + } + return (0); +} + +/* + * __bam_nrecs -- + * Return the number of records in the tree. + * + * PUBLIC: int __bam_nrecs __P((DBC *, db_recno_t *)); + */ +int +__bam_nrecs(dbc, rep) + DBC *dbc; + db_recno_t *rep; +{ + DB *dbp; + DB_LOCK lock; + DB_MPOOLFILE *mpf; + PAGE *h; + db_pgno_t pgno; + int ret, t_ret; + + COMPQUIET(h, NULL); + dbp = dbc->dbp; + mpf = dbp->mpf; + LOCK_INIT(lock); + + pgno = PGNO_INVALID; + BAM_GET_ROOT(dbc, pgno, h, 0, DB_LOCK_READ, lock, ret); + if (ret != 0) + goto err; + DB_ASSERT(dbp->env, h != NULL); + + *rep = RE_NREC(h); + + ret = __memp_fput(mpf, dbc->thread_info, h, dbc->priority); +err: if ((t_ret = __TLPUT(dbc, lock)) != 0 && ret == 0) + ret = t_ret; + + return (ret); +} + +/* + * __bam_total -- + * Return the number of records below a page. + * + * PUBLIC: db_recno_t __bam_total __P((DB *, PAGE *)); + */ +db_recno_t +__bam_total(dbp, h) + DB *dbp; + PAGE *h; +{ + db_recno_t nrecs; + db_indx_t indx, top; + + nrecs = 0; + top = NUM_ENT(h); + + switch (TYPE(h)) { + case P_LBTREE: + /* Check for logically deleted records. */ + for (indx = 0; indx < top; indx += P_INDX) + if (!B_DISSET( + GET_BKEYDATA(dbp, h, indx + O_INDX)->type)) + ++nrecs; + break; + case P_LDUP: + /* Check for logically deleted records. */ + for (indx = 0; indx < top; indx += O_INDX) + if (!B_DISSET(GET_BKEYDATA(dbp, h, indx)->type)) + ++nrecs; + break; + case P_IBTREE: + for (indx = 0; indx < top; indx += O_INDX) + nrecs += GET_BINTERNAL(dbp, h, indx)->nrecs; + break; + case P_LRECNO: + nrecs = NUM_ENT(h); + break; + case P_IRECNO: + for (indx = 0; indx < top; indx += O_INDX) + nrecs += GET_RINTERNAL(dbp, h, indx)->nrecs; + break; + } + + return (nrecs); +} diff -r 000000000000 -r a1985f14b030 src/btree/bt_search.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/btree/bt_search.c Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,1050 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 1996, 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +/* + * Copyright (c) 1990, 1993, 1994, 1995, 1996 + * Keith Bostic. All rights reserved. + */ +/* + * Copyright (c) 1990, 1993, 1994, 1995 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Mike Olson. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $Id$ + */ + +#include "db_config.h" + +#include "db_int.h" +#include "dbinc/db_page.h" +#include "dbinc/btree.h" +#include "dbinc/lock.h" +#include "dbinc/mp.h" + +/* + * __bam_get_root -- + * Fetch the root of a tree and see if we want to keep + * it in the stack. + * + * PUBLIC: int __bam_get_root __P((DBC *, db_pgno_t, int, u_int32_t, int *)); + */ +int +__bam_get_root(dbc, root_pgno, slevel, flags, stack) + DBC *dbc; + db_pgno_t root_pgno; + int slevel; + u_int32_t flags; + int *stack; +{ + BTREE_CURSOR *cp; + DB *dbp; + DB_LOCK lock; + DB_MPOOLFILE *mpf; + PAGE *h; + db_lockmode_t lock_mode; + u_int32_t get_mode; + int ret, t_ret; + + COMPQUIET(h, NULL); + LOCK_INIT(lock); + dbp = dbc->dbp; + mpf = dbp->mpf; + cp = (BTREE_CURSOR *)dbc->internal; + /* + * If write-locking pages, we need to know whether or not to acquire a + * write lock on a page before getting it. This depends on how deep it + * is in tree, which we don't know until we acquire the root page. So, + * if we need to lock the root page we may have to upgrade it later, + * because we won't get the correct lock initially. + * + * Retrieve the root page. + */ +try_again: + *stack = LF_ISSET(SR_STACK) && + (dbc->dbtype == DB_RECNO || F_ISSET(cp, C_RECNUM)); + lock_mode = DB_LOCK_READ; + if (*stack || + LF_ISSET(SR_DEL) || (LF_ISSET(SR_NEXT) && LF_ISSET(SR_WRITE))) + lock_mode = DB_LOCK_WRITE; + + /* + * Get the root. If the root happens to be a leaf page then + * we are supposed to get a read lock on it before latching + * it. So if we have not locked it do a try get first. + * If we can't get the root shared, then get a lock on it and + * then wait for the latch. + */ +retry: if (lock_mode == DB_LOCK_WRITE) + get_mode = DB_MPOOL_DIRTY; + else if (LOCK_ISSET(lock) || !STD_LOCKING(dbc) || + F_ISSET(dbc, DBC_DOWNREV) || + dbc->dbtype == DB_RECNO || F_ISSET(cp, C_RECNUM)) + get_mode = 0; + else + get_mode = DB_MPOOL_TRY; + + BAM_GET_ROOT(dbc, root_pgno, h, get_mode, lock_mode, lock, ret); + if (ret == DB_LOCK_NOTGRANTED && get_mode == DB_MPOOL_TRY) { + DB_ASSERT(dbp->env, !LOCK_ISSET(lock)); + if ((ret = __db_lget(dbc, 0, + root_pgno == PGNO_INVALID ? BAM_ROOT_PGNO(dbc) : root_pgno, + lock_mode, 0, &lock)) != 0) + return (ret); + goto retry; + } + if (ret != 0) { + /* Did not read it, so we can release the lock */ + (void)__LPUT(dbc, lock); + return (ret); + } + DB_ASSERT(dbp->env, TYPE(h) == P_IBTREE || TYPE(h) == P_IRECNO || + TYPE(h) == P_LBTREE || TYPE(h) == P_LRECNO || TYPE(h) == P_LDUP); + + /* + * Decide if we need to dirty and/or lock this page. + * We must not hold the latch while we get the lock. + */ + if (!*stack && + ((LF_ISSET(SR_PARENT) && (u_int8_t)(slevel + 1) >= LEVEL(h)) || + LEVEL(h) == LEAFLEVEL || + (LF_ISSET(SR_START) && slevel == LEVEL(h)))) { + *stack = 1; + /* If we already have the write lock, we are done. */ + if (dbc->dbtype == DB_RECNO || F_ISSET(cp, C_RECNUM)) { + if (lock_mode == DB_LOCK_WRITE) + goto done; + if ((ret = __LPUT(dbc, lock)) != 0) + return (ret); + } + + /* + * Now that we know what level the root is at, do we need a + * write lock? If not or we got the lock before latching + * we are done. + */ + if (LEVEL(h) != LEAFLEVEL || LF_ISSET(SR_WRITE)) { + lock_mode = DB_LOCK_WRITE; + /* Drop the read lock if we got it above. */ + if ((ret = __LPUT(dbc, lock)) != 0) + return (ret); + } else if (LOCK_ISSET(lock)) + goto done; + if (!STD_LOCKING(dbc)) { + if (lock_mode != DB_LOCK_WRITE) + goto done; + if ((ret = __memp_dirty(mpf, &h, dbc->thread_info, + dbc->txn, dbc->priority, 0)) != 0) { + if (h != NULL) + (void)__memp_fput(mpf, + dbc->thread_info, h, dbc->priority); + return (ret); + } + } else { + /* Try to lock the page without waiting first. */ + if ((ret = __db_lget(dbc, 0, root_pgno, + lock_mode, DB_LOCK_NOWAIT, &lock)) == 0) { + if (lock_mode == DB_LOCK_WRITE && (ret = + __memp_dirty(mpf, &h, dbc->thread_info, + dbc->txn, dbc->priority, 0)) != 0) { + if (h != NULL) + (void)__memp_fput(mpf, + dbc->thread_info, h, + dbc->priority); + return (ret); + } + goto done; + } + + t_ret = __memp_fput(mpf, + dbc->thread_info, h, dbc->priority); + h = NULL; + + if (ret == DB_LOCK_DEADLOCK || + ret == DB_LOCK_NOTGRANTED) + ret = 0; + if (ret == 0) + ret = t_ret; + + if (ret != 0) + return (ret); + get_mode = 0; + if (lock_mode == DB_LOCK_WRITE) + get_mode = DB_MPOOL_DIRTY; + + if ((ret = __db_lget(dbc, + 0, root_pgno, lock_mode, 0, &lock)) != 0) + return (ret); + if ((ret = __memp_fget(mpf, + &root_pgno, dbc->thread_info, dbc->txn, + (atomic_read(&mpf->mfp->multiversion) == 0 && + lock_mode == DB_LOCK_WRITE) ? DB_MPOOL_DIRTY : 0, + &h)) != 0) { + /* Did not read it, release the lock */ + (void)__LPUT(dbc, lock); + return (ret); + } + } + /* + * While getting dirty or locked we need to drop the mutex + * so someone else could get in and split the root. + */ + if (!((LF_ISSET(SR_PARENT) && + (u_int8_t)(slevel + 1) >= LEVEL(h)) || + LEVEL(h) == LEAFLEVEL || + (LF_ISSET(SR_START) && slevel == LEVEL(h)))) { + /* Someone else split the root, start over. */ + ret = __memp_fput(mpf, + dbc->thread_info, h, dbc->priority); + h = NULL; + if ((t_ret = __LPUT(dbc, lock)) != 0 && ret == 0) + ret = t_ret; + if (ret != 0) + return (ret); + goto try_again; + } else if (atomic_read(&mpf->mfp->multiversion) != 0 && + lock_mode == DB_LOCK_WRITE && (ret = __memp_dirty(mpf, &h, + dbc->thread_info, dbc->txn, dbc->priority, 0)) != 0) { + (void)__memp_fput(mpf, + dbc->thread_info, h, dbc->priority); + (void)__LPUT(dbc, lock); + } + } + +done: BT_STK_ENTER(dbp->env, cp, h, 0, lock, lock_mode, ret); + + return (ret); +} + +/* + * __bam_search -- + * Search a btree for a key. + * + * PUBLIC: int __bam_search __P((DBC *, db_pgno_t, + * PUBLIC: const DBT *, u_int32_t, int, db_recno_t *, int *)); + */ +int +__bam_search(dbc, root_pgno, key, flags, slevel, recnop, exactp) + DBC *dbc; + db_pgno_t root_pgno; + const DBT *key; + u_int32_t flags; + int slevel, *exactp; + db_recno_t *recnop; +{ + BTREE *t; + BTREE_CURSOR *cp; + DB *dbp; + DB_LOCK lock, saved_lock; + DB_MPOOLFILE *mpf; + ENV *env; + PAGE *h, *parent_h; + db_indx_t base, i, indx, *inp, lim; + db_lockmode_t lock_mode; + db_pgno_t pg, saved_pg, start_pgno; + db_recno_t recno; + int adjust, cmp, deloffset, ret, set_stack, stack, t_ret; + int getlock, was_next; + int (*func) __P((DB *, const DBT *, const DBT *)); + u_int32_t get_mode, wait; + u_int8_t level, saved_level; + + if (F_ISSET(dbc, DBC_OPD)) + LOCK_CHECK_OFF(dbc->thread_info); + + dbp = dbc->dbp; + env = dbp->env; + mpf = dbp->mpf; + cp = (BTREE_CURSOR *)dbc->internal; + h = NULL; + parent_h = NULL; + t = dbp->bt_internal; + recno = 0; + t_ret = 0; + + BT_STK_CLR(cp); + LOCK_INIT(saved_lock); + LOCK_INIT(lock); + was_next = LF_ISSET(SR_NEXT); + wait = DB_LOCK_NOWAIT; + + /* + * There are several ways we search a btree tree. The flags argument + * specifies if we're acquiring read or write latches, if we position + * to the first or last item in a set of duplicates, if we return + * deleted items, and if we are latching pairs of pages. In addition, + * if we're modifying record numbers, we have to latch the entire tree + * regardless. See btree.h for more details. + */ + + start_pgno = saved_pg = root_pgno; + saved_level = MAXBTREELEVEL; +retry: if ((ret = __bam_get_root(dbc, start_pgno, slevel, flags, &stack)) != 0) + goto err; + lock_mode = cp->csp->lock_mode; + get_mode = lock_mode == DB_LOCK_WRITE ? DB_MPOOL_DIRTY : 0; + h = cp->csp->page; + root_pgno = pg = PGNO(h); + lock = cp->csp->lock; + set_stack = stack; + /* + * Determine if we need to lock interior nodes. + * If we have record numbers we always lock. Otherwise we only + * need to do this if we are write locking and we are returning + * a stack of nodes. SR_NEXT will eventually get a stack and + * release the locks above that level. + */ + if (F_ISSET(dbc, DBC_DOWNREV)) { + getlock = 1; + wait = 0; + } else + getlock = F_ISSET(cp, C_RECNUM) || + (lock_mode == DB_LOCK_WRITE && + (stack || LF_ISSET(SR_NEXT | SR_DEL))); + + /* + * If we are asked a level that is above the root, + * just return the root. This can happen if the tree + * collapses while we are trying to lock the root. + */ + if (!LF_ISSET(SR_START) && LEVEL(h) < slevel) + goto done; + + BT_STK_CLR(cp); + + /* Choose a comparison function. */ + func = F_ISSET(dbc, DBC_OPD) ? + (dbp->dup_compare == NULL ? __bam_defcmp : dbp->dup_compare) : + t->bt_compare; + + for (;;) { + if (TYPE(h) == P_LBTREE) + adjust = P_INDX; + else { + /* + * It is possible to catch an internal page as a change + * is being backed out. Its leaf pages will be locked + * but we must be sure we get to one. If the page + * is not populated enough lock it. + */ + if (TYPE(h) != P_LDUP && NUM_ENT(h) == 0) { + getlock = 1; + level = LEVEL(h) + 1; + if ((ret = __memp_fput(mpf, dbc->thread_info, + h, dbc->priority)) != 0) + goto err; + goto lock_next; + } + adjust = O_INDX; + } + inp = P_INP(dbp, h); + if (LF_ISSET(SR_MIN | SR_MAX)) { + if (LF_ISSET(SR_MIN) || NUM_ENT(h) == 0) + indx = 0; + else if (TYPE(h) == P_LBTREE) + indx = NUM_ENT(h) - 2; + else + indx = NUM_ENT(h) - 1; + + if (LEVEL(h) == LEAFLEVEL || + (!LF_ISSET(SR_START) && LEVEL(h) == slevel)) { + if (LF_ISSET(SR_NEXT)) + goto get_next; + goto found; + } + goto next; + } + /* + * Do a binary search on the current page. If we're searching + * a Btree leaf page, we have to walk the indices in groups of + * two. If we're searching an internal page or a off-page dup + * page, they're an index per page item. If we find an exact + * match on a leaf page, we're done. + */ + DB_BINARY_SEARCH_FOR(base, lim, NUM_ENT(h), adjust) { + DB_BINARY_SEARCH_INCR(indx, base, lim, adjust); + if ((ret = __bam_cmp(dbc, key, h, indx, + func, &cmp)) != 0) + goto err; + if (cmp == 0) { + if (LEVEL(h) == LEAFLEVEL || + (!LF_ISSET(SR_START) && + LEVEL(h) == slevel)) { + if (LF_ISSET(SR_NEXT)) + goto get_next; + goto found; + } + goto next; + } + if (cmp > 0) + DB_BINARY_SEARCH_SHIFT_BASE(indx, base, + lim, adjust); + } + + /* + * No match found. Base is the smallest index greater than + * key and may be zero or a last + O_INDX index. + * + * If it's a leaf page or the stopping point, + * return base as the "found" value. + * Delete only deletes exact matches. + */ + if (LEVEL(h) == LEAFLEVEL || + (!LF_ISSET(SR_START) && LEVEL(h) == slevel)) { + *exactp = 0; + + if (LF_ISSET(SR_EXACT)) { + ret = DB_NOTFOUND; + goto err; + } + + if (LF_ISSET(SR_STK_ONLY)) { + BT_STK_NUM(env, cp, h, base, ret); + if ((t_ret = + __LPUT(dbc, lock)) != 0 && ret == 0) + ret = t_ret; + if ((t_ret = __memp_fput(mpf, dbc->thread_info, + h, dbc->priority)) != 0 && ret == 0) + ret = t_ret; + h = NULL; + if (ret != 0) + goto err; + goto done; + } + if (LF_ISSET(SR_NEXT)) { +get_next: /* + * The caller could have asked for a NEXT + * at the root if the tree recently collapsed. + */ + if (PGNO(h) == root_pgno) { + ret = DB_NOTFOUND; + goto err; + } + + indx = cp->sp->indx + 1; + if (indx == NUM_ENT(cp->sp->page)) { + ret = DB_NOTFOUND; + cp->csp++; + goto err; + } + /* + * If we want both the key page and the next + * page, push the key page on the stack + * otherwise save the root of the subtree + * and drop the rest of the subtree. + * Search down again starting at the + * next child of the root of this subtree. + */ + LF_SET(SR_MIN); + LF_CLR(SR_NEXT); + set_stack = stack = 1; + if (LF_ISSET(SR_BOTH)) { + cp->csp++; + BT_STK_PUSH(env, + cp, h, indx, lock, lock_mode, ret); + if (ret != 0) + goto err; + LOCK_INIT(lock); + h = cp->sp->page; + pg = GET_BINTERNAL(dbp, h, indx)->pgno; + level = LEVEL(h); + h = NULL; + goto lock_next; + } else { + if ((ret = __LPUT(dbc, lock)) != 0) + goto err; + if ((ret = __memp_fput(mpf, + dbc->thread_info, + h, dbc->priority)) != 0) + goto err; + h = cp->sp->page; + cp->sp->page = NULL; + lock = cp->sp->lock; + LOCK_INIT(cp->sp->lock); + if ((ret = __bam_stkrel(dbc, + STK_NOLOCK)) != 0) + goto err; + goto next; + } + } + + /* + * !!! + * Possibly returning a deleted record -- DB_SET_RANGE, + * DB_KEYFIRST and DB_KEYLAST don't require an exact + * match, and we don't want to walk multiple pages here + * to find an undeleted record. This is handled by the + * calling routine. + */ + if (LF_ISSET(SR_DEL) && cp->csp == cp->sp) + cp->csp++; + BT_STK_ENTER(env, cp, h, base, lock, lock_mode, ret); + if (ret != 0) + goto err; + goto done; + } + + /* + * If it's not a leaf page, record the internal page (which is + * a parent page for the key). Decrement the base by 1 if it's + * non-zero so that if a split later occurs, the inserted page + * will be to the right of the saved page. + */ + indx = base > 0 ? base - O_INDX : base; + + /* + * If we're trying to calculate the record number, sum up + * all the record numbers on this page up to the indx point. + */ +next: if (recnop != NULL) + for (i = 0; i < indx; ++i) + recno += GET_BINTERNAL(dbp, h, i)->nrecs; + + pg = GET_BINTERNAL(dbp, h, indx)->pgno; + level = LEVEL(h); + + /* See if we are at the level to start stacking. */ + if (LF_ISSET(SR_START) && slevel == level) + set_stack = stack = 1; + + if (LF_ISSET(SR_STK_ONLY)) { + if (slevel == LEVEL(h)) { + BT_STK_NUM(env, cp, h, indx, ret); + if ((t_ret = __memp_fput(mpf, dbc->thread_info, + h, dbc->priority)) != 0 && ret == 0) + ret = t_ret; + h = NULL; + if (ret != 0) + goto err; + goto done; + } + BT_STK_NUMPUSH(env, cp, h, indx, ret); + (void)__memp_fput(mpf, + dbc->thread_info, h, dbc->priority); + h = NULL; + } else if (stack) { + /* Return if this is the lowest page wanted. */ + if (LF_ISSET(SR_PARENT) && slevel == level) { + BT_STK_ENTER(env, + cp, h, indx, lock, lock_mode, ret); + if (ret != 0) + goto err; + goto done; + } + if (LF_ISSET(SR_DEL) && NUM_ENT(h) > 1) { + /* + * There was a page with a singleton pointer + * to a non-empty subtree. + */ + cp->csp--; + if ((ret = __bam_stkrel(dbc, STK_NOLOCK)) != 0) + goto err; + set_stack = stack = 0; + goto do_del; + } + BT_STK_PUSH(env, + cp, h, indx, lock, lock_mode, ret); + if (ret != 0) + goto err; + + LOCK_INIT(lock); + get_mode = DB_MPOOL_DIRTY; + lock_mode = DB_LOCK_WRITE; + getlock = 1; + goto lock_next; + } else { + /* + * Decide if we want to return a reference to the next + * page in the return stack. If so, latch it and don't + * unlatch it. We will want to stack things on the + * next iteration. The stack variable cannot be + * set until we leave this clause. If we are locking + * then we must lock this level before getting the page. + */ + if ((LF_ISSET(SR_PARENT) && + (u_int8_t)(slevel + 1) >= (level - 1)) || + (level - 1) == LEAFLEVEL) + set_stack = 1; + + /* + * Check for a normal search. If so, we need to + * latch couple the parent/chid buffers. + */ + if (!LF_ISSET(SR_DEL | SR_NEXT)) { + parent_h = h; + goto lock_next; + } + + /* + * Returning a subtree. See if we have hit the start + * point if so save the parent and set stack. + * Otherwise free the parent and temporarily + * save this one. + * For SR_DEL we need to find a page with 1 entry. + * For SR_NEXT we want find the minimal subtree + * that contains the key and the next page. + * We save pages as long as we are at the right + * edge of the subtree. When we leave the right + * edge, then drop the subtree. + */ + + if ((LF_ISSET(SR_DEL) && NUM_ENT(h) == 1)) { + /* + * We are pushing the things on the stack, + * set the stack variable now to indicate this + * has happened. + */ + stack = set_stack = 1; + LF_SET(SR_WRITE); + /* Push the parent. */ + cp->csp++; + /* Push this node. */ + BT_STK_PUSH(env, cp, h, + indx, lock, DB_LOCK_NG, ret); + if (ret != 0) + goto err; + LOCK_INIT(lock); + } else { + /* + * See if we want to save the tree so far. + * If we are looking for the next key, + * then we must save this node if we are + * at the end of the page. If not then + * discard anything we have saved so far. + * For delete only keep one node until + * we find a singleton. + */ +do_del: if (cp->csp->page != NULL) { + if (LF_ISSET(SR_NEXT) && + indx == NUM_ENT(h) - 1) + cp->csp++; + else if ((ret = + __bam_stkrel(dbc, STK_NOLOCK)) != 0) + goto err; + } + /* Save this node. */ + BT_STK_ENTER(env, cp, + h, indx, lock, lock_mode, ret); + if (ret != 0) + goto err; + LOCK_INIT(lock); + } + +lock_next: h = NULL; + + if (set_stack && LF_ISSET(SR_WRITE)) { + lock_mode = DB_LOCK_WRITE; + get_mode = DB_MPOOL_DIRTY; + getlock = 1; + } + /* + * If we are retrying and we are back at the same + * page then we already have it locked. If we are + * at a different page we want to lock couple and + * release that lock. + */ + if (level - 1 == saved_level) { + if ((ret = __LPUT(dbc, lock)) != 0) + goto err; + lock = saved_lock; + LOCK_INIT(saved_lock); + saved_level = MAXBTREELEVEL; + if (pg == saved_pg) + goto skip_lock; + } + if ((getlock || level - 1 == LEAFLEVEL) && + (ret = __db_lget(dbc, LCK_COUPLE_ALWAYS, + pg, lock_mode, wait, &lock)) != 0) { + /* + * If we are doing DEL or NEXT then we + * have an extra level saved in the stack, + * push it so it will get freed. + */ + if (LF_ISSET(SR_DEL | SR_NEXT) && !stack) + cp->csp++; + PERFMON6(env, race, bam_search, dbp->fname, + dbp->dname, ret, h, parent_h, flags); + /* + * If we fail, discard the lock we held. + * This is ok because we will either search + * again or exit without actually looking + * at the data. + */ + if ((t_ret = __LPUT(dbc, lock)) != 0) + ret = t_ret; + /* + * If we blocked at a different level release + * the previous saved lock. + */ + if ((t_ret = __LPUT(dbc, saved_lock)) != 0 && + ret == 0) + ret = t_ret; + if (wait == 0 || (ret != DB_LOCK_NOTGRANTED && + ret != DB_LOCK_DEADLOCK)) + goto err; + + /* Release the parent if we are holding it. */ + if (parent_h != NULL && + (ret = __memp_fput(mpf, dbc->thread_info, + parent_h, dbc->priority)) != 0) + goto err; + parent_h = NULL; + + BT_STK_POP(cp); + if ((ret = __bam_stkrel(dbc, STK_NOLOCK)) != 0) + goto err; + if ((ret = __db_lget(dbc, + 0, pg, lock_mode, 0, &saved_lock)) != 0) + goto err; + /* + * A very strange case: if this page was + * freed while we wait then we cannot hold + * the lock on it while we reget the root + * latch because allocation is one place + * we lock while holding a latch. + * We want to hold the lock but must ensure + * that the page is not free or cannot become + * free. If we are at the LEAF level we can + * hold on to the lock if the page is still + * of the right type. Otherwise we need to + * be sure this page cannot move to an off page + * duplicate tree (which are not locked) and + * masquerade as the page we want. + */ + + /* + * If the page is not at leaf level + * then see if OPD trees are around. + * If the page could appear as an + * interior offpage duplicate node + * at the right level the it will + * not be locked and subsequently be + * freed. If there are multiple + * databases in the file then they + * could have OPDs. + */ + if (level - 1 > LEAFLEVEL && + (F_ISSET(dbp, DB_AM_SUBDB) || + (dbp->type == DB_BTREE && + F_ISSET(dbp, DB_AM_DUPSORT)))) + goto drop_lock; + + /* + * Take a look at the page. If it got + * freed it could be very gone. + */ + if ((ret = __memp_fget(mpf, &pg, + dbc->thread_info, dbc->txn, 0, &h)) != 0 && + ret != DB_PAGE_NOTFOUND) + goto err; + + /* + * Check for right level and page type. + */ + if (ret != 0 || LEVEL(h) != level - 1 || + (LEVEL(h) == LEAFLEVEL ? + TYPE(h) != (dbc->dbtype == DB_BTREE ? + P_LBTREE : P_LRECNO) : + TYPE(h) != (dbc->dbtype == DB_BTREE ? + P_IBTREE : P_IRECNO))) { +drop_lock: ret = __LPUT(dbc, saved_lock); + if (ret != 0) + goto err; + pg = root_pgno; + saved_level = MAXBTREELEVEL; + } + if (h != NULL && (ret = __memp_fput(mpf, + dbc->thread_info, h, dbc->priority)) != 0) + goto err; + h = NULL; + + if (was_next) { + LF_CLR(SR_MIN); + LF_SET(SR_NEXT); + } + /* + * We have the lock but we dropped the + * latch so we need to search again. If + * we get back to the same page then all + * is good, otherwise we need to try to + * lock the new page. + */ + saved_pg = pg; + saved_level = level - 1; + goto retry; + } +skip_lock: stack = set_stack; + } + /* Get the child page. */ + if ((ret = __memp_fget(mpf, &pg, + dbc->thread_info, dbc->txn, get_mode, &h)) != 0) + goto err; + /* Release the parent. */ + if (parent_h != NULL && (ret = __memp_fput(mpf, + dbc->thread_info, parent_h, dbc->priority)) != 0) + goto err; + parent_h = NULL; + } + /* NOTREACHED */ + +found: *exactp = 1; + + /* + * If we got here, we know that we have a Btree leaf or off-page + * duplicates page. If it's a Btree leaf page, we have to handle + * on-page duplicates. + * + * If there are duplicates, go to the first/last one. This is + * safe because we know that we're not going to leave the page, + * all duplicate sets that are not on overflow pages exist on a + * single leaf page. + */ + if (TYPE(h) == P_LBTREE && NUM_ENT(h) > P_INDX) { + if (LF_ISSET(SR_DUPLAST)) + while (indx < (db_indx_t)(NUM_ENT(h) - P_INDX) && + inp[indx] == inp[indx + P_INDX]) + indx += P_INDX; + else if (LF_ISSET(SR_DUPFIRST)) + while (indx > 0 && + inp[indx] == inp[indx - P_INDX]) + indx -= P_INDX; + } + + /* + * Now check if we are allowed to return deleted items; if not, then + * find the next (or previous) non-deleted duplicate entry. (We do + * not move from the original found key on the basis of the SR_DELNO + * flag.) + */ + DB_ASSERT(env, recnop == NULL || LF_ISSET(SR_DELNO)); + if (LF_ISSET(SR_DELNO)) { + deloffset = TYPE(h) == P_LBTREE ? O_INDX : 0; + if (LF_ISSET(SR_DUPLAST)) + while (B_DISSET(GET_BKEYDATA(dbp, + h, indx + deloffset)->type) && indx > 0 && + inp[indx] == inp[indx - adjust]) + indx -= adjust; + else + while (B_DISSET(GET_BKEYDATA(dbp, + h, indx + deloffset)->type) && + indx < (db_indx_t)(NUM_ENT(h) - adjust) && + inp[indx] == inp[indx + adjust]) + indx += adjust; + + /* + * If we weren't able to find a non-deleted duplicate, return + * DB_NOTFOUND. + */ + if (B_DISSET(GET_BKEYDATA(dbp, h, indx + deloffset)->type)) { + ret = DB_NOTFOUND; + goto err; + } + + /* + * Increment the record counter to point to the found element. + * Ignore any deleted key/data pairs. There doesn't need to + * be any correction for duplicates, as Btree doesn't support + * duplicates and record numbers in the same tree. + */ + if (recnop != NULL) { + DB_ASSERT(env, TYPE(h) == P_LBTREE); + + for (i = 0; i < indx; i += P_INDX) + if (!B_DISSET( + GET_BKEYDATA(dbp, h, i + O_INDX)->type)) + ++recno; + + /* Correct the number for a 0-base. */ + *recnop = recno + 1; + } + } + + if (LF_ISSET(SR_STK_ONLY)) { + BT_STK_NUM(env, cp, h, indx, ret); + if ((t_ret = __memp_fput(mpf, + dbc->thread_info, h, dbc->priority)) != 0 && ret == 0) + ret = t_ret; + h = NULL; + } else { + if (LF_ISSET(SR_DEL) && cp->csp == cp->sp) + cp->csp++; + BT_STK_ENTER(env, cp, h, indx, lock, lock_mode, ret); + } + if (ret != 0) + goto err; + + cp->csp->lock = lock; + DB_ASSERT(env, parent_h == NULL); + +done: + if (F_ISSET(dbc, DBC_OPD)) + LOCK_CHECK_ON(dbc->thread_info); + + if ((ret = __LPUT(dbc, saved_lock)) != 0) + return (ret); + + return (0); + +err: if (ret == 0) + ret = t_ret; + if (h != NULL && (t_ret = __memp_fput(mpf, + dbc->thread_info, h, dbc->priority)) != 0 && ret == 0) + ret = t_ret; + if (parent_h != NULL && (t_ret = __memp_fput(mpf, + dbc->thread_info, parent_h, dbc->priority)) != 0 && ret == 0) + ret = t_ret; + + /* Keep any not-found page locked for serializability. */ + if ((t_ret = __TLPUT(dbc, lock)) != 0 && ret == 0) + ret = t_ret; + + (void)__LPUT(dbc, saved_lock); + + BT_STK_POP(cp); + (void)__bam_stkrel(dbc, 0); + + if (F_ISSET(dbc, DBC_OPD)) + LOCK_CHECK_ON(dbc->thread_info); + + return (ret); +} + +/* + * __bam_stkrel -- + * Release all pages currently held in the stack. + * + * PUBLIC: int __bam_stkrel __P((DBC *, u_int32_t)); + */ +int +__bam_stkrel(dbc, flags) + DBC *dbc; + u_int32_t flags; +{ + BTREE_CURSOR *cp; + DB *dbp; + DB_MPOOLFILE *mpf; + EPG *epg; + int ret, t_ret; + + DB_ASSERT(NULL, dbc != NULL); + dbp = dbc->dbp; + mpf = dbp->mpf; + cp = (BTREE_CURSOR *)dbc->internal; + + /* + * Release inner pages first. + * + * The caller must be sure that setting STK_NOLOCK will not effect + * either serializability or recoverability. + */ + for (ret = 0, epg = cp->sp; epg <= cp->csp; ++epg) { + if (epg->page != NULL) { + if (LF_ISSET(STK_CLRDBC) && cp->page == epg->page) { + cp->page = NULL; + LOCK_INIT(cp->lock); + } + if ((t_ret = __memp_fput(mpf, dbc->thread_info, + epg->page, dbc->priority)) != 0 && ret == 0) + ret = t_ret; + epg->page = NULL; + } + /* + * We set this if we need to release our pins, + * but are not logically ready to have the pages + * visible. + */ + if (LF_ISSET(STK_PGONLY)) + continue; + if (LF_ISSET(STK_NOLOCK) && + (epg->lock.mode == DB_LOCK_READ || + atomic_read(&mpf->mfp->multiversion) == 0)) { + if ((t_ret = __LPUT(dbc, epg->lock)) != 0 && ret == 0) + ret = t_ret; + } else + if ((t_ret = __TLPUT(dbc, epg->lock)) != 0 && ret == 0) + ret = t_ret; + } + + /* Clear the stack, all pages have been released. */ + if (!LF_ISSET(STK_PGONLY)) + BT_STK_CLR(cp); + + return (ret); +} + +/* + * __bam_stkgrow -- + * Grow the stack. + * + * PUBLIC: int __bam_stkgrow __P((ENV *, BTREE_CURSOR *)); + */ +int +__bam_stkgrow(env, cp) + ENV *env; + BTREE_CURSOR *cp; +{ + EPG *p; + size_t entries; + int ret; + + entries = cp->esp - cp->sp; + + if ((ret = __os_calloc(env, entries * 2, sizeof(EPG), &p)) != 0) + return (ret); + memcpy(p, cp->sp, entries * sizeof(EPG)); + if (cp->sp != cp->stack) + __os_free(env, cp->sp); + cp->sp = p; + cp->csp = p + entries; + cp->esp = p + entries * 2; + return (0); +} diff -r 000000000000 -r a1985f14b030 src/btree/bt_split.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/btree/bt_split.c Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,1354 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 1996, 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +/* + * Copyright (c) 1990, 1993, 1994, 1995, 1996 + * Keith Bostic. All rights reserved. + */ +/* + * Copyright (c) 1990, 1993, 1994, 1995 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $Id$ + */ + +#include "db_config.h" + +#include "db_int.h" +#include "dbinc/db_page.h" +#include "dbinc/lock.h" +#include "dbinc/mp.h" +#include "dbinc/btree.h" + +static int __bam_page __P((DBC *, EPG *, EPG *)); +static int __bam_psplit __P((DBC *, EPG *, PAGE *, PAGE *, db_indx_t *)); +static int __bam_root __P((DBC *, EPG *)); + +/* + * __bam_split -- + * Split a page. + * + * PUBLIC: int __bam_split __P((DBC *, void *, db_pgno_t *)); + */ +int +__bam_split(dbc, arg, root_pgnop) + DBC *dbc; + void *arg; + db_pgno_t *root_pgnop; +{ + BTREE_CURSOR *cp; + DB_LOCK metalock, next_lock; + enum { UP, DOWN } dir; + db_pgno_t pgno, next_pgno, root_pgno; + int exact, level, ret; + + if (F_ISSET(dbc, DBC_OPD)) + LOCK_CHECK_OFF(dbc->thread_info); + + cp = (BTREE_CURSOR *)dbc->internal; + LOCK_INIT(next_lock); + next_pgno = PGNO_INVALID; + + /* + * First get a lock on the metadata page, we will have to allocate + * pages and cannot get a lock while we have the search tree pinned. + */ + + pgno = PGNO_BASE_MD; + if ((ret = __db_lget(dbc, + 0, pgno, DB_LOCK_WRITE, 0, &metalock)) != 0) + goto err; + root_pgno = BAM_ROOT_PGNO(dbc); + + /* + * The locking protocol we use to avoid deadlock to acquire locks by + * walking down the tree, but we do it as lazily as possible, locking + * the root only as a last resort. We expect all stack pages to have + * been discarded before we're called; we discard all short-term locks. + * + * When __bam_split is first called, we know that a leaf page was too + * full for an insert. We don't know what leaf page it was, but we + * have the key/recno that caused the problem. We call XX_search to + * reacquire the leaf page, but this time get both the leaf page and + * its parent, locked. We then split the leaf page and see if the new + * internal key will fit into the parent page. If it will, we're done. + * + * If it won't, we discard our current locks and repeat the process, + * only this time acquiring the parent page and its parent, locked. + * This process repeats until we succeed in the split, splitting the + * root page as the final resort. The entire process then repeats, + * as necessary, until we split a leaf page. + * + * XXX + * A traditional method of speeding this up is to maintain a stack of + * the pages traversed in the original search. You can detect if the + * stack is correct by storing the page's LSN when it was searched and + * comparing that LSN with the current one when it's locked during the + * split. This would be an easy change for this code, but I have no + * numbers that indicate it's worthwhile. + */ + for (dir = UP, level = LEAFLEVEL;; dir == UP ? ++level : --level) { + /* + * Acquire a page and its parent, locked. + */ +retry: if ((ret = (dbc->dbtype == DB_BTREE ? + __bam_search(dbc, PGNO_INVALID, + arg, SR_WRPAIR, level, NULL, &exact) : + __bam_rsearch(dbc, + (db_recno_t *)arg, SR_WRPAIR, level, &exact))) != 0) + break; + + if (cp->csp[0].page->pgno == root_pgno) { + /* we can overshoot the top of the tree. */ + level = cp->csp[0].page->level; + if (root_pgnop != NULL) + *root_pgnop = root_pgno; + } else if (root_pgnop != NULL) + *root_pgnop = cp->csp[-1].page->pgno; + + /* + * Split the page if it still needs it (it's possible another + * thread of control has already split the page). If we are + * guaranteed that two items will fit on the page, the split + * is no longer necessary. + */ + if (2 * B_MAXSIZEONPAGE(cp->ovflsize) + <= (db_indx_t)P_FREESPACE(dbc->dbp, cp->csp[0].page)) { + if ((ret = __bam_stkrel(dbc, STK_NOLOCK)) != 0) + goto err; + goto no_split; + } + + /* + * We need to try to lock the next page so we can update + * its PREV. + */ + if (ISLEAF(cp->csp->page) && + (pgno = NEXT_PGNO(cp->csp->page)) != PGNO_INVALID) { + TRY_LOCK(dbc, pgno, + next_pgno, next_lock, DB_LOCK_WRITE, retry); + if (ret != 0) + goto err; + } + ret = cp->csp[0].page->pgno == root_pgno ? + __bam_root(dbc, &cp->csp[0]) : + __bam_page(dbc, &cp->csp[-1], &cp->csp[0]); + BT_STK_CLR(cp); + + switch (ret) { + case 0: +no_split: /* Once we've split the leaf page, we're done. */ + if (level == LEAFLEVEL) + goto done; + + /* Switch directions. */ + if (dir == UP) + dir = DOWN; + break; + case DB_NEEDSPLIT: + /* + * It's possible to fail to split repeatedly, as other + * threads may be modifying the tree, or the page usage + * is sufficiently bad that we don't get enough space + * the first time. + */ + if (dir == DOWN) + dir = UP; + break; + default: + goto err; + } + } + + if (root_pgnop != NULL) + *root_pgnop = BAM_ROOT_PGNO(dbc); +err: +done: (void)__LPUT(dbc, metalock); + (void)__TLPUT(dbc, next_lock); + + if (F_ISSET(dbc, DBC_OPD)) + LOCK_CHECK_ON(dbc->thread_info); + return (ret); +} + +/* + * __bam_root -- + * Split the root page of a btree. + */ +static int +__bam_root(dbc, cp) + DBC *dbc; + EPG *cp; +{ + DB *dbp; + DBT log_dbt, rootent[2]; + DB_LOCK llock, rlock; + DB_LSN log_lsn; + DB_MPOOLFILE *mpf; + PAGE *lp, *rp; + db_indx_t split; + u_int32_t opflags; + int ret, t_ret; + + dbp = dbc->dbp; + mpf = dbp->mpf; + lp = rp = NULL; + LOCK_INIT(llock); + LOCK_INIT(rlock); + COMPQUIET(log_dbt.data, NULL); + + /* Yeah, right. */ + if (cp->page->level >= MAXBTREELEVEL) { + __db_errx(dbp->env, DB_STR_A("1021", + "Too many btree levels: %d", "%d"), cp->page->level); + return (ENOSPC); + } + + if ((ret = __memp_dirty(mpf, + &cp->page, dbc->thread_info, dbc->txn, dbc->priority, 0)) != 0) + goto err; + + /* Create new left and right pages for the split. */ + if ((ret = __db_new(dbc, TYPE(cp->page), &llock, &lp)) != 0 || + (ret = __db_new(dbc, TYPE(cp->page), &rlock, &rp)) != 0) + goto err; + P_INIT(lp, dbp->pgsize, lp->pgno, + PGNO_INVALID, ISINTERNAL(cp->page) ? PGNO_INVALID : rp->pgno, + cp->page->level, TYPE(cp->page)); + P_INIT(rp, dbp->pgsize, rp->pgno, + ISINTERNAL(cp->page) ? PGNO_INVALID : lp->pgno, PGNO_INVALID, + cp->page->level, TYPE(cp->page)); + + PERFMON5(env, alloc, btree_split, + dbp->fname, dbp->dname, lp->pgno, cp->page->pgno, lp->level); + + /* Split the page. */ + if ((ret = __bam_psplit(dbc, cp, lp, rp, &split)) != 0) + goto err; + + if (DBC_LOGGING(dbc)) { + memset(&log_dbt, 0, sizeof(log_dbt)); + if ((ret = + __os_malloc(dbp->env, dbp->pgsize, &log_dbt.data)) != 0) + goto err; + log_dbt.size = dbp->pgsize; + memcpy(log_dbt.data, cp->page, dbp->pgsize); + } + + /* Clean up the new root page. */ + if ((ret = (dbc->dbtype == DB_RECNO ? + __ram_root(dbc, cp->page, lp, rp) : + __bam_broot(dbc, cp->page, split, lp, rp))) != 0) { + if (DBC_LOGGING(dbc)) + __os_free(dbp->env, log_dbt.data); + goto err; + } + + /* Log the change. */ + if (DBC_LOGGING(dbc)) { + memset(rootent, 0, sizeof(rootent)); + rootent[0].data = GET_BINTERNAL(dbp, cp->page, 0); + rootent[1].data = GET_BINTERNAL(dbp, cp->page, 1); + if (dbc->dbtype == DB_RECNO) + rootent[0].size = rootent[1].size = RINTERNAL_SIZE; + else { + rootent[0].size = BINTERNAL_SIZE( + ((BINTERNAL *)rootent[0].data)->len); + rootent[1].size = BINTERNAL_SIZE( + ((BINTERNAL *)rootent[1].data)->len); + } + ZERO_LSN(log_lsn); + opflags = F_ISSET( + (BTREE_CURSOR *)dbc->internal, C_RECNUM) ? SPL_NRECS : 0; + if (dbc->dbtype == DB_RECNO) + opflags |= SPL_RECNO; + ret = __bam_split_log(dbp, dbc->txn, &LSN(cp->page), 0, + OP_SET(opflags, cp->page), PGNO(lp), &LSN(lp), + PGNO(rp), &LSN(rp), (u_int32_t)NUM_ENT(lp), + PGNO_INVALID, &log_lsn, PGNO(cp->page), + &LSN(cp->page), 0, &log_dbt, &rootent[0], &rootent[1]); + + /* On failure, restore the page. */ + if (ret != 0) + memcpy(cp->page, log_dbt.data, dbp->pgsize); + __os_free(dbp->env, log_dbt.data); + + if (ret != 0) + goto err; + } else + LSN_NOT_LOGGED(LSN(cp->page)); + LSN(lp) = LSN(cp->page); + LSN(rp) = LSN(cp->page); + + /* Adjust any cursors. */ + ret = __bam_ca_split(dbc, cp->page->pgno, lp->pgno, rp->pgno, split, 1); + + /* Success or error: release pages and locks. */ +err: if (cp->page != NULL && (t_ret = __memp_fput(mpf, + dbc->thread_info, cp->page, dbc->priority)) != 0 && ret == 0) + ret = t_ret; + cp->page = NULL; + + /* + * We are done. Put or downgrade all our locks and release + * the pages. + */ + if ((t_ret = __TLPUT(dbc, llock)) != 0 && ret == 0) + ret = t_ret; + if ((t_ret = __TLPUT(dbc, rlock)) != 0 && ret == 0) + ret = t_ret; + if ((t_ret = __TLPUT(dbc, cp->lock)) != 0 && ret == 0) + ret = t_ret; + if (lp != NULL && (t_ret = __memp_fput(mpf, + dbc->thread_info, lp, dbc->priority)) != 0 && ret == 0) + ret = t_ret; + if (rp != NULL && (t_ret = __memp_fput(mpf, + dbc->thread_info, rp, dbc->priority)) != 0 && ret == 0) + ret = t_ret; + + return (ret); +} + +/* + * __bam_page -- + * Split the non-root page of a btree. + */ +static int +__bam_page(dbc, pp, cp) + DBC *dbc; + EPG *pp, *cp; +{ + BTREE_CURSOR *bc; + DB *dbp; + DBT log_dbt, rentry; + DB_LOCK rplock; + DB_LSN log_lsn; + DB_LSN save_lsn; + DB_MPOOLFILE *mpf; + PAGE *lp, *rp, *alloc_rp, *tp; + db_indx_t split; + u_int32_t opflags; + int ret, t_ret; + + dbp = dbc->dbp; + mpf = dbp->mpf; + alloc_rp = lp = rp = tp = NULL; + LOCK_INIT(rplock); + ret = -1; + + /* + * Create new left page for the split, and fill in everything + * except its LSN and next-page page number. + * + * Create a new right page for the split, and fill in everything + * except its LSN and page number. + * + * We malloc space for both the left and right pages, so we don't get + * a new page from the underlying buffer pool until we know the split + * is going to succeed. The reason is that we can't release locks + * acquired during the get-a-new-page process because metadata page + * locks can't be discarded on failure since we may have modified the + * free list. So, if you assume that we're holding a write lock on the + * leaf page which ran out of space and started this split (e.g., we + * have already written records to the page, or we retrieved a record + * from it with the DB_RMW flag set), failing in a split with both a + * leaf page locked and the metadata page locked can potentially lock + * up the tree badly, because we've violated the rule of always locking + * down the tree, and never up. + */ + if ((ret = __os_malloc(dbp->env, dbp->pgsize * 2, &lp)) != 0) + goto err; + P_INIT(lp, dbp->pgsize, PGNO(cp->page), + ISINTERNAL(cp->page) ? PGNO_INVALID : PREV_PGNO(cp->page), + ISINTERNAL(cp->page) ? PGNO_INVALID : 0, + cp->page->level, TYPE(cp->page)); + + rp = (PAGE *)((u_int8_t *)lp + dbp->pgsize); + P_INIT(rp, dbp->pgsize, 0, + ISINTERNAL(cp->page) ? PGNO_INVALID : PGNO(cp->page), + ISINTERNAL(cp->page) ? PGNO_INVALID : NEXT_PGNO(cp->page), + cp->page->level, TYPE(cp->page)); + + /* + * Split right. + * + * Only the indices are sorted on the page, i.e., the key/data pairs + * aren't, so it's simpler to copy the data from the split page onto + * two new pages instead of copying half the data to a new right page + * and compacting the left page in place. Since the left page can't + * change, we swap the original and the allocated left page after the + * split. + */ + if ((ret = __bam_psplit(dbc, cp, lp, rp, &split)) != 0) + goto err; + + /* + * Test to see if we are going to be able to insert the new pages into + * the parent page. The interesting failure here is that the parent + * page can't hold the new keys, and has to be split in turn, in which + * case we want to release all the locks we can. + */ + if ((ret = __bam_pinsert(dbc, pp, split, lp, rp, BPI_SPACEONLY)) != 0) + goto err; + + /* + * We've got everything locked down we need, and we know the split + * is going to succeed. Go and get the additional page we'll need. + */ + if ((ret = __db_new(dbc, TYPE(cp->page), &rplock, &alloc_rp)) != 0) + goto err; + + /* + * Prepare to fix up the previous pointer of any leaf page following + * the split page. Our caller has already write locked the page so + * we can get it without deadlocking on the parent latch. + */ + if (ISLEAF(cp->page) && NEXT_PGNO(cp->page) != PGNO_INVALID && + (ret = __memp_fget(mpf, &NEXT_PGNO(cp->page), + dbc->thread_info, dbc->txn, DB_MPOOL_DIRTY, &tp)) != 0) + goto err; + + PERFMON5(env, alloc, btree_split, dbp->fname, + dbp->dname, cp->page->pgno, pp->page->pgno, cp->page->level); + + /* + * Fix up the page numbers we didn't have before. We have to do this + * before calling __bam_pinsert because it may copy a page number onto + * the parent page and it takes the page number from its page argument. + */ + PGNO(rp) = NEXT_PGNO(lp) = PGNO(alloc_rp); + + DB_ASSERT(dbp->env, IS_DIRTY(cp->page)); + DB_ASSERT(dbp->env, IS_DIRTY(pp->page)); + + bc = (BTREE_CURSOR *)dbc->internal; + + /* Actually update the parent page. */ + if ((ret = __bam_pinsert(dbc, + pp, split, lp, rp, F_ISSET(bc, C_RECNUM) ? 0 : BPI_NOLOGGING)) != 0) + goto err; + + /* Log the change. */ + if (DBC_LOGGING(dbc)) { + memset(&log_dbt, 0, sizeof(log_dbt)); + log_dbt.data = cp->page; + log_dbt.size = dbp->pgsize; + memset(&rentry, 0, sizeof(rentry)); + rentry.data = GET_BINTERNAL(dbp, pp->page, pp->indx + 1); + opflags = F_ISSET(bc, C_RECNUM) ? SPL_NRECS : 0; + if (dbc->dbtype == DB_RECNO) { + opflags |= SPL_RECNO; + rentry.size = RINTERNAL_SIZE; + } else + rentry.size = + BINTERNAL_SIZE(((BINTERNAL *)rentry.data)->len); + if (tp == NULL) + ZERO_LSN(log_lsn); + if ((ret = __bam_split_log(dbp, dbc->txn, &LSN(cp->page), + 0, OP_SET(opflags, pp->page), PGNO(cp->page), + &LSN(cp->page), PGNO(alloc_rp), &LSN(alloc_rp), + (u_int32_t)NUM_ENT(lp), tp == NULL ? 0 : PGNO(tp), + tp == NULL ? &log_lsn : &LSN(tp), PGNO(pp->page), + &LSN(pp->page), pp->indx, &log_dbt, NULL, &rentry)) != 0) { + /* + * If this is not RECNO then undo the update + * to the parent page, which has not been + * logged yet. This must succeed. Renco + * database trees are locked and therefore + * the parent can be logged independently. + */ + if (F_ISSET(bc, C_RECNUM) == 0) { + t_ret = __db_ditem_nolog(dbc, pp->page, + pp->indx + 1, rentry.size); + DB_ASSERT(dbp->env, t_ret == 0); + } + + goto err; + } + + } else + LSN_NOT_LOGGED(LSN(cp->page)); + + /* Update the LSNs for all involved pages. */ + LSN(alloc_rp) = LSN(cp->page); + LSN(lp) = LSN(cp->page); + LSN(rp) = LSN(cp->page); + LSN(pp->page) = LSN(cp->page); + if (tp != NULL) { + /* Log record has been written; so safe to update next page. */ + PREV_PGNO(tp) = PGNO(rp); + LSN(tp) = LSN(cp->page); + } + + /* + * Copy the left and right pages into place. There are two paths + * through here. Either we are logging and we set the LSNs in the + * logging path. However, if we are not logging, then we do not + * have valid LSNs on lp or rp. The correct LSNs to use are the + * ones on the page we got from __db_new or the one that was + * originally on cp->page. In both cases, we save the LSN from the + * real database page (not a malloc'd one) and reapply it after we + * do the copy. + */ + save_lsn = alloc_rp->lsn; + memcpy(alloc_rp, rp, LOFFSET(dbp, rp)); + memcpy((u_int8_t *)alloc_rp + HOFFSET(rp), + (u_int8_t *)rp + HOFFSET(rp), dbp->pgsize - HOFFSET(rp)); + alloc_rp->lsn = save_lsn; + + save_lsn = cp->page->lsn; + memcpy(cp->page, lp, LOFFSET(dbp, lp)); + memcpy((u_int8_t *)cp->page + HOFFSET(lp), + (u_int8_t *)lp + HOFFSET(lp), dbp->pgsize - HOFFSET(lp)); + cp->page->lsn = save_lsn; + + /* Adjust any cursors. */ + if ((ret = __bam_ca_split(dbc, + PGNO(cp->page), PGNO(cp->page), PGNO(rp), split, 0)) != 0) + goto err; + + __os_free(dbp->env, lp); + + /* + * Success -- write the real pages back to the store. + */ + if ((t_ret = __memp_fput(mpf, + dbc->thread_info, alloc_rp, dbc->priority)) != 0 && ret == 0) + ret = t_ret; + if ((t_ret = __TLPUT(dbc, rplock)) != 0 && ret == 0) + ret = t_ret; + if (tp != NULL) { + if ((t_ret = __memp_fput(mpf, + dbc->thread_info, tp, dbc->priority)) != 0 && ret == 0) + ret = t_ret; + } + if ((t_ret = __bam_stkrel(dbc, STK_CLRDBC)) != 0 && ret == 0) + ret = t_ret; + return (ret); + +err: if (lp != NULL) + __os_free(dbp->env, lp); + if (alloc_rp != NULL) + (void)__memp_fput(mpf, + dbc->thread_info, alloc_rp, dbc->priority); + if (tp != NULL) + (void)__memp_fput(mpf, dbc->thread_info, tp, dbc->priority); + + if (pp->page != NULL) + (void)__memp_fput(mpf, + dbc->thread_info, pp->page, dbc->priority); + + if (ret == DB_NEEDSPLIT && atomic_read(&mpf->mfp->multiversion) == 0) + (void)__LPUT(dbc, pp->lock); + else + (void)__TLPUT(dbc, pp->lock); + + (void)__memp_fput(mpf, dbc->thread_info, cp->page, dbc->priority); + + /* + * We don't drop the left and right page locks. If we doing dirty + * reads then we need to hold the locks until we abort the transaction. + * If we are not transactional, we are hosed anyway as the tree + * is trashed. It may be better not to leak the locks. + */ + + if (dbc->txn == NULL) + (void)__LPUT(dbc, rplock); + + if (dbc->txn == NULL || ret == DB_NEEDSPLIT) + (void)__LPUT(dbc, cp->lock); + + return (ret); +} + +/* + * __bam_broot -- + * Fix up the btree root page after it has been split. + * PUBLIC: int __bam_broot __P((DBC *, PAGE *, u_int32_t, PAGE *, PAGE *)); + */ +int +__bam_broot(dbc, rootp, split, lp, rp) + DBC *dbc; + u_int32_t split; + PAGE *rootp, *lp, *rp; +{ + BINTERNAL bi, bi0, *child_bi; + BKEYDATA *child_bk; + BOVERFLOW bo, *child_bo; + BTREE_CURSOR *cp; + DB *dbp; + DBT hdr, hdr0, data; + db_pgno_t root_pgno; + int ret; + + dbp = dbc->dbp; + cp = (BTREE_CURSOR *)dbc->internal; + child_bo = NULL; + data.data = NULL; + memset(&bi, 0, sizeof(bi)); + + switch (TYPE(rootp)) { + case P_IBTREE: + /* Copy the first key of the child page onto the root page. */ + child_bi = GET_BINTERNAL(dbp, rootp, split); + switch (B_TYPE(child_bi->type)) { + case B_KEYDATA: + bi.len = child_bi->len; + B_TSET(bi.type, B_KEYDATA); + bi.pgno = rp->pgno; + DB_SET_DBT(hdr, &bi, SSZA(BINTERNAL, data)); + if ((ret = __os_malloc(dbp->env, + child_bi->len, &data.data)) != 0) + return (ret); + memcpy(data.data, child_bi->data, child_bi->len); + data.size = child_bi->len; + break; + case B_OVERFLOW: + /* Reuse the overflow key. */ + child_bo = (BOVERFLOW *)child_bi->data; + memset(&bo, 0, sizeof(bo)); + bo.type = B_OVERFLOW; + bo.tlen = child_bo->tlen; + bo.pgno = child_bo->pgno; + bi.len = BOVERFLOW_SIZE; + B_TSET(bi.type, B_OVERFLOW); + bi.pgno = rp->pgno; + DB_SET_DBT(hdr, &bi, SSZA(BINTERNAL, data)); + DB_SET_DBT(data, &bo, BOVERFLOW_SIZE); + break; + case B_DUPLICATE: + default: + goto pgfmt; + } + break; + case P_LDUP: + case P_LBTREE: + /* Copy the first key of the child page onto the root page. */ + child_bk = GET_BKEYDATA(dbp, rootp, split); + switch (B_TYPE(child_bk->type)) { + case B_KEYDATA: + bi.len = child_bk->len; + B_TSET(bi.type, B_KEYDATA); + bi.pgno = rp->pgno; + DB_SET_DBT(hdr, &bi, SSZA(BINTERNAL, data)); + if ((ret = __os_malloc(dbp->env, + child_bk->len, &data.data)) != 0) + return (ret); + memcpy(data.data, child_bk->data, child_bk->len); + data.size = child_bk->len; + break; + case B_OVERFLOW: + /* Copy the overflow key. */ + child_bo = (BOVERFLOW *)child_bk; + memset(&bo, 0, sizeof(bo)); + bo.type = B_OVERFLOW; + bo.tlen = child_bo->tlen; + memset(&hdr, 0, sizeof(hdr)); + if ((ret = __db_goff(dbc, &hdr, child_bo->tlen, + child_bo->pgno, &hdr.data, &hdr.size)) == 0) + ret = __db_poff(dbc, &hdr, &bo.pgno); + + if (hdr.data != NULL) + __os_free(dbp->env, hdr.data); + if (ret != 0) + return (ret); + + bi.len = BOVERFLOW_SIZE; + B_TSET(bi.type, B_OVERFLOW); + bi.pgno = rp->pgno; + DB_SET_DBT(hdr, &bi, SSZA(BINTERNAL, data)); + DB_SET_DBT(data, &bo, BOVERFLOW_SIZE); + break; + case B_DUPLICATE: + default: + goto pgfmt; + } + break; + default: +pgfmt: return (__db_pgfmt(dbp->env, rp->pgno)); + } + /* + * If the root page was a leaf page, change it into an internal page. + * We copy the key we split on (but not the key's data, in the case of + * a leaf page) to the new root page. + */ + root_pgno = BAM_ROOT_PGNO(dbc); + P_INIT(rootp, dbp->pgsize, + root_pgno, PGNO_INVALID, PGNO_INVALID, lp->level + 1, P_IBTREE); + + /* + * The btree comparison code guarantees that the left-most key on any + * internal btree page is never used, so it doesn't need to be filled + * in. Set the record count if necessary. + */ + memset(&bi0, 0, sizeof(bi0)); + B_TSET(bi0.type, B_KEYDATA); + bi0.pgno = lp->pgno; + if (F_ISSET(cp, C_RECNUM)) { + bi0.nrecs = __bam_total(dbp, lp); + RE_NREC_SET(rootp, bi0.nrecs); + bi.nrecs = __bam_total(dbp, rp); + RE_NREC_ADJ(rootp, bi.nrecs); + } + DB_SET_DBT(hdr0, &bi0, SSZA(BINTERNAL, data)); + if ((ret = __db_pitem_nolog(dbc, rootp, + 0, BINTERNAL_SIZE(0), &hdr0, NULL)) != 0) + goto err; + ret = __db_pitem_nolog(dbc, rootp, 1, + BINTERNAL_SIZE(data.size), &hdr, &data); + +err: if (data.data != NULL && child_bo == NULL) + __os_free(dbp->env, data.data); + return (ret); +} + +/* + * __ram_root -- + * Fix up the recno root page after it has been split. + * PUBLIC: int __ram_root __P((DBC *, PAGE *, PAGE *, PAGE *)); + */ +int +__ram_root(dbc, rootp, lp, rp) + DBC *dbc; + PAGE *rootp, *lp, *rp; +{ + DB *dbp; + DBT hdr; + RINTERNAL ri; + db_pgno_t root_pgno; + int ret; + + dbp = dbc->dbp; + root_pgno = BAM_ROOT_PGNO(dbc); + + /* Initialize the page. */ + P_INIT(rootp, dbp->pgsize, + root_pgno, PGNO_INVALID, PGNO_INVALID, lp->level + 1, P_IRECNO); + + /* Initialize the header. */ + DB_SET_DBT(hdr, &ri, RINTERNAL_SIZE); + + /* Insert the left and right keys, set the header information. */ + ri.pgno = lp->pgno; + ri.nrecs = __bam_total(dbp, lp); + if ((ret = __db_pitem_nolog(dbc, + rootp, 0, RINTERNAL_SIZE, &hdr, NULL)) != 0) + return (ret); + RE_NREC_SET(rootp, ri.nrecs); + ri.pgno = rp->pgno; + ri.nrecs = __bam_total(dbp, rp); + if ((ret = __db_pitem_nolog(dbc, + rootp, 1, RINTERNAL_SIZE, &hdr, NULL)) != 0) + return (ret); + RE_NREC_ADJ(rootp, ri.nrecs); + return (0); +} + +/* + * __bam_pinsert -- + * Insert a new key into a parent page, completing the split. + * + * PUBLIC: int __bam_pinsert + * PUBLIC: __P((DBC *, EPG *, u_int32_t, PAGE *, PAGE *, int)); + */ +int +__bam_pinsert(dbc, parent, split, lchild, rchild, flags) + DBC *dbc; + EPG *parent; + u_int32_t split; + PAGE *lchild, *rchild; + int flags; +{ + BINTERNAL bi, *child_bi; + BKEYDATA *child_bk, *tmp_bk; + BOVERFLOW bo, *child_bo; + BTREE *t; + BTREE_CURSOR *cp; + DB *dbp; + DBT a, b, hdr, data; + EPG *child; + PAGE *ppage; + RINTERNAL ri; + db_indx_t off; + db_recno_t nrecs; + size_t (*func) __P((DB *, const DBT *, const DBT *)); + int (*pitem) __P((DBC *, PAGE *, u_int32_t, u_int32_t, DBT *, DBT *)); + u_int32_t n, nbytes, nksize, oldsize, size; + int ret; + + dbp = dbc->dbp; + cp = (BTREE_CURSOR *)dbc->internal; + t = dbp->bt_internal; + ppage = parent->page; + child = parent + 1; + + /* If handling record numbers, count records split to the right page. */ + nrecs = F_ISSET(cp, C_RECNUM) && + !LF_ISSET(BPI_SPACEONLY) ? __bam_total(dbp, rchild) : 0; + + /* + * Now we insert the new page's first key into the parent page, which + * completes the split. The parent points to a PAGE and a page index + * offset, where the new key goes ONE AFTER the index, because we split + * to the right. + * + * XXX + * Some btree algorithms replace the key for the old page as well as + * the new page. We don't, as there's no reason to believe that the + * first key on the old page is any better than the key we have, and, + * in the case of a key being placed at index 0 causing the split, the + * key is unavailable. + */ + off = parent->indx + O_INDX; + if (LF_ISSET(BPI_REPLACE)) + oldsize = TYPE(ppage) == P_IRECNO ? RINTERNAL_PSIZE : + BINTERNAL_PSIZE(GET_BINTERNAL(dbp, ppage, off)->len); + else + oldsize = 0; + + /* + * Calculate the space needed on the parent page. + * + * Prefix trees: space hack used when inserting into BINTERNAL pages. + * Retain only what's needed to distinguish between the new entry and + * the LAST entry on the page to its left. If the keys compare equal, + * retain the entire key. We ignore overflow keys, and the entire key + * must be retained for the next-to-leftmost key on the leftmost page + * of each level, or the search will fail. Applicable ONLY to internal + * pages that have leaf pages as children. Further reduction of the + * key between pairs of internal pages loses too much information. + */ + switch (TYPE(child->page)) { + case P_IBTREE: + child_bi = GET_BINTERNAL(dbp, child->page, split); + nbytes = BINTERNAL_PSIZE(child_bi->len); + + if (P_FREESPACE(dbp, ppage) + oldsize < nbytes) + return (DB_NEEDSPLIT); + if (LF_ISSET(BPI_SPACEONLY)) + return (0); + + switch (B_TYPE(child_bi->type)) { + case B_KEYDATA: + /* Add a new record for the right page. */ + memset(&bi, 0, sizeof(bi)); + bi.len = child_bi->len; + B_TSET(bi.type, B_KEYDATA); + bi.pgno = rchild->pgno; + bi.nrecs = nrecs; + DB_SET_DBT(hdr, &bi, SSZA(BINTERNAL, data)); + DB_SET_DBT(data, child_bi->data, child_bi->len); + size = BINTERNAL_SIZE(child_bi->len); + break; + case B_OVERFLOW: + /* Reuse the overflow key. */ + child_bo = (BOVERFLOW *)child_bi->data; + memset(&bo, 0, sizeof(bo)); + bo.type = B_OVERFLOW; + bo.tlen = child_bo->tlen; + bo.pgno = child_bo->pgno; + bi.len = BOVERFLOW_SIZE; + B_TSET(bi.type, B_OVERFLOW); + bi.pgno = rchild->pgno; + bi.nrecs = nrecs; + DB_SET_DBT(hdr, &bi, SSZA(BINTERNAL, data)); + DB_SET_DBT(data, &bo, BOVERFLOW_SIZE); + size = BINTERNAL_SIZE(BOVERFLOW_SIZE); + break; + case B_DUPLICATE: + default: + goto pgfmt; + } + break; + case P_LDUP: + case P_LBTREE: + child_bk = GET_BKEYDATA(dbp, child->page, split); + switch (B_TYPE(child_bk->type)) { + case B_KEYDATA: + nbytes = BINTERNAL_PSIZE(child_bk->len); + nksize = child_bk->len; + + /* + * Prefix compression: + * We set t->bt_prefix to NULL if we have a comparison + * callback but no prefix compression callback. But, + * if we're splitting in an off-page duplicates tree, + * we still have to do some checking. If using the + * default off-page duplicates comparison routine we + * can use the default prefix compression callback. If + * not using the default off-page duplicates comparison + * routine, we can't do any kind of prefix compression + * as there's no way for an application to specify a + * prefix compression callback that corresponds to its + * comparison callback. + * + * No prefix compression if we don't have a compression + * function, or the key we'd compress isn't a normal + * key (for example, it references an overflow page). + * + * Generate a parent page key for the right child page + * from a comparison of the last key on the left child + * page and the first key on the right child page. + */ + if (F_ISSET(dbc, DBC_OPD)) { + if (dbp->dup_compare == __bam_defcmp) + func = __bam_defpfx; + else + func = NULL; + } else + func = t->bt_prefix; + if (func == NULL) + goto noprefix; + tmp_bk = GET_BKEYDATA(dbp, lchild, NUM_ENT(lchild) - + (TYPE(lchild) == P_LDUP ? O_INDX : P_INDX)); + if (B_TYPE(tmp_bk->type) != B_KEYDATA) + goto noprefix; + DB_INIT_DBT(a, tmp_bk->data, tmp_bk->len); + DB_INIT_DBT(b, child_bk->data, child_bk->len); + nksize = (u_int32_t)func(dbp, &a, &b); + if ((n = BINTERNAL_PSIZE(nksize)) < nbytes) + nbytes = n; + else + nksize = child_bk->len; + +noprefix: if (P_FREESPACE(dbp, ppage) + oldsize < nbytes) + return (DB_NEEDSPLIT); + if (LF_ISSET(BPI_SPACEONLY)) + return (0); + + memset(&bi, 0, sizeof(bi)); + bi.len = nksize; + B_TSET(bi.type, B_KEYDATA); + bi.pgno = rchild->pgno; + bi.nrecs = nrecs; + DB_SET_DBT(hdr, &bi, SSZA(BINTERNAL, data)); + DB_SET_DBT(data, child_bk->data, nksize); + size = BINTERNAL_SIZE(nksize); + break; + case B_OVERFLOW: + nbytes = BINTERNAL_PSIZE(BOVERFLOW_SIZE); + + if (P_FREESPACE(dbp, ppage) + oldsize < nbytes) + return (DB_NEEDSPLIT); + if (LF_ISSET(BPI_SPACEONLY)) + return (0); + + /* Copy the overflow key. */ + child_bo = (BOVERFLOW *)child_bk; + memset(&bo, 0, sizeof(bo)); + bo.type = B_OVERFLOW; + bo.tlen = child_bo->tlen; + memset(&hdr, 0, sizeof(hdr)); + if ((ret = __db_goff(dbc, &hdr, child_bo->tlen, + child_bo->pgno, &hdr.data, &hdr.size)) == 0) + ret = __db_poff(dbc, &hdr, &bo.pgno); + + if (hdr.data != NULL) + __os_free(dbp->env, hdr.data); + if (ret != 0) + return (ret); + + memset(&bi, 0, sizeof(bi)); + bi.len = BOVERFLOW_SIZE; + B_TSET(bi.type, B_OVERFLOW); + bi.pgno = rchild->pgno; + bi.nrecs = nrecs; + DB_SET_DBT(hdr, &bi, SSZA(BINTERNAL, data)); + DB_SET_DBT(data, &bo, BOVERFLOW_SIZE); + size = BINTERNAL_SIZE(BOVERFLOW_SIZE); + + break; + case B_DUPLICATE: + default: + goto pgfmt; + } + break; + case P_IRECNO: + case P_LRECNO: + nbytes = RINTERNAL_PSIZE; + + if (P_FREESPACE(dbp, ppage) + oldsize < nbytes) + return (DB_NEEDSPLIT); + if (LF_ISSET(BPI_SPACEONLY)) + return (0); + + /* Add a new record for the right page. */ + DB_SET_DBT(hdr, &ri, RINTERNAL_SIZE); + ri.pgno = rchild->pgno; + ri.nrecs = nrecs; + size = RINTERNAL_SIZE; + data.size = 0; + /* + * For now, we are locking internal recno nodes so + * use two steps. + */ + if (LF_ISSET(BPI_REPLACE)) { + if ((ret = __bam_ditem(dbc, ppage, off)) != 0) + return (ret); + LF_CLR(BPI_REPLACE); + } + break; + default: +pgfmt: return (__db_pgfmt(dbp->env, PGNO(child->page))); + } + + if (LF_ISSET(BPI_REPLACE)) { + DB_ASSERT(dbp->env, !LF_ISSET(BPI_NOLOGGING)); + if ((ret = __bam_irep(dbc, ppage, off, &hdr, &data)) != 0) + return (ret); + } else { + if (LF_ISSET(BPI_NOLOGGING)) + pitem = __db_pitem_nolog; + else + pitem = __db_pitem; + + if ((ret = pitem(dbc, ppage, + off, size, &hdr, data.size != 0 ? &data : NULL)) != 0) + return (ret); + } + + /* + * If a Recno or Btree with record numbers AM page, or an off-page + * duplicates tree, adjust the parent page's left page record count. + */ + if (F_ISSET(cp, C_RECNUM) && !LF_ISSET(BPI_NORECNUM)) { + /* Log the change. */ + if (DBC_LOGGING(dbc)) { + if ((ret = __bam_cadjust_log(dbp, dbc->txn, + &LSN(ppage), 0, PGNO(ppage), &LSN(ppage), + parent->indx, -(int32_t)nrecs, 0)) != 0) + return (ret); + } else + LSN_NOT_LOGGED(LSN(ppage)); + + /* Update the left page count. */ + if (dbc->dbtype == DB_RECNO) + GET_RINTERNAL(dbp, ppage, parent->indx)->nrecs -= nrecs; + else + GET_BINTERNAL(dbp, ppage, parent->indx)->nrecs -= nrecs; + } + + return (0); +} + +/* + * __bam_psplit -- + * Do the real work of splitting the page. + */ +static int +__bam_psplit(dbc, cp, lp, rp, splitret) + DBC *dbc; + EPG *cp; + PAGE *lp, *rp; + db_indx_t *splitret; +{ + DB *dbp; + PAGE *pp; + db_indx_t half, *inp, nbytes, off, splitp, top; + int adjust, cnt, iflag, isbigkey, ret; + + dbp = dbc->dbp; + pp = cp->page; + inp = P_INP(dbp, pp); + adjust = TYPE(pp) == P_LBTREE ? P_INDX : O_INDX; + + /* + * If we're splitting the first (last) page on a level because we're + * inserting (appending) a key to it, it's likely that the data is + * sorted. Moving a single item to the new page is less work and can + * push the fill factor higher than normal. This is trivial when we + * are splitting a new page before the beginning of the tree, all of + * the interesting tests are against values of 0. + * + * Catching appends to the tree is harder. In a simple append, we're + * inserting an item that sorts past the end of the tree; the cursor + * will point past the last element on the page. But, in trees with + * duplicates, the cursor may point to the last entry on the page -- + * in this case, the entry will also be the last element of a duplicate + * set (the last because the search call specified the SR_DUPLAST flag). + * The only way to differentiate between an insert immediately before + * the last item in a tree or an append after a duplicate set which is + * also the last item in the tree is to call the comparison function. + * When splitting internal pages during an append, the search code + * guarantees the cursor always points to the largest page item less + * than the new internal entry. To summarize, we want to catch three + * possible index values: + * + * NUM_ENT(page) Btree/Recno leaf insert past end-of-tree + * NUM_ENT(page) - O_INDX Btree or Recno internal insert past EOT + * NUM_ENT(page) - P_INDX Btree leaf insert past EOT after a set + * of duplicates + * + * two of which, (NUM_ENT(page) - O_INDX or P_INDX) might be an insert + * near the end of the tree, and not after the end of the tree at all. + * Do a simple test which might be wrong because calling the comparison + * functions is expensive. Regardless, it's not a big deal if we're + * wrong, we'll do the split the right way next time. + */ + off = 0; + if (NEXT_PGNO(pp) == PGNO_INVALID && cp->indx >= NUM_ENT(pp) - adjust) + off = NUM_ENT(pp) - adjust; + else if (PREV_PGNO(pp) == PGNO_INVALID && cp->indx == 0) + off = adjust; + if (off != 0) + goto sort; + + /* + * Split the data to the left and right pages. Try not to split on + * an overflow key. (Overflow keys on internal pages will slow down + * searches.) Refuse to split in the middle of a set of duplicates. + * + * First, find the optimum place to split. + * + * It's possible to try and split past the last record on the page if + * there's a very large record at the end of the page. Make sure this + * doesn't happen by bounding the check at the next-to-last entry on + * the page. + * + * Note, we try and split half the data present on the page. This is + * because another process may have already split the page and left + * it half empty. We don't try and skip the split -- we don't know + * how much space we're going to need on the page, and we may need up + * to half the page for a big item, so there's no easy test to decide + * if we need to split or not. Besides, if two threads are inserting + * data into the same place in the database, we're probably going to + * need more space soon anyway. + */ + top = NUM_ENT(pp) - adjust; + half = (dbp->pgsize - HOFFSET(pp)) / 2; + for (nbytes = 0, off = 0; off < top && nbytes < half; ++off) + switch (TYPE(pp)) { + case P_IBTREE: + if (B_TYPE( + GET_BINTERNAL(dbp, pp, off)->type) == B_KEYDATA) + nbytes += BINTERNAL_SIZE( + GET_BINTERNAL(dbp, pp, off)->len); + else + nbytes += BINTERNAL_SIZE(BOVERFLOW_SIZE); + break; + case P_LBTREE: + if (B_TYPE(GET_BKEYDATA(dbp, pp, off)->type) == + B_KEYDATA) + nbytes += BKEYDATA_SIZE(GET_BKEYDATA(dbp, + pp, off)->len); + else + nbytes += BOVERFLOW_SIZE; + + ++off; + /* FALLTHROUGH */ + case P_LDUP: + case P_LRECNO: + if (B_TYPE(GET_BKEYDATA(dbp, pp, off)->type) == + B_KEYDATA) + nbytes += BKEYDATA_SIZE(GET_BKEYDATA(dbp, + pp, off)->len); + else + nbytes += BOVERFLOW_SIZE; + break; + case P_IRECNO: + nbytes += RINTERNAL_SIZE; + break; + default: + return (__db_pgfmt(dbp->env, pp->pgno)); + } +sort: splitp = off; + + /* + * Splitp is either at or just past the optimum split point. If the + * tree type is such that we're going to promote a key to an internal + * page, and our current choice is an overflow key, look for something + * close by that's smaller. + */ + switch (TYPE(pp)) { + case P_IBTREE: + iflag = 1; + isbigkey = + B_TYPE(GET_BINTERNAL(dbp, pp, off)->type) != B_KEYDATA; + break; + case P_LBTREE: + case P_LDUP: + iflag = 0; + isbigkey = B_TYPE(GET_BKEYDATA(dbp, pp, off)->type) != + B_KEYDATA; + break; + default: + iflag = isbigkey = 0; + } + if (isbigkey) + for (cnt = 1; cnt <= 3; ++cnt) { + off = splitp + cnt * adjust; + if (off < (db_indx_t)NUM_ENT(pp) && + ((iflag && B_TYPE( + GET_BINTERNAL(dbp, pp,off)->type) == B_KEYDATA) || + B_TYPE(GET_BKEYDATA(dbp, pp, off)->type) == + B_KEYDATA)) { + splitp = off; + break; + } + if (splitp <= (db_indx_t)(cnt * adjust)) + continue; + off = splitp - cnt * adjust; + if (iflag ? B_TYPE( + GET_BINTERNAL(dbp, pp, off)->type) == B_KEYDATA : + B_TYPE(GET_BKEYDATA(dbp, pp, off)->type) == + B_KEYDATA) { + splitp = off; + break; + } + } + + /* + * We can't split in the middle a set of duplicates. We know that + * no duplicate set can take up more than about 25% of the page, + * because that's the point where we push it off onto a duplicate + * page set. So, this loop can't be unbounded. + */ + if (TYPE(pp) == P_LBTREE && + inp[splitp] == inp[splitp - adjust]) + for (cnt = 1;; ++cnt) { + off = splitp + cnt * adjust; + if (off < NUM_ENT(pp) && + inp[splitp] != inp[off]) { + splitp = off; + break; + } + if (splitp <= (db_indx_t)(cnt * adjust)) + continue; + off = splitp - cnt * adjust; + if (inp[splitp] != inp[off]) { + splitp = off + adjust; + break; + } + } + + /* We're going to split at splitp. */ + if ((ret = __bam_copy(dbp, pp, lp, 0, splitp)) != 0) + return (ret); + if ((ret = __bam_copy(dbp, pp, rp, splitp, NUM_ENT(pp))) != 0) + return (ret); + + *splitret = splitp; + return (0); +} + +/* + * __bam_copy -- + * Copy a set of records from one page to another. + * + * PUBLIC: int __bam_copy __P((DB *, PAGE *, PAGE *, u_int32_t, u_int32_t)); + */ +int +__bam_copy(dbp, pp, cp, nxt, stop) + DB *dbp; + PAGE *pp, *cp; + u_int32_t nxt, stop; +{ + BINTERNAL internal; + db_indx_t *cinp, nbytes, off, *pinp; + + cinp = P_INP(dbp, cp); + pinp = P_INP(dbp, pp); + /* + * Nxt is the offset of the next record to be placed on the target page. + */ + for (off = 0; nxt < stop; ++nxt, ++NUM_ENT(cp), ++off) { + switch (TYPE(pp)) { + case P_IBTREE: + if (off == 0 && nxt != 0) + nbytes = BINTERNAL_SIZE(0); + else if (B_TYPE( + GET_BINTERNAL(dbp, pp, nxt)->type) == B_KEYDATA) + nbytes = BINTERNAL_SIZE( + GET_BINTERNAL(dbp, pp, nxt)->len); + else + nbytes = BINTERNAL_SIZE(BOVERFLOW_SIZE); + break; + case P_LBTREE: + /* + * If we're on a key and it's a duplicate, just copy + * the offset. + */ + if (off != 0 && (nxt % P_INDX) == 0 && + pinp[nxt] == pinp[nxt - P_INDX]) { + cinp[off] = cinp[off - P_INDX]; + continue; + } + /* FALLTHROUGH */ + case P_LDUP: + case P_LRECNO: + if (B_TYPE(GET_BKEYDATA(dbp, pp, nxt)->type) == + B_KEYDATA) + nbytes = BKEYDATA_SIZE(GET_BKEYDATA(dbp, + pp, nxt)->len); + else + nbytes = BOVERFLOW_SIZE; + break; + case P_IRECNO: + nbytes = RINTERNAL_SIZE; + break; + default: + return (__db_pgfmt(dbp->env, pp->pgno)); + } + cinp[off] = HOFFSET(cp) -= nbytes; + if (off == 0 && nxt != 0 && TYPE(pp) == P_IBTREE) { + internal.len = 0; + UMRW_SET(internal.unused); + internal.type = B_KEYDATA; + internal.pgno = GET_BINTERNAL(dbp, pp, nxt)->pgno; + internal.nrecs = GET_BINTERNAL(dbp, pp, nxt)->nrecs; + memcpy(P_ENTRY(dbp, cp, off), &internal, nbytes); + } + else + memcpy(P_ENTRY(dbp, cp, off), + P_ENTRY(dbp, pp, nxt), nbytes); + } + return (0); +} diff -r 000000000000 -r a1985f14b030 src/btree/bt_stat.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/btree/bt_stat.c Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,691 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 1996, 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + * $Id$ + */ + +#include "db_config.h" + +#include "db_int.h" +#include "dbinc/db_page.h" +#include "dbinc/btree.h" +#include "dbinc/lock.h" +#include "dbinc/mp.h" +#include "dbinc/partition.h" + +#ifdef HAVE_STATISTICS +/* + * __bam_stat -- + * Gather/print the btree statistics + * + * PUBLIC: int __bam_stat __P((DBC *, void *, u_int32_t)); + */ +int +__bam_stat(dbc, spp, flags) + DBC *dbc; + void *spp; + u_int32_t flags; +{ + BTMETA *meta; + BTREE *t; + DB *dbp; + DB_BTREE_STAT *sp; + DB_LOCK lock, metalock; + DB_MPOOLFILE *mpf; + ENV *env; + PAGE *h; + db_pgno_t pgno; + int ret, t_ret, write_meta; + + dbp = dbc->dbp; + env = dbp->env; + + meta = NULL; + t = dbp->bt_internal; + sp = NULL; + LOCK_INIT(metalock); + LOCK_INIT(lock); + mpf = dbp->mpf; + h = NULL; + ret = write_meta = 0; + + /* Allocate and clear the structure. */ + if ((ret = __os_umalloc(env, sizeof(*sp), &sp)) != 0) + goto err; + memset(sp, 0, sizeof(*sp)); + + /* Get the metadata page for the entire database. */ + pgno = PGNO_BASE_MD; + if ((ret = __db_lget(dbc, 0, pgno, DB_LOCK_READ, 0, &metalock)) != 0) + goto err; + if ((ret = __memp_fget(mpf, &pgno, + dbc->thread_info, dbc->txn, 0, &meta)) != 0) + goto err; + + if (flags == DB_FAST_STAT) + goto meta_only; + + /* Walk the metadata free list, counting pages. */ + for (sp->bt_free = 0, pgno = meta->dbmeta.free; pgno != PGNO_INVALID;) { + ++sp->bt_free; + + if ((ret = __memp_fget(mpf, &pgno, + dbc->thread_info, dbc->txn, 0, &h)) != 0) + goto err; + + pgno = h->next_pgno; + if ((ret = __memp_fput(mpf, + dbc->thread_info, h, dbc->priority)) != 0) + goto err; + h = NULL; + } + + /* Get the root page. */ + BAM_GET_ROOT(dbc, pgno, h, 0, DB_LOCK_READ, lock, ret); + if (ret != 0) + goto err; + DB_ASSERT(env, h != NULL); + + /* Get the levels from the root page. */ + sp->bt_levels = h->level; + + /* Discard the root page. */ + ret = __memp_fput(mpf, dbc->thread_info, h, dbc->priority); + h = NULL; + if ((t_ret = __LPUT(dbc, lock)) != 0 && ret == 0) + ret = t_ret; + if (ret != 0) + goto err; + + /* Discard the metadata page. */ + ret = __memp_fput(mpf, dbc->thread_info, meta, dbc->priority); + meta = NULL; + if ((t_ret = __LPUT(dbc, metalock)) != 0 && ret == 0) + ret = t_ret; + if (ret != 0) + goto err; + + /* Walk the tree. */ + if ((ret = __bam_traverse(dbc, + DB_LOCK_READ, PGNO_INVALID, __bam_stat_callback, sp)) != 0) + goto err; + +#ifdef HAVE_COMPRESSION + if (DB_IS_COMPRESSED(dbp) && (ret = __bam_compress_count(dbc, + &sp->bt_nkeys, &sp->bt_ndata)) != 0) + goto err; +#endif + + /* + * Get the subdatabase metadata page if it's not the same as the + * one we already have. + */ + write_meta = !F_ISSET(dbp, DB_AM_RDONLY) && + (!MULTIVERSION(dbp) || dbc->txn != NULL); +meta_only: + if (meta == NULL || t->bt_meta != PGNO_BASE_MD || write_meta) { + if (meta != NULL) { + ret = __memp_fput(mpf, + dbc->thread_info, meta, dbc->priority); + meta = NULL; + if ((t_ret = __LPUT(dbc, metalock)) != 0 && ret == 0) + ret = t_ret; + if (ret != 0) + goto err; + } + + if ((ret = __db_lget(dbc, + 0, t->bt_meta, write_meta ? DB_LOCK_WRITE : DB_LOCK_READ, + 0, &metalock)) != 0) + goto err; + if ((ret = __memp_fget(mpf, &t->bt_meta, + dbc->thread_info, dbc->txn, + write_meta ? DB_MPOOL_DIRTY : 0, &meta)) != 0) + goto err; + } + if (flags == DB_FAST_STAT) { + if (dbp->type == DB_RECNO || + (dbp->type == DB_BTREE && F_ISSET(dbp, DB_AM_RECNUM))) { + BAM_GET_ROOT(dbc, pgno, h, 0, DB_LOCK_READ, lock, ret); + if (ret != 0) + goto err; + + sp->bt_nkeys = RE_NREC(h); + } else + sp->bt_nkeys = meta->dbmeta.key_count; + + sp->bt_ndata = dbp->type == DB_RECNO ? + sp->bt_nkeys : meta->dbmeta.record_count; + } + + /* Get metadata page statistics. */ + sp->bt_metaflags = meta->dbmeta.flags; + sp->bt_minkey = meta->minkey; + sp->bt_re_len = meta->re_len; + sp->bt_re_pad = meta->re_pad; + /* + * Don't take the page number from the meta-data page -- that value is + * only maintained in the primary database, we may have been called on + * a subdatabase. (Yes, I read the primary database meta-data page + * earlier in this function, but I'm asking the underlying cache so the + * code for the Hash and Btree methods is the same.) + */ + if ((ret = __memp_get_last_pgno(dbp->mpf, &pgno)) != 0) + goto err; + sp->bt_pagecnt = pgno + 1; + sp->bt_pagesize = meta->dbmeta.pagesize; + sp->bt_magic = meta->dbmeta.magic; + sp->bt_version = meta->dbmeta.version; + + if (write_meta != 0) { + meta->dbmeta.key_count = sp->bt_nkeys; + meta->dbmeta.record_count = sp->bt_ndata; + } + + *(DB_BTREE_STAT **)spp = sp; + +err: /* Discard the second page. */ + if (h != NULL && (t_ret = __memp_fput(mpf, + dbc->thread_info, h, dbc->priority)) != 0 && ret == 0) + ret = t_ret; + if ((t_ret = __LPUT(dbc, lock)) != 0 && ret == 0) + ret = t_ret; + + /* Discard the metadata page. */ + if (meta != NULL && (t_ret = __memp_fput(mpf, + dbc->thread_info, meta, dbc->priority)) != 0 && ret == 0) + ret = t_ret; + if ((t_ret = __LPUT(dbc, metalock)) != 0 && ret == 0) + ret = t_ret; + + if (ret != 0 && sp != NULL) { + __os_ufree(env, sp); + *(DB_BTREE_STAT **)spp = NULL; + } + + return (ret); +} + +/* + * __bam_stat_print -- + * Display btree/recno statistics. + * + * PUBLIC: int __bam_stat_print __P((DBC *, u_int32_t)); + */ +int +__bam_stat_print(dbc, flags) + DBC *dbc; + u_int32_t flags; +{ + static const FN fn[] = { + { BTM_DUP, "duplicates" }, + { BTM_RECNO, "recno" }, + { BTM_RECNUM, "record-numbers" }, + { BTM_FIXEDLEN, "fixed-length" }, + { BTM_RENUMBER, "renumber" }, + { BTM_SUBDB, "multiple-databases" }, + { BTM_DUPSORT, "sorted duplicates" }, + { BTM_COMPRESS, "compressed" }, + { 0, NULL } + }; + DB *dbp; + DB_BTREE_STAT *sp; + ENV *env; + int lorder, ret; + const char *s; + + dbp = dbc->dbp; + env = dbp->env; +#ifdef HAVE_PARTITION + if (DB_IS_PARTITIONED(dbp)) { + if ((ret = __partition_stat(dbc, &sp, flags)) != 0) + return (ret); + } else +#endif + if ((ret = __bam_stat(dbc, &sp, LF_ISSET(DB_FAST_STAT))) != 0) + return (ret); + + if (LF_ISSET(DB_STAT_ALL)) { + __db_msg(env, "%s", DB_GLOBAL(db_line)); + __db_msg(env, "Default Btree/Recno database information:"); + } + + __db_msg(env, "%lx\tBtree magic number", (u_long)sp->bt_magic); + __db_msg(env, "%lu\tBtree version number", (u_long)sp->bt_version); + + (void)__db_get_lorder(dbp, &lorder); + switch (lorder) { + case 1234: + s = "Little-endian"; + break; + case 4321: + s = "Big-endian"; + break; + default: + s = "Unrecognized byte order"; + break; + } + __db_msg(env, "%s\tByte order", s); + __db_prflags(env, NULL, sp->bt_metaflags, fn, NULL, "\tFlags"); + if (dbp->type == DB_BTREE) + __db_dl(env, "Minimum keys per-page", (u_long)sp->bt_minkey); + if (dbp->type == DB_RECNO) { + __db_dl(env, + "Fixed-length record size", (u_long)sp->bt_re_len); + __db_msg(env, + "%#x\tFixed-length record pad", (u_int)sp->bt_re_pad); + } + __db_dl(env, + "Underlying database page size", (u_long)sp->bt_pagesize); + if (dbp->type == DB_BTREE) + __db_dl(env, "Overflow key/data size", + ((BTREE_CURSOR *)dbc->internal)->ovflsize); + __db_dl(env, "Number of levels in the tree", (u_long)sp->bt_levels); + __db_dl(env, dbp->type == DB_BTREE ? + "Number of unique keys in the tree" : + "Number of records in the tree", (u_long)sp->bt_nkeys); + __db_dl(env, + "Number of data items in the tree", (u_long)sp->bt_ndata); + + __db_dl(env, + "Number of tree internal pages", (u_long)sp->bt_int_pg); + __db_dl_pct(env, + "Number of bytes free in tree internal pages", + (u_long)sp->bt_int_pgfree, + DB_PCT_PG(sp->bt_int_pgfree, sp->bt_int_pg, sp->bt_pagesize), "ff"); + + __db_dl(env, + "Number of tree leaf pages", (u_long)sp->bt_leaf_pg); + __db_dl_pct(env, "Number of bytes free in tree leaf pages", + (u_long)sp->bt_leaf_pgfree, DB_PCT_PG( + sp->bt_leaf_pgfree, sp->bt_leaf_pg, sp->bt_pagesize), "ff"); + + __db_dl(env, + "Number of tree duplicate pages", (u_long)sp->bt_dup_pg); + __db_dl_pct(env, + "Number of bytes free in tree duplicate pages", + (u_long)sp->bt_dup_pgfree, + DB_PCT_PG(sp->bt_dup_pgfree, sp->bt_dup_pg, sp->bt_pagesize), "ff"); + + __db_dl(env, + "Number of tree overflow pages", (u_long)sp->bt_over_pg); + __db_dl_pct(env, "Number of bytes free in tree overflow pages", + (u_long)sp->bt_over_pgfree, DB_PCT_PG( + sp->bt_over_pgfree, sp->bt_over_pg, sp->bt_pagesize), "ff"); + __db_dl(env, "Number of empty pages", (u_long)sp->bt_empty_pg); + + __db_dl(env, "Number of pages on the free list", (u_long)sp->bt_free); + + __os_ufree(env, sp); + + return (0); +} + +/* + * __bam_stat_callback -- + * Statistics callback. + * + * PUBLIC: int __bam_stat_callback __P((DBC *, PAGE *, void *, int *)); + */ +int +__bam_stat_callback(dbc, h, cookie, putp) + DBC *dbc; + PAGE *h; + void *cookie; + int *putp; +{ + DB *dbp; + DB_BTREE_STAT *sp; + db_indx_t indx, *inp, top; + u_int8_t type; + + dbp = dbc->dbp; + sp = cookie; + *putp = 0; + top = NUM_ENT(h); + inp = P_INP(dbp, h); + + switch (TYPE(h)) { + case P_IBTREE: + case P_IRECNO: + ++sp->bt_int_pg; + sp->bt_int_pgfree += P_FREESPACE(dbp, h); + break; + case P_LBTREE: + if (top == 0) + ++sp->bt_empty_pg; + + /* Correct for on-page duplicates and deleted items. */ + for (indx = 0; indx < top; indx += P_INDX) { + type = GET_BKEYDATA(dbp, h, indx + O_INDX)->type; + /* Ignore deleted items. */ + if (B_DISSET(type)) + continue; + + /* Ignore duplicate keys. */ + if (indx + P_INDX >= top || + inp[indx] != inp[indx + P_INDX]) + ++sp->bt_nkeys; + + /* Ignore off-page duplicates. */ + if (B_TYPE(type) != B_DUPLICATE) + ++sp->bt_ndata; + } + + ++sp->bt_leaf_pg; + sp->bt_leaf_pgfree += P_FREESPACE(dbp, h); + break; + case P_LRECNO: + if (top == 0) + ++sp->bt_empty_pg; + + /* + * If walking a recno tree, then each of these items is a key. + * Otherwise, we're walking an off-page duplicate set. + */ + if (dbp->type == DB_RECNO) { + /* + * Correct for deleted items in non-renumbering Recno + * databases. + */ + if (F_ISSET(dbp, DB_AM_RENUMBER)) { + sp->bt_nkeys += top; + sp->bt_ndata += top; + } else + for (indx = 0; indx < top; indx += O_INDX) { + type = GET_BKEYDATA(dbp, h, indx)->type; + if (!B_DISSET(type)) { + ++sp->bt_ndata; + ++sp->bt_nkeys; + } + } + + ++sp->bt_leaf_pg; + sp->bt_leaf_pgfree += P_FREESPACE(dbp, h); + } else { + sp->bt_ndata += top; + + ++sp->bt_dup_pg; + sp->bt_dup_pgfree += P_FREESPACE(dbp, h); + } + break; + case P_LDUP: + if (top == 0) + ++sp->bt_empty_pg; + + /* Correct for deleted items. */ + for (indx = 0; indx < top; indx += O_INDX) + if (!B_DISSET(GET_BKEYDATA(dbp, h, indx)->type)) + ++sp->bt_ndata; + + ++sp->bt_dup_pg; + sp->bt_dup_pgfree += P_FREESPACE(dbp, h); + break; + case P_OVERFLOW: + ++sp->bt_over_pg; + sp->bt_over_pgfree += P_OVFLSPACE(dbp, dbp->pgsize, h); + break; + default: + return (__db_pgfmt(dbp->env, h->pgno)); + } + return (0); +} + +/* + * __bam_print_cursor -- + * Display the current internal cursor. + * + * PUBLIC: void __bam_print_cursor __P((DBC *)); + */ +void +__bam_print_cursor(dbc) + DBC *dbc; +{ + static const FN fn[] = { + { C_DELETED, "C_DELETED" }, + { C_RECNUM, "C_RECNUM" }, + { C_RENUMBER, "C_RENUMBER" }, + { 0, NULL } + }; + ENV *env; + BTREE_CURSOR *cp; + + env = dbc->env; + cp = (BTREE_CURSOR *)dbc->internal; + + STAT_ULONG("Overflow size", cp->ovflsize); + if (dbc->dbtype == DB_RECNO) + STAT_ULONG("Recno", cp->recno); + STAT_ULONG("Order", cp->order); + __db_prflags(env, NULL, cp->flags, fn, NULL, "\tInternal Flags"); +} + +#else /* !HAVE_STATISTICS */ + +int +__bam_stat(dbc, spp, flags) + DBC *dbc; + void *spp; + u_int32_t flags; +{ + COMPQUIET(spp, NULL); + COMPQUIET(flags, 0); + + return (__db_stat_not_built(dbc->env)); +} + +int +__bam_stat_print(dbc, flags) + DBC *dbc; + u_int32_t flags; +{ + COMPQUIET(flags, 0); + + return (__db_stat_not_built(dbc->env)); +} +#endif + +/* + * __bam_key_range -- + * Return proportion of keys relative to given key. The numbers are + * slightly skewed due to on page duplicates. + * + * PUBLIC: int __bam_key_range __P((DBC *, DBT *, DB_KEY_RANGE *, u_int32_t)); + */ +int +__bam_key_range(dbc, dbt, kp, flags) + DBC *dbc; + DBT *dbt; + DB_KEY_RANGE *kp; + u_int32_t flags; +{ + BTREE_CURSOR *cp; + EPG *sp; + double factor; + int exact, ret; + + COMPQUIET(flags, 0); + + if ((ret = __bam_search(dbc, PGNO_INVALID, + dbt, SR_STK_ONLY, 1, NULL, &exact)) != 0) + return (ret); + + cp = (BTREE_CURSOR *)dbc->internal; + kp->less = kp->greater = 0.0; + + factor = 1.0; + + /* Correct the leaf page. */ + cp->csp->entries /= 2; + cp->csp->indx /= 2; + for (sp = cp->sp; sp <= cp->csp; ++sp) { + /* + * At each level we know that pages greater than indx contain + * keys greater than what we are looking for and those less + * than indx are less than. The one pointed to by indx may + * have some less, some greater or even equal. If indx is + * equal to the number of entries, then the key is out of range + * and everything is less. + */ + if (sp->indx == 0) + kp->greater += factor * (sp->entries - 1)/sp->entries; + else if (sp->indx == sp->entries) + kp->less += factor; + else { + kp->less += factor * sp->indx / sp->entries; + kp->greater += factor * + ((sp->entries - sp->indx) - 1) / sp->entries; + } + factor *= 1.0/sp->entries; + } + + /* + * If there was an exact match then assign 1 n'th to the key itself. + * Otherwise that factor belongs to those greater than the key, unless + * the key was out of range. + */ + if (exact) + kp->equal = factor; + else { + if (kp->less != 1) + kp->greater += factor; + kp->equal = 0; + } + + if ((ret = __bam_stkrel(dbc, 0)) != 0) + return (ret); + + return (0); +} + +/* + * __bam_traverse -- + * Walk a Btree database. + * + * PUBLIC: int __bam_traverse __P((DBC *, db_lockmode_t, + * PUBLIC: db_pgno_t, int (*)(DBC *, PAGE *, void *, int *), void *)); + */ +int +__bam_traverse(dbc, mode, root_pgno, callback, cookie) + DBC *dbc; + db_lockmode_t mode; + db_pgno_t root_pgno; + int (*callback)__P((DBC *, PAGE *, void *, int *)); + void *cookie; +{ + BINTERNAL *bi; + BKEYDATA *bk; + DB *dbp; + DB_LOCK lock; + DB_MPOOLFILE *mpf; + PAGE *h; + RINTERNAL *ri; + db_indx_t indx, *inp; + int already_put, ret, t_ret; + + dbp = dbc->dbp; + mpf = dbp->mpf; + already_put = 0; + LOCK_INIT(lock); + + COMPQUIET(h, NULL); + BAM_GET_ROOT(dbc, root_pgno, h, 0, mode, lock, ret); + if (ret != 0) + goto err1; + + switch (TYPE(h)) { + case P_IBTREE: + for (indx = 0; indx < NUM_ENT(h); indx += O_INDX) { + bi = GET_BINTERNAL(dbp, h, indx); + if (B_TYPE(bi->type) == B_OVERFLOW && + (ret = __db_traverse_big(dbc, + ((BOVERFLOW *)bi->data)->pgno, + callback, cookie)) != 0) + goto err; + if ((ret = __bam_traverse( + dbc, mode, bi->pgno, callback, cookie)) != 0) + goto err; + } + break; + case P_IRECNO: + for (indx = 0; indx < NUM_ENT(h); indx += O_INDX) { + ri = GET_RINTERNAL(dbp, h, indx); + if ((ret = __bam_traverse( + dbc, mode, ri->pgno, callback, cookie)) != 0) + goto err; + } + break; + case P_LBTREE: + inp = P_INP(dbp, h); + for (indx = 0; indx < NUM_ENT(h); indx += P_INDX) { + bk = GET_BKEYDATA(dbp, h, indx); + if (B_TYPE(bk->type) == B_OVERFLOW && + (indx + P_INDX >= NUM_ENT(h) || + inp[indx] != inp[indx + P_INDX])) { + if ((ret = __db_traverse_big(dbc, + GET_BOVERFLOW(dbp, h, indx)->pgno, + callback, cookie)) != 0) + goto err; + } + bk = GET_BKEYDATA(dbp, h, indx + O_INDX); + if (B_TYPE(bk->type) == B_DUPLICATE && + (ret = __bam_traverse(dbc, mode, + GET_BOVERFLOW(dbp, h, indx + O_INDX)->pgno, + callback, cookie)) != 0) + goto err; + if (B_TYPE(bk->type) == B_OVERFLOW && + (ret = __db_traverse_big(dbc, + GET_BOVERFLOW(dbp, h, indx + O_INDX)->pgno, + callback, cookie)) != 0) + goto err; + } + break; + case P_LDUP: + case P_LRECNO: + for (indx = 0; indx < NUM_ENT(h); indx += O_INDX) { + bk = GET_BKEYDATA(dbp, h, indx); + if (B_TYPE(bk->type) == B_OVERFLOW && + (ret = __db_traverse_big(dbc, + GET_BOVERFLOW(dbp, h, indx)->pgno, + callback, cookie)) != 0) + goto err; + } + break; + default: + return (__db_pgfmt(dbp->env, h->pgno)); + } + + ret = callback(dbc, h, cookie, &already_put); + +err: if (!already_put && (t_ret = __memp_fput(mpf, + dbc->thread_info, h, dbc->priority)) != 0 && ret == 0) + ret = t_ret; +err1: if ((t_ret = __TLPUT(dbc, lock)) != 0 && ret == 0) + ret = t_ret; + + return (ret); +} diff -r 000000000000 -r a1985f14b030 src/btree/bt_verify.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/btree/bt_verify.c Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,2827 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 1999, 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + * $Id$ + */ + +#include "db_config.h" + +#include "db_int.h" +#include "dbinc/db_page.h" +#include "dbinc/db_verify.h" +#include "dbinc/btree.h" +#include "dbinc/lock.h" +#include "dbinc/mp.h" + +static int __bam_safe_getdata __P((DB *, DB_THREAD_INFO *, + PAGE *, u_int32_t, int, DBT *, int *)); +static int __bam_vrfy_inp __P((DB *, VRFY_DBINFO *, PAGE *, db_pgno_t, + db_indx_t *, u_int32_t)); +static int __bam_vrfy_treeorder __P((DB *, DB_THREAD_INFO *, PAGE *, + BINTERNAL *, BINTERNAL *, int (*)(DB *, const DBT *, const DBT *), + u_int32_t)); +static int __ram_vrfy_inp __P((DB *, VRFY_DBINFO *, PAGE *, db_pgno_t, + db_indx_t *, u_int32_t)); + +/* + * __bam_vrfy_meta -- + * Verify the btree-specific part of a metadata page. + * + * PUBLIC: int __bam_vrfy_meta __P((DB *, VRFY_DBINFO *, BTMETA *, + * PUBLIC: db_pgno_t, u_int32_t)); + */ +int +__bam_vrfy_meta(dbp, vdp, meta, pgno, flags) + DB *dbp; + VRFY_DBINFO *vdp; + BTMETA *meta; + db_pgno_t pgno; + u_int32_t flags; +{ + ENV *env; + VRFY_PAGEINFO *pip; + int isbad, t_ret, ret; + db_indx_t ovflsize; + + env = dbp->env; + isbad = 0; + + if ((ret = __db_vrfy_getpageinfo(vdp, pgno, &pip)) != 0) + return (ret); + + /* + * If we came through __db_vrfy_pagezero, we have already checked the + * common fields. However, we used the on-disk metadata page, it may + * have been stale. We now have the page from mpool, so check that. + */ + if ((ret = __db_vrfy_meta(dbp, vdp, &meta->dbmeta, pgno, flags)) != 0) { + if (ret == DB_VERIFY_BAD) + isbad = 1; + else + goto err; + } + + /* bt_minkey: must be >= 2; must produce sensible ovflsize */ + + /* avoid division by zero */ + ovflsize = meta->minkey > 0 ? + B_MINKEY_TO_OVFLSIZE(dbp, meta->minkey, dbp->pgsize) : 0; + + if (meta->minkey < 2 || + ovflsize > B_MINKEY_TO_OVFLSIZE(dbp, DEFMINKEYPAGE, dbp->pgsize)) { + pip->bt_minkey = 0; + isbad = 1; + EPRINT((env, DB_STR_A("1034", + "Page %lu: nonsensical bt_minkey value %lu on metadata page", + "%lu %lu"), (u_long)pgno, (u_long)meta->minkey)); + } else + pip->bt_minkey = meta->minkey; + + /* re_len: no constraints on this (may be zero or huge--we make rope) */ + pip->re_pad = meta->re_pad; + pip->re_len = meta->re_len; + + /* + * The root must not be current page or 0 and it must be within + * database. If this metadata page is the master meta data page + * of the file, then the root page had better be page 1. + */ + pip->root = 0; + if (meta->root == PGNO_INVALID || + meta->root == pgno || !IS_VALID_PGNO(meta->root) || + (pgno == PGNO_BASE_MD && meta->root != 1)) { + isbad = 1; + EPRINT((env, DB_STR_A("1035", + "Page %lu: nonsensical root page %lu on metadata page", + "%lu %lu"), (u_long)pgno, (u_long)meta->root)); + } else + pip->root = meta->root; + + /* Flags. */ + if (F_ISSET(&meta->dbmeta, BTM_RENUMBER)) + F_SET(pip, VRFY_IS_RRECNO); + + if (F_ISSET(&meta->dbmeta, BTM_SUBDB)) { + /* + * If this is a master db meta page, it had better not have + * duplicates. + */ + if (F_ISSET(&meta->dbmeta, BTM_DUP) && pgno == PGNO_BASE_MD) { + isbad = 1; + EPRINT((env, DB_STR_A("1036", +"Page %lu: Btree metadata page has both duplicates and multiple databases", + "%lu"), (u_long)pgno)); + } + F_SET(pip, VRFY_HAS_SUBDBS); + } + + if (F_ISSET(&meta->dbmeta, BTM_DUP)) + F_SET(pip, VRFY_HAS_DUPS); + if (F_ISSET(&meta->dbmeta, BTM_DUPSORT)) + F_SET(pip, VRFY_HAS_DUPSORT); + if (F_ISSET(&meta->dbmeta, BTM_RECNUM)) + F_SET(pip, VRFY_HAS_RECNUMS); + if (F_ISSET(pip, VRFY_HAS_RECNUMS) && F_ISSET(pip, VRFY_HAS_DUPS)) { + EPRINT((env, DB_STR_A("1037", + "Page %lu: Btree metadata page illegally has both recnums and dups", + "%lu"), (u_long)pgno)); + isbad = 1; + } + + if (F_ISSET(&meta->dbmeta, BTM_RECNO)) { + F_SET(pip, VRFY_IS_RECNO); + dbp->type = DB_RECNO; + } else if (F_ISSET(pip, VRFY_IS_RRECNO)) { + isbad = 1; + EPRINT((env, DB_STR_A("1038", + "Page %lu: metadata page has renumber flag set but is not recno", + "%lu"), (u_long)pgno)); + } + +#ifdef HAVE_COMPRESSION + if (F_ISSET(&meta->dbmeta, BTM_COMPRESS)) { + F_SET(pip, VRFY_HAS_COMPRESS); + if (!DB_IS_COMPRESSED(dbp)) { + ((BTREE *)dbp->bt_internal)->bt_compress = + __bam_defcompress; + ((BTREE *)dbp->bt_internal)->bt_decompress = + __bam_defdecompress; + } + /* + * Copy dup_compare to compress_dup_compare, and use the + * compression duplicate compare. + */ + if (F_ISSET(pip, VRFY_HAS_DUPSORT)) { + if (dbp->dup_compare == NULL) + dbp->dup_compare = __bam_defcmp; + if (((BTREE *)dbp->bt_internal)->compress_dup_compare + == NULL) { + ((BTREE *)dbp->bt_internal)-> + compress_dup_compare = dbp->dup_compare; + dbp->dup_compare = __bam_compress_dupcmp; + } + } + } + + if (F_ISSET(pip, VRFY_HAS_RECNUMS) && F_ISSET(pip, VRFY_HAS_COMPRESS)) { + EPRINT((env, DB_STR_A("1039", + "Page %lu: Btree metadata page illegally has both recnums and compression", + "%lu"), (u_long)pgno)); + isbad = 1; + } + if (F_ISSET(pip, VRFY_HAS_DUPS) && !F_ISSET(pip, VRFY_HAS_DUPSORT) && + F_ISSET(pip, VRFY_HAS_COMPRESS)) { + EPRINT((env, DB_STR_A("1040", + "Page %lu: Btree metadata page illegally has both " + "unsorted duplicates and compression", + "%lu"), (u_long)pgno)); + isbad = 1; + } +#endif + + if (F_ISSET(pip, VRFY_IS_RECNO) && F_ISSET(pip, VRFY_HAS_DUPS)) { + EPRINT((env, DB_STR_A("1041", + "Page %lu: recno metadata page specifies duplicates", + "%lu"), (u_long)pgno)); + isbad = 1; + } + + if (F_ISSET(&meta->dbmeta, BTM_FIXEDLEN)) + F_SET(pip, VRFY_IS_FIXEDLEN); + else if (pip->re_len > 0) { + /* + * It's wrong to have an re_len if it's not a fixed-length + * database + */ + isbad = 1; + EPRINT((env, DB_STR_A("1042", + "Page %lu: re_len of %lu in non-fixed-length database", + "%lu %lu"), (u_long)pgno, (u_long)pip->re_len)); + } + + /* + * We do not check that the rest of the page is 0, because it may + * not be and may still be correct. + */ + +err: if ((t_ret = __db_vrfy_putpageinfo(env, vdp, pip)) != 0 && ret == 0) + ret = t_ret; + if (LF_ISSET(DB_SALVAGE) && + (t_ret = __db_salvage_markdone(vdp, pgno)) != 0 && ret == 0) + ret = t_ret; + return ((ret == 0 && isbad == 1) ? DB_VERIFY_BAD : ret); +} + +/* + * __ram_vrfy_leaf -- + * Verify a recno leaf page. + * + * PUBLIC: int __ram_vrfy_leaf __P((DB *, VRFY_DBINFO *, PAGE *, db_pgno_t, + * PUBLIC: u_int32_t)); + */ +int +__ram_vrfy_leaf(dbp, vdp, h, pgno, flags) + DB *dbp; + VRFY_DBINFO *vdp; + PAGE *h; + db_pgno_t pgno; + u_int32_t flags; +{ + BKEYDATA *bk; + ENV *env; + VRFY_PAGEINFO *pip; + db_indx_t i; + int ret, t_ret, isbad; + u_int32_t re_len_guess, len; + + env = dbp->env; + isbad = 0; + + if ((ret = __db_vrfy_getpageinfo(vdp, pgno, &pip)) != 0) + return (ret); + + if (TYPE(h) != P_LRECNO) { + ret = __db_unknown_path(env, "__ram_vrfy_leaf"); + goto err; + } + + /* + * Verify (and, if relevant, save off) page fields common to + * all PAGEs. + */ + if ((ret = __db_vrfy_datapage(dbp, vdp, h, pgno, flags)) != 0) { + if (ret == DB_VERIFY_BAD) + isbad = 1; + else + goto err; + } + + /* + * Verify inp[]. Return immediately if it returns DB_VERIFY_BAD; + * further checks are dangerous. + */ + if ((ret = __bam_vrfy_inp(dbp, + vdp, h, pgno, &pip->entries, flags)) != 0) + goto err; + + if (F_ISSET(pip, VRFY_HAS_DUPS)) { + EPRINT((env, DB_STR_A("1043", + "Page %lu: Recno database has dups", + "%lu"), (u_long)pgno)); + ret = DB_VERIFY_BAD; + goto err; + } + + /* + * Walk through inp and see if the lengths of all the records are the + * same--if so, this may be a fixed-length database, and we want to + * save off this value. We know inp to be safe if we've gotten this + * far. + */ + re_len_guess = 0; + for (i = 0; i < NUM_ENT(h); i++) { + bk = GET_BKEYDATA(dbp, h, i); + /* KEYEMPTY. Go on. */ + if (B_DISSET(bk->type)) + continue; + if (bk->type == B_OVERFLOW) + len = ((BOVERFLOW *)bk)->tlen; + else if (bk->type == B_KEYDATA) + len = bk->len; + else { + isbad = 1; + EPRINT((env, DB_STR_A("1044", + "Page %lu: nonsensical type for item %lu", + "%lu %lu"), (u_long)pgno, (u_long)i)); + continue; + } + if (re_len_guess == 0) + re_len_guess = len; + + /* + * Is this item's len the same as the last one's? If not, + * reset to 0 and break--we don't have a single re_len. + * Otherwise, go on to the next item. + */ + if (re_len_guess != len) { + re_len_guess = 0; + break; + } + } + pip->re_len = re_len_guess; + + /* Save off record count. */ + pip->rec_cnt = NUM_ENT(h); + +err: if ((t_ret = __db_vrfy_putpageinfo(env, vdp, pip)) != 0 && ret == 0) + ret = t_ret; + return ((ret == 0 && isbad == 1) ? DB_VERIFY_BAD : ret); +} + +/* + * __bam_vrfy -- + * Verify a btree leaf or internal page. + * + * PUBLIC: int __bam_vrfy __P((DB *, VRFY_DBINFO *, PAGE *, db_pgno_t, + * PUBLIC: u_int32_t)); + */ +int +__bam_vrfy(dbp, vdp, h, pgno, flags) + DB *dbp; + VRFY_DBINFO *vdp; + PAGE *h; + db_pgno_t pgno; + u_int32_t flags; +{ + ENV *env; + VRFY_PAGEINFO *pip; + int ret, t_ret, isbad; + + env = dbp->env; + isbad = 0; + + if ((ret = __db_vrfy_getpageinfo(vdp, pgno, &pip)) != 0) + return (ret); + + switch (TYPE(h)) { + case P_IBTREE: + case P_IRECNO: + case P_LBTREE: + case P_LDUP: + break; + default: + ret = __db_unknown_path(env, "__bam_vrfy"); + goto err; + } + + /* + * Verify (and, if relevant, save off) page fields common to + * all PAGEs. + */ + if ((ret = __db_vrfy_datapage(dbp, vdp, h, pgno, flags)) != 0) { + if (ret == DB_VERIFY_BAD) + isbad = 1; + else + goto err; + } + + /* + * The record count is, on internal pages, stored in an overloaded + * next_pgno field. Save it off; we'll verify it when we check + * overall database structure. We could overload the field + * in VRFY_PAGEINFO, too, but this seems gross, and space + * is not at such a premium. + */ + pip->rec_cnt = RE_NREC(h); + + /* + * Verify inp[]. + */ + if (TYPE(h) == P_IRECNO) { + if ((ret = __ram_vrfy_inp(dbp, + vdp, h, pgno, &pip->entries, flags)) != 0) + goto err; + } else if ((ret = __bam_vrfy_inp(dbp, + vdp, h, pgno, &pip->entries, flags)) != 0) { + if (ret == DB_VERIFY_BAD) + isbad = 1; + else + goto err; + EPRINT((env, DB_STR_A("1045", + "Page %lu: item order check unsafe: skipping", + "%lu"), (u_long)pgno)); + } else if (!LF_ISSET(DB_NOORDERCHK) && (ret = + __bam_vrfy_itemorder(dbp, + vdp, vdp->thread_info, h, pgno, 0, 0, 0, flags)) != 0) { + /* + * We know that the elements of inp are reasonable. + * + * Check that elements fall in the proper order. + */ + if (ret == DB_VERIFY_BAD) + isbad = 1; + else + goto err; + } + +err: if ((t_ret = __db_vrfy_putpageinfo(env, vdp, pip)) != 0 && ret == 0) + ret = t_ret; + return ((ret == 0 && isbad == 1) ? DB_VERIFY_BAD : ret); +} + +/* + * __ram_vrfy_inp -- + * Verify that all entries in a P_IRECNO inp[] array are reasonable, + * and count them. Note that P_LRECNO uses __bam_vrfy_inp; + * P_IRECNOs are a special, and simpler, case, since they have + * RINTERNALs rather than BKEYDATA/BINTERNALs. + */ +static int +__ram_vrfy_inp(dbp, vdp, h, pgno, nentriesp, flags) + DB *dbp; + VRFY_DBINFO *vdp; + PAGE *h; + db_pgno_t pgno; + db_indx_t *nentriesp; + u_int32_t flags; +{ + ENV *env; + RINTERNAL *ri; + VRFY_CHILDINFO child; + VRFY_PAGEINFO *pip; + int ret, t_ret, isbad; + u_int32_t himark, i, offset, nentries; + db_indx_t *inp; + u_int8_t *pagelayout, *p; + + env = dbp->env; + isbad = 0; + memset(&child, 0, sizeof(VRFY_CHILDINFO)); + nentries = 0; + pagelayout = NULL; + + if ((ret = __db_vrfy_getpageinfo(vdp, pgno, &pip)) != 0) + return (ret); + + if (TYPE(h) != P_IRECNO) { + ret = __db_unknown_path(env, "__ram_vrfy_inp"); + goto err; + } + + himark = dbp->pgsize; + if ((ret = __os_malloc(env, dbp->pgsize, &pagelayout)) != 0) + goto err; + memset(pagelayout, 0, dbp->pgsize); + inp = P_INP(dbp, h); + for (i = 0; i < NUM_ENT(h); i++) { + if ((u_int8_t *)inp + i >= (u_int8_t *)h + himark) { + EPRINT((env, DB_STR_A("1046", + "Page %lu: entries listing %lu overlaps data", + "%lu %lu"), (u_long)pgno, (u_long)i)); + ret = DB_VERIFY_BAD; + goto err; + } + offset = inp[i]; + /* + * Check that the item offset is reasonable: it points + * somewhere after the inp array and before the end of the + * page. + */ + if (offset <= (u_int32_t)((u_int8_t *)inp + i - + (u_int8_t *)h) || + offset > (u_int32_t)(dbp->pgsize - RINTERNAL_SIZE)) { + isbad = 1; + EPRINT((env, DB_STR_A("1047", + "Page %lu: bad offset %lu at index %lu", + "%lu %lu %lu"), (u_long)pgno, (u_long)offset, + (u_long)i)); + continue; + } + + /* Update the high-water mark (what HOFFSET should be) */ + if (offset < himark) + himark = offset; + + nentries++; + + /* Make sure this RINTERNAL is not multiply referenced. */ + ri = GET_RINTERNAL(dbp, h, i); + if (pagelayout[offset] == 0) { + pagelayout[offset] = 1; + child.pgno = ri->pgno; + child.type = V_RECNO; + child.nrecs = ri->nrecs; + if ((ret = __db_vrfy_childput(vdp, pgno, &child)) != 0) + goto err; + } else { + EPRINT((env, DB_STR_A("1048", + "Page %lu: RINTERNAL structure at offset %lu referenced twice", + "%lu %lu"), (u_long)pgno, (u_long)offset)); + isbad = 1; + } + } + + for (p = pagelayout + himark; + p < pagelayout + dbp->pgsize; + p += RINTERNAL_SIZE) + if (*p != 1) { + EPRINT((env, DB_STR_A("1049", + "Page %lu: gap between items at offset %lu", + "%lu %lu"), (u_long)pgno, + (u_long)(p - pagelayout))); + isbad = 1; + } + + if ((db_indx_t)himark != HOFFSET(h)) { + EPRINT((env, DB_STR_A("1050", + "Page %lu: bad HOFFSET %lu, appears to be %lu", + "%lu %lu %lu"), (u_long)pgno, (u_long)(HOFFSET(h)), + (u_long)himark)); + isbad = 1; + } + + *nentriesp = nentries; + +err: if ((t_ret = __db_vrfy_putpageinfo(env, vdp, pip)) != 0 && ret == 0) + ret = t_ret; + if (pagelayout != NULL) + __os_free(env, pagelayout); + return ((ret == 0 && isbad == 1) ? DB_VERIFY_BAD : ret); +} + +typedef enum { VRFY_ITEM_NOTSET=0, VRFY_ITEM_BEGIN, VRFY_ITEM_END } VRFY_ITEM; + +/* + * __bam_vrfy_inp -- + * Verify that all entries in inp[] array are reasonable; + * count them. + */ +static int +__bam_vrfy_inp(dbp, vdp, h, pgno, nentriesp, flags) + DB *dbp; + VRFY_DBINFO *vdp; + PAGE *h; + db_pgno_t pgno; + db_indx_t *nentriesp; + u_int32_t flags; +{ + BKEYDATA *bk; + BOVERFLOW *bo; + ENV *env; + VRFY_CHILDINFO child; + VRFY_ITEM *pagelayout; + VRFY_PAGEINFO *pip; + u_int32_t himark, offset; /* + * These would be db_indx_ts + * but for alignment. + */ + u_int32_t i, endoff, nentries; + int isbad, initem, isdupitem, ret, t_ret; + + env = dbp->env; + isbad = isdupitem = 0; + nentries = 0; + memset(&child, 0, sizeof(VRFY_CHILDINFO)); + if ((ret = __db_vrfy_getpageinfo(vdp, pgno, &pip)) != 0) + return (ret); + + switch (TYPE(h)) { + case P_IBTREE: + case P_LBTREE: + case P_LDUP: + case P_LRECNO: + break; + default: + /* + * In the salvager, we might call this from a page which + * we merely suspect is a btree page. Otherwise, it + * shouldn't get called--if it is, that's a verifier bug. + */ + if (LF_ISSET(DB_SALVAGE)) + break; + ret = __db_unknown_path(env, "__bam_vrfy_inp"); + goto err; + } + + /* + * Loop through inp[], the array of items, until we either + * run out of entries or collide with the data. Keep track + * of h_offset in himark. + * + * For each element in inp[i], make sure it references a region + * that starts after the end of the inp array (as defined by + * NUM_ENT(h)), ends before the beginning of the page, doesn't + * overlap any other regions, and doesn't have a gap between + * it and the region immediately after it. + */ + himark = dbp->pgsize; + if ((ret = __os_calloc( + env, dbp->pgsize, sizeof(pagelayout[0]), &pagelayout)) != 0) + goto err; + for (i = 0; i < NUM_ENT(h); i++) { + switch (ret = __db_vrfy_inpitem(dbp, + h, pgno, i, 1, flags, &himark, &offset)) { + case 0: + break; + case DB_VERIFY_BAD: + isbad = 1; + continue; + case DB_VERIFY_FATAL: + isbad = 1; + goto err; + default: + DB_ASSERT(env, ret != 0); + break; + } + + /* + * We now have a plausible beginning for the item, and we know + * its length is safe. + * + * Mark the beginning and end in pagelayout so we can make sure + * items have no overlaps or gaps. + */ + bk = GET_BKEYDATA(dbp, h, i); + if (pagelayout[offset] == VRFY_ITEM_NOTSET) + pagelayout[offset] = VRFY_ITEM_BEGIN; + else if (pagelayout[offset] == VRFY_ITEM_BEGIN) { + /* + * Having two inp entries that point at the same patch + * of page is legal if and only if the page is + * a btree leaf and they're onpage duplicate keys-- + * that is, if (i % P_INDX) == 0. + */ + if ((i % P_INDX == 0) && (TYPE(h) == P_LBTREE)) { + /* Flag for later. */ + F_SET(pip, VRFY_HAS_DUPS); + + /* Bump up nentries so we don't undercount. */ + nentries++; + + /* + * We'll check to make sure the end is + * equal, too. + */ + isdupitem = 1; + } else { + isbad = 1; + EPRINT((env, DB_STR_A("1051", + "Page %lu: duplicated item %lu", + "%lu %lu"), (u_long)pgno, (u_long)i)); + } + } + + /* + * Mark the end. Its location varies with the page type + * and the item type. + * + * If the end already has a sign other than 0, do nothing-- + * it's an overlap that we'll catch later. + */ + switch (B_TYPE(bk->type)) { + case B_KEYDATA: + if (TYPE(h) == P_IBTREE) + /* It's a BINTERNAL. */ + endoff = offset + BINTERNAL_SIZE(bk->len) - 1; + else + endoff = offset + BKEYDATA_SIZE(bk->len) - 1; + break; + case B_DUPLICATE: + /* + * Flag that we have dups; we'll check whether + * that's okay during the structure check. + */ + F_SET(pip, VRFY_HAS_DUPS); + /* FALLTHROUGH */ + case B_OVERFLOW: + /* + * Overflow entries on internal pages are stored + * as the _data_ of a BINTERNAL; overflow entries + * on leaf pages are stored as the entire entry. + */ + endoff = offset + + ((TYPE(h) == P_IBTREE) ? + BINTERNAL_SIZE(BOVERFLOW_SIZE) : + BOVERFLOW_SIZE) - 1; + break; + default: + /* + * We'll complain later; for now, just mark + * a minimum. + */ + endoff = offset + BKEYDATA_SIZE(0) - 1; + break; + } + + /* + * If this is an onpage duplicate key we've seen before, + * the end had better coincide too. + */ + if (isdupitem && pagelayout[endoff] != VRFY_ITEM_END) { + EPRINT((env, DB_STR_A("1052", + "Page %lu: duplicated item %lu", + "%lu %lu"), (u_long)pgno, (u_long)i)); + isbad = 1; + } else if (pagelayout[endoff] == VRFY_ITEM_NOTSET) + pagelayout[endoff] = VRFY_ITEM_END; + isdupitem = 0; + + /* + * There should be no deleted items in a quiescent tree, + * except in recno. + */ + if (B_DISSET(bk->type) && TYPE(h) != P_LRECNO) { + isbad = 1; + EPRINT((env, DB_STR_A("1053", + "Page %lu: item %lu marked deleted", "%lu %lu"), + (u_long)pgno, (u_long)i)); + } + + /* + * Check the type and such of bk--make sure it's reasonable + * for the pagetype. + */ + switch (B_TYPE(bk->type)) { + case B_KEYDATA: + /* + * This is a normal, non-overflow BKEYDATA or BINTERNAL. + * The only thing to check is the len, and that's + * already been done. + */ + break; + case B_DUPLICATE: + if (TYPE(h) == P_IBTREE) { + isbad = 1; + EPRINT((env, DB_STR_A("1054", + "Page %lu: duplicate page referenced by internal btree page at item %lu", + "%lu %lu"), (u_long)pgno, (u_long)i)); + break; + } else if (TYPE(h) == P_LRECNO) { + isbad = 1; + EPRINT((env, DB_STR_A("1055", + "Page %lu: duplicate page referenced by recno page at item %lu", + "%lu %lu"), (u_long)pgno, (u_long)i)); + break; + } + /* FALLTHROUGH */ + case B_OVERFLOW: + bo = (TYPE(h) == P_IBTREE) ? + (BOVERFLOW *)(((BINTERNAL *)bk)->data) : + (BOVERFLOW *)bk; + + if (B_TYPE(bk->type) == B_OVERFLOW) + /* Make sure tlen is reasonable. */ + if (bo->tlen > dbp->pgsize * vdp->last_pgno) { + isbad = 1; + EPRINT((env, DB_STR_A("1056", + "Page %lu: impossible tlen %lu, item %lu", + "%lu %lu %lu"), (u_long)pgno, + (u_long)bo->tlen, (u_long)i)); + /* Don't save as a child. */ + break; + } + + if (!IS_VALID_PGNO(bo->pgno) || bo->pgno == pgno || + bo->pgno == PGNO_INVALID) { + isbad = 1; + EPRINT((env, DB_STR_A("1057", + "Page %lu: offpage item %lu has bad pgno %lu", + "%lu %lu %lu"), (u_long)pgno, (u_long)i, + (u_long)bo->pgno)); + /* Don't save as a child. */ + break; + } + + child.pgno = bo->pgno; + child.type = (B_TYPE(bk->type) == B_OVERFLOW ? + V_OVERFLOW : V_DUPLICATE); + child.tlen = bo->tlen; + if ((ret = __db_vrfy_childput(vdp, pgno, &child)) != 0) + goto err; + break; + default: + isbad = 1; + EPRINT((env, DB_STR_A("1058", + "Page %lu: item %lu of invalid type %lu", + "%lu %lu %lu"), (u_long)pgno, (u_long)i, + (u_long)B_TYPE(bk->type))); + break; + } + } + + /* + * Now, loop through and make sure the items are contiguous and + * non-overlapping. + */ + initem = 0; + for (i = himark; i < dbp->pgsize; i++) + if (initem == 0) + switch (pagelayout[i]) { + case VRFY_ITEM_NOTSET: + /* May be just for alignment. */ + if (i != DB_ALIGN(i, sizeof(u_int32_t))) + continue; + + isbad = 1; + EPRINT((env, DB_STR_A("1059", + "Page %lu: gap between items at offset %lu", + "%lu %lu"), (u_long)pgno, (u_long)i)); + /* Find the end of the gap */ + for (; pagelayout[i + 1] == VRFY_ITEM_NOTSET && + (size_t)(i + 1) < dbp->pgsize; i++) + ; + break; + case VRFY_ITEM_BEGIN: + /* We've found an item. Check its alignment. */ + if (i != DB_ALIGN(i, sizeof(u_int32_t))) { + isbad = 1; + EPRINT((env, DB_STR_A("1060", + "Page %lu: offset %lu unaligned", + "%lu %lu"), (u_long)pgno, + (u_long)i)); + } + initem = 1; + nentries++; + break; + case VRFY_ITEM_END: + /* + * We've hit the end of an item even though + * we don't think we're in one; must + * be an overlap. + */ + isbad = 1; + EPRINT((env, DB_STR_A("1061", + "Page %lu: overlapping items at offset %lu", + "%lu %lu"), (u_long)pgno, (u_long)i)); + break; + } + else + switch (pagelayout[i]) { + case VRFY_ITEM_NOTSET: + /* In the middle of an item somewhere. Okay. */ + break; + case VRFY_ITEM_END: + /* End of an item; switch to out-of-item mode.*/ + initem = 0; + break; + case VRFY_ITEM_BEGIN: + /* + * Hit a second item beginning without an + * end. Overlap. + */ + isbad = 1; + EPRINT((env, DB_STR_A("1062", + "Page %lu: overlapping items at offset %lu", + "%lu %lu"), (u_long)pgno, (u_long)i)); + break; + } + + __os_free(env, pagelayout); + + /* Verify HOFFSET. */ + if ((db_indx_t)himark != HOFFSET(h)) { + EPRINT((env, DB_STR_A("1063", + "Page %lu: bad HOFFSET %lu, appears to be %lu", + "%lu %lu %lu"), (u_long)pgno, (u_long)HOFFSET(h), + (u_long)himark)); + isbad = 1; + } + +err: if (nentriesp != NULL) + *nentriesp = nentries; + + if ((t_ret = __db_vrfy_putpageinfo(env, vdp, pip)) != 0 && ret == 0) + ret = t_ret; + + return ((isbad == 1 && ret == 0) ? DB_VERIFY_BAD : ret); +} + +/* + * __bam_vrfy_itemorder -- + * Make sure the items on a page sort correctly. + * + * Assumes that NUM_ENT(h) and inp[0]..inp[NUM_ENT(h) - 1] are + * reasonable; be sure that __bam_vrfy_inp has been called first. + * + * If ovflok is set, it also assumes that overflow page chains + * hanging off the current page have been sanity-checked, and so we + * can use __bam_cmp to verify their ordering. If it is not set, + * and we run into an overflow page, carp and return DB_VERIFY_BAD; + * we shouldn't be called if any exist. + * + * PUBLIC: int __bam_vrfy_itemorder __P((DB *, VRFY_DBINFO *, DB_THREAD_INFO *, + * PUBLIC: PAGE *, db_pgno_t, u_int32_t, int, int, u_int32_t)); + */ +int +__bam_vrfy_itemorder(dbp, vdp, ip, h, pgno, nentries, ovflok, hasdups, flags) + DB *dbp; + VRFY_DBINFO *vdp; + DB_THREAD_INFO *ip; + PAGE *h; + db_pgno_t pgno; + u_int32_t nentries; + int ovflok, hasdups; + u_int32_t flags; +{ + BINTERNAL *bi; + BKEYDATA *bk; + BOVERFLOW *bo; + BTREE *bt; + DB_MPOOLFILE *mpf; + DBC *dbc; + DBT dbta, dbtb, dup_1, dup_2, *p1, *p2, *tmp; + ENV *env; + PAGE *child; + db_pgno_t cpgno; + VRFY_PAGEINFO *pip; + db_indx_t i, *inp; + int adj, cmp, freedup_1, freedup_2, isbad, ret, t_ret; + int (*dupfunc) __P((DB *, const DBT *, const DBT *)); + int (*func) __P((DB *, const DBT *, const DBT *)); + void *buf1, *buf2, *tmpbuf; + + /* + * We need to work in the ORDERCHKONLY environment where we might + * not have a pip, but we also may need to work in contexts where + * NUM_ENT isn't safe. + */ + if (vdp != NULL) { + if ((ret = __db_vrfy_getpageinfo(vdp, pgno, &pip)) != 0) + return (ret); + nentries = pip->entries; + } else + pip = NULL; + + env = dbp->env; + ret = isbad = 0; + bo = NULL; /* Shut up compiler. */ + + memset(&dbta, 0, sizeof(DBT)); + F_SET(&dbta, DB_DBT_REALLOC); + + memset(&dbtb, 0, sizeof(DBT)); + F_SET(&dbtb, DB_DBT_REALLOC); + + buf1 = buf2 = NULL; + + DB_ASSERT(env, !LF_ISSET(DB_NOORDERCHK)); + + dupfunc = (dbp->dup_compare == NULL) ? __bam_defcmp : dbp->dup_compare; + if (TYPE(h) == P_LDUP) + func = dupfunc; + else { + func = __bam_defcmp; + if (dbp->bt_internal != NULL) { + bt = (BTREE *)dbp->bt_internal; + if (TYPE(h) == P_IBTREE && (bt->bt_compare != NULL || + dupfunc != __bam_defcmp)) { + /* + * The problem here is that we cannot + * tell the difference between an off + * page duplicate internal page and + * a main database internal page. + * Walk down the tree to figure it out. + */ + mpf = dbp->mpf; + child = h; + while (TYPE(child) == P_IBTREE) { + bi = GET_BINTERNAL(dbp, child, 0); + cpgno = bi->pgno; + if (child != h && + (ret = __memp_fput(mpf, + vdp->thread_info, child, + DB_PRIORITY_UNCHANGED)) != 0) + goto err; + if ((ret = __memp_fget(mpf, + &cpgno, vdp->thread_info, + NULL, 0, &child)) != 0) + goto err; + } + if (TYPE(child) == P_LDUP) + func = dupfunc; + else if (bt->bt_compare != NULL) + func = bt->bt_compare; + if ((ret = __memp_fput(mpf, vdp->thread_info, + child, DB_PRIORITY_UNCHANGED)) != 0) + goto err; + } else if (bt->bt_compare != NULL) + func = bt->bt_compare; + } + } + + /* + * We alternate our use of dbta and dbtb so that we can walk + * through the page key-by-key without copying a dbt twice. + * p1 is always the dbt for index i - 1, and p2 for index i. + * Reset the data pointers in case we are retrying. + */ +retry: p1 = &dbta; + p1->data = NULL; + p2 = &dbtb; + p2->data = NULL; + + /* + * Loop through the entries. nentries ought to contain the + * actual count, and so is a safe way to terminate the loop; whether + * we inc. by one or two depends on whether we're a leaf page-- + * on a leaf page, we care only about keys. On internal pages + * and LDUP pages, we want to check the order of all entries. + * + * Note that on IBTREE pages or the index page of a partitioned + * database, we start with item 1, since item 0 doesn't get looked + * at by __bam_cmp. + */ + inp = P_INP(dbp, h); + adj = (TYPE(h) == P_LBTREE) ? P_INDX : O_INDX; + for (i = (TYPE(h) == P_IBTREE || dbp->p_internal != NULL) ? adj : 0; + i < nentries; i += adj) { + /* + * Put key i-1, now in p2, into p1, by swapping DBTs and bufs. + */ + tmp = p1; + p1 = p2; + p2 = tmp; + tmpbuf = buf1; + buf1 = buf2; + buf2 = tmpbuf; + + /* + * Get key i into p2. + */ + switch (TYPE(h)) { + case P_IBTREE: + bi = GET_BINTERNAL(dbp, h, i); + if (B_TYPE(bi->type) == B_OVERFLOW) { + bo = (BOVERFLOW *)(bi->data); + goto overflow; + } else { + p2->data = bi->data; + p2->size = bi->len; + } + + /* + * The leftmost key on an internal page must be + * len 0, since it's just a placeholder and + * automatically sorts less than all keys. + * + * XXX + * This criterion does not currently hold! + * See todo list item #1686. Meanwhile, it's harmless + * to just not check for it. + */ +#if 0 + if (i == 0 && bi->len != 0) { + isbad = 1; + EPRINT((env, DB_STR_A("1064", + "Page %lu: lowest key on internal page of nonzero length", + "%lu"), (u_long)pgno)); + } +#endif + break; + case P_LBTREE: + case P_LDUP: + bk = GET_BKEYDATA(dbp, h, i); + if (B_TYPE(bk->type) == B_OVERFLOW) { + bo = (BOVERFLOW *)bk; + goto overflow; + } else { + p2->data = bk->data; + p2->size = bk->len; + } + break; + default: + /* + * This means our caller screwed up and sent us + * an inappropriate page. + */ + ret = __db_unknown_path(env, "__bam_vrfy_itemorder"); + goto err; + } + + if (0) { + /* + * If ovflok != 1, we can't safely go chasing + * overflow pages with the normal routines now; + * they might be unsafe or nonexistent. Mark this + * page as incomplete and return. + * + * Note that we don't need to worry about freeing + * buffers, since they can't have been allocated + * if overflow items are unsafe. + */ +overflow: if (!ovflok) { + if (pip != NULL) + F_SET(pip, VRFY_INCOMPLETE); + goto err; + } + + /* + * Overflow items are safe to chase. Do so. + * Fetch the overflow item into p2->data, + * NULLing it or reallocing it as appropriate. + * + * (We set p2->data to buf2 before the call + * so we're sure to realloc if we can and if p2 + * was just pointing at a non-overflow item.) + */ + p2->data = buf2; + if ((ret = __db_cursor_int(dbp, ip, NULL, DB_BTREE, + PGNO_INVALID, 0, DB_LOCK_INVALIDID, &dbc)) != 0) + goto err; + if ((ret = __db_goff(dbc, + p2, bo->tlen, bo->pgno, NULL, NULL)) != 0) { + isbad = 1; + EPRINT((env, DB_STR_A("1065", + "Page %lu: error %lu in fetching overflow item %lu", + "%lu %lu %lu"), (u_long)pgno, (u_long)ret, + (u_long)i)); + } + /* In case it got realloc'ed and thus changed. */ + buf2 = p2->data; + } + + /* Compare with the last key. */ + if (p1->data != NULL && p2->data != NULL) { + cmp = inp[i] == inp[i - adj] ? 0 : func(dbp, p1, p2); + + /* comparison succeeded */ + if (cmp > 0) { + /* + * If we are looking at an internal page, we + * don't know whether it is part of the main + * database or in an off-page-duplicate tree. + * If the main comparator fails, retry with + * the duplicate comparator. + */ + if (TYPE(h) == P_IBTREE && func != dupfunc) { + func = dupfunc; + goto retry; + } + + isbad = 1; + EPRINT((env, DB_STR_A("1066", + "Page %lu: out-of-order key at entry %lu", + "%lu %lu"), (u_long)pgno, (u_long)i)); + /* proceed */ + } else if (cmp == 0) { + if (inp[i] != inp[i - adj]) { + /* See above. */ + if (TYPE(h) == P_IBTREE && + func != dupfunc) { + func = dupfunc; + goto retry; + } + isbad = 1; + EPRINT((env, DB_STR_A("1067", + "Page %lu: non-dup dup key at entry %lu", + "%lu %lu"), (u_long)pgno, + (u_long)i)); + } + /* + * If they compared equally, this + * had better be a (sub)database with dups. + * Mark it so we can check during the + * structure check. + */ + if (pip != NULL) + F_SET(pip, VRFY_HAS_DUPS); + else if (hasdups == 0) { + /* See above. */ + if (TYPE(h) == P_IBTREE && + func != dupfunc) { + func = dupfunc; + goto retry; + } + isbad = 1; + EPRINT((env, DB_STR_A("1068", + "Page %lu: database with no duplicates has duplicated keys", + "%lu"), (u_long)pgno)); + } + + /* + * If we're a btree leaf, check to see + * if the data items of these on-page dups are + * in sorted order. If not, flag this, so + * that we can make sure during the + * structure checks that the DUPSORT flag + * is unset. + * + * At this point i points to a duplicate key. + * Compare the datum before it (same key) + * to the datum after it, i.e. i-1 to i+1. + */ + if (TYPE(h) == P_LBTREE) { + /* + * Unsafe; continue and we'll pick + * up the bogus nentries later. + */ + if (i + 1 >= (db_indx_t)nentries) + continue; + + /* + * We don't bother with clever memory + * management with on-page dups, + * as it's only really a big win + * in the overflow case, and overflow + * dups are probably (?) rare. + */ + if (((ret = __bam_safe_getdata(dbp, + ip, h, i - 1, ovflok, + &dup_1, &freedup_1)) != 0) || + ((ret = __bam_safe_getdata(dbp, + ip, h, i + 1, ovflok, + &dup_2, &freedup_2)) != 0)) + goto err; + + /* + * If either of the data are NULL, + * it's because they're overflows and + * it's not safe to chase them now. + * Mark an incomplete and return. + */ + if (dup_1.data == NULL || + dup_2.data == NULL) { + DB_ASSERT(env, !ovflok); + if (pip != NULL) + F_SET(pip, + VRFY_INCOMPLETE); + goto err; + } + + /* + * If the dups are out of order, + * flag this. It's not an error + * until we do the structure check + * and see whether DUPSORT is set. + */ + if (dupfunc(dbp, &dup_1, &dup_2) > 0 && + pip != NULL) + F_SET(pip, VRFY_DUPS_UNSORTED); + + if (freedup_1) + __os_ufree(env, dup_1.data); + if (freedup_2) + __os_ufree(env, dup_2.data); + } + } + } + } + +err: if (pip != NULL && ((t_ret = + __db_vrfy_putpageinfo(env, vdp, pip)) != 0) && ret == 0) + ret = t_ret; + + if (buf1 != NULL) + __os_ufree(env, buf1); + if (buf2 != NULL) + __os_ufree(env, buf2); + + return ((ret == 0 && isbad == 1) ? DB_VERIFY_BAD : ret); +} + +/* + * __bam_vrfy_structure -- + * Verify the tree structure of a btree database (including the master + * database containing subdbs). + * + * PUBLIC: int __bam_vrfy_structure __P((DB *, VRFY_DBINFO *, db_pgno_t, + * PUBLIC: void *, void *, u_int32_t)); + */ +int +__bam_vrfy_structure(dbp, vdp, meta_pgno, lp, rp, flags) + DB *dbp; + VRFY_DBINFO *vdp; + db_pgno_t meta_pgno; + void *lp, *rp; + u_int32_t flags; +{ + DB *pgset; + ENV *env; + VRFY_PAGEINFO *mip, *rip; + db_pgno_t root, p; + int t_ret, ret; + u_int32_t nrecs, level, relen, stflags; + + env = dbp->env; + mip = rip = 0; + pgset = vdp->pgset; + + if ((ret = __db_vrfy_getpageinfo(vdp, meta_pgno, &mip)) != 0) + return (ret); + + if ((ret = __db_vrfy_pgset_get(pgset, + vdp->thread_info, vdp->txn, meta_pgno, (int *)&p)) != 0) + goto err; + if (p != 0) { + EPRINT((env, DB_STR_A("1069", + "Page %lu: btree metadata page observed twice", + "%lu"), (u_long)meta_pgno)); + ret = DB_VERIFY_BAD; + goto err; + } + if ((ret = __db_vrfy_pgset_inc( + pgset, vdp->thread_info, vdp->txn, meta_pgno)) != 0) + goto err; + + root = mip->root; + + if (root == 0) { + EPRINT((env, DB_STR_A("1070", + "Page %lu: btree metadata page has no root", + "%lu"), (u_long)meta_pgno)); + ret = DB_VERIFY_BAD; + goto err; + } + + if ((ret = __db_vrfy_getpageinfo(vdp, root, &rip)) != 0) + goto err; + + switch (rip->type) { + case P_IBTREE: + case P_LBTREE: + stflags = flags | DB_ST_TOPLEVEL; + if (F_ISSET(mip, VRFY_HAS_DUPS)) + stflags |= DB_ST_DUPOK; + if (F_ISSET(mip, VRFY_HAS_DUPSORT)) + stflags |= DB_ST_DUPSORT; + if (F_ISSET(mip, VRFY_HAS_RECNUMS)) + stflags |= DB_ST_RECNUM; + ret = __bam_vrfy_subtree(dbp, + vdp, root, lp, rp, stflags, NULL, NULL, NULL); + break; + case P_IRECNO: + case P_LRECNO: + stflags = + flags | DB_ST_RECNUM | DB_ST_IS_RECNO | DB_ST_TOPLEVEL; + if (mip->re_len > 0) + stflags |= DB_ST_RELEN; + if ((ret = __bam_vrfy_subtree(dbp, vdp, + root, NULL, NULL, stflags, &level, &nrecs, &relen)) != 0) + goto err; + /* + * Even if mip->re_len > 0, re_len may come back zero if the + * tree is empty. It should be okay to just skip the check in + * this case, as if there are any non-deleted keys at all, + * that should never happen. + */ + if (mip->re_len > 0 && relen > 0 && mip->re_len != relen) { + EPRINT((env, DB_STR_A("1071", + "Page %lu: recno database has bad re_len %lu", + "%lu %lu"), (u_long)meta_pgno, (u_long)relen)); + ret = DB_VERIFY_BAD; + goto err; + } + ret = 0; + break; + case P_LDUP: + EPRINT((env, DB_STR_A("1072", + "Page %lu: duplicate tree referenced from metadata page", + "%lu"), (u_long)meta_pgno)); + ret = DB_VERIFY_BAD; + break; + default: + EPRINT((env, DB_STR_A("1073", + "Page %lu: btree root of incorrect type %lu on metadata page", + "%lu %lu"), (u_long)meta_pgno, (u_long)rip->type)); + ret = DB_VERIFY_BAD; + break; + } + +err: if (mip != NULL && ((t_ret = + __db_vrfy_putpageinfo(env, vdp, mip)) != 0) && ret == 0) + ret = t_ret; + if (rip != NULL && ((t_ret = + __db_vrfy_putpageinfo(env, vdp, rip)) != 0) && ret == 0) + ret = t_ret; + return (ret); +} + +/* + * __bam_vrfy_subtree-- + * Verify a subtree (or entire) btree with specified root. + * + * Note that this is public because it must be called to verify + * offpage dup trees, including from hash. + * + * PUBLIC: int __bam_vrfy_subtree __P((DB *, VRFY_DBINFO *, db_pgno_t, void *, + * PUBLIC: void *, u_int32_t, u_int32_t *, u_int32_t *, u_int32_t *)); + */ +int +__bam_vrfy_subtree(dbp, vdp, pgno, l, r, flags, levelp, nrecsp, relenp) + DB *dbp; + VRFY_DBINFO *vdp; + db_pgno_t pgno; + void *l, *r; + u_int32_t flags, *levelp, *nrecsp, *relenp; +{ + BINTERNAL *li, *ri; + DB *pgset; + DBC *cc; + DB_MPOOLFILE *mpf; + ENV *env; + PAGE *h; + VRFY_CHILDINFO *child; + VRFY_PAGEINFO *pip; + db_indx_t i; + db_pgno_t next_pgno, prev_pgno; + db_recno_t child_nrecs, nrecs; + u_int32_t child_level, child_relen, j, level, relen, stflags; + u_int8_t leaf_type; + int (*func) __P((DB *, const DBT *, const DBT *)); + int isbad, p, ret, t_ret, toplevel; + + if (levelp != NULL) /* Don't leave uninitialized on error. */ + *levelp = 0; + if (nrecsp != NULL) + *nrecsp = 0; + + env = dbp->env; + mpf = dbp->mpf; + h = NULL; + next_pgno = prev_pgno = PGNO_INVALID; + nrecs = 0; + relen = 0; + leaf_type = P_INVALID; + isbad = ret = 0; + + /* Provide feedback on our progress to the application. */ + if (!LF_ISSET(DB_SALVAGE)) + __db_vrfy_struct_feedback(dbp, vdp); + + if ((ret = __db_vrfy_getpageinfo(vdp, pgno, &pip)) != 0) + return (ret); + + cc = NULL; + level = pip->bt_level; + + toplevel = LF_ISSET(DB_ST_TOPLEVEL) ? 1 : 0; + LF_CLR(DB_ST_TOPLEVEL); + + /* + * If this is the root, initialize the vdp's prev- and next-pgno + * accounting. + * + * For each leaf page we hit, we'll want to make sure that + * vdp->prev_pgno is the same as pip->prev_pgno and vdp->next_pgno is + * our page number. Then, we'll set vdp->next_pgno to pip->next_pgno + * and vdp->prev_pgno to our page number, and the next leaf page in + * line should be able to do the same verification. + */ + if (toplevel) { + /* + * Cache the values stored in the vdp so that if we're an + * auxiliary tree such as an off-page duplicate set, our + * caller's leaf page chain doesn't get lost. + */ + prev_pgno = vdp->prev_pgno; + next_pgno = vdp->next_pgno; + leaf_type = vdp->leaf_type; + vdp->next_pgno = vdp->prev_pgno = PGNO_INVALID; + vdp->leaf_type = P_INVALID; + } + + /* + * We are recursively descending a btree, starting from the root + * and working our way out to the leaves. + * + * There are four cases we need to deal with: + * 1. pgno is a recno leaf page. Any children are overflows. + * 2. pgno is a duplicate leaf page. Any children + * are overflow pages; traverse them, and then return + * level and nrecs. + * 3. pgno is an ordinary leaf page. Check whether dups are + * allowed, and if so, traverse any off-page dups or + * overflows. Then return nrecs and level. + * 4. pgno is a recno internal page. Recursively check any + * child pages, making sure their levels are one lower + * and their nrecs sum to ours. + * 5. pgno is a btree internal page. Same as #4, plus we + * must verify that for each pair of BINTERNAL entries + * N and N+1, the leftmost item on N's child sorts + * greater than N, and the rightmost item on N's child + * sorts less than N+1. + * + * Furthermore, in any sorted page type (P_LDUP, P_LBTREE, P_IBTREE), + * we need to verify the internal sort order is correct if, + * due to overflow items, we were not able to do so earlier. + */ + switch (pip->type) { + case P_LRECNO: + case P_LDUP: + case P_LBTREE: + /* + * Cases 1, 2 and 3. + * + * We're some sort of leaf page; verify + * that our linked list of leaves is consistent. + */ + if (vdp->leaf_type == P_INVALID) { + /* + * First leaf page. Set the type that all its + * successors should be, and verify that our prev_pgno + * is PGNO_INVALID. + */ + vdp->leaf_type = pip->type; + if (pip->prev_pgno != PGNO_INVALID) + goto bad_prev; + } else { + /* + * Successor leaf page. Check our type, the previous + * page's next_pgno, and our prev_pgno. + */ + if (pip->type != vdp->leaf_type) { + isbad = 1; + EPRINT((env, DB_STR_A("1074", + "Page %lu: unexpected page type %lu found in leaf chain (expected %lu)", + "%lu %lu %lu"), (u_long)pip->pgno, + (u_long)pip->type, + (u_long)vdp->leaf_type)); + } + + /* + * Don't do the prev/next_pgno checks if we've lost + * leaf pages due to another corruption. + */ + if (!F_ISSET(vdp, VRFY_LEAFCHAIN_BROKEN)) { + if (pip->pgno != vdp->next_pgno) { + isbad = 1; + EPRINT((env, DB_STR_A("1075", + "Page %lu: incorrect next_pgno %lu found in leaf chain (should be %lu)", + "%lu %lu %lu"), + (u_long)vdp->prev_pgno, + (u_long)vdp->next_pgno, + (u_long)pip->pgno)); + } + if (pip->prev_pgno != vdp->prev_pgno) { +bad_prev: isbad = 1; + EPRINT((env, DB_STR_A("1076", + "Page %lu: incorrect prev_pgno %lu found in leaf chain (should be %lu)", + "%lu %lu %lu"), + (u_long)pip->pgno, + (u_long)pip->prev_pgno, + (u_long)vdp->prev_pgno)); + } + } + } + vdp->prev_pgno = pip->pgno; + vdp->next_pgno = pip->next_pgno; + F_CLR(vdp, VRFY_LEAFCHAIN_BROKEN); + + /* + * Overflow pages are common to all three leaf types; + * traverse the child list, looking for overflows. + */ + if ((ret = __db_vrfy_childcursor(vdp, &cc)) != 0) + goto err; + for (ret = __db_vrfy_ccset(cc, pgno, &child); ret == 0; + ret = __db_vrfy_ccnext(cc, &child)) + if (child->type == V_OVERFLOW && + (ret = __db_vrfy_ovfl_structure(dbp, vdp, + child->pgno, child->tlen, + flags | DB_ST_OVFL_LEAF)) != 0) { + if (ret == DB_VERIFY_BAD) + isbad = 1; + else + goto done; + } + + if ((ret = __db_vrfy_ccclose(cc)) != 0) + goto err; + cc = NULL; + + /* Case 1 */ + if (pip->type == P_LRECNO) { + if (!LF_ISSET(DB_ST_IS_RECNO) && + !(LF_ISSET(DB_ST_DUPOK) && + !LF_ISSET(DB_ST_DUPSORT))) { + isbad = 1; + EPRINT((env, DB_STR_A("1077", + "Page %lu: recno leaf page non-recno tree", + "%lu"), (u_long)pgno)); + goto done; + } + goto leaf; + } else if (LF_ISSET(DB_ST_IS_RECNO)) { + /* + * It's a non-recno leaf. Had better not be a recno + * subtree. + */ + isbad = 1; + EPRINT((env, DB_STR_A("1078", + "Page %lu: non-recno leaf page in recno tree", + "%lu"), (u_long)pgno)); + goto done; + } + + /* Case 2--no more work. */ + if (pip->type == P_LDUP) + goto leaf; + + /* Case 3 */ + + /* Check if we have any dups. */ + if (F_ISSET(pip, VRFY_HAS_DUPS)) { + /* If dups aren't allowed in this btree, trouble. */ + if (!LF_ISSET(DB_ST_DUPOK)) { + isbad = 1; + EPRINT((env, DB_STR_A("1079", + "Page %lu: duplicates in non-dup btree", + "%lu"), (u_long)pgno)); + } else { + /* + * We correctly have dups. If any are off-page, + * traverse those btrees recursively. + */ + if ((ret = + __db_vrfy_childcursor(vdp, &cc)) != 0) + goto err; + for (ret = __db_vrfy_ccset(cc, pgno, &child); + ret == 0; + ret = __db_vrfy_ccnext(cc, &child)) { + stflags = + flags | DB_ST_RECNUM | DB_ST_DUPSET; + /* Skip any overflow entries. */ + if (child->type == V_DUPLICATE) { + if ((ret = __db_vrfy_duptype( + dbp, vdp, child->pgno, + stflags)) != 0) { + isbad = 1; + /* Next child. */ + continue; + } + if ((ret = __bam_vrfy_subtree( + dbp, vdp, child->pgno, + NULL, NULL, + stflags | DB_ST_TOPLEVEL, + NULL, NULL, NULL)) != 0) { + if (ret == + DB_VERIFY_BAD) + isbad = 1; + else + goto err; + } + } + } + + if ((ret = __db_vrfy_ccclose(cc)) != 0) + goto err; + cc = NULL; + + /* + * If VRFY_DUPS_UNSORTED is set, + * DB_ST_DUPSORT had better not be. + */ + if (F_ISSET(pip, VRFY_DUPS_UNSORTED) && + LF_ISSET(DB_ST_DUPSORT)) { + isbad = 1; + EPRINT((env, DB_STR_A("1080", + "Page %lu: unsorted duplicate set in sorted-dup database", + "%lu"), (u_long)pgno)); + } + } + } + goto leaf; + case P_IBTREE: + case P_IRECNO: + /* We handle these below. */ + break; + default: + /* + * If a P_IBTREE or P_IRECNO contains a reference to an + * invalid page, we'll wind up here; handle it gracefully. + * Note that the code at the "done" label assumes that the + * current page is a btree/recno one of some sort; this + * is not the case here, so we goto err. + * + * If the page is entirely zeroed, its pip->type will be a lie + * (we assumed it was a hash page, as they're allowed to be + * zeroed); handle this case specially. + */ + if (F_ISSET(pip, VRFY_IS_ALLZEROES)) + ZEROPG_ERR_PRINT(env, pgno, DB_STR_P( + "btree or recno page")); + else + EPRINT((env, DB_STR_A("1081", + "Page %lu: btree or recno page is of inappropriate type %lu", + "%lu %lu"), (u_long)pgno, (u_long)pip->type)); + + /* + * We probably lost a leaf page (or more if this was an + * internal page) from our prev/next_pgno chain. Flag + * that this is expected; we don't want or need to + * spew error messages about erroneous prev/next_pgnos, + * since that's probably not the real problem. + */ + F_SET(vdp, VRFY_LEAFCHAIN_BROKEN); + + ret = DB_VERIFY_BAD; + goto err; + } + + /* + * Cases 4 & 5: This is a btree or recno internal page. For each child, + * recurse, keeping a running count of nrecs and making sure the level + * is always reasonable. + */ + if ((ret = __db_vrfy_childcursor(vdp, &cc)) != 0) + goto err; + for (ret = __db_vrfy_ccset(cc, pgno, &child); ret == 0; + ret = __db_vrfy_ccnext(cc, &child)) + if (child->type == V_RECNO) { + if (pip->type != P_IRECNO) { + ret = __db_unknown_path( + env, "__bam_vrfy_subtree"); + goto err; + } + if ((ret = __bam_vrfy_subtree(dbp, vdp, child->pgno, + NULL, NULL, flags, &child_level, &child_nrecs, + &child_relen)) != 0) { + if (ret == DB_VERIFY_BAD) + isbad = 1; + else + goto done; + } + + if (LF_ISSET(DB_ST_RELEN)) { + if (relen == 0) + relen = child_relen; + /* + * child_relen may be zero if the child subtree + * is empty. + */ + else if (child_relen > 0 && + relen != child_relen) { + isbad = 1; + EPRINT((env, DB_STR_A("1082", + "Page %lu: recno page returned bad re_len %lu", + "%lu %lu"), (u_long)child->pgno, + (u_long)child_relen)); + } + if (relenp) + *relenp = relen; + } + if (LF_ISSET(DB_ST_RECNUM)) { + if (child->nrecs != child_nrecs) { + isbad = 1; + EPRINT((env, DB_STR_A("1083", + "Page %lu: record count incorrect: actual %lu, in record %lu", + "%lu %lu %lu"), + (u_long)child->pgno, + (u_long)child_nrecs, + (u_long)child->nrecs)); + } + nrecs += child_nrecs; + } + if (isbad == 0 && level != child_level + 1) { + isbad = 1; + EPRINT((env, DB_STR_A("1084", + "Page %lu: recno level incorrect: got %lu, expected %lu", + "%lu %lu %lu"), + (u_long)child->pgno, (u_long)child_level, + (u_long)(level - 1))); + } + } else if (child->type == V_OVERFLOW) { + /* + * It is possible for one internal page to reference + * a single overflow page twice, if all the items + * in the subtree referenced by slot 0 are deleted, + * then a similar number of items are put back + * before the key that formerly had been in slot 1. + * + * (Btree doesn't look at the key in slot 0, so the + * fact that the key formerly at slot 1 is the "wrong" + * parent of the stuff in the slot 0 subtree isn't + * really incorrect.) + * + * __db_vrfy_ovfl_structure is designed to be + * efficiently called multiple times for multiple + * references; call it here as many times as is + * appropriate. + */ + + /* Otherwise, __db_vrfy_childput would be broken. */ + DB_ASSERT(env, child->refcnt >= 1); + + /* + * An overflow referenced more than twice here + * shouldn't happen. + */ + if (child->refcnt > 2) { + isbad = 1; + EPRINT((env, DB_STR_A("1085", + "Page %lu: overflow page %lu referenced more than twice from internal page", + "%lu %lu"), (u_long)pgno, + (u_long)child->pgno)); + } else + for (j = 0; j < child->refcnt; j++) + if ((ret = __db_vrfy_ovfl_structure(dbp, + vdp, child->pgno, child->tlen, + flags)) != 0) { + if (ret == DB_VERIFY_BAD) + isbad = 1; + else + goto done; + } + } + + if ((ret = __db_vrfy_ccclose(cc)) != 0) + goto err; + cc = NULL; + + /* We're done with case 4. */ + if (pip->type == P_IRECNO) + goto done; + + /* + * Case 5. Btree internal pages. + * As described above, we need to iterate through all the + * items on the page and make sure that our children sort appropriately + * with respect to them. + * + * For each entry, li will be the "left-hand" key for the entry + * itself, which must sort lower than all entries on its child; + * ri will be the key to its right, which must sort greater. + */ + if (h == NULL && + (ret = __memp_fget(mpf, &pgno, vdp->thread_info, NULL, 0, &h)) != 0) + goto err; + for (i = 0; i < pip->entries; i += O_INDX) { + li = GET_BINTERNAL(dbp, h, i); + ri = (i + O_INDX < pip->entries) ? + GET_BINTERNAL(dbp, h, i + O_INDX) : r; + + /* + * The leftmost key is forcibly sorted less than all entries, + * so don't bother passing it. + */ + if ((ret = __bam_vrfy_subtree(dbp, vdp, li->pgno, + i == 0 ? NULL : li, ri, flags, &child_level, + &child_nrecs, NULL)) != 0) { + if (ret == DB_VERIFY_BAD) + isbad = 1; + else + goto done; + } + + if (LF_ISSET(DB_ST_RECNUM)) { + /* + * Keep a running tally on the actual record count so + * we can return it to our parent (if we have one) or + * compare it to the NRECS field if we're a root page. + */ + nrecs += child_nrecs; + + /* + * Make sure the actual record count of the child + * is equal to the value in the BINTERNAL structure. + */ + if (li->nrecs != child_nrecs) { + isbad = 1; + EPRINT((env, DB_STR_A("1086", + "Page %lu: item %lu has incorrect record count of %lu, should be %lu", + "%lu %lu %lu %lu"), (u_long)pgno, + (u_long)i, (u_long)li->nrecs, + (u_long)child_nrecs)); + } + } + + if (level != child_level + 1) { + isbad = 1; + EPRINT((env, DB_STR_A("1087", + "Page %lu: Btree level incorrect: got %lu, expected %lu", + "%lu %lu %lu"), (u_long)li->pgno, + (u_long)child_level, (u_long)(level - 1))); + } + } + + if (0) { +leaf: level = LEAFLEVEL; + if (LF_ISSET(DB_ST_RECNUM)) + nrecs = pip->rec_cnt; + + /* XXX + * We should verify that the record count on a leaf page + * is the sum of the number of keys and the number of + * records in its off-page dups. This requires looking + * at the page again, however, and it may all be changing + * soon, so for now we don't bother. + */ + + if (LF_ISSET(DB_ST_RELEN) && relenp) + *relenp = pip->re_len; + } +done: if (F_ISSET(pip, VRFY_INCOMPLETE) && isbad == 0 && ret == 0) { + /* + * During the page-by-page pass, item order verification was + * not finished due to the presence of overflow items. If + * isbad == 0, though, it's now safe to do so, as we've + * traversed any child overflow pages. Do it. + */ + if (h == NULL && (ret = __memp_fget(mpf, &pgno, + vdp->thread_info, NULL, 0, &h)) != 0) + goto err; + if ((ret = __bam_vrfy_itemorder(dbp, + vdp, vdp->thread_info, h, pgno, 0, 1, 0, flags)) != 0) + goto err; + F_CLR(pip, VRFY_INCOMPLETE); + } + + /* + * It's possible to get to this point with a page that has no + * items, but without having detected any sort of failure yet. + * Having zero items is legal if it's a leaf--it may be the + * root page in an empty tree, or the tree may have been + * modified with the DB_REVSPLITOFF flag set (there's no way + * to tell from what's on disk). For an internal page, + * though, having no items is a problem (all internal pages + * must have children). + */ + if (isbad == 0 && ret == 0) { + if (h == NULL && (ret = __memp_fget(mpf, &pgno, + vdp->thread_info, NULL, 0, &h)) != 0) + goto err; + + if (NUM_ENT(h) == 0 && ISINTERNAL(h)) { + isbad = 1; + EPRINT((env, DB_STR_A("1088", + "Page %lu: internal page is empty and should not be", + "%lu"), (u_long)pgno)); + goto err; + } + } + + /* + * Our parent has sent us BINTERNAL pointers to parent records + * so that we can verify our place with respect to them. If it's + * appropriate--we have a default sort function--verify this. + */ + if (isbad == 0 && ret == 0 && !LF_ISSET(DB_NOORDERCHK) && + pip->type != P_IRECNO && pip->type != P_LRECNO) { + if (h == NULL && (ret = __memp_fget(mpf, &pgno, + vdp->thread_info, NULL, 0, &h)) != 0) + goto err; + + /* + * __bam_vrfy_treeorder needs to know what comparison function + * to use. If DB_ST_DUPSET is set, we're in a duplicate tree + * and we use the duplicate comparison function; otherwise, + * use the btree one. If unset, use the default, of course. + */ + func = LF_ISSET(DB_ST_DUPSET) ? dbp->dup_compare : + ((BTREE *)dbp->bt_internal)->bt_compare; + if (func == NULL) + func = __bam_defcmp; + + if ((ret = __bam_vrfy_treeorder(dbp, + vdp->thread_info, h, l, r, func, flags)) != 0) { + if (ret == DB_VERIFY_BAD) + isbad = 1; + else + goto err; + } + } + + /* + * This is guaranteed to succeed for leaf pages, but no harm done. + * + * Internal pages below the top level do not store their own + * record numbers, so we skip them. + */ + if (LF_ISSET(DB_ST_RECNUM) && nrecs != pip->rec_cnt && toplevel) { + isbad = 1; + EPRINT((env, DB_STR_A("1089", + "Page %lu: bad record count: has %lu records, claims %lu", + "%lu %lu %lu"), (u_long)pgno, (u_long)nrecs, + (u_long)pip->rec_cnt)); + } + + if (levelp) + *levelp = level; + if (nrecsp) + *nrecsp = nrecs; + + pgset = vdp->pgset; + if ((ret = __db_vrfy_pgset_get(pgset, + vdp->thread_info, vdp->txn, pgno, &p)) != 0) + goto err; + if (p != 0) { + isbad = 1; + EPRINT((env, DB_STR_A("1090", + "Page %lu: linked twice", "%lu"), (u_long)pgno)); + } else if ((ret = + __db_vrfy_pgset_inc(pgset, vdp->thread_info, vdp->txn, pgno)) != 0) + goto err; + + if (toplevel) + /* + * The last page's next_pgno in the leaf chain should have been + * PGNO_INVALID. + */ + if (vdp->next_pgno != PGNO_INVALID) { + isbad = 1; + EPRINT((env, DB_STR_A("1091", + "Page %lu: unterminated leaf chain", + "%lu"), (u_long)vdp->prev_pgno)); + } + +err: if (toplevel) { + /* Restore our caller's settings. */ + vdp->next_pgno = next_pgno; + vdp->prev_pgno = prev_pgno; + vdp->leaf_type = leaf_type; + } + + if (h != NULL && (t_ret = __memp_fput(mpf, + vdp->thread_info, h, DB_PRIORITY_UNCHANGED)) != 0 && ret == 0) + ret = t_ret; + if ((t_ret = __db_vrfy_putpageinfo(env, vdp, pip)) != 0 && ret == 0) + ret = t_ret; + if (cc != NULL && ((t_ret = __db_vrfy_ccclose(cc)) != 0) && ret == 0) + ret = t_ret; + return ((ret == 0 && isbad == 1) ? DB_VERIFY_BAD : ret); +} + +/* + * __bam_vrfy_treeorder -- + * Verify that the lowest key on a page sorts greater than the + * BINTERNAL which points to it (lp), and the highest key + * sorts less than the BINTERNAL above that (rp). + * + * If lp is NULL, this means that it was the leftmost key on the + * parent, which (regardless of sort function) sorts less than + * all keys. No need to check it. + * + * If rp is NULL, lp was the highest key on the parent, so there's + * no higher key we must sort less than. + */ +static int +__bam_vrfy_treeorder(dbp, ip, h, lp, rp, func, flags) + DB *dbp; + DB_THREAD_INFO *ip; + PAGE *h; + BINTERNAL *lp, *rp; + int (*func) __P((DB *, const DBT *, const DBT *)); + u_int32_t flags; +{ + BOVERFLOW *bo; + DBC *dbc; + DBT dbt; + ENV *env; + db_indx_t last; + int ret, cmp; + + env = dbp->env; + memset(&dbt, 0, sizeof(DBT)); + F_SET(&dbt, DB_DBT_MALLOC); + ret = 0; + + /* + * Empty pages are sorted correctly by definition. We check + * to see whether they ought to be empty elsewhere; leaf + * pages legally may be. + */ + if (NUM_ENT(h) == 0) + return (0); + + switch (TYPE(h)) { + case P_IBTREE: + case P_LDUP: + last = NUM_ENT(h) - O_INDX; + break; + case P_LBTREE: + last = NUM_ENT(h) - P_INDX; + break; + default: + return (__db_unknown_path(env, "__bam_vrfy_treeorder")); + } + + /* Populate a dummy cursor. */ + if ((ret = __db_cursor_int(dbp, ip, NULL, DB_BTREE, + PGNO_INVALID, 0, DB_LOCK_INVALIDID, &dbc)) != 0) + return (ret); + /* + * The key on page h, the child page, is more likely to be + * an overflow page, so we pass its offset, rather than lp/rp's, + * into __bam_cmp. This will take advantage of __db_moff. + */ + + /* + * Skip first-item check if we're an internal page--the first + * entry on an internal page is treated specially by __bam_cmp, + * so what's on the page shouldn't matter. (Plus, since we're passing + * our page and item 0 as to __bam_cmp, we'll sort before our + * parent and falsely report a failure.) + */ + if (lp != NULL && TYPE(h) != P_IBTREE) { + if ((ret = __db_cursor_int(dbp, ip, NULL, DB_BTREE, + PGNO_INVALID, 0, DB_LOCK_INVALIDID, &dbc)) != 0) + return (ret); + if (lp->type == B_KEYDATA) { + dbt.data = lp->data; + dbt.size = lp->len; + } else if (lp->type == B_OVERFLOW) { + bo = (BOVERFLOW *)lp->data; + if ((ret = __db_goff(dbc, &dbt, + bo->tlen, bo->pgno, NULL, NULL)) != 0) + return (ret); + } else + return ( + __db_unknown_path(env, "__bam_vrfy_treeorder")); + + /* On error, fall through, free if needed, and return. */ + if ((ret = __bam_cmp(dbc, &dbt, h, 0, func, &cmp)) == 0) { + if (cmp > 0) { + EPRINT((env, DB_STR_A("1092", + "Page %lu: first item on page sorted greater than parent entry", + "%lu"), (u_long)PGNO(h))); + ret = DB_VERIFY_BAD; + } + } else + EPRINT((env, DB_STR_A("1093", + "Page %lu: first item on page had comparison error", + "%lu"), (u_long)PGNO(h))); + + if (dbt.data != lp->data) + __os_ufree(env, dbt.data); + if (ret != 0) + return (ret); + } + + if (rp != NULL) { + if (rp->type == B_KEYDATA) { + dbt.data = rp->data; + dbt.size = rp->len; + } else if (rp->type == B_OVERFLOW) { + bo = (BOVERFLOW *)rp->data; + if ((ret = __db_goff(dbc, &dbt, + bo->tlen, bo->pgno, NULL, NULL)) != 0) + return (ret); + } else + return ( + __db_unknown_path(env, "__bam_vrfy_treeorder")); + + /* On error, fall through, free if needed, and return. */ + if ((ret = __bam_cmp(dbc, &dbt, h, last, func, &cmp)) == 0) { + if (cmp < 0) { + EPRINT((env, DB_STR_A("1094", + "Page %lu: last item on page sorted greater than parent entry", + "%lu"), (u_long)PGNO(h))); + ret = DB_VERIFY_BAD; + } + } else + EPRINT((env, DB_STR_A("1095", + "Page %lu: last item on page had comparison error", + "%lu"), (u_long)PGNO(h))); + + if (dbt.data != rp->data) + __os_ufree(env, dbt.data); + } + + return (ret); +} + +/* + * __bam_salvage -- + * Safely dump out anything that looks like a key on an alleged + * btree leaf page, also mark overflow pages as seen. For internal btree + * pages, just mark any overflow pages as seen. + * + * PUBLIC: int __bam_salvage __P((DB *, VRFY_DBINFO *, + * PUBLIC: db_pgno_t, u_int32_t, PAGE *, void *, + * PUBLIC: int (*)(void *, const void *), DBT *, u_int32_t)); + */ +int +__bam_salvage(dbp, vdp, pgno, pgtype, h, handle, callback, key, flags) + DB *dbp; + VRFY_DBINFO *vdp; + db_pgno_t pgno; + u_int32_t pgtype; + PAGE *h; + void *handle; + int (*callback) __P((void *, const void *)); + DBT *key; + u_int32_t flags; +{ + BKEYDATA *bk; + BOVERFLOW *bo; + DBT dbt, repldbt, unknown_key, unknown_data; + ENV *env; + VRFY_ITEM *pgmap; + db_indx_t i, last, beg, end, *inp; + db_pgno_t ovflpg; + u_int32_t himark, ovfl_bufsz; + void *ovflbuf; + int adj, ret, t_ret, t2_ret; +#ifdef HAVE_COMPRESSION + DBT kcpy, *last_key; + int unknown_dup_key; +#endif + + env = dbp->env; + ovflbuf = pgmap = NULL; + inp = P_INP(dbp, h); + + memset(&dbt, 0, sizeof(DBT)); + dbt.flags = DB_DBT_REALLOC; + memset(&repldbt, 0, sizeof(DBT)); + +#ifdef HAVE_COMPRESSION + memset(&kcpy, 0, sizeof(DBT)); + unknown_dup_key = LF_ISSET(DB_SA_UNKNOWNKEY); + last_key = unknown_dup_key ? NULL : key; +#endif + LF_CLR(DB_SA_UNKNOWNKEY); + + DB_INIT_DBT(unknown_key, "UNKNOWN_KEY", sizeof("UNKNOWN_KEY") - 1); + DB_INIT_DBT(unknown_data, "UNKNOWN_DATA", sizeof("UNKNOWN_DATA") - 1); + + /* + * Allocate a buffer for overflow items. Start at one page; + * __db_safe_goff will realloc as needed. + */ + if ((ret = __os_malloc(env, dbp->pgsize, &ovflbuf)) != 0) + goto err; + ovfl_bufsz = dbp->pgsize; + + if (LF_ISSET(DB_AGGRESSIVE) && (ret = + __os_calloc(env, dbp->pgsize, sizeof(pgmap[0]), &pgmap)) != 0) + goto err; + + /* + * Loop through the inp array, spitting out key/data pairs. + * + * If we're salvaging normally, loop from 0 through NUM_ENT(h). If + * we're being aggressive, loop until we hit the end of the page -- + * NUM_ENT() may be bogus. + */ + himark = dbp->pgsize; + for (i = 0, last = UINT16_MAX;; i += O_INDX) { + /* + * If we're not aggressive, or if we're on an internal page, + * break when we hit NUM_ENT(h). + */ + if ((!LF_ISSET(DB_AGGRESSIVE) || + pgtype == P_IBTREE) && i >= NUM_ENT(h)) + break; + + /* Verify the current item. */ + t_ret = + __db_vrfy_inpitem(dbp, h, pgno, i, 1, flags, &himark, NULL); + + if (t_ret != 0) { + /* + * If this is a btree leaf and we've printed out a key + * but not its associated data item, fix this imbalance + * by printing an "UNKNOWN_DATA". + */ + if (pgtype == P_LBTREE && i % P_INDX == 1 && + last == i - 1 && (t2_ret = __db_vrfy_prdbt( + &unknown_data, + 0, " ", handle, callback, 0, 0, vdp)) != 0) { + if (ret == 0) + ret = t2_ret; + goto err; + } + + /* + * Don't return DB_VERIFY_FATAL; it's private and means + * only that we can't go on with this page, not with + * the whole database. It's not even an error if we've + * run into it after NUM_ENT(h). + */ + if (t_ret == DB_VERIFY_FATAL) { + if (i < NUM_ENT(h) && ret == 0) + ret = DB_VERIFY_BAD; + break; + } + continue; + } + + /* + * If this returned 0, it's safe to print or (carefully) + * try to fetch. + * + * We only print deleted items if DB_AGGRESSIVE is set. + */ + bk = GET_BKEYDATA(dbp, h, i); + if (!LF_ISSET(DB_AGGRESSIVE) && B_DISSET(bk->type)) + continue; + + /* + * If this is a btree leaf and we're about to print out a data + * item for which we didn't print out a key, fix this imbalance + * by printing an "UNKNOWN_KEY". + */ + if (pgtype == P_LBTREE && i % P_INDX == 1 && last != i - 1) { +#ifdef HAVE_COMPRESSION + last_key = NULL; +#endif + if ((t_ret = __db_vrfy_prdbt(&unknown_key, + 0, " ", handle, callback, 0, 0, vdp)) != 0) { + if (ret == 0) + ret = t_ret; + goto err; + } + } + last = i; + + /* + * We're going to go try to print the next item. If key is + * non-NULL, we're a dup page, so we've got to print the key + * first, unless DB_SA_SKIPFIRSTKEY is set and we're on the + * first entry. + */ + if (key != NULL && (i != 0 || !LF_ISSET(DB_SA_SKIPFIRSTKEY))) { +#ifdef HAVE_COMPRESSION + last_key = unknown_dup_key ? NULL : key; +#endif + if ((t_ret = __db_vrfy_prdbt(key, + 0, " ", handle, callback, 0, 0, vdp)) != 0) { + if (ret == 0) + ret = t_ret; + goto err; + } + } + + beg = end = inp[i]; + switch (B_TYPE(bk->type)) { + case B_DUPLICATE: + if (pgtype == P_IBTREE) + break; + + end = beg + BOVERFLOW_SIZE - 1; + /* + * If we're not on a normal btree leaf page, there + * shouldn't be off-page dup sets. Something's + * confused; just drop it, and the code to pick up + * unlinked offpage dup sets will print it out + * with key "UNKNOWN" later. + */ + if (pgtype != P_LBTREE) + break; + + bo = (BOVERFLOW *)bk; + + /* + * If the page number is unreasonable, or if this is + * supposed to be a key item, output "UNKNOWN_KEY" -- + * the best we can do is run into the data items in + * the unlinked offpage dup pass. + */ + if (!IS_VALID_PGNO(bo->pgno) || (i % P_INDX == 0)) { + /* Not much to do on failure. */ +#ifdef HAVE_COMPRESSION + if (key == NULL && i % P_INDX == 0) + last_key = NULL; +#endif + if ((t_ret = __db_vrfy_prdbt( + i % P_INDX == 0 ? &unknown_key : &unknown_data, + 0, " ", handle, callback, 0, 0,vdp)) != 0) { + if (ret == 0) + ret = t_ret; + goto err; + } + break; + } + + /* Don't stop on error. */ + if ((t_ret = __db_salvage_duptree(dbp, + vdp, bo->pgno, &dbt, handle, callback, + flags | DB_SA_SKIPFIRSTKEY +#ifdef HAVE_COMPRESSION + | (last_key == NULL ? DB_SA_UNKNOWNKEY : 0) +#endif + )) != 0 && ret == 0) + ret = t_ret; + + break; + case B_KEYDATA: + if (pgtype == P_IBTREE) + break; + + end = (db_indx_t)DB_ALIGN( + beg + bk->len, sizeof(u_int32_t)) - 1; + + dbt.data = bk->data; + dbt.size = bk->len; + +#ifdef HAVE_COMPRESSION + if (DB_IS_COMPRESSED(dbp) && last_key != NULL && + (key != NULL || (i % P_INDX == 1))) { + /* Decompress the key/data pair - the key + is in last_key, and the data is in dbt */ + if ((t_ret = __bam_compress_salvage(dbp, vdp, + handle, callback, last_key, &dbt)) != 0) { + if (t_ret == DB_VERIFY_FATAL) { + if (ret == 0) + ret = DB_VERIFY_BAD; + if (!LF_ISSET(DB_AGGRESSIVE)) + goto err; + } else if (ret == 0) { + ret = t_ret; + goto err; + } + } + } else { + if (key == NULL && i % P_INDX == 0) { + if ((ret = __os_realloc( + env, dbt.size, &kcpy.data)) != 0) + goto err; + memcpy(kcpy.data, dbt.data, dbt.size); + kcpy.size = dbt.size; + last_key = &kcpy; + } +#endif + + if ((t_ret = __db_vrfy_prdbt(&dbt, + 0, " ", handle, callback, 0, 0, vdp)) != 0) { + if (ret == 0) + ret = t_ret; + goto err; + } +#ifdef HAVE_COMPRESSION + } +#endif + break; + case B_OVERFLOW: + if (pgtype != P_IBTREE) + end = beg + BOVERFLOW_SIZE - 1; + bo = (BOVERFLOW *)bk; + + /* + * Check for replicated overflow keys, so that we only + * call __db_safe_goff once per overflow page. If we + * get the same offset as the previous key just re-use + * the previous dbt. + * + * P_IBTREE pages will never have replicated overflow + * keys. + */ + adj = pgtype == P_IBTREE ? O_INDX : P_INDX; + if (pgtype == P_IBTREE) { + /* + * If we're looking at a P_IBTREE, we just want + * to mark the overflow page as seen. + * + * Note that this call to __db_safe_goff differs + * from the non-P_IBTREE call. + * + * Only call __db_safe_goff if the overflow page + * hasn't been seen. + */ + ovflpg = ((BOVERFLOW *) + ((BINTERNAL *)bk)->data)->pgno; + if (__db_salvage_isdone(vdp, ovflpg) == 0 && + (t_ret =__db_safe_goff(dbp, vdp, ovflpg, + &dbt, &ovflbuf, + &ovfl_bufsz, flags)) != 0 && ret == 0) + ret = t_ret; + break; + } else if (i > adj - 1 && + i % adj == 0 && inp[i] == inp[i - adj]) + dbt = repldbt; + else { + /* Don't stop on error. */ + if ((t_ret = __db_safe_goff(dbp, vdp, + bo->pgno, &dbt, &ovflbuf, + &ovfl_bufsz, flags)) != 0 && ret == 0) + ret = t_ret; + + /* + * If this is a key, save it in case the next + * key is a replicated overflow, so we don't + * call __db_safe_goff again. Copy out dbt.data + * in case that pointer gets realloc'd when + * getting a data item. + */ + if (i % P_INDX == 0) { + if (t_ret == 0) { + if ((t_ret = __os_realloc(env, + dbt.size, + &repldbt.data)) != 0) { + if (ret == 0) + ret = t_ret; + goto err; + } + memcpy(repldbt.data, + dbt.data, dbt.size); + repldbt.size = dbt.size; + } else { + if (__os_realloc(env, + unknown_key.size, + &repldbt.data) != 0) + goto err; + memcpy(repldbt.data, + unknown_key.data, + unknown_key.size); + repldbt.size = unknown_key.size; + } + } + + } + +#ifdef HAVE_COMPRESSION + if (DB_IS_COMPRESSED(dbp) && last_key && t_ret == 0 && + (key != NULL || (i % P_INDX == 1))) { + /* Decompress the key/data pair - the key + is in last_key, and the data is in dbt */ + if ((t_ret = __bam_compress_salvage(dbp, vdp, + handle, callback, last_key, &dbt)) != 0) { + if (t_ret == DB_VERIFY_FATAL) { + if (ret == 0) + ret = DB_VERIFY_BAD; + if (!LF_ISSET(DB_AGGRESSIVE)) + goto err; + } else if (ret == 0) { + ret = t_ret; + goto err; + } + } + } else { + if (key == NULL && i % P_INDX == 0) { + if (t_ret == 0) { + if ((ret = __os_realloc(env, + dbt.size, &kcpy.data)) != 0) + goto err; + memcpy(kcpy.data, dbt.data, + dbt.size); + kcpy.size = dbt.size; + last_key = &kcpy; + } else + last_key = NULL; + } +#endif + + if ((t_ret = __db_vrfy_prdbt( + t_ret == 0 ? &dbt : &unknown_key, + 0, " ", handle, callback, 0, 0, vdp)) + != 0 && ret == 0) + ret = t_ret; +#ifdef HAVE_COMPRESSION + } +#endif + break; + default: + /* + * We should never get here; __db_vrfy_inpitem should + * not be returning 0 if bk->type is unrecognizable. + */ + t_ret = __db_unknown_path(env, "__bam_salvage"); + if (ret == 0) + ret = t_ret; + goto err; + } + + /* + * If we're being aggressive, mark the beginning and end of + * the item; we'll come back and print whatever "junk" is in + * the gaps in case we had any bogus inp elements and thereby + * missed stuff. + */ + if (LF_ISSET(DB_AGGRESSIVE) && pgtype != P_IBTREE) { + pgmap[beg] = VRFY_ITEM_BEGIN; + pgmap[end] = VRFY_ITEM_END; + } + } + +err: if (pgmap != NULL) + __os_free(env, pgmap); + if (ovflbuf != NULL) + __os_free(env, ovflbuf); + if (repldbt.data != NULL) + __os_free(env, repldbt.data); +#ifdef HAVE_COMPRESSION + if (kcpy.data != NULL) + __os_free(env, kcpy.data); +#endif + + /* Mark this page as done. */ + if ((t_ret = __db_salvage_markdone(vdp, pgno)) != 0 && ret == 0) + ret = t_ret; + + return (ret); +} + +/* + * __bam_salvage_walkdupint -- + * Walk a known-good btree or recno internal page which is part of + * a dup tree, calling __db_salvage_duptree on each child page. + * + * PUBLIC: int __bam_salvage_walkdupint __P((DB *, VRFY_DBINFO *, PAGE *, + * PUBLIC: DBT *, void *, int (*)(void *, const void *), u_int32_t)); + */ +int +__bam_salvage_walkdupint(dbp, vdp, h, key, handle, callback, flags) + DB *dbp; + VRFY_DBINFO *vdp; + PAGE *h; + DBT *key; + void *handle; + int (*callback) __P((void *, const void *)); + u_int32_t flags; +{ + BINTERNAL *bi; + ENV *env; + RINTERNAL *ri; + int ret, t_ret; + db_indx_t i; + + env = dbp->env; + ret = 0; + + for (i = 0; i < NUM_ENT(h); i++) { + switch (TYPE(h)) { + case P_IBTREE: + bi = GET_BINTERNAL(dbp, h, i); + if ((t_ret = __db_salvage_duptree(dbp, + vdp, bi->pgno, key, handle, callback, flags)) != 0) + ret = t_ret; + break; + case P_IRECNO: + ri = GET_RINTERNAL(dbp, h, i); + if ((t_ret = __db_salvage_duptree(dbp, + vdp, ri->pgno, key, handle, callback, flags)) != 0) + ret = t_ret; + break; + default: + return (__db_unknown_path( + env, "__bam_salvage_walkdupint")); + } + /* Pass DB_SA_SKIPFIRSTKEY, if set, on to the 0th child only. */ + flags &= ~LF_ISSET(DB_SA_SKIPFIRSTKEY); + } + + return (ret); +} + +/* + * __bam_meta2pgset -- + * Given a known-good meta page, return in pgsetp a 0-terminated list of + * db_pgno_t's corresponding to the pages in the btree. + * + * We do this by a somewhat sleazy method, to avoid having to traverse the + * btree structure neatly: we walk down the left side to the very + * first leaf page, then we mark all the pages in the chain of + * NEXT_PGNOs (being wary of cycles and invalid ones), then we + * consolidate our scratch array into a nice list, and return. This + * avoids the memory management hassles of recursion and the + * trouble of walking internal pages--they just don't matter, except + * for the left branch. + * + * PUBLIC: int __bam_meta2pgset __P((DB *, VRFY_DBINFO *, BTMETA *, + * PUBLIC: u_int32_t, DB *)); + */ +int +__bam_meta2pgset(dbp, vdp, btmeta, flags, pgset) + DB *dbp; + VRFY_DBINFO *vdp; + BTMETA *btmeta; + u_int32_t flags; + DB *pgset; +{ + BINTERNAL *bi; + DB_MPOOLFILE *mpf; + PAGE *h; + RINTERNAL *ri; + db_pgno_t current, p; + int err_ret, ret; + + DB_ASSERT(dbp->env, pgset != NULL); + + mpf = dbp->mpf; + h = NULL; + ret = err_ret = 0; + + for (current = btmeta->root;;) { + if (!IS_VALID_PGNO(current) || current == PGNO(btmeta)) { + err_ret = DB_VERIFY_BAD; + goto err; + } + if ((ret = __memp_fget(mpf, ¤t, + vdp->thread_info, NULL, 0, &h)) != 0) { + err_ret = ret; + goto err; + } + + switch (TYPE(h)) { + case P_IBTREE: + case P_IRECNO: + if ((ret = __bam_vrfy(dbp, + vdp, h, current, flags | DB_NOORDERCHK)) != 0) { + err_ret = ret; + goto err; + } + if (TYPE(h) == P_IBTREE) { + bi = GET_BINTERNAL(dbp, h, 0); + current = bi->pgno; + } else { /* P_IRECNO */ + ri = GET_RINTERNAL(dbp, h, 0); + current = ri->pgno; + } + break; + case P_LBTREE: + case P_LRECNO: + goto traverse; + default: + err_ret = DB_VERIFY_BAD; + goto err; + } + + if ((ret = __memp_fput(mpf, + vdp->thread_info, h, DB_PRIORITY_UNCHANGED)) != 0) + err_ret = ret; + h = NULL; + } + + /* + * At this point, current is the pgno of leaf page h, the 0th in the + * tree we're concerned with. + */ +traverse: + while (IS_VALID_PGNO(current) && current != PGNO_INVALID) { + if (h == NULL && (ret = __memp_fget(mpf, + ¤t, vdp->thread_info, NULL, 0, &h)) != 0) { + err_ret = ret; + break; + } + + if ((ret = __db_vrfy_pgset_get(pgset, + vdp->thread_info, vdp->txn, current, (int *)&p)) != 0) + goto err; + + if (p != 0) { + /* + * We've found a cycle. Return success anyway-- + * our caller may as well use however much of + * the pgset we've come up with. + */ + break; + } + if ((ret = __db_vrfy_pgset_inc( + pgset, vdp->thread_info, vdp->txn, current)) != 0) + goto err; + + current = NEXT_PGNO(h); + if ((ret = __memp_fput(mpf, + vdp->thread_info, h, DB_PRIORITY_UNCHANGED)) != 0) + err_ret = ret; + h = NULL; + } + +err: if (h != NULL) + (void)__memp_fput(mpf, + vdp->thread_info, h, DB_PRIORITY_UNCHANGED); + + return (ret == 0 ? err_ret : ret); +} + +/* + * __bam_safe_getdata -- + * + * Utility function for __bam_vrfy_itemorder. Safely gets the datum at + * index i, page h, and sticks it in DBT dbt. If ovflok is 1 and i's an + * overflow item, we do a safe_goff to get the item and signal that we need + * to free dbt->data; if ovflok is 0, we leaves the DBT zeroed. + */ +static int +__bam_safe_getdata(dbp, ip, h, i, ovflok, dbt, freedbtp) + DB *dbp; + DB_THREAD_INFO *ip; + PAGE *h; + u_int32_t i; + int ovflok; + DBT *dbt; + int *freedbtp; +{ + BKEYDATA *bk; + BOVERFLOW *bo; + DBC *dbc; + int ret; + + memset(dbt, 0, sizeof(DBT)); + *freedbtp = 0; + + bk = GET_BKEYDATA(dbp, h, i); + if (B_TYPE(bk->type) == B_OVERFLOW) { + if (!ovflok) + return (0); + + if ((ret = __db_cursor_int(dbp, ip, NULL, DB_BTREE, + PGNO_INVALID, 0, DB_LOCK_INVALIDID, &dbc)) != 0) + return (ret); + bo = (BOVERFLOW *)bk; + F_SET(dbt, DB_DBT_MALLOC); + + *freedbtp = 1; + return (__db_goff(dbc, dbt, bo->tlen, bo->pgno, NULL, NULL)); + } else { + dbt->data = bk->data; + dbt->size = bk->len; + } + + return (0); +} diff -r 000000000000 -r a1985f14b030 src/clib/getopt.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/clib/getopt.c Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,175 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 1996, 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +/* + * Copyright (c) 1987, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $Id$ + */ + +/* + * Avoid inclusion of internal header files as this + * file is used by example code. + * + * Unconditional inclusion of stdio and string are + * OK in this file. It will work on all platforms + * for which this file is used + */ +extern char *__db_rpath(const char *); +#include +#include + +int __db_getopt_reset; /* global reset for VxWorks. */ + +int opterr = 1, /* if error message should be printed */ + optind = 1, /* index into parent argv vector */ + optopt, /* character checked for validity */ + optreset; /* reset getopt */ +char *optarg; /* argument associated with option */ + +#undef BADCH +#define BADCH (int)'?' +#undef BADARG +#define BADARG (int)':' +#undef EMSG +#define EMSG "" + +/* + * getopt -- + * Parse argc/argv argument vector. + * + * PUBLIC: #ifndef HAVE_GETOPT + * PUBLIC: int getopt __P((int, char * const *, const char *)); + * PUBLIC: #endif + */ +int +getopt(nargc, nargv, ostr) + int nargc; + char * const *nargv; + const char *ostr; +{ + static char *progname; + static char *place = EMSG; /* option letter processing */ + char *oli; /* option letter list index */ + + /* + * VxWorks needs to be able to repeatedly call getopt from multiple + * programs within its global name space. + */ + if (__db_getopt_reset) { + __db_getopt_reset = 0; + + opterr = optind = 1; + optopt = optreset = 0; + optarg = NULL; + progname = NULL; + place = EMSG; + } + if (!progname) { + if ((progname = __db_rpath(*nargv)) == NULL) + progname = *nargv; + else + ++progname; + } + + if (optreset || !*place) { /* update scanning pointer */ + optreset = 0; + if (optind >= nargc || *(place = nargv[optind]) != '-') { + place = EMSG; + return (EOF); + } + if (place[1] && *++place == '-') { /* found "--" */ + ++optind; + place = EMSG; + return (EOF); + } + } /* option letter okay? */ + if ((optopt = (int)*place++) == (int)':' || + !(oli = strchr(ostr, optopt))) { + /* + * if the user didn't specify '-' as an option, + * assume it means EOF. + */ + if (optopt == (int)'-') + return (EOF); + if (!*place) + ++optind; + if (opterr && *ostr != ':') + (void)fprintf(stderr, + "%s: illegal option -- %c\n", progname, optopt); + return (BADCH); + } + if (*++oli != ':') { /* don't need argument */ + optarg = NULL; + if (!*place) + ++optind; + } + else { /* need an argument */ + if (*place) /* no white space */ + optarg = place; + else if (nargc <= ++optind) { /* no arg */ + place = EMSG; + if (*ostr == ':') + return (BADARG); + if (opterr) + (void)fprintf(stderr, + "%s: option requires an argument -- %c\n", + progname, optopt); + return (BADCH); + } + else /* white space */ + optarg = nargv[optind]; + place = EMSG; + ++optind; + } + return (optopt); /* dump back option letter */ +} diff -r 000000000000 -r a1985f14b030 src/clib/isalpha.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/clib/isalpha.c Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,50 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 2005, 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + * $Id$ + */ + +#include "db_config.h" + +#include "db_int.h" + +/* + * isalpha -- + * + * PUBLIC: #ifndef HAVE_ISALPHA + * PUBLIC: int isalpha __P((int)); + * PUBLIC: #endif + */ +int +isalpha(c) + int c; +{ + /* + * Depends on ASCII-like character ordering. + */ + return ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') ? 1 : 0); +} diff -r 000000000000 -r a1985f14b030 src/clib/snprintf.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/clib/snprintf.c Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,171 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 1996, 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + * $Id$ + */ + +#include "db_config.h" + +#include "db_int.h" + +#if !defined(HAVE_SNPRINTF) || !defined(HAVE_VSNPRINTF) +static void sprintf_overflow __P((void)); +static int sprintf_retcharpnt __P((void)); +#endif + +/* + * snprintf -- + * Bounded version of sprintf. + * + * PUBLIC: #ifndef HAVE_SNPRINTF + * PUBLIC: int snprintf __P((char *, size_t, const char *, ...)); + * PUBLIC: #endif + */ +#ifndef HAVE_SNPRINTF +int +#ifdef STDC_HEADERS +snprintf(char *str, size_t n, const char *fmt, ...) +#else +snprintf(str, n, fmt, va_alist) + char *str; + size_t n; + const char *fmt; + va_dcl +#endif +{ + static int ret_charpnt = -1; + va_list ap; + size_t len; + + if (ret_charpnt == -1) + ret_charpnt = sprintf_retcharpnt(); + +#ifdef STDC_HEADERS + va_start(ap, fmt); +#else + va_start(ap); +#endif + len = (size_t)vsprintf(str, fmt, ap); + if (ret_charpnt) + len = strlen(str); + + va_end(ap); + + if (len >= n) { + sprintf_overflow(); + /* NOTREACHED */ + } + return ((int)len); +} +#endif + +/* + * vsnprintf -- + * Bounded version of vsprintf. + * + * PUBLIC: #ifndef HAVE_VSNPRINTF + * PUBLIC: int vsnprintf __P((char *, size_t, const char *, va_list)); + * PUBLIC: #endif + */ +#ifndef HAVE_VSNPRINTF +int +vsnprintf(str, n, fmt, ap) + char *str; + size_t n; + const char *fmt; + va_list ap; +{ + static int ret_charpnt = -1; + size_t len; + + if (ret_charpnt == -1) + ret_charpnt = sprintf_retcharpnt(); + + len = (size_t)vsprintf(str, fmt, ap); + if (ret_charpnt) + len = strlen(str); + + if (len >= n) { + sprintf_overflow(); + /* NOTREACHED */ + } + return ((int)len); +} +#endif + +#if !defined(HAVE_SNPRINTF) || !defined(HAVE_VSNPRINTF) +static void +sprintf_overflow() +{ + /* + * !!! + * We're potentially manipulating strings handed us by the application, + * and on systems without a real snprintf() the sprintf() calls could + * have overflowed the buffer. We can't do anything about it now, but + * we don't want to return control to the application, we might have + * overwritten the stack with a Trojan horse. We're not trying to do + * anything recoverable here because systems without snprintf support + * are pretty rare anymore. + */ +#define OVERFLOW_ERROR "internal buffer overflow, process ended\n" +#ifndef STDERR_FILENO +#define STDERR_FILENO 2 +#endif + (void)write(STDERR_FILENO, OVERFLOW_ERROR, sizeof(OVERFLOW_ERROR) - 1); + + /* Be polite. */ + exit(1); + + /* But firm. */ + __os_abort(NULL); + + /* NOTREACHED */ +} + +static int +sprintf_retcharpnt() +{ + int ret_charpnt; + char buf[10]; + + /* + * Some old versions of sprintf return a pointer to the first argument + * instead of a character count. Assume the return value of snprintf, + * vsprintf, etc. will be the same as sprintf, and check the easy one. + * + * We do this test at run-time because it's not a test we can do in a + * cross-compilation environment. + */ + + ret_charpnt = + (int)sprintf(buf, "123") != 3 || + (int)sprintf(buf, "123456789") != 9 || + (int)sprintf(buf, "1234") != 4; + + return (ret_charpnt); +} +#endif diff -r 000000000000 -r a1985f14b030 src/clib/strsep.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/clib/strsep.c Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,105 @@ +/*- + * + * Copyright (c) 2006, 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include "db_config.h" + +#include "db_int.h" + +/* + * Get next token from string *stringp, where tokens are possibly-empty + * strings separated by characters from delim. + * + * Writes NULs into the string at *stringp to end tokens. + * delim need not remain constant from call to call. + * On return, *stringp points past the last NUL written (if there might + * be further tokens), or is NULL (if there are definitely no more tokens). + * + * If *stringp is NULL, strsep returns NULL. + * + * PUBLIC: #ifndef HAVE_STRSEP + * PUBLIC: char *strsep __P((char **, const char *)); + * PUBLIC: #endif + */ +char * +strsep(stringp, delim) + char **stringp; + const char *delim; +{ + char *s; + const char *spanp; + int c, sc; + char *tok; + + if ((s = *stringp) == NULL) + return (NULL); + for (tok = s;;) { + c = *s++; + spanp = delim; + do { + if ((sc = *spanp++) == c) { + if (c == 0) + s = NULL; + else + s[-1] = 0; + *stringp = s; + return (tok); + } + } while (sc != 0); + } + /* NOTREACHED */ +} diff -r 000000000000 -r a1985f14b030 src/common/clock.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/common/clock.c Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,79 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 1996, 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + * $Id$ + */ + +#include "db_config.h" + +#include "db_int.h" +/* + * __clock_set_expires -- + * Set the expire time given the time to live. + * + * PUBLIC: void __clock_set_expires __P((ENV *, db_timespec *, db_timeout_t)); + */ +void +__clock_set_expires(env, timespecp, timeout) + ENV *env; + db_timespec *timespecp; + db_timeout_t timeout; +{ + db_timespec v; + + /* + * If timespecp is set then it contains "now". This avoids repeated + * system calls to get the time. + */ + if (!timespecisset(timespecp)) + __os_gettime(env, timespecp, 1); + + /* Convert the microsecond timeout argument to a timespec. */ + DB_TIMEOUT_TO_TIMESPEC(timeout, &v); + + /* Add the timeout to "now". */ + timespecadd(timespecp, &v); +} + +/* + * __clock_expired -- determine if a timeout has expired. + * + * PUBLIC: int __clock_expired __P((ENV *, db_timespec *, db_timespec *)); + */ +int +__clock_expired(env, now, timespecp) + ENV *env; + db_timespec *now, *timespecp; +{ + if (!timespecisset(timespecp)) + return (0); + + if (!timespecisset(now)) + __os_gettime(env, now, 1); + + return (timespeccmp(now, timespecp, >=)); +} diff -r 000000000000 -r a1985f14b030 src/common/crypto_stub.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/common/crypto_stub.c Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,66 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 1996, 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + * $Id$ + */ + +#include "db_config.h" + +#include "db_int.h" + +/* + * __crypto_region_init -- + * Initialize crypto. + * + * + * !!! + * We don't put this stub file in the crypto/ directory of the distribution + * because that entire directory is removed for non-crypto distributions. + * + * PUBLIC: int __crypto_region_init __P((ENV *)); + */ +int +__crypto_region_init(env) + ENV *env; +{ + REGENV *renv; + REGINFO *infop; + int ret; + + infop = env->reginfo; + renv = infop->primary; + MUTEX_LOCK(env, renv->mtx_regenv); + ret = !(renv->cipher_off == INVALID_ROFF); + MUTEX_UNLOCK(env, renv->mtx_regenv); + + if (ret == 0) + return (0); + + __db_errx(env, DB_STR("0040", +"Encrypted environment: library build did not include cryptography support")); + return (DB_OPNOTSUP); +} diff -r 000000000000 -r a1985f14b030 src/common/db_byteorder.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/common/db_byteorder.c Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,85 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 1996, 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + * $Id$ + */ + +#include "db_config.h" + +#include "db_int.h" + +/* + * __db_isbigendian -- + * Return 1 if big-endian (Motorola and Sparc), not little-endian + * (Intel and Vax). We do this work at run-time, rather than at + * configuration time so cross-compilation and general embedded + * system support is simpler. + * + * PUBLIC: int __db_isbigendian __P((void)); + */ +int +__db_isbigendian() +{ + union { /* From Harbison & Steele. */ + long l; + char c[sizeof(long)]; + } u; + + u.l = 1; + return (u.c[sizeof(long) - 1] == 1); +} + +/* + * __db_byteorder -- + * Return if we need to do byte swapping, checking for illegal + * values. + * + * PUBLIC: int __db_byteorder __P((ENV *, int)); + */ +int +__db_byteorder(env, lorder) + ENV *env; + int lorder; +{ + switch (lorder) { + case 0: + break; + case 1234: + if (!F_ISSET(env, ENV_LITTLEENDIAN)) + return (DB_SWAPBYTES); + break; + case 4321: + if (F_ISSET(env, ENV_LITTLEENDIAN)) + return (DB_SWAPBYTES); + break; + default: + __db_errx(env, DB_STR("0041", + "unsupported byte order, only big and little-endian supported")); + return (EINVAL); + } + return (0); +} diff -r 000000000000 -r a1985f14b030 src/common/db_err.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/common/db_err.c Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,996 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 1996, 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + * $Id$ + */ + +#include "db_config.h" + +#include "db_int.h" +#include "dbinc/db_page.h" +#include "dbinc/db_am.h" +#include "dbinc/lock.h" +#include "dbinc/mp.h" +#include "dbinc/txn.h" + +static void __db_msgcall __P((const DB_ENV *, const char *, va_list)); +static void __db_msgfile __P((const DB_ENV *, const char *, va_list)); + +/* + * __db_fchk -- + * General flags checking routine. + * + * PUBLIC: int __db_fchk __P((ENV *, const char *, u_int32_t, u_int32_t)); + */ +int +__db_fchk(env, name, flags, ok_flags) + ENV *env; + const char *name; + u_int32_t flags, ok_flags; +{ + return (LF_ISSET(~ok_flags) ? __db_ferr(env, name, 0) : 0); +} + +/* + * __db_fcchk -- + * General combination flags checking routine. + * + * PUBLIC: int __db_fcchk + * PUBLIC: __P((ENV *, const char *, u_int32_t, u_int32_t, u_int32_t)); + */ +int +__db_fcchk(env, name, flags, flag1, flag2) + ENV *env; + const char *name; + u_int32_t flags, flag1, flag2; +{ + return (LF_ISSET(flag1) && + LF_ISSET(flag2) ? __db_ferr(env, name, 1) : 0); +} + +/* + * __db_ferr -- + * Common flag errors. + * + * PUBLIC: int __db_ferr __P((const ENV *, const char *, int)); + */ +int +__db_ferr(env, name, iscombo) + const ENV *env; + const char *name; + int iscombo; +{ + if (iscombo) + __db_errx(env, DB_STR_A("0054", + "illegal flag combination specified to %s", "%s"), name); + else + __db_errx(env, DB_STR_A("0055", + "illegal flag specified to %s", "%s"), name); + + return (EINVAL); +} + +/* + * __db_fnl -- + * Common flag-needs-locking message. + * + * PUBLIC: int __db_fnl __P((const ENV *, const char *)); + */ +int +__db_fnl(env, name) + const ENV *env; + const char *name; +{ + __db_errx(env, DB_STR_A("0056", + "%s: DB_READ_COMMITTED, DB_READ_UNCOMMITTED and DB_RMW require locking", + "%s"), name); + return (EINVAL); +} + +/* + * __db_pgerr -- + * Error when unable to retrieve a specified page. + * + * PUBLIC: int __db_pgerr __P((DB *, db_pgno_t, int)); + */ +int +__db_pgerr(dbp, pgno, errval) + DB *dbp; + db_pgno_t pgno; + int errval; +{ + /* + * Three things are certain: + * Death, taxes, and lost data. + * Guess which has occurred. + */ + __db_errx(dbp->env, DB_STR_A("0057", + "unable to create/retrieve page %lu", "%lu"), (u_long)pgno); + return (__env_panic(dbp->env, errval)); +} + +/* + * __db_pgfmt -- + * Error when a page has the wrong format. + * + * PUBLIC: int __db_pgfmt __P((ENV *, db_pgno_t)); + */ +int +__db_pgfmt(env, pgno) + ENV *env; + db_pgno_t pgno; +{ + __db_errx(env, DB_STR_A("0058", + "page %lu: illegal page type or format", "%lu"), (u_long)pgno); + return (__env_panic(env, EINVAL)); +} + +#ifdef DIAGNOSTIC +/* + * __db_assert -- + * Error when an assertion fails. Only checked if #DIAGNOSTIC defined. + * + * PUBLIC: #ifdef DIAGNOSTIC + * PUBLIC: void __db_assert __P((ENV *, const char *, const char *, int)); + * PUBLIC: #endif + */ +void +__db_assert(env, e, file, line) + ENV *env; + const char *e, *file; + int line; +{ + if (DB_GLOBAL(j_assert) != NULL) + DB_GLOBAL(j_assert)(e, file, line); + else { + __db_errx(env, DB_STR_A("0059", + "assert failure: %s/%d: \"%s\"", + "%s %d %s"), file, line, e); + + __os_abort(env); + /* NOTREACHED */ + } +} +#endif + +/* + * __env_panic_msg -- + * Just report that someone else paniced. + * + * PUBLIC: int __env_panic_msg __P((ENV *)); + */ +int +__env_panic_msg(env) + ENV *env; +{ + DB_ENV *dbenv; + int ret; + + dbenv = env->dbenv; + + ret = DB_RUNRECOVERY; + + __db_errx(env, DB_STR("0060", + "PANIC: fatal region error detected; run recovery")); + + if (dbenv->db_paniccall != NULL) /* Deprecated */ + dbenv->db_paniccall(dbenv, ret); + + /* Must check for DB_EVENT_REG_PANIC panic first because it is never + * set by itself. If set, it means panic came from DB_REGISTER code + * only, otherwise it could be from many possible places in the code. + */ + if ((env->reginfo != NULL) && + (((REGENV *)env->reginfo->primary)->reg_panic)) + DB_EVENT(env, DB_EVENT_REG_PANIC, &ret); + else + DB_EVENT(env, DB_EVENT_PANIC, &ret); + + return (ret); +} + +/* + * __env_panic -- + * Lock out the database environment due to unrecoverable error. + * + * PUBLIC: int __env_panic __P((ENV *, int)); + */ +int +__env_panic(env, errval) + ENV *env; + int errval; +{ + DB_ENV *dbenv; + + dbenv = env->dbenv; + + if (env != NULL) { + __env_panic_set(env, 1); + + __db_err(env, errval, DB_STR("0061", "PANIC")); + + if (dbenv->db_paniccall != NULL) /* Deprecated */ + dbenv->db_paniccall(dbenv, errval); + + /* Must check for DB_EVENT_REG_PANIC first because it is never + * set by itself. If set, it means panic came from DB_REGISTER + * code only, otherwise it could be from many possible places + * in the code. + */ + if ((env->reginfo != NULL) && + (((REGENV *)env->reginfo->primary)->reg_panic)) + DB_EVENT(env, DB_EVENT_REG_PANIC, &errval); + else + DB_EVENT(env, DB_EVENT_PANIC, &errval); + } + +#if defined(DIAGNOSTIC) && !defined(CONFIG_TEST) + /* + * We want a stack trace of how this could possibly happen. + * + * Don't drop core if it's the test suite -- it's reasonable for the + * test suite to check to make sure that DB_RUNRECOVERY is returned + * under certain conditions. + */ + __os_abort(env); + /* NOTREACHED */ +#endif + + /* + * Chaos reigns within. + * Reflect, repent, and reboot. + * Order shall return. + */ + return (DB_RUNRECOVERY); +} + +/* + * db_strerror -- + * ANSI C strerror(3) for DB. + * + * EXTERN: char *db_strerror __P((int)); + */ +char * +db_strerror(error) + int error; +{ + char *p; + + if (error == 0) + return (DB_STR("0062", "Successful return: 0")); + if (error > 0) { + if ((p = strerror(error)) != NULL) + return (p); + return (__db_unknown_error(error)); + } + + /* + * !!! + * The Tcl API requires that some of these return strings be compared + * against strings stored in application scripts. So, any of these + * errors that do not invariably result in a Tcl exception may not be + * altered. + */ + switch (error) { + case DB_BUFFER_SMALL: + return (DB_STR("0063", + "DB_BUFFER_SMALL: User memory too small for return value")); + case DB_DONOTINDEX: + return (DB_STR("0064", + "DB_DONOTINDEX: Secondary index callback returns null")); + case DB_FOREIGN_CONFLICT: + return (DB_STR("0065", + "DB_FOREIGN_CONFLICT: A foreign database constraint has been violated")); + case DB_HEAP_FULL: + return (DB_STR("0208","DB_HEAP_FULL: no free space in db")); + case DB_KEYEMPTY: + return (DB_STR("0066", + "DB_KEYEMPTY: Non-existent key/data pair")); + case DB_KEYEXIST: + return (DB_STR("0067", + "DB_KEYEXIST: Key/data pair already exists")); + case DB_LOCK_DEADLOCK: + return (DB_STR("0068", + "DB_LOCK_DEADLOCK: Locker killed to resolve a deadlock")); + case DB_LOCK_NOTGRANTED: + return (DB_STR("0069", "DB_LOCK_NOTGRANTED: Lock not granted")); + case DB_LOG_BUFFER_FULL: + return (DB_STR("0070", + "DB_LOG_BUFFER_FULL: In-memory log buffer is full")); + case DB_LOG_VERIFY_BAD: + return (DB_STR("0071", + "DB_LOG_VERIFY_BAD: Log verification failed")); + case DB_NOSERVER: + return (DB_STR("0072", + "DB_NOSERVER: No message dispatch call-back function has been configured")); + case DB_NOTFOUND: + return (DB_STR("0073", + "DB_NOTFOUND: No matching key/data pair found")); + case DB_OLD_VERSION: + return (DB_STR("0074", + "DB_OLDVERSION: Database requires a version upgrade")); + case DB_PAGE_NOTFOUND: + return (DB_STR("0075", + "DB_PAGE_NOTFOUND: Requested page not found")); + case DB_REP_DUPMASTER: + return (DB_STR("0076", + "DB_REP_DUPMASTER: A second master site appeared")); + case DB_REP_HANDLE_DEAD: + return (DB_STR("0077", + "DB_REP_HANDLE_DEAD: Handle is no longer valid")); + case DB_REP_HOLDELECTION: + return (DB_STR("0078", + "DB_REP_HOLDELECTION: Need to hold an election")); + case DB_REP_IGNORE: + return (DB_STR("0079", + "DB_REP_IGNORE: Replication record/operation ignored")); + case DB_REP_ISPERM: + return (DB_STR("0080", + "DB_REP_ISPERM: Permanent record written")); + case DB_REP_JOIN_FAILURE: + return (DB_STR("0081", + "DB_REP_JOIN_FAILURE: Unable to join replication group")); + case DB_REP_LEASE_EXPIRED: + return (DB_STR("0082", + "DB_REP_LEASE_EXPIRED: Replication leases have expired")); + case DB_REP_LOCKOUT: + return (DB_STR("0083", + "DB_REP_LOCKOUT: Waiting for replication recovery to complete")); + case DB_REP_NEWSITE: + return (DB_STR("0084", + "DB_REP_NEWSITE: A new site has entered the system")); + case DB_REP_NOTPERM: + return (DB_STR("0085", + "DB_REP_NOTPERM: Permanent log record not written")); + case DB_REP_UNAVAIL: + return (DB_STR("0086", + "DB_REP_UNAVAIL: Too few remote sites to complete operation")); + case DB_REP_WOULDROLLBACK: /* Undocumented; C API only. */ + return (DB_STR("0207", + "DB_REP_WOULDROLLBACK: Client data has diverged")); + case DB_RUNRECOVERY: + return (DB_STR("0087", + "DB_RUNRECOVERY: Fatal error, run database recovery")); + case DB_SECONDARY_BAD: + return (DB_STR("0088", + "DB_SECONDARY_BAD: Secondary index inconsistent with primary")); + case DB_TIMEOUT: + return (DB_STR("0089", "DB_TIMEOUT: Operation timed out")); + case DB_VERIFY_BAD: + return (DB_STR("0090", + "DB_VERIFY_BAD: Database verification failed")); + case DB_VERSION_MISMATCH: + return (DB_STR("0091", + "DB_VERSION_MISMATCH: Database environment version mismatch")); + default: + break; + } + + return (__db_unknown_error(error)); +} + +/* + * __db_unknown_error -- + * Format an unknown error value into a static buffer. + * + * PUBLIC: char *__db_unknown_error __P((int)); + */ +char * +__db_unknown_error(error) + int error; +{ + /* + * !!! + * Room for a 64-bit number + slop. This buffer is only used + * if we're given an unknown error number, which should never + * happen. + * + * We're no longer thread-safe if it does happen, but the worst + * result is a corrupted error string because there will always + * be a trailing nul byte since the error buffer is nul filled + * and longer than any error message. + */ + (void)snprintf(DB_GLOBAL(error_buf), + sizeof(DB_GLOBAL(error_buf)), DB_STR_A("0092", + "Unknown error: %d", "%d"), error); + return (DB_GLOBAL(error_buf)); +} + +/* + * __db_syserr -- + * Standard error routine. + * + * PUBLIC: void __db_syserr __P((const ENV *, int, const char *, ...)) + * PUBLIC: __attribute__ ((__format__ (__printf__, 3, 4))); + */ +void +#ifdef STDC_HEADERS +__db_syserr(const ENV *env, int error, const char *fmt, ...) +#else +__db_syserr(env, error, fmt, va_alist) + const ENV *env; + int error; + const char *fmt; + va_dcl +#endif +{ + DB_ENV *dbenv; + + dbenv = env == NULL ? NULL : env->dbenv; + + /* + * The same as DB->err, except we don't default to writing to stderr + * after any output channel has been configured, and we use a system- + * specific function to translate errors to strings. + */ + DB_REAL_ERR(dbenv, error, DB_ERROR_SYSTEM, 0, fmt); +} + +/* + * __db_err -- + * Standard error routine. + * + * PUBLIC: void __db_err __P((const ENV *, int, const char *, ...)) + * PUBLIC: __attribute__ ((__format__ (__printf__, 3, 4))); + */ +void +#ifdef STDC_HEADERS +__db_err(const ENV *env, int error, const char *fmt, ...) +#else +__db_err(env, error, fmt, va_alist) + const ENV *env; + int error; + const char *fmt; + va_dcl +#endif +{ + DB_ENV *dbenv; + + dbenv = env == NULL ? NULL : env->dbenv; + + /* + * The same as DB->err, except we don't default to writing to stderr + * once an output channel has been configured. + */ + DB_REAL_ERR(dbenv, error, DB_ERROR_SET, 0, fmt); +} + +/* + * __db_errx -- + * Standard error routine. + * + * PUBLIC: void __db_errx __P((const ENV *, const char *, ...)) + * PUBLIC: __attribute__ ((__format__ (__printf__, 2, 3))); + */ +void +#ifdef STDC_HEADERS +__db_errx(const ENV *env, const char *fmt, ...) +#else +__db_errx(env, fmt, va_alist) + const ENV *env; + const char *fmt; + va_dcl +#endif +{ + DB_ENV *dbenv; + + dbenv = env == NULL ? NULL : env->dbenv; + + /* + * The same as DB->errx, except we don't default to writing to stderr + * once an output channel has been configured. + */ + DB_REAL_ERR(dbenv, 0, DB_ERROR_NOT_SET, 0, fmt); +} + +/* + * __db_errcall -- + * Do the error message work for callback functions. + * + * PUBLIC: void __db_errcall + * PUBLIC: __P((const DB_ENV *, int, db_error_set_t, const char *, va_list)); + */ +void +__db_errcall(dbenv, error, error_set, fmt, ap) + const DB_ENV *dbenv; + int error; + db_error_set_t error_set; + const char *fmt; + va_list ap; +{ + char *p; + char buf[2048]; /* !!!: END OF THE STACK DON'T TRUST SPRINTF. */ + char sysbuf[1024]; /* !!!: END OF THE STACK DON'T TRUST SPRINTF. */ + + p = buf; + if (fmt != NULL) + p += vsnprintf(buf, sizeof(buf), fmt, ap); + if (error_set != DB_ERROR_NOT_SET) + p += snprintf(p, + sizeof(buf) - (size_t)(p - buf), ": %s", + error_set == DB_ERROR_SET ? db_strerror(error) : + __os_strerror(error, sysbuf, sizeof(sysbuf))); + + dbenv->db_errcall(dbenv, dbenv->db_errpfx, buf); +} + +/* + * __db_errfile -- + * Do the error message work for FILE *s. + * + * PUBLIC: void __db_errfile + * PUBLIC: __P((const DB_ENV *, int, db_error_set_t, const char *, va_list)); + */ +void +__db_errfile(dbenv, error, error_set, fmt, ap) + const DB_ENV *dbenv; + int error; + db_error_set_t error_set; + const char *fmt; + va_list ap; +{ + FILE *fp; + int need_sep; + char sysbuf[1024]; /* !!!: END OF THE STACK DON'T TRUST SPRINTF. */ + + fp = dbenv == NULL || + dbenv->db_errfile == NULL ? stderr : dbenv->db_errfile; + need_sep = 0; + + if (dbenv != NULL && dbenv->db_errpfx != NULL) { + (void)fprintf(fp, "%s", dbenv->db_errpfx); + need_sep = 1; + } + if (fmt != NULL && fmt[0] != '\0') { + if (need_sep) + (void)fprintf(fp, ": "); + need_sep = 1; + (void)vfprintf(fp, fmt, ap); + } + if (error_set != DB_ERROR_NOT_SET) + (void)fprintf(fp, "%s%s", + need_sep ? ": " : "", + error_set == DB_ERROR_SET ? db_strerror(error) : + __os_strerror(error, sysbuf, sizeof(sysbuf))); + (void)fprintf(fp, "\n"); + (void)fflush(fp); +} + +/* + * __db_msgadd -- + * Aggregate a set of strings into a buffer for the callback API. + * + * PUBLIC: void __db_msgadd __P((ENV *, DB_MSGBUF *, const char *, ...)) + * PUBLIC: __attribute__ ((__format__ (__printf__, 3, 4))); + */ +void +#ifdef STDC_HEADERS +__db_msgadd(ENV *env, DB_MSGBUF *mbp, const char *fmt, ...) +#else +__db_msgadd(env, mbp, fmt, va_alist) + ENV *env; + DB_MSGBUF *mbp; + const char *fmt; + va_dcl +#endif +{ + va_list ap; + +#ifdef STDC_HEADERS + va_start(ap, fmt); +#else + va_start(ap); +#endif + __db_msgadd_ap(env, mbp, fmt, ap); + va_end(ap); +} + +/* + * __db_msgadd_ap -- + * Aggregate a set of strings into a buffer for the callback API. + * + * PUBLIC: void __db_msgadd_ap + * PUBLIC: __P((ENV *, DB_MSGBUF *, const char *, va_list)); + */ +void +__db_msgadd_ap(env, mbp, fmt, ap) + ENV *env; + DB_MSGBUF *mbp; + const char *fmt; + va_list ap; +{ + size_t len, olen; + char buf[2048]; /* !!!: END OF THE STACK DON'T TRUST SPRINTF. */ + + len = (size_t)vsnprintf(buf, sizeof(buf), fmt, ap); + + /* + * There's a heap buffer in the ENV handle we use to aggregate the + * message chunks. We maintain a pointer to the buffer, the next slot + * to be filled in in the buffer, and a total buffer length. + */ + olen = (size_t)(mbp->cur - mbp->buf); + if (olen + len >= mbp->len) { + if (__os_realloc(env, mbp->len + len + 256, &mbp->buf)) + return; + mbp->len += (len + 256); + mbp->cur = mbp->buf + olen; + } + + memcpy(mbp->cur, buf, len + 1); + mbp->cur += len; +} + +/* + * __db_msg -- + * Standard DB stat message routine. + * + * PUBLIC: void __db_msg __P((const ENV *, const char *, ...)) + * PUBLIC: __attribute__ ((__format__ (__printf__, 2, 3))); + */ +void +#ifdef STDC_HEADERS +__db_msg(const ENV *env, const char *fmt, ...) +#else +__db_msg(env, fmt, va_alist) + const ENV *env; + const char *fmt; + va_dcl +#endif +{ + DB_ENV *dbenv; + + dbenv = env == NULL ? NULL : env->dbenv; + + DB_REAL_MSG(dbenv, fmt); +} + +/* + * __db_repmsg -- + * Replication system message routine. + * + * PUBLIC: void __db_repmsg __P((const ENV *, const char *, ...)) + * PUBLIC: __attribute__ ((__format__ (__printf__, 2, 3))); + */ +void +#ifdef STDC_HEADERS +__db_repmsg(const ENV *env, const char *fmt, ...) +#else +__db_repmsg(env, fmt, va_alist) + const ENV *env; + const char *fmt; + va_dcl +#endif +{ + va_list ap; + char buf[2048]; /* !!!: END OF THE STACK DON'T TRUST SPRINTF. */ + +#ifdef STDC_HEADERS + va_start(ap, fmt); +#else + va_start(ap); +#endif + (void)vsnprintf(buf, sizeof(buf), fmt, ap); + __rep_msg(env, buf); + va_end(ap); +} + +/* + * __db_msgcall -- + * Do the message work for callback functions. + */ +static void +__db_msgcall(dbenv, fmt, ap) + const DB_ENV *dbenv; + const char *fmt; + va_list ap; +{ + char buf[2048]; /* !!!: END OF THE STACK DON'T TRUST SPRINTF. */ + + (void)vsnprintf(buf, sizeof(buf), fmt, ap); + + dbenv->db_msgcall(dbenv, buf); +} + +/* + * __db_msgfile -- + * Do the message work for FILE *s. + */ +static void +__db_msgfile(dbenv, fmt, ap) + const DB_ENV *dbenv; + const char *fmt; + va_list ap; +{ + FILE *fp; + + fp = dbenv == NULL || + dbenv->db_msgfile == NULL ? stdout : dbenv->db_msgfile; + (void)vfprintf(fp, fmt, ap); + + (void)fprintf(fp, "\n"); + (void)fflush(fp); +} + +/* + * __db_unknown_flag -- report internal error + * + * PUBLIC: int __db_unknown_flag __P((ENV *, char *, u_int32_t)); + */ +int +__db_unknown_flag(env, routine, flag) + ENV *env; + char *routine; + u_int32_t flag; +{ + __db_errx(env, DB_STR_A("0093", "%s: Unknown flag: %#x", "%s %#x"), + routine, (u_int)flag); + +#ifdef DIAGNOSTIC + __os_abort(env); + /* NOTREACHED */ +#endif + return (EINVAL); +} + +/* + * __db_unknown_type -- report internal database type error + * + * PUBLIC: int __db_unknown_type __P((ENV *, char *, DBTYPE)); + */ +int +__db_unknown_type(env, routine, type) + ENV *env; + char *routine; + DBTYPE type; +{ + __db_errx(env, DB_STR_A("0094", "%s: Unexpected database type: %s", + "%s %s"), routine, __db_dbtype_to_string(type)); + +#ifdef DIAGNOSTIC + __os_abort(env); + /* NOTREACHED */ +#endif + return (EINVAL); +} + +/* + * __db_unknown_path -- report unexpected database code path error. + * + * PUBLIC: int __db_unknown_path __P((ENV *, char *)); + */ +int +__db_unknown_path(env, routine) + ENV *env; + char *routine; +{ + __db_errx(env, DB_STR_A("0095", "%s: Unexpected code path error", + "%s"), routine); + +#ifdef DIAGNOSTIC + __os_abort(env); + /* NOTREACHED */ +#endif + return (EINVAL); +} + +/* + * __db_not_txn_env -- + * DB handle must be in an environment that supports transactions. + * + * PUBLIC: int __db_not_txn_env __P((ENV *)); + */ +int +__db_not_txn_env(env) + ENV *env; +{ + __db_errx(env, DB_STR("0103", + "DB environment not configured for transactions")); + return (EINVAL); +} + +/* + * __db_rec_toobig -- + * Fixed record length exceeded error message. + * + * PUBLIC: int __db_rec_toobig __P((ENV *, u_int32_t, u_int32_t)); + */ +int +__db_rec_toobig(env, data_len, fixed_rec_len) + ENV *env; + u_int32_t data_len, fixed_rec_len; +{ + __db_errx(env, DB_STR_A("0104", + "%lu larger than database's maximum record length %lu", + "%lu %lu"), (u_long)data_len, (u_long)fixed_rec_len); + return (EINVAL); +} + +/* + * __db_rec_repl -- + * Fixed record replacement length error message. + * + * PUBLIC: int __db_rec_repl __P((ENV *, u_int32_t, u_int32_t)); + */ +int +__db_rec_repl(env, data_size, data_dlen) + ENV *env; + u_int32_t data_size, data_dlen; +{ + __db_errx(env, DB_STR_A("0105", + "Record length error: " + "replacement length %lu differs from replaced length %lu", + "%lu %lu"), (u_long)data_size, (u_long)data_dlen); + return (EINVAL); +} + +#if defined(DIAGNOSTIC) || defined(DEBUG_ROP) || defined(DEBUG_WOP) +/* + * __dbc_logging -- + * In DIAGNOSTIC mode, check for bad replication combinations. + * + * PUBLIC: int __dbc_logging __P((DBC *)); + */ +int +__dbc_logging(dbc) + DBC *dbc; +{ + DB_REP *db_rep; + ENV *env; + int ret; + + env = dbc->env; + db_rep = env->rep_handle; + + ret = LOGGING_ON(env) && + !F_ISSET(dbc, DBC_RECOVER) && !IS_REP_CLIENT(env); + + /* + * If we're not using replication or running recovery, return. + */ + if (db_rep == NULL || F_ISSET(dbc, DBC_RECOVER)) + return (ret); + +#ifndef DEBUG_ROP + /* + * Only check when DEBUG_ROP is not configured. People often do + * non-transactional reads, and debug_rop is going to write + * a log record. + */ + { + REP *rep; + + rep = db_rep->region; + + /* + * If we're a client and not running recovery or non durably, error. + */ + if (IS_REP_CLIENT(env) && !F_ISSET(dbc->dbp, DB_AM_NOT_DURABLE)) { + __db_errx(env, DB_STR("0106", + "dbc_logging: Client update")); + goto err; + } + +#ifndef DEBUG_WOP + /* + * If DEBUG_WOP is enabled, then we'll generate debugging log records + * that are non-transactional. This is OK. + */ + if (IS_REP_MASTER(env) && + dbc->txn == NULL && !F_ISSET(dbc->dbp, DB_AM_NOT_DURABLE)) { + __db_errx(env, DB_STR("0107", + "Dbc_logging: Master non-txn update")); + goto err; + } +#endif + + if (0) { +err: __db_errx(env, DB_STR_A("0108", "Rep: flags 0x%lx msg_th %lu", + "%lx %lu"), (u_long)rep->flags, (u_long)rep->msg_th); + __db_errx(env, DB_STR_A("0109", "Rep: handle %lu, opcnt %lu", + "%lu %lu"), (u_long)rep->handle_cnt, (u_long)rep->op_cnt); + __os_abort(env); + /* NOTREACHED */ + } + } +#endif + return (ret); +} +#endif + +/* + * __db_check_lsn -- + * Display the log sequence error message. + * + * PUBLIC: int __db_check_lsn __P((ENV *, DB_LSN *, DB_LSN *)); + */ +int +__db_check_lsn(env, lsn, prev) + ENV *env; + DB_LSN *lsn, *prev; +{ + __db_errx(env, DB_STR_A("0110", + "Log sequence error: page LSN %lu %lu; previous LSN %lu %lu", + "%lu %lu %lu %lu"), (u_long)(lsn)->file, + (u_long)(lsn)->offset, (u_long)(prev)->file, + (u_long)(prev)->offset); + return (EINVAL); +} + +/* + * __db_rdonly -- + * Common readonly message. + * PUBLIC: int __db_rdonly __P((const ENV *, const char *)); + */ +int +__db_rdonly(env, name) + const ENV *env; + const char *name; +{ + __db_errx(env, DB_STR_A("0111", + "%s: attempt to modify a read-only database", "%s"), name); + return (EACCES); +} + +/* + * __db_space_err -- + * Common out of space message. + * PUBLIC: int __db_space_err __P((const DB *)); + */ +int +__db_space_err(dbp) + const DB *dbp; +{ + __db_errx(dbp->env, DB_STR_A("0112", + "%s: file limited to %lu pages", "%s %lu"), + dbp->fname, (u_long)dbp->mpf->mfp->maxpgno); + return (ENOSPC); +} + +/* + * __db_failed -- + * Common failed thread message. + * + * PUBLIC: int __db_failed __P((const ENV *, + * PUBLIC: const char *, pid_t, db_threadid_t)); + */ +int +__db_failed(env, msg, pid, tid) + const ENV *env; + const char *msg; + pid_t pid; + db_threadid_t tid; +{ + DB_ENV *dbenv; + char buf[DB_THREADID_STRLEN]; + + dbenv = env->dbenv; + + __db_errx(env, DB_STR_A("0113", "Thread/process %s failed: %s", + "%s %s"), dbenv->thread_id_string(dbenv, pid, tid, buf), msg); + return (DB_RUNRECOVERY); +} diff -r 000000000000 -r a1985f14b030 src/common/db_getlong.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/common/db_getlong.c Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,170 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 1996, 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + * $Id$ + */ + +#include "db_config.h" + +#include "db_int.h" + +/* + * __db_getlong -- + * Return a long value inside of basic parameters. + * + * PUBLIC: int __db_getlong + * PUBLIC: __P((DB_ENV *, const char *, char *, long, long, long *)); + */ +int +__db_getlong(dbenv, progname, p, min, max, storep) + DB_ENV *dbenv; + const char *progname; + char *p; + long min, max, *storep; +{ + long val; + char *end; + + __os_set_errno(0); + val = strtol(p, &end, 10); + if ((val == LONG_MIN || val == LONG_MAX) && + __os_get_errno() == ERANGE) { + if (dbenv != NULL) + dbenv->err(dbenv, ERANGE, "%s", p); + else + fprintf(stderr, "%s: %s: %s\n", + progname, p, strerror(ERANGE)); + return (ERANGE); + } + if (p[0] == '\0' || (end[0] != '\0' && end[0] != '\n')) { + if (dbenv != NULL) + dbenv->errx(dbenv, DB_STR_A("0043", + "%s: Invalid numeric argument", "%s"), p); + else + fprintf(stderr, DB_STR_A("0042", + "%s: %s: Invalid numeric argument\n", + "%s %s\n"), progname, p); + return (EINVAL); + } + if (val < min) { + if (dbenv != NULL) + dbenv->errx(dbenv, DB_STR_A("0045", + "%s: Less than minimum value (%ld)", + "%s %ld"), p, min); + else + fprintf(stderr, DB_STR_A("0044", + "%s: %s: Less than minimum value (%ld)\n", + "%s %s %ld\n"), progname, p, min); + return (ERANGE); + } + if (val > max) { + if (dbenv != NULL) + dbenv->errx(dbenv, DB_STR_A("0047", + "%s: Greater than maximum value (%ld)", + "%s %ld"), p, max); + else + fprintf(stderr, DB_STR_A("0046", + "%s: %s: Greater than maximum value (%ld)\n", + "%s %s %ld\n"), progname, p, max); + return (ERANGE); + } + *storep = val; + return (0); +} + +/* + * __db_getulong -- + * Return an unsigned long value inside of basic parameters. + * + * PUBLIC: int __db_getulong + * PUBLIC: __P((DB_ENV *, const char *, char *, u_long, u_long, u_long *)); + */ +int +__db_getulong(dbenv, progname, p, min, max, storep) + DB_ENV *dbenv; + const char *progname; + char *p; + u_long min, max, *storep; +{ + u_long val; + char *end; + + __os_set_errno(0); + val = strtoul(p, &end, 10); + if (val == ULONG_MAX && __os_get_errno() == ERANGE) { +#ifndef HAVE_RDS_BUILD + if (dbenv != NULL) + dbenv->err(dbenv, ERANGE, "%s", p); + else +#endif + fprintf(stderr, "%s: %s: %s\n", + progname, p, strerror(ERANGE)); + return (ERANGE); + } + if (p[0] == '\0' || (end[0] != '\0' && end[0] != '\n')) { + if (dbenv != NULL) + dbenv->errx(dbenv, DB_STR_A("0049", + "%s: Invalid numeric argument", + "%s"), p); + else + fprintf(stderr, DB_STR_A("0048", + "%s: %s: Invalid numeric argument\n", + "%s %s\n"), progname, p); + return (EINVAL); + } + if (val < min) { + if (dbenv != NULL) + dbenv->errx(dbenv, DB_STR_A("0051", + "%s: Less than minimum value (%lu)", + "%s %lu"), p, min); + else + fprintf(stderr, DB_STR_A("0050", + "%s: %s: Less than minimum value (%lu)\n", + "%s %s %lu\n"), progname, p, min); + return (ERANGE); + } + + /* + * We allow a 0 to substitute as a max value for ULONG_MAX because + * 1) accepting only a 0 value is unlikely to be necessary, and 2) + * we don't want callers to have to use ULONG_MAX explicitly, as it + * may not exist on all platforms. + */ + if (max != 0 && val > max) { + if (dbenv != NULL) + dbenv->errx(dbenv, DB_STR_A("0053", + "%s: Greater than maximum value (%lu)", + "%s %lu"), p, max); + else + fprintf(stderr, DB_STR_A("0052", + "%s: %s: Greater than maximum value (%lu)\n", + "%s %s %lu\n"), progname, p, max); + return (ERANGE); + } + *storep = val; + return (0); +} diff -r 000000000000 -r a1985f14b030 src/common/db_idspace.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/common/db_idspace.c Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,107 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 2001, 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + * $Id$ + */ + +#include "db_config.h" + +#include "db_int.h" + +static int __db_idcmp __P((const void *, const void *)); + +static int +__db_idcmp(a, b) + const void *a; + const void *b; +{ + u_int32_t i, j; + + i = *(u_int32_t *)a; + j = *(u_int32_t *)b; + + if (i < j) + return (-1); + else if (i > j) + return (1); + else + return (0); +} + +/* + * __db_idspace -- + * + * On input, minp and maxp contain the minimum and maximum valid values for + * the name space and on return, they contain the minimum and maximum ids + * available (by finding the biggest gap). The minimum can be an inuse + * value, but the maximum cannot be. + * + * PUBLIC: void __db_idspace __P((u_int32_t *, int, u_int32_t *, u_int32_t *)); + */ +void +__db_idspace(inuse, n, minp, maxp) + u_int32_t *inuse; + int n; + u_int32_t *minp, *maxp; +{ + int i, low; + u_int32_t gap, t; + + /* A single locker ID is a special case. */ + if (n == 1) { + /* + * If the single item in use is the last one in the range, + * then we've got to perform wrap which means that we set + * the min to the minimum ID, which is what we came in with, + * so we don't do anything. + */ + if (inuse[0] != *maxp) + *minp = inuse[0]; + *maxp = inuse[0] - 1; + return; + } + + gap = 0; + low = 0; + qsort(inuse, (size_t)n, sizeof(u_int32_t), __db_idcmp); + for (i = 0; i < n - 1; i++) + if ((t = (inuse[i + 1] - inuse[i])) > gap) { + gap = t; + low = i; + } + + /* Check for largest gap at the end of the space. */ + if ((*maxp - inuse[n - 1]) + (inuse[0] - *minp) > gap) { + /* Do same check as we do in the n == 1 case. */ + if (inuse[n - 1] != *maxp) + *minp = inuse[n - 1]; + *maxp = inuse[0] - 1; + } else { + *minp = inuse[low]; + *maxp = inuse[low + 1] - 1; + } +} diff -r 000000000000 -r a1985f14b030 src/common/db_log2.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/common/db_log2.c Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,79 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 1996, 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +/* + * Copyright (c) 1995, 1996 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Margo Seltzer. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $Id$ + */ + +#include "db_config.h" + +#include "db_int.h" + +/* + * PUBLIC: u_int32_t __db_log2 __P((u_int32_t)); + */ +u_int32_t +__db_log2(num) + u_int32_t num; +{ + u_int32_t i, limit; + + limit = 1; + for (i = 0; limit < num; limit = limit << 1) + ++i; + return (i); +} diff -r 000000000000 -r a1985f14b030 src/common/db_shash.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/common/db_shash.c Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,126 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 1996, 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + * $Id$ + */ + +#include "db_config.h" + +#include "db_int.h" + +/* + * __db_tablesize -- + * Choose a size for the hash table. + * + * PUBLIC: u_int32_t __db_tablesize __P((u_int32_t)); + */ +u_int32_t +__db_tablesize(n_buckets) + u_int32_t n_buckets; +{ + /* + * We try to be clever about how big we make the hash tables. Use a + * prime number close to the "suggested" number of elements that will + * be in the hash table. Use 32 as the minimum hash table size. + * + * Ref: Sedgewick, Algorithms in C, "Hash Functions" + * + * Up to ~250,000 buckets, we use powers of 2. After that, we slow + * the rate of increase by half. For each choice, we then use a + * nearby prime number as the hash value. + * + * If a terabyte is the maximum cache we'll see, and we assume there + * are 10 1K buckets on each hash chain, then 107374182 is the maximum + * number of buckets we'll ever need. + * + * We don't use the obvious static data structure because some C + * compilers (and I use the term loosely), can't handle them. + */ +#define HASH_SIZE(power, prime) { \ + if ((power) >= n_buckets) \ + return (prime); \ +} + HASH_SIZE(32, 37); /* 2^5 */ + HASH_SIZE(64, 67); /* 2^6 */ + HASH_SIZE(128, 131); /* 2^7 */ + HASH_SIZE(256, 257); /* 2^8 */ + HASH_SIZE(512, 521); /* 2^9 */ + HASH_SIZE(1024, 1031); /* 2^10 */ + HASH_SIZE(2048, 2053); /* 2^11 */ + HASH_SIZE(4096, 4099); /* 2^12 */ + HASH_SIZE(8192, 8191); /* 2^13 */ + HASH_SIZE(16384, 16381); /* 2^14 */ + HASH_SIZE(32768, 32771); /* 2^15 */ + HASH_SIZE(65536, 65537); /* 2^16 */ + HASH_SIZE(131072, 131071); /* 2^17 */ + HASH_SIZE(262144, 262147); /* 2^18 */ + HASH_SIZE(393216, 393209); /* 2^18 + 2^18/2 */ + HASH_SIZE(524288, 524287); /* 2^19 */ + HASH_SIZE(786432, 786431); /* 2^19 + 2^19/2 */ + HASH_SIZE(1048576, 1048573); /* 2^20 */ + HASH_SIZE(1572864, 1572869); /* 2^20 + 2^20/2 */ + HASH_SIZE(2097152, 2097169); /* 2^21 */ + HASH_SIZE(3145728, 3145721); /* 2^21 + 2^21/2 */ + HASH_SIZE(4194304, 4194301); /* 2^22 */ + HASH_SIZE(6291456, 6291449); /* 2^22 + 2^22/2 */ + HASH_SIZE(8388608, 8388617); /* 2^23 */ + HASH_SIZE(12582912, 12582917); /* 2^23 + 2^23/2 */ + HASH_SIZE(16777216, 16777213); /* 2^24 */ + HASH_SIZE(25165824, 25165813); /* 2^24 + 2^24/2 */ + HASH_SIZE(33554432, 33554393); /* 2^25 */ + HASH_SIZE(50331648, 50331653); /* 2^25 + 2^25/2 */ + HASH_SIZE(67108864, 67108859); /* 2^26 */ + HASH_SIZE(100663296, 100663291); /* 2^26 + 2^26/2 */ + HASH_SIZE(134217728, 134217757); /* 2^27 */ + HASH_SIZE(201326592, 201326611); /* 2^27 + 2^27/2 */ + HASH_SIZE(268435456, 268435459); /* 2^28 */ + HASH_SIZE(402653184, 402653189); /* 2^28 + 2^28/2 */ + HASH_SIZE(536870912, 536870909); /* 2^29 */ + HASH_SIZE(805306368, 805306357); /* 2^29 + 2^29/2 */ + HASH_SIZE(1073741824, 1073741827); /* 2^30 */ + return (1073741827); +} + +/* + * __db_hashinit -- + * Initialize a hash table that resides in shared memory. + * + * PUBLIC: void __db_hashinit __P((void *, u_int32_t)); + */ +void +__db_hashinit(begin, nelements) + void *begin; + u_int32_t nelements; +{ + u_int32_t i; + SH_TAILQ_HEAD(hash_head) *headp; + + headp = (struct hash_head *)begin; + + for (i = 0; i < nelements; i++, headp++) + SH_TAILQ_INIT(headp); +} diff -r 000000000000 -r a1985f14b030 src/common/dbt.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/common/dbt.c Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,96 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 1997, 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + * $Id$ + */ + +#include "db_config.h" + +#include "db_int.h" + +/* + * __dbt_usercopy -- + * Take a copy of the user's data, if a callback is supplied. + * + * PUBLIC: int __dbt_usercopy __P((ENV *, DBT *)); + */ +int +__dbt_usercopy(env, dbt) + ENV *env; + DBT *dbt; +{ + void *buf; + int ret; + + if (dbt == NULL || !F_ISSET(dbt, DB_DBT_USERCOPY) || dbt->size == 0 || + dbt->data != NULL) + return (0); + + buf = NULL; + if ((ret = __os_umalloc(env, dbt->size, &buf)) != 0 || + (ret = env->dbt_usercopy(dbt, 0, buf, dbt->size, + DB_USERCOPY_GETDATA)) != 0) + goto err; + dbt->data = buf; + + return (0); + +err: if (buf != NULL) { + __os_ufree(env, buf); + dbt->data = NULL; + } + + return (ret); +} + +/* + * __dbt_userfree -- + * Free a copy of the user's data, if necessary. + * + * PUBLIC: void __dbt_userfree __P((ENV *, DBT *, DBT *, DBT *)); + */ +void +__dbt_userfree(env, key, pkey, data) + ENV *env; + DBT *key, *pkey, *data; +{ + if (key != NULL && + F_ISSET(key, DB_DBT_USERCOPY) && key->data != NULL) { + __os_ufree(env, key->data); + key->data = NULL; + } + if (pkey != NULL && + F_ISSET(pkey, DB_DBT_USERCOPY) && pkey->data != NULL) { + __os_ufree(env, pkey->data); + pkey->data = NULL; + } + if (data != NULL && + F_ISSET(data, DB_DBT_USERCOPY) && data->data != NULL) { + __os_ufree(env, data->data); + data->data = NULL; + } +} diff -r 000000000000 -r a1985f14b030 src/common/mkpath.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/common/mkpath.c Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,90 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 1997, 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + * $Id$ + */ + +#include "db_config.h" + +#include "db_int.h" + +/* + * __db_mkpath -- -- + * Create intermediate directories. + * + * PUBLIC: int __db_mkpath __P((ENV *, const char *)); + */ +int +__db_mkpath(env, name) + ENV *env; + const char *name; +{ + size_t len; + int ret; + char *p, *t, savech; + + /* + * Get a copy so we can modify the string. It's a path and potentially + * quite long, so don't allocate the space on the stack. + */ + len = strlen(name) + 1; + if ((ret = __os_malloc(env, len, &t)) != 0) + return (ret); + memcpy(t, name, len); + + /* + * Cycle through the path, creating intermediate directories. + * + * Skip the first byte if it's a path separator, it's the start of an + * absolute pathname. + */ + if (PATH_SEPARATOR[1] == '\0') { + for (p = t + 1; p[0] != '\0'; ++p) + if (p[0] == PATH_SEPARATOR[0]) { + savech = *p; + *p = '\0'; + if (__os_exists(env, t, NULL) && + (ret = __os_mkdir( + env, t, env->dir_mode)) != 0) + break; + *p = savech; + } + } else + for (p = t + 1; p[0] != '\0'; ++p) + if (strchr(PATH_SEPARATOR, p[0]) != NULL) { + savech = *p; + *p = '\0'; + if (__os_exists(env, t, NULL) && + (ret = __os_mkdir( + env, t, env->dir_mode)) != 0) + break; + *p = savech; + } + + __os_free(env, t); + return (ret); +} diff -r 000000000000 -r a1985f14b030 src/common/os_method.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/common/os_method.c Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,292 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 1999, 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + * $Id$ + */ + +#include "db_config.h" + +#include "db_int.h" + +/* + * EXTERN: int db_env_set_func_assert + * EXTERN: __P((void (*)(const char *, const char *, int))); + */ +int +db_env_set_func_assert(func_assert) + void (*func_assert) __P((const char *, const char *, int)); +{ + DB_GLOBAL(j_assert) = func_assert; + return (0); +} + +/* + * EXTERN: int db_env_set_func_close __P((int (*)(int))); + */ +int +db_env_set_func_close(func_close) + int (*func_close) __P((int)); +{ + DB_GLOBAL(j_close) = func_close; + return (0); +} + +/* + * EXTERN: int db_env_set_func_dirfree __P((void (*)(char **, int))); + */ +int +db_env_set_func_dirfree(func_dirfree) + void (*func_dirfree) __P((char **, int)); +{ + DB_GLOBAL(j_dirfree) = func_dirfree; + return (0); +} + +/* + * EXTERN: int db_env_set_func_dirlist + * EXTERN: __P((int (*)(const char *, char ***, int *))); + */ +int +db_env_set_func_dirlist(func_dirlist) + int (*func_dirlist) __P((const char *, char ***, int *)); +{ + DB_GLOBAL(j_dirlist) = func_dirlist; + return (0); +} + +/* + * EXTERN: int db_env_set_func_exists __P((int (*)(const char *, int *))); + */ +int +db_env_set_func_exists(func_exists) + int (*func_exists) __P((const char *, int *)); +{ + DB_GLOBAL(j_exists) = func_exists; + return (0); +} + +/* + * EXTERN: int db_env_set_func_free __P((void (*)(void *))); + */ +int +db_env_set_func_free(func_free) + void (*func_free) __P((void *)); +{ + DB_GLOBAL(j_free) = func_free; + return (0); +} + +/* + * EXTERN: int db_env_set_func_fsync __P((int (*)(int))); + */ +int +db_env_set_func_fsync(func_fsync) + int (*func_fsync) __P((int)); +{ + DB_GLOBAL(j_fsync) = func_fsync; + return (0); +} + +/* + * EXTERN: int db_env_set_func_ftruncate __P((int (*)(int, off_t))); + */ +int +db_env_set_func_ftruncate(func_ftruncate) + int (*func_ftruncate) __P((int, off_t)); +{ + DB_GLOBAL(j_ftruncate) = func_ftruncate; + return (0); +} + +/* + * EXTERN: int db_env_set_func_ioinfo __P((int (*)(const char *, + * EXTERN: int, u_int32_t *, u_int32_t *, u_int32_t *))); + */ +int +db_env_set_func_ioinfo(func_ioinfo) + int (*func_ioinfo) + __P((const char *, int, u_int32_t *, u_int32_t *, u_int32_t *)); +{ + DB_GLOBAL(j_ioinfo) = func_ioinfo; + return (0); +} + +/* + * EXTERN: int db_env_set_func_malloc __P((void *(*)(size_t))); + */ +int +db_env_set_func_malloc(func_malloc) + void *(*func_malloc) __P((size_t)); +{ + DB_GLOBAL(j_malloc) = func_malloc; + return (0); +} + +/* + * EXTERN: int db_env_set_func_file_map + * EXTERN: __P((int (*)(DB_ENV *, char *, size_t, int, void **), + * EXTERN: int (*)(DB_ENV *, void *))); + */ +int +db_env_set_func_file_map(func_file_map, func_file_unmap) + int (*func_file_map) __P((DB_ENV *, char *, size_t, int, void **)); + int (*func_file_unmap) __P((DB_ENV *, void *)); +{ + DB_GLOBAL(j_file_map) = func_file_map; + DB_GLOBAL(j_file_unmap) = func_file_unmap; + return (0); +} + +/* + * EXTERN: int db_env_set_func_region_map + * EXTERN: __P((int (*)(DB_ENV *, char *, size_t, int *, void **), + * EXTERN: int (*)(DB_ENV *, void *))); + */ +int +db_env_set_func_region_map(func_region_map, func_region_unmap) + int (*func_region_map) __P((DB_ENV *, char *, size_t, int *, void **)); + int (*func_region_unmap) __P((DB_ENV *, void *)); +{ + DB_GLOBAL(j_region_map) = func_region_map; + DB_GLOBAL(j_region_unmap) = func_region_unmap; + return (0); +} + +/* + * EXTERN: int db_env_set_func_pread + * EXTERN: __P((ssize_t (*)(int, void *, size_t, off_t))); + */ +int +db_env_set_func_pread(func_pread) + ssize_t (*func_pread) __P((int, void *, size_t, off_t)); +{ + DB_GLOBAL(j_pread) = func_pread; + return (0); +} + +/* + * EXTERN: int db_env_set_func_pwrite + * EXTERN: __P((ssize_t (*)(int, const void *, size_t, off_t))); + */ +int +db_env_set_func_pwrite(func_pwrite) + ssize_t (*func_pwrite) __P((int, const void *, size_t, off_t)); +{ + DB_GLOBAL(j_pwrite) = func_pwrite; + return (0); +} + +/* + * EXTERN: int db_env_set_func_open __P((int (*)(const char *, int, ...))); + */ +int +db_env_set_func_open(func_open) + int (*func_open) __P((const char *, int, ...)); +{ + DB_GLOBAL(j_open) = func_open; + return (0); +} + +/* + * EXTERN: int db_env_set_func_read __P((ssize_t (*)(int, void *, size_t))); + */ +int +db_env_set_func_read(func_read) + ssize_t (*func_read) __P((int, void *, size_t)); +{ + DB_GLOBAL(j_read) = func_read; + return (0); +} + +/* + * EXTERN: int db_env_set_func_realloc __P((void *(*)(void *, size_t))); + */ +int +db_env_set_func_realloc(func_realloc) + void *(*func_realloc) __P((void *, size_t)); +{ + DB_GLOBAL(j_realloc) = func_realloc; + return (0); +} + +/* + * EXTERN: int db_env_set_func_rename + * EXTERN: __P((int (*)(const char *, const char *))); + */ +int +db_env_set_func_rename(func_rename) + int (*func_rename) __P((const char *, const char *)); +{ + DB_GLOBAL(j_rename) = func_rename; + return (0); +} + +/* + * EXTERN: int db_env_set_func_seek + * EXTERN: __P((int (*)(int, off_t, int))); + */ +int +db_env_set_func_seek(func_seek) + int (*func_seek) __P((int, off_t, int)); +{ + DB_GLOBAL(j_seek) = func_seek; + return (0); +} + +/* + * EXTERN: int db_env_set_func_unlink __P((int (*)(const char *))); + */ +int +db_env_set_func_unlink(func_unlink) + int (*func_unlink) __P((const char *)); +{ + DB_GLOBAL(j_unlink) = func_unlink; + return (0); +} + +/* + * EXTERN: int db_env_set_func_write + * EXTERN: __P((ssize_t (*)(int, const void *, size_t))); + */ +int +db_env_set_func_write(func_write) + ssize_t (*func_write) __P((int, const void *, size_t)); +{ + DB_GLOBAL(j_write) = func_write; + return (0); +} + +/* + * EXTERN: int db_env_set_func_yield __P((int (*)(u_long, u_long))); + */ +int +db_env_set_func_yield(func_yield) + int (*func_yield) __P((u_long, u_long)); +{ + DB_GLOBAL(j_yield) = func_yield; + return (0); +} diff -r 000000000000 -r a1985f14b030 src/common/rds_stub.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/common/rds_stub.c Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,1417 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + * $Id$ + */ + +#include "db_config.h" + +#include "db_int.h" +#include "dbinc/db_page.h" +#include "dbinc/log.h" +#include "dbinc/mp.h" +#include "dbinc/txn.h" + +/* + * If the library was built in the 'lite' version, various routines + * aren't available. Stub them here, returning an appropriate error. + */ +static int __db_rds __P((ENV *)); +static int __db_notransactions __P((ENV *)); + + + +/* + * __dbreg_get_name - a non-trival 'stub' function! + * + * Interface to get name of registered files. This is mainly diagnostic + * and the name passed could be transient unless there is something + * ensuring that the file cannot be closed. + * + * It is used in __lock_stat_print(). + */ +int +__dbreg_get_name(env, fid, fnamep, dnamep) + ENV *env; + u_int8_t *fid; + char **fnamep, **dnamep; +{ + *fnamep = ""; + *dnamep = NULL; + COMPQUIET(env, NULL); + COMPQUIET(fid, NULL); + return (-1); +} + +/* + * __db_rds -- + * Error when a restricted distribution invokes a full Berkeley DB feature. + * + * PUBLIC: + */ +static int +__db_rds(env) + ENV *env; +{ + __db_errx(env, DB_STR("0750", + "This RDS build does not include support for this function")); + __os_stack(env); + return (DB_OPNOTSUP); +} + +/* + * __db_notransactions -- + * Error when a Berkeley DB build doesn't include transaction support. + */ +static int +__db_notransactions(env) + ENV *env; +{ + __db_errx(env, DB_STR("0751", + "library build did not include support for transactions")); + __os_stack(env); + return (DB_OPNOTSUP); +} + +int +__db_check_chksum(env, hdr, db_cipher, chksum, data, data_len, is_hmac) + ENV *env; + void *hdr; + DB_CIPHER *db_cipher; + u_int8_t *chksum; + void *data; + size_t data_len; + int is_hmac; +{ + COMPQUIET(hdr, NULL); + COMPQUIET(db_cipher, NULL); + COMPQUIET(chksum, NULL); + COMPQUIET(data, NULL); + COMPQUIET(data_len, 0); + COMPQUIET(is_hmac, 0); + return (__db_rds(env)); +} + +int +__db_relink_log(DB *dbp, DB_TXN *txnp, DB_LSN *ret_lsnp, u_int32_t flags, db_pgno_t pgno, db_pgno_t new_pgno, db_pgno_t prev_pgno, DB_LSN * lsn_prev, + db_pgno_t next_pgno, DB_LSN * lsn_next) +{ + COMPQUIET(txnp, NULL); + COMPQUIET(ret_lsnp, NULL); + COMPQUIET(flags, 0); + COMPQUIET(pgno, 0); + COMPQUIET(new_pgno, 0); + COMPQUIET(prev_pgno, 0); + COMPQUIET(lsn_prev, NULL); + COMPQUIET(next_pgno, 0); + COMPQUIET(lsn_next, NULL); + return (__db_rds(dbp->env)); +} + +int +__db_relink_42_print(env, dbtp, lsnp, notused2, info) + ENV *env; + DBT *dbtp; + DB_LSN *lsnp; + db_recops notused2; + void *info; +{ + COMPQUIET(dbtp, NULL); + COMPQUIET(lsnp, NULL); + COMPQUIET(notused2, 0); + COMPQUIET(info, NULL); + return (__db_notransactions(env)); +} + +int +__db_relink_print(env, dbtp, lsnp, notused2, info) + ENV *env; + DBT *dbtp; + DB_LSN *lsnp; + db_recops notused2; + void *info; +{ + COMPQUIET(dbtp, NULL); + COMPQUIET(lsnp, NULL); + COMPQUIET(notused2, 0); + COMPQUIET(info, NULL); + return (__db_notransactions(env)); +} + +int +__db_relink_42_recover(env, dbtp, lsnp, op, info) + ENV *env; + DBT *dbtp; + DB_LSN *lsnp; + db_recops op; + void *info; +{ + COMPQUIET(dbtp, NULL); + COMPQUIET(lsnp, NULL); + COMPQUIET(op, 0); + COMPQUIET(info, NULL); + return (__db_notransactions(env)); +} + +int +__db_relink_recover(env, dbtp, lsnp, op, info) + ENV *env; + DBT *dbtp; + DB_LSN *lsnp; + db_recops op; + void *info; +{ + COMPQUIET(dbtp, NULL); + COMPQUIET(lsnp, NULL); + COMPQUIET(op, 0); + COMPQUIET(info, NULL); + return (__db_notransactions(env)); +} + +int +__db_upgrade_pp(dbp, fname, flags) + DB *dbp; + const char *fname; + u_int32_t flags; +{ + COMPQUIET(fname, NULL); + COMPQUIET(flags, 0); + return (__db_rds(dbp->env)); +} + +int +__dbreg_log_id(dbp, txn, id, needlock) + DB *dbp; + DB_TXN *txn; + int32_t id; + int needlock; +{ + COMPQUIET(txn, NULL); + COMPQUIET(id, 0); + COMPQUIET(needlock, 0); + return (__db_notransactions(dbp->env)); +} + +void +__dbreg_print_fname(env, fnp) + ENV *env; + FNAME *fnp; +{ + COMPQUIET(env, NULL); + COMPQUIET(fnp, NULL); +} + +int +__env_get_backup_config(dbenv, config, valuep) + DB_ENV *dbenv; + DB_BACKUP_CONFIG config; + u_int32_t *valuep; +{ + COMPQUIET(config, 0); + COMPQUIET(valuep, 0); + return (__db_rds(dbenv->env)); +} + +int +__env_set_backup_config(dbenv, config, value) + DB_ENV *dbenv; + DB_BACKUP_CONFIG config; + u_int32_t value; +{ + COMPQUIET(config, 0); + COMPQUIET(value, 0); + return (__db_rds(dbenv->env)); +} + +int +__env_get_backup_callbacks(dbenv, openp, writep, closep) + DB_ENV *dbenv; + int (**openp)(DB_ENV *, const char *, const char *, void **); + int (**writep)(DB_ENV *, + u_int32_t, u_int32_t, u_int32_t, u_int8_t *, void *); + int (**closep)(DB_ENV *, const char *, void *); +{ + COMPQUIET(openp, NULL); + COMPQUIET(writep, NULL); + COMPQUIET(closep, NULL); + return (__db_rds(dbenv->env)); +} + +int +__env_set_backup_callbacks(dbenv, open_func, write_func, close_func) + DB_ENV *dbenv; + int (*open_func)(DB_ENV *, const char *, const char *, void **); + int (*write_func)(DB_ENV *, + u_int32_t, u_int32_t, u_int32_t, u_int8_t *, void *); + int (*close_func)(DB_ENV *, const char *, void *); +{ + COMPQUIET(open_func, NULL); + COMPQUIET(write_func, NULL); + COMPQUIET(close_func, NULL); + return (__db_rds(dbenv->env)); +} + +int +__env_failchk_pp(dbenv, flags) + DB_ENV *dbenv; + u_int32_t flags; +{ + COMPQUIET(flags, 0); + return (__db_rds(dbenv->env)); +} + +int +__env_failchk_int(dbenv) + DB_ENV *dbenv; +{ + return (__db_rds(dbenv->env)); +} + +size_t +__env_thread_size(env, other_alloc) + ENV *env; + size_t other_alloc; +{ + COMPQUIET(env, NULL); + COMPQUIET(other_alloc, 0); + return (0); +} + +size_t +__env_thread_max(env) + ENV *env; +{ + COMPQUIET(env, NULL); + return (0); +} + +int +__env_thread_init(env, during_creation) + ENV *env; + int during_creation; +{ + COMPQUIET(env, NULL); + COMPQUIET(during_creation, 0); + return (0); +} + +void +__env_thread_destroy(env) + ENV *env; +{ + COMPQUIET(env, NULL); +} + +int +__env_set_state(env, ipp, state) + ENV *env; + DB_THREAD_INFO **ipp; + DB_THREAD_STATE state; +{ + COMPQUIET(ipp, NULL); + COMPQUIET(state, 0); + return (__db_rds(env)); +} + +int +__env_init_rec(env, version) + ENV *env; + u_int32_t version; +{ + COMPQUIET(version, 0); + return (__db_rds(env)); +} + +int +__env_init_rec_42(env) + ENV *env; +{ + return (__db_rds(env)); +} + +int +__env_init_rec_43(env) + ENV *env; +{ + return (__db_rds(env)); +} + +int +__env_init_rec_46(env) + ENV *env; +{ + return (__db_rds(env)); +} + +int +__env_init_rec_47(env) + ENV *env; +{ + return (__db_rds(env)); +} + +int +__env_init_rec_48(env) + ENV *env; +{ + return (__db_rds(env)); +} + +int +__envreg_register(env, need_recoveryp, flags) + ENV *env; + int *need_recoveryp; + u_int32_t flags; +{ + COMPQUIET(need_recoveryp, NULL); + COMPQUIET(flags, 0); + return (__db_rds(env)); +} + +int +__envreg_unregister(env, recovery_failed) + ENV *env; + int recovery_failed; +{ + COMPQUIET(recovery_failed, 0); + return (__db_rds(env)); +} + +int +__envreg_xunlock(env) + ENV *env; +{ + return (__db_rds(env)); +} + +int +__envreg_isalive(dbenv, pid, tid, flags ) + DB_ENV *dbenv; + pid_t pid; + db_threadid_t tid; + u_int32_t flags; +{ + COMPQUIET(pid, 0); + DB_THREADID_INIT(tid); + COMPQUIET(flags, 0); + return (__db_rds(dbenv->env)); +} + +int +__log_open(env) + ENV *env; +{ + return (__db_notransactions(env)); +} + +size_t +__log_region_size(env) + ENV *env; +{ + COMPQUIET(env, NULL); + return (0); +} + +size_t +__log_region_max(env) + ENV *env; +{ + COMPQUIET(env, NULL); + return (0); +} + +u_int32_t +__log_region_mutex_count(env) + ENV *env; +{ + COMPQUIET(env, NULL); + return (0); +} + +u_int32_t +__log_region_mutex_max(env) + ENV *env; +{ + COMPQUIET(env, NULL); + return (0); +} + +int +__log_archive_pp(dbenv, listp, flags) + DB_ENV *dbenv; + char ***listp; + u_int32_t flags; +{ + COMPQUIET(listp, NULL); + COMPQUIET(flags, 0); + return (__db_notransactions(dbenv->env)); +} + +int +__log_archive(env, listp, flags) + ENV *env; + char ***listp; + u_int32_t flags; +{ + COMPQUIET(listp, NULL); + COMPQUIET(flags, 0); + return (__db_notransactions(env)); +} + +int +__log_env_create(dbenv) + DB_ENV *dbenv; +{ + COMPQUIET(dbenv, NULL); + return (0); +} + +void +__log_env_destroy(dbenv) + DB_ENV *dbenv; +{ + COMPQUIET(dbenv, NULL); +} + +int +__log_get_config(dbenv, which, onp) + DB_ENV *dbenv; + u_int32_t which; + int *onp; +{ + COMPQUIET(which, 0); + COMPQUIET(onp, NULL); + return (__db_notransactions(dbenv->env)); +} + +int +__log_set_lg_bsize(dbenv, lg_bsize) + DB_ENV *dbenv; + u_int32_t lg_bsize; +{ + COMPQUIET(lg_bsize, 0); + return (__db_notransactions(dbenv->env)); +} + +int +__log_set_lg_filemode(dbenv, lg_mode) + DB_ENV *dbenv; + int lg_mode; +{ + COMPQUIET(lg_mode, 0); + return (__db_notransactions(dbenv->env)); +} + +int +__log_set_lg_max(dbenv, lg_max) + DB_ENV *dbenv; + u_int32_t lg_max; +{ + COMPQUIET(lg_max, 0); + return (__db_notransactions(dbenv->env)); +} + +int +__log_set_lg_regionmax(dbenv, lg_regionmax) + DB_ENV *dbenv; + u_int32_t lg_regionmax; +{ + COMPQUIET(lg_regionmax, 0); + return (__db_notransactions(dbenv->env)); +} + +int +__log_set_lg_dir(dbenv, dir) + DB_ENV *dbenv; + const char *dir; +{ + COMPQUIET(dir, NULL); + return (__db_notransactions(dbenv->env)); +} + +int +__log_set_config(dbenv, flags, on) + DB_ENV *dbenv; + u_int32_t flags; + int on; +{ + COMPQUIET(flags, 0); + COMPQUIET(on, 0); + return (__db_notransactions(dbenv->env)); +} + +int +__log_set_config_int(dbenv, flags, on, in_open) + DB_ENV *dbenv; + u_int32_t flags; + int on; + int in_open; +{ + COMPQUIET(flags, 0); + COMPQUIET(on, 0); + COMPQUIET(in_open, 0); + return (__db_notransactions(dbenv->env)); +} + +int +__log_flush_commit(env, lsnp, flags) + ENV *env; + const DB_LSN *lsnp; + u_int32_t flags; +{ + COMPQUIET(lsnp, NULL); + COMPQUIET(flags, 0); + return (__db_notransactions(env)); +} + +int +__log_flush_pp(dbenv, lsn) + DB_ENV *dbenv; + const DB_LSN *lsn; +{ + COMPQUIET(lsn, NULL); + return (__db_notransactions(dbenv->env)); +} + +int +__log_flush(env, lsn) + ENV *env; + const DB_LSN *lsn; +{ + COMPQUIET(lsn, NULL); + return (__db_notransactions(env)); +} + +int +__log_flush_int(dblp, lsnp, release) + DB_LOG *dblp; + const DB_LSN *lsnp; + int release; +{ + COMPQUIET(lsnp, NULL); + COMPQUIET(release, 0); + return (__db_notransactions(dblp->env)); +} + +int +__log_stat_print(env, flags) + ENV *env; + u_int32_t flags; +{ + COMPQUIET(flags, 0); + return (__db_notransactions(env)); +} + + +int +log_compare(lsn0, lsn1) + const DB_LSN *lsn0, *lsn1; +{ + COMPQUIET(lsn0, NULL); + COMPQUIET(lsn1, NULL); + return (__db_notransactions(NULL)); +} + +int +__log_check_page_lsn(env, dbp, lsnp) + ENV *env; + DB *dbp; + DB_LSN *lsnp; +{ + COMPQUIET(dbp, NULL); + COMPQUIET(lsnp, NULL); + return (__db_notransactions(env)); +} + +int +__log_current_lsn_int(env, lsnp, mbytesp, bytesp) + ENV *env; + DB_LSN *lsnp; + u_int32_t *mbytesp, *bytesp; +{ + COMPQUIET(lsnp, NULL); + COMPQUIET(mbytesp, NULL); + COMPQUIET(bytesp, NULL); + return (__db_notransactions(env)); +} + +int +__log_env_refresh(env) + ENV *env; +{ + return (__db_notransactions(env)); +} + +#ifdef STDC_HEADERS +int +__log_put_record(ENV *env, DB *dbp, DB_TXN *txnp, DB_LSN *ret_lsnp, + u_int32_t flags, u_int32_t rectype, u_int32_t has_data, u_int32_t size, + DB_LOG_RECSPEC *spec, ...) +#else +int +__log_put_record(env, dbp, txnp, ret_lsnp, + flags, rectype, has_data, size, spec, va_alist); + ENV *env; + DB *dbp; + DB_TXN *txnp; + DB_LSN *ret_lsnp; + u_int32_t flags; + u_int32_t rectype; + u_int32_t has_data; + u_int32_t size; + DB_LOG_RECSPEC *spec; + va_dcl +#endif +{ + COMPQUIET(dbp, NULL); + COMPQUIET(txnp, NULL); + COMPQUIET(ret_lsnp, NULL); + COMPQUIET(flags, 0); + COMPQUIET(rectype, 0); + COMPQUIET(has_data, 0); + COMPQUIET(size, 0); + COMPQUIET(spec, NULL); + return (__db_notransactions(env)); +} + +int +__log_read_record(env, dbpp, td, recbuf, spec, size, argpp) + ENV *env; + DB **dbpp; + void *td; + void *recbuf; + DB_LOG_RECSPEC *spec; + u_int32_t size; + void **argpp; +{ + COMPQUIET(dbpp, NULL); + COMPQUIET(td, NULL); + COMPQUIET(recbuf, NULL); + COMPQUIET(spec, NULL); + COMPQUIET(size, 0); + COMPQUIET(argpp, NULL); + return (__db_notransactions(env)); +} + +int +__db_relink_42_verify(env, dbtp, lsnp, notused2, lvhp) + ENV *env; + DBT *dbtp; + DB_LSN *lsnp; + db_recops notused2; + void *lvhp; +{ + COMPQUIET(dbtp, NULL); + COMPQUIET(lsnp, NULL); + COMPQUIET(notused2, 0); + COMPQUIET(lvhp, NULL); + return (__db_notransactions(env)); +} + +int +__db_relink_verify(env, dbtp, lsnp, notused2, lvhp) + ENV *env; + DBT *dbtp; + DB_LSN *lsnp; + db_recops notused2; + void *lvhp; +{ + COMPQUIET(dbtp, NULL); + COMPQUIET(lsnp, NULL); + COMPQUIET(notused2, 0); + COMPQUIET(lvhp, NULL); + return (__db_notransactions(env)); +} + +int +__db_dbtxn_remove(dbp, ip, txn, name, subdb) + DB *dbp; + DB_THREAD_INFO *ip; + DB_TXN *txn; + const char *name, *subdb; +{ + COMPQUIET(ip, NULL); + COMPQUIET(txn, NULL); + COMPQUIET(name, NULL); + COMPQUIET(subdb, NULL); + + return (__db_notransactions(dbp->env)); +} + +void +__db_chksum(hdr, data, data_len, mac_key, store) + void *hdr; + u_int8_t *data; + size_t data_len; + u_int8_t *mac_key; + u_int8_t *store; +{ + COMPQUIET(hdr, NULL); + COMPQUIET(data, NULL); + COMPQUIET(data_len, 0); + COMPQUIET(mac_key, NULL); + COMPQUIET(store, NULL); + (void)__db_rds(NULL); +} + +int +__fop_subdb_setup(dbp, ip, txn, mname, name, mode, flags) + DB *dbp; + DB_THREAD_INFO *ip; + DB_TXN *txn; + const char *mname, *name; + int mode; + u_int32_t flags; +{ + COMPQUIET(dbp, NULL); + COMPQUIET(ip, NULL); + COMPQUIET(mname, NULL); + COMPQUIET(name, NULL); + COMPQUIET(mode, 0); + COMPQUIET(flags, 0); + return (__db_rds(NULL)); +} + +int +__fop_dummy(dbp, txn, old, new) + DB *dbp; + DB_TXN *txn; + const char *old, *new; +{ + COMPQUIET(txn, NULL); + COMPQUIET(old, NULL); + COMPQUIET(new, NULL); + return (__db_notransactions(dbp->env)); +} + +int +__memp_backup_open(env, mpf, dbfile, target, flags, fpp, handlep) + ENV *env; + DB_MPOOLFILE *mpf; + const char *dbfile; + const char *target; + u_int32_t flags; + DB_FH **fpp; + void **handlep; +{ + COMPQUIET(mpf, NULL); + COMPQUIET(dbfile, NULL); + COMPQUIET(target, NULL); + COMPQUIET(flags, 0); + COMPQUIET(fpp, NULL); + COMPQUIET(handlep, NULL); + return (__db_rds(env)); +} + +int +__memp_backup_mpf(env, mpf, ip, first_pgno, last_pgno, fp, handle, flags) + ENV *env; + DB_MPOOLFILE *mpf; + DB_THREAD_INFO *ip; + db_pgno_t first_pgno, last_pgno; + DB_FH *fp; + void *handle; + u_int32_t flags; +{ + COMPQUIET(mpf, NULL); + COMPQUIET(ip, NULL); + COMPQUIET(first_pgno, 0); + COMPQUIET(last_pgno, 0); + COMPQUIET(fp, NULL); + COMPQUIET(handle, NULL); + COMPQUIET(flags, 0); + return (__db_rds(env)); +} + +int +__memp_backup_close(env, mpf, dbfile, fp, handle) + ENV *env; + DB_MPOOLFILE *mpf; + const char *dbfile; + DB_FH *fp; + void *handle; +{ + COMPQUIET(mpf, NULL); + COMPQUIET(dbfile, NULL); + COMPQUIET(fp, NULL); + COMPQUIET(handle, NULL); + return (__db_rds(env)); +} + +int +__memp_bh_freeze(dbmp, infop, hp, bhp, need_frozenp) + DB_MPOOL *dbmp; + REGINFO *infop; + DB_MPOOL_HASH *hp; + BH *bhp; + int *need_frozenp; +{ + COMPQUIET(infop, NULL); + COMPQUIET(hp, NULL); + COMPQUIET(bhp, NULL); + COMPQUIET(need_frozenp, NULL); + return (__db_rds(dbmp->env)); +} + +int +__memp_bh_thaw(dbmp, infop, hp, frozen_bhp, alloc_bhp) + DB_MPOOL *dbmp; + REGINFO *infop; + DB_MPOOL_HASH *hp; + BH *frozen_bhp, *alloc_bhp; +{ + COMPQUIET(infop, NULL); + COMPQUIET(hp, NULL); + COMPQUIET(frozen_bhp, NULL); + COMPQUIET(alloc_bhp, NULL); + return (__db_rds(dbmp->env)); +} + +int +__memp_bh_settxn(dbmp, mfp, bhp, vtd) + DB_MPOOL *dbmp; + MPOOLFILE *mfp; + BH *bhp; + void *vtd; +{ + COMPQUIET(mfp, NULL); + COMPQUIET(bhp, NULL); + COMPQUIET(vtd, NULL); + return (__db_notransactions(dbmp->env)); +} + +int +__memp_skip_curadj(dbc, pgno) + DBC *dbc; + db_pgno_t pgno; +{ + COMPQUIET(dbc, NULL); + COMPQUIET(pgno, 0); + return (FALSE); +} + +int +__txn_checkpoint_pp(dbenv, kbytes, minutes, flags) + DB_ENV *dbenv; + u_int32_t kbytes, minutes, flags; +{ + COMPQUIET(kbytes, 0); + COMPQUIET(minutes, 0); + COMPQUIET(flags, 0); + return (__db_notransactions(dbenv->env)); +} + +int +__txn_checkpoint(env, kbytes, minutes, flags) + ENV *env; + u_int32_t kbytes, minutes, flags; +{ + COMPQUIET(kbytes, 0); + COMPQUIET(minutes, 0); + COMPQUIET(flags, 0); + return (__db_notransactions(env)); +} + +int +__txn_env_create(dbenv) + DB_ENV *dbenv; +{ + COMPQUIET(dbenv, NULL); + return (0); +} + +void +__txn_env_destroy(dbenv) + DB_ENV *dbenv; +{ + COMPQUIET(dbenv, NULL); +} + +int +__txn_set_timeout(txn, timeout, op) + DB_TXN *txn; + db_timeout_t timeout; + u_int32_t op; +{ + COMPQUIET(txn, NULL); + COMPQUIET(timeout, 0); + COMPQUIET(op, 0); + return (0); +} + +int +__txn_set_tx_max(dbenv, tx_max) + DB_ENV *dbenv; + u_int32_t tx_max; +{ + COMPQUIET(tx_max, 0); + return (__db_notransactions(dbenv->env)); +} + +int +__txn_set_tx_timestamp(dbenv, timestamp) + DB_ENV *dbenv; + time_t *timestamp; +{ + COMPQUIET(timestamp, NULL); + return (__db_notransactions(dbenv->env)); +} + +int +__txn_begin(env, ip, parent, txnpp, flags) + ENV *env; + DB_THREAD_INFO *ip; + DB_TXN *parent, **txnpp; + u_int32_t flags; +{ + COMPQUIET(ip, NULL); + COMPQUIET(parent, NULL); + COMPQUIET(txnpp, NULL); + COMPQUIET(flags, 0); + return (__db_notransactions(env)); +} + +int +__txn_commit(txn, flags) + DB_TXN *txn; + u_int32_t flags; +{ + COMPQUIET(txn, NULL); + COMPQUIET(flags, 0); + return (__db_notransactions(NULL)); + +} + +int +__txn_abort(txn) + DB_TXN *txn; +{ + COMPQUIET(txn, NULL); + return (__db_notransactions(NULL)); +} + +int +__txn_preclose(env) + ENV *env; +{ + return (__db_notransactions(env)); +} + +int +__dbreg_setup(dbp, fname, dname, create_txnid) + DB *dbp; + const char *fname, *dname; + u_int32_t create_txnid; +{ + COMPQUIET(fname, NULL); + COMPQUIET(dname, NULL); + COMPQUIET(create_txnid, 0); + + return (__db_notransactions(dbp->env)); +} + +int +__dbreg_new_id(dbp, txn) + DB *dbp; + DB_TXN *txn; +{ + COMPQUIET(txn, NULL); + return (__db_notransactions(dbp->env)); +} + +int +__dbreg_revoke_id(dbp, have_lock, force_id) + DB *dbp; + int have_lock; + int32_t force_id; +{ + COMPQUIET(have_lock, 0); + COMPQUIET(force_id, 0); + return (__db_notransactions(dbp->env)); +} + +int +__dbreg_teardown(dbp) + DB *dbp; +{ + return (__db_notransactions(dbp->env)); +} + +int +__dbreg_close_id(dbp, txn, op) + DB *dbp; + DB_TXN *txn; + u_int32_t op; +{ + COMPQUIET(txn, NULL); + COMPQUIET(op, 0); + return (__db_notransactions(dbp->env)); +} + +int +__dbreg_stat_print(env, flags) + ENV *env; + u_int32_t flags; +{ + COMPQUIET(flags, 0); + return (__db_notransactions(env)); +} + +/* txn_util.c */ +int +__txn_closeevent(env, txn, dbp) + ENV *env; + DB_TXN *txn; + DB *dbp; +{ + COMPQUIET(txn, NULL); + COMPQUIET(dbp, NULL); + return (__db_notransactions(env)); +} + +int +__txn_remevent(env, txn, name, fileid, inmem) + ENV *env; + DB_TXN *txn; + const char *name; + u_int8_t *fileid; + int inmem; +{ + COMPQUIET(txn, NULL); + COMPQUIET(name, NULL); + COMPQUIET(fileid, NULL); + COMPQUIET(inmem, 0); + return (__db_notransactions(env)); +} + +void +__txn_remrem(env, txn, name) + ENV *env; + DB_TXN *txn; + const char *name; +{ + COMPQUIET(txn, NULL); + COMPQUIET(name, NULL); + (void) __db_notransactions(env); +} + +int +__txn_lockevent(env, txn, dbp, lock, locker) + ENV *env; + DB_TXN *txn; + DB *dbp; + DB_LOCK *lock; + DB_LOCKER *locker; +{ + COMPQUIET(txn, NULL); + COMPQUIET(dbp, NULL); + COMPQUIET(lock, NULL); + COMPQUIET(locker, NULL); + return (__db_notransactions(env)); +} + +void +__txn_remlock(env, txn, lock, locker) + ENV *env; + DB_TXN *txn; + DB_LOCK *lock; + DB_LOCKER *locker; +{ + COMPQUIET(txn, NULL); + COMPQUIET(lock, NULL); + COMPQUIET(locker, NULL); + (void) __db_notransactions(env); +} + +int +__txn_record_fname(env, txn, fname) + ENV *env; + DB_TXN *txn; + FNAME *fname; +{ + COMPQUIET(txn, NULL); + COMPQUIET(fname, NULL); + return (__db_notransactions(env)); +} + +void +__txn_remove_fe_watermark(txn, db) + DB_TXN *txn; + DB *db; +{ + COMPQUIET(txn, NULL); + COMPQUIET(db, NULL); +} + +void +__txn_add_fe_watermark(txn, db, pgno) + DB_TXN *txn; + DB *db; + db_pgno_t pgno; +{ + COMPQUIET(txn, NULL); + COMPQUIET(db, NULL); + COMPQUIET(pgno, 0); + return; +} + +int +__txn_pg_above_fe_watermark(txn, mpf, pgno) + DB_TXN *txn; + MPOOLFILE *mpf; + db_pgno_t pgno; +{ + COMPQUIET(txn, NULL); + COMPQUIET(mpf, NULL); + COMPQUIET(pgno, 0); + return (0); +} + +int +__txn_stat_print(env, flags) + ENV *env; + u_int32_t flags; +{ + COMPQUIET(flags, 0); + return (__db_notransactions(env)); +} + +/* txn_region.c */ +int +__txn_open(env) + ENV *env; +{ + return (__db_notransactions(env)); +} + +int +__txn_env_refresh(env) + ENV *env; +{ + return (__db_notransactions(env)); +} + +int +__txn_id_set(env, cur_txnid, max_txnid) + ENV *env; + u_int32_t cur_txnid, max_txnid; +{ + COMPQUIET(env, NULL); + COMPQUIET(cur_txnid, 0); + COMPQUIET(max_txnid, 0); + return (0); +} + +size_t +__txn_region_max(env) + ENV *env; +{ + COMPQUIET(env, NULL); + return (0); +} + +size_t +__txn_region_size(env) + ENV *env; +{ + COMPQUIET(env, NULL); + return (0); +} + +int +__txn_oldest_reader(env, lsnp) + ENV *env; + DB_LSN *lsnp; +{ + COMPQUIET(lsnp, NULL); + return (__db_notransactions(env)); +} + +int +__txn_add_buffer(env, td) + ENV *env; + TXN_DETAIL *td; +{ + COMPQUIET(td, NULL); + return (__db_notransactions(env)); +} + +int +__txn_remove_buffer(env, td, hash_mtx) + ENV *env; + TXN_DETAIL *td; + db_mutex_t hash_mtx; +{ + COMPQUIET(td, NULL); + COMPQUIET(hash_mtx, 0); + return (__db_notransactions(env)); +} + +u_int32_t +__txn_region_mutex_count(env) + ENV *env; +{ + COMPQUIET(env, NULL); + /* + * We need a mutex for DB_TXNMGR structure, two mutexes for + * the DB_TXNREGION structure. + */ + return (1 + 2); +} + +u_int32_t +__txn_region_mutex_max(env) + ENV *env; +{ + COMPQUIET(env, NULL); + return (0); +} + +int +__cdsgroup_begin_pp(dbenv, txnpp) + DB_ENV *dbenv; + DB_TXN **txnpp; +{ + COMPQUIET(txnpp, NULL); + return (__db_notransactions(dbenv->env)); +} + +int +__cdsgroup_begin(env, txnpp) + ENV *env; + DB_TXN **txnpp; +{ + COMPQUIET(txnpp, NULL); + return (__db_notransactions(env)); +} + +int +__db_check_txn(dbp, txn, assoc_locker, read_op) + DB *dbp; + DB_TXN *txn; + DB_LOCKER *assoc_locker; + int read_op; +{ + COMPQUIET(dbp, NULL); + COMPQUIET(txn, NULL); + COMPQUIET(assoc_locker, NULL); + COMPQUIET(read_op, 0); + return (0); +} + +int +__db_join_close(dbc) + DBC *dbc; +{ + return (__db_rds(dbc->env)); +} + +DB_LOG_RECSPEC __bam_split_desc[] = { { 0 , 0, NULL, { '\0' } } }; +DB_LOG_RECSPEC __bam_split_48_desc[] = { { 0 , 0, NULL, { '\0' } } }; +DB_LOG_RECSPEC __bam_split_42_desc[] = { { 0 , 0, NULL, { '\0' } } }; +DB_LOG_RECSPEC __bam_rsplit_desc[] = { { 0 , 0, NULL, { '\0' } } }; +DB_LOG_RECSPEC __bam_adj_desc[] = { { 0 , 0, NULL, { '\0' } } }; +DB_LOG_RECSPEC __bam_cadjust_desc[] = { { 0 , 0, NULL, { '\0' } } }; +DB_LOG_RECSPEC __bam_cdel_desc[] = { { 0 , 0, NULL, { '\0' } } }; +DB_LOG_RECSPEC __bam_repl_desc[] = { { 0 , 0, NULL, { '\0' } } }; +DB_LOG_RECSPEC __bam_irep_desc[] = { { 0 , 0, NULL, { '\0' } } }; +DB_LOG_RECSPEC __bam_root_desc[] = { { 0 , 0, NULL, { '\0' } } }; +DB_LOG_RECSPEC __bam_curadj_desc[] = { { 0 , 0, NULL, { '\0' } } }; +DB_LOG_RECSPEC __bam_rcuradj_desc[] = { { 0 , 0, NULL, { '\0' } } }; +DB_LOG_RECSPEC __bam_relink_43_desc[] = { { 0 , 0, NULL, { '\0' } } }; +DB_LOG_RECSPEC __bam_merge_44_desc[] = { { 0 , 0, NULL, { '\0' } } }; +DB_LOG_RECSPEC __crdel_metasub_desc[] = { { 0 , 0, NULL, { '\0' } } }; +DB_LOG_RECSPEC __crdel_inmem_create_desc[] = { { 0 , 0, NULL, { '\0' } } }; +DB_LOG_RECSPEC __crdel_inmem_rename_desc[] = { { 0 , 0, NULL, { '\0' } } }; +DB_LOG_RECSPEC __crdel_inmem_remove_desc[] = { { 0 , 0, NULL, { '\0' } } }; +DB_LOG_RECSPEC __db_addrem_desc[] = { { 0 , 0, NULL, { '\0' } } }; +DB_LOG_RECSPEC __db_addrem_42_desc[] = { { 0 , 0, NULL, { '\0' } } }; +DB_LOG_RECSPEC __db_big_desc[] = { { 0 , 0, NULL, { '\0' } } }; +DB_LOG_RECSPEC __db_big_42_desc[] = { { 0 , 0, NULL, { '\0' } } }; +DB_LOG_RECSPEC __db_ovref_desc[] = { { 0 , 0, NULL, { '\0' } } }; +DB_LOG_RECSPEC __db_relink_42_desc[] = { { 0 , 0, NULL, { '\0' } } }; +DB_LOG_RECSPEC __db_debug_desc[] = { { 0 , 0, NULL, { '\0' } } }; +DB_LOG_RECSPEC __db_noop_desc[] = { { 0 , 0, NULL, { '\0' } } }; +DB_LOG_RECSPEC __db_pg_alloc_42_desc[] = { { 0 , 0, NULL, { '\0' } } }; +DB_LOG_RECSPEC __db_pg_alloc_desc[] = { { 0 , 0, NULL, { '\0' } } }; +DB_LOG_RECSPEC __db_pg_free_42_desc[] = { { 0 , 0, NULL, { '\0' } } }; +DB_LOG_RECSPEC __db_pg_free_desc[] = { { 0 , 0, NULL, { '\0' } } }; +DB_LOG_RECSPEC __db_cksum_desc[] = { { 0 , 0, NULL, { '\0' } } }; +DB_LOG_RECSPEC __db_pg_freedata_42_desc[] = { { 0 , 0, NULL, { '\0' } } }; +DB_LOG_RECSPEC __db_pg_freedata_desc[] = { { 0 , 0, NULL, { '\0' } } }; +DB_LOG_RECSPEC __db_pg_init_desc[] = { { 0 , 0, NULL, { '\0' } } }; +DB_LOG_RECSPEC __db_pg_sort_44_desc[] = { { 0 , 0, NULL, { '\0' } } }; +DB_LOG_RECSPEC __db_pg_trunc_desc[] = { { 0 , 0, NULL, { '\0' } } }; +DB_LOG_RECSPEC __db_realloc_desc[] = { { 0 , 0, NULL, { '\0' } } }; +DB_LOG_RECSPEC __db_relink_desc[] = { { 0 , 0, NULL, { '\0' } } }; +DB_LOG_RECSPEC __db_merge_desc[] = { { 0 , 0, NULL, { '\0' } } }; +DB_LOG_RECSPEC __db_pgno_desc[] = { { 0 , 0, NULL, { '\0' } } }; +DB_LOG_RECSPEC __dbreg_register_desc[] = { { 0 , 0, NULL, { '\0' } } }; +DB_LOG_RECSPEC __fop_create_42_desc[] = { { 0 , 0, NULL, { '\0' } } }; +DB_LOG_RECSPEC __fop_create_desc[] = { { 0 , 0, NULL, { '\0' } } }; +DB_LOG_RECSPEC __fop_remove_desc[] = { { 0 , 0, NULL, { '\0' } } }; +DB_LOG_RECSPEC __fop_write_42_desc[] = { { 0 , 0, NULL, { '\0' } } }; +DB_LOG_RECSPEC __fop_write_desc[] = { { 0 , 0, NULL, { '\0' } } }; +DB_LOG_RECSPEC __fop_rename_42_desc[] = { { 0 , 0, NULL, { '\0' } } }; +DB_LOG_RECSPEC __fop_rename_noundo_46_desc[] = { { 0 , 0, NULL, { '\0' } } }; +DB_LOG_RECSPEC __fop_rename_desc[] = { { 0 , 0, NULL, { '\0' } } }; +DB_LOG_RECSPEC __fop_rename_noundo_desc[] = { { 0 , 0, NULL, { '\0' } } }; +DB_LOG_RECSPEC __fop_file_remove_desc[] = { { 0 , 0, NULL, { '\0' } } }; +DB_LOG_RECSPEC __ham_insdel_desc[] = { { 0 , 0, NULL, { '\0' } } }; +DB_LOG_RECSPEC __ham_insdel_42_desc[] = { { 0 , 0, NULL, { '\0' } } }; +DB_LOG_RECSPEC __ham_newpage_desc[] = { { 0 , 0, NULL, { '\0' } } }; +DB_LOG_RECSPEC __ham_splitdata_desc[] = { { 0 , 0, NULL, { '\0' } } }; +DB_LOG_RECSPEC __ham_replace_desc[] = { { 0 , 0, NULL, { '\0' } } }; +DB_LOG_RECSPEC __ham_replace_42_desc[] = { { 0 , 0, NULL, { '\0' } } }; +DB_LOG_RECSPEC __ham_copypage_desc[] = { { 0 , 0, NULL, { '\0' } } }; +DB_LOG_RECSPEC __ham_metagroup_42_desc[] = { { 0 , 0, NULL, { '\0' } } }; +DB_LOG_RECSPEC __ham_metagroup_desc[] = { { 0 , 0, NULL, { '\0' } } }; +DB_LOG_RECSPEC __ham_groupalloc_42_desc[] = { { 0 , 0, NULL, { '\0' } } }; +DB_LOG_RECSPEC __ham_groupalloc_desc[] = { { 0 , 0, NULL, { '\0' } } }; +DB_LOG_RECSPEC __ham_changeslot_desc[] = { { 0 , 0, NULL, { '\0' } } }; +DB_LOG_RECSPEC __ham_contract_desc[] = { { 0 , 0, NULL, { '\0' } } }; +DB_LOG_RECSPEC __ham_curadj_desc[] = { { 0 , 0, NULL, { '\0' } } }; +DB_LOG_RECSPEC __ham_chgpg_desc[] = { { 0 , 0, NULL, { '\0' } } }; +DB_LOG_RECSPEC __heap_addrem_desc[] = { { 0 , 0, NULL, { '\0' } } }; +DB_LOG_RECSPEC __heap_addrem_50_desc[] = { { 0 , 0, NULL, { '\0' } } }; +DB_LOG_RECSPEC __heap_pg_alloc_desc[] = { { 0 , 0, NULL, { '\0' } } }; +DB_LOG_RECSPEC __heap_trunc_meta_desc[] = { { 0 , 0, NULL, { '\0' } } }; +DB_LOG_RECSPEC __heap_trunc_page_desc[] = { { 0 , 0, NULL, { '\0' } } }; +DB_LOG_RECSPEC __qam_incfirst_desc[] = { { 0 , 0, NULL, { '\0' } } }; +DB_LOG_RECSPEC __qam_mvptr_desc[] = { { 0 , 0, NULL, { '\0' } } }; +DB_LOG_RECSPEC __qam_del_desc[] = { { 0 , 0, NULL, { '\0' } } }; +DB_LOG_RECSPEC __qam_add_desc[] = { { 0 , 0, NULL, { '\0' } } }; +DB_LOG_RECSPEC __qam_delext_desc[] = { { 0 , 0, NULL, { '\0' } } }; +DB_LOG_RECSPEC __repmgr_member_desc[] = { { 0 , 0, NULL, { '\0' } } }; +DB_LOG_RECSPEC __txn_regop_42_desc[] = { { 0 , 0, NULL, { '\0' } } }; +DB_LOG_RECSPEC __txn_regop_desc[] = { { 0 , 0, NULL, { '\0' } } }; +DB_LOG_RECSPEC __txn_ckp_42_desc[] = { { 0 , 0, NULL, { '\0' } } }; +DB_LOG_RECSPEC __txn_ckp_desc[] = { { 0 , 0, NULL, { '\0' } } }; +DB_LOG_RECSPEC __txn_child_desc[] = { { 0 , 0, NULL, { '\0' } } }; +DB_LOG_RECSPEC __txn_xa_regop_42_desc[] = { { 0 , 0, NULL, { '\0' } } }; +DB_LOG_RECSPEC __txn_prepare_desc[] = { { 0 , 0, NULL, { '\0' } } }; +DB_LOG_RECSPEC __txn_recycle_desc[] = { { 0 , 0, NULL, { '\0' } } }; diff -r 000000000000 -r a1985f14b030 src/common/util_cache.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/common/util_cache.c Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,69 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 2000, 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + * $Id$ + */ + +#include "db_config.h" + +#include "db_int.h" + +/* + * __db_util_cache -- + * Compute if we have enough cache. + * + * PUBLIC: int __db_util_cache __P((DB *, u_int32_t *, int *)); + */ +int +__db_util_cache(dbp, cachep, resizep) + DB *dbp; + u_int32_t *cachep; + int *resizep; +{ + u_int32_t pgsize; + int ret; + + /* Get the current page size. */ + if ((ret = dbp->get_pagesize(dbp, &pgsize)) != 0) + return (ret); + + /* + * The current cache size is in cachep. If it's insufficient, set the + * the memory referenced by resizep to 1 and set cachep to the minimum + * size needed. + * + * Make sure our current cache is big enough. We want at least + * DB_MINPAGECACHE pages in the cache. + */ + if ((*cachep / pgsize) < DB_MINPAGECACHE) { + *resizep = 1; + *cachep = pgsize * DB_MINPAGECACHE; + } else + *resizep = 0; + + return (0); +} diff -r 000000000000 -r a1985f14b030 src/common/util_log.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/common/util_log.c Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,67 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 2000, 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + * $Id$ + */ + +#include "db_config.h" + +#include "db_int.h" + +/* + * __db_util_logset -- + * Log that we're running. + * + * PUBLIC: int __db_util_logset __P((const char *, char *)); + */ +int +__db_util_logset(progname, fname) + const char *progname; + char *fname; +{ + pid_t pid; + FILE *fp; + time_t now; + char time_buf[CTIME_BUFLEN]; + + if ((fp = fopen(fname, "w")) == NULL) + goto err; + + (void)time(&now); + + __os_id(NULL, &pid, NULL); + fprintf(fp, + "%s: %lu %s", progname, (u_long)pid, __os_ctime(&now, time_buf)); + + if (fclose(fp) == EOF) + goto err; + + return (0); + +err: fprintf(stderr, "%s: %s: %s\n", progname, fname, strerror(errno)); + return (1); +} diff -r 000000000000 -r a1985f14b030 src/common/util_sig.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/common/util_sig.c Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,132 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 2000, 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + * $Id$ + */ + +#include "db_config.h" + +#include "db_int.h" + +static int interrupt; +static void set_signal __P((int, int)); +static void signal_handler __P((int)); + +/* + * signal_handler -- + * Interrupt signal handler. + */ +static void +signal_handler(signo) + int signo; +{ +#ifndef HAVE_SIGACTION + /* Assume signal() is unreliable and reset it, first thing. */ + set_signal(signo, 0); +#endif + /* Some systems don't pass in the correct signal value -- check. */ + if ((interrupt = signo) == 0) + interrupt = SIGINT; +} + +/* + * set_signal + */ +static void +set_signal(s, is_dflt) + int s, is_dflt; +{ + /* + * Use sigaction if it's available, otherwise use signal(). + */ +#ifdef HAVE_SIGACTION + struct sigaction sa, osa; + + sa.sa_handler = is_dflt ? SIG_DFL : signal_handler; + (void)sigemptyset(&sa.sa_mask); + sa.sa_flags = 0; + (void)sigaction(s, &sa, &osa); +#else + (void)signal(s, is_dflt ? SIG_DFL : signal_handler); +#endif +} + +/* + * __db_util_siginit -- + * + * PUBLIC: void __db_util_siginit __P((void)); + */ +void +__db_util_siginit() +{ + /* + * Initialize the set of signals for which we want to clean up. + * Generally, we try not to leave the shared regions locked if + * we can. + */ +#ifdef SIGHUP + set_signal(SIGHUP, 0); +#endif +#ifdef SIGINT + set_signal(SIGINT, 0); +#endif +#ifdef SIGPIPE + set_signal(SIGPIPE, 0); +#endif +#ifdef SIGTERM + set_signal(SIGTERM, 0); +#endif +} + +/* + * __db_util_interrupted -- + * Return if interrupted. + * + * PUBLIC: int __db_util_interrupted __P((void)); + */ +int +__db_util_interrupted() +{ + return (interrupt != 0); +} + +/* + * __db_util_sigresend -- + * + * PUBLIC: void __db_util_sigresend __P((void)); + */ +void +__db_util_sigresend() +{ + /* Resend any caught signal. */ + if (interrupt != 0) { + set_signal(interrupt, 1); + + (void)raise(interrupt); + /* NOTREACHED */ + } +} diff -r 000000000000 -r a1985f14b030 src/common/zerofill.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/common/zerofill.c Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,151 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 1997, 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + * $Id$ + */ + +#include "db_config.h" + +#include "db_int.h" + +/* + * __db_zero_fill -- + * Zero out bytes in the file. + * + * Pages allocated by writing pages past end-of-file are not zeroed, + * on some systems. Recovery could theoretically be fooled by a page + * showing up that contained garbage. In order to avoid this, we + * have to write the pages out to disk, and flush them. The reason + * for the flush is because if we don't sync, the allocation of another + * page subsequent to this one might reach the disk first, and if we + * crashed at the right moment, leave us with this page as the one + * allocated by writing a page past it in the file. + * + * PUBLIC: int __db_zero_fill __P((ENV *, DB_FH *)); + */ +int +__db_zero_fill(env, fhp) + ENV *env; + DB_FH *fhp; +{ +#ifdef HAVE_FILESYSTEM_NOTZERO + off_t stat_offset, write_offset; + size_t blen, nw; + u_int32_t bytes, mbytes; + int group_sync, ret; + u_int8_t *bp; + + /* Calculate the byte offset of the next write. */ + write_offset = (off_t)fhp->pgno * fhp->pgsize + fhp->offset; + + /* Stat the file. */ + if ((ret = __os_ioinfo(env, NULL, fhp, &mbytes, &bytes, NULL)) != 0) + return (ret); + stat_offset = (off_t)mbytes * MEGABYTE + bytes; + + /* Check if the file is large enough. */ + if (stat_offset >= write_offset) + return (0); + + /* Get a large buffer if we're writing lots of data. */ +#undef ZF_LARGE_WRITE +#define ZF_LARGE_WRITE (64 * 1024) + if ((ret = __os_calloc(env, 1, ZF_LARGE_WRITE, &bp)) != 0) + return (ret); + blen = ZF_LARGE_WRITE; + + /* Seek to the current end of the file. */ + if ((ret = __os_seek(env, fhp, mbytes, MEGABYTE, bytes)) != 0) + goto err; + + /* + * Hash is the only access method that allocates groups of pages. Hash + * uses the existence of the last page in a group to signify the entire + * group is OK; so, write all the pages but the last one in the group, + * flush them to disk, then write the last one to disk and flush it. + */ + for (group_sync = 0; stat_offset < write_offset; group_sync = 1) { + if (write_offset - stat_offset <= (off_t)blen) { + blen = (size_t)(write_offset - stat_offset); + if (group_sync && (ret = __os_fsync(env, fhp)) != 0) + goto err; + } + if ((ret = __os_physwrite(env, fhp, bp, blen, &nw)) != 0) + goto err; + stat_offset += blen; + } + if ((ret = __os_fsync(env, fhp)) != 0) + goto err; + + /* Seek back to where we started. */ + mbytes = (u_int32_t)(write_offset / MEGABYTE); + bytes = (u_int32_t)(write_offset % MEGABYTE); + ret = __os_seek(env, fhp, mbytes, MEGABYTE, bytes); + +err: __os_free(env, bp); + return (ret); +#else + COMPQUIET(env, NULL); + COMPQUIET(fhp, NULL); + return (0); +#endif /* HAVE_FILESYSTEM_NOTZERO */ +} + +/* + * __db_zero -- + * Zero to the end of the file. + * + * PUBLIC: int __db_zero_extend __P((ENV *, + * PUBLIC: DB_FH *, db_pgno_t, db_pgno_t, u_int32_t)); + */ +int +__db_zero_extend(env, fhp, pgno, last_pgno, pgsize) + ENV *env; + DB_FH *fhp; + db_pgno_t pgno, last_pgno; + u_int32_t pgsize; +{ + int ret; + size_t nwrote; + u_int8_t *buf; + + if ((ret = __os_calloc(env, 1, pgsize, &buf)) != 0) + return (ret); + memset(buf, 0, pgsize); + for (; pgno <= last_pgno; pgno++) + if ((ret = __os_io(env, DB_IO_WRITE, + fhp, pgno, pgsize, 0, pgsize, buf, &nwrote)) != 0) { + if (ret == 0) { + ret = EIO; + goto err; + } + goto err; + } + +err: __os_free(env, buf); + return (ret); +} diff -r 000000000000 -r a1985f14b030 src/db/db.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/db/db.c Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,1681 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 1996, 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +/* + * Copyright (c) 1990, 1993, 1994, 1995, 1996 + * Keith Bostic. All rights reserved. + */ +/* + * Copyright (c) 1990, 1993, 1994, 1995 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $Id$ + */ + +#include "db_config.h" + +#include "db_int.h" +#include "dbinc/db_page.h" +#include "dbinc/db_swap.h" +#include "dbinc/btree.h" +#include "dbinc/fop.h" +#include "dbinc/hash.h" +#include "dbinc/heap.h" +#include "dbinc/lock.h" +#include "dbinc/mp.h" +#include "dbinc/partition.h" +#include "dbinc/qam.h" +#include "dbinc/txn.h" + +static int __db_disassociate __P((DB *)); +static int __db_disassociate_foreign __P ((DB *)); + +#ifdef CONFIG_TEST +static int __db_makecopy __P((ENV *, const char *, const char *)); +static int __qam_testdocopy __P((DB *, const char *)); +#endif + +/* + * DB.C -- + * This file contains the utility functions for the DBP layer. + */ + +/* + * __db_master_open -- + * Open up a handle on a master database. + * + * PUBLIC: int __db_master_open __P((DB *, DB_THREAD_INFO *, + * PUBLIC: DB_TXN *, const char *, u_int32_t, int, DB **)); + */ +int +__db_master_open(subdbp, ip, txn, name, flags, mode, dbpp) + DB *subdbp; + DB_THREAD_INFO *ip; + DB_TXN *txn; + const char *name; + u_int32_t flags; + int mode; + DB **dbpp; +{ + DB *dbp; + int ret; + + *dbpp = NULL; + + /* Open up a handle on the main database. */ + if ((ret = __db_create_internal(&dbp, subdbp->env, 0)) != 0) + return (ret); + + /* + * It's always a btree. + * Run in the transaction we've created. + * Set the pagesize in case we're creating a new database. + * Flag that we're creating a database with subdatabases. + */ + dbp->pgsize = subdbp->pgsize; + F_SET(dbp, DB_AM_SUBDB); + F_SET(dbp, F_ISSET(subdbp, + DB_AM_RECOVER | DB_AM_SWAP | + DB_AM_ENCRYPT | DB_AM_CHKSUM | DB_AM_NOT_DURABLE)); + + /* + * If there was a subdb specified, then we only want to apply + * DB_EXCL to the subdb, not the actual file. We only got here + * because there was a subdb specified. + */ + LF_CLR(DB_EXCL); + LF_SET(DB_RDWRMASTER); + if ((ret = __db_open(dbp, ip, txn, + name, NULL, DB_BTREE, flags, mode, PGNO_BASE_MD)) != 0) + goto err; + + /* + * The items in dbp are initialized from the master file's meta page. + * Other items such as checksum and encryption are checked when we + * read the meta-page, so we do not check those here. However, if + * the meta-page caused checksumming to be turned on and it wasn't + * already, set it here. + */ + if (F_ISSET(dbp, DB_AM_CHKSUM)) + F_SET(subdbp, DB_AM_CHKSUM); + + /* + * The user may have specified a page size for an existing file, + * which we want to ignore. + */ + subdbp->pgsize = dbp->pgsize; + *dbpp = dbp; + + if (0) { +err: if (!F_ISSET(dbp, DB_AM_DISCARD)) + (void)__db_close(dbp, txn, DB_NOSYNC); + } + + return (ret); +} + +/* + * __db_master_update -- + * Add/Open/Remove a subdatabase from a master database. + * + * PUBLIC: int __db_master_update __P((DB *, DB *, DB_THREAD_INFO *, DB_TXN *, + * PUBLIC: const char *, DBTYPE, mu_action, const char *, u_int32_t)); + */ +int +__db_master_update(mdbp, sdbp, ip, txn, subdb, type, action, newname, flags) + DB *mdbp, *sdbp; + DB_TXN *txn; + DB_THREAD_INFO *ip; + const char *subdb; + DBTYPE type; + mu_action action; + const char *newname; + u_int32_t flags; +{ + DBC *dbc, *ndbc; + DBT key, data, ndata; + ENV *env; + PAGE *p, *r; + db_pgno_t t_pgno; + int modify, ret, t_ret; + + env = mdbp->env; + dbc = ndbc = NULL; + p = NULL; + + /* + * Open up a cursor. If this is CDB and we're creating the database, + * make it an update cursor. + * + * Might we modify the master database? If so, we'll need to lock. + */ + modify = (!F_ISSET(mdbp, DB_AM_RDONLY) && + (action != MU_OPEN || LF_ISSET(DB_CREATE))) ? 1 : 0; + + if ((ret = __db_cursor(mdbp, ip, txn, &dbc, + (CDB_LOCKING(env) && modify) ? DB_WRITECURSOR : 0)) != 0) + return (ret); + + /* + * Point the cursor at the record. + * + * If we're removing or potentially creating an entry, lock the page + * with DB_RMW. + * + * We do multiple cursor operations with the cursor in some cases and + * subsequently access the data DBT information. Set DB_DBT_MALLOC so + * we don't risk modification of the data between our uses of it. + * + * !!! + * We don't include the name's nul termination in the database. + */ + DB_INIT_DBT(key, subdb, strlen(subdb)); + memset(&data, 0, sizeof(data)); + F_SET(&data, DB_DBT_MALLOC); + + ret = __dbc_get(dbc, &key, &data, + DB_SET | ((STD_LOCKING(dbc) && modify) ? DB_RMW : 0)); + + /* + * What we do next--whether or not we found a record for the + * specified subdatabase--depends on what the specified action is. + * Handle ret appropriately as the first statement of each case. + */ + switch (action) { + case MU_REMOVE: + /* + * We should have found something if we're removing it. Note + * that in the common case where the DB we're asking to remove + * doesn't exist, we won't get this far; __db_subdb_remove + * will already have returned an error from __db_open. + */ + if (ret != 0) + goto err; + + /* + * Delete the subdatabase entry first; if this fails, + * we don't want to touch the actual subdb pages. + */ + if ((ret = __dbc_del(dbc, 0)) != 0) + goto err; + + /* + * We're handling actual data, not on-page meta-data, + * so it hasn't been converted to/from opposite + * endian architectures. Do it explicitly, now. + */ + memcpy(&sdbp->meta_pgno, data.data, sizeof(db_pgno_t)); + DB_NTOHL_SWAP(env, &sdbp->meta_pgno); + if ((ret = __memp_fget(mdbp->mpf, &sdbp->meta_pgno, + ip, dbc->txn, DB_MPOOL_DIRTY, &p)) != 0) + goto err; + + /* Free the root on the master db if it was created. */ + if (TYPE(p) == P_BTREEMETA && + ((BTMETA *)p)->root != PGNO_INVALID) { + if ((ret = __memp_fget(mdbp->mpf, + &((BTMETA *)p)->root, ip, dbc->txn, + DB_MPOOL_DIRTY, &r)) != 0) + goto err; + + /* Free and put the page. */ + if ((ret = __db_free(dbc, r, 0)) != 0) { + r = NULL; + goto err; + } + } + /* Free and put the page. */ + if ((ret = __db_free(dbc, p, 0)) != 0) { + p = NULL; + goto err; + } + p = NULL; + break; + case MU_RENAME: + /* We should have found something if we're renaming it. */ + if (ret != 0) + goto err; + + /* + * Before we rename, we need to make sure we're not + * overwriting another subdatabase, or else this operation + * won't be undoable. Open a second cursor and check + * for the existence of newname; it shouldn't appear under + * us since we hold the metadata lock. + */ + if ((ret = __db_cursor(mdbp, ip, txn, &ndbc, + CDB_LOCKING(env) ? DB_WRITECURSOR : 0)) != 0) + goto err; + DB_SET_DBT(key, newname, strlen(newname)); + + /* + * We don't actually care what the meta page of the potentially- + * overwritten DB is; we just care about existence. + */ + memset(&ndata, 0, sizeof(ndata)); + F_SET(&ndata, DB_DBT_USERMEM | DB_DBT_PARTIAL); + + if ((ret = __dbc_get(ndbc, &key, &ndata, DB_SET)) == 0) { + /* A subdb called newname exists. Bail. */ + ret = EEXIST; + __db_errx(env, DB_STR_A("0673", + "rename: database %s exists", "%s"), newname); + goto err; + } else if (ret != DB_NOTFOUND) + goto err; + + /* + * Now do the put first; we don't want to lose our only + * reference to the subdb. Use the second cursor so the + * first one continues to point to the old record. + */ + if ((ret = __dbc_put(ndbc, &key, &data, DB_KEYFIRST)) != 0) + goto err; + if ((ret = __dbc_del(dbc, 0)) != 0) { + /* + * If the delete fails, try to delete the record + * we just put, in case we're not txn-protected. + */ + (void)__dbc_del(ndbc, 0); + goto err; + } + + break; + case MU_OPEN: + /* + * Get the subdatabase information. If it already exists, + * copy out the page number and we're done. + */ + switch (ret) { + case 0: + if (LF_ISSET(DB_CREATE) && LF_ISSET(DB_EXCL)) { + ret = EEXIST; + goto err; + } + memcpy(&sdbp->meta_pgno, data.data, sizeof(db_pgno_t)); + DB_NTOHL_SWAP(env, &sdbp->meta_pgno); + goto done; + case DB_NOTFOUND: + if (LF_ISSET(DB_CREATE)) + break; + /* + * No db_err, it is reasonable to remove a + * nonexistent db. + */ + ret = ENOENT; + goto err; + default: + goto err; + } + + /* Create a subdatabase. */ + if (F_ISSET(mdbp, DB_AM_RDONLY)) { + ret = EBADF; + goto err; + } + if ((ret = __db_new(dbc, + type == DB_HASH ? P_HASHMETA : P_BTREEMETA, NULL, &p)) != 0) + goto err; + sdbp->meta_pgno = PGNO(p); + + /* + * XXX + * We're handling actual data, not on-page meta-data, so it + * hasn't been converted to/from opposite endian architectures. + * Do it explicitly, now. + */ + t_pgno = PGNO(p); + DB_HTONL_SWAP(env, &t_pgno); + memset(&ndata, 0, sizeof(ndata)); + ndata.data = &t_pgno; + ndata.size = sizeof(db_pgno_t); + if ((ret = __dbc_put(dbc, &key, &ndata, 0)) != 0) + goto err; + F_SET(sdbp, DB_AM_CREATED); + break; + + case MU_MOVE: + /* We should have found something if we're moving it. */ + if (ret != 0) + goto err; + t_pgno = sdbp->meta_pgno; + DB_HTONL_SWAP(env, &t_pgno); + memset(&ndata, 0, sizeof(ndata)); + ndata.data = &t_pgno; + ndata.size = sizeof(db_pgno_t); + if ((ret = __dbc_put(dbc, &key, &ndata, 0)) != 0) + goto err; + mdbp->mpf->mfp->revision++; + } + +err: +done: /* + * If we allocated a page: if we're successful, mark the page dirty + * and return it to the cache, otherwise, discard/free it. + */ + if (p != NULL && (t_ret = __memp_fput(mdbp->mpf, + dbc->thread_info, p, dbc->priority)) != 0 && ret == 0) + ret = t_ret; + + /* Discard the cursor(s) and data. */ + if (data.data != NULL) + __os_ufree(env, data.data); + if (dbc != NULL && (t_ret = __dbc_close(dbc)) != 0 && ret == 0) + ret = t_ret; + if (ndbc != NULL && (t_ret = __dbc_close(ndbc)) != 0 && ret == 0) + ret = t_ret; + + return (ret); +} + +/* + * __env_dbreg_setup -- + * + * PUBLIC: int __env_dbreg_setup __P((DB *, + * PUBLIC: DB_TXN *, const char *, const char *, u_int32_t)); + */ +int +__env_dbreg_setup(dbp, txn, fname, dname, id) + DB *dbp; + DB_TXN *txn; + const char *fname, *dname; + u_int32_t id; +{ + ENV *env; + int ret; + + env = dbp->env; + if (dbp->log_filename == NULL +#if !defined(DEBUG_ROP) && !defined(DEBUG_WOP) && !defined(DIAGNOSTIC) + && (txn != NULL || F_ISSET(dbp, DB_AM_RECOVER)) +#endif +#if !defined(DEBUG_ROP) + && !F_ISSET(dbp, DB_AM_RDONLY) +#endif + ) { + if ((ret = __dbreg_setup(dbp, + F_ISSET(dbp, DB_AM_INMEM) ? dname: fname, + F_ISSET(dbp, DB_AM_INMEM) ? NULL : dname, id)) != 0) + return (ret); + + /* + * If we're actively logging and our caller isn't a + * recovery function that already did so, then assign + * this dbp a log fileid. + */ + if (DBENV_LOGGING(env) && !F_ISSET(dbp, DB_AM_RECOVER) && + (ret = __dbreg_new_id(dbp, txn)) != 0) + return (ret); + } + return (0); +} + +/* + * __env_setup -- + * Set up the underlying environment during a db_open. + * + * PUBLIC: int __env_setup __P((DB *, + * PUBLIC: DB_TXN *, const char *, const char *, u_int32_t, u_int32_t)); + */ +int +__env_setup(dbp, txn, fname, dname, id, flags) + DB *dbp; + DB_TXN *txn; + const char *fname, *dname; + u_int32_t id, flags; +{ + DB *ldbp; + DB_ENV *dbenv; + ENV *env; + u_int32_t maxid; + int ret; + + env = dbp->env; + dbenv = env->dbenv; + + /* + * When verifying an in-memory db, we need to pass dname to + * __env_mpool. That is the only time fname will be used. + */ + if (F_ISSET(dbp, DB_AM_INMEM) && F_ISSET(dbp, DB_AM_VERIFYING)) + fname = dname; + + /* If we don't yet have an environment, it's time to create it. */ + if (!F_ISSET(env, ENV_OPEN_CALLED)) { +#if defined(HAVE_MIXED_SIZE_ADDRESSING) && (SIZEOF_CHAR_P == 8) + __db_errx(env, DB_STR("0701", "DB_PRIVATE is not supported by" + " 64-bit applications in mixed-size-addressing mode")); + return (EINVAL); +#endif + /* Make sure we have at least DB_MINCACHE pages in our cache. */ + if (dbenv->mp_gbytes == 0 && + dbenv->mp_bytes < dbp->pgsize * DB_MINPAGECACHE && + (ret = __memp_set_cachesize( + dbenv, 0, dbp->pgsize * DB_MINPAGECACHE, 0)) != 0) + return (ret); + + if ((ret = __env_open(dbenv, NULL, DB_CREATE | + DB_INIT_MPOOL | DB_PRIVATE | LF_ISSET(DB_THREAD), 0)) != 0) + return (ret); + } + + /* Join the underlying cache. */ + if ((!F_ISSET(dbp, DB_AM_INMEM) || F_ISSET(dbp, DB_AM_VERIFYING) || + dname == NULL) && (ret = __env_mpool(dbp, fname, flags)) != 0) + return (ret); + + /* We may need a per-thread mutex. */ + if (LF_ISSET(DB_THREAD) && (ret = __mutex_alloc( + env, MTX_DB_HANDLE, DB_MUTEX_PROCESS_ONLY, &dbp->mutex)) != 0) + return (ret); + + /* + * Set up a bookkeeping entry for this database in the log region, + * if such a region exists. Note that even if we're in recovery + * or a replication client, where we won't log registries, we'll + * still need an FNAME struct, so LOGGING_ON is the correct macro. + */ + if (LOGGING_ON(env) && + (!F_ISSET(dbp, DB_AM_INMEM) || dname == NULL) && + (ret = __env_dbreg_setup(dbp, txn, fname, dname, id)) != 0) + return (ret); + + /* + * Insert ourselves into the ENV's dblist. We allocate a + * unique ID to each {fileid, meta page number} pair, and to + * each temporary file (since they all have a zero fileid). + * This ID gives us something to use to tell which DB handles + * go with which databases in all the cursor adjustment + * routines, where we don't want to do a lot of ugly and + * expensive memcmps. + */ + MUTEX_LOCK(env, env->mtx_dblist); + maxid = 0; + TAILQ_FOREACH(ldbp, &env->dblist, dblistlinks) { + /* + * There are three cases: on-disk database (first clause), + * named in-memory database (second clause), temporary database + * (never matches; no clause). + */ + if (!F_ISSET(dbp, DB_AM_INMEM)) { + if (memcmp(ldbp->fileid, dbp->fileid, DB_FILE_ID_LEN) + == 0 && ldbp->meta_pgno == dbp->meta_pgno) + break; + } else if (dname != NULL) { + if (F_ISSET(ldbp, DB_AM_INMEM) && + ldbp->dname != NULL && + strcmp(ldbp->dname, dname) == 0) + break; + } + if (ldbp->adj_fileid > maxid) + maxid = ldbp->adj_fileid; + } + + /* + * If ldbp is NULL, we didn't find a match. Assign the dbp an + * adj_fileid one higher than the largest we found, and + * insert it at the head of the master dbp list. + * + * If ldbp is not NULL, it is a match for our dbp. Give dbp + * the same ID that ldbp has, and add it after ldbp so they're + * together in the list. + */ + if (ldbp == NULL) { + dbp->adj_fileid = maxid + 1; + TAILQ_INSERT_HEAD(&env->dblist, dbp, dblistlinks); + } else { + dbp->adj_fileid = ldbp->adj_fileid; + TAILQ_INSERT_AFTER(&env->dblist, ldbp, dbp, dblistlinks); + } + MUTEX_UNLOCK(env, env->mtx_dblist); + + return (0); +} + +/* + * __env_mpool -- + * Set up the underlying environment cache during a db_open. + * + * PUBLIC: int __env_mpool __P((DB *, const char *, u_int32_t)); + */ +int +__env_mpool(dbp, fname, flags) + DB *dbp; + const char *fname; + u_int32_t flags; +{ + DBT pgcookie; + DB_MPOOLFILE *mpf; + DB_PGINFO pginfo; + ENV *env; + int fidset, ftype, ret; + int32_t lsn_off; + u_int8_t nullfid[DB_FILE_ID_LEN]; + u_int32_t clear_len; + + env = dbp->env; + + /* The LSN is the first entry on a DB page, byte offset 0. */ + lsn_off = F_ISSET(dbp, DB_AM_NOT_DURABLE) ? DB_LSN_OFF_NOTSET : 0; + + /* It's possible that this database is already open. */ + if (F_ISSET(dbp, DB_AM_OPEN_CALLED)) + return (0); + + /* + * If we need to pre- or post-process a file's pages on I/O, set the + * file type. If it's a hash file, always call the pgin and pgout + * routines. This means that hash files can never be mapped into + * process memory. If it's a btree file and requires swapping, we + * need to page the file in and out. This has to be right -- we can't + * mmap files that are being paged in and out. + */ + switch (dbp->type) { + case DB_BTREE: + case DB_HEAP: + case DB_RECNO: + ftype = F_ISSET(dbp, DB_AM_SWAP | DB_AM_ENCRYPT | DB_AM_CHKSUM) + ? DB_FTYPE_SET : DB_FTYPE_NOTSET; + clear_len = CRYPTO_ON(env) ? + (dbp->pgsize != 0 ? dbp->pgsize : DB_CLEARLEN_NOTSET) : + DB_PAGE_DB_LEN; + break; + case DB_HASH: + ftype = DB_FTYPE_SET; + clear_len = CRYPTO_ON(env) ? + (dbp->pgsize != 0 ? dbp->pgsize : DB_CLEARLEN_NOTSET) : + DB_PAGE_DB_LEN; + break; + case DB_QUEUE: + ftype = F_ISSET(dbp, + DB_AM_SWAP | DB_AM_ENCRYPT | DB_AM_CHKSUM) ? + DB_FTYPE_SET : DB_FTYPE_NOTSET; + + /* + * If we came in here without a pagesize set, then we need + * to mark the in-memory handle as having clear_len not + * set, because we don't really know the clear length or + * the page size yet (since the file doesn't yet exist). + */ + clear_len = dbp->pgsize != 0 ? dbp->pgsize : DB_CLEARLEN_NOTSET; + break; + case DB_UNKNOWN: + /* + * If we're running in the verifier, our database might + * be corrupt and we might not know its type--but we may + * still want to be able to verify and salvage. + * + * If we can't identify the type, it's not going to be safe + * to call __db_pgin--we pretty much have to give up all + * hope of salvaging cross-endianness. Proceed anyway; + * at worst, the database will just appear more corrupt + * than it actually is, but at best, we may be able + * to salvage some data even with no metadata page. + */ + if (F_ISSET(dbp, DB_AM_VERIFYING)) { + ftype = DB_FTYPE_NOTSET; + clear_len = DB_PAGE_DB_LEN; + break; + } + + /* + * This might be an in-memory file and we won't know its + * file type until after we open it and read the meta-data + * page. + */ + if (F_ISSET(dbp, DB_AM_INMEM)) { + clear_len = DB_CLEARLEN_NOTSET; + ftype = DB_FTYPE_NOTSET; + lsn_off = DB_LSN_OFF_NOTSET; + break; + } + /* FALLTHROUGH */ + default: + return (__db_unknown_type(env, "DB->open", dbp->type)); + } + + mpf = dbp->mpf; + + memset(nullfid, 0, DB_FILE_ID_LEN); + fidset = memcmp(nullfid, dbp->fileid, DB_FILE_ID_LEN); + if (fidset) + (void)__memp_set_fileid(mpf, dbp->fileid); + + (void)__memp_set_clear_len(mpf, clear_len); + (void)__memp_set_ftype(mpf, ftype); + (void)__memp_set_lsn_offset(mpf, lsn_off); + + pginfo.db_pagesize = dbp->pgsize; + pginfo.flags = + F_ISSET(dbp, (DB_AM_CHKSUM | DB_AM_ENCRYPT | DB_AM_SWAP)); + pginfo.type = dbp->type; + pgcookie.data = &pginfo; + pgcookie.size = sizeof(DB_PGINFO); + (void)__memp_set_pgcookie(mpf, &pgcookie); + +#ifndef DIAG_MVCC + if (F_ISSET(env->dbenv, DB_ENV_MULTIVERSION)) +#endif + if (F_ISSET(dbp, DB_AM_TXN) && + dbp->type != DB_QUEUE && dbp->type != DB_UNKNOWN) + LF_SET(DB_MULTIVERSION); + + if ((ret = __memp_fopen(mpf, NULL, fname, &dbp->dirname, + LF_ISSET(DB_CREATE | DB_DURABLE_UNKNOWN | DB_MULTIVERSION | + DB_NOMMAP | DB_ODDFILESIZE | DB_RDONLY | DB_TRUNCATE) | + (F_ISSET(env->dbenv, DB_ENV_DIRECT_DB) ? DB_DIRECT : 0) | + (F_ISSET(dbp, DB_AM_NOT_DURABLE) ? DB_TXN_NOT_DURABLE : 0), + 0, dbp->pgsize)) != 0) { + /* + * The open didn't work; we need to reset the mpf, + * retaining the in-memory semantics (if any). + */ + (void)__memp_fclose(dbp->mpf, 0); + (void)__memp_fcreate(env, &dbp->mpf); + if (F_ISSET(dbp, DB_AM_INMEM)) + MAKE_INMEM(dbp); + return (ret); + } + + /* + * Set the open flag. We use it to mean that the dbp has gone + * through mpf setup, including dbreg_register. Also, below, + * the underlying access method open functions may want to do + * things like acquire cursors, so the open flag has to be set + * before calling them. + */ + F_SET(dbp, DB_AM_OPEN_CALLED); + if (!fidset && fname != NULL) { + (void)__memp_get_fileid(dbp->mpf, dbp->fileid); + dbp->preserve_fid = 1; + } + + return (0); +} + +/* + * __db_close -- + * DB->close method. + * + * PUBLIC: int __db_close __P((DB *, DB_TXN *, u_int32_t)); + */ +int +__db_close(dbp, txn, flags) + DB *dbp; + DB_TXN *txn; + u_int32_t flags; +{ + ENV *env; + int db_ref, deferred_close, ret, t_ret; + + env = dbp->env; + deferred_close = 0; + + PERFMON4(env, db, close, + dbp->fname, dbp->dname, flags, &dbp->fileid[0]); + + /* Refresh the structure and close any underlying resources. */ + ret = __db_refresh(dbp, txn, flags, &deferred_close, 0); + + /* + * If we've deferred the close because the logging of the close failed, + * return our failure right away without destroying the handle. + */ + if (deferred_close) + return (ret); + + /* !!! + * This code has an apparent race between the moment we read and + * decrement env->db_ref and the moment we check whether it's 0. + * However, if the environment is DBLOCAL, the user shouldn't have a + * reference to the env handle anyway; the only way we can get + * multiple dbps sharing a local env is if we open them internally + * during something like a subdatabase open. If any such thing is + * going on while the user is closing the original dbp with a local + * env, someone's already badly screwed up, so there's no reason + * to bother engineering around this possibility. + */ + MUTEX_LOCK(env, env->mtx_dblist); + db_ref = --env->db_ref; + MUTEX_UNLOCK(env, env->mtx_dblist); + if (F_ISSET(env, ENV_DBLOCAL) && db_ref == 0 && + (t_ret = __env_close(env->dbenv, 0)) != 0 && ret == 0) + ret = t_ret; + + /* Free the database handle. */ + memset(dbp, CLEAR_BYTE, sizeof(*dbp)); + __os_free(env, dbp); + + return (ret); +} + +/* + * __db_refresh -- + * Refresh the DB structure, releasing any allocated resources. + * This does most of the work of closing files now because refresh + * is what is used during abort processing (since we can't destroy + * the actual handle) and during abort processing, we may have a + * fully opened handle. + * + * PUBLIC: int __db_refresh __P((DB *, DB_TXN *, u_int32_t, int *, int)); + */ +int +__db_refresh(dbp, txn, flags, deferred_closep, reuse) + DB *dbp; + DB_TXN *txn; + u_int32_t flags; + int *deferred_closep, reuse; +{ + DB *sdbp; + DBC *dbc; + DB_FOREIGN_INFO *f_info, *tmp; + DB_LOCKER *locker; + DB_LOCKREQ lreq; + ENV *env; + REGENV *renv; + REGINFO *infop; + u_int32_t save_flags; + int resync, ret, t_ret; + + ret = 0; + + env = dbp->env; + infop = env->reginfo; + if (infop != NULL) + renv = infop->primary; + else + renv = NULL; + + /* + * If this dbp is not completely open, avoid trapping by trying to + * sync without an mpool file. + */ + if (dbp->mpf == NULL) + LF_SET(DB_NOSYNC); + + /* If never opened, or not currently open, it's easy. */ + if (!F_ISSET(dbp, DB_AM_OPEN_CALLED)) + goto never_opened; + + /* + * If we have any secondary indices, disassociate them from us. + * We don't bother with the mutex here; it only protects some + * of the ops that will make us core-dump mid-close anyway, and + * if you're trying to do something with a secondary *while* you're + * closing the primary, you deserve what you get. The disassociation + * is mostly done just so we can close primaries and secondaries in + * any order--but within one thread of control. + */ + LIST_FOREACH(sdbp, &dbp->s_secondaries, s_links) { + LIST_REMOVE(sdbp, s_links); + if ((t_ret = __db_disassociate(sdbp)) != 0 && ret == 0) + ret = t_ret; + } + if (F_ISSET(dbp, DB_AM_SECONDARY)) + LIST_REMOVE(dbp, s_links); + + /* + * Disassociate ourself from any databases using us as a foreign key + * database by clearing the referring db's pointer. Reclaim memory. + */ + f_info = LIST_FIRST(&dbp->f_primaries); + while (f_info != NULL) { + tmp = LIST_NEXT(f_info, f_links); + LIST_REMOVE(f_info, f_links); + f_info->dbp->s_foreign = NULL; + __os_free(env, f_info); + f_info = tmp; + } + + if (dbp->s_foreign != NULL && + (t_ret = __db_disassociate_foreign(dbp)) != 0 && ret == 0) + ret = t_ret; + + /* + * Sync the underlying access method. Do before closing the cursors + * because DB->sync allocates cursors in order to write Recno backing + * source text files. + * + * Sync is slow on some systems, notably Solaris filesystems where the + * entire buffer cache is searched. If we're in recovery, don't flush + * the file, it's not necessary. + */ + if (!LF_ISSET(DB_NOSYNC) && + !F_ISSET(dbp, DB_AM_DISCARD | DB_AM_RECOVER) && + (t_ret = __db_sync(dbp)) != 0 && ret == 0) + ret = t_ret; + + /* + * Go through the active cursors, unregister each cursor from its + * transaction if any, and call the cursor recycle routine, + * which resolves pending operations and moves the cursors onto the + * free list. Then, walk the free list and call the cursor destroy + * routine. Note that any failure on a close is considered "really + * bad" and we just break out of the loop and force forward. + */ + resync = TAILQ_FIRST(&dbp->active_queue) == NULL ? 0 : 1; + while ((dbc = TAILQ_FIRST(&dbp->active_queue)) != NULL) { + if (dbc->txn != NULL) + TAILQ_REMOVE(&(dbc->txn->my_cursors), dbc, txn_cursors); + + if ((t_ret = __dbc_close(dbc)) != 0) { + if (ret == 0) + ret = t_ret; + break; + } + } + + while ((dbc = TAILQ_FIRST(&dbp->free_queue)) != NULL) + if ((t_ret = __dbc_destroy(dbc)) != 0) { + if (ret == 0) + ret = t_ret; + break; + } + + /* + * Close any outstanding join cursors. Join cursors destroy themselves + * on close and have no separate destroy routine. We don't have to set + * the resync flag here, because join cursors aren't write cursors. + */ + while ((dbc = TAILQ_FIRST(&dbp->join_queue)) != NULL) + if ((t_ret = __db_join_close(dbc)) != 0) { + if (ret == 0) + ret = t_ret; + break; + } + + /* + * Sync the memory pool, even though we've already called DB->sync, + * because closing cursors can dirty pages by deleting items they + * referenced. + * + * Sync is slow on some systems, notably Solaris filesystems where the + * entire buffer cache is searched. If we're in recovery, don't flush + * the file, it's not necessary. + */ + if (resync && !LF_ISSET(DB_NOSYNC) && + !F_ISSET(dbp, DB_AM_DISCARD | DB_AM_RECOVER) && + (t_ret = __memp_fsync(dbp->mpf)) != 0 && ret == 0) + ret = t_ret; + + /* + * If there is a file extension watermark associated with this + * database, we don't need it any more. + */ + __txn_remove_fe_watermark(txn, dbp); + +never_opened: + MUTEX_LOCK(env, env->mtx_dblist); + /* + * At this point, we haven't done anything to render the DB handle + * unusable, at least by a transaction abort. Take the opportunity + * now to log the file close if we have initialized the logging + * information. If this log fails and we're in a transaction, + * we have to bail out of the attempted close; we'll need a dbp in + * order to successfully abort the transaction, and we can't conjure + * a new one up because we haven't gotten out the dbreg_register + * record that represents the close. In this case, we put off + * actually closing the dbp until we've performed the abort. + */ + if (!reuse && LOGGING_ON(dbp->env) && dbp->log_filename != NULL) { + /* + * Discard the log file id, if any. We want to log the close + * if and only if this is not a recovery dbp or a client dbp, + * or a dead dbp handle. + */ + DB_ASSERT(env, renv != NULL); + if (F_ISSET(dbp, DB_AM_RECOVER) || IS_REP_CLIENT(env) || + dbp->timestamp != renv->rep_timestamp) { + if ((t_ret = __dbreg_revoke_id(dbp, + 0, DB_LOGFILEID_INVALID)) == 0 && ret == 0) + ret = t_ret; + if ((t_ret = __dbreg_teardown(dbp)) != 0 && ret == 0) + ret = t_ret; + } else { + if ((t_ret = __dbreg_close_id(dbp, + txn, DBREG_CLOSE)) != 0 && txn != NULL) { + MUTEX_UNLOCK(env, env->mtx_dblist); + /* + * We're in a txn and the attempt to log the + * close failed; let the txn subsystem know + * that we need to destroy this dbp once we're + * done with the abort, then bail from the + * close. + * + * Note that if the attempt to put off the + * close -also- fails--which it won't unless + * we're out of heap memory--we're really + * screwed. Panic. + */ + if ((ret = + __txn_closeevent(env, txn, dbp)) != 0) + return (__env_panic(env, ret)); + if (deferred_closep != NULL) + *deferred_closep = 1; + return (t_ret); + } + /* + * If dbreg_close_id failed and we were not in a + * transaction, then we need to finish this close + * because the caller can't do anything with the + * handle after we return an error. We rely on + * dbreg_close_id to mark the entry in some manner + * so that we do not do a clean shutdown of this + * environment. If shutdown isn't clean, then the + * application *must* run recovery and that will + * generate the RCLOSE record. + */ + } + + } + + /* Close any handle we've been holding since the open. */ + if (dbp->saved_open_fhp != NULL && + (t_ret = __os_closehandle(env, dbp->saved_open_fhp)) != 0 && + ret == 0) + ret = t_ret; + + /* + * Remove this DB handle from the ENV's dblist, if it's been added. + * + * Close our reference to the underlying cache while locked, we don't + * want to race with a thread searching for our underlying cache link + * while opening a DB handle. + * + * The DB handle may not yet have been added to the ENV list, don't + * blindly call the underlying TAILQ_REMOVE macro. Explicitly reset + * the field values to NULL so that we can't call TAILQ_REMOVE twice. + */ + if (!reuse && + (dbp->dblistlinks.tqe_next != NULL || + dbp->dblistlinks.tqe_prev != NULL)) { + TAILQ_REMOVE(&env->dblist, dbp, dblistlinks); + dbp->dblistlinks.tqe_next = NULL; + dbp->dblistlinks.tqe_prev = NULL; + } + + /* Close the memory pool file handle. */ + if (dbp->mpf != NULL) { + if ((t_ret = __memp_fclose(dbp->mpf, + F_ISSET(dbp, DB_AM_DISCARD) ? DB_MPOOL_DISCARD : 0)) != 0 && + ret == 0) + ret = t_ret; + dbp->mpf = NULL; + if (reuse && + (t_ret = __memp_fcreate(env, &dbp->mpf)) != 0 && + ret == 0) + ret = t_ret; + } + + MUTEX_UNLOCK(env, env->mtx_dblist); + + /* + * Call the access specific close function. + * + * We do this here rather than in __db_close as we need to do this when + * aborting an open so that file descriptors are closed and abort of + * renames can succeed on platforms that lock open files (such as + * Windows). In particular, we need to ensure that all the extents + * associated with a queue are closed so that queue renames can be + * aborted. + * + * It is also important that we do this before releasing the handle + * lock, because dbremove and dbrename assume that once they have the + * handle lock, it is safe to modify the underlying file(s). + * + * !!! + * Because of where these functions are called in the DB handle close + * process, these routines can't do anything that would dirty pages or + * otherwise affect closing down the database. Specifically, we can't + * abort and recover any of the information they control. + */ +#ifdef HAVE_PARTITION + if (dbp->p_internal != NULL && + (t_ret = __partition_close(dbp, txn, flags)) != 0 && ret == 0) + ret = t_ret; +#endif + if ((t_ret = __bam_db_close(dbp)) != 0 && ret == 0) + ret = t_ret; + if ((t_ret = __ham_db_close(dbp)) != 0 && ret == 0) + ret = t_ret; + if ((t_ret = __heap_db_close(dbp)) != 0 && ret == 0) + ret = t_ret; + if ((t_ret = __qam_db_close(dbp, dbp->flags)) != 0 && ret == 0) + ret = t_ret; + + /* + * !!! + * At this point, the access-method specific information has been + * freed. From now on, we can use the dbp, but not touch any + * access-method specific data. + */ + + if (!reuse && dbp->locker != NULL) { + /* We may have pending trade operations on this dbp. */ + if (txn == NULL) + txn = dbp->cur_txn; + if (IS_REAL_TXN(txn)) + __txn_remlock(env, + txn, &dbp->handle_lock, dbp->locker); + + /* We may be holding the handle lock; release it. */ + lreq.op = DB_LOCK_PUT_ALL; + lreq.obj = NULL; + if ((t_ret = __lock_vec(env, + dbp->locker, 0, &lreq, 1, NULL)) != 0 && ret == 0) + ret = t_ret; + + if ((t_ret = + __lock_id_free(env, dbp->locker)) != 0 && ret == 0) + ret = t_ret; + dbp->locker = NULL; + LOCK_INIT(dbp->handle_lock); + } + + /* + * If this is a temporary file (un-named in-memory file), then + * discard the locker ID allocated as the fileid. + */ + if (LOCKING_ON(env) && + F_ISSET(dbp, DB_AM_INMEM) && !dbp->preserve_fid && + *(u_int32_t *)dbp->fileid != DB_LOCK_INVALIDID) { + if ((t_ret = __lock_getlocker(env->lk_handle, + *(u_int32_t *)dbp->fileid, 0, &locker)) == 0) + t_ret = __lock_id_free(env, locker); + if (ret == 0) + ret = t_ret; + } + + if (reuse) { + /* + * If we are reusing this dbp, then we're done now. Re-init + * the handle, preserving important flags, and then return. + * This code is borrowed from __db_init, which does more + * than we can do here. + */ + save_flags = F_ISSET(dbp, DB_AM_INMEM | + DB_AM_RDONLY | DB_AM_TXN); + + if ((ret = __bam_db_create(dbp)) != 0) + return (ret); + if ((ret = __ham_db_create(dbp)) != 0) + return (ret); + if ((ret = __heap_db_create(dbp)) != 0) + return (ret); + if ((ret = __qam_db_create(dbp)) != 0) + return (ret); + + /* Restore flags */ + dbp->flags = dbp->orig_flags | save_flags; + + if (FLD_ISSET(save_flags, DB_AM_INMEM)) { + /* + * If this is inmem, then it may have a fileid + * even if it was never opened, and we need to + * clear out that fileid. + */ + memset(dbp->fileid, 0, sizeof(dbp->fileid)); + MAKE_INMEM(dbp); + } + return (ret); + } + + dbp->type = DB_UNKNOWN; + + /* + * The thread mutex may have been invalidated in __dbreg_close_id if the + * fname refcount did not go to 0. If not, discard the thread mutex. + */ + if ((t_ret = __mutex_free(env, &dbp->mutex)) != 0 && ret == 0) + ret = t_ret; + + /* Discard any memory allocated for the file and database names. */ + if (dbp->fname != NULL) { + __os_free(dbp->env, dbp->fname); + dbp->fname = NULL; + } + if (dbp->dname != NULL) { + __os_free(dbp->env, dbp->dname); + dbp->dname = NULL; + } + + /* Discard any memory used to store returned data. */ + if (dbp->my_rskey.data != NULL) + __os_free(dbp->env, dbp->my_rskey.data); + if (dbp->my_rkey.data != NULL) + __os_free(dbp->env, dbp->my_rkey.data); + if (dbp->my_rdata.data != NULL) + __os_free(dbp->env, dbp->my_rdata.data); + + /* For safety's sake; we may refresh twice. */ + memset(&dbp->my_rskey, 0, sizeof(DBT)); + memset(&dbp->my_rkey, 0, sizeof(DBT)); + memset(&dbp->my_rdata, 0, sizeof(DBT)); + + /* Clear out fields that normally get set during open. */ + memset(dbp->fileid, 0, sizeof(dbp->fileid)); + dbp->adj_fileid = 0; + dbp->meta_pgno = 0; + dbp->cur_locker = NULL; + dbp->cur_txn = NULL; + dbp->associate_locker = NULL; + dbp->open_flags = 0; + + /* + * If we are being refreshed with a txn specified, then we need + * to make sure that we clear out the lock handle field, because + * releasing all the locks for this transaction will release this + * lock and we don't want close to stumble upon this handle and + * try to close it. + */ + if (txn != NULL) + LOCK_INIT(dbp->handle_lock); + + /* Reset flags to whatever the user configured. */ + dbp->flags = dbp->orig_flags; + + return (ret); +} + +/* + * __db_disassociate -- + * Destroy the association between a given secondary and its primary. + */ +static int +__db_disassociate(sdbp) + DB *sdbp; +{ + DBC *dbc; + int ret, t_ret; + + ret = 0; + + sdbp->s_callback = NULL; + sdbp->s_primary = NULL; + sdbp->get = sdbp->stored_get; + sdbp->close = sdbp->stored_close; + + /* + * Complain, but proceed, if we have any active cursors. (We're in + * the middle of a close, so there's really no turning back.) + */ + if (sdbp->s_refcnt != 1 || + TAILQ_FIRST(&sdbp->active_queue) != NULL || + TAILQ_FIRST(&sdbp->join_queue) != NULL) { + __db_errx(sdbp->env, DB_STR("0674", +"Closing a primary DB while a secondary DB has active cursors is unsafe")); + ret = EINVAL; + } + sdbp->s_refcnt = 0; + + while ((dbc = TAILQ_FIRST(&sdbp->free_queue)) != NULL) + if ((t_ret = __dbc_destroy(dbc)) != 0 && ret == 0) + ret = t_ret; + + F_CLR(sdbp, DB_AM_SECONDARY); + return (ret); +} + +/* + * __db_disassociate_foreign -- + * Destroy the association between a given secondary and its foreign. + */ +static int +__db_disassociate_foreign(sdbp) + DB *sdbp; +{ + DB *fdbp; + DB_FOREIGN_INFO *f_info, *tmp; + int ret; + + if (sdbp->s_foreign == NULL) + return (0); + if ((ret = __os_malloc(sdbp->env, sizeof(DB_FOREIGN_INFO), &tmp)) != 0) + return (ret); + + fdbp = sdbp->s_foreign; + ret = 0; + f_info = LIST_FIRST(&fdbp->f_primaries); + while (f_info != NULL) { + tmp = LIST_NEXT(f_info, f_links); + if (f_info ->dbp == sdbp) { + LIST_REMOVE(f_info, f_links); + __os_free(sdbp->env, f_info); + } + f_info = tmp; + } + + return (ret); +} + +/* + * __db_log_page + * Log a meta-data or root page during a subdatabase create operation. + * + * PUBLIC: int __db_log_page __P((DB *, DB_TXN *, DB_LSN *, db_pgno_t, PAGE *)); + */ +int +__db_log_page(dbp, txn, lsn, pgno, page) + DB *dbp; + DB_TXN *txn; + DB_LSN *lsn; + db_pgno_t pgno; + PAGE *page; +{ + DBT page_dbt; + DB_LSN new_lsn; + int ret; + + if (!LOGGING_ON(dbp->env) || txn == NULL) + return (0); + + memset(&page_dbt, 0, sizeof(page_dbt)); + page_dbt.size = dbp->pgsize; + page_dbt.data = page; + + ret = __crdel_metasub_log(dbp, txn, &new_lsn, F_ISSET(dbp, + DB_AM_NOT_DURABLE) ? DB_LOG_NOT_DURABLE : 0, pgno, &page_dbt, lsn); + + if (ret == 0) + page->lsn = new_lsn; + return (ret); +} + +/* + * __db_walk_cursors + * Walk all cursors for a database. + * + * PUBLIC: int __db_walk_cursors __P((DB *, DBC *, + * PUBLIC: int (*) __P((DBC *, DBC *, + * PUBLIC: u_int32_t *, db_pgno_t, u_int32_t, void *)), + * PUBLIC: u_int32_t *, db_pgno_t, u_int32_t, void *)); + */ + int + __db_walk_cursors(dbp, my_dbc, func, countp, pgno, indx, args) + DB *dbp; + DBC *my_dbc; + int (*func)__P((DBC *, DBC *, + u_int32_t *, db_pgno_t, u_int32_t, void *)); + u_int32_t *countp; + db_pgno_t pgno; + u_int32_t indx; + void *args; +{ + ENV *env; + DB *ldbp; + DBC *dbc; + int ret; + + env = dbp->env; + ret = 0; + + MUTEX_LOCK(env, env->mtx_dblist); + FIND_FIRST_DB_MATCH(env, dbp, ldbp); + for (*countp = 0; + ldbp != NULL && ldbp->adj_fileid == dbp->adj_fileid; + ldbp = TAILQ_NEXT(ldbp, dblistlinks)) { +loop: MUTEX_LOCK(env, ldbp->mutex); + TAILQ_FOREACH(dbc, &ldbp->active_queue, links) + if ((ret = (func)(dbc, my_dbc, + countp, pgno, indx, args)) != 0) + break; + /* + * We use the error to communicate that function + * dropped the mutex. + */ + if (ret == DB_LOCK_NOTGRANTED) + goto loop; + MUTEX_UNLOCK(env, ldbp->mutex); + if (ret != 0) + break; + } + MUTEX_UNLOCK(env, env->mtx_dblist); + return (ret); +} + +/* + * __db_backup_name + * Create the backup file name for a given file. + * + * PUBLIC: int __db_backup_name __P((ENV *, const char *, DB_TXN *, char **)); + */ +#undef BACKUP_PREFIX +#define BACKUP_PREFIX "__db." + +#undef MAX_INT_TO_HEX +#define MAX_INT_TO_HEX 8 + +int +__db_backup_name(env, name, txn, backup) + ENV *env; + const char *name; + DB_TXN *txn; + char **backup; +{ + u_int32_t id; + size_t len; + int ret; + char *p, *retp; + + *backup = NULL; + + /* + * Part of the name may be a full path, so we need to make sure that + * we allocate enough space for it, even in the case where we don't + * use the entire filename for the backup name. + */ + len = strlen(name) + strlen(BACKUP_PREFIX) + 2 * MAX_INT_TO_HEX + 1; + if ((ret = __os_malloc(env, len, &retp)) != 0) + return (ret); + + /* + * Create the name. Backup file names are in one of 2 forms: in a + * transactional env "__db.TXNID.ID", where ID is a random number, + * and in any other env "__db.FILENAME". + * + * In addition, the name passed may contain an env-relative path. + * In that case, put the "__db." in the right place (in the last + * component of the pathname). + * + * There are four cases here: + * 1. simple path w/out transaction + * 2. simple path + transaction + * 3. multi-component path w/out transaction + * 4. multi-component path + transaction + */ + p = __db_rpath(name); + if (IS_REAL_TXN(txn)) { + __os_unique_id(env, &id); + if (p == NULL) /* Case 2. */ + snprintf(retp, len, "%s%x.%x", + BACKUP_PREFIX, txn->txnid, id); + else /* Case 4. */ + snprintf(retp, len, "%.*s%x.%x", + (int)(p - name) + 1, name, txn->txnid, id); + } else + { + if (p == NULL) /* Case 1. */ + snprintf(retp, len, "%s%s", BACKUP_PREFIX, name); + else /* Case 3. */ + snprintf(retp, len, "%.*s%s%s", + (int)(p - name) + 1, name, BACKUP_PREFIX, p + 1); + } + + *backup = retp; + return (0); +} + +#ifdef CONFIG_TEST +/* + * __db_testcopy + * Create a copy of all backup files and our "main" DB. + * + * PUBLIC: #ifdef CONFIG_TEST + * PUBLIC: int __db_testcopy __P((ENV *, DB *, const char *)); + * PUBLIC: #endif + */ +int +__db_testcopy(env, dbp, name) + ENV *env; + DB *dbp; + const char *name; +{ + DB_MPOOL *dbmp; + DB_MPOOLFILE *mpf; + + DB_ASSERT(env, dbp != NULL || name != NULL); + + if (name == NULL) { + dbmp = env->mp_handle; + mpf = dbp->mpf; + name = R_ADDR(dbmp->reginfo, mpf->mfp->path_off); + } + + if (dbp != NULL && dbp->type == DB_QUEUE) + return (__qam_testdocopy(dbp, name)); + else +#ifdef HAVE_PARTITION + if (dbp != NULL && DB_IS_PARTITIONED(dbp)) + return (__part_testdocopy(dbp, name)); + else +#endif + return (__db_testdocopy(env, name)); +} + +static int +__qam_testdocopy(dbp, name) + DB *dbp; + const char *name; +{ + DB_THREAD_INFO *ip; + QUEUE_FILELIST *filelist, *fp; + int ret; + char buf[DB_MAXPATHLEN], *dir; + + filelist = NULL; + if ((ret = __db_testdocopy(dbp->env, name)) != 0) + return (ret); + + /* Call ENV_GET_THREAD_INFO to get a valid DB_THREAD_INFO */ + ENV_GET_THREAD_INFO(dbp->env, ip); + if (dbp->mpf != NULL && + (ret = __qam_gen_filelist(dbp, ip, &filelist)) != 0) + goto done; + + if (filelist == NULL) + return (0); + dir = ((QUEUE *)dbp->q_internal)->dir; + for (fp = filelist; fp->mpf != NULL; fp++) { + snprintf(buf, sizeof(buf), + QUEUE_EXTENT, dir, PATH_SEPARATOR[0], name, fp->id); + if ((ret = __db_testdocopy(dbp->env, buf)) != 0) + return (ret); + } + +done: __os_free(dbp->env, filelist); + return (0); +} + +/* + * __db_testdocopy + * Create a copy of all backup files and our "main" DB. + * PUBLIC: int __db_testdocopy __P((ENV *, const char *)); + */ +int +__db_testdocopy(env, name) + ENV *env; + const char *name; +{ + size_t len; + int dircnt, i, ret; + char *copy, **namesp, *p, *real_name; + + dircnt = 0; + copy = NULL; + namesp = NULL; + + /* Create the real backing file name. */ + if ((ret = __db_appname(env, + DB_APP_DATA, name, NULL, &real_name)) != 0) + return (ret); + + /* + * !!! + * There are tests that attempt to copy non-existent files. I'd guess + * it's a testing bug, but I don't have time to figure it out. Block + * the case here. + */ + if (__os_exists(env, real_name, NULL) != 0) { + __os_free(env, real_name); + return (0); + } + + /* + * Copy the file itself. + * + * Allocate space for the file name, including adding an ".afterop" and + * trailing nul byte. + */ + len = strlen(real_name) + sizeof(".afterop"); + if ((ret = __os_malloc(env, len, ©)) != 0) + goto err; + snprintf(copy, len, "%s.afterop", real_name); + if ((ret = __db_makecopy(env, real_name, copy)) != 0) + goto err; + + /* + * Get the directory path to call __os_dirlist(). + */ + if ((p = __db_rpath(real_name)) != NULL) + *p = '\0'; + if ((ret = __os_dirlist(env, real_name, 0, &namesp, &dircnt)) != 0) + goto err; + + /* + * Walk the directory looking for backup files. Backup file names in + * transactional environments are of the form: + * + * BACKUP_PREFIX.TXNID.ID + */ + for (i = 0; i < dircnt; i++) { + /* Check for a related backup file name. */ + if (strncmp( + namesp[i], BACKUP_PREFIX, sizeof(BACKUP_PREFIX) - 1) != 0) + continue; + p = namesp[i] + sizeof(BACKUP_PREFIX); + p += strspn(p, "0123456789ABCDEFabcdef"); + if (*p != '.') + continue; + ++p; + p += strspn(p, "0123456789ABCDEFabcdef"); + if (*p != '\0') + continue; + + /* + * Copy the backup file. + * + * Allocate space for the file name, including adding a + * ".afterop" and trailing nul byte. + */ + if (real_name != NULL) { + __os_free(env, real_name); + real_name = NULL; + } + if ((ret = __db_appname(env, + DB_APP_DATA, namesp[i], NULL, &real_name)) != 0) + goto err; + if (copy != NULL) { + __os_free(env, copy); + copy = NULL; + } + len = strlen(real_name) + sizeof(".afterop"); + if ((ret = __os_malloc(env, len, ©)) != 0) + goto err; + snprintf(copy, len, "%s.afterop", real_name); + if ((ret = __db_makecopy(env, real_name, copy)) != 0) + goto err; + } + +err: if (namesp != NULL) + __os_dirfree(env, namesp, dircnt); + if (copy != NULL) + __os_free(env, copy); + if (real_name != NULL) + __os_free(env, real_name); + return (ret); +} + +static int +__db_makecopy(env, src, dest) + ENV *env; + const char *src, *dest; +{ + DB_FH *rfhp, *wfhp; + size_t rcnt, wcnt; + int ret; + char *buf; + + rfhp = wfhp = NULL; + + if ((ret = __os_malloc(env, 64 * 1024, &buf)) != 0) + goto err; + + if ((ret = __os_open(env, src, 0, + DB_OSO_RDONLY, DB_MODE_600, &rfhp)) != 0) + goto err; + if ((ret = __os_open(env, dest, 0, + DB_OSO_CREATE | DB_OSO_TRUNC, DB_MODE_600, &wfhp)) != 0) + goto err; + + for (;;) { + if ((ret = + __os_read(env, rfhp, buf, sizeof(buf), &rcnt)) != 0) + goto err; + if (rcnt == 0) + break; + if ((ret = + __os_write(env, wfhp, buf, sizeof(buf), &wcnt)) != 0) + goto err; + } + + if (0) { +err: __db_err(env, ret, "__db_makecopy: %s -> %s", src, dest); + } + + if (buf != NULL) + __os_free(env, buf); + if (rfhp != NULL) + (void)__os_closehandle(env, rfhp); + if (wfhp != NULL) + (void)__os_closehandle(env, wfhp); + return (ret); +} +#endif diff -r 000000000000 -r a1985f14b030 src/db/db_am.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/db/db_am.c Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,1172 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 1998, 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + * $Id$ + */ + +#include "db_config.h" + +#include "db_int.h" +#include "dbinc/db_page.h" +#include "dbinc/btree.h" +#include "dbinc/hash.h" +#include "dbinc/heap.h" +#include "dbinc/lock.h" +#include "dbinc/mp.h" +#include "dbinc/partition.h" +#include "dbinc/qam.h" +#include "dbinc/txn.h" + +static int __db_secondary_get __P((DB *, DB_TXN *, DBT *, DBT *, u_int32_t)); +static int __dbc_set_priority __P((DBC *, DB_CACHE_PRIORITY)); +static int __dbc_get_priority __P((DBC *, DB_CACHE_PRIORITY* )); + +/* + * __db_cursor_int -- + * Internal routine to create a cursor. + * + * PUBLIC: int __db_cursor_int __P((DB *, DB_THREAD_INFO *, + * PUBLIC: DB_TXN *, DBTYPE, db_pgno_t, int, DB_LOCKER *, DBC **)); + */ +int +__db_cursor_int(dbp, ip, txn, dbtype, root, flags, locker, dbcp) + DB *dbp; + DB_THREAD_INFO *ip; + DB_TXN *txn; + DBTYPE dbtype; + db_pgno_t root; + int flags; + DB_LOCKER *locker; + DBC **dbcp; +{ + DBC *dbc; + DBC_INTERNAL *cp; + DB_LOCKREQ req; + ENV *env; + db_threadid_t tid; + int allocated, envlid, ret; + pid_t pid; + + env = dbp->env; + allocated = envlid = 0; + + /* + * If dbcp is non-NULL it is assumed to point to an area to initialize + * as a cursor. + * + * Take one from the free list if it's available. Take only the + * right type. With off page dups we may have different kinds + * of cursors on the queue for a single database. + */ + MUTEX_LOCK(env, dbp->mutex); + +#ifndef HAVE_NO_DB_REFCOUNT + /* + * If this DBP is being logged then refcount the log filename + * relative to this transaction. We do this here because we have + * the dbp->mutex which protects the refcount. We want to avoid + * calling the function if the transaction handle has a shared parent + * locker or we are duplicating a cursor. This includes the case of + * creating an off page duplicate cursor. + * If we knew this cursor will not be used in an update, we could avoid + * this, but we don't have that information. + */ + if (IS_REAL_TXN(txn) && + !LF_ISSET(DBC_OPD | DBC_DUPLICATE) && + !F_ISSET(dbp, DB_AM_RECOVER) && + dbp->log_filename != NULL && !IS_REP_CLIENT(env) && + (ret = __txn_record_fname(env, txn, dbp->log_filename)) != 0) { + MUTEX_UNLOCK(env, dbp->mutex); + return (ret); + } + +#endif + + TAILQ_FOREACH(dbc, &dbp->free_queue, links) + if (dbtype == dbc->dbtype) { + TAILQ_REMOVE(&dbp->free_queue, dbc, links); + F_CLR(dbc, ~DBC_OWN_LID); + break; + } + MUTEX_UNLOCK(env, dbp->mutex); + + if (dbc == NULL) { + if ((ret = __os_calloc(env, 1, sizeof(DBC), &dbc)) != 0) + return (ret); + allocated = 1; + dbc->flags = 0; + + dbc->dbp = dbp; + dbc->dbenv = dbp->dbenv; + dbc->env = dbp->env; + + /* Set up locking information. */ + if (LOCKING_ON(env)) { + /* + * If we are not threaded, we share a locker ID among + * all cursors opened in the environment handle, + * allocating one if this is the first cursor. + * + * This relies on the fact that non-threaded DB handles + * always have non-threaded environment handles, since + * we set DB_THREAD on DB handles created with threaded + * environment handles. + */ + if (!DB_IS_THREADED(dbp)) { + if (env->env_lref == NULL) { + if ((ret = __lock_id(env, + NULL, &env->env_lref)) != 0) + goto err; + envlid = 1; + } + dbc->lref = env->env_lref; + } + + /* + * In CDB, secondary indices should share a lock file + * ID with the primary; otherwise we're susceptible + * to deadlocks. We also use __db_cursor_int rather + * than __db_cursor to create secondary update cursors + * in c_put and c_del; these won't acquire a new lock. + * + * !!! + * Since this is in the one-time cursor allocation + * code, we need to be sure to destroy, not just + * close, all cursors in the secondary when we + * associate. + */ + if (CDB_LOCKING(env) && + F_ISSET(dbp, DB_AM_SECONDARY)) + memcpy(dbc->lock.fileid, + dbp->s_primary->fileid, DB_FILE_ID_LEN); + else + memcpy(dbc->lock.fileid, + dbp->fileid, DB_FILE_ID_LEN); + + if (CDB_LOCKING(env)) { + if (F_ISSET(env->dbenv, DB_ENV_CDB_ALLDB)) { + /* + * If we are doing a single lock per + * environment, set up the global + * lock object just like we do to + * single thread creates. + */ + DB_ASSERT(env, sizeof(db_pgno_t) == + sizeof(u_int32_t)); + dbc->lock_dbt.size = sizeof(u_int32_t); + dbc->lock_dbt.data = &dbc->lock.pgno; + dbc->lock.pgno = 0; + } else { + dbc->lock_dbt.size = DB_FILE_ID_LEN; + dbc->lock_dbt.data = dbc->lock.fileid; + } + } else { + dbc->lock.type = DB_PAGE_LOCK; + dbc->lock_dbt.size = sizeof(dbc->lock); + dbc->lock_dbt.data = &dbc->lock; + } + } + /* Init the DBC internal structure. */ +#ifdef HAVE_PARTITION + if (DB_IS_PARTITIONED(dbp)) { + if ((ret = __partc_init(dbc)) != 0) + goto err; + } else +#endif + switch (dbtype) { + case DB_BTREE: + case DB_RECNO: + if ((ret = __bamc_init(dbc, dbtype)) != 0) + goto err; + break; + case DB_HASH: + if ((ret = __hamc_init(dbc)) != 0) + goto err; + break; + case DB_HEAP: + if ((ret = __heapc_init(dbc)) != 0) + goto err; + break; + case DB_QUEUE: + if ((ret = __qamc_init(dbc)) != 0) + goto err; + break; + case DB_UNKNOWN: + default: + ret = __db_unknown_type(env, "DB->cursor", dbtype); + goto err; + } + + cp = dbc->internal; + } + + /* Refresh the DBC structure. */ + dbc->dbtype = dbtype; + RESET_RET_MEM(dbc); + dbc->set_priority = __dbc_set_priority; + dbc->get_priority = __dbc_get_priority; + dbc->priority = dbp->priority; + dbc->txn_cursors.tqe_next = NULL; + dbc->txn_cursors.tqe_prev = NULL; + + /* + * If the DB handle is not threaded, there is one locker ID for the + * whole environment. There should only one family transaction active + * as well. This doesn't apply to CDS group transactions, where the + * cursor can simply use the transaction's locker directly. + */ + if (!CDB_LOCKING(env) && txn != NULL && F_ISSET(txn, TXN_FAMILY) && + (F_ISSET(dbc, DBC_OWN_LID) || dbc->lref == NULL || envlid)) { + if (LOCKING_ON(env)) { + if (dbc->lref == NULL) { + if ((ret = + __lock_id(env, NULL, &dbc->lref)) != 0) + goto err; + F_SET(dbc, DBC_OWN_LID); + } + if ((ret = __lock_addfamilylocker(env, + txn->txnid, dbc->lref->id, 1)) != 0) + goto err; + } + F_SET(dbc, DBC_FAMILY); + txn = NULL; + } + + if ((dbc->txn = txn) != NULL) + dbc->locker = txn->locker; + else if (LOCKING_ON(env)) { + /* + * There are certain cases in which we want to create a + * new cursor with a particular locker ID that is known + * to be the same as (and thus not conflict with) an + * open cursor. + * + * The most obvious case is cursor duplication; when we + * call DBC->dup or __dbc_idup, we want to use the original + * cursor's locker ID. + * + * Another case is when updating secondary indices. Standard + * CDB locking would mean that we might block ourself: we need + * to open an update cursor in the secondary while an update + * cursor in the primary is open, and when the secondary and + * primary are subdatabases or we're using env-wide locking, + * this is disastrous. + * + * In these cases, our caller will pass a nonzero locker + * ID into this function. Use this locker ID instead of + * the default as the locker ID for our new cursor. + */ + if (locker != NULL) + dbc->locker = locker; + else if (LF_ISSET(DB_RECOVER)) + dbc->locker = NULL; + else { + if (dbc->lref == NULL) { + if ((ret = + __lock_id(env, NULL, &dbc->lref)) != 0) + goto err; + F_SET(dbc, DBC_OWN_LID); + } + /* + * If we are threaded then we need to set the + * proper thread id into the locker. + */ + if (DB_IS_THREADED(dbp)) { + env->dbenv->thread_id(env->dbenv, &pid, &tid); + __lock_set_thread_id(dbc->lref, pid, tid); + } + dbc->locker = dbc->lref; + } + } + + /* + * These fields change when we are used as a secondary index, so + * if the DB is a secondary, make sure they're set properly just + * in case we opened some cursors before we were associated. + * + * __dbc_get is used by all access methods, so this should be safe. + */ + if (F_ISSET(dbp, DB_AM_SECONDARY)) + dbc->get = dbc->c_get = __dbc_secondary_get_pp; + + /* + * Don't enable bulk for btrees with record numbering, since avoiding + * a full search avoids taking write locks necessary to maintain + * consistent numbering. + */ + if (LF_ISSET(DB_CURSOR_BULK) && dbtype == DB_BTREE && + !F_ISSET(dbp, DB_AM_RECNUM)) + F_SET(dbc, DBC_BULK); + if (LF_ISSET(DB_CURSOR_TRANSIENT)) + F_SET(dbc, DBC_TRANSIENT); + if (LF_ISSET(DBC_OPD)) + F_SET(dbc, DBC_OPD); + if (F_ISSET(dbp, DB_AM_RECOVER) || LF_ISSET(DB_RECOVER)) + F_SET(dbc, DBC_RECOVER); + if (F_ISSET(dbp, DB_AM_COMPENSATE)) + F_SET(dbc, DBC_DONTLOCK); + /* + * If this database is exclusive then the cursor + * does not need to get locks. + */ + if (F2_ISSET(dbp, DB2_AM_EXCL)) { + F_SET(dbc, DBC_DONTLOCK); + if (IS_REAL_TXN(txn) && !LF_ISSET(DBC_OPD | DBC_DUPLICATE)) { + /* + * Exclusive databases can only have one active + * transaction at a time since there are no internal + * locks to prevent one transaction from reading and + * writing another's uncommitted changes. + */ + if (dbp->cur_txn != NULL && dbp->cur_txn != txn) { + __db_errx(env, DB_STR("0749", +"Exclusive database handles can only have one active transaction at a time.")); + ret = EINVAL; + goto err; + } + /* Do not trade a second time. */ + if (dbp->cur_txn != txn) { + /* Trade the handle lock to the txn locker. */ + memset(&req, 0, sizeof(req)); + req.lock = dbp->handle_lock; + req.op = DB_LOCK_TRADE; + if ((ret = __lock_vec(env, txn->locker, 0, + &req, 1, 0)) != 0) + goto err; + dbp->cur_txn = txn; + dbp->cur_locker = txn->locker; + if ((ret = __txn_lockevent(env, txn, dbp, + &dbp->handle_lock, dbp->locker)) != 0) + goto err; + } + } + } +#ifdef HAVE_REPLICATION + /* + * If we are replicating from a down rev version then we must + * use old locking protocols. + */ + if (LOGGING_ON(env) && + ((LOG *)env->lg_handle-> + reginfo.primary)->persist.version < DB_LOGVERSION_LATCHING) + F_SET(dbc, DBC_DOWNREV); +#endif + + /* Refresh the DBC internal structure. */ + cp = dbc->internal; + cp->opd = NULL; + cp->pdbc = NULL; + + cp->indx = 0; + cp->page = NULL; + cp->pgno = PGNO_INVALID; + cp->root = root; + cp->stream_start_pgno = cp->stream_curr_pgno = PGNO_INVALID; + cp->stream_off = 0; + + if (DB_IS_PARTITIONED(dbp)) { + DBC_PART_REFRESH(dbc); + } else switch (dbtype) { + case DB_BTREE: + case DB_RECNO: + if ((ret = __bamc_refresh(dbc)) != 0) + goto err; + break; + case DB_HEAP: + if ((ret = __heapc_refresh(dbc)) != 0) + goto err; + break; + case DB_HASH: + case DB_QUEUE: + break; + case DB_UNKNOWN: + default: + ret = __db_unknown_type(env, "DB->cursor", dbp->type); + goto err; + } + + /* + * The transaction keeps track of how many cursors were opened within + * it to catch application errors where the cursor isn't closed when + * the transaction is resolved. + */ + if (txn != NULL) + ++txn->cursors; + if (ip != NULL) { + dbc->thread_info = ip; +#ifdef DIAGNOSTIC + if (dbc->locker != NULL) + ip->dbth_locker = + R_OFFSET(&(env->lk_handle->reginfo), dbc->locker); + else + ip->dbth_locker = INVALID_ROFF; +#endif + } else if (txn != NULL) + dbc->thread_info = txn->thread_info; + else + ENV_GET_THREAD_INFO(env, dbc->thread_info); + + MUTEX_LOCK(env, dbp->mutex); + TAILQ_INSERT_TAIL(&dbp->active_queue, dbc, links); + F_SET(dbc, DBC_ACTIVE); + MUTEX_UNLOCK(env, dbp->mutex); + + *dbcp = dbc; + return (0); + +err: if (allocated) + __os_free(env, dbc); + return (ret); +} + +/* + * __db_put -- + * Store a key/data pair. + * + * PUBLIC: int __db_put __P((DB *, + * PUBLIC: DB_THREAD_INFO *, DB_TXN *, DBT *, DBT *, u_int32_t)); + */ +int +__db_put(dbp, ip, txn, key, data, flags) + DB *dbp; + DB_THREAD_INFO *ip; + DB_TXN *txn; + DBT *key, *data; + u_int32_t flags; +{ + DB_HEAP_RID rid; + DBC *dbc; + DBT tdata, tkey; + ENV *env; + void *bulk_kptr, *bulk_ptr; + db_recno_t recno; + u_int32_t cursor_flags; + int ret, t_ret; + + env = dbp->env; + + /* + * See the comment in __db_get() regarding DB_CURSOR_TRANSIENT. + * + * Note that the get in the DB_NOOVERWRITE case is safe to do with this + * flag set; if it errors in any way other than DB_NOTFOUND, we're + * going to close the cursor without doing anything else, and if it + * returns DB_NOTFOUND then it's safe to do a c_put(DB_KEYLAST) even if + * an access method moved the cursor, since that's not + * position-dependent. + */ + cursor_flags = DB_WRITELOCK; + if (LF_ISSET(DB_MULTIPLE | DB_MULTIPLE_KEY)) + cursor_flags |= DB_CURSOR_BULK; + else + cursor_flags |= DB_CURSOR_TRANSIENT; + if ((ret = __db_cursor(dbp, ip, txn, &dbc, cursor_flags)) != 0) + return (ret); + + DEBUG_LWRITE(dbc, txn, "DB->put", key, data, flags); + PERFMON6(env, db, put, dbp->fname, + dbp->dname, txn == NULL ? 0 : txn->txnid, key, data, flags); + + SET_RET_MEM(dbc, dbp); + + if (flags == DB_APPEND && !DB_IS_PRIMARY(dbp)) { + /* + * If there is an append callback, the value stored in + * data->data may be replaced and then freed. To avoid + * passing a freed pointer back to the user, just operate + * on a copy of the data DBT. + */ + tdata = *data; + + /* + * Append isn't a normal put operation; call the appropriate + * access method's append function. + */ + switch (dbp->type) { + case DB_HEAP: + if ((ret = __heap_append(dbc, key, &tdata)) != 0) + goto err; + break; + case DB_QUEUE: + if ((ret = __qam_append(dbc, key, &tdata)) != 0) + goto err; + break; + case DB_RECNO: + if ((ret = __ram_append(dbc, key, &tdata)) != 0) + goto err; + break; + case DB_BTREE: + case DB_HASH: + case DB_UNKNOWN: + default: + /* The interface should prevent this. */ + DB_ASSERT(env, + dbp->type == DB_QUEUE || dbp->type == DB_RECNO); + + ret = __db_ferr(env, "DB->put", 0); + goto err; + } + + /* + * The append callback, if one exists, may have allocated + * a new tdata.data buffer. If so, free it. + */ + FREE_IF_NEEDED(env, &tdata); + + /* No need for a cursor put; we're done. */ +#ifdef HAVE_COMPRESSION + } else if (DB_IS_COMPRESSED(dbp) && !F_ISSET(dbp, DB_AM_SECONDARY) && + !DB_IS_PRIMARY(dbp) && LIST_FIRST(&dbp->f_primaries) == NULL) { + ret = __dbc_put(dbc, key, data, flags); +#endif + } else if (LF_ISSET(DB_MULTIPLE)) { + ret = 0; + memset(&tkey, 0, sizeof(tkey)); + if (dbp->type == DB_QUEUE || dbp->type == DB_RECNO) { + tkey.data = &recno; + tkey.size = sizeof(recno); + } + memset(&tdata, 0, sizeof(tdata)); + DB_MULTIPLE_INIT(bulk_kptr, key); + DB_MULTIPLE_INIT(bulk_ptr, data); + key->doff = 0; + while (ret == 0) { + if (dbp->type == DB_QUEUE || dbp->type == DB_RECNO) + DB_MULTIPLE_RECNO_NEXT(bulk_kptr, key, + recno, tdata.data, tdata.size); + else + DB_MULTIPLE_NEXT(bulk_kptr, key, + tkey.data, tkey.size); + DB_MULTIPLE_NEXT(bulk_ptr, data, + tdata.data, tdata.size); + if (bulk_kptr == NULL || bulk_ptr == NULL) + break; + if (dbp->type == DB_HEAP) { + memcpy(&rid, tkey.data, sizeof(DB_HEAP_RID)); + tkey.data = &rid; + } + ret = __dbc_put(dbc, &tkey, &tdata, + LF_ISSET(DB_OPFLAGS_MASK)); + if (ret == 0) + ++key->doff; + } + } else if (LF_ISSET(DB_MULTIPLE_KEY)) { + ret = 0; + memset(&tkey, 0, sizeof(tkey)); + if (dbp->type == DB_QUEUE || dbp->type == DB_RECNO) { + tkey.data = &recno; + tkey.size = sizeof(recno); + } + memset(&tdata, 0, sizeof(tdata)); + DB_MULTIPLE_INIT(bulk_ptr, key); + while (ret == 0) { + if (dbp->type == DB_QUEUE || dbp->type == DB_RECNO) + DB_MULTIPLE_RECNO_NEXT(bulk_ptr, key, recno, + tdata.data, tdata.size); + else + DB_MULTIPLE_KEY_NEXT(bulk_ptr, key, tkey.data, + tkey.size, tdata.data, tdata.size); + if (bulk_ptr == NULL) + break; + if (dbp->type == DB_HEAP) { + memcpy(&rid, tkey.data, sizeof(DB_HEAP_RID)); + tkey.data = &rid; + } + ret = __dbc_put(dbc, &tkey, &tdata, + LF_ISSET(DB_OPFLAGS_MASK)); + if (ret == 0) + ++key->doff; + } + } else + ret = __dbc_put(dbc, key, data, flags); + +err: /* Close the cursor. */ + if (!DB_RETOK_DBPUT(ret)) + F_SET(dbc, DBC_ERROR); + if ((t_ret = __dbc_close(dbc)) != 0 && ret == 0) + ret = t_ret; + + return (ret); +} + +/* + * __db_del -- + * Delete the items referenced by a key. + * + * PUBLIC: int __db_del __P((DB *, + * PUBLIC: DB_THREAD_INFO *, DB_TXN *, DBT *, u_int32_t)); + */ +int +__db_del(dbp, ip, txn, key, flags) + DB *dbp; + DB_THREAD_INFO *ip; + DB_TXN *txn; + DBT *key; + u_int32_t flags; +{ + DB_HEAP_RID rid; + DBC *dbc; + DBT data, tkey; + void *bulk_ptr; + db_recno_t recno; + u_int32_t cursor_flags, f_init, f_next; + int ret, t_ret; + + COMPQUIET(bulk_ptr, NULL); + /* Allocate a cursor. */ + cursor_flags = DB_WRITELOCK; + if (LF_ISSET(DB_MULTIPLE | DB_MULTIPLE_KEY)) + cursor_flags |= DB_CURSOR_BULK; + if ((ret = __db_cursor(dbp, ip, txn, &dbc, cursor_flags)) != 0) + return (ret); + + DEBUG_LWRITE(dbc, txn, "DB->del", key, NULL, flags); + PERFMON5(env, db, del, + dbp->fname, dbp->dname, txn == NULL ? 0 : txn->txnid, key, flags); + +#ifdef HAVE_COMPRESSION + if (DB_IS_COMPRESSED(dbp) && !F_ISSET(dbp, DB_AM_SECONDARY) && + !DB_IS_PRIMARY(dbp) && LIST_FIRST(&dbp->f_primaries) == NULL) { + F_SET(dbc, DBC_TRANSIENT); + ret = __dbc_bulk_del(dbc, key, flags); + goto err; + } +#endif + + /* + * Walk a cursor through the key/data pairs, deleting as we go. Set + * the DB_DBT_USERMEM flag, as this might be a threaded application + * and the flags checking will catch us. We don't actually want the + * keys or data, set DB_DBT_ISSET. We rely on __dbc_get to clear + * this. + */ + memset(&data, 0, sizeof(data)); + F_SET(&data, DB_DBT_USERMEM); + tkey = *key; + + f_init = LF_ISSET(DB_MULTIPLE_KEY) ? DB_GET_BOTH : DB_SET; + f_next = DB_NEXT_DUP; + + /* + * If locking (and we haven't already acquired CDB locks), set the + * read-modify-write flag. + */ + if (STD_LOCKING(dbc)) { + f_init |= DB_RMW; + f_next |= DB_RMW; + } + + if (LF_ISSET(DB_MULTIPLE | DB_MULTIPLE_KEY)) { + if (dbp->type == DB_QUEUE || dbp->type == DB_RECNO) { + memset(&tkey, 0, sizeof(tkey)); + tkey.data = &recno; + tkey.size = sizeof(recno); + } + DB_MULTIPLE_INIT(bulk_ptr, key); + /* We return the number of keys deleted in doff. */ + key->doff = 0; +bulk_next: if (dbp->type == DB_QUEUE || dbp->type == DB_RECNO) + DB_MULTIPLE_RECNO_NEXT(bulk_ptr, key, + recno, data.data, data.size); + else if (LF_ISSET(DB_MULTIPLE)) + DB_MULTIPLE_NEXT(bulk_ptr, key, tkey.data, tkey.size); + else + DB_MULTIPLE_KEY_NEXT(bulk_ptr, key, + tkey.data, tkey.size, data.data, data.size); + if (bulk_ptr == NULL) + goto err; + if (dbp->type == DB_HEAP) { + memcpy(&rid, tkey.data, sizeof(DB_HEAP_RID)); + tkey.data = &rid; + } + + } + + /* We're not interested in the data -- do not return it. */ + F_SET(&tkey, DB_DBT_ISSET); + F_SET(&data, DB_DBT_ISSET); + + /* + * Optimize the simple cases. For all AMs if we don't have secondaries + * and are not a secondary and we aren't a foreign database and there + * are no dups then we can avoid a bunch of overhead. For queue we + * don't need to fetch the record since we delete by direct calculation + * from the record number. + * + * Hash permits an optimization in DB->del: since on-page duplicates are + * stored in a single HKEYDATA structure, it's possible to delete an + * entire set of them at once, and as the HKEYDATA has to be rebuilt + * and re-put each time it changes, this is much faster than deleting + * the duplicates one by one. Thus, if not pointing at an off-page + * duplicate set, and we're not using secondary indices (in which case + * we'd have to examine the items one by one anyway), let hash do this + * "quick delete". + * + * !!! + * Note that this is the only application-executed delete call in + * Berkeley DB that does not go through the __dbc_del function. + * If anything other than the delete itself (like a secondary index + * update) has to happen there in a particular situation, the + * conditions here should be modified not to use these optimizations. + * The ordinary AM-independent alternative will work just fine; + * it'll just be slower. + */ + if (!F_ISSET(dbp, DB_AM_SECONDARY) && !DB_IS_PRIMARY(dbp) && + LIST_FIRST(&dbp->f_primaries) == NULL) { +#ifdef HAVE_QUEUE + if (dbp->type == DB_QUEUE) { + ret = __qam_delete(dbc, &tkey, flags); + goto next; + } +#endif + + /* Fetch the first record. */ + if ((ret = __dbc_get(dbc, &tkey, &data, f_init)) != 0) + goto err; + +#ifdef HAVE_HASH + /* + * Hash "quick delete" removes all on-page duplicates. We + * can't do that if deleting specific key/data pairs. + */ + if (dbp->type == DB_HASH && !LF_ISSET(DB_MULTIPLE_KEY)) { + DBC *sdbc; + sdbc = dbc; +#ifdef HAVE_PARTITION + if (F_ISSET(dbc, DBC_PARTITIONED)) + sdbc = + ((PART_CURSOR*)dbc->internal)->sub_cursor; +#endif + if (sdbc->internal->opd == NULL) { + ret = __ham_quick_delete(sdbc); + goto next; + } + } +#endif + + if (!F_ISSET(dbp, DB_AM_DUP)) { + ret = dbc->am_del(dbc, 0); + goto next; + } + } else if ((ret = __dbc_get(dbc, &tkey, &data, f_init)) != 0) + goto err; + + /* Walk through the set of key/data pairs, deleting as we go. */ + for (;;) { + if ((ret = __dbc_del(dbc, flags)) != 0) + break; + /* + * With DB_MULTIPLE_KEY, the application has specified the + * exact records they want deleted. We don't need to walk + * through a set of duplicates. + */ + if (LF_ISSET(DB_MULTIPLE_KEY)) + break; + + F_SET(&tkey, DB_DBT_ISSET); + F_SET(&data, DB_DBT_ISSET); + if ((ret = __dbc_get(dbc, &tkey, &data, f_next)) != 0) { + if (ret == DB_NOTFOUND) + ret = 0; + break; + } + } + +next: if (ret == 0 && LF_ISSET(DB_MULTIPLE | DB_MULTIPLE_KEY)) { + ++key->doff; + goto bulk_next; + } +err: /* Discard the cursor. */ + if (!DB_RETOK_DBDEL(ret)) + F_SET(dbc, DBC_ERROR); + if ((t_ret = __dbc_close(dbc)) != 0 && ret == 0) + ret = t_ret; + + return (ret); +} + +/* + * __db_sync -- + * Flush the database cache. + * + * PUBLIC: int __db_sync __P((DB *)); + */ +int +__db_sync(dbp) + DB *dbp; +{ + int ret, t_ret; + + ret = 0; + + /* If the database was read-only, we're done. */ + if (F_ISSET(dbp, DB_AM_RDONLY)) + return (0); + + /* If it's a Recno tree, write the backing source text file. */ + if (dbp->type == DB_RECNO) + ret = __ram_writeback(dbp); + + /* If the database was never backed by a database file, we're done. */ + if (F_ISSET(dbp, DB_AM_INMEM)) + return (ret); +#ifdef HAVE_PARTITION + if (DB_IS_PARTITIONED(dbp)) + ret = __partition_sync(dbp); + else +#endif + if (dbp->type == DB_QUEUE) + ret = __qam_sync(dbp); + else + /* Flush any dirty pages from the cache to the backing file. */ + if ((t_ret = __memp_fsync(dbp->mpf)) != 0 && ret == 0) + ret = t_ret; + + return (ret); +} + +/* + * __db_associate -- + * Associate another database as a secondary index to this one. + * + * PUBLIC: int __db_associate __P((DB *, DB_THREAD_INFO *, DB_TXN *, DB *, + * PUBLIC: int (*)(DB *, const DBT *, const DBT *, DBT *), u_int32_t)); + */ +int +__db_associate(dbp, ip, txn, sdbp, callback, flags) + DB *dbp, *sdbp; + DB_THREAD_INFO *ip; + DB_TXN *txn; + int (*callback) __P((DB *, const DBT *, const DBT *, DBT *)); + u_int32_t flags; +{ + DBC *pdbc, *sdbc; + DBT key, data, skey, *tskeyp; + ENV *env; + int build, ret, t_ret; + u_int32_t nskey; + + env = dbp->env; + pdbc = sdbc = NULL; + ret = 0; + + memset(&skey, 0, sizeof(DBT)); + nskey = 0; + tskeyp = NULL; + + /* + * Check to see if the secondary is empty -- and thus if we should + * build it -- before we link it in and risk making it show up in other + * threads. Do this first so that the databases remain unassociated on + * error. + */ + build = 0; + if (LF_ISSET(DB_CREATE)) { + FLD_SET(sdbp->s_assoc_flags, DB_ASSOC_CREATE); + + if ((ret = __db_cursor(sdbp, ip, txn, &sdbc, 0)) != 0) + goto err; + + /* + * We don't care about key or data; we're just doing + * an existence check. + */ + memset(&key, 0, sizeof(DBT)); + memset(&data, 0, sizeof(DBT)); + F_SET(&key, DB_DBT_PARTIAL | DB_DBT_USERMEM); + F_SET(&data, DB_DBT_PARTIAL | DB_DBT_USERMEM); + if ((ret = __dbc_get(sdbc, &key, &data, + (STD_LOCKING(sdbc) ? DB_RMW : 0) | + DB_FIRST)) == DB_NOTFOUND) { + build = 1; + ret = 0; + } + + if (ret != 0) + F_SET(sdbc, DBC_ERROR); + if ((t_ret = __dbc_close(sdbc)) != 0 && ret == 0) + ret = t_ret; + + /* Reset for later error check. */ + sdbc = NULL; + + if (ret != 0) + goto err; + } + + /* + * Set up the database handle as a secondary. + */ + sdbp->s_callback = callback; + sdbp->s_primary = dbp; + + sdbp->stored_get = sdbp->get; + sdbp->get = __db_secondary_get; + + sdbp->stored_close = sdbp->close; + sdbp->close = __db_secondary_close_pp; + + F_SET(sdbp, DB_AM_SECONDARY); + + if (LF_ISSET(DB_IMMUTABLE_KEY)) + FLD_SET(sdbp->s_assoc_flags, DB_ASSOC_IMMUTABLE_KEY); + + /* + * Add the secondary to the list on the primary. Do it here + * so that we see any updates that occur while we're walking + * the primary. + */ + MUTEX_LOCK(env, dbp->mutex); + + /* See __db_s_next for an explanation of secondary refcounting. */ + DB_ASSERT(env, sdbp->s_refcnt == 0); + sdbp->s_refcnt = 1; + LIST_INSERT_HEAD(&dbp->s_secondaries, sdbp, s_links); + MUTEX_UNLOCK(env, dbp->mutex); + + if (build) { + /* + * We loop through the primary, putting each item we + * find into the new secondary. + * + * If we're using CDB, opening these two cursors puts us + * in a bit of a locking tangle: CDB locks are done on the + * primary, so that we stay deadlock-free, but that means + * that updating the secondary while we have a read cursor + * open on the primary will self-block. To get around this, + * we force the primary cursor to use the same locker ID + * as the secondary, so they won't conflict. This should + * be harmless even if we're not using CDB. + */ + if ((ret = __db_cursor(sdbp, ip, txn, &sdbc, + CDB_LOCKING(sdbp->env) ? DB_WRITECURSOR : 0)) != 0) + goto err; + if ((ret = __db_cursor_int(dbp, ip, + txn, dbp->type, PGNO_INVALID, 0, sdbc->locker, &pdbc)) != 0) + goto err; + + /* Lock out other threads, now that we have a locker. */ + dbp->associate_locker = sdbc->locker; + + memset(&key, 0, sizeof(DBT)); + memset(&data, 0, sizeof(DBT)); + while ((ret = __dbc_get(pdbc, &key, &data, DB_NEXT)) == 0) { + if ((ret = callback(sdbp, &key, &data, &skey)) != 0) { + if (ret == DB_DONOTINDEX) + continue; + goto err; + } + if (F_ISSET(&skey, DB_DBT_MULTIPLE)) { +#ifdef DIAGNOSTIC + __db_check_skeyset(sdbp, &skey); +#endif + nskey = skey.size; + tskeyp = (DBT *)skey.data; + } else { + nskey = 1; + tskeyp = &skey; + } + SWAP_IF_NEEDED(sdbp, &key); + for (; nskey > 0; nskey--, tskeyp++) { + if ((ret = __dbc_put(sdbc, + tskeyp, &key, DB_UPDATE_SECONDARY)) != 0) + goto err; + FREE_IF_NEEDED(env, tskeyp); + } + SWAP_IF_NEEDED(sdbp, &key); + FREE_IF_NEEDED(env, &skey); + } + if (ret == DB_NOTFOUND) + ret = 0; + } + +err: if (sdbc != NULL && (t_ret = __dbc_close(sdbc)) != 0 && ret == 0) + ret = t_ret; + + if (pdbc != NULL && (t_ret = __dbc_close(pdbc)) != 0 && ret == 0) + ret = t_ret; + + dbp->associate_locker = NULL; + + for (; nskey > 0; nskey--, tskeyp++) + FREE_IF_NEEDED(env, tskeyp); + FREE_IF_NEEDED(env, &skey); + + return (ret); +} + +/* + * __db_secondary_get -- + * This wrapper function for DB->pget() is the DB->get() function + * on a database which has been made into a secondary index. + */ +static int +__db_secondary_get(sdbp, txn, skey, data, flags) + DB *sdbp; + DB_TXN *txn; + DBT *skey, *data; + u_int32_t flags; +{ + DB_ASSERT(sdbp->env, F_ISSET(sdbp, DB_AM_SECONDARY)); + return (__db_pget_pp(sdbp, txn, skey, NULL, data, flags)); +} + +/* + * __db_secondary_close -- + * Wrapper function for DB->close() which we use on secondaries to + * manage refcounting and make sure we don't close them underneath + * a primary that is updating. + * + * PUBLIC: int __db_secondary_close __P((DB *, u_int32_t)); + */ +int +__db_secondary_close(sdbp, flags) + DB *sdbp; + u_int32_t flags; +{ + DB *primary; + ENV *env; + int doclose; + + /* + * If the opening transaction is rolled back then the db handle + * will have already been refreshed, we just need to call + * __db_close to free the data. + */ + if (!F_ISSET(sdbp, DB_AM_OPEN_CALLED)) { + doclose = 1; + goto done; + } + doclose = 0; + primary = sdbp->s_primary; + env = primary->env; + + MUTEX_LOCK(env, primary->mutex); + /* + * Check the refcount--if it was at 1 when we were called, no + * thread is currently updating this secondary through the primary, + * so it's safe to close it for real. + * + * If it's not safe to do the close now, we do nothing; the + * database will actually be closed when the refcount is decremented, + * which can happen in either __db_s_next or __db_s_done. + */ + DB_ASSERT(env, sdbp->s_refcnt != 0); + if (--sdbp->s_refcnt == 0) { + LIST_REMOVE(sdbp, s_links); + /* We don't want to call close while the mutex is held. */ + doclose = 1; + } + MUTEX_UNLOCK(env, primary->mutex); + + /* + * sdbp->close is this function; call the real one explicitly if + * need be. + */ +done: return (doclose ? __db_close(sdbp, NULL, flags) : 0); +} + +/* + * __db_associate_foreign -- + * Associate this database (fdbp) as a foreign constraint to another + * database (pdbp). That is, dbp's keys appear as foreign key values in + * pdbp. + * + * PUBLIC: int __db_associate_foreign __P((DB *, DB *, + * PUBLIC: int (*)(DB *, const DBT *, DBT *, const DBT *, int *), + * PUBLIC: u_int32_t)); + */ +int +__db_associate_foreign(fdbp, pdbp, callback, flags) + DB *fdbp, *pdbp; + int (*callback)(DB *, const DBT *, DBT *, const DBT *, int *); + u_int32_t flags; +{ + DB_FOREIGN_INFO *f_info; + ENV *env; + int ret; + + env = fdbp->env; + ret = 0; + + if ((ret = __os_malloc(env, sizeof(DB_FOREIGN_INFO), &f_info)) != 0) { + return (ret); + } + memset(f_info, 0, sizeof(DB_FOREIGN_INFO)); + + f_info->dbp = pdbp; + f_info->callback = callback; + + /* + * It might be wise to filter this, but for now the flags only + * set the delete action type. + */ + FLD_SET(f_info->flags, flags); + + /* + * Add f_info to the foreign database's list of primaries. That is to + * say, fdbp->f_primaries lists all databases for which fdbp is a + * foreign constraint. + */ + MUTEX_LOCK(env, fdbp->mutex); + LIST_INSERT_HEAD(&fdbp->f_primaries, f_info, f_links); + MUTEX_UNLOCK(env, fdbp->mutex); + + /* + * Associate fdbp as pdbp's foreign db, for referential integrity + * checks. We don't allow the foreign db to be changed, because we + * currently have no way of removing pdbp from the old foreign db's list + * of primaries. + */ + if (pdbp->s_foreign != NULL) + return (EINVAL); + pdbp->s_foreign = fdbp; + + return (ret); +} + +static int +__dbc_set_priority(dbc, priority) + DBC *dbc; + DB_CACHE_PRIORITY priority; +{ + dbc->priority = priority; + return (0); +} + +static int +__dbc_get_priority(dbc, priority) + DBC *dbc; + DB_CACHE_PRIORITY *priority; +{ + if (dbc->priority == DB_PRIORITY_UNCHANGED) + return (__memp_get_priority(dbc->dbp->mpf, priority)); + else + *priority = dbc->priority; + + return (0); +} diff -r 000000000000 -r a1985f14b030 src/db/db_backup.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/db/db_backup.c Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,797 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 2011, 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + * $Id$ + */ + +#include "db_config.h" +#include "db_int.h" +#include "dbinc/db_page.h" +#include "dbinc/db_am.h" +#include "dbinc/heap.h" +#include "dbinc/mp.h" +#include "dbinc/partition.h" + +#ifdef HAVE_QUEUE +#include "dbinc/qam.h" +#endif + +static void save_error __P((const DB_ENV *, const char *, const char *)); +static int backup_read_log_dir __P((DB_ENV *, const char *, int *, u_int32_t)); +static int backup_read_data_dir + __P((DB_ENV *, DB_THREAD_INFO *, const char *, const char *, u_int32_t)); +static int backup_dir_clean + __P((DB_ENV *, const char *, const char *, int *, u_int32_t)); +static int backup_data_copy + __P((DB_ENV *, const char *, const char *, const char *, int)); + +/* + * __db_dbbackup_pp -- + * Copy a database file coordinated with mpool. + * + * PUBLIC: int __db_dbbackup_pp __P((DB_ENV *, + * PUBLIC: const char *, const char *, u_int32_t)); + */ +int +__db_dbbackup_pp(dbenv, dbfile, target, flags) + DB_ENV *dbenv; + const char *dbfile, *target; + u_int32_t flags; +{ + DB_THREAD_INFO *ip; + int ret; + + if ((ret = __db_fchk(dbenv->env, + "DB_ENV->dbbackup", flags, DB_EXCL)) != 0) + return (ret); + ENV_ENTER(dbenv->env, ip); + + ret = __db_dbbackup(dbenv, ip, dbfile, target, flags); + + ENV_LEAVE(dbenv->env, ip); + return (ret); +} + +/* + * __db_dbbackup -- + * Copy a database file coordinated with mpool. + * + * PUBLIC: int __db_dbbackup __P((DB_ENV *, DB_THREAD_INFO *, + * PUBLIC: const char *, const char *, u_int32_t)); + */ +int +__db_dbbackup(dbenv, ip, dbfile, target, flags) + DB_ENV *dbenv; + DB_THREAD_INFO *ip; + const char *dbfile, *target; + u_int32_t flags; +{ + DB *dbp; + DB_FH *fp; + void *handle; + int ret, retry_count, t_ret; + + dbp = NULL; + retry_count = 0; + +retry: if ((ret = __db_create_internal(&dbp, dbenv->env, 0)) == 0 && + (ret = __db_open(dbp, ip, NULL, dbfile, NULL, + DB_UNKNOWN, DB_AUTO_COMMIT | DB_RDONLY, 0, PGNO_BASE_MD)) != 0) { + if (ret == DB_LOCK_DEADLOCK || ret == DB_LOCK_NOTGRANTED) { + (void)__db_close(dbp, NULL, DB_NOSYNC); + dbp = NULL; + if (++retry_count > 100) + return (ret); + __db_errx(dbenv->env, DB_STR_A("0702", + "Deadlock while opening %s, retrying", "%s"), dbfile); + __os_yield(dbenv->env, 1, 0); + goto retry; + } + } + + if (ret == 0) { + if ((ret = __memp_backup_open(dbenv->env, + dbp->mpf, dbfile, target, flags, &fp, &handle)) == 0) { + if (dbp->type == DB_HEAP) + ret = __heap_backup( + dbenv, dbp, ip, fp, handle, flags); + else + ret = __memp_backup_mpf( + dbenv->env, dbp->mpf, + ip, 0, dbp->mpf->mfp->last_pgno, + fp, handle, flags); + } + if ((t_ret = __memp_backup_close(dbenv->env, + dbp->mpf, dbfile, fp, handle)) != 0 && ret == 0) + ret = t_ret; + } + +#ifdef HAVE_QUEUE + /* + * For compatibility with the 5.2 and patch versions of db_copy + * dump the queue extents here. + */ + if (ret == 0 && dbp->type == DB_QUEUE) + ret = __qam_backup_extents(dbp, ip, target, flags); +#endif + + if (dbp != NULL && + (t_ret = __db_close(dbp, NULL, DB_NOSYNC)) != 0 && ret == 0) + ret = t_ret; + + if (ret != 0) + __db_err(dbenv->env, ret, "Backup Failed"); + return (ret); +} + +/* + * backup_dir_clean -- + * Clean out the backup directory. + */ +static int +backup_dir_clean(dbenv, backup_dir, log_dir, remove_maxp, flags) + DB_ENV *dbenv; + const char *backup_dir, *log_dir; + int *remove_maxp; + u_int32_t flags; +{ + ENV *env; + int cnt, fcnt, ret, v; + const char *dir; + char **names, buf[DB_MAXPATHLEN], path[DB_MAXPATHLEN]; + + env = dbenv->env; + + /* We may be cleaning a log directory separate from the target. */ + if (log_dir != NULL) { + if ((ret = __os_concat_path(buf, + sizeof(buf), backup_dir, log_dir)) != 0) { + buf[sizeof(buf) - 1] = '\0'; + __db_errx(env, DB_STR_A("0717", + "%s: path too long", "%s"), buf); + return (EINVAL); + } + dir = buf; + } else + dir = backup_dir; + + /* Get a list of file names. */ + if ((ret = __os_dirlist(env, dir, 0, &names, &fcnt)) != 0) { + if (log_dir != NULL && !LF_ISSET(DB_BACKUP_UPDATE)) + return (0); + __db_err(env, + ret, DB_STR_A("0718", "%s: directory read", "%s"), dir); + return (ret); + } + for (cnt = fcnt; --cnt >= 0;) { + /* + * Skip non-log files (if update was specified). + */ + if (!IS_LOG_FILE(names[cnt])) { + if (LF_ISSET(DB_BACKUP_UPDATE)) + continue; + } else { + /* Track the highest-numbered log file removed. */ + v = atoi(names[cnt] + sizeof(LFPREFIX) - 1); + if (*remove_maxp < v) + *remove_maxp = v; + } + if ((ret = __os_concat_path(path, + sizeof(path), dir, names[cnt])) != 0) { + path[sizeof(path) - 1] = '\0'; + __db_errx(env, DB_STR_A("0714", + "%s: path too long", "%s"), path); + return (EINVAL); + } + if (FLD_ISSET(dbenv->verbose, DB_VERB_BACKUP)) + __db_msg(env, DB_STR_A("0715", "removing %s", + "%s"), path); + if ((ret = __os_unlink(env, path, 0)) != 0) + return (ret); + } + + __os_dirfree(env, names, fcnt); + + if (FLD_ISSET(dbenv->verbose, DB_VERB_BACKUP) && *remove_maxp != 0) + __db_msg(env, DB_STR_A("0719", + "highest numbered log file removed: %d", "%d"), + *remove_maxp); + + return (0); +} + +/* + * backup_data_copy -- + * Copy a non-database file into the backup directory. + */ +static int +backup_data_copy(dbenv, file, from_dir, to_dir, log) + DB_ENV *dbenv; + const char *file, *from_dir, *to_dir; + int log; +{ + DB_BACKUP *backup; + DB_FH *rfhp, *wfhp; + ENV *env; + u_int32_t gigs, off; + size_t nr, nw; + int ret, t_ret; + char *buf; + void *handle; + char from[DB_MAXPATHLEN], to[DB_MAXPATHLEN]; + + rfhp = wfhp = NULL; + handle = NULL; + buf = NULL; + env = dbenv->env; + backup = env->backup_handle; + + if ((ret = __os_concat_path(from, + sizeof(from), from_dir, file)) != 0) { + from[sizeof(from) - 1] = '\0'; + __db_errx(env, DB_STR_A("0728", + "%s: path too long", "%s"), from); + goto err; + } + if ((ret = __os_concat_path(to, + sizeof(to), to_dir, file)) != 0) { + to[sizeof(to) - 1] = '\0'; + __db_errx(env, DB_STR_A("0729", + "%s: path too long", "%s"), to); + goto err; + } + if (FLD_ISSET(dbenv->verbose, DB_VERB_BACKUP)) + __db_msg(env, DB_STR_A("0726", + "copying %s to %s", "%s %s"), from, to); + + if ((ret = __os_malloc(env, MEGABYTE, &buf)) != 0) { + __db_err(env, ret, DB_STR_A("0727", + "%lu buffer allocation", "%lu"), (u_long)MEGABYTE); + return (ret); + } + + /* Open the input file. */ + if ((ret = __os_open(env, from, 0, DB_OSO_RDONLY, 0, &rfhp)) != 0) { + if (ret == ENOENT && !log) { + ret = 0; + if (FLD_ISSET(dbenv->verbose, DB_VERB_BACKUP)) + __db_msg(env, DB_STR_A("0730", + "%s%c%s not present", "%s %c %s"), + from_dir, PATH_SEPARATOR[0], file); + goto done; + } + __db_err(env, ret, "%s", buf); + goto err; + } + + /* Open the output file. */ + if (backup != NULL && backup->open != NULL) + ret = backup->open(env->dbenv, file, to_dir, &handle); + else { + if ((ret = __os_open(env, to, 0, + DB_OSO_CREATE | DB_OSO_TRUNC, DB_MODE_600, &wfhp)) != 0) { + __db_err(env, ret, "%s", to); + goto err; + } + } + + off = 0; + gigs = 0; + /* Copy the data. */ + while ((ret = __os_read(env, rfhp, buf, MEGABYTE, &nr)) == 0 && + nr > 0) { + if (backup != NULL && backup->write != NULL) { + if ((ret = backup->write(env->dbenv, gigs, + off, (u_int32_t)nr, (u_int8_t *)buf, handle)) != 0) + break; + } else { + if ((ret = __os_write(env, wfhp, buf, nr, &nw)) != 0) + break; + if (nr != nw) { + ret = EIO; + break; + } + } + off += (u_int32_t)nr; + if (off >= GIGABYTE) { + gigs++; + off -= GIGABYTE; + } + } + if (ret != 0) + __db_err(env, ret, DB_STR("0748", "Write failed.")); + +err: +done: if (buf != NULL) + __os_free(env, buf); + + if (backup != NULL && backup->close != NULL && + (t_ret = backup->close(env->dbenv, file, handle)) != 0 && ret != 0) + ret = t_ret; + if (rfhp != NULL && + (t_ret = __os_closehandle(env, rfhp)) != 0 && ret == 0) + ret = t_ret; + + /* We may be running on a remote filesystem; force the flush. */ + if (ret == 0 && wfhp != NULL) { + ret = __os_fsync(env, wfhp); + if (ret != 0) + __db_err(env, ret, DB_STR("0731", "Sync failed")); + } + if (wfhp != NULL && + (t_ret = __os_closehandle(env, wfhp)) != 0 && ret == 0) + ret = t_ret; + return (ret); +} + +static void save_error(dbenv, prefix, errstr) + const DB_ENV *dbenv; + const char *prefix; + const char *errstr; +{ + COMPQUIET(prefix, NULL); + if (DB_GLOBAL(saved_errstr) != NULL) + __os_free(dbenv->env, DB_GLOBAL(saved_errstr)); + (void)__os_strdup(dbenv->env, errstr, &DB_GLOBAL(saved_errstr)); +} + +/* + * backup_read_data_dir -- + * Read a directory looking for databases to copy. + */ +static int +backup_read_data_dir(dbenv, ip, dir, backup_dir, flags) + DB_ENV *dbenv; + DB_THREAD_INFO *ip; + const char *dir, *backup_dir; + u_int32_t flags; +{ + DB_MSGBUF mb; + ENV *env; + FILE *savefile; + int fcnt, ret; + size_t cnt; + const char *bd; + char **names, buf[DB_MAXPATHLEN], bbuf[DB_MAXPATHLEN]; + void (*savecall) (const DB_ENV *, const char *, const char *); + + env = dbenv->env; + memset(bbuf, 0, sizeof(bbuf)); + + bd = backup_dir; + if (!LF_ISSET(DB_BACKUP_SINGLE_DIR) && dir != env->db_home) { + cnt = sizeof(bbuf); + /* Build a path name to the destination. */ + if ((ret = __os_concat_path(bbuf, sizeof(bbuf), + backup_dir, dir)) != 0 || + (((cnt = strlen(bbuf)) == sizeof(bbuf) || + (cnt == sizeof(bbuf) - 1 && + strchr(PATH_SEPARATOR, bbuf[cnt - 1]) == NULL)) && + LF_ISSET(DB_CREATE))) { + bbuf[sizeof(bbuf) - 1] = '\0'; + __db_errx(env, DB_STR_A("0720", + "%s: path too long", "%s"), bbuf); + return (1); + } + + /* Create the path. */ + if (LF_ISSET(DB_CREATE)) { + if (strchr(PATH_SEPARATOR, bbuf[cnt - 1]) == NULL) + bbuf[cnt] = PATH_SEPARATOR[0]; + + if ((ret = __db_mkpath(env, bbuf)) != 0) { + __db_err(env, ret, DB_STR_A("0721", + "%s: cannot create", "%s"), bbuf); + return (ret); + } + /* step on the trailing '/' */ + bbuf[cnt] = '\0'; + } + bd = bbuf; + + } + if (!__os_abspath(dir) && dir != env->db_home) { + /* Build a path name to the source. */ + if ((ret = __os_concat_path(buf, + sizeof(buf), env->db_home, dir)) != 0) { + buf[sizeof(buf) - 1] = '\0'; + __db_errx(env, DB_STR_A("0722", + "%s: path too long", "%s"), buf); + return (EINVAL); + } + dir = buf; + } + /* Get a list of file names. */ + if ((ret = __os_dirlist(env, dir, 0, &names, &fcnt)) != 0) { + __db_err(env, ret, DB_STR_A("0723", "%s: directory read", + "%s"), dir); + return (ret); + } + for (cnt = (size_t)fcnt; cnt-- > 0;) { + /* + * Skip files in DB's name space, except replication dbs. + */ + if (IS_LOG_FILE(names[cnt])) + continue; + if (IS_DB_FILE(names[cnt]) && !IS_REP_FILE(names[cnt]) +#ifdef HAVE_PARTITION + && !IS_PARTITION_DB_FILE(names[cnt]) +#endif + ) + continue; + + /* + * Skip DB_CONFIG. + */ + if (LF_ISSET(DB_BACKUP_SINGLE_DIR) && + !strncmp(names[cnt], "DB_CONFIG", sizeof("DB_CONFIG"))) + continue; + + /* + * Copy the database. + */ + + DB_MSGBUF_INIT(&mb); + if (FLD_ISSET(dbenv->verbose, DB_VERB_BACKUP)) + __db_msgadd(env, &mb, DB_STR_A("0724", + "copying database %s%c%s to %s%c%s", + "%s%c%s %s%c%s"), + dir, PATH_SEPARATOR[0], names[cnt], + bd, PATH_SEPARATOR[0], names[cnt]); + + /* + * Suppress errors on non-db files. + */ + savecall = dbenv->db_errcall; + dbenv->db_errcall = save_error; + savefile = dbenv->db_errfile; + dbenv->db_errfile = NULL; + + ret = __db_dbbackup(dbenv, ip, names[cnt], bd, flags); + + dbenv->db_errcall = savecall; + dbenv->db_errfile = savefile; + + /* The file might not be a database. */ + if (ret == ENOENT || ret == EINVAL) { + if (FLD_ISSET(dbenv->verbose, DB_VERB_BACKUP)) { + __db_msgadd(env, &mb, " -- Not a database"); + DB_MSGBUF_FLUSH(env, &mb); + } + if (LF_ISSET(DB_BACKUP_FILES)) + ret = backup_data_copy( + dbenv, names[cnt], dir, bd, 0); + else + ret = 0; + } else if (FLD_ISSET(dbenv->verbose, DB_VERB_BACKUP)) + DB_MSGBUF_FLUSH(env, &mb); + + if (ret != 0) { + if (DB_GLOBAL(saved_errstr) != NULL) { + __db_errx(env, "%s", DB_GLOBAL(saved_errstr)); + __os_free(env, DB_GLOBAL(saved_errstr)); + DB_GLOBAL(saved_errstr) = NULL; + } + break; + } + } + + __os_dirfree(env, names, fcnt); + + return (ret); +} + +/* + * backup_read_log_dir -- + * Read a directory looking for log files to copy. + */ +static int +backup_read_log_dir(dbenv, backup_dir, copy_minp, flags) + DB_ENV *dbenv; + const char *backup_dir; + int *copy_minp; + u_int32_t flags; +{ + ENV *env; + u_int32_t aflag; + size_t cnt; + int ret, update, v; + const char *backupd; + char **begin, **names, *logd; + char from[DB_MAXPATHLEN], to[DB_MAXPATHLEN]; + + env = dbenv->env; + ret = 0; + begin = NULL; + memset(to, 0, sizeof(to)); + + /* + * Figure out where the log files are and create the log + * destination directory if necessary. + */ + backupd = backup_dir; + if ((logd = dbenv->db_log_dir) == NULL) + logd = env->db_home; + else { + if (!LF_ISSET(DB_BACKUP_SINGLE_DIR)) { + cnt = sizeof(to); + if ((ret = __os_concat_path(to, + sizeof(to), backup_dir, logd)) != 0 || + (((cnt = strlen(to)) == sizeof(to) || + (cnt == sizeof(to) - 1 && + strchr(PATH_SEPARATOR, to[cnt - 1]) == NULL)) && + LF_ISSET(DB_CREATE))) { + to[sizeof(to) - 1] = '\0'; + __db_errx(env, DB_STR_A("0733", + "%s: path too long", "%s"), to); + goto err; + } + if (LF_ISSET(DB_CREATE)) { + if (strchr(PATH_SEPARATOR, to[cnt - 1]) == NULL) + to[cnt] = PATH_SEPARATOR[0]; + + if ((ret = __db_mkpath(env, to)) != 0) { + __db_err(env, ret, DB_STR_A("0734", + "%s: cannot create", "%s"), to); + goto err; + } + to[cnt] = '\0'; + } + if ((ret = __os_strdup(env, to, (void*) &backupd)) != 0) + goto err; + } + if (!__os_abspath(logd)) { + if ((ret = __os_concat_path(from, + sizeof(from), env->db_home, logd)) != 0) { + from[sizeof(from) - 1] = '\0'; + __db_errx(env, DB_STR_A("0732", + "%s: path too long", "%s"), from); + goto err; + } + if ((ret = __os_strdup(env, from, &logd)) != 0) + goto err; + } + } + + update = LF_ISSET(DB_BACKUP_UPDATE); +again: aflag = DB_ARCH_LOG; + + /* + * If this is an update and we are deleting files, first process + * those files that can be removed, then repeat with the rest. + */ + if (update) + aflag = 0; + + /* Flush the log to get latest info. */ + if ((ret = __log_flush(env, NULL)) != 0) { + __db_err(env, ret, DB_STR("0735", "Can't flush log")); + goto err; + } + + /* Get a list of file names to be copied. */ + if ((ret = __log_archive(env, &names, aflag)) != 0) { + __db_err(env, ret, DB_STR("0736", "Can't get log file names")); + goto err; + } + if (names == NULL) + goto done; + begin = names; + for (; *names != NULL; names++) { + /* Track the lowest-numbered log file copied. */ + v = atoi(*names + sizeof(LFPREFIX) - 1); + if (*copy_minp == 0 || *copy_minp > v) + *copy_minp = v; + + if ((ret = __os_concat_path(from, + sizeof(from), env->db_home, *names)) != 0) { + from[sizeof(from) - 1] = '\0'; + __db_errx(env, DB_STR_A("0737", + "%s: path too long", "%s"), from); + goto err; + } + + /* + * If we're going to remove the file, attempt to rename it + * instead of copying and then removing. The likely failure + * is EXDEV (source and destination are on different volumes). + * Fall back to a copy, regardless of the error. We don't + * worry about partial contents, the copy truncates the file + * on open. + */ + if (update) { + if ((ret = __os_concat_path(to, + sizeof(to), backupd, *names)) != 0) { + to[sizeof(to) - 1] = '\0'; + __db_errx(env, DB_STR_A("0738", + "%s: path too long", "%s"), to); + goto err; + } + if (__os_rename(env, from, to, 1) == 0) { + if (FLD_ISSET(dbenv->verbose, DB_VERB_BACKUP)) + __db_msg(env, DB_STR_A("0739", + "moving %s to %s", + "%s %s"), from, to); + continue; + } + } + + /* Copy the file. */ + if (backup_data_copy(dbenv, *names, logd, backupd, 1) != 0) { + ret = 1; + goto err; + } + + if (update) { + if (FLD_ISSET(dbenv->verbose, DB_VERB_BACKUP)) + __db_msg(env, DB_STR_A("0740", + "removing %s", "%s"), from); + if ((ret = __os_unlink(env, from, 0)) != 0) { + __db_err(env, ret, DB_STR_A("0741", + "unlink of %s failed", "%s"), from); + goto err; + } + } + + } + + __os_ufree(env, begin); + begin = NULL; +done: if (update) { + update = 0; + goto again; + } + + if (FLD_ISSET(dbenv->verbose, DB_VERB_BACKUP) && *copy_minp != 0) + __db_msg(env, DB_STR_A("0742", + "lowest numbered log file copied: %d", "%d"), + *copy_minp); +err: if (logd != dbenv->db_log_dir && logd != env->db_home) + __os_free(env, logd); + if (backupd != NULL && backupd != backup_dir) + __os_free(env, (void *)backupd); + if (begin != NULL) + __os_free(env, begin); + + return (ret); +} + +/* + * __db_backup -- + * Backup databases in the enviornment. + * + * PUBLIC: int __db_backup __P((DB_ENV *, const char *, u_int32_t)); + */ +int +__db_backup(dbenv, target, flags) + DB_ENV *dbenv; + const char *target; + u_int32_t flags; +{ + DB_THREAD_INFO *ip; + ENV *env; + int copy_min, remove_max, ret; + char **dir; + + env = dbenv->env; + remove_max = copy_min = 0; + +#undef OKFLAGS +#define OKFLAGS \ + (DB_CREATE | DB_EXCL | DB_BACKUP_FILES | DB_BACKUP_SINGLE_DIR | \ + DB_BACKUP_UPDATE | DB_BACKUP_NO_LOGS | DB_BACKUP_CLEAN) + + if ((ret = __db_fchk(env, "DB_ENV->backup", flags, OKFLAGS)) != 0) + return (ret); + + if (target == NULL) { + __db_errx(env, + DB_STR("0716", "Target directory may not be null.")); + return (EINVAL); + } + + /* + * If the target directory for the backup does not exist, create it + * with mode read-write-execute for the owner. Ignore errors here, + * it's simpler and more portable to just always try the create. If + * there's a problem, we'll fail with reasonable errors later. + */ + if (LF_ISSET(DB_CREATE)) + (void)__os_mkdir(NULL, target, DB_MODE_700); + + if (LF_ISSET(DB_BACKUP_CLEAN)) { + if (!LF_ISSET(DB_BACKUP_SINGLE_DIR) && + dbenv->db_log_dir != NULL && + (ret = backup_dir_clean(dbenv, target, + dbenv->db_log_dir, &remove_max, flags)) != 0) + return (ret); + if ((ret = backup_dir_clean(dbenv, + target, NULL, &remove_max, flags)) != 0) + return (ret); + + } + + ENV_ENTER(env, ip); + + /* + * If the UPDATE option was not specified, copy all database + * files found in the database environment home directory and + * data directories.. + */ + if ((ret = __env_set_backup(env, 1)) != 0) + goto end; + F_SET(dbenv, DB_ENV_HOTBACKUP); + if (!LF_ISSET(DB_BACKUP_UPDATE)) { + if ((ret = backup_read_data_dir(dbenv, + ip, env->db_home, target, flags)) != 0) + goto err; + for (dir = dbenv->db_data_dir; + dir != NULL && *dir != NULL; ++dir) { + /* + * Don't allow absolute path names taken from the + * enviroment -- running recovery with them would + * corrupt the source files. + */ + if (!LF_ISSET(DB_BACKUP_SINGLE_DIR) + && __os_abspath(*dir)) { + __db_errx(env, DB_STR_A("0725", +"data directory '%s' is absolute path, not permitted unless backup is to a single directory", + "%s"), *dir); + ret = EINVAL; + goto err; + } + if ((ret = backup_read_data_dir( + dbenv, ip, *dir, target, flags)) != 0) + goto err; + } + } + + /* + * Copy all log files found in the log directory. + * The log directory defaults to the home directory. + */ + if ((ret = backup_read_log_dir(dbenv, target, ©_min, flags)) != 0) + goto err; + /* + * If we're updating a snapshot, the lowest-numbered log file copied + * into the backup directory should be less than, or equal to, the + * highest-numbered log file removed from the backup directory during + * cleanup. + */ + if (LF_ISSET(DB_BACKUP_UPDATE) && remove_max < copy_min && + !(remove_max == 0 && copy_min == 1)) { + __db_errx(env, DB_STR_A("0743", +"the largest log file removed (%d) must be greater than or equal the smallest log file copied (%d)", + "%d %d"), remove_max, copy_min); + ret = EINVAL; + } + +err: F_CLR(dbenv, DB_ENV_HOTBACKUP); + (void)__env_set_backup(env, 0); +end: ENV_LEAVE(env, ip); + return (ret); +} diff -r 000000000000 -r a1985f14b030 src/db/db_cam.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/db/db_cam.c Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,3545 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 2000, 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + * $Id$ + */ + +#include "db_config.h" + +#include "db_int.h" +#include "dbinc/db_page.h" +#include "dbinc/btree.h" +#include "dbinc/hash.h" +#include "dbinc/heap.h" +#include "dbinc/lock.h" +#include "dbinc/mp.h" +#include "dbinc/partition.h" +#include "dbinc/qam.h" +#include "dbinc/txn.h" + +static int __db_s_count __P((DB *)); +static int __db_wrlock_err __P((ENV *)); +static int __dbc_del_foreign __P((DBC *)); +static int __dbc_del_oldskey __P((DB *, DBC *, DBT *, DBT *, DBT *)); +static int __dbc_del_secondary __P((DBC *)); +static int __dbc_pget_recno __P((DBC *, DBT *, DBT *, u_int32_t)); +static inline int __dbc_put_append __P((DBC *, + DBT *, DBT *, u_int32_t *, u_int32_t)); +static inline int __dbc_put_fixed_len __P((DBC *, DBT *, DBT *)); +static inline int __dbc_put_partial __P((DBC *, + DBT *, DBT *, DBT *, DBT *, u_int32_t *, u_int32_t)); +static int __dbc_put_primary __P((DBC *, DBT *, DBT *, u_int32_t)); +static inline int __dbc_put_resolve_key __P((DBC *, + DBT *, DBT *, u_int32_t *, u_int32_t)); +static inline int __dbc_put_secondaries __P((DBC *, + DBT *, DBT *, DBT *, int, DBT *, u_int32_t *)); + +#define CDB_LOCKING_INIT(env, dbc) \ + /* \ + * If we are running CDB, this had better be either a write \ + * cursor or an immediate writer. If it's a regular writer, \ + * that means we have an IWRITE lock and we need to upgrade \ + * it to a write lock. \ + */ \ + if (CDB_LOCKING(env)) { \ + if (!F_ISSET(dbc, DBC_WRITECURSOR | DBC_WRITER)) \ + return (__db_wrlock_err(env)); \ + \ + if (F_ISSET(dbc, DBC_WRITECURSOR) && \ + (ret = __lock_get(env, \ + (dbc)->locker, DB_LOCK_UPGRADE, &(dbc)->lock_dbt, \ + DB_LOCK_WRITE, &(dbc)->mylock)) != 0) \ + return (ret); \ + } +#define CDB_LOCKING_DONE(env, dbc) \ + /* Release the upgraded lock. */ \ + if (F_ISSET(dbc, DBC_WRITECURSOR)) \ + (void)__lock_downgrade( \ + env, &(dbc)->mylock, DB_LOCK_IWRITE, 0); + +#define SET_READ_LOCKING_FLAGS(dbc, var) do { \ + var = 0; \ + if (!F_ISSET(dbc, DBC_READ_COMMITTED | DBC_READ_UNCOMMITTED)) { \ + if (LF_ISSET(DB_READ_COMMITTED)) \ + var = DBC_READ_COMMITTED | DBC_WAS_READ_COMMITTED; \ + if (LF_ISSET(DB_READ_UNCOMMITTED)) \ + var = DBC_READ_UNCOMMITTED; \ + } \ + LF_CLR(DB_READ_COMMITTED | DB_READ_UNCOMMITTED); \ +} while (0) + +/* + * __dbc_close -- + * DBC->close. + * + * PUBLIC: int __dbc_close __P((DBC *)); + */ +int +__dbc_close(dbc) + DBC *dbc; +{ + DB *dbp; + DBC *opd; + DBC_INTERNAL *cp; + DB_TXN *txn; + ENV *env; + int ret, t_ret; + + dbp = dbc->dbp; + env = dbp->env; + cp = dbc->internal; + opd = cp->opd; + ret = 0; + + /* + * Remove the cursor(s) from the active queue. We may be closing two + * cursors at once here, a top-level one and a lower-level, off-page + * duplicate one. The access-method specific cursor close routine must + * close both of them in a single call. + * + * !!! + * Cursors must be removed from the active queue before calling the + * access specific cursor close routine, btree depends on having that + * order of operations. + */ + MUTEX_LOCK(env, dbp->mutex); + + if (opd != NULL) { + DB_ASSERT(env, F_ISSET(opd, DBC_ACTIVE)); + F_CLR(opd, DBC_ACTIVE); + TAILQ_REMOVE(&dbp->active_queue, opd, links); + } + DB_ASSERT(env, F_ISSET(dbc, DBC_ACTIVE)); + F_CLR(dbc, DBC_ACTIVE); + TAILQ_REMOVE(&dbp->active_queue, dbc, links); + + MUTEX_UNLOCK(env, dbp->mutex); + + /* Call the access specific cursor close routine. */ + if ((t_ret = + dbc->am_close(dbc, PGNO_INVALID, NULL)) != 0 && ret == 0) + ret = t_ret; + + /* + * Release the lock after calling the access method specific close + * routine, a Btree cursor may have had pending deletes. + * + * Also, be sure not to free anything if mylock.off is INVALID; in + * some cases, such as idup'ed read cursors and secondary update + * cursors, a cursor in a CDB environment may not have a lock at all. + */ + if (LOCK_ISSET(dbc->mylock)) { + if ((t_ret = __LPUT(dbc, dbc->mylock)) != 0 && ret == 0) + ret = t_ret; + + /* For safety's sake, since this is going on the free queue. */ + memset(&dbc->mylock, 0, sizeof(dbc->mylock)); + if (opd != NULL) + memset(&opd->mylock, 0, sizeof(opd->mylock)); + } + + /* + * Remove this cursor's locker ID from its family. + */ + if (F_ISSET(dbc, DBC_OWN_LID) && F_ISSET(dbc, DBC_FAMILY)) { + if ((t_ret = __lock_familyremove(env->lk_handle, + dbc->lref)) != 0 && ret == 0) + ret = t_ret; + F_CLR(dbc, DBC_FAMILY); + } + + if ((txn = dbc->txn) != NULL) + txn->cursors--; + + /* Move the cursor(s) to the free queue. */ + MUTEX_LOCK(env, dbp->mutex); + if (opd != NULL) { + if (txn != NULL) + txn->cursors--; + TAILQ_INSERT_TAIL(&dbp->free_queue, opd, links); + } + TAILQ_INSERT_TAIL(&dbp->free_queue, dbc, links); + MUTEX_UNLOCK(env, dbp->mutex); + + if (txn != NULL && F_ISSET(txn, TXN_PRIVATE) && txn->cursors == 0 && + (t_ret = __txn_commit(txn, 0)) != 0 && ret == 0) + ret = t_ret; + + return (ret); +} + +/* + * __dbc_destroy -- + * Destroy the cursor, called after DBC->close. + * + * PUBLIC: int __dbc_destroy __P((DBC *)); + */ +int +__dbc_destroy(dbc) + DBC *dbc; +{ + DB *dbp; + ENV *env; + int ret, t_ret; + + dbp = dbc->dbp; + env = dbp->env; + + /* Remove the cursor from the free queue. */ + MUTEX_LOCK(env, dbp->mutex); + TAILQ_REMOVE(&dbp->free_queue, dbc, links); + MUTEX_UNLOCK(env, dbp->mutex); + + /* Free up allocated memory. */ + if (dbc->my_rskey.data != NULL) + __os_free(env, dbc->my_rskey.data); + if (dbc->my_rkey.data != NULL) + __os_free(env, dbc->my_rkey.data); + if (dbc->my_rdata.data != NULL) + __os_free(env, dbc->my_rdata.data); + + /* Call the access specific cursor destroy routine. */ + ret = dbc->am_destroy == NULL ? 0 : dbc->am_destroy(dbc); + + /* + * Release the lock id for this cursor. + */ + if (LOCKING_ON(env) && + F_ISSET(dbc, DBC_OWN_LID) && + (t_ret = __lock_id_free(env, dbc->lref)) != 0 && ret == 0) + ret = t_ret; + + __os_free(env, dbc); + + return (ret); +} + +/* + * __dbc_cmp -- + * Compare the position of two cursors. Return whether two cursors are + * pointing to the same key/data pair. + * + * result == 0 if both cursors refer to the same item. + * result == 1 otherwise + * + * PUBLIC: int __dbc_cmp __P((DBC *, DBC *, int *)); + */ +int +__dbc_cmp(dbc, other_dbc, result) + DBC *dbc, *other_dbc; + int *result; +{ + DBC *curr_dbc, *curr_odbc; + DBC_INTERNAL *dbc_int, *odbc_int; + ENV *env; + int ret; + + env = dbc->env; + ret = 0; + +#ifdef HAVE_PARTITION + if (DB_IS_PARTITIONED(dbc->dbp)) { + dbc = ((PART_CURSOR *)dbc->internal)->sub_cursor; + other_dbc = ((PART_CURSOR *)other_dbc->internal)->sub_cursor; + } + /* Both cursors must still be valid. */ + if (dbc == NULL || other_dbc == NULL) { + __db_errx(env, DB_STR("0692", +"Both cursors must be initialized before calling DBC->cmp.")); + return (EINVAL); + } + + if (dbc->dbp != other_dbc->dbp) { + *result = 1; + return (0); + } +#endif + +#ifdef HAVE_COMPRESSION + if (DB_IS_COMPRESSED(dbc->dbp)) + return (__bamc_compress_cmp(dbc, other_dbc, result)); +#endif + + curr_dbc = dbc; + curr_odbc = other_dbc; + dbc_int = dbc->internal; + odbc_int = other_dbc->internal; + + /* Both cursors must be on valid positions. */ + if (dbc_int->pgno == PGNO_INVALID || odbc_int->pgno == PGNO_INVALID) { + __db_errx(env, DB_STR("0693", +"Both cursors must be initialized before calling DBC->cmp.")); + return (EINVAL); + } + + /* + * Use a loop since cursors can be nested. Off page duplicate + * sets can only be nested one level deep, so it is safe to use a + * while (true) loop. + */ + while (1) { + if (dbc_int->pgno == odbc_int->pgno && + dbc_int->indx == odbc_int->indx) { + /* + * If one cursor is sitting on an off page duplicate + * set, the other will be pointing to the same set. Be + * careful, and check anyway. + */ + if (dbc_int->opd != NULL && odbc_int->opd != NULL) { + curr_dbc = dbc_int->opd; + curr_odbc = odbc_int->opd; + dbc_int = dbc_int->opd->internal; + odbc_int= odbc_int->opd->internal; + continue; + } else if (dbc_int->opd == NULL && + odbc_int->opd == NULL) + *result = 0; + else { + __db_errx(env, DB_STR("0694", + "DBCursor->cmp mismatched off page duplicate cursor pointers.")); + return (EINVAL); + } + + switch (curr_dbc->dbtype) { + case DB_HASH: + /* + * Make sure that on-page duplicate data + * indexes match, and that the deleted + * flags are consistent. + */ + ret = __hamc_cmp(curr_dbc, curr_odbc, result); + break; + case DB_BTREE: + case DB_RECNO: + /* + * Check for consisted deleted flags on btree + * specific cursors. + */ + ret = __bamc_cmp(curr_dbc, curr_odbc, result); + break; + default: + /* NO-OP break out. */ + break; + } + } else + *result = 1; + return (ret); + } + /* NOTREACHED. */ + return (ret); +} + +/* + * __dbc_count -- + * Return a count of duplicate data items. + * + * PUBLIC: int __dbc_count __P((DBC *, db_recno_t *)); + */ +int +__dbc_count(dbc, recnop) + DBC *dbc; + db_recno_t *recnop; +{ + ENV *env; + int ret; + + env = dbc->env; + +#ifdef HAVE_PARTITION + if (DB_IS_PARTITIONED(dbc->dbp)) + dbc = ((PART_CURSOR *)dbc->internal)->sub_cursor; +#endif + /* + * Cursor Cleanup Note: + * All of the cursors passed to the underlying access methods by this + * routine are not duplicated and will not be cleaned up on return. + * So, pages/locks that the cursor references must be resolved by the + * underlying functions. + */ + switch (dbc->dbtype) { + case DB_HEAP: + case DB_QUEUE: + case DB_RECNO: + *recnop = 1; + break; + case DB_HASH: + if (dbc->internal->opd == NULL) { + if ((ret = __hamc_count(dbc, recnop)) != 0) + return (ret); + break; + } + /* FALLTHROUGH */ + case DB_BTREE: +#ifdef HAVE_COMPRESSION + if (DB_IS_COMPRESSED(dbc->dbp)) + return (__bamc_compress_count(dbc, recnop)); +#endif + if ((ret = __bamc_count(dbc, recnop)) != 0) + return (ret); + break; + case DB_UNKNOWN: + default: + return (__db_unknown_type(env, "__dbc_count", dbc->dbtype)); + } + return (0); +} + +/* + * __dbc_del -- + * DBC->del. + * + * PUBLIC: int __dbc_del __P((DBC *, u_int32_t)); + */ +int +__dbc_del(dbc, flags) + DBC *dbc; + u_int32_t flags; +{ + DB *dbp; + ENV *env; + int ret; + + dbp = dbc->dbp; + env = dbp->env; + + CDB_LOCKING_INIT(env, dbc); + F_CLR(dbc, DBC_ERROR); + + /* + * If we're a secondary index, and DB_UPDATE_SECONDARY isn't set + * (which it only is if we're being called from a primary update), + * then we need to call through to the primary and delete the item. + * + * Note that this will delete the current item; we don't need to + * delete it ourselves as well, so we can just goto done. + */ + if (flags != DB_UPDATE_SECONDARY && F_ISSET(dbp, DB_AM_SECONDARY)) { + ret = __dbc_del_secondary(dbc); + goto done; + } + + /* + * If we are a foreign db, go through and check any foreign key + * constraints first, which will make rolling back changes on an abort + * simpler. + */ + if (LIST_FIRST(&dbp->f_primaries) != NULL && + (ret = __dbc_del_foreign(dbc)) != 0) + goto done; + + /* + * If we are a primary and have secondary indices, go through + * and delete any secondary keys that point at the current record. + */ + if (DB_IS_PRIMARY(dbp) && + (ret = __dbc_del_primary(dbc)) != 0) + goto done; + +#ifdef HAVE_COMPRESSION + if (DB_IS_COMPRESSED(dbp)) + ret = __bamc_compress_del(dbc, flags); + else +#endif + ret = __dbc_idel(dbc, flags); + +done: CDB_LOCKING_DONE(env, dbc); + + if (!DB_RETOK_DBCDEL(ret)) + F_SET(dbc, DBC_ERROR); + return (ret); +} + +/* + * __dbc_del -- + * Implemenation of DBC->del. + * + * PUBLIC: int __dbc_idel __P((DBC *, u_int32_t)); + */ +int +__dbc_idel(dbc, flags) + DBC *dbc; + u_int32_t flags; +{ + DB *dbp; + DBC *opd; + int ret, t_ret; + + COMPQUIET(flags, 0); + + dbp = dbc->dbp; + + /* + * Cursor Cleanup Note: + * All of the cursors passed to the underlying access methods by this + * routine are not duplicated and will not be cleaned up on return. + * So, pages/locks that the cursor references must be resolved by the + * underlying functions. + */ + + /* + * Off-page duplicate trees are locked in the primary tree, that is, + * we acquire a write lock in the primary tree and no locks in the + * off-page dup tree. If the del operation is done in an off-page + * duplicate tree, call the primary cursor's upgrade routine first. + */ + opd = dbc->internal->opd; + if (opd == NULL) + ret = dbc->am_del(dbc, flags); + else if ((ret = dbc->am_writelock(dbc)) == 0) + ret = opd->am_del(opd, flags); + + /* + * If this was an update that is supporting dirty reads + * then we may have just swapped our read for a write lock + * which is held by the surviving cursor. We need + * to explicitly downgrade this lock. The closed cursor + * may only have had a read lock. + */ + if (ret == 0 && F_ISSET(dbp, DB_AM_READ_UNCOMMITTED) && + dbc->internal->lock_mode == DB_LOCK_WRITE) { + if ((ret = __TLPUT(dbc, dbc->internal->lock)) == 0) + dbc->internal->lock_mode = DB_LOCK_WWRITE; + if (dbc->internal->page != NULL && (t_ret = + __memp_shared(dbp->mpf, dbc->internal->page)) != 0 && + ret == 0) + ret = t_ret; + } + + return (ret); +} + +#ifdef HAVE_COMPRESSION +/* + * __dbc_bulk_del -- + * Bulk del for a cursor. + * + * Only implemented for compressed BTrees. In this file in order to + * use the CDB_LOCKING_* macros. + * + * PUBLIC: #ifdef HAVE_COMPRESSION + * PUBLIC: int __dbc_bulk_del __P((DBC *, DBT *, u_int32_t)); + * PUBLIC: #endif + */ +int +__dbc_bulk_del(dbc, key, flags) + DBC *dbc; + DBT *key; + u_int32_t flags; +{ + ENV *env; + int ret; + + env = dbc->env; + + DB_ASSERT(env, DB_IS_COMPRESSED(dbc->dbp)); + + CDB_LOCKING_INIT(env, dbc); + F_CLR(dbc, DBC_ERROR); + + ret = __bamc_compress_bulk_del(dbc, key, flags); + + CDB_LOCKING_DONE(env, dbc); + + return (ret); +} +#endif + +/* + * __dbc_dup -- + * Duplicate a cursor + * + * PUBLIC: int __dbc_dup __P((DBC *, DBC **, u_int32_t)); + */ +int +__dbc_dup(dbc_orig, dbcp, flags) + DBC *dbc_orig; + DBC **dbcp; + u_int32_t flags; +{ + DBC *dbc_n, *dbc_nopd; + int ret; + + dbc_n = dbc_nopd = NULL; + + /* Allocate a new cursor and initialize it. */ + if ((ret = __dbc_idup(dbc_orig, &dbc_n, flags)) != 0) + goto err; + *dbcp = dbc_n; + + /* + * If the cursor references an off-page duplicate tree, allocate a + * new cursor for that tree and initialize it. + */ + if (dbc_orig->internal->opd != NULL) { + if ((ret = + __dbc_idup(dbc_orig->internal->opd, &dbc_nopd, flags)) != 0) + goto err; + dbc_n->internal->opd = dbc_nopd; + dbc_nopd->internal->pdbc = dbc_n; + } + return (0); + +err: if (dbc_n != NULL) + (void)__dbc_close(dbc_n); + if (dbc_nopd != NULL) + (void)__dbc_close(dbc_nopd); + + return (ret); +} + +/* + * __dbc_idup -- + * Internal version of __dbc_dup. + * + * PUBLIC: int __dbc_idup __P((DBC *, DBC **, u_int32_t)); + */ +int +__dbc_idup(dbc_orig, dbcp, flags) + DBC *dbc_orig, **dbcp; + u_int32_t flags; +{ + DB *dbp; + DBC *dbc_n; + DBC_INTERNAL *int_n, *int_orig; + ENV *env; + int ret; + + dbp = dbc_orig->dbp; + dbc_n = *dbcp; + env = dbp->env; + + if ((ret = __db_cursor_int(dbp, dbc_orig->thread_info, + dbc_orig->txn, dbc_orig->dbtype, dbc_orig->internal->root, + F_ISSET(dbc_orig, DBC_OPD) | DBC_DUPLICATE, + dbc_orig->locker, &dbc_n)) != 0) + return (ret); + + /* Position the cursor if requested, acquiring the necessary locks. */ + if (LF_ISSET(DB_POSITION)) { + int_n = dbc_n->internal; + int_orig = dbc_orig->internal; + + dbc_n->flags |= dbc_orig->flags & ~DBC_OWN_LID; + + int_n->indx = int_orig->indx; + int_n->pgno = int_orig->pgno; + int_n->root = int_orig->root; + int_n->lock_mode = int_orig->lock_mode; + + int_n->stream_start_pgno = int_orig->stream_start_pgno; + int_n->stream_off = int_orig->stream_off; + int_n->stream_curr_pgno = int_orig->stream_curr_pgno; + + switch (dbc_orig->dbtype) { + case DB_QUEUE: + if ((ret = __qamc_dup(dbc_orig, dbc_n)) != 0) + goto err; + break; + case DB_BTREE: + case DB_RECNO: + if ((ret = __bamc_dup(dbc_orig, dbc_n, flags)) != 0) + goto err; + break; + case DB_HASH: + if ((ret = __hamc_dup(dbc_orig, dbc_n)) != 0) + goto err; + break; + case DB_HEAP: + if ((ret = __heapc_dup(dbc_orig, dbc_n)) != 0) + goto err; + break; + case DB_UNKNOWN: + default: + ret = __db_unknown_type(env, + "__dbc_idup", dbc_orig->dbtype); + goto err; + } + } else if (F_ISSET(dbc_orig, DBC_BULK)) { + /* + * For bulk cursors, remember what page were on, even if we + * don't know that the next operation will be nearby. + */ + dbc_n->internal->pgno = dbc_orig->internal->pgno; + } + + /* Copy the locking flags to the new cursor. */ + F_SET(dbc_n, F_ISSET(dbc_orig, DBC_BULK | + DBC_READ_COMMITTED | DBC_READ_UNCOMMITTED | DBC_WRITECURSOR)); + + /* + * If we're in CDB and this isn't an offpage dup cursor, then + * we need to get a lock for the duplicated cursor. + */ + if (CDB_LOCKING(env) && !F_ISSET(dbc_n, DBC_OPD) && + (ret = __lock_get(env, dbc_n->locker, 0, + &dbc_n->lock_dbt, F_ISSET(dbc_orig, DBC_WRITECURSOR) ? + DB_LOCK_IWRITE : DB_LOCK_READ, &dbc_n->mylock)) != 0) + goto err; + + dbc_n->priority = dbc_orig->priority; + dbc_n->internal->pdbc = dbc_orig->internal->pdbc; + *dbcp = dbc_n; + return (0); + +err: (void)__dbc_close(dbc_n); + return (ret); +} + +/* + * __dbc_newopd -- + * Create a new off-page duplicate cursor. + * + * PUBLIC: int __dbc_newopd __P((DBC *, db_pgno_t, DBC *, DBC **)); + */ +int +__dbc_newopd(dbc_parent, root, oldopd, dbcp) + DBC *dbc_parent; + db_pgno_t root; + DBC *oldopd; + DBC **dbcp; +{ + DB *dbp; + DBC *opd; + DBTYPE dbtype; + int ret; + + dbp = dbc_parent->dbp; + dbtype = (dbp->dup_compare == NULL) ? DB_RECNO : DB_BTREE; + + /* + * On failure, we want to default to returning the old off-page dup + * cursor, if any; our caller can't be left with a dangling pointer + * to a freed cursor. On error the only allowable behavior is to + * close the cursor (and the old OPD cursor it in turn points to), so + * this should be safe. + */ + *dbcp = oldopd; + + if ((ret = __db_cursor_int(dbp, dbc_parent->thread_info, + dbc_parent->txn, + dbtype, root, DBC_OPD, dbc_parent->locker, &opd)) != 0) + return (ret); + + opd->priority = dbc_parent->priority; + opd->internal->pdbc = dbc_parent; + *dbcp = opd; + + /* + * Check to see if we already have an off-page dup cursor that we've + * passed in. If we do, close it. It'd be nice to use it again + * if it's a cursor belonging to the right tree, but if we're doing + * a cursor-relative operation this might not be safe, so for now + * we'll take the easy way out and always close and reopen. + * + * Note that under no circumstances do we want to close the old + * cursor without returning a valid new one; we don't want to + * leave the main cursor in our caller with a non-NULL pointer + * to a freed off-page dup cursor. + */ + if (oldopd != NULL && (ret = __dbc_close(oldopd)) != 0) + return (ret); + + return (0); +} + +/* + * __dbc_get -- + * Get using a cursor. + * + * PUBLIC: int __dbc_get __P((DBC *, DBT *, DBT *, u_int32_t)); + */ +int +__dbc_get(dbc, key, data, flags) + DBC *dbc; + DBT *key, *data; + u_int32_t flags; +{ + F_CLR(dbc, DBC_ERROR); +#ifdef HAVE_PARTITION + if (F_ISSET(dbc, DBC_PARTITIONED)) + return (__partc_get(dbc, key, data, flags)); +#endif + +#ifdef HAVE_COMPRESSION + if (DB_IS_COMPRESSED(dbc->dbp)) + return (__bamc_compress_get(dbc, key, data, flags)); +#endif + + return (__dbc_iget(dbc, key, data, flags)); +} + +/* + * __dbc_iget -- + * Implementation of get using a cursor. + * + * PUBLIC: int __dbc_iget __P((DBC *, DBT *, DBT *, u_int32_t)); + */ +int +__dbc_iget(dbc, key, data, flags) + DBC *dbc; + DBT *key, *data; + u_int32_t flags; +{ + DB *dbp; + DBC *ddbc, *dbc_n, *opd; + DBC_INTERNAL *cp, *cp_n; + DB_MPOOLFILE *mpf; + ENV *env; + db_pgno_t pgno; + db_indx_t indx_off; + u_int32_t multi, orig_ulen, tmp_flags, tmp_read_locking, tmp_rmw; + u_int8_t type; + int key_small, ret, t_ret; + + COMPQUIET(orig_ulen, 0); + + key_small = 0; + + /* + * Cursor Cleanup Note: + * All of the cursors passed to the underlying access methods by this + * routine are duplicated cursors. On return, any referenced pages + * will be discarded, and, if the cursor is not intended to be used + * again, the close function will be called. So, pages/locks that + * the cursor references do not need to be resolved by the underlying + * functions. + */ + dbp = dbc->dbp; + env = dbp->env; + mpf = dbp->mpf; + dbc_n = NULL; + opd = NULL; + + PERFMON6(env, db, get, dbp->fname, dbp->dname, + dbc->txn == NULL ? 0 : dbc->txn->txnid, key, data, flags); + + /* Clear OR'd in additional bits so we can check for flag equality. */ + tmp_rmw = LF_ISSET(DB_RMW); + LF_CLR(DB_RMW); + + SET_READ_LOCKING_FLAGS(dbc, tmp_read_locking); + + multi = LF_ISSET(DB_MULTIPLE|DB_MULTIPLE_KEY); + LF_CLR(DB_MULTIPLE|DB_MULTIPLE_KEY); + + /* + * Return a cursor's record number. It has nothing to do with the + * cursor get code except that it was put into the interface. + */ + if (flags == DB_GET_RECNO) { + if (tmp_rmw) + F_SET(dbc, DBC_RMW); + F_SET(dbc, tmp_read_locking); + ret = __bamc_rget(dbc, data); + if (tmp_rmw) + F_CLR(dbc, DBC_RMW); + /* Clear the temp flags, but leave WAS_READ_COMMITTED. */ + F_CLR(dbc, tmp_read_locking & ~DBC_WAS_READ_COMMITTED); + return (ret); + } + + if (flags == DB_CONSUME || flags == DB_CONSUME_WAIT) + CDB_LOCKING_INIT(env, dbc); + + /* Don't return the key or data if it was passed to us. */ + if (!DB_RETURNS_A_KEY(dbp, flags)) + F_SET(key, DB_DBT_ISSET); + if (flags == DB_GET_BOTH && + (dbp->dup_compare == NULL || dbp->dup_compare == __bam_defcmp)) + F_SET(data, DB_DBT_ISSET); + + /* + * If we have an off-page duplicates cursor, and the operation applies + * to it, perform the operation. Duplicate the cursor and call the + * underlying function. + * + * Off-page duplicate trees are locked in the primary tree, that is, + * we acquire a write lock in the primary tree and no locks in the + * off-page dup tree. If the DB_RMW flag was specified and the get + * operation is done in an off-page duplicate tree, call the primary + * cursor's upgrade routine first. + */ + cp = dbc->internal; + if (cp->opd != NULL && + (flags == DB_CURRENT || flags == DB_GET_BOTHC || + flags == DB_NEXT || flags == DB_NEXT_DUP || + flags == DB_PREV || flags == DB_PREV_DUP)) { + if (tmp_rmw && (ret = dbc->am_writelock(dbc)) != 0) + goto err; + if (F_ISSET(dbc, DBC_TRANSIENT)) + opd = cp->opd; + else if ((ret = __dbc_idup(cp->opd, &opd, DB_POSITION)) != 0) + goto err; + + if ((ret = opd->am_get(opd, key, data, flags, NULL)) == 0) + goto done; + /* + * Another cursor may have deleted all of the off-page + * duplicates, so for operations that are moving a cursor, we + * need to skip the empty tree and retry on the parent cursor. + */ + if (ret == DB_NOTFOUND && + (flags == DB_PREV || flags == DB_NEXT)) { + ret = __dbc_close(opd); + opd = NULL; + if (F_ISSET(dbc, DBC_TRANSIENT)) + cp->opd = NULL; + } + if (ret != 0) + goto err; + } else if (cp->opd != NULL && F_ISSET(dbc, DBC_TRANSIENT)) { + if ((ret = __dbc_close(cp->opd)) != 0) + goto err; + cp->opd = NULL; + } + + /* + * Perform an operation on the main cursor. Duplicate the cursor, + * upgrade the lock as required, and call the underlying function. + */ + switch (flags) { + case DB_CURRENT: + case DB_GET_BOTHC: + case DB_NEXT: + case DB_NEXT_DUP: + case DB_NEXT_NODUP: + case DB_PREV: + case DB_PREV_DUP: + case DB_PREV_NODUP: + tmp_flags = DB_POSITION; + break; + default: + tmp_flags = 0; + break; + } + + /* + * If this cursor is going to be closed immediately, we don't + * need to take precautions to clean it up on error. + */ + if (F_ISSET(dbc, DBC_TRANSIENT | DBC_PARTITIONED)) + dbc_n = dbc; + else { + ret = __dbc_idup(dbc, &dbc_n, tmp_flags); + + if (ret != 0) + goto err; + COPY_RET_MEM(dbc, dbc_n); + } + + if (tmp_rmw) + F_SET(dbc_n, DBC_RMW); + F_SET(dbc_n, tmp_read_locking); + + switch (multi) { + case DB_MULTIPLE: + F_SET(dbc_n, DBC_MULTIPLE); + break; + case DB_MULTIPLE_KEY: + F_SET(dbc_n, DBC_MULTIPLE_KEY); + break; + case DB_MULTIPLE | DB_MULTIPLE_KEY: + F_SET(dbc_n, DBC_MULTIPLE|DBC_MULTIPLE_KEY); + break; + case 0: + default: + break; + } + +retry: pgno = PGNO_INVALID; + ret = dbc_n->am_get(dbc_n, key, data, flags, &pgno); + if (tmp_rmw) + F_CLR(dbc_n, DBC_RMW); + /* + * Clear the temporary locking flags in the new cursor. The user's + * (old) cursor needs to have the WAS_READ_COMMITTED flag because this + * is used on the next call on that cursor. + */ + F_CLR(dbc_n, tmp_read_locking); + F_SET(dbc, tmp_read_locking & DBC_WAS_READ_COMMITTED); + F_CLR(dbc_n, DBC_MULTIPLE|DBC_MULTIPLE_KEY); + if (ret != 0) + goto err; + + cp_n = dbc_n->internal; + + /* + * We may be referencing a new off-page duplicates tree. Acquire + * a new cursor and call the underlying function. + */ + if (pgno != PGNO_INVALID) { + if ((ret = __dbc_newopd(dbc, + pgno, cp_n->opd, &cp_n->opd)) != 0) + goto err; + + switch (flags) { + case DB_FIRST: + case DB_NEXT: + case DB_NEXT_NODUP: + case DB_SET: + case DB_SET_RECNO: + case DB_SET_RANGE: + tmp_flags = DB_FIRST; + break; + case DB_LAST: + case DB_PREV: + case DB_PREV_NODUP: + tmp_flags = DB_LAST; + break; + case DB_GET_BOTH: + case DB_GET_BOTHC: + case DB_GET_BOTH_RANGE: + tmp_flags = flags; + break; + default: + ret = __db_unknown_flag(env, "__dbc_get", flags); + goto err; + } + ret = cp_n->opd->am_get(cp_n->opd, key, data, tmp_flags, NULL); + /* + * Another cursor may have deleted all of the off-page + * duplicates, so for operations that are moving a cursor, we + * need to skip the empty tree and retry on the parent cursor. + */ + if (ret == DB_NOTFOUND) { + PERFMON5(env, race, dbc_get, + dbp->fname, dbp->dname, ret, tmp_flags, key); + + switch (flags) { + case DB_FIRST: + case DB_NEXT: + case DB_NEXT_NODUP: + flags = DB_NEXT; + break; + case DB_LAST: + case DB_PREV: + case DB_PREV_NODUP: + flags = DB_PREV; + break; + default: + goto err; + } + + ret = __dbc_close(cp_n->opd); + cp_n->opd = NULL; + if (ret == 0) + goto retry; + } + if (ret != 0) + goto err; + } + +done: /* + * Return a key/data item. The only exception is that we don't return + * a key if the user already gave us one, that is, if the DB_SET flag + * was set. The DB_SET flag is necessary. In a Btree, the user's key + * doesn't have to be the same as the key stored the tree, depending on + * the magic performed by the comparison function. As we may not have + * done any key-oriented operation here, the page reference may not be + * valid. Fill it in as necessary. We don't have to worry about any + * locks, the cursor must already be holding appropriate locks. + * + * XXX + * If not a Btree and DB_SET_RANGE is set, we shouldn't return a key + * either, should we? + */ + cp_n = dbc_n == NULL ? dbc->internal : dbc_n->internal; + if (!F_ISSET(key, DB_DBT_ISSET)) { + if (cp_n->page == NULL && (ret = __memp_fget(mpf, &cp_n->pgno, + dbc->thread_info, dbc->txn, 0, &cp_n->page)) != 0) + goto err; + + if ((ret = __db_ret(dbc, cp_n->page, cp_n->indx, key, + &dbc->rkey->data, &dbc->rkey->ulen)) != 0) { + /* + * If the key DBT is too small, we still want to return + * the size of the data. Otherwise applications are + * forced to check each one with a separate call. We + * don't want to copy the data, so we set the ulen to + * zero before calling __db_ret. + */ + if (ret == DB_BUFFER_SMALL && + F_ISSET(data, DB_DBT_USERMEM)) { + key_small = 1; + orig_ulen = data->ulen; + data->ulen = 0; + } else + goto err; + } + } + if (multi != 0 && dbc->am_bulk != NULL) { + /* + * Even if fetching from the OPD cursor we need a duplicate + * primary cursor if we are going after multiple keys. + */ + if (dbc_n == NULL) { + /* + * Non-"_KEY" DB_MULTIPLE doesn't move the main cursor, + * so it's safe to just use dbc, unless the cursor + * has an open off-page duplicate cursor whose state + * might need to be preserved. + */ + if ((!(multi & DB_MULTIPLE_KEY) && + dbc->internal->opd == NULL) || + F_ISSET(dbc, DBC_TRANSIENT | DBC_PARTITIONED)) + dbc_n = dbc; + else { + if ((ret = __dbc_idup(dbc, + &dbc_n, DB_POSITION)) != 0) + goto err; + if ((ret = dbc_n->am_get(dbc_n, + key, data, DB_CURRENT, &pgno)) != 0) + goto err; + } + cp_n = dbc_n->internal; + } + + /* + * If opd is set then we dupped the opd that we came in with. + * When we return we may have a new opd if we went to another + * key. + */ + if (opd != NULL) { + DB_ASSERT(env, cp_n->opd == NULL); + cp_n->opd = opd; + opd = NULL; + } + + /* + * Bulk get doesn't use __db_retcopy, so data.size won't + * get set up unless there is an error. Assume success + * here. This is the only call to am_bulk, and it avoids + * setting it exactly the same everywhere. If we have an + * DB_BUFFER_SMALL error, it'll get overwritten with the + * needed value. + */ + data->size = data->ulen; + ret = dbc_n->am_bulk(dbc_n, data, flags | multi); + } else if (!F_ISSET(data, DB_DBT_ISSET)) { + ddbc = opd != NULL ? opd : + cp_n->opd != NULL ? cp_n->opd : dbc_n; + cp = ddbc->internal; + if (cp->page == NULL && + (ret = __memp_fget(mpf, &cp->pgno, + dbc->thread_info, ddbc->txn, 0, &cp->page)) != 0) + goto err; + + type = TYPE(cp->page); + indx_off = ((type == P_LBTREE || + type == P_HASH || type == P_HASH_UNSORTED) ? O_INDX : 0); + ret = __db_ret(ddbc, cp->page, cp->indx + indx_off, + data, &dbc->rdata->data, &dbc->rdata->ulen); + } + +err: /* Don't pass DB_DBT_ISSET back to application level, error or no. */ + F_CLR(key, DB_DBT_ISSET); + F_CLR(data, DB_DBT_ISSET); + + /* Cleanup and cursor resolution. */ + if (opd != NULL) { + /* + * To support dirty reads we must reget the write lock + * if we have just stepped off a deleted record. + * Since the OPD cursor does not know anything + * about the referencing page or cursor we need + * to peek at the OPD cursor and get the lock here. + */ + if (F_ISSET(dbp, DB_AM_READ_UNCOMMITTED) && + F_ISSET((BTREE_CURSOR *) + dbc->internal->opd->internal, C_DELETED)) + if ((t_ret = + dbc->am_writelock(dbc)) != 0 && ret == 0) + ret = t_ret; + if ((t_ret = __dbc_cleanup( + dbc->internal->opd, opd, ret)) != 0 && ret == 0) + ret = t_ret; + } + + if (key_small) { + data->ulen = orig_ulen; + if (ret == 0) + ret = DB_BUFFER_SMALL; + } + + if ((t_ret = __dbc_cleanup(dbc, dbc_n, ret)) != 0 && + (ret == 0 || ret == DB_BUFFER_SMALL)) + ret = t_ret; + + if (flags == DB_CONSUME || flags == DB_CONSUME_WAIT) + CDB_LOCKING_DONE(env, dbc); + return (ret); +} + +/* Internal flags shared by the dbc_put functions. */ +#define DBC_PUT_RMW 0x001 +#define DBC_PUT_NODEL 0x002 +#define DBC_PUT_HAVEREC 0x004 + +/* + * __dbc_put_resolve_key -- + * Get the current key and data so that we can correctly update the + * secondary and foreign databases. + */ +static inline int +__dbc_put_resolve_key(dbc, oldkey, olddata, put_statep, flags) + DBC *dbc; + DBT *oldkey, *olddata; + u_int32_t flags, *put_statep; +{ + DB *dbp; + ENV *env; + int ret, rmw; + + dbp = dbc->dbp; + env = dbp->env; + rmw = FLD_ISSET(*put_statep, DBC_PUT_RMW) ? DB_RMW : 0; + + DB_ASSERT(env, flags == DB_CURRENT); + COMPQUIET(flags, 0); + + /* + * This is safe to do on the cursor we already have; + * error or no, it won't move. + * + * We use DB_RMW for all of these gets because we'll be + * writing soon enough in the "normal" put code. In + * transactional databases we'll hold those write locks + * even if we close the cursor we're reading with. + * + * The DB_KEYEMPTY return needs special handling -- if the + * cursor is on a deleted key, we return DB_NOTFOUND. + */ + memset(oldkey, 0, sizeof(DBT)); + if ((ret = __dbc_get(dbc, oldkey, olddata, rmw | DB_CURRENT)) != 0) + return (ret == DB_KEYEMPTY ? DB_NOTFOUND : ret); + + /* Record that we've looked for the old record. */ + FLD_SET(*put_statep, DBC_PUT_HAVEREC); + return (0); +} + +/* + * __dbc_put_append -- + * Handle an append to a primary. + */ +static inline int +__dbc_put_append(dbc, key, data, put_statep, flags) + DBC *dbc; + DBT *key, *data; + u_int32_t flags, *put_statep; +{ + DB *dbp; + ENV *env; + DBC *dbc_n; + DBT tdata; + int ret, t_ret; + + dbp = dbc->dbp; + env = dbp->env; + ret = 0; + dbc_n = NULL; + + DB_ASSERT(env, flags == DB_APPEND); + COMPQUIET(flags, 0); + + /* + * With DB_APPEND, we need to do the insert to populate the key value. + * So we swap the 'normal' order of updating secondary / verifying + * foreign databases and inserting. + * + * If there is an append callback, the value stored in data->data may + * be replaced and then freed. To avoid passing a freed pointer back + * to the user, just operate on a copy of the data DBT. + */ + tdata = *data; + + /* + * If this cursor is going to be closed immediately, we don't + * need to take precautions to clean it up on error. + */ + if (F_ISSET(dbc, DBC_TRANSIENT)) + dbc_n = dbc; + else if ((ret = __dbc_idup(dbc, &dbc_n, 0)) != 0) + goto err; + + /* + * Append isn't a normal put operation; call the appropriate access + * method's append function. + */ + switch (dbp->type) { + case DB_HEAP: + if ((ret = __heap_append(dbc_n, key, &tdata)) != 0) + goto err; + break; + case DB_QUEUE: + if ((ret = __qam_append(dbc_n, key, &tdata)) != 0) + goto err; + break; + case DB_RECNO: + if ((ret = __ram_append(dbc_n, key, &tdata)) != 0) + goto err; + break; + default: + /* The interface should prevent this. */ + DB_ASSERT(env, + dbp->type == DB_QUEUE || dbp->type == DB_RECNO); + + ret = __db_ferr(env, "DBC->put", 0); + goto err; + } + + /* + * The append callback, if one exists, may have allocated a new + * tdata.data buffer. If so, free it. + */ + FREE_IF_NEEDED(env, &tdata); + + /* + * The key value may have been generated by the above operation, but + * not set in the data buffer. Make sure it is there so that secondary + * updates can complete. + */ + __dbt_userfree(env, key, NULL, NULL); + if ((ret = __dbt_usercopy(env, key)) != 0) + goto err; + + /* An append cannot be replacing an existing item. */ + FLD_SET(*put_statep, DBC_PUT_NODEL); + +err: if (dbc_n != NULL && + (t_ret = __dbc_cleanup(dbc, dbc_n, ret)) != 0 && ret == 0) + ret = t_ret; + return (ret); +} + +/* + * __dbc_put_partial -- + * Ensure that the data item we are using is complete and correct. + * Otherwise we could break the secondary constraints. + */ +static inline int +__dbc_put_partial(dbc, pkey, data, orig_data, out_data, put_statep, flags) + DBC *dbc; + DBT *pkey, *data, *orig_data, *out_data; + u_int32_t *put_statep, flags; +{ + DB *dbp; + DBC *pdbc; + ENV *env; + int ret, rmw, t_ret; + + dbp = dbc->dbp; + env = dbp->env; + ret = t_ret = 0; + rmw = FLD_ISSET(*put_statep, DBC_PUT_RMW) ? DB_RMW : 0; + + if (!FLD_ISSET(*put_statep, DBC_PUT_HAVEREC) && + !FLD_ISSET(*put_statep, DBC_PUT_NODEL)) { + /* + * We're going to have to search the tree for the + * specified key. Dup a cursor (so we have the same + * locking info) and do a c_get. + */ + if ((ret = __dbc_idup(dbc, &pdbc, 0)) != 0) + return (ret); + + /* + * When doing a put with DB_CURRENT, partial data items have + * already been resolved. + */ + DB_ASSERT(env, flags != DB_CURRENT); + + F_SET(pkey, DB_DBT_ISSET); + ret = __dbc_get(pdbc, pkey, orig_data, rmw | DB_SET); + if (ret == DB_KEYEMPTY || ret == DB_NOTFOUND) { + FLD_SET(*put_statep, DBC_PUT_NODEL); + ret = 0; + } + if ((t_ret = __dbc_close(pdbc)) != 0) + ret = t_ret; + if (ret != 0) + return (ret); + + FLD_SET(*put_statep, DBC_PUT_HAVEREC); + } + + COMPQUIET(flags, 0); + + /* + * Now build the new datum from orig_data and the partial data + * we were given. It's okay to do this if no record was + * returned above: a partial put on an empty record is allowed, + * if a little strange. The data is zero-padded. + */ + return (__db_buildpartial(dbp, orig_data, data, out_data)); +} + +/* + * __dbc_put_fixed_len -- + * Handle padding for fixed-length records. + */ +static inline int +__dbc_put_fixed_len(dbc, data, out_data) + DBC *dbc; + DBT *data, *out_data; +{ + DB *dbp; + ENV *env; + int re_pad, ret; + u_int32_t re_len, size; + + dbp = dbc->dbp; + env = dbp->env; + ret = 0; + + /* + * Handle fixed-length records. If the primary database has + * fixed-length records, we need to pad out the datum before + * we pass it into the callback function; we always index the + * "real" record. + */ + if (dbp->type == DB_QUEUE) { + re_len = ((QUEUE *)dbp->q_internal)->re_len; + re_pad = ((QUEUE *)dbp->q_internal)->re_pad; + } else { + re_len = ((BTREE *)dbp->bt_internal)->re_len; + re_pad = ((BTREE *)dbp->bt_internal)->re_pad; + } + + size = data->size; + if (size > re_len) { + ret = __db_rec_toobig(env, size, re_len); + return (ret); + } else if (size < re_len) { + /* + * If we're not doing a partial put, copy data->data into + * out_data->data, then pad out out_data->data. This overrides + * the assignment made above, which is used in the more common + * case when padding is not needed. + * + * If we're doing a partial put, the data we want are already + * in out_data.data; we just need to pad. + */ + if (F_ISSET(data, DB_DBT_PARTIAL)) { + if ((ret = __os_realloc( + env, re_len, &out_data->data)) != 0) + return (ret); + /* + * In the partial case, we have built the item into + * out_data already using __db_buildpartial. Just need + * to pad from the end of out_data, not from data->size. + */ + size = out_data->size; + } else { + if ((ret = __os_malloc( + env, re_len, &out_data->data)) != 0) + return (ret); + memcpy(out_data->data, data->data, size); + } + memset((u_int8_t *)out_data->data + size, re_pad, + re_len - size); + out_data->size = re_len; + } + + return (ret); +} + +/* + * __dbc_put_secondaries -- + * Insert the secondary keys, and validate the foreign key constraints. + */ +static inline int +__dbc_put_secondaries(dbc, + pkey, data, orig_data, s_count, s_keys_buf, put_statep) + DBC *dbc; + DBT *pkey, *data, *orig_data, *s_keys_buf; + int s_count; + u_int32_t *put_statep; +{ + DB *dbp, *sdbp; + DBC *fdbc, *sdbc; + DBT fdata, oldpkey, *skeyp, temppkey, tempskey, *tskeyp; + ENV *env; + int cmp, ret, rmw, t_ret; + u_int32_t nskey; + + dbp = dbc->dbp; + env = dbp->env; + fdbc = sdbc = NULL; + sdbp = NULL; + t_ret = 0; + rmw = FLD_ISSET(*put_statep, DBC_PUT_RMW) ? DB_RMW : 0; + + /* + * Loop through the secondaries. (Step 3.) + * + * Note that __db_s_first and __db_s_next will take care of + * thread-locking and refcounting issues. + */ + for (ret = __db_s_first(dbp, &sdbp), skeyp = s_keys_buf; + sdbp != NULL && ret == 0; + ret = __db_s_next(&sdbp, dbc->txn), ++skeyp) { + DB_ASSERT(env, skeyp - s_keys_buf < s_count); + /* + * Don't process this secondary if the key is immutable and we + * know that the old record exists. This optimization can't be + * used if we have not checked for the old record yet. + */ + if (FLD_ISSET(*put_statep, DBC_PUT_HAVEREC) && + !FLD_ISSET(*put_statep, DBC_PUT_NODEL) && + FLD_ISSET(sdbp->s_assoc_flags, DB_ASSOC_IMMUTABLE_KEY)) + continue; + + /* + * Call the callback for this secondary, to get the + * appropriate secondary key. + */ + if ((ret = sdbp->s_callback(sdbp, + pkey, data, skeyp)) != 0) { + /* Not indexing is equivalent to an empty key set. */ + if (ret == DB_DONOTINDEX) { + F_SET(skeyp, DB_DBT_MULTIPLE); + skeyp->size = 0; + ret = 0; + } else + goto err; + } + + if (sdbp->s_foreign != NULL && + (ret = __db_cursor_int(sdbp->s_foreign, + dbc->thread_info, dbc->txn, sdbp->s_foreign->type, + PGNO_INVALID, 0, dbc->locker, &fdbc)) != 0) + goto err; + + /* + * Mark the secondary key DBT(s) as set -- that is, the + * callback returned at least one secondary key. + * + * Also, if this secondary index is associated with a foreign + * database, check that the foreign db contains the key(s) to + * maintain referential integrity. Set flags in fdata to avoid + * mem copying, we just need to know existence. We need to do + * this check before setting DB_DBT_ISSET, otherwise __dbc_get + * will overwrite the flag values. + */ + if (F_ISSET(skeyp, DB_DBT_MULTIPLE)) { +#ifdef DIAGNOSTIC + __db_check_skeyset(sdbp, skeyp); +#endif + for (tskeyp = (DBT *)skeyp->data, nskey = skeyp->size; + nskey > 0; nskey--, tskeyp++) { + if (fdbc != NULL) { + memset(&fdata, 0, sizeof(DBT)); + F_SET(&fdata, + DB_DBT_PARTIAL | DB_DBT_USERMEM); + if ((ret = __dbc_get( + fdbc, tskeyp, &fdata, + DB_SET | rmw)) == DB_NOTFOUND || + ret == DB_KEYEMPTY) { + ret = DB_FOREIGN_CONFLICT; + break; + } + } + F_SET(tskeyp, DB_DBT_ISSET); + } + tskeyp = (DBT *)skeyp->data; + nskey = skeyp->size; + } else { + if (fdbc != NULL) { + memset(&fdata, 0, sizeof(DBT)); + F_SET(&fdata, DB_DBT_PARTIAL | DB_DBT_USERMEM); + if ((ret = __dbc_get(fdbc, skeyp, &fdata, + DB_SET | rmw)) == DB_NOTFOUND || + ret == DB_KEYEMPTY) + ret = DB_FOREIGN_CONFLICT; + } + F_SET(skeyp, DB_DBT_ISSET); + tskeyp = skeyp; + nskey = 1; + } + if (fdbc != NULL && (t_ret = __dbc_close(fdbc)) != 0 && + ret == 0) + ret = t_ret; + fdbc = NULL; + if (ret != 0) + goto err; + + /* + * If we have the old record, we can generate and remove any + * old secondary key(s) now. We can also skip the secondary + * put if there is no change. + */ + if (FLD_ISSET(*put_statep, DBC_PUT_HAVEREC)) { + if ((ret = __dbc_del_oldskey(sdbp, dbc, + skeyp, pkey, orig_data)) == DB_KEYEXIST) + continue; + else if (ret != 0) + goto err; + } + if (nskey == 0) + continue; + + /* + * Open a cursor in this secondary. + * + * Use the same locker ID as our primary cursor, so that + * we're guaranteed that the locks don't conflict (e.g. in CDB + * or if we're subdatabases that share and want to lock a + * metadata page). + */ + if ((ret = __db_cursor_int(sdbp, dbc->thread_info, dbc->txn, + sdbp->type, PGNO_INVALID, 0, dbc->locker, &sdbc)) != 0) + goto err; + + /* + * If we're in CDB, updates will fail since the new cursor + * isn't a writer. However, we hold the WRITE lock in the + * primary and will for as long as our new cursor lasts, + * and the primary and secondary share a lock file ID, + * so it's safe to consider this a WRITER. The close + * routine won't try to put anything because we don't + * really have a lock. + */ + if (CDB_LOCKING(env)) { + DB_ASSERT(env, sdbc->mylock.off == LOCK_INVALID); + F_SET(sdbc, DBC_WRITER); + } + + /* + * Swap the primary key to the byte order of this secondary, if + * necessary. By doing this now, we can compare directly + * against the data already in the secondary without having to + * swap it after reading. + */ + SWAP_IF_NEEDED(sdbp, pkey); + + for (; nskey > 0 && ret == 0; nskey--, tskeyp++) { + /* Skip this key if it is already in the database. */ + if (!F_ISSET(tskeyp, DB_DBT_ISSET)) + continue; + + /* + * There are three cases here-- + * 1) The secondary supports sorted duplicates. + * If we attempt to put a secondary/primary pair + * that already exists, that's a duplicate + * duplicate, and c_put will return DB_KEYEXIST + * (see __db_duperr). This will leave us with + * exactly one copy of the secondary/primary pair, + * and this is just right--we'll avoid deleting it + * later, as the old and new secondaries will + * match (since the old secondary is the dup dup + * that's already there). + * 2) The secondary supports duplicates, but they're not + * sorted. We need to avoid putting a duplicate + * duplicate, because the matching old and new + * secondaries will prevent us from deleting + * anything and we'll wind up with two secondary + * records that point to the same primary key. Do + * a c_get(DB_GET_BOTH); only do the put if the + * secondary doesn't exist. + * 3) The secondary doesn't support duplicates at all. + * In this case, secondary keys must be unique; + * if another primary key already exists for this + * secondary key, we have to either overwrite it + * or not put this one, and in either case we've + * corrupted the secondary index. Do a + * c_get(DB_SET). If the secondary/primary pair + * already exists, do nothing; if the secondary + * exists with a different primary, return an + * error; and if the secondary does not exist, + * put it. + */ + if (!F_ISSET(sdbp, DB_AM_DUP)) { + /* Case 3. */ + memset(&oldpkey, 0, sizeof(DBT)); + F_SET(&oldpkey, DB_DBT_MALLOC); + ret = __dbc_get(sdbc, + tskeyp, &oldpkey, rmw | DB_SET); + if (ret == 0) { + cmp = __bam_defcmp(sdbp, + &oldpkey, pkey); + __os_ufree(env, oldpkey.data); + /* + * If the secondary key is unchanged, + * skip the put and go on to the next + * one. + */ + if (cmp == 0) + continue; + + __db_errx(env, DB_STR("0695", + "Put results in a non-unique secondary key in an " + "index not configured to support duplicates")); + ret = EINVAL; + } + if (ret != DB_NOTFOUND && ret != DB_KEYEMPTY) + break; + } else if (!F_ISSET(sdbp, DB_AM_DUPSORT)) { + /* Case 2. */ + DB_INIT_DBT(tempskey, + tskeyp->data, tskeyp->size); + DB_INIT_DBT(temppkey, + pkey->data, pkey->size); + ret = __dbc_get(sdbc, &tempskey, &temppkey, + rmw | DB_GET_BOTH); + if (ret != DB_NOTFOUND && ret != DB_KEYEMPTY) + break; + } + + ret = __dbc_put(sdbc, tskeyp, pkey, + DB_UPDATE_SECONDARY); + + /* + * We don't know yet whether this was a put-overwrite + * that in fact changed nothing. If it was, we may get + * DB_KEYEXIST. This is not an error. + */ + if (ret == DB_KEYEXIST) + ret = 0; + } + + /* Make sure the primary key is back in native byte-order. */ + SWAP_IF_NEEDED(sdbp, pkey); + + if ((t_ret = __dbc_close(sdbc)) != 0 && ret == 0) + ret = t_ret; + + if (ret != 0) + goto err; + + /* + * Mark that we have a key for this secondary so we can check + * it later before deleting the old one. We can't set it + * earlier or it would be cleared in the calls above. + */ + F_SET(skeyp, DB_DBT_ISSET); + } +err: if (sdbp != NULL && + (t_ret = __db_s_done(sdbp, dbc->txn)) != 0 && ret == 0) + ret = t_ret; + COMPQUIET(s_count, 0); + return (ret); +} + +static int +__dbc_put_primary(dbc, key, data, flags) + DBC *dbc; + DBT *key, *data; + u_int32_t flags; +{ + DB *dbp, *sdbp; + DBC *dbc_n, *pdbc; + DBT oldkey, olddata, newdata; + DBT *all_skeys, *skeyp, *tskeyp; + ENV *env; + int ret, t_ret, s_count; + u_int32_t nskey, put_state, rmw; + + dbp = dbc->dbp; + env = dbp->env; + t_ret = 0; + put_state = 0; + sdbp = NULL; + pdbc = dbc_n = NULL; + all_skeys = NULL; + memset(&newdata, 0, sizeof(DBT)); + memset(&olddata, 0, sizeof(DBT)); + + /* + * We do multiple cursor operations in some cases and subsequently + * access the data DBT information. Set DB_DBT_MALLOC so we don't risk + * modification of the data between our uses of it. + */ + F_SET(&olddata, DB_DBT_MALLOC); + + /* + * We have at least one secondary which we may need to update. + * + * There is a rather vile locking issue here. Secondary gets + * will always involve acquiring a read lock in the secondary, + * then acquiring a read lock in the primary. Ideally, we + * would likewise perform puts by updating all the secondaries + * first, then doing the actual put in the primary, to avoid + * deadlock (since having multiple threads doing secondary + * gets and puts simultaneously is probably a common case). + * + * However, if this put is a put-overwrite--and we have no way to + * tell in advance whether it will be--we may need to delete + * an outdated secondary key. In order to find that old + * secondary key, we need to get the record we're overwriting, + * before we overwrite it. + * + * (XXX: It would be nice to avoid this extra get, and have the + * underlying put routines somehow pass us the old record + * since they need to traverse the tree anyway. I'm saving + * this optimization for later, as it's a lot of work, and it + * would be hard to fit into this locking paradigm anyway.) + * + * The simple thing to do would be to go get the old record before + * we do anything else. Unfortunately, though, doing so would + * violate our "secondary, then primary" lock acquisition + * ordering--even in the common case where no old primary record + * exists, we'll still acquire and keep a lock on the page where + * we're about to do the primary insert. + * + * To get around this, we do the following gyrations, which + * hopefully solve this problem in the common case: + * + * 1) If this is a c_put(DB_CURRENT), go ahead and get the + * old record. We already hold the lock on this page in + * the primary, so no harm done, and we'll need the primary + * key (which we weren't passed in this case) to do any + * secondary puts anyway. + * If this is a put(DB_APPEND), then we need to insert the item, + * so that we can know the key value. So go ahead and insert. In + * the case of a put(DB_APPEND) without secondaries it is + * implemented in the __db_put method as an optimization. + * + * 2) If we're doing a partial put, we need to perform the + * get on the primary key right away, since we don't have + * the whole datum that the secondary key is based on. + * We may also need to pad out the record if the primary + * has a fixed record length. + * + * 3) Loop through the secondary indices, putting into each a + * new secondary key that corresponds to the new record. + * + * 4) If we haven't done so in (1) or (2), get the old primary + * key/data pair. If one does not exist--the common case--we're + * done with secondary indices, and can go straight on to the + * primary put. + * + * 5) If we do have an old primary key/data pair, however, we need + * to loop through all the secondaries a second time and delete + * the old secondary in each. + */ + s_count = __db_s_count(dbp); + if ((ret = __os_calloc(env, + (u_int)s_count, sizeof(DBT), &all_skeys)) != 0) + goto err; + + /* + * Primary indices can't have duplicates, so only DB_APPEND, + * DB_CURRENT, DB_KEYFIRST, and DB_KEYLAST make any sense. Other flags + * should have been caught by the checking routine, but + * add a sprinkling of paranoia. + */ + DB_ASSERT(env, flags == DB_APPEND || flags == DB_CURRENT || + flags == DB_KEYFIRST || flags == DB_KEYLAST || + flags == DB_NOOVERWRITE || flags == DB_OVERWRITE_DUP); + + /* + * We'll want to use DB_RMW in a few places, but it's only legal + * when locking is on. + */ + rmw = STD_LOCKING(dbc) ? DB_RMW : 0; + if (rmw) + FLD_SET(put_state, DBC_PUT_RMW); + + /* Resolve the primary key if required (Step 1). */ + if (flags == DB_CURRENT) { + if ((ret = __dbc_put_resolve_key(dbc, + &oldkey, &olddata, &put_state, flags)) != 0) + goto err; + key = &oldkey; + } else if (flags == DB_APPEND) { + if ((ret = __dbc_put_append(dbc, + key, data, &put_state, flags)) != 0) + goto err; + } + + /* + * PUT_NOOVERWRITE with secondaries is a troublesome case. We need + * to check that the insert will work prior to making any changes + * to secondaries. Try to work within the locking constraints outlined + * above. + * + * This is DB->put (DB_NOOVERWRITE). DBC->put(DB_NODUPDATA) is not + * relevant since it is only valid on DBs that support duplicates, + * which primaries with secondaries can't have. + */ + if (flags == DB_NOOVERWRITE) { + /* Don't bother retrieving the data. */ + F_SET(key, DB_DBT_ISSET); + olddata.dlen = 0; + olddata.flags = DB_DBT_PARTIAL | DB_DBT_USERMEM; + ret = __dbc_get(dbc, key, &olddata, DB_SET); + if (ret == 0) { + ret = DB_KEYEXIST; + goto done; + } else if (ret != DB_NOTFOUND && ret != DB_KEYEMPTY) + goto err; + } + + /* + * Check for partial puts using DB_DBT_PARTIAL (Step 2). + */ + if (F_ISSET(data, DB_DBT_PARTIAL)) { + if ((ret = __dbc_put_partial(dbc, + key, data, &olddata, &newdata, &put_state, flags)) != 0) + goto err; + } else { + newdata = *data; + } + + /* + * Check for partial puts, with fixed length record databases (Step 2). + */ + if ((dbp->type == DB_RECNO && F_ISSET(dbp, DB_AM_FIXEDLEN)) || + (dbp->type == DB_QUEUE)) { + if ((ret = __dbc_put_fixed_len(dbc, data, &newdata)) != 0) + goto err; + } + + /* Validate any foreign databases, and update secondaries. (Step 3). */ + if ((ret = __dbc_put_secondaries(dbc, key, &newdata, + &olddata, s_count, all_skeys, &put_state)) + != 0) + goto err; + /* + * If we've already got the old primary key/data pair, the secondary + * updates are already done. + */ + if (FLD_ISSET(put_state, DBC_PUT_HAVEREC)) + goto done; + + /* + * If still necessary, go get the old primary key/data. (Step 4.) + * + * See the comments in step 2. This is real familiar. + */ + if ((ret = __dbc_idup(dbc, &pdbc, 0)) != 0) + goto err; + DB_ASSERT(env, flags != DB_CURRENT); + F_SET(key, DB_DBT_ISSET); + ret = __dbc_get(pdbc, key, &olddata, rmw | DB_SET); + if (ret == DB_KEYEMPTY || ret == DB_NOTFOUND) { + FLD_SET(put_state, DBC_PUT_NODEL); + ret = 0; + } + if ((t_ret = __dbc_close(pdbc)) != 0 && ret == 0) + ret = t_ret; + if (ret != 0) + goto err; + + /* + * Check whether we do in fact have an old record we may need to + * delete. (Step 5). + */ + if (FLD_ISSET(put_state, DBC_PUT_NODEL)) + goto done; + + for (ret = __db_s_first(dbp, &sdbp), skeyp = all_skeys; + sdbp != NULL && ret == 0; + ret = __db_s_next(&sdbp, dbc->txn), skeyp++) { + DB_ASSERT(env, skeyp - all_skeys < s_count); + /* + * Don't process this secondary if the key is immutable. We + * know that the old record exists, so this optimization can + * always be used. + */ + if (FLD_ISSET(sdbp->s_assoc_flags, DB_ASSOC_IMMUTABLE_KEY)) + continue; + + if ((ret = __dbc_del_oldskey(sdbp, dbc, + skeyp, key, &olddata)) != 0 && ret != DB_KEYEXIST) + goto err; + } + if (ret != 0) + goto err; + +done: +err: + if ((t_ret = __dbc_cleanup(dbc, dbc_n, ret)) != 0 && ret == 0) + ret = t_ret; + + /* If newdata or olddata were used, free their buffers. */ + if (newdata.data != NULL && newdata.data != data->data) + __os_free(env, newdata.data); + if (olddata.data != NULL) + __os_ufree(env, olddata.data); + + CDB_LOCKING_DONE(env, dbc); + + if (sdbp != NULL && + (t_ret = __db_s_done(sdbp, dbc->txn)) != 0 && ret == 0) + ret = t_ret; + + if (all_skeys != NULL) { + for (skeyp = all_skeys; skeyp - all_skeys < s_count; skeyp++) { + if (F_ISSET(skeyp, DB_DBT_MULTIPLE)) { + for (nskey = skeyp->size, + tskeyp = (DBT *)skeyp->data; + nskey > 0; + nskey--, tskeyp++) + FREE_IF_NEEDED(env, tskeyp); + } + FREE_IF_NEEDED(env, skeyp); + } + __os_free(env, all_skeys); + } + return (ret); +} + +/* + * __dbc_put -- + * Put using a cursor. + * + * PUBLIC: int __dbc_put __P((DBC *, DBT *, DBT *, u_int32_t)); + */ +int +__dbc_put(dbc, key, data, flags) + DBC *dbc; + DBT *key, *data; + u_int32_t flags; +{ + DB *dbp; + int ret; + + dbp = dbc->dbp; + ret = 0; + F_CLR(dbc, DBC_ERROR); + + /* + * Putting to secondary indices is forbidden; when we need to + * internally update one, we're called with a private flag, + * DB_UPDATE_SECONDARY, which does the right thing but won't return an + * error during flag checking. + * + * As a convenience, many places that want the default DB_KEYLAST + * behavior call DBC->put with flags == 0. Protect lower-level code + * here by translating that. + * + * Lastly, the DB_OVERWRITE_DUP flag is equivalent to DB_KEYLAST unless + * there are sorted duplicates. Limit the number of places that need + * to test for it explicitly. + */ + if (flags == DB_UPDATE_SECONDARY || flags == 0 || + (flags == DB_OVERWRITE_DUP && !F_ISSET(dbp, DB_AM_DUPSORT))) + flags = DB_KEYLAST; + + CDB_LOCKING_INIT(dbc->env, dbc); + + PERFMON6(env, db, put, dbp->fname, dbp->dname, + dbc->txn == NULL ? 0 : dbc->txn->txnid, key, data, flags); + /* + * Check to see if we are a primary and have secondary indices. + * If we are not, we save ourselves a good bit of trouble and + * just skip to the "normal" put. + */ + if (DB_IS_PRIMARY(dbp) && + ((ret = __dbc_put_primary(dbc, key, data, flags)) != 0)) + return (ret); + + /* + * If this is an append operation, the insert was done prior to the + * secondary updates, so we are finished. + */ + if (flags == DB_APPEND) + return (ret); + +#ifdef HAVE_COMPRESSION + if (DB_IS_COMPRESSED(dbp)) + return (__bamc_compress_put(dbc, key, data, flags)); +#endif + + return (__dbc_iput(dbc, key, data, flags)); +} + +/* + * __dbc_iput -- + * Implementation of put using a cursor. + * + * PUBLIC: int __dbc_iput __P((DBC *, DBT *, DBT *, u_int32_t)); + */ +int +__dbc_iput(dbc, key, data, flags) + DBC *dbc; + DBT *key, *data; + u_int32_t flags; +{ + DBC *dbc_n, *oldopd, *opd; + db_pgno_t pgno; + int ret, t_ret; + u_int32_t tmp_flags; + + /* + * Cursor Cleanup Note: + * All of the cursors passed to the underlying access methods by this + * routine are duplicated cursors. On return, any referenced pages + * will be discarded, and, if the cursor is not intended to be used + * again, the close function will be called. So, pages/locks that + * the cursor references do not need to be resolved by the underlying + * functions. + */ + dbc_n = NULL; + ret = t_ret = 0; + + /* + * If we have an off-page duplicates cursor, and the operation applies + * to it, perform the operation. Duplicate the cursor and call the + * underlying function. + * + * Off-page duplicate trees are locked in the primary tree, that is, + * we acquire a write lock in the primary tree and no locks in the + * off-page dup tree. If the put operation is done in an off-page + * duplicate tree, call the primary cursor's upgrade routine first. + */ + if (dbc->internal->opd != NULL && + (flags == DB_AFTER || flags == DB_BEFORE || flags == DB_CURRENT)) { + /* + * A special case for hash off-page duplicates. Hash doesn't + * support (and is documented not to support) put operations + * relative to a cursor which references an already deleted + * item. For consistency, apply the same criteria to off-page + * duplicates as well. + */ + if (dbc->dbtype == DB_HASH && F_ISSET( + ((BTREE_CURSOR *)(dbc->internal->opd->internal)), + C_DELETED)) { + ret = DB_NOTFOUND; + goto err; + } + + if ((ret = dbc->am_writelock(dbc)) != 0 || + (ret = __dbc_dup(dbc, &dbc_n, DB_POSITION)) != 0) + goto err; + opd = dbc_n->internal->opd; + if ((ret = opd->am_put( + opd, key, data, flags, NULL)) != 0) + goto err; + goto done; + } + + /* + * Perform an operation on the main cursor. Duplicate the cursor, + * and call the underlying function. + */ + if (flags == DB_AFTER || flags == DB_BEFORE || flags == DB_CURRENT) + tmp_flags = DB_POSITION; + else + tmp_flags = 0; + + /* + * If this cursor is going to be closed immediately, we don't + * need to take precautions to clean it up on error. + */ + if (F_ISSET(dbc, DBC_TRANSIENT | DBC_PARTITIONED)) + dbc_n = dbc; + else if ((ret = __dbc_idup(dbc, &dbc_n, tmp_flags)) != 0) + goto err; + + pgno = PGNO_INVALID; + if ((ret = dbc_n->am_put(dbc_n, key, data, flags, &pgno)) != 0) + goto err; + + /* + * We may be referencing a new off-page duplicates tree. Acquire + * a new cursor and call the underlying function. + */ + if (pgno != PGNO_INVALID) { + oldopd = dbc_n->internal->opd; + if ((ret = __dbc_newopd(dbc, pgno, oldopd, &opd)) != 0) { + dbc_n->internal->opd = opd; + goto err; + } + + dbc_n->internal->opd = opd; + opd->internal->pdbc = dbc_n; + + if (flags == DB_NOOVERWRITE) + flags = DB_KEYLAST; + if ((ret = opd->am_put( + opd, key, data, flags, NULL)) != 0) + goto err; + } + +done: +err: /* Cleanup and cursor resolution. */ + if (dbc_n != NULL && !DB_RETOK_DBCPUT(ret)) + F_SET(dbc_n, DBC_ERROR); + if ((t_ret = __dbc_cleanup(dbc, dbc_n, ret)) != 0 && ret == 0) + ret = t_ret; + return (ret); +} + +/* + * __dbc_del_oldskey -- + * Delete an old secondary key, if necessary. + * Returns DB_KEYEXIST if the new and old keys match.. + */ +static int +__dbc_del_oldskey(sdbp, dbc, skey, pkey, olddata) + DB *sdbp; + DBC *dbc; + DBT *skey, *pkey, *olddata; +{ + DB *dbp; + DBC *sdbc; + DBT *toldskeyp, *tskeyp; + DBT oldskey, temppkey, tempskey; + ENV *env; + int ret, t_ret; + u_int32_t i, noldskey, nsame, nskey, rmw; + + sdbc = NULL; + dbp = sdbp->s_primary; + env = dbp->env; + nsame = 0; + rmw = STD_LOCKING(dbc) ? DB_RMW : 0; + + /* + * Get the old secondary key. + */ + memset(&oldskey, 0, sizeof(DBT)); + if ((ret = sdbp->s_callback(sdbp, pkey, olddata, &oldskey)) != 0) { + if (ret == DB_DONOTINDEX || + (F_ISSET(&oldskey, DB_DBT_MULTIPLE) && oldskey.size == 0)) + /* There's no old key to delete. */ + ret = 0; + return (ret); + } + + if (F_ISSET(&oldskey, DB_DBT_MULTIPLE)) { +#ifdef DIAGNOSTIC + __db_check_skeyset(sdbp, &oldskey); +#endif + toldskeyp = (DBT *)oldskey.data; + noldskey = oldskey.size; + } else { + toldskeyp = &oldskey; + noldskey = 1; + } + + if (F_ISSET(skey, DB_DBT_MULTIPLE)) { + nskey = skey->size; + skey = (DBT *)skey->data; + } else + nskey = F_ISSET(skey, DB_DBT_ISSET) ? 1 : 0; + + for (; noldskey > 0 && ret == 0; noldskey--, toldskeyp++) { + /* + * Check whether this old secondary key is also a new key + * before we delete it. Note that bt_compare is (and must be) + * set no matter what access method we're in. + */ + for (i = 0, tskeyp = skey; i < nskey; i++, tskeyp++) + if (((BTREE *)sdbp->bt_internal)->bt_compare(sdbp, + toldskeyp, tskeyp) == 0) { + nsame++; + F_CLR(tskeyp, DB_DBT_ISSET); + break; + } + + if (i < nskey) { + FREE_IF_NEEDED(env, toldskeyp); + continue; + } + + if (sdbc == NULL) { + if ((ret = __db_cursor_int(sdbp, + dbc->thread_info, dbc->txn, sdbp->type, + PGNO_INVALID, 0, dbc->locker, &sdbc)) != 0) + goto err; + if (CDB_LOCKING(env)) { + DB_ASSERT(env, + sdbc->mylock.off == LOCK_INVALID); + F_SET(sdbc, DBC_WRITER); + } + } + + /* + * Don't let c_get(DB_GET_BOTH) stomp on our data. Use + * temporary DBTs instead. + */ + SWAP_IF_NEEDED(sdbp, pkey); + DB_INIT_DBT(temppkey, pkey->data, pkey->size); + DB_INIT_DBT(tempskey, toldskeyp->data, toldskeyp->size); + if ((ret = __dbc_get(sdbc, + &tempskey, &temppkey, rmw | DB_GET_BOTH)) == 0) + ret = __dbc_del(sdbc, DB_UPDATE_SECONDARY); + else if (ret == DB_NOTFOUND) + ret = __db_secondary_corrupt(dbp); + SWAP_IF_NEEDED(sdbp, pkey); + FREE_IF_NEEDED(env, toldskeyp); + } + +err: for (; noldskey > 0; noldskey--, toldskeyp++) + FREE_IF_NEEDED(env, toldskeyp); + FREE_IF_NEEDED(env, &oldskey); + if (sdbc != NULL && (t_ret = __dbc_close(sdbc)) != 0 && ret == 0) + ret = t_ret; + if (ret == 0 && nsame == nskey) + return (DB_KEYEXIST); + return (ret); +} + +/* + * __db_duperr() + * Error message: we don't currently support sorted duplicate duplicates. + * PUBLIC: int __db_duperr __P((DB *, u_int32_t)); + */ +int +__db_duperr(dbp, flags) + DB *dbp; + u_int32_t flags; +{ + /* + * If we run into this error while updating a secondary index, + * don't yell--there's no clean way to pass DB_NODUPDATA in along + * with DB_UPDATE_SECONDARY, but we may run into this problem + * in a normal, non-error course of events. + * + * !!! + * If and when we ever permit duplicate duplicates in sorted-dup + * databases, we need to either change the secondary index code + * to check for dup dups, or we need to maintain the implicit + * "DB_NODUPDATA" behavior for databases with DB_AM_SECONDARY set. + */ + if (flags != DB_NODUPDATA && !F_ISSET(dbp, DB_AM_SECONDARY)) + __db_errx(dbp->env, DB_STR("0696", + "Duplicate data items are not supported with sorted data")); + return (DB_KEYEXIST); +} + +/* + * __dbc_cleanup -- + * Clean up duplicate cursors. + * + * PUBLIC: int __dbc_cleanup __P((DBC *, DBC *, int)); + */ +int +__dbc_cleanup(dbc, dbc_n, failed) + DBC *dbc, *dbc_n; + int failed; +{ + DB *dbp; + DBC *opd; + DBC_INTERNAL *internal; + DB_MPOOLFILE *mpf; + int ret, t_ret; + + if (F_ISSET(dbc, DBC_OPD)) + LOCK_CHECK_OFF(dbc->thread_info); + + dbp = dbc->dbp; + mpf = dbp->mpf; + internal = dbc->internal; + ret = 0; + + /* Discard any pages we're holding. */ + if (internal->page != NULL) { + if ((t_ret = __memp_fput(mpf, dbc->thread_info, + internal->page, dbc->priority)) != 0 && ret == 0) + ret = t_ret; + internal->page = NULL; + } + opd = internal->opd; + if (opd != NULL && opd->internal->page != NULL) { + if ((t_ret = __memp_fput(mpf, dbc->thread_info, + opd->internal->page, dbc->priority)) != 0 && ret == 0) + ret = t_ret; + opd->internal->page = NULL; + } + + /* + * If dbc_n is NULL, there's no internal cursor swapping to be done + * and no dbc_n to close--we probably did the entire operation on an + * offpage duplicate cursor. Just return. + * + * If dbc and dbc_n are the same, we're either inside a DB->{put/get} + * operation, and as an optimization we performed the operation on + * the main cursor rather than on a duplicated one, or we're in a + * bulk get that can't have moved the cursor (DB_MULTIPLE with the + * initial c_get operation on an off-page dup cursor). Just + * return--either we know we didn't move the cursor, or we're going + * to close it before we return to application code, so we're sure + * not to visibly violate the "cursor stays put on error" rule. + */ + if (dbc_n == NULL || dbc == dbc_n) + goto done; + + if (dbc_n->internal->page != NULL) { + if ((t_ret = __memp_fput(mpf, dbc->thread_info, + dbc_n->internal->page, dbc->priority)) != 0 && ret == 0) + ret = t_ret; + dbc_n->internal->page = NULL; + } + opd = dbc_n->internal->opd; + if (opd != NULL && opd->internal->page != NULL) { + if ((t_ret = __memp_fput(mpf, dbc->thread_info, + opd->internal->page, dbc->priority)) != 0 && ret == 0) + ret = t_ret; + opd->internal->page = NULL; + } + + /* + * If we didn't fail before entering this routine or just now when + * freeing pages, swap the interesting contents of the old and new + * cursors. + */ + if (!failed && ret == 0) { + if (opd != NULL) + opd->internal->pdbc = dbc; + if (internal->opd != NULL) + internal->opd->internal->pdbc = dbc_n; + dbc->internal = dbc_n->internal; + dbc_n->internal = internal; + } + + /* + * Close the cursor we don't care about anymore. The close can fail, + * but we only expect DB_LOCK_DEADLOCK failures. This violates our + * "the cursor is unchanged on error" semantics, but since all you can + * do with a DB_LOCK_DEADLOCK failure is close the cursor, I believe + * that's OK. + * + * XXX + * There's no way to recover from failure to close the old cursor. + * All we can do is move to the new position and return an error. + * + * XXX + * We might want to consider adding a flag to the cursor, so that any + * subsequent operations other than close just return an error? + */ + if ((t_ret = __dbc_close(dbc_n)) != 0 && ret == 0) + ret = t_ret; + + /* + * If this was an update that is supporting dirty reads + * then we may have just swapped our read for a write lock + * which is held by the surviving cursor. We need + * to explicitly downgrade this lock. The closed cursor + * may only have had a read lock. + */ + if (ret == 0 && failed == 0 && F_ISSET(dbp, DB_AM_READ_UNCOMMITTED) && + dbc->internal->lock_mode == DB_LOCK_WRITE && + (ret = __TLPUT(dbc, dbc->internal->lock)) == 0) + dbc->internal->lock_mode = DB_LOCK_WWRITE; + +done: + if (F_ISSET(dbc, DBC_OPD)) + LOCK_CHECK_ON(dbc->thread_info); + + return (ret); +} + +/* + * __dbc_secondary_get_pp -- + * This wrapper function for DBC->pget() is the DBC->get() function + * for a secondary index cursor. + * + * PUBLIC: int __dbc_secondary_get_pp __P((DBC *, DBT *, DBT *, u_int32_t)); + */ +int +__dbc_secondary_get_pp(dbc, skey, data, flags) + DBC *dbc; + DBT *skey, *data; + u_int32_t flags; +{ + DB_ASSERT(dbc->env, F_ISSET(dbc->dbp, DB_AM_SECONDARY)); + return (__dbc_pget_pp(dbc, skey, NULL, data, flags)); +} + +/* + * __dbc_pget -- + * Get a primary key/data pair through a secondary index. + * + * PUBLIC: int __dbc_pget __P((DBC *, DBT *, DBT *, DBT *, u_int32_t)); + */ +int +__dbc_pget(dbc, skey, pkey, data, flags) + DBC *dbc; + DBT *skey, *pkey, *data; + u_int32_t flags; +{ + DB *pdbp, *sdbp; + DBC *dbc_n, *pdbc; + DBT nullpkey, *save_data; + u_int32_t save_pkey_flags, tmp_flags, tmp_read_locking, tmp_rmw; + int pkeymalloc, ret, t_ret; + + sdbp = dbc->dbp; + pdbp = sdbp->s_primary; + dbc_n = NULL; + save_data = NULL; + pkeymalloc = t_ret = 0; + + /* + * The challenging part of this function is getting the behavior + * right for all the various permutations of DBT flags. The + * next several blocks handle the various cases we need to + * deal with specially. + */ + + /* + * We may be called with a NULL pkey argument, if we've been + * wrapped by a 2-DBT get call. If so, we need to use our + * own DBT. + */ + if (pkey == NULL) { + memset(&nullpkey, 0, sizeof(DBT)); + pkey = &nullpkey; + } + + /* Clear OR'd in additional bits so we can check for flag equality. */ + tmp_rmw = LF_ISSET(DB_RMW); + LF_CLR(DB_RMW); + + SET_READ_LOCKING_FLAGS(dbc, tmp_read_locking); + /* + * DB_GET_RECNO is a special case, because we're interested not in + * the primary key/data pair, but rather in the primary's record + * number. + */ + if (flags == DB_GET_RECNO) { + if (tmp_rmw) + F_SET(dbc, DBC_RMW); + F_SET(dbc, tmp_read_locking); + ret = __dbc_pget_recno(dbc, pkey, data, flags); + if (tmp_rmw) + F_CLR(dbc, DBC_RMW); + /* Clear the temp flags, but leave WAS_READ_COMMITTED. */ + F_CLR(dbc, tmp_read_locking & ~DBC_WAS_READ_COMMITTED); + return (ret); + } + + /* + * If the DBTs we've been passed don't have any of the + * user-specified memory management flags set, we want to make sure + * we return values using the DBTs dbc->rskey, dbc->rkey, and + * dbc->rdata, respectively. + * + * There are two tricky aspects to this: first, we need to pass + * skey and pkey *in* to the initial c_get on the secondary key, + * since either or both may be looked at by it (depending on the + * get flag). Second, we must not use a normal DB->get call + * on the secondary, even though that's what we want to accomplish, + * because the DB handle may be free-threaded. Instead, + * we open a cursor, then take steps to ensure that we actually use + * the rkey/rdata from the *secondary* cursor. + * + * We accomplish all this by passing in the DBTs we started out + * with to the c_get, but swapping the contents of rskey and rkey, + * respectively, into rkey and rdata; __db_ret will treat them like + * the normal key/data pair in a c_get call, and will realloc them as + * need be (this is "step 1"). Then, for "step 2", we swap back + * rskey/rkey/rdata to normal, and do a get on the primary with the + * secondary dbc appointed as the owner of the returned-data memory. + * + * Note that in step 2, we copy the flags field in case we need to + * pass down a DB_DBT_PARTIAL or other flag that is compatible with + * letting DB do the memory management. + */ + + /* + * It is correct, though slightly sick, to attempt a partial get of a + * primary key. However, if we do so here, we'll never find the + * primary record; clear the DB_DBT_PARTIAL field of pkey just for the + * duration of the next call. + */ + save_pkey_flags = pkey->flags; + F_CLR(pkey, DB_DBT_PARTIAL); + + /* + * Now we can go ahead with the meat of this call. First, get the + * primary key from the secondary index. (What exactly we get depends + * on the flags, but the underlying cursor get will take care of the + * dirty work.) Duplicate the cursor, in case the later get on the + * primary fails. + */ + switch (flags) { + case DB_CURRENT: + case DB_GET_BOTHC: + case DB_NEXT: + case DB_NEXT_DUP: + case DB_NEXT_NODUP: + case DB_PREV: + case DB_PREV_DUP: + case DB_PREV_NODUP: + tmp_flags = DB_POSITION; + break; + default: + tmp_flags = 0; + break; + } + + if (dbc->internal->opd != NULL || + F_ISSET(dbc, DBC_PARTITIONED | DBC_TRANSIENT)) { + dbc_n = dbc; + save_data = dbc_n->rdata; + } else { + if ((ret = __dbc_dup(dbc, &dbc_n, tmp_flags)) != 0) + return (ret); + F_SET(dbc_n, DBC_TRANSIENT); + } + dbc_n->rdata = dbc->rkey; + dbc_n->rkey = dbc->rskey; + + if (tmp_rmw) + F_SET(dbc_n, DBC_RMW); + F_SET(dbc_n, tmp_read_locking); + + /* + * If we've been handed a primary key, it will be in native byte order, + * so we need to swap it before reading from the secondary. + */ + if (flags == DB_GET_BOTH || flags == DB_GET_BOTHC || + flags == DB_GET_BOTH_RANGE) + SWAP_IF_NEEDED(sdbp, pkey); + +retry: /* Step 1. */ + ret = __dbc_get(dbc_n, skey, pkey, flags); + /* Restore pkey's flags in case we stomped the PARTIAL flag. */ + pkey->flags = save_pkey_flags; + + /* + * We need to swap the primary key to native byte order if we read it + * successfully, or if we swapped it on entry above. We can't return + * with the application's data modified. + */ + if (ret == 0 || flags == DB_GET_BOTH || flags == DB_GET_BOTHC || + flags == DB_GET_BOTH_RANGE) + SWAP_IF_NEEDED(sdbp, pkey); + + if (ret != 0) + goto err; + + /* + * Now we're ready for "step 2". If either or both of pkey and data do + * not have memory management flags set--that is, if DB is managing + * their memory--we need to swap around the rkey/rdata structures so + * that we don't wind up trying to use memory managed by the primary + * database cursor, which we'll close before we return. + * + * !!! + * If you're carefully following the bouncing ball, you'll note that in + * the DB-managed case, the buffer hanging off of pkey is the same as + * dbc->rkey->data. This is just fine; we may well realloc and stomp + * on it when we return, if we're doing a DB_GET_BOTH and need to + * return a different partial or key (depending on the comparison + * function), but this is safe. + * + * !!! + * We need to use __db_cursor_int here rather than simply calling + * pdbp->cursor, because otherwise, if we're in CDB, we'll allocate a + * new locker ID and leave ourselves open to deadlocks. (Even though + * we're only acquiring read locks, we'll still block if there are any + * waiters.) + */ + if ((ret = __db_cursor_int(pdbp, dbc->thread_info, + dbc->txn, pdbp->type, PGNO_INVALID, 0, dbc->locker, &pdbc)) != 0) + goto err; + + F_SET(pdbc, tmp_read_locking | + F_ISSET(dbc, DBC_READ_UNCOMMITTED | DBC_READ_COMMITTED | DBC_RMW)); + + /* + * We're about to use pkey a second time. If DB_DBT_MALLOC is set on + * it, we'll leak the memory we allocated the first time. Thus, set + * DB_DBT_REALLOC instead so that we reuse that memory instead of + * leaking it. + * + * Alternatively, if the application is handling copying for pkey, we + * need to take a copy now. The copy will be freed on exit from + * __dbc_pget_pp (and we must be coming through there if DB_DBT_USERCOPY + * is set). In the case of DB_GET_BOTH_RANGE, the pkey supplied by + * the application has already been copied in but the value may have + * changed in the search. In that case, free the original copy and get + * a new one. + * + * !!! + * This assumes that the user must always specify a compatible realloc + * function if a malloc function is specified. I think this is a + * reasonable requirement. + */ + if (F_ISSET(pkey, DB_DBT_MALLOC)) { + F_CLR(pkey, DB_DBT_MALLOC); + F_SET(pkey, DB_DBT_REALLOC); + pkeymalloc = 1; + } else if (F_ISSET(pkey, DB_DBT_USERCOPY)) { + if (flags == DB_GET_BOTH_RANGE) + __dbt_userfree(sdbp->env, NULL, pkey, NULL); + if ((ret = __dbt_usercopy(sdbp->env, pkey)) != 0) + goto err; + } + + /* + * Do the actual get. Set DBC_TRANSIENT since we don't care about + * preserving the position on error, and it's faster. SET_RET_MEM so + * that the secondary DBC owns any returned-data memory. + */ + F_SET(pdbc, DBC_TRANSIENT); + SET_RET_MEM(pdbc, dbc); + ret = __dbc_get(pdbc, pkey, data, DB_SET); + DB_ASSERT(pdbp->env, ret != DB_PAGE_NOTFOUND); + + /* + * If the item wasn't found in the primary, this is a bug; our + * secondary has somehow gotten corrupted, and contains elements that + * don't correspond to anything in the primary. Complain. + */ + + /* Now close the primary cursor. */ + if ((t_ret = __dbc_close(pdbc)) != 0 && ret == 0) + ret = t_ret; + + else if (ret == DB_NOTFOUND) { + if (!F_ISSET(dbc, DBC_READ_UNCOMMITTED)) + ret = __db_secondary_corrupt(pdbp); + else switch (flags) { + case DB_GET_BOTHC: + case DB_NEXT: + case DB_NEXT_DUP: + case DB_NEXT_NODUP: + case DB_PREV: + case DB_PREV_DUP: + case DB_PREV_NODUP: + PERFMON5(pdbp->env, race, dbc_get, + sdbp->fname, sdbp->dname, ret, flags, pkey); + goto retry; + default: + break; + } + } + +err: /* Cleanup and cursor resolution. */ + if (dbc_n == dbc) { + dbc_n->rkey = dbc_n->rdata; + dbc_n->rdata = save_data; + } + if ((t_ret = __dbc_cleanup(dbc, dbc_n, ret)) != 0 && ret == 0) + ret = t_ret; + if (pkeymalloc) { + /* + * If pkey had a MALLOC flag, we need to restore it; otherwise, + * if the user frees the buffer but reuses the DBT without + * NULL'ing its data field or changing the flags, we may drop + * core. + */ + F_CLR(pkey, DB_DBT_REALLOC); + F_SET(pkey, DB_DBT_MALLOC); + } + + return (ret); +} + +/* + * __dbc_pget_recno -- + * Perform a DB_GET_RECNO c_pget on a secondary index. Returns + * the secondary's record number in the pkey field and the primary's + * in the data field. + */ +static int +__dbc_pget_recno(sdbc, pkey, data, flags) + DBC *sdbc; + DBT *pkey, *data; + u_int32_t flags; +{ + DB *pdbp, *sdbp; + DBC *pdbc; + DBT discardme, primary_key; + ENV *env; + db_recno_t oob; + u_int32_t rmw; + int ret, t_ret; + + sdbp = sdbc->dbp; + pdbp = sdbp->s_primary; + env = sdbp->env; + pdbc = NULL; + ret = t_ret = 0; + + rmw = LF_ISSET(DB_RMW); + + memset(&discardme, 0, sizeof(DBT)); + F_SET(&discardme, DB_DBT_USERMEM | DB_DBT_PARTIAL); + + oob = RECNO_OOB; + + /* + * If the primary is an rbtree, we want its record number, whether + * or not the secondary is one too. Fetch the recno into "data". + * + * If it's not an rbtree, return RECNO_OOB in "data". + */ + if (F_ISSET(pdbp, DB_AM_RECNUM)) { + /* + * Get the primary key, so we can find the record number + * in the primary. (We're uninterested in the secondary key.) + */ + memset(&primary_key, 0, sizeof(DBT)); + F_SET(&primary_key, DB_DBT_MALLOC); + if ((ret = __dbc_get(sdbc, + &discardme, &primary_key, rmw | DB_CURRENT)) != 0) + return (ret); + + /* + * Open a cursor on the primary, set it to the right record, + * and fetch its recno into "data". + * + * (See __dbc_pget for comments on the use of __db_cursor_int.) + * + * SET_RET_MEM so that the secondary DBC owns any returned-data + * memory. + */ + if ((ret = __db_cursor_int(pdbp, sdbc->thread_info, sdbc->txn, + pdbp->type, PGNO_INVALID, 0, sdbc->locker, &pdbc)) != 0) + goto perr; + SET_RET_MEM(pdbc, sdbc); + if ((ret = __dbc_get(pdbc, + &primary_key, &discardme, rmw | DB_SET)) != 0) + goto perr; + + ret = __dbc_get(pdbc, &discardme, data, rmw | DB_GET_RECNO); + +perr: __os_ufree(env, primary_key.data); + if (pdbc != NULL && + (t_ret = __dbc_close(pdbc)) != 0 && ret == 0) + ret = t_ret; + if (ret != 0) + return (ret); + } else if ((ret = __db_retcopy(env, data, &oob, + sizeof(oob), &sdbc->rkey->data, &sdbc->rkey->ulen)) != 0) + return (ret); + + /* + * If the secondary is an rbtree, we want its record number, whether + * or not the primary is one too. Fetch the recno into "pkey". + * + * If it's not an rbtree, return RECNO_OOB in "pkey". + */ + if (F_ISSET(sdbp, DB_AM_RECNUM)) + return (__dbc_get(sdbc, &discardme, pkey, flags)); + else + return (__db_retcopy(env, pkey, &oob, + sizeof(oob), &sdbc->rdata->data, &sdbc->rdata->ulen)); +} + +/* + * __db_wrlock_err -- do not have a write lock. + */ +static int +__db_wrlock_err(env) + ENV *env; +{ + __db_errx(env, DB_STR("0697", "Write attempted on read-only cursor")); + return (EPERM); +} + +/* + * __dbc_del_secondary -- + * Perform a delete operation on a secondary index: call through + * to the primary and delete the primary record that this record + * points to. + * + * Note that deleting the primary record will call c_del on all + * the secondaries, including this one; thus, it is not necessary + * to execute both this function and an actual delete. + */ +static int +__dbc_del_secondary(dbc) + DBC *dbc; +{ + DB *pdbp; + DBC *pdbc; + DBT skey, pkey; + ENV *env; + int ret, t_ret; + u_int32_t rmw; + + pdbp = dbc->dbp->s_primary; + env = pdbp->env; + rmw = STD_LOCKING(dbc) ? DB_RMW : 0; + + /* + * Get the current item that we're pointing at. + * We don't actually care about the secondary key, just + * the primary. + */ + memset(&skey, 0, sizeof(DBT)); + memset(&pkey, 0, sizeof(DBT)); + F_SET(&skey, DB_DBT_PARTIAL | DB_DBT_USERMEM); + if ((ret = __dbc_get(dbc, &skey, &pkey, DB_CURRENT)) != 0) + return (ret); + + SWAP_IF_NEEDED(dbc->dbp, &pkey); + DEBUG_LWRITE(dbc, dbc->txn, "del_secondary", &skey, &pkey, 0); + + /* + * Create a cursor on the primary with our locker ID, + * so that when it calls back, we don't conflict. + * + * We create a cursor explicitly because there's no + * way to specify the same locker ID if we're using + * locking but not transactions if we use the DB->del + * interface. This shouldn't be any less efficient + * anyway. + */ + if ((ret = __db_cursor_int(pdbp, dbc->thread_info, dbc->txn, + pdbp->type, PGNO_INVALID, 0, dbc->locker, &pdbc)) != 0) + return (ret); + + /* + * See comment in __dbc_put--if we're in CDB, + * we already hold the locks we need, and we need to flag + * the cursor as a WRITER so we don't run into errors + * when we try to delete. + */ + if (CDB_LOCKING(env)) { + DB_ASSERT(env, pdbc->mylock.off == LOCK_INVALID); + F_SET(pdbc, DBC_WRITER); + } + + /* + * Set the new cursor to the correct primary key. Then + * delete it. We don't really care about the datum; + * just reuse our skey DBT. + * + * If the primary get returns DB_NOTFOUND, something is amiss-- + * every record in the secondary should correspond to some record + * in the primary. + */ + if ((ret = __dbc_get(pdbc, &pkey, &skey, DB_SET | rmw)) == 0) + ret = __dbc_del(pdbc, 0); + else if (ret == DB_NOTFOUND) + ret = __db_secondary_corrupt(pdbp); + + if ((t_ret = __dbc_close(pdbc)) != 0 && ret == 0) + ret = t_ret; + + return (ret); +} + +/* + * __dbc_del_primary -- + * Perform a delete operation on a primary index. Loop through + * all the secondary indices which correspond to this primary + * database, and delete any secondary keys that point at the current + * record. + * + * PUBLIC: int __dbc_del_primary __P((DBC *)); + */ +int +__dbc_del_primary(dbc) + DBC *dbc; +{ + DB *dbp, *sdbp; + DBC *sdbc; + DBT *tskeyp; + DBT data, pkey, skey, temppkey, tempskey; + ENV *env; + u_int32_t nskey, rmw; + int ret, t_ret; + + dbp = dbc->dbp; + env = dbp->env; + sdbp = NULL; + rmw = STD_LOCKING(dbc) ? DB_RMW : 0; + + /* + * If we're called at all, we have at least one secondary. + * (Unfortunately, we can't assert this without grabbing the mutex.) + * Get the current record so that we can construct appropriate + * secondary keys as needed. + */ + memset(&pkey, 0, sizeof(DBT)); + memset(&data, 0, sizeof(DBT)); + if ((ret = __dbc_get(dbc, &pkey, &data, DB_CURRENT)) != 0) + return (ret); + + memset(&skey, 0, sizeof(DBT)); + for (ret = __db_s_first(dbp, &sdbp); + sdbp != NULL && ret == 0; + ret = __db_s_next(&sdbp, dbc->txn)) { + /* + * Get the secondary key for this secondary and the current + * item. + */ + if ((ret = sdbp->s_callback(sdbp, &pkey, &data, &skey)) != 0) { + /* Not indexing is equivalent to an empty key set. */ + if (ret == DB_DONOTINDEX) { + F_SET(&skey, DB_DBT_MULTIPLE); + skey.size = 0; + } else /* We had a substantive error. Bail. */ + goto err; + } + +#ifdef DIAGNOSTIC + if (F_ISSET(&skey, DB_DBT_MULTIPLE)) + __db_check_skeyset(sdbp, &skey); +#endif + + if (F_ISSET(&skey, DB_DBT_MULTIPLE)) { + tskeyp = (DBT *)skey.data; + nskey = skey.size; + if (nskey == 0) + continue; + } else { + tskeyp = &skey; + nskey = 1; + } + + /* Open a secondary cursor. */ + if ((ret = __db_cursor_int(sdbp, + dbc->thread_info, dbc->txn, sdbp->type, + PGNO_INVALID, 0, dbc->locker, &sdbc)) != 0) + goto err; + /* See comment above and in __dbc_put. */ + if (CDB_LOCKING(env)) { + DB_ASSERT(env, sdbc->mylock.off == LOCK_INVALID); + F_SET(sdbc, DBC_WRITER); + } + + for (; nskey > 0; nskey--, tskeyp++) { + /* + * Set the secondary cursor to the appropriate item. + * Delete it. + * + * We want to use DB_RMW if locking is on; it's only + * legal then, though. + * + * !!! + * Don't stomp on any callback-allocated buffer in skey + * when we do a c_get(DB_GET_BOTH); use a temp DBT + * instead. Similarly, don't allow pkey to be + * invalidated when the cursor is closed. + */ + DB_INIT_DBT(tempskey, tskeyp->data, tskeyp->size); + SWAP_IF_NEEDED(sdbp, &pkey); + DB_INIT_DBT(temppkey, pkey.data, pkey.size); + if ((ret = __dbc_get(sdbc, &tempskey, &temppkey, + DB_GET_BOTH | rmw)) == 0) + ret = __dbc_del(sdbc, DB_UPDATE_SECONDARY); + else if (ret == DB_NOTFOUND) + ret = __db_secondary_corrupt(dbp); + SWAP_IF_NEEDED(sdbp, &pkey); + FREE_IF_NEEDED(env, tskeyp); + } + + if ((t_ret = __dbc_close(sdbc)) != 0 && ret == 0) + ret = t_ret; + if (ret != 0) + goto err; + + /* + * In the common case where there is a single secondary key, we + * will have freed any application-allocated data in skey + * already. In the multiple key case, we need to free it here. + * It is safe to do this twice as the macro resets the data + * field. + */ + FREE_IF_NEEDED(env, &skey); + } + +err: if (sdbp != NULL && + (t_ret = __db_s_done(sdbp, dbc->txn)) != 0 && ret == 0) + ret = t_ret; + FREE_IF_NEEDED(env, &skey); + return (ret); +} + +/* + * __dbc_del_foreign -- + * Apply the foreign database constraints for a particular foreign + * database when an item is being deleted (dbc points at item being deleted + * in the foreign database.) + * + * Delete happens in dbp, check for occurrences of key in pdpb. + * Terminology: + * Foreign db = Where delete occurs (dbp). + * Secondary db = Where references to dbp occur (sdbp, a secondary) + * Primary db = sdbp's primary database, references to dbp are secondary + * keys here + * Foreign Key = Key being deleted in dbp (fkey) + * Primary Key = Key of the corresponding entry in sdbp's primary (pkey). + */ +static int +__dbc_del_foreign(dbc) + DBC *dbc; +{ + DB_FOREIGN_INFO *f_info; + DB *dbp, *pdbp, *sdbp; + DBC *pdbc, *sdbc; + DBT data, fkey, pkey; + ENV *env; + u_int32_t flags, rmw; + int changed, ret, t_ret; + + dbp = dbc->dbp; + env = dbp->env; + + memset(&fkey, 0, sizeof(DBT)); + memset(&data, 0, sizeof(DBT)); + if ((ret = __dbc_get(dbc, &fkey, &data, DB_CURRENT)) != 0) + return (ret); + + LIST_FOREACH(f_info, &(dbp->f_primaries), f_links) { + sdbp = f_info->dbp; + pdbp = sdbp->s_primary; + flags = f_info->flags; + + rmw = (STD_LOCKING(dbc) && + !LF_ISSET(DB_FOREIGN_ABORT)) ? DB_RMW : 0; + + /* + * Handle CDB locking. Some of this is copied from + * __dbc_del_primary, but a bit more acrobatics are required. + * If we're not going to abort, then we need to get a write + * cursor. If CDB_ALLDB is set, then only one write cursor is + * allowed and we hold it, so we fudge things and promote the + * cursor on the other DBs manually, it won't cause a problem. + * If CDB_ALLDB is not set, then we go through the usual route + * to make sure we block as necessary. If there are any open + * read cursors on sdbp, the delete or put call later will + * block. + * + * If NULLIFY is set, we'll need a cursor on the primary to + * update it with the nullified data. Because primary and + * secondary dbs share a lock file ID in CDB, we open a cursor + * on the secondary and then get another writable cursor on the + * primary via __db_cursor_int to avoid deadlocking. + */ + sdbc = pdbc = NULL; + if (!LF_ISSET(DB_FOREIGN_ABORT) && CDB_LOCKING(env) && + !F_ISSET(env->dbenv, DB_ENV_CDB_ALLDB)) { + ret = __db_cursor(sdbp, + dbc->thread_info, dbc->txn, &sdbc, DB_WRITECURSOR); + if (LF_ISSET(DB_FOREIGN_NULLIFY) && ret == 0) { + ret = __db_cursor_int(pdbp, + dbc->thread_info, dbc->txn, pdbp->type, + PGNO_INVALID, 0, dbc->locker, &pdbc); + F_SET(pdbc, DBC_WRITER); + } + } else { + ret = __db_cursor_int(sdbp, dbc->thread_info, dbc->txn, + sdbp->type, PGNO_INVALID, 0, dbc->locker, &sdbc); + if (LF_ISSET(DB_FOREIGN_NULLIFY) && ret == 0) + ret = __db_cursor_int(pdbp, dbc->thread_info, + dbc->txn, pdbp->type, PGNO_INVALID, 0, + dbc->locker, &pdbc); + } + if (ret != 0) { + if (sdbc != NULL) + (void)__dbc_close(sdbc); + return (ret); + } + if (CDB_LOCKING(env) && F_ISSET(env->dbenv, DB_ENV_CDB_ALLDB)) { + DB_ASSERT(env, sdbc->mylock.off == LOCK_INVALID); + F_SET(sdbc, DBC_WRITER); + if (LF_ISSET(DB_FOREIGN_NULLIFY) && pdbc != NULL) { + DB_ASSERT(env, + pdbc->mylock.off == LOCK_INVALID); + F_SET(pdbc, DBC_WRITER); + } + } + + /* + * There are three actions possible when a foreign database has + * items corresponding to a deleted item: + * DB_FOREIGN_ABORT - The delete operation should be aborted. + * DB_FOREIGN_CASCADE - All corresponding foreign items should + * be deleted. + * DB_FOREIGN_NULLIFY - A callback needs to be made, allowing + * the application to modify the data DBT from the + * associated database. If the callback makes a + * modification, the updated item needs to replace the + * original item in the foreign db + */ + memset(&pkey, 0, sizeof(DBT)); + memset(&data, 0, sizeof(DBT)); + ret = __dbc_pget(sdbc, &fkey, &pkey, &data, DB_SET|rmw); + + if (ret == DB_NOTFOUND) { + /* No entry means no constraint */ + ret = __dbc_close(sdbc); + if (LF_ISSET(DB_FOREIGN_NULLIFY) && + (t_ret = __dbc_close(pdbc)) != 0) + ret = t_ret; + if (ret != 0) + return (ret); + continue; + } else if (ret != 0) { + /* Just return the error code from the pget */ + (void)__dbc_close(sdbc); + if (LF_ISSET(DB_FOREIGN_NULLIFY)) + (void)__dbc_close(pdbc); + return (ret); + } else if (LF_ISSET(DB_FOREIGN_ABORT)) { + /* If the record exists and ABORT is set, we're done */ + if ((ret = __dbc_close(sdbc)) != 0) + return (ret); + return (DB_FOREIGN_CONFLICT); + } + + /* + * There were matching items in the primary DB, and the action + * is either DB_FOREIGN_CASCADE or DB_FOREIGN_NULLIFY. + */ + while (ret == 0) { + if (LF_ISSET(DB_FOREIGN_CASCADE)) { + /* + * Don't use the DB_UPDATE_SECONDARY flag, + * since we want the delete to cascade into the + * secondary's primary. + */ + if ((ret = __dbc_del(sdbc, 0)) != 0) { + __db_err(env, ret, DB_STR("0698", + "Attempt to execute cascading delete in a foreign index failed")); + break; + } + } else if (LF_ISSET(DB_FOREIGN_NULLIFY)) { + changed = 0; + if ((ret = f_info->callback(sdbp, + &pkey, &data, &fkey, &changed)) != 0) { + __db_err(env, ret, DB_STR("0699", + "Foreign database application callback")); + break; + } + + /* + * If the user callback modified the DBT and + * a put on the primary failed. + */ + if (changed && (ret = __dbc_put(pdbc, + &pkey, &data, DB_KEYFIRST)) != 0) { + __db_err(env, ret, DB_STR("0700", +"Attempt to overwrite item in foreign database with nullified value failed")); + break; + } + } + /* retrieve the next matching item from the prim. db */ + memset(&pkey, 0, sizeof(DBT)); + memset(&data, 0, sizeof(DBT)); + ret = __dbc_pget(sdbc, + &fkey, &pkey, &data, DB_NEXT_DUP|rmw); + } + + if (ret == DB_NOTFOUND) + ret = 0; + if ((t_ret = __dbc_close(sdbc)) != 0 && ret == 0) + ret = t_ret; + if (LF_ISSET(DB_FOREIGN_NULLIFY) && + (t_ret = __dbc_close(pdbc)) != 0 && ret == 0) + ret = t_ret; + if (ret != 0) + return (ret); + } + + return (ret); +} + +/* + * __db_s_first -- + * Get the first secondary, if any are present, from the primary. + * + * PUBLIC: int __db_s_first __P((DB *, DB **)); + */ +int +__db_s_first(pdbp, sdbpp) + DB *pdbp, **sdbpp; +{ + DB *sdbp; + + MUTEX_LOCK(pdbp->env, pdbp->mutex); + sdbp = LIST_FIRST(&pdbp->s_secondaries); + + /* See __db_s_next. */ + if (sdbp != NULL) + sdbp->s_refcnt++; + MUTEX_UNLOCK(pdbp->env, pdbp->mutex); + + *sdbpp = sdbp; + + return (0); +} + +/* + * __db_s_next -- + * Get the next secondary in the list. + * + * PUBLIC: int __db_s_next __P((DB **, DB_TXN *)); + */ +int +__db_s_next(sdbpp, txn) + DB **sdbpp; + DB_TXN *txn; +{ + DB *sdbp, *pdbp, *closeme; + ENV *env; + int ret; + + /* + * Secondary indices are kept in a linked list, s_secondaries, + * off each primary DB handle. If a primary is free-threaded, + * this list may only be traversed or modified while the primary's + * thread mutex is held. + * + * The tricky part is that we don't want to hold the thread mutex + * across the full set of secondary puts necessary for each primary + * put, or we'll wind up essentially single-threading all the puts + * to the handle; the secondary puts will each take about as + * long as the primary does, and may require I/O. So we instead + * hold the thread mutex only long enough to follow one link to the + * next secondary, and then we release it before performing the + * actual secondary put. + * + * The only danger here is that we might legitimately close a + * secondary index in one thread while another thread is performing + * a put and trying to update that same secondary index. To + * prevent this from happening, we refcount the secondary handles. + * If close is called on a secondary index handle while we're putting + * to it, it won't really be closed--the refcount will simply drop, + * and we'll be responsible for closing it here. + */ + sdbp = *sdbpp; + pdbp = sdbp->s_primary; + env = pdbp->env; + closeme = NULL; + + MUTEX_LOCK(env, pdbp->mutex); + DB_ASSERT(env, sdbp->s_refcnt != 0); + if (--sdbp->s_refcnt == 0) { + LIST_REMOVE(sdbp, s_links); + closeme = sdbp; + } + sdbp = LIST_NEXT(sdbp, s_links); + if (sdbp != NULL) + sdbp->s_refcnt++; + MUTEX_UNLOCK(env, pdbp->mutex); + + *sdbpp = sdbp; + + /* + * closeme->close() is a wrapper; call __db_close explicitly. + */ + if (closeme == NULL) + ret = 0; + else + ret = __db_close(closeme, txn, 0); + + return (ret); +} + +/* + * __db_s_done -- + * Properly decrement the refcount on a secondary database handle we're + * using, without calling __db_s_next. + * + * PUBLIC: int __db_s_done __P((DB *, DB_TXN *)); + */ +int +__db_s_done(sdbp, txn) + DB *sdbp; + DB_TXN *txn; +{ + DB *pdbp; + ENV *env; + int doclose, ret; + + pdbp = sdbp->s_primary; + env = pdbp->env; + doclose = 0; + + MUTEX_LOCK(env, pdbp->mutex); + DB_ASSERT(env, sdbp->s_refcnt != 0); + if (--sdbp->s_refcnt == 0) { + LIST_REMOVE(sdbp, s_links); + doclose = 1; + } + MUTEX_UNLOCK(env, pdbp->mutex); + + if (doclose == 0) + ret = 0; + else + ret = __db_close(sdbp, txn, 0); + return (ret); +} + +/* + * __db_s_count -- + * Count the number of secondaries associated with a given primary. + */ +static int +__db_s_count(pdbp) + DB *pdbp; +{ + DB *sdbp; + ENV *env; + int count; + + env = pdbp->env; + count = 0; + + MUTEX_LOCK(env, pdbp->mutex); + for (sdbp = LIST_FIRST(&pdbp->s_secondaries); + sdbp != NULL; + sdbp = LIST_NEXT(sdbp, s_links)) + ++count; + MUTEX_UNLOCK(env, pdbp->mutex); + + return (count); +} + +/* + * __db_buildpartial -- + * Build the record that will result after a partial put is applied to + * an existing record. + * + * This should probably be merged with __bam_build, but that requires + * a little trickery if we plan to keep the overflow-record optimization + * in that function. + * + * PUBLIC: int __db_buildpartial __P((DB *, DBT *, DBT *, DBT *)); + */ +int +__db_buildpartial(dbp, oldrec, partial, newrec) + DB *dbp; + DBT *oldrec, *partial, *newrec; +{ + ENV *env; + u_int32_t len, nbytes; + u_int8_t *buf; + int ret; + + env = dbp->env; + + DB_ASSERT(env, F_ISSET(partial, DB_DBT_PARTIAL)); + + memset(newrec, 0, sizeof(DBT)); + + nbytes = __db_partsize(oldrec->size, partial); + newrec->size = nbytes; + + if ((ret = __os_malloc(env, nbytes, &buf)) != 0) + return (ret); + newrec->data = buf; + + /* Nul or pad out the buffer, for any part that isn't specified. */ + memset(buf, + F_ISSET(dbp, DB_AM_FIXEDLEN) ? ((BTREE *)dbp->bt_internal)->re_pad : + 0, nbytes); + + /* Copy in any leading data from the original record. */ + memcpy(buf, oldrec->data, + partial->doff > oldrec->size ? oldrec->size : partial->doff); + + /* Copy the data from partial. */ + memcpy(buf + partial->doff, partial->data, partial->size); + + /* Copy any trailing data from the original record. */ + len = partial->doff + partial->dlen; + if (oldrec->size > len) + memcpy(buf + partial->doff + partial->size, + (u_int8_t *)oldrec->data + len, oldrec->size - len); + + return (0); +} + +/* + * __db_partsize -- + * Given the number of bytes in an existing record and a DBT that + * is about to be partial-put, calculate the size of the record + * after the put. + * + * This code is called from __bam_partsize. + * + * PUBLIC: u_int32_t __db_partsize __P((u_int32_t, DBT *)); + */ +u_int32_t +__db_partsize(nbytes, data) + u_int32_t nbytes; + DBT *data; +{ + + /* + * There are really two cases here: + * + * Case 1: We are replacing some bytes that do not exist (i.e., they + * are past the end of the record). In this case the number of bytes + * we are replacing is irrelevant and all we care about is how many + * bytes we are going to add from offset. So, the new record length + * is going to be the size of the new bytes (size) plus wherever those + * new bytes begin (doff). + * + * Case 2: All the bytes we are replacing exist. Therefore, the new + * size is the oldsize (nbytes) minus the bytes we are replacing (dlen) + * plus the bytes we are adding (size). + */ + if (nbytes < data->doff + data->dlen) /* Case 1 */ + return (data->doff + data->size); + + return (nbytes + data->size - data->dlen); /* Case 2 */ +} + +/* + * __db_secondary_corrupt -- + * Report primary/secondary inconsistencies. + * + * PUBLIC: int __db_secondary_corrupt __P((DB *)); + */ +int +__db_secondary_corrupt(dbp) + DB *dbp; +{ + __db_err(dbp->env, DB_SECONDARY_BAD, "%s%s%s", + dbp->fname == NULL ? "unnamed" : dbp->fname, + dbp->dname == NULL ? "" : "/", + dbp->dname == NULL ? "" : dbp->dname); + return (DB_SECONDARY_BAD); +} + +#ifdef DIAGNOSTIC +/* + * __db_check_skeyset -- + * Diagnostic check that the application's callback returns a set of + * secondary keys without repeats. + * + * PUBLIC: #ifdef DIAGNOSTIC + * PUBLIC: void __db_check_skeyset __P((DB *, DBT *)); + * PUBLIC: #endif + */ +void +__db_check_skeyset(sdbp, skeyp) + DB *sdbp; + DBT *skeyp; +{ + DBT *first_key, *last_key, *key1, *key2; + ENV *env; + + env = sdbp->env; + + first_key = (DBT *)skeyp->data; + last_key = first_key + skeyp->size; + for (key1 = first_key; key1 < last_key; key1++) + for (key2 = key1 + 1; key2 < last_key; key2++) + DB_ASSERT(env, + ((BTREE *)sdbp->bt_internal)->bt_compare(sdbp, + key1, key2) != 0); +} +#endif diff -r 000000000000 -r a1985f14b030 src/db/db_conv.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/db/db_conv.c Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,944 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 1996, 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +/* + * Copyright (c) 1990, 1993, 1994, 1995, 1996 + * Keith Bostic. All rights reserved. + */ +/* + * Copyright (c) 1990, 1993, 1994, 1995 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $Id$ + */ + +#include "db_config.h" + +#include "db_int.h" +#include "dbinc/crypto.h" +#include "dbinc/hmac.h" +#include "dbinc/db_page.h" +#include "dbinc/db_swap.h" +#include "dbinc/btree.h" +#include "dbinc/hash.h" +#include "dbinc/heap.h" +#include "dbinc/qam.h" + +/* + * __db_pgin -- + * Primary page-swap routine. + * + * PUBLIC: int __db_pgin __P((DB_ENV *, db_pgno_t, void *, DBT *)); + */ +int +__db_pgin(dbenv, pg, pp, cookie) + DB_ENV *dbenv; + db_pgno_t pg; + void *pp; + DBT *cookie; +{ + DB dummydb, *dbp; + DB_CIPHER *db_cipher; + DB_LSN not_used; + DB_PGINFO *pginfo; + ENV *env; + PAGE *pagep; + size_t sum_len; + int is_hmac, ret; + u_int8_t *chksum; + + pginfo = (DB_PGINFO *)cookie->data; + env = dbenv->env; + pagep = (PAGE *)pp; + + ret = is_hmac = 0; + chksum = NULL; + memset(&dummydb, 0, sizeof(DB)); + dbp = &dummydb; + dbp->dbenv = dbenv; + dbp->env = env; + dbp->flags = pginfo->flags; + dbp->pgsize = pginfo->db_pagesize; + db_cipher = env->crypto_handle; + switch (pagep->type) { + case P_HASHMETA: + case P_HEAPMETA: + case P_BTREEMETA: + case P_QAMMETA: + /* + * If checksumming is set on the meta-page, we must set + * it in the dbp. + */ + if (FLD_ISSET(((DBMETA *)pp)->metaflags, DBMETA_CHKSUM)) + F_SET(dbp, DB_AM_CHKSUM); + else + F_CLR(dbp, DB_AM_CHKSUM); + if (((DBMETA *)pp)->encrypt_alg != 0 || + F_ISSET(dbp, DB_AM_ENCRYPT)) + is_hmac = 1; + /* + * !!! + * For all meta pages it is required that the chksum + * be at the same location. Use BTMETA to get to it + * for any meta type. + */ + chksum = ((BTMETA *)pp)->chksum; + sum_len = DBMETASIZE; + break; + case P_INVALID: + /* + * We assume that we've read a file hole if we have + * a zero LSN, zero page number and P_INVALID. Otherwise + * we have an invalid page that might contain real data. + */ + if (IS_ZERO_LSN(LSN(pagep)) && pagep->pgno == PGNO_INVALID) { + sum_len = 0; + break; + } + /* FALLTHROUGH */ + default: + chksum = P_CHKSUM(dbp, pagep); + sum_len = pginfo->db_pagesize; + /* + * If we are reading in a non-meta page, then if we have + * a db_cipher then we are using hmac. + */ + is_hmac = CRYPTO_ON(env) ? 1 : 0; + break; + } + + /* + * We expect a checksum error if there was a configuration problem. + * If there is no configuration problem and we don't get a match, + * it's fatal: panic the system. + */ + if (F_ISSET(dbp, DB_AM_CHKSUM) && sum_len != 0) { + if (F_ISSET(dbp, DB_AM_SWAP) && is_hmac == 0) + P_32_SWAP(chksum); + switch (ret = __db_check_chksum( + env, NULL, db_cipher, chksum, pp, sum_len, is_hmac)) { + case 0: + break; + case -1: + if (DBENV_LOGGING(env)) + (void)__db_cksum_log( + env, NULL, ¬_used, DB_FLUSH); + __db_errx(env, DB_STR_A("0684", + "checksum error: page %lu: catastrophic recovery required", + "%lu"), (u_long)pg); + return (__env_panic(env, DB_RUNRECOVERY)); + default: + return (ret); + } + } + if ((ret = __db_decrypt_pg(env, dbp, pagep)) != 0) + return (ret); + switch (pagep->type) { + case P_INVALID: + if (pginfo->type == DB_QUEUE) + return (__qam_pgin_out(env, pg, pp, cookie)); + else if (pginfo->type == DB_HEAP) + return (__heap_pgin(dbp, pg, pp, cookie)); + /* + * This page is either newly allocated from the end of the + * file, or from the free list, or it is an as-yet unwritten + * hash bucket page. In this last case it needs to be + * initialized, but never byte-swapped. Otherwise the header + * may need swapping. It will not be a metadata page, so the + * byte swapping code of __ham_pgin is adequate. If hash + * is not configured fall back to btree swapping. + */ +#ifdef HAVE_HASH + return (__ham_pgin(dbp, pg, pp, cookie)); +#else + return (__bam_pgin(dbp, pg, pp, cookie)); +#endif + /* NOTREACHED. */ + break; + case P_HASH_UNSORTED: + case P_HASH: + case P_HASHMETA: + return (__ham_pgin(dbp, pg, pp, cookie)); + case P_HEAP: + case P_HEAPMETA: + case P_IHEAP: + return (__heap_pgin(dbp, pg, pp, cookie)); + case P_BTREEMETA: + case P_IBTREE: + case P_IRECNO: + case P_LBTREE: + case P_LDUP: + case P_LRECNO: + case P_OVERFLOW: + return (__bam_pgin(dbp, pg, pp, cookie)); + case P_QAMMETA: + case P_QAMDATA: + return (__qam_pgin_out(env, pg, pp, cookie)); + default: + break; + } + return (__db_pgfmt(env, pg)); +} + +/* + * __db_pgout -- + * Primary page-swap routine. + * + * PUBLIC: int __db_pgout __P((DB_ENV *, db_pgno_t, void *, DBT *)); + */ +int +__db_pgout(dbenv, pg, pp, cookie) + DB_ENV *dbenv; + db_pgno_t pg; + void *pp; + DBT *cookie; +{ + DB dummydb, *dbp; + DB_PGINFO *pginfo; + ENV *env; + PAGE *pagep; + int ret; + + pginfo = (DB_PGINFO *)cookie->data; + env = dbenv->env; + pagep = (PAGE *)pp; + + memset(&dummydb, 0, sizeof(DB)); + dbp = &dummydb; + dbp->dbenv = dbenv; + dbp->env = env; + dbp->flags = pginfo->flags; + dbp->pgsize = pginfo->db_pagesize; + ret = 0; + switch (pagep->type) { + case P_INVALID: + switch (pginfo->type) { + case DB_QUEUE: + ret = __qam_pgin_out(env, pg, pp, cookie); + break; +#ifdef HAVE_HASH + case DB_HASH: + ret = __ham_pgout(dbp, pg, pp, cookie); + break; +#endif +#ifdef HAVE_HEAP + case DB_HEAP: + ret = __heap_pgout(dbp, pg, pp, cookie); + break; +#endif + case DB_BTREE: + case DB_RECNO: + ret = __bam_pgout(dbp, pg, pp, cookie); + break; + default: + return (__db_pgfmt(env, pg)); + } + break; + case P_HASH: + case P_HASH_UNSORTED: + /* + * Support pgout of unsorted hash pages - since online + * replication upgrade can cause pages of this type to be + * written out. + * + * FALLTHROUGH + */ + case P_HASHMETA: + ret = __ham_pgout(dbp, pg, pp, cookie); + break; + case P_HEAP: + case P_HEAPMETA: + case P_IHEAP: + ret = __heap_pgout(dbp, pg, pp, cookie); + break; + case P_BTREEMETA: + case P_IBTREE: + case P_IRECNO: + case P_LBTREE: + case P_LDUP: + case P_LRECNO: + case P_OVERFLOW: + ret = __bam_pgout(dbp, pg, pp, cookie); + break; + case P_QAMMETA: + case P_QAMDATA: + ret = __qam_pgin_out(env, pg, pp, cookie); + break; + default: + return (__db_pgfmt(env, pg)); + } + if (ret) + return (ret); + + return (__db_encrypt_and_checksum_pg(env, dbp, pagep)); +} + +/* + * __db_decrypt_pg -- + * Utility function to decrypt a db page. + * + * PUBLIC: int __db_decrypt_pg __P((ENV *, DB *, PAGE *)); + */ +int +__db_decrypt_pg (env, dbp, pagep) + ENV *env; + DB *dbp; + PAGE *pagep; +{ + DB_CIPHER *db_cipher; + size_t pg_len, pg_off; + u_int8_t *iv; + int ret; + + db_cipher = env->crypto_handle; + ret = 0; + iv = NULL; + if (F_ISSET(dbp, DB_AM_ENCRYPT)) { + DB_ASSERT(env, db_cipher != NULL); + DB_ASSERT(env, F_ISSET(dbp, DB_AM_CHKSUM)); + + pg_off = P_OVERHEAD(dbp); + DB_ASSERT(env, db_cipher->adj_size(pg_off) == 0); + + switch (pagep->type) { + case P_HASHMETA: + case P_HEAPMETA: + case P_BTREEMETA: + case P_QAMMETA: + /* + * !!! + * For all meta pages it is required that the iv + * be at the same location. Use BTMETA to get to it + * for any meta type. + */ + iv = ((BTMETA *)pagep)->iv; + pg_len = DBMETASIZE; + break; + case P_INVALID: + if (IS_ZERO_LSN(LSN(pagep)) && + pagep->pgno == PGNO_INVALID) { + pg_len = 0; + break; + } + /* FALLTHROUGH */ + default: + iv = P_IV(dbp, pagep); + pg_len = dbp->pgsize; + break; + } + if (pg_len != 0) + ret = db_cipher->decrypt(env, db_cipher->data, + iv, ((u_int8_t *)pagep) + pg_off, + pg_len - pg_off); + } + return (ret); +} + +/* + * __db_encrypt_and_checksum_pg -- + * Utility function to encrypt and checksum a db page. + * + * PUBLIC: int __db_encrypt_and_checksum_pg + * PUBLIC: __P((ENV *, DB *, PAGE *)); + */ +int +__db_encrypt_and_checksum_pg (env, dbp, pagep) + ENV *env; + DB *dbp; + PAGE *pagep; +{ + DB_CIPHER *db_cipher; + int ret; + size_t pg_off, pg_len, sum_len; + u_int8_t *chksum, *iv, *key; + + chksum = iv = key = NULL; + db_cipher = env->crypto_handle; + + if (F_ISSET(dbp, DB_AM_ENCRYPT)) { + DB_ASSERT(env, db_cipher != NULL); + DB_ASSERT(env, F_ISSET(dbp, DB_AM_CHKSUM)); + + pg_off = P_OVERHEAD(dbp); + DB_ASSERT(env, db_cipher->adj_size(pg_off) == 0); + + key = db_cipher->mac_key; + + switch (pagep->type) { + case P_HASHMETA: + case P_HEAPMETA: + case P_BTREEMETA: + case P_QAMMETA: + /* + * !!! + * For all meta pages it is required that the iv + * be at the same location. Use BTMETA to get to it + * for any meta type. + */ + iv = ((BTMETA *)pagep)->iv; + pg_len = DBMETASIZE; + break; + default: + iv = P_IV(dbp, pagep); + pg_len = dbp->pgsize; + break; + } + if ((ret = db_cipher->encrypt(env, db_cipher->data, + iv, ((u_int8_t *)pagep) + pg_off, pg_len - pg_off)) != 0) + return (ret); + } + if (F_ISSET(dbp, DB_AM_CHKSUM)) { + switch (pagep->type) { + case P_HASHMETA: + case P_HEAPMETA: + case P_BTREEMETA: + case P_QAMMETA: + /* + * !!! + * For all meta pages it is required that the chksum + * be at the same location. Use BTMETA to get to it + * for any meta type. + */ + chksum = ((BTMETA *)pagep)->chksum; + sum_len = DBMETASIZE; + break; + default: + chksum = P_CHKSUM(dbp, pagep); + sum_len = dbp->pgsize; + break; + } + __db_chksum(NULL, (u_int8_t *)pagep, sum_len, key, chksum); + if (F_ISSET(dbp, DB_AM_SWAP) && !F_ISSET(dbp, DB_AM_ENCRYPT)) + P_32_SWAP(chksum); + } + return (0); +} + +/* + * __db_metaswap -- + * Byteswap the common part of the meta-data page. + * + * PUBLIC: void __db_metaswap __P((PAGE *)); + */ +void +__db_metaswap(pg) + PAGE *pg; +{ + u_int8_t *p; + + p = (u_int8_t *)pg; + + /* Swap the meta-data information. */ + SWAP32(p); /* lsn.file */ + SWAP32(p); /* lsn.offset */ + SWAP32(p); /* pgno */ + SWAP32(p); /* magic */ + SWAP32(p); /* version */ + SWAP32(p); /* pagesize */ + p += 4; /* unused, page type, unused, unused */ + SWAP32(p); /* free */ + SWAP32(p); /* alloc_lsn part 1 */ + SWAP32(p); /* alloc_lsn part 2 */ + SWAP32(p); /* cached key count */ + SWAP32(p); /* cached record count */ + SWAP32(p); /* flags */ +} + +/* + * __db_byteswap -- + * Byteswap an ordinary database page. + * + * PUBLIC: int __db_byteswap + * PUBLIC: __P((DB *, db_pgno_t, PAGE *, size_t, int)); + */ +int +__db_byteswap(dbp, pg, h, pagesize, pgin) + DB *dbp; + db_pgno_t pg; + PAGE *h; + size_t pagesize; + int pgin; +{ + ENV *env; + BINTERNAL *bi; + BKEYDATA *bk; + BOVERFLOW *bo; + HEAPHDR *hh; + HEAPSPLITHDR *hsh; + RINTERNAL *ri; + db_indx_t i, *inp, len, tmp; + u_int8_t *end, *p, *pgend; + + if (pagesize == 0) + return (0); + + if (pgin) { + M_32_SWAP(h->lsn.file); + M_32_SWAP(h->lsn.offset); + M_32_SWAP(h->pgno); + M_32_SWAP(h->prev_pgno); + M_32_SWAP(h->next_pgno); + M_16_SWAP(h->entries); + M_16_SWAP(h->hf_offset); + } + + if (dbp == NULL) + return (0); + env = dbp->env; + + pgend = (u_int8_t *)h + pagesize; + + inp = P_INP(dbp, h); + if ((u_int8_t *)inp >= pgend) + goto out; + + switch (TYPE(h)) { + case P_HASH_UNSORTED: + case P_HASH: + for (i = 0; i < NUM_ENT(h); i++) { + if (pgin) + M_16_SWAP(inp[i]); + + if (P_ENTRY(dbp, h, i) >= pgend) + continue; + + switch (HPAGE_TYPE(dbp, h, i)) { + case H_KEYDATA: + break; + case H_DUPLICATE: + len = LEN_HKEYDATA(dbp, h, pagesize, i); + p = HKEYDATA_DATA(P_ENTRY(dbp, h, i)); + for (end = p + len; p < end;) { + if (pgin) { + P_16_SWAP(p); + memcpy(&tmp, + p, sizeof(db_indx_t)); + p += sizeof(db_indx_t); + } else { + memcpy(&tmp, + p, sizeof(db_indx_t)); + SWAP16(p); + } + p += tmp; + SWAP16(p); + } + break; + case H_OFFDUP: + p = HOFFPAGE_PGNO(P_ENTRY(dbp, h, i)); + SWAP32(p); /* pgno */ + break; + case H_OFFPAGE: + p = HOFFPAGE_PGNO(P_ENTRY(dbp, h, i)); + SWAP32(p); /* pgno */ + SWAP32(p); /* tlen */ + break; + default: + return (__db_pgfmt(env, pg)); + } + + } + + /* + * The offsets in the inp array are used to determine + * the size of entries on a page; therefore they + * cannot be converted until we've done all the + * entries. + */ + if (!pgin) + for (i = 0; i < NUM_ENT(h); i++) + M_16_SWAP(inp[i]); + break; + case P_LBTREE: + case P_LDUP: + case P_LRECNO: + for (i = 0; i < NUM_ENT(h); i++) { + if (pgin) + M_16_SWAP(inp[i]); + + /* + * In the case of on-page duplicates, key information + * should only be swapped once. + */ + if (h->type == P_LBTREE && i > 1) { + if (pgin) { + if (inp[i] == inp[i - 2]) + continue; + } else { + M_16_SWAP(inp[i]); + if (inp[i] == inp[i - 2]) + continue; + M_16_SWAP(inp[i]); + } + } + + bk = GET_BKEYDATA(dbp, h, i); + if ((u_int8_t *)bk >= pgend) + continue; + switch (B_TYPE(bk->type)) { + case B_KEYDATA: + M_16_SWAP(bk->len); + break; + case B_DUPLICATE: + case B_OVERFLOW: + bo = (BOVERFLOW *)bk; + M_32_SWAP(bo->pgno); + M_32_SWAP(bo->tlen); + break; + default: + return (__db_pgfmt(env, pg)); + } + + if (!pgin) + M_16_SWAP(inp[i]); + } + break; + case P_IBTREE: + for (i = 0; i < NUM_ENT(h); i++) { + if (pgin) + M_16_SWAP(inp[i]); + + bi = GET_BINTERNAL(dbp, h, i); + if ((u_int8_t *)bi >= pgend) + continue; + + M_16_SWAP(bi->len); + M_32_SWAP(bi->pgno); + M_32_SWAP(bi->nrecs); + + switch (B_TYPE(bi->type)) { + case B_KEYDATA: + break; + case B_DUPLICATE: + case B_OVERFLOW: + bo = (BOVERFLOW *)bi->data; + M_32_SWAP(bo->pgno); + M_32_SWAP(bo->tlen); + break; + default: + return (__db_pgfmt(env, pg)); + } + + if (!pgin) + M_16_SWAP(inp[i]); + } + break; + case P_IRECNO: + for (i = 0; i < NUM_ENT(h); i++) { + if (pgin) + M_16_SWAP(inp[i]); + + ri = GET_RINTERNAL(dbp, h, i); + if ((u_int8_t *)ri >= pgend) + continue; + + M_32_SWAP(ri->pgno); + M_32_SWAP(ri->nrecs); + + if (!pgin) + M_16_SWAP(inp[i]); + } + break; + case P_HEAP: + for (i = 0; i < HEAP_HIGHINDX(h); i++) { + if (pgin) + M_16_SWAP(inp[i]); + + hh = (HEAPHDR *)P_ENTRY(dbp, h, i); + if ((u_int8_t *)hh >= pgend) + continue; + M_16_SWAP(hh->size); + if (F_ISSET(hh, HEAP_RECSPLIT)) { + hsh = (HEAPSPLITHDR *)hh; + M_32_SWAP(hsh->tsize); + M_32_SWAP(hsh->nextpg); + M_16_SWAP(hsh->nextindx); + } + + if (!pgin) + M_16_SWAP(inp[i]); + } + break; + case P_IHEAP: + case P_INVALID: + case P_OVERFLOW: + case P_QAMDATA: + /* Nothing to do. */ + break; + default: + return (__db_pgfmt(env, pg)); + } + +out: if (!pgin) { + /* Swap the header information. */ + M_32_SWAP(h->lsn.file); + M_32_SWAP(h->lsn.offset); + M_32_SWAP(h->pgno); + M_32_SWAP(h->prev_pgno); + M_32_SWAP(h->next_pgno); + M_16_SWAP(h->entries); + M_16_SWAP(h->hf_offset); + } + return (0); +} + +/* + * __db_pageswap -- + * Byteswap any database page. Normally, the page to be swapped will be + * referenced by the "pp" argument and the pdata argument will be NULL. + * This function is also called by automatically generated log functions, + * where the page may be split into separate header and data parts. In + * that case, pdata is not NULL we reconsitute + * + * PUBLIC: int __db_pageswap + * PUBLIC: __P((ENV *, DB *, void *, size_t, DBT *, int)); + */ +int +__db_pageswap(env, dbp, pp, len, pdata, pgin) + ENV *env; + DB *dbp; + void *pp; + size_t len; + DBT *pdata; + int pgin; +{ + db_pgno_t pg; + size_t pgsize; + void *pgcopy; + int ret; + u_int16_t hoffset; + + switch (TYPE(pp)) { + case P_BTREEMETA: + return (__bam_mswap(env, pp)); + + case P_HASHMETA: + return (__ham_mswap(env, pp)); + + case P_QAMMETA: + return (__qam_mswap(env, pp)); + + case P_INVALID: + case P_OVERFLOW: + case P_QAMDATA: + /* + * We may have been passed an invalid page, or a queue data + * page, or an overflow page where fields like hoffset have a + * special meaning. In that case, no swapping of the page data + * is required, just the fields in the page header. + */ + pdata = NULL; + break; + + default: + break; + } + + if (pgin) { + P_32_COPYSWAP(&PGNO(pp), &pg); + P_16_COPYSWAP(&HOFFSET(pp), &hoffset); + } else { + pg = PGNO(pp); + hoffset = HOFFSET(pp); + } + + if (pdata == NULL) + ret = __db_byteswap(dbp, pg, (PAGE *)pp, len, pgin); + else { + pgsize = hoffset + pdata->size; + if ((ret = __os_malloc(env, pgsize, &pgcopy)) != 0) + return (ret); + memset(pgcopy, 0, pgsize); + memcpy(pgcopy, pp, len); + memcpy((u_int8_t *)pgcopy + hoffset, pdata->data, pdata->size); + + ret = __db_byteswap(dbp, pg, (PAGE *)pgcopy, pgsize, pgin); + memcpy(pp, pgcopy, len); + + /* + * If we are swapping data to be written to the log, we can't + * overwrite the buffer that was passed in: it may be a pointer + * into a page in cache. We set DB_DBT_APPMALLOC here so that + * the calling code can free the memory we allocate here. + */ + if (!pgin) { + if ((ret = + __os_malloc(env, pdata->size, &pdata->data)) != 0) { + __os_free(env, pgcopy); + return (ret); + } + F_SET(pdata, DB_DBT_APPMALLOC); + } + memcpy(pdata->data, (u_int8_t *)pgcopy + hoffset, pdata->size); + __os_free(env, pgcopy); + } + + return (ret); +} + +/* + * __db_recordswap -- + * Byteswap any database record. + * + * PUBLIC: void __db_recordswap __P((u_int32_t, + * PUBLIC: u_int32_t, void *, void *, u_int32_t)); + */ +void +__db_recordswap(op, size, hdr, data, pgin) + u_int32_t op; + u_int32_t size; + void *hdr, *data; + u_int32_t pgin; +{ + BKEYDATA *bk; + BOVERFLOW *bo; + BINTERNAL *bi; + HEAPHDR *hh; + HEAPSPLITHDR *hsh; + RINTERNAL *ri; + db_indx_t tmp; + u_int8_t *p, *end; + + if (size == 0) + return; + switch (OP_PAGE_GET(op)) { + case P_LDUP: + case P_LBTREE: + case P_LRECNO: + bk = (BKEYDATA *)hdr; + switch (B_TYPE(bk->type)) { + case B_KEYDATA: + M_16_SWAP(bk->len); + break; + case B_DUPLICATE: + case B_OVERFLOW: + bo = (BOVERFLOW *)hdr; + M_32_SWAP(bo->pgno); + M_32_SWAP(bo->tlen); + break; + default: + DB_ASSERT(NULL, bk->type != bk->type); + } + break; + case P_IBTREE: + bi = (BINTERNAL *)hdr; + M_16_SWAP(bi->len); + M_32_SWAP(bi->pgno); + M_32_SWAP(bi->nrecs); + if (B_TYPE(bi->type) == B_OVERFLOW) { + if (data == NULL) { + DB_ASSERT(NULL, + size == BINTERNAL_SIZE(BOVERFLOW_SIZE)); + bo = (BOVERFLOW *)bi->data; + } else + bo = (BOVERFLOW *)data; + M_32_SWAP(bo->pgno); + } + break; + case P_IRECNO: + ri = (RINTERNAL *)hdr; + M_32_SWAP(ri->pgno); + M_32_SWAP(ri->nrecs); + break; + case P_OVERFLOW: + break; + case P_HASH: + case P_HASH_UNSORTED: + switch (OP_MODE_GET(op)) { + /* KEYDATA and DUPLICATE records do not include the header. */ + case H_KEYDATA: + break; + case H_DUPLICATE: + p = (u_int8_t *)hdr; + for (end = p + size; p < end;) { + if (pgin) { + P_16_SWAP(p); + memcpy(&tmp, + p, sizeof(db_indx_t)); + p += sizeof(db_indx_t); + } else { + memcpy(&tmp, + p, sizeof(db_indx_t)); + SWAP16(p); + } + p += tmp; + SWAP16(p); + } + break; + /* These two record types include the full header. */ + case H_OFFDUP: + p = (u_int8_t *)hdr; + p += SSZ(HOFFPAGE, pgno); + SWAP32(p); /* pgno */ + break; + case H_OFFPAGE: + p = (u_int8_t *)hdr; + p += SSZ(HOFFPAGE, pgno); + SWAP32(p); /* pgno */ + SWAP32(p); /* tlen */ + break; + default: + DB_ASSERT(NULL, op != op); + } + break; + case P_HEAP: + hh = (HEAPHDR *)hdr; + M_16_SWAP(hh->size); + if (F_ISSET(hh, HEAP_RECSPLIT)) { + hsh = (HEAPSPLITHDR *)hdr; + M_32_SWAP(hsh->tsize); + M_32_SWAP(hsh->nextpg); + M_16_SWAP(hsh->nextindx); + } + break; + default: + DB_ASSERT(NULL, op != op); + } +} diff -r 000000000000 -r a1985f14b030 src/db/db_copy.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/db/db_copy.c Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,53 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 2011, 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + * $Id$ + */ + +#include "db_config.h" +#include "db_int.h" +#include "dbinc/db_page.h" +#include "dbinc/db_am.h" + +/* + * db_copy -- + * Copy a database file coordinated with mpool. + * This is for backward compatibility to the quick fix in 5.2. + * + * EXTERN: int db_copy __P((DB_ENV *, + * EXTERN: const char *, const char *, const char *)); + */ +int +db_copy(dbenv, dbfile, target, passwd) + DB_ENV *dbenv; + const char *dbfile; + const char *target; + const char *passwd; +{ + COMPQUIET(passwd, NULL); + return (__db_dbbackup_pp(dbenv, dbfile, target, 0)); +} diff -r 000000000000 -r a1985f14b030 src/db/db_dup.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/db/db_dup.c Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,236 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 1996, 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + * $Id$ + */ + +#include "db_config.h" + +#include "db_int.h" +#include "dbinc/db_page.h" +#include "dbinc/mp.h" +#include "dbinc/log.h" +#include "dbinc/db_am.h" +#include "dbinc/txn.h" + +/* + * __db_ditem_nolog -- + * Remove an item from a page without affecting its recoverability. + * + * PUBLIC: int __db_ditem_nolog __P((DBC *, PAGE *, u_int32_t, u_int32_t)); + */ +int +__db_ditem_nolog(dbc, pagep, indx, nbytes) + DBC *dbc; + PAGE *pagep; + u_int32_t indx, nbytes; +{ + DB *dbp; + db_indx_t cnt, *inp, offset; + u_int8_t *from; + + dbp = dbc->dbp; + DB_ASSERT(dbp->env, IS_DIRTY(pagep)); + DB_ASSERT(dbp->env, indx < NUM_ENT(pagep)); + + /* + * If there's only a single item on the page, we don't have to + * work hard. + */ + if (NUM_ENT(pagep) == 1) { + NUM_ENT(pagep) = 0; + HOFFSET(pagep) = dbp->pgsize; + return (0); + } + + inp = P_INP(dbp, pagep); + /* + * Pack the remaining key/data items at the end of the page. Use + * memmove(3), the regions may overlap. + */ + from = (u_int8_t *)pagep + HOFFSET(pagep); + DB_ASSERT(dbp->env, inp[indx] >= HOFFSET(pagep)); + memmove(from + nbytes, from, inp[indx] - HOFFSET(pagep)); + HOFFSET(pagep) += nbytes; + + /* Adjust the indices' offsets. */ + offset = inp[indx]; + for (cnt = 0; cnt < NUM_ENT(pagep); ++cnt) + if (inp[cnt] < offset) + inp[cnt] += nbytes; + + /* Shift the indices down. */ + --NUM_ENT(pagep); + if (indx != NUM_ENT(pagep)) + memmove(&inp[indx], &inp[indx + 1], + sizeof(db_indx_t) * (NUM_ENT(pagep) - indx)); + + return (0); +} + +/* + * __db_ditem -- + * Remove an item from a page, logging it if enabled. + * + * PUBLIC: int __db_ditem __P((DBC *, PAGE *, u_int32_t, u_int32_t)); + */ +int +__db_ditem(dbc, pagep, indx, nbytes) + DBC *dbc; + PAGE *pagep; + u_int32_t indx, nbytes; +{ + DB *dbp; + DBT ldbt; + int ret; + + dbp = dbc->dbp; + + if (DBC_LOGGING(dbc)) { + ldbt.data = P_ENTRY(dbp, pagep, indx); + ldbt.size = nbytes; + if ((ret = __db_addrem_log(dbp, dbc->txn, &LSN(pagep), 0, + OP_SET(DB_REM_DUP, pagep), PGNO(pagep), + (u_int32_t)indx, nbytes, &ldbt, NULL, &LSN(pagep))) != 0) + return (ret); + } else + LSN_NOT_LOGGED(LSN(pagep)); + + return (__db_ditem_nolog(dbc, pagep, indx, nbytes)); +} + +/* + * __db_pitem_nolog -- + * Put an item on a page without logging. + * + * PUBLIC: int __db_pitem_nolog + * PUBLIC: __P((DBC *, PAGE *, u_int32_t, u_int32_t, DBT *, DBT *)); + */ +int +__db_pitem_nolog(dbc, pagep, indx, nbytes, hdr, data) + DBC *dbc; + PAGE *pagep; + u_int32_t indx; + u_int32_t nbytes; + DBT *hdr, *data; +{ + BKEYDATA bk; + DB *dbp; + DBT thdr; + db_indx_t *inp; + u_int8_t *p; + + dbp = dbc->dbp; + + DB_ASSERT(dbp->env, IS_DIRTY(pagep)); + + if (nbytes > P_FREESPACE(dbp, pagep)) { + DB_ASSERT(dbp->env, nbytes <= P_FREESPACE(dbp, pagep)); + return (EINVAL); + } + + if (hdr == NULL) { + B_TSET(bk.type, B_KEYDATA); + bk.len = data == NULL ? 0 : data->size; + + thdr.data = &bk; + thdr.size = SSZA(BKEYDATA, data); + hdr = &thdr; + } + inp = P_INP(dbp, pagep); + + /* Adjust the index table, then put the item on the page. */ + if (indx != NUM_ENT(pagep)) + memmove(&inp[indx + 1], &inp[indx], + sizeof(db_indx_t) * (NUM_ENT(pagep) - indx)); + HOFFSET(pagep) -= nbytes; + inp[indx] = HOFFSET(pagep); + ++NUM_ENT(pagep); + + p = P_ENTRY(dbp, pagep, indx); + memcpy(p, hdr->data, hdr->size); + if (data != NULL) + memcpy(p + hdr->size, data->data, data->size); + + return (0); +} + +/* + * __db_pitem -- + * Put an item on a page. + * + * PUBLIC: int __db_pitem + * PUBLIC: __P((DBC *, PAGE *, u_int32_t, u_int32_t, DBT *, DBT *)); + */ +int +__db_pitem(dbc, pagep, indx, nbytes, hdr, data) + DBC *dbc; + PAGE *pagep; + u_int32_t indx; + u_int32_t nbytes; + DBT *hdr, *data; +{ + DB *dbp; + MPOOLFILE *mpf; + int ret; + + dbp = dbc->dbp; + mpf = dbp->mpf->mfp; + /* + * Put a single item onto a page. The logic figuring out where to + * insert and whether it fits is handled in the caller. All we do + * here is manage the page shuffling. We cheat a little bit in that + * we don't want to copy the dbt on a normal put twice. If hdr is + * NULL, we create a BKEYDATA structure on the page, otherwise, just + * copy the caller's information onto the page. + * + * This routine is also used to put entries onto the page where the + * entry is pre-built, e.g., during recovery. In this case, the hdr + * will point to the entry, and the data argument will be NULL. + * + * If transactional bulk loading is enabled in this + * transaction, and the page is above the file's extension + * watermark, skip logging, but do not invoke LSN_NOT_LOGGED. + * + * !!! + * There's a tremendous potential for off-by-one errors here, since + * the passed in header sizes must be adjusted for the structure's + * placeholder for the trailing variable-length data field. + */ + if (DBC_LOGGING(dbc)) { + if (__txn_pg_above_fe_watermark(dbc->txn, mpf, PGNO(pagep))) { + mpf->fe_nlws++; /* Note that logging was skipped. */ + } else if ((ret = __db_addrem_log(dbp, dbc->txn, &LSN(pagep), + 0, OP_SET(DB_ADD_DUP, pagep), PGNO(pagep), + (u_int32_t)indx, nbytes, hdr, data, &LSN(pagep)))) { + return (ret); + } + } else + LSN_NOT_LOGGED(LSN(pagep)); + + return (__db_pitem_nolog(dbc, pagep, indx, nbytes, hdr, data)); +} diff -r 000000000000 -r a1985f14b030 src/db/db_iface.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/db/db_iface.c Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,2717 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 1996, 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + * $Id$ + */ + +#include "db_config.h" + +#include "db_int.h" +#include "dbinc/db_page.h" +#include "dbinc/btree.h" +#include "dbinc/hash.h" +#ifndef HAVE_QUEUE +#include "dbinc/qam.h" /* For __db_no_queue_am(). */ +#endif +#include "dbinc/lock.h" +#include "dbinc/mp.h" +#include "dbinc/partition.h" +#include "dbinc/txn.h" + +static int __db_associate_arg __P((DB *, DB *, + int (*)(DB *, const DBT *, const DBT *, DBT *), u_int32_t)); +static int __dbc_del_arg __P((DBC *, u_int32_t)); +static int __dbc_pget_arg __P((DBC *, DBT *, u_int32_t)); +static int __dbc_put_arg __P((DBC *, DBT *, DBT *, u_int32_t)); +static int __db_curinval __P((const ENV *)); +static int __db_cursor_arg __P((DB *, u_int32_t)); +static int __db_del_arg __P((DB *, DBT *, u_int32_t)); +static int __db_get_arg __P((const DB *, DBT *, DBT *, u_int32_t)); +static int __db_open_arg __P((DB *, + DB_TXN *, const char *, const char *, DBTYPE, u_int32_t)); +static int __db_pget_arg __P((DB *, DBT *, u_int32_t)); +static int __db_put_arg __P((DB *, DBT *, DBT *, u_int32_t)); +static int __dbt_ferr __P((const DB *, const char *, const DBT *, int)); + +/* + * These functions implement the Berkeley DB API. They are organized in a + * layered fashion. The interface functions (XXX_pp) perform all generic + * error checks (for example, PANIC'd region, replication state change + * in progress, inconsistent transaction usage), call function-specific + * check routines (_arg) to check for proper flag usage, etc., do pre-amble + * processing (incrementing handle counts, handling local transactions), + * call the function and then do post-amble processing (local transactions, + * decrement handle counts). + * + * The basic structure is: + * Check for simple/generic errors (PANIC'd region) + * Check if replication is changing state (increment handle count). + * Call function-specific argument checking routine + * Create internal transaction if necessary + * Call underlying worker function + * Commit/abort internal transaction if necessary + * Decrement handle count + */ + +/* + * __db_associate_pp -- + * DB->associate pre/post processing. + * + * PUBLIC: int __db_associate_pp __P((DB *, DB_TXN *, DB *, + * PUBLIC: int (*)(DB *, const DBT *, const DBT *, DBT *), u_int32_t)); + */ +int +__db_associate_pp(dbp, txn, sdbp, callback, flags) + DB *dbp, *sdbp; + DB_TXN *txn; + int (*callback) __P((DB *, const DBT *, const DBT *, DBT *)); + u_int32_t flags; +{ + DBC *sdbc; + DB_THREAD_INFO *ip; + ENV *env; + int handle_check, ret, t_ret, txn_local; + + env = dbp->env; + txn_local = 0; + + STRIP_AUTO_COMMIT(flags); + + ENV_ENTER(env, ip); + XA_CHECK_TXN(ip, txn); + + /* Check for replication block. */ + handle_check = IS_ENV_REPLICATED(env); + if (handle_check && + (ret = __db_rep_enter(dbp, 1, 0, IS_REAL_TXN(txn))) != 0) { + handle_check = 0; + goto err; + } + + /* + * Secondary cursors may have the primary's lock file ID, so we need + * to make sure that no older cursors are lying around when we make + * the transition. + */ + if (TAILQ_FIRST(&sdbp->active_queue) != NULL || + TAILQ_FIRST(&sdbp->join_queue) != NULL) { + __db_errx(env, DB_STR("0572", + "Databases may not become secondary indices while cursors are open")); + ret = EINVAL; + goto err; + } + + if ((ret = __db_associate_arg(dbp, sdbp, callback, flags)) != 0) + goto err; + + /* + * Create a local transaction as necessary, check for consistent + * transaction usage, and, if we have no transaction but do have + * locking on, acquire a locker id for the handle lock acquisition. + */ + if (IS_DB_AUTO_COMMIT(dbp, txn)) { + if ((ret = __txn_begin(env, ip, NULL, &txn, 0)) != 0) + goto err; + txn_local = 1; + } + + /* Check for consistent transaction usage. */ + if ((ret = __db_check_txn(dbp, txn, DB_LOCK_INVALIDID, 0)) != 0) + goto err; + + while ((sdbc = TAILQ_FIRST(&sdbp->free_queue)) != NULL) + if ((ret = __dbc_destroy(sdbc)) != 0) + goto err; + + ret = __db_associate(dbp, ip, txn, sdbp, callback, flags); + +err: if (txn_local && + (t_ret = __db_txn_auto_resolve(env, txn, 0, ret)) && ret == 0) + ret = t_ret; + + /* Release replication block. */ + if (handle_check && (t_ret = __env_db_rep_exit(env)) != 0 && ret == 0) + ret = t_ret; + ENV_LEAVE(env, ip); + return (ret); +} + +/* + * __db_associate_arg -- + * Check DB->associate arguments. + */ +static int +__db_associate_arg(dbp, sdbp, callback, flags) + DB *dbp, *sdbp; + int (*callback) __P((DB *, const DBT *, const DBT *, DBT *)); + u_int32_t flags; +{ + ENV *env; + int ret; + + env = dbp->env; + + if (sdbp->type == DB_HEAP) { + __db_errx(env, + "Heap databases may not be used as secondary databases"); + return (EINVAL); + } + + if (F_ISSET(sdbp, DB_AM_SECONDARY)) { + __db_errx(env, DB_STR("0573", + "Secondary index handles may not be re-associated")); + return (EINVAL); + } + if (F_ISSET(dbp, DB_AM_SECONDARY)) { + __db_errx(env, DB_STR("0574", + "Secondary indices may not be used as primary databases")); + return (EINVAL); + } + if (F_ISSET(dbp, DB_AM_DUP)) { + __db_errx(env, DB_STR("0575", + "Primary databases may not be configured with duplicates")); + return (EINVAL); + } + if (F_ISSET(dbp, DB_AM_RENUMBER)) { + __db_errx(env, DB_STR("0576", + "Renumbering recno databases may not be used as primary databases")); + return (EINVAL); + } + + /* + * It's OK for the primary and secondary to not share an environment IFF + * the environments are local to the DB handle. (Specifically, cursor + * adjustment will work correctly in this case.) The environment being + * local implies the environment is not configured for either locking or + * transactions, as neither of those could work correctly. + */ + if (dbp->env != sdbp->env && + (!F_ISSET(dbp->env, ENV_DBLOCAL) || + !F_ISSET(sdbp->env, ENV_DBLOCAL))) { + __db_errx(env, DB_STR("0577", + "The primary and secondary must be opened in the same environment")); + return (EINVAL); + } + if ((DB_IS_THREADED(dbp) && !DB_IS_THREADED(sdbp)) || + (!DB_IS_THREADED(dbp) && DB_IS_THREADED(sdbp))) { + __db_errx(env, DB_STR("0578", + "The DB_THREAD setting must be the same for primary and secondary")); + return (EINVAL); + } + if (callback == NULL && + (!F_ISSET(dbp, DB_AM_RDONLY) || !F_ISSET(sdbp, DB_AM_RDONLY))) { + __db_errx(env, DB_STR("0579", +"Callback function may be NULL only when database handles are read-only")); + return (EINVAL); + } + + if ((ret = __db_fchk(env, "DB->associate", flags, DB_CREATE | + DB_IMMUTABLE_KEY)) != 0) + return (ret); + + return (0); +} + +/* + * __db_close_pp -- + * DB->close pre/post processing. + * + * PUBLIC: int __db_close_pp __P((DB *, u_int32_t)); + */ +int +__db_close_pp(dbp, flags) + DB *dbp; + u_int32_t flags; +{ + DB_THREAD_INFO *ip; + ENV *env; + int handle_check, ret, t_ret; + + env = dbp->env; + ret = 0; + + /* + * Close a DB handle -- as a handle destructor, we can't fail. + * + * !!! + * The actual argument checking is simple, do it inline, outside of + * the replication block. + */ + if (flags != 0 && flags != DB_NOSYNC) + ret = __db_ferr(env, "DB->close", 0); + + ENV_ENTER(env, ip); + + /* Check for replication block. */ + handle_check = IS_ENV_REPLICATED(env); + if (handle_check && (t_ret = __db_rep_enter(dbp, 0, 0, 0)) != 0) { + handle_check = 0; + if (ret == 0) + ret = t_ret; + } + + if ((t_ret = __db_close(dbp, NULL, flags)) != 0 && ret == 0) + ret = t_ret; + + /* Release replication block. */ + if (handle_check && (t_ret = __env_db_rep_exit(env)) != 0 && ret == 0) + ret = t_ret; + + ENV_LEAVE(env, ip); + return (ret); +} + +/* + * __db_cursor_pp -- + * DB->cursor pre/post processing. + * + * PUBLIC: int __db_cursor_pp __P((DB *, DB_TXN *, DBC **, u_int32_t)); + */ +int +__db_cursor_pp(dbp, txn, dbcp, flags) + DB *dbp; + DB_TXN *txn; + DBC **dbcp; + u_int32_t flags; +{ + DB_THREAD_INFO *ip; + ENV *env; + REGENV *renv; + int rep_blocked, ret; + + env = dbp->env; + + DB_ILLEGAL_BEFORE_OPEN(dbp, "DB->cursor"); + + ENV_ENTER(env, ip); + XA_CHECK_TXN(ip, txn); + + /* Check for replication block. */ + rep_blocked = 0; + if (IS_ENV_REPLICATED(env)) { + if (!IS_REAL_TXN(txn)) { + if ((ret = __op_rep_enter(env, 0, 1)) != 0) + goto err; + rep_blocked = 1; + } + renv = env->reginfo->primary; + if (dbp->timestamp != renv->rep_timestamp) { + __db_errx(env, DB_STR("0580", + "replication recovery unrolled committed transactions;" + "open DB and DBcursor handles must be closed")); + ret = DB_REP_HANDLE_DEAD; + goto err; + } + } + if ((ret = __db_cursor_arg(dbp, flags)) != 0) + goto err; + + /* + * Check for consistent transaction usage. For now, assume this + * cursor might be used for read operations only (in which case + * it may not require a txn). We'll check more stringently in + * c_del and c_put. (Note this means the read-op txn tests have + * to be a subset of the write-op ones.) + */ + if ((ret = __db_check_txn(dbp, txn, DB_LOCK_INVALIDID, 1)) != 0) + goto err; + + ret = __db_cursor(dbp, ip, txn, dbcp, flags); + + /* + * Register externally created cursors into the valid transaction. + * If a family transaction was passed in, the transaction handle in + * the cursor may not match. + */ + txn = (*dbcp)->txn; + if (txn != NULL && ret == 0) + TAILQ_INSERT_HEAD(&(txn->my_cursors), *dbcp, txn_cursors); + +err: /* Release replication block on error. */ + if (ret != 0 && rep_blocked) + (void)__op_rep_exit(env); + + ENV_LEAVE(env, ip); + return (ret); +} + +/* + * __db_cursor -- + * DB->cursor. + * + * PUBLIC: int __db_cursor __P((DB *, + * PUBLIC: DB_THREAD_INFO *, DB_TXN *, DBC **, u_int32_t)); + */ +int +__db_cursor(dbp, ip, txn, dbcp, flags) + DB *dbp; + DB_THREAD_INFO *ip; + DB_TXN *txn; + DBC **dbcp; + u_int32_t flags; +{ + DBC *dbc; + ENV *env; + db_lockmode_t mode; + int ret; + + env = dbp->env; + + if (MULTIVERSION(dbp) && txn == NULL && (LF_ISSET(DB_TXN_SNAPSHOT) || + F_ISSET(env->dbenv, DB_ENV_TXN_SNAPSHOT))) { + if ((ret = + __txn_begin(env, ip, NULL, &txn, DB_TXN_SNAPSHOT)) != 0) + return (ret); + F_SET(txn, TXN_PRIVATE); + } + + PERFMON5(env, db, cursor, dbp->fname, + dbp->dname, txn == NULL ? 0 : txn->txnid, flags, &dbp->fileid[0]); + + if ((ret = __db_cursor_int(dbp, ip, txn, dbp->type, PGNO_INVALID, + LF_ISSET(DB_CURSOR_BULK | DB_CURSOR_TRANSIENT | DB_RECOVER), + NULL, &dbc)) != 0) + return (ret); + + /* + * If this is CDB, do all the locking in the interface, which is + * right here. + */ + if (CDB_LOCKING(env)) { + mode = (LF_ISSET(DB_WRITELOCK)) ? DB_LOCK_WRITE : + ((LF_ISSET(DB_WRITECURSOR) || txn != NULL) ? + DB_LOCK_IWRITE : DB_LOCK_READ); + if ((ret = __lock_get(env, dbc->locker, 0, + &dbc->lock_dbt, mode, &dbc->mylock)) != 0) + goto err; + if (LF_ISSET(DB_WRITECURSOR)) + F_SET(dbc, DBC_WRITECURSOR); + if (LF_ISSET(DB_WRITELOCK)) + F_SET(dbc, DBC_WRITER); + } + + if (LF_ISSET(DB_READ_UNCOMMITTED) || + (txn != NULL && F_ISSET(txn, TXN_READ_UNCOMMITTED))) + F_SET(dbc, DBC_READ_UNCOMMITTED); + + if (LF_ISSET(DB_READ_COMMITTED) || + (txn != NULL && F_ISSET(txn, TXN_READ_COMMITTED))) + F_SET(dbc, DBC_READ_COMMITTED); + + *dbcp = dbc; + return (0); + +err: (void)__dbc_close(dbc); + return (ret); +} + +/* + * __db_cursor_arg -- + * Check DB->cursor arguments. + */ +static int +__db_cursor_arg(dbp, flags) + DB *dbp; + u_int32_t flags; +{ + ENV *env; + + env = dbp->env; + + /* + * DB_READ_COMMITTED and DB_READ_UNCOMMITTED require locking. + */ + if (LF_ISSET(DB_READ_COMMITTED | DB_READ_UNCOMMITTED)) { + if (!LOCKING_ON(env)) + return (__db_fnl(env, "DB->cursor")); + } + + LF_CLR(DB_CURSOR_BULK | + DB_READ_COMMITTED | DB_READ_UNCOMMITTED | DB_TXN_SNAPSHOT); + + /* Check for invalid function flags. */ + if (LF_ISSET(DB_WRITECURSOR)) { + if (DB_IS_READONLY(dbp)) + return (__db_rdonly(env, "DB->cursor")); + if (!CDB_LOCKING(env)) + return (__db_ferr(env, "DB->cursor", 0)); + LF_CLR(DB_WRITECURSOR); + } else if (LF_ISSET(DB_WRITELOCK)) { + if (DB_IS_READONLY(dbp)) + return (__db_rdonly(env, "DB->cursor")); + LF_CLR(DB_WRITELOCK); + } + + if (flags != 0) + return (__db_ferr(env, "DB->cursor", 0)); + + return (0); +} + +/* + * __db_del_pp -- + * DB->del pre/post processing. + * + * PUBLIC: int __db_del_pp __P((DB *, DB_TXN *, DBT *, u_int32_t)); + */ +int +__db_del_pp(dbp, txn, key, flags) + DB *dbp; + DB_TXN *txn; + DBT *key; + u_int32_t flags; +{ + DB_THREAD_INFO *ip; + ENV *env; + int handle_check, ret, t_ret, txn_local; + + env = dbp->env; + txn_local = 0; + + STRIP_AUTO_COMMIT(flags); + DB_ILLEGAL_BEFORE_OPEN(dbp, "DB->del"); + +#ifdef CONFIG_TEST + if (IS_REP_MASTER(env)) + DB_TEST_WAIT(env, env->test_check); +#endif + ENV_ENTER(env, ip); + XA_CHECK_TXN(ip, txn); + + /* Check for replication block. */ + handle_check = IS_ENV_REPLICATED(env); + if (handle_check && + (ret = __db_rep_enter(dbp, 1, 0, IS_REAL_TXN(txn))) != 0) { + handle_check = 0; + goto err; + } + + if ((ret = __db_del_arg(dbp, key, flags)) != 0) + goto err; + + /* Create local transaction as necessary. */ + if (IS_DB_AUTO_COMMIT(dbp, txn)) { + if ((ret = __txn_begin(env, ip, NULL, &txn, 0)) != 0) + goto err; + txn_local = 1; + } + + /* Check for consistent transaction usage. */ + if ((ret = __db_check_txn(dbp, txn, DB_LOCK_INVALIDID, 0)) != 0) + goto err; + + ret = __db_del(dbp, ip, txn, key, flags); + +err: if (txn_local && + (t_ret = __db_txn_auto_resolve(env, txn, 0, ret)) && ret == 0) + ret = t_ret; + + /* Release replication block. */ + if (handle_check && (t_ret = __env_db_rep_exit(env)) != 0 && ret == 0) + ret = t_ret; + ENV_LEAVE(env, ip); + __dbt_userfree(env, key, NULL, NULL); + return (ret); +} + +/* + * __db_del_arg -- + * Check DB->delete arguments. + */ +static int +__db_del_arg(dbp, key, flags) + DB *dbp; + DBT *key; + u_int32_t flags; +{ + ENV *env; + int ret; + + env = dbp->env; + + /* Check for changes to a read-only tree. */ + if (DB_IS_READONLY(dbp)) + return (__db_rdonly(env, "DB->del")); + + /* Check for invalid function flags. */ + switch (flags) { + case DB_CONSUME: + if (dbp->type != DB_QUEUE) + return (__db_ferr(env, "DB->del", 0)); + goto copy; + case DB_MULTIPLE: + case DB_MULTIPLE_KEY: + if (!F_ISSET(key, DB_DBT_BULK)) { + __db_errx(env, DB_STR("0581", + "DB->del with DB_MULTIPLE(_KEY) requires multiple key records")); + return (EINVAL); + } + /* FALL THROUGH */ + case 0: +copy: if ((ret = __dbt_usercopy(env, key)) != 0) + return (ret); + break; + default: + return (__db_ferr(env, "DB->del", 0)); + } + + return (0); +} + +/* + * __db_exists -- + * DB->exists implementation. + * + * PUBLIC: int __db_exists __P((DB *, DB_TXN *, DBT *, u_int32_t)); + */ +int +__db_exists(dbp, txn, key, flags) + DB *dbp; + DB_TXN *txn; + DBT *key; + u_int32_t flags; +{ + DBT data; + int ret; + + /* + * Most flag checking is done in the DB->get call, we only check for + * specific incompatibilities here. This saves making __get_arg + * aware of the exist method's API constraints. + */ + STRIP_AUTO_COMMIT(flags); + + if ((ret = __db_fchk(dbp->env, "DB->exists", flags, + DB_READ_COMMITTED | DB_READ_UNCOMMITTED | DB_RMW)) != 0) + return (ret); + + /* + * Configure a data DBT that returns no bytes so there's no copy + * of the data. + */ + memset(&data, 0, sizeof(data)); + data.dlen = 0; + data.flags = DB_DBT_PARTIAL | DB_DBT_USERMEM; + + return (dbp->get(dbp, txn, key, &data, flags)); +} + +/* + * db_fd_pp -- + * DB->fd pre/post processing. + * + * PUBLIC: int __db_fd_pp __P((DB *, int *)); + */ +int +__db_fd_pp(dbp, fdp) + DB *dbp; + int *fdp; +{ + DB_FH *fhp; + DB_THREAD_INFO *ip; + ENV *env; + int handle_check, ret, t_ret; + + env = dbp->env; + + DB_ILLEGAL_BEFORE_OPEN(dbp, "DB->fd"); + + ENV_ENTER(env, ip); + + /* Check for replication block. */ + handle_check = IS_ENV_REPLICATED(env); + if (handle_check && (ret = __db_rep_enter(dbp, 1, 0, 0)) != 0) + goto err; + + /* + * !!! + * There's no argument checking to be done. + * + * !!! + * The actual method call is simple, do it inline. + * + * XXX + * Truly spectacular layering violation. + */ + if ((ret = __mp_xxx_fh(dbp->mpf, &fhp)) == 0) { + if (fhp == NULL) { + *fdp = -1; + __db_errx(env, DB_STR("0582", + "Database does not have a valid file handle")); + ret = ENOENT; + } else + *fdp = fhp->fd; + } + + /* Release replication block. */ + if (handle_check && (t_ret = __env_db_rep_exit(env)) != 0 && ret == 0) + ret = t_ret; + +err: ENV_LEAVE(env, ip); + return (ret); +} + +/* + * __db_get_pp -- + * DB->get pre/post processing. + * + * PUBLIC: int __db_get_pp __P((DB *, DB_TXN *, DBT *, DBT *, u_int32_t)); + */ +int +__db_get_pp(dbp, txn, key, data, flags) + DB *dbp; + DB_TXN *txn; + DBT *key, *data; + u_int32_t flags; +{ + DB_THREAD_INFO *ip; + ENV *env; + u_int32_t mode; + int handle_check, ignore_lease, ret, t_ret, txn_local; + + env = dbp->env; + mode = 0; + txn_local = 0; + + STRIP_AUTO_COMMIT(flags); + DB_ILLEGAL_BEFORE_OPEN(dbp, "DB->get"); + + ignore_lease = LF_ISSET(DB_IGNORE_LEASE) ? 1 : 0; + LF_CLR(DB_IGNORE_LEASE); + + if ((ret = __db_get_arg(dbp, key, data, flags)) != 0) { + __dbt_userfree(env, key, NULL, data); + return (ret); + } + + ENV_ENTER(env, ip); + XA_CHECK_TXN(ip, txn); + + /* Check for replication block. */ + handle_check = IS_ENV_REPLICATED(env); + if (handle_check && + (ret = __db_rep_enter(dbp, 1, 0, IS_REAL_TXN(txn))) != 0) { + handle_check = 0; + goto err; + } + + if (LF_ISSET(DB_READ_UNCOMMITTED)) + mode = DB_READ_UNCOMMITTED; + else if ((flags & DB_OPFLAGS_MASK) == DB_CONSUME || + (flags & DB_OPFLAGS_MASK) == DB_CONSUME_WAIT) { + mode = DB_WRITELOCK; + if (IS_DB_AUTO_COMMIT(dbp, txn)) { + if ((ret = __txn_begin(env, ip, NULL, &txn, 0)) != 0) + goto err; + txn_local = 1; + } + } + + /* Check for consistent transaction usage. */ + if ((ret = __db_check_txn(dbp, txn, DB_LOCK_INVALIDID, + mode == DB_WRITELOCK || LF_ISSET(DB_RMW) ? 0 : 1)) != 0) + goto err; + + ret = __db_get(dbp, ip, txn, key, data, flags); + /* + * Check for master leases. + */ + if (ret == 0 && + IS_REP_MASTER(env) && IS_USING_LEASES(env) && !ignore_lease) + ret = __rep_lease_check(env, 1); + +err: if (txn_local && + (t_ret = __db_txn_auto_resolve(env, txn, 0, ret)) && ret == 0) + ret = t_ret; + + /* Release replication block. */ + if (handle_check && (t_ret = __env_db_rep_exit(env)) != 0 && ret == 0) + ret = t_ret; + + ENV_LEAVE(env, ip); + __dbt_userfree(env, key, NULL, data); + return (ret); +} + +/* + * __db_get -- + * DB->get. + * + * PUBLIC: int __db_get __P((DB *, + * PUBLIC: DB_THREAD_INFO *, DB_TXN *, DBT *, DBT *, u_int32_t)); + */ +int +__db_get(dbp, ip, txn, key, data, flags) + DB *dbp; + DB_THREAD_INFO *ip; + DB_TXN *txn; + DBT *key, *data; + u_int32_t flags; +{ + DBC *dbc; + u_int32_t mode; + int ret, t_ret; + + /* + * The DB_CURSOR_TRANSIENT flag indicates that we're just doing a single + * operation with this cursor, and that in case of error we don't need + * to restore it to its old position. Thus, we can perform the get + * without duplicating the cursor, saving some cycles in this common + * case. + */ + mode = DB_CURSOR_TRANSIENT; + if (LF_ISSET(DB_READ_UNCOMMITTED)) { + mode |= DB_READ_UNCOMMITTED; + LF_CLR(DB_READ_UNCOMMITTED); + } else if (LF_ISSET(DB_READ_COMMITTED)) { + mode |= DB_READ_COMMITTED; + LF_CLR(DB_READ_COMMITTED); + } else if ((flags & DB_OPFLAGS_MASK) == DB_CONSUME || + (flags & DB_OPFLAGS_MASK) == DB_CONSUME_WAIT) + mode |= DB_WRITELOCK; + + if ((ret = __db_cursor(dbp, ip, txn, &dbc, mode)) != 0) + return (ret); + + DEBUG_LREAD(dbc, txn, "DB->get", key, NULL, flags); + + /* + * The semantics of bulk gets are different for DB->get vs DBC->get. + * Mark the cursor so the low-level bulk get routines know which + * behavior we want. + */ + F_SET(dbc, DBC_FROM_DB_GET); + + /* + * SET_RET_MEM indicates that if key and/or data have no DBT + * flags set and DB manages the returned-data memory, that memory + * will belong to this handle, not to the underlying cursor. + */ + SET_RET_MEM(dbc, dbp); + + if (LF_ISSET(~(DB_RMW | DB_MULTIPLE)) == 0) + LF_SET(DB_SET); + +#ifdef HAVE_PARTITION + if (F_ISSET(dbc, DBC_PARTITIONED)) + ret = __partc_get(dbc, key, data, flags); + else +#endif + ret = __dbc_get(dbc, key, data, flags); + + if (dbc != NULL && (t_ret = __dbc_close(dbc)) != 0 && ret == 0) + ret = t_ret; + + return (ret); +} + +/* + * __db_get_arg -- + * DB->get argument checking, used by both DB->get and DB->pget. + */ +static int +__db_get_arg(dbp, key, data, flags) + const DB *dbp; + DBT *key, *data; + u_int32_t flags; +{ + ENV *env; + int dirty, multi, ret; + + env = dbp->env; + + /* + * Check for read-modify-write validity. DB_RMW doesn't make sense + * with CDB cursors since if you're going to write the cursor, you + * had to create it with DB_WRITECURSOR. Regardless, we check for + * LOCKING_ON and not STD_LOCKING, as we don't want to disallow it. + * If this changes, confirm that DB does not itself set the DB_RMW + * flag in a path where CDB may have been configured. + */ + dirty = 0; + if (LF_ISSET(DB_READ_COMMITTED | DB_READ_UNCOMMITTED | DB_RMW)) { + if (!LOCKING_ON(env)) + return (__db_fnl(env, "DB->get")); + if ((ret = __db_fcchk(env, "DB->get", + flags, DB_READ_UNCOMMITTED, DB_READ_COMMITTED)) != 0) + return (ret); + if (LF_ISSET(DB_READ_COMMITTED | DB_READ_UNCOMMITTED)) + dirty = 1; + LF_CLR(DB_READ_COMMITTED | DB_READ_UNCOMMITTED | DB_RMW); + } + + multi = 0; + if (LF_ISSET(DB_MULTIPLE | DB_MULTIPLE_KEY)) { + if (LF_ISSET(DB_MULTIPLE_KEY)) + goto multi_err; + multi = LF_ISSET(DB_MULTIPLE) ? 1 : 0; + LF_CLR(DB_MULTIPLE); + } + + /* Check for invalid function flags. */ + switch (flags) { + case DB_GET_BOTH: + if ((ret = __dbt_usercopy(env, data)) != 0) + return (ret); + /* FALLTHROUGH */ + case 0: + if ((ret = __dbt_usercopy(env, key)) != 0) { + __dbt_userfree(env, key, NULL, data); + return (ret); + } + break; + case DB_SET_RECNO: + if (!F_ISSET(dbp, DB_AM_RECNUM)) + goto err; + if ((ret = __dbt_usercopy(env, key)) != 0) + return (ret); + break; + case DB_CONSUME: + case DB_CONSUME_WAIT: + if (DB_IS_READONLY(dbp)) + return (__db_rdonly(env, + "DB->get CONSUME/CONSUME_WAIT")); + if (dirty) { + __db_errx(env, DB_STR_A("0583", + "%s is not supported with DB_CONSUME or DB_CONSUME_WAIT", + "%s"), LF_ISSET(DB_READ_UNCOMMITTED) ? + "DB_READ_UNCOMMITTED" : "DB_READ_COMMITTED"); + return (EINVAL); + } + if (multi) +multi_err: return (__db_ferr(env, "DB->get", 1)); + if (dbp->type == DB_QUEUE) + break; + /* FALLTHROUGH */ + default: +err: return (__db_ferr(env, "DB->get", 0)); + } + + /* + * Check for invalid key/data flags. + */ + if ((ret = + __dbt_ferr(dbp, "key", key, DB_RETURNS_A_KEY(dbp, flags))) != 0) + return (ret); + + if (F_ISSET(data, DB_DBT_READONLY)) { + __db_errx(env, DB_STR("0584", + "DB_DBT_READONLY should not be set on data DBT.")); + return (EINVAL); + } + if ((ret = __dbt_ferr(dbp, "data", data, 1)) != 0) + return (ret); + + if (multi) { + if (!F_ISSET(data, DB_DBT_USERMEM)) { + __db_errx(env, DB_STR("0585", + "DB_MULTIPLE requires DB_DBT_USERMEM be set")); + return (EINVAL); + } + if (F_ISSET(key, DB_DBT_PARTIAL) || + F_ISSET(data, DB_DBT_PARTIAL)) { + __db_errx(env, DB_STR("0586", + "DB_MULTIPLE does not support DB_DBT_PARTIAL")); + return (EINVAL); + } + if (data->ulen < 1024 || + data->ulen < dbp->pgsize || data->ulen % 1024 != 0) { + __db_errx(env, DB_STR("0587", + "DB_MULTIPLE buffers must be aligned, " + "at least page size and multiples of 1KB")); + return (EINVAL); + } + } + + /* Check invalid partial key. */ + if (F_ISSET(key, DB_DBT_PARTIAL) && !(LF_ISSET(DB_CONSUME) && + LF_ISSET(DB_CONSUME_WAIT) && LF_ISSET(DB_SET_RECNO))) { + __db_errx(env, DB_STR("0708", + "Invalid positioning flag combined with DB_DBT_PARTIAL")); + return (EINVAL); + } + + return (0); +} + +/* + * __db_key_range_pp -- + * DB->key_range pre/post processing. + * + * PUBLIC: int __db_key_range_pp + * PUBLIC: __P((DB *, DB_TXN *, DBT *, DB_KEY_RANGE *, u_int32_t)); + */ +int +__db_key_range_pp(dbp, txn, key, kr, flags) + DB *dbp; + DB_TXN *txn; + DBT *key; + DB_KEY_RANGE *kr; + u_int32_t flags; +{ + DBC *dbc; + DB_THREAD_INFO *ip; + ENV *env; + int handle_check, ret, t_ret; + + env = dbp->env; + + DB_ILLEGAL_BEFORE_OPEN(dbp, "DB->key_range"); + + /* + * !!! + * The actual argument checking is simple, do it inline, outside of + * the replication block. + */ + if (flags != 0) + return (__db_ferr(env, "DB->key_range", 0)); + + ENV_ENTER(env, ip); + XA_CHECK_TXN(ip, txn); + + /* Check for replication block. */ + handle_check = IS_ENV_REPLICATED(env); + if (handle_check && + (ret = __db_rep_enter(dbp, 1, 0, IS_REAL_TXN(txn))) != 0) { + handle_check = 0; + goto err; + } + + /* Check for consistent transaction usage. */ + if ((ret = __db_check_txn(dbp, txn, DB_LOCK_INVALIDID, 1)) != 0) + goto err; + + /* + * !!! + * The actual method call is simple, do it inline. + */ + switch (dbp->type) { + case DB_BTREE: + if ((ret = __dbt_usercopy(env, key)) != 0) + goto err; + + /* Acquire a cursor. */ + if ((ret = __db_cursor(dbp, ip, txn, &dbc, 0)) != 0) { + __dbt_userfree(env, key, NULL, NULL); + break; + } + + DEBUG_LWRITE(dbc, NULL, "bam_key_range", NULL, NULL, 0); +#ifdef HAVE_PARTITION + if (DB_IS_PARTITIONED(dbp)) + ret = __part_key_range(dbc, key, kr, flags); + else +#endif + ret = __bam_key_range(dbc, key, kr, flags); + + if ((t_ret = __dbc_close(dbc)) != 0 && ret == 0) + ret = t_ret; + __dbt_userfree(env, key, NULL, NULL); + break; + case DB_HASH: + case DB_QUEUE: + case DB_RECNO: + ret = __dbh_am_chk(dbp, DB_OK_BTREE); + break; + case DB_UNKNOWN: + default: + ret = __db_unknown_type(env, "DB->key_range", dbp->type); + break; + } + +err: /* Release replication block. */ + if (handle_check && (t_ret = __env_db_rep_exit(env)) != 0 && ret == 0) + ret = t_ret; + + ENV_LEAVE(env, ip); + return (ret); +} + +/* + * __db_open_pp -- + * DB->open pre/post processing. + * + * PUBLIC: int __db_open_pp __P((DB *, DB_TXN *, + * PUBLIC: const char *, const char *, DBTYPE, u_int32_t, int)); + */ +int +__db_open_pp(dbp, txn, fname, dname, type, flags, mode) + DB *dbp; + DB_TXN *txn; + const char *fname, *dname; + DBTYPE type; + u_int32_t flags; + int mode; +{ + DB_THREAD_INFO *ip; + ENV *env; + int handle_check, nosync, remove_me, ret, t_ret, txn_local; + + env = dbp->env; + nosync = 1; + handle_check = remove_me = txn_local = 0; + + ENV_ENTER(env, ip); + + /* + * Save the flags. We do this here because we don't pass all of the + * flags down into the actual DB->open method call, we strip + * DB_AUTO_COMMIT at this layer. + */ + dbp->open_flags = flags; + + /* Save the current DB handle flags for refresh. */ + dbp->orig_flags = dbp->flags; + + /* Check for replication block. */ + handle_check = IS_ENV_REPLICATED(env); + if (handle_check && + (ret = __db_rep_enter(dbp, 1, 0, IS_REAL_TXN(txn))) != 0) { + handle_check = 0; + goto err; + } + + /* + * A replication client can't create a database, but it's convenient to + * allow a repmgr application to specify DB_CREATE anyway. Thus for + * such an application the meaning of DB_CREATE becomes "create it if + * I'm a master, and otherwise ignore the flag". A repmgr application + * running as master can't be sure that it won't spontaneously become a + * client, so there's a race condition. + */ + if (IS_REP_CLIENT(env) && !F_ISSET(dbp, DB_AM_NOT_DURABLE)) + LF_CLR(DB_CREATE); + + /* + * Create local transaction as necessary, check for consistent + * transaction usage. + */ + if (IS_ENV_AUTO_COMMIT(env, txn, flags)) { + if ((ret = __db_txn_auto_init(env, ip, &txn)) != 0) + goto err; + txn_local = 1; + } else if (txn != NULL && !TXN_ON(env) && + (!CDB_LOCKING(env) || !F_ISSET(txn, TXN_FAMILY))) { + ret = __db_not_txn_env(env); + goto err; + } + LF_CLR(DB_AUTO_COMMIT); + + /* + * We check arguments after possibly creating a local transaction, + * which is unusual -- the reason is some flags are illegal if any + * kind of transaction is in effect. + */ + if ((ret = __db_open_arg(dbp, txn, fname, dname, type, flags)) == 0) + if ((ret = __db_open(dbp, ip, txn, fname, dname, type, + flags, mode, PGNO_BASE_MD)) != 0) + goto txnerr; + + /* + * You can open the database that describes the subdatabases in the + * rest of the file read-only. The content of each key's data is + * unspecified and applications should never be adding new records + * or updating existing records. However, during recovery, we need + * to open these databases R/W so we can redo/undo changes in them. + * Likewise, we need to open master databases read/write during + * rename and remove so we can be sure they're fully sync'ed, so + * we provide an override flag for the purpose. + */ + if (dname == NULL && !IS_RECOVERING(env) && !LF_ISSET(DB_RDONLY) && + !LF_ISSET(DB_RDWRMASTER) && F_ISSET(dbp, DB_AM_SUBDB)) { + __db_errx(env, DB_STR("0590", + "files containing multiple databases may only be opened read-only")); + ret = EINVAL; + goto txnerr; + } + + /* + * Success: file creations have to be synchronous, otherwise we don't + * care. + */ + if (F_ISSET(dbp, DB_AM_CREATED | DB_AM_CREATED_MSTR)) + nosync = 0; + + /* Success: don't discard the file on close. */ + F_CLR(dbp, DB_AM_DISCARD | DB_AM_CREATED | DB_AM_CREATED_MSTR); + + /* + * If not transactional, remove the databases/subdatabases if it is + * persistent. If we're transactional, the child transaction abort + * cleans up. + */ +txnerr: if (ret != 0 && !IS_REAL_TXN(txn)) { + remove_me = (F_ISSET(dbp, DB_AM_CREATED) && + (fname != NULL || dname != NULL)) ? 1 : 0; + if (F_ISSET(dbp, DB_AM_CREATED_MSTR) || + (dname == NULL && remove_me)) + /* Remove file. */ + (void)__db_remove_int(dbp, + ip, txn, fname, NULL, DB_FORCE); + else if (remove_me) + /* Remove subdatabase. */ + (void)__db_remove_int(dbp, + ip, txn, fname, dname, DB_FORCE); + } + + if (txn_local && (t_ret = + __db_txn_auto_resolve(env, txn, nosync, ret)) && ret == 0) + ret = t_ret; + +err: /* Release replication block. */ + if (handle_check && (t_ret = __env_db_rep_exit(env)) != 0 && ret == 0) + ret = t_ret; + + ENV_LEAVE(env, ip); + return (ret); +} + +/* + * __db_open_arg -- + * Check DB->open arguments. + */ +static int +__db_open_arg(dbp, txn, fname, dname, type, flags) + DB *dbp; + DB_TXN *txn; + const char *fname, *dname; + DBTYPE type; + u_int32_t flags; +{ + ENV *env; + u_int32_t ok_flags; + int ret; + + env = dbp->env; + + /* Validate arguments. */ +#undef OKFLAGS +#define OKFLAGS \ + (DB_AUTO_COMMIT | DB_CREATE | DB_EXCL | DB_FCNTL_LOCKING | \ + DB_MULTIVERSION | DB_NOMMAP | DB_NO_AUTO_COMMIT | DB_RDONLY | \ + DB_RDWRMASTER | DB_READ_UNCOMMITTED | DB_THREAD | DB_TRUNCATE) + if ((ret = __db_fchk(env, "DB->open", flags, OKFLAGS)) != 0) + return (ret); + if (LF_ISSET(DB_EXCL) && !LF_ISSET(DB_CREATE)) + return (__db_ferr(env, "DB->open", 1)); + if (LF_ISSET(DB_RDONLY) && LF_ISSET(DB_CREATE)) + return (__db_ferr(env, "DB->open", 1)); + +#ifdef HAVE_VXWORKS + if (LF_ISSET(DB_TRUNCATE)) { + __db_errx(env, DB_STR("0591", + "DB_TRUNCATE not supported on VxWorks")); + return (DB_OPNOTSUP); + } +#endif + switch (type) { + case DB_UNKNOWN: + if (LF_ISSET(DB_CREATE|DB_TRUNCATE)) { + __db_errx(env, DB_STR("0592", + "DB_UNKNOWN type specified with DB_CREATE or DB_TRUNCATE")); + return (EINVAL); + } + ok_flags = 0; + break; + case DB_BTREE: + ok_flags = DB_OK_BTREE; + break; + case DB_HASH: +#ifndef HAVE_HASH + return (__db_no_hash_am(env)); +#endif + ok_flags = DB_OK_HASH; + break; + case DB_HEAP: + ok_flags = DB_OK_HEAP; + break; + case DB_QUEUE: +#ifndef HAVE_QUEUE + return (__db_no_queue_am(env)); +#endif + ok_flags = DB_OK_QUEUE; + break; + case DB_RECNO: + ok_flags = DB_OK_RECNO; + break; + default: + __db_errx(env, DB_STR_A("0593", + "unknown type: %lu", "%lu"), (u_long)type); + return (EINVAL); + } + if (ok_flags) + DB_ILLEGAL_METHOD(dbp, ok_flags); + + /* The environment may have been created, but never opened. */ + if (!F_ISSET(env, ENV_DBLOCAL | ENV_OPEN_CALLED)) { + __db_errx(env, DB_STR("0594", + "database environment not yet opened")); + return (EINVAL); + } + + /* + * Historically, you could pass in an environment that didn't have a + * mpool, and DB would create a private one behind the scenes. This + * no longer works. + */ + if (!F_ISSET(env, ENV_DBLOCAL) && !MPOOL_ON(env)) { + __db_errx(env, DB_STR("0595", + "environment did not include a memory pool")); + return (EINVAL); + } + + /* + * You can't specify threads during DB->open if subsystems in the + * environment weren't configured with them. + */ + if (LF_ISSET(DB_THREAD) && !F_ISSET(env, ENV_DBLOCAL | ENV_THREAD)) { + __db_errx(env, DB_STR("0596", + "environment not created using DB_THREAD")); + return (EINVAL); + } + + /* Exclusive database handles cannot be threaded.*/ + if (LF_ISSET(DB_THREAD) && F2_ISSET(dbp, DB2_AM_EXCL)) { + __db_errx(env, DB_STR("0744", + "Exclusive database handles cannot be threaded.")); + return (EINVAL); + } + + /* Exclusive database handles require transactional environments. */ + if (F2_ISSET(dbp, DB2_AM_EXCL) && !TXN_ON(env)) { + __db_errx(env, DB_STR("0745", + "Exclusive database handles require transactional environments.")); + return (EINVAL); + } + + /* Replication clients cannot open exclusive database handles. */ + if (F2_ISSET(dbp, DB2_AM_EXCL) && IS_REP_CLIENT(env)) { + __db_errx(env, DB_STR("0746", +"Exclusive database handles cannot be opened on replication clients.")); + return (EINVAL); + } + + /* DB_MULTIVERSION requires a database configured for transactions. */ + if (LF_ISSET(DB_MULTIVERSION) && !IS_REAL_TXN(txn)) { + __db_errx(env, DB_STR("0597", + "DB_MULTIVERSION illegal without a transaction specified")); + return (EINVAL); + } + + if (LF_ISSET(DB_MULTIVERSION) && type == DB_QUEUE) { + __db_errx(env, DB_STR("0598", + "DB_MULTIVERSION illegal with queue databases")); + return (EINVAL); + } + + /* DB_TRUNCATE is neither transaction recoverable nor lockable. */ + if (LF_ISSET(DB_TRUNCATE) && (LOCKING_ON(env) || txn != NULL)) { + __db_errx(env, DB_STR_A("0599", + "DB_TRUNCATE illegal with %s specified", "%s"), + LOCKING_ON(env) ? "locking" : "transactions"); + return (EINVAL); + } + + /* Subdatabase checks. */ + if (dname != NULL) { + /* QAM can only be done on in-memory subdatabases. */ + if (type == DB_QUEUE && fname != NULL) { + __db_errx(env, DB_STR("0600", + "Queue databases must be one-per-file")); + return (EINVAL); + } + + /* + * Named in-memory databases can't support certain flags, + * so check here. + */ + if (fname == NULL) + F_CLR(dbp, DB_AM_CHKSUM | DB_AM_ENCRYPT); + } + + return (0); +} + +/* + * __db_pget_pp -- + * DB->pget pre/post processing. + * + * PUBLIC: int __db_pget_pp + * PUBLIC: __P((DB *, DB_TXN *, DBT *, DBT *, DBT *, u_int32_t)); + */ +int +__db_pget_pp(dbp, txn, skey, pkey, data, flags) + DB *dbp; + DB_TXN *txn; + DBT *skey, *pkey, *data; + u_int32_t flags; +{ + DB_THREAD_INFO *ip; + ENV *env; + int handle_check, ignore_lease, ret, t_ret; + + env = dbp->env; + + DB_ILLEGAL_BEFORE_OPEN(dbp, "DB->pget"); + + ignore_lease = LF_ISSET(DB_IGNORE_LEASE) ? 1 : 0; + LF_CLR(DB_IGNORE_LEASE); + + if ((ret = __db_pget_arg(dbp, pkey, flags)) != 0 || + (ret = __db_get_arg(dbp, skey, data, flags)) != 0) { + __dbt_userfree(env, skey, pkey, data); + return (ret); + } + + ENV_ENTER(env, ip); + XA_CHECK_TXN(ip, txn); + + /* Check for replication block. */ + handle_check = IS_ENV_REPLICATED(env); + if (handle_check && + (ret = __db_rep_enter(dbp, 1, 0, IS_REAL_TXN(txn))) != 0) { + handle_check = 0; + goto err; + } + + ret = __db_pget(dbp, ip, txn, skey, pkey, data, flags); + /* + * Check for master leases. + */ + if (ret == 0 && + IS_REP_MASTER(env) && IS_USING_LEASES(env) && !ignore_lease) + ret = __rep_lease_check(env, 1); + +err: /* Release replication block. */ + if (handle_check && (t_ret = __env_db_rep_exit(env)) != 0 && ret == 0) + ret = t_ret; + + ENV_LEAVE(env, ip); + __dbt_userfree(env, skey, pkey, data); + return (ret); +} + +/* + * __db_pget -- + * DB->pget. + * + * PUBLIC: int __db_pget __P((DB *, + * PUBLIC: DB_THREAD_INFO *, DB_TXN *, DBT *, DBT *, DBT *, u_int32_t)); + */ +int +__db_pget(dbp, ip, txn, skey, pkey, data, flags) + DB *dbp; + DB_THREAD_INFO *ip; + DB_TXN *txn; + DBT *skey, *pkey, *data; + u_int32_t flags; +{ + DBC *dbc; + u_int32_t mode; + int ret, t_ret; + + mode = DB_CURSOR_TRANSIENT; + if (LF_ISSET(DB_READ_UNCOMMITTED)) { + mode |= DB_READ_UNCOMMITTED; + LF_CLR(DB_READ_UNCOMMITTED); + } else if (LF_ISSET(DB_READ_COMMITTED)) { + mode |= DB_READ_COMMITTED; + LF_CLR(DB_READ_COMMITTED); + } + + if ((ret = __db_cursor(dbp, ip, txn, &dbc, mode)) != 0) + return (ret); + + SET_RET_MEM(dbc, dbp); + + DEBUG_LREAD(dbc, txn, "__db_pget", skey, NULL, flags); + + /* + * !!! + * The actual method call is simple, do it inline. + * + * The underlying cursor pget will fill in a default DBT for null + * pkeys, and use the cursor's returned-key memory internally to + * store any intermediate primary keys. However, we've just set + * the returned-key memory to the DB handle's key memory, which + * is unsafe to use if the DB handle is threaded. If the pkey + * argument is NULL, use the DBC-owned returned-key memory + * instead; it'll go away when we close the cursor before we + * return, but in this case that's just fine, as we're not + * returning the primary key. + */ + if (pkey == NULL) + dbc->rkey = &dbc->my_rkey; + + /* + * The cursor is just a perfectly ordinary secondary database cursor. + * Call its c_pget() method to do the dirty work. + */ + if (flags == 0 || flags == DB_RMW) + flags |= DB_SET; + + ret = __dbc_pget(dbc, skey, pkey, data, flags); + + if ((t_ret = __dbc_close(dbc)) != 0 && ret == 0) + ret = t_ret; + + return (ret); +} + +/* + * __db_pget_arg -- + * Check DB->pget arguments. + */ +static int +__db_pget_arg(dbp, pkey, flags) + DB *dbp; + DBT *pkey; + u_int32_t flags; +{ + ENV *env; + int ret; + + env = dbp->env; + + if (!F_ISSET(dbp, DB_AM_SECONDARY)) { + __db_errx(env, DB_STR("0601", + "DB->pget may only be used on secondary indices")); + return (EINVAL); + } + + if (LF_ISSET(DB_MULTIPLE | DB_MULTIPLE_KEY)) { + __db_errx(env,DB_STR("0602", +"DB_MULTIPLE and DB_MULTIPLE_KEY may not be used on secondary indices")); + return (EINVAL); + } + + /* DB_CONSUME makes no sense on a secondary index. */ + LF_CLR(DB_READ_COMMITTED | DB_READ_UNCOMMITTED | DB_RMW); + switch (flags) { + case DB_CONSUME: + case DB_CONSUME_WAIT: + return (__db_ferr(env, "DB->pget", 0)); + default: + /* __db_get_arg will catch the rest. */ + break; + } + + /* + * We allow the pkey field to be NULL, so that we can make the + * two-DBT get calls into wrappers for the three-DBT ones. + */ + if (pkey != NULL && + (ret = __dbt_ferr(dbp, "primary key", pkey, 1)) != 0) + return (ret); + + /* Check invalid partial pkey. */ + if (pkey != NULL && F_ISSET(pkey, DB_DBT_PARTIAL)) { + __db_errx(env, DB_STR("0709", + "The primary key returned by pget can't be partial")); + return (EINVAL); + } + + if (flags == DB_GET_BOTH) { + /* The pkey field can't be NULL if we're doing a DB_GET_BOTH. */ + if (pkey == NULL) { + __db_errx(env, DB_STR("0603", + "DB_GET_BOTH on a secondary index requires a primary key")); + return (EINVAL); + } + if ((ret = __dbt_usercopy(env, pkey)) != 0) + return (ret); + } + + return (0); +} + +/* + * __db_put_pp -- + * DB->put pre/post processing. + * + * PUBLIC: int __db_put_pp __P((DB *, DB_TXN *, DBT *, DBT *, u_int32_t)); + */ +int +__db_put_pp(dbp, txn, key, data, flags) + DB *dbp; + DB_TXN *txn; + DBT *key, *data; + u_int32_t flags; +{ + DB_THREAD_INFO *ip; + ENV *env; + int handle_check, ret, txn_local, t_ret; + + env = dbp->env; + txn_local = 0; + + STRIP_AUTO_COMMIT(flags); + DB_ILLEGAL_BEFORE_OPEN(dbp, "DB->put"); + + if ((ret = __db_put_arg(dbp, key, data, flags)) != 0) + return (ret); + + ENV_ENTER(env, ip); + XA_CHECK_TXN(ip, txn); + + /* Check for replication block. */ + handle_check = IS_ENV_REPLICATED(env); + if (handle_check && + (ret = __db_rep_enter(dbp, 1, 0, IS_REAL_TXN(txn))) != 0) { + handle_check = 0; + goto err; + } + + /* Create local transaction as necessary. */ + if (IS_DB_AUTO_COMMIT(dbp, txn)) { + if ((ret = __txn_begin(env, ip, NULL, &txn, 0)) != 0) + goto err; + txn_local = 1; + } + + /* Check for consistent transaction usage. */ + if ((ret = __db_check_txn(dbp, txn, DB_LOCK_INVALIDID, 0)) != 0) + goto err; + + ret = __db_put(dbp, ip, txn, key, data, flags); + +err: if (txn_local && + (t_ret = __db_txn_auto_resolve(env, txn, 0, ret)) && ret == 0) + ret = t_ret; + + /* Release replication block. */ + if (handle_check && (t_ret = __env_db_rep_exit(env)) != 0 && ret == 0) + ret = t_ret; + + ENV_LEAVE(env, ip); + __dbt_userfree(env, key, NULL, data); + return (ret); +} + +/* + * __db_put_arg -- + * Check DB->put arguments. + */ +static int +__db_put_arg(dbp, key, data, flags) + DB *dbp; + DBT *key, *data; + u_int32_t flags; +{ + ENV *env; + int ret, returnkey; + + env = dbp->env; + returnkey = 0; + + /* Check for changes to a read-only tree. */ + if (DB_IS_READONLY(dbp)) + return (__db_rdonly(env, "DB->put")); + + /* Check for puts on a secondary. */ + if (F_ISSET(dbp, DB_AM_SECONDARY)) { + __db_errx(env, DB_STR("0604", + "DB->put forbidden on secondary indices")); + return (EINVAL); + } + + if (LF_ISSET(DB_MULTIPLE_KEY | DB_MULTIPLE)) { + if (LF_ISSET(DB_MULTIPLE) && LF_ISSET(DB_MULTIPLE_KEY)) + goto err; + + switch (LF_ISSET(DB_OPFLAGS_MASK)) { + case 0: + case DB_OVERWRITE_DUP: + break; + default: + __db_errx(env, DB_STR("0605", +"DB->put: DB_MULTIPLE(_KEY) can only be combined with DB_OVERWRITE_DUP")); + return (EINVAL); + } + + if (!F_ISSET(key, DB_DBT_BULK)) { + __db_errx(env, DB_STR("0606", + "DB->put with DB_MULTIPLE(_KEY) requires a bulk key buffer")); + return (EINVAL); + } + } + if (LF_ISSET(DB_MULTIPLE)) { + if (!F_ISSET(data, DB_DBT_BULK)) { + __db_errx(env, DB_STR("0607", + "DB->put with DB_MULTIPLE requires a bulk data buffer")); + return (EINVAL); + } + } + + /* Check for invalid function flags. */ + switch (LF_ISSET(DB_OPFLAGS_MASK)) { + case 0: + case DB_NOOVERWRITE: + case DB_OVERWRITE_DUP: + break; + case DB_APPEND: + if (dbp->type != DB_RECNO && + dbp->type != DB_QUEUE && dbp->type != DB_HEAP) + goto err; + returnkey = 1; + break; + case DB_NODUPDATA: + if (F_ISSET(dbp, DB_AM_DUPSORT)) + break; + /* FALLTHROUGH */ + default: +err: return (__db_ferr(env, "DB->put", 0)); + } + + /* + * Check for invalid key/data flags. The key may reasonably be NULL + * if DB_APPEND is set and the application doesn't care about the + * returned key. + */ + if (((returnkey && key != NULL) || !returnkey) && + (ret = __dbt_ferr(dbp, "key", key, returnkey)) != 0) + return (ret); + if (!LF_ISSET(DB_MULTIPLE_KEY) && + (ret = __dbt_ferr(dbp, "data", data, 0)) != 0) + return (ret); + + /* + * The key parameter should not be NULL or have the "partial" flag set + * in a put call unless the user doesn't care about a key value we'd + * return. The user tells us they don't care about the returned key by + * setting the key parameter to NULL or configuring the key DBT to not + * return any information. (Returned keys from a put are always record + * numbers, and returning part of a record number doesn't make sense: + * only accept a partial return if the length returned is 0.) + */ + if ((returnkey && + key != NULL && F_ISSET(key, DB_DBT_PARTIAL) && key->dlen != 0) || + (!returnkey && F_ISSET(key, DB_DBT_PARTIAL))) + return (__db_ferr(env, "key DBT", 0)); + + /* Check for partial puts in the presence of duplicates. */ + if (data != NULL && F_ISSET(data, DB_DBT_PARTIAL) && + (F_ISSET(dbp, DB_AM_DUP) || F_ISSET(key, DB_DBT_DUPOK))) { + __db_errx(env, DB_STR("0608", +"a partial put in the presence of duplicates requires a cursor operation")); + return (EINVAL); + } + + if ((flags != DB_APPEND && (ret = __dbt_usercopy(env, key)) != 0) || + (!LF_ISSET(DB_MULTIPLE_KEY) && + (ret = __dbt_usercopy(env, data)) != 0)) + return (ret); + + return (0); +} + +/* + * __db_sync_pp -- + * DB->sync pre/post processing. + * + * PUBLIC: int __db_sync_pp __P((DB *, u_int32_t)); + */ +int +__db_sync_pp(dbp, flags) + DB *dbp; + u_int32_t flags; +{ + DB_THREAD_INFO *ip; + ENV *env; + int handle_check, ret, t_ret; + + env = dbp->env; + + DB_ILLEGAL_BEFORE_OPEN(dbp, "DB->sync"); + + /* + * !!! + * The actual argument checking is simple, do it inline, outside of + * the replication block. + */ + if (flags != 0) + return (__db_ferr(env, "DB->sync", 0)); + + ENV_ENTER(env, ip); + + /* Check for replication block. */ + handle_check = IS_ENV_REPLICATED(env); + if (handle_check && (ret = __db_rep_enter(dbp, 1, 0, 0)) != 0) { + handle_check = 0; + goto err; + } + + ret = __db_sync(dbp); + + /* Release replication block. */ + if (handle_check && (t_ret = __env_db_rep_exit(env)) != 0 && ret == 0) + ret = t_ret; + +err: ENV_LEAVE(env, ip); + return (ret); +} + +/* + * __dbc_close_pp -- + * DBC->close pre/post processing. + * + * PUBLIC: int __dbc_close_pp __P((DBC *)); + */ +int +__dbc_close_pp(dbc) + DBC *dbc; +{ + DB *dbp; + DB_THREAD_INFO *ip; + ENV *env; + DB_TXN *txn; + int handle_check, ret, t_ret; + + dbp = dbc->dbp; + env = dbp->env; + txn = dbc->txn; + + /* + * If the cursor is already closed we have a serious problem, and we + * assume that the cursor isn't on the active queue. Don't do any of + * the remaining cursor close processing. + */ + if (!F_ISSET(dbc, DBC_ACTIVE)) { + __db_errx(env, DB_STR("0616", + "Closing already-closed cursor")); + return (EINVAL); + } + + ENV_ENTER(env, ip); + + /* Check for replication block. */ + handle_check = !IS_REAL_TXN(dbc->txn) && IS_ENV_REPLICATED(env); + + /* Unregister the cursor from its transaction, regardless of ret. */ + if (txn != NULL) { + TAILQ_REMOVE(&(txn->my_cursors), dbc, txn_cursors); + dbc->txn_cursors.tqe_next = NULL; + dbc->txn_cursors.tqe_prev = NULL; + } else { + DB_ASSERT(env, dbc->txn_cursors.tqe_next == NULL && + dbc->txn_cursors.tqe_prev == NULL); + } + + ret = __dbc_close(dbc); + + /* Release replication block. */ + if (handle_check && + (t_ret = __op_rep_exit(env)) != 0 && ret == 0) + ret = t_ret; + + ENV_LEAVE(env, ip); + return (ret); +} + +/* + * __dbc_cmp_pp -- + * DBC->cmp pre/post processing. + * + * PUBLIC: int __dbc_cmp_pp __P((DBC *, DBC *, int*, u_int32_t)); + */ +int +__dbc_cmp_pp(dbc, other_cursor, result, flags) + DBC *dbc, *other_cursor; + int *result; + u_int32_t flags; +{ + DB *dbp, *odbp; + DB_THREAD_INFO *ip; + ENV *env; + int ret; + + dbp = dbc->dbp; + odbp = other_cursor->dbp; + env = dbp->env; + + if (flags != 0) + return (__db_ferr(env, "DBcursor->cmp", 0)); + + if (other_cursor == NULL) { + __db_errx(env, DB_STR("0617", + "DBcursor->cmp dbc pointer must not be null")); + return (EINVAL); + } + + if (dbp != odbp) { + __db_errx(env, DB_STR("0618", +"DBcursor->cmp both cursors must refer to the same database.")); + return (EINVAL); + } + + ENV_ENTER(env, ip); + ret = __dbc_cmp(dbc, other_cursor, result); + ENV_LEAVE(env, ip); + return (ret); +} + +/* + * __dbc_count_pp -- + * DBC->count pre/post processing. + * + * PUBLIC: int __dbc_count_pp __P((DBC *, db_recno_t *, u_int32_t)); + */ +int +__dbc_count_pp(dbc, recnop, flags) + DBC *dbc; + db_recno_t *recnop; + u_int32_t flags; +{ + DB *dbp; + DB_THREAD_INFO *ip; + ENV *env; + int ret; + + dbp = dbc->dbp; + env = dbp->env; + + /* + * !!! + * The actual argument checking is simple, do it inline, outside of + * the replication block. + * + * The cursor must be initialized, return EINVAL for an invalid cursor. + */ + if (flags != 0) + return (__db_ferr(env, "DBcursor->count", 0)); + + if (!IS_INITIALIZED(dbc)) + return (__db_curinval(env)); + + ENV_ENTER(env, ip); + ret = __dbc_count(dbc, recnop); + ENV_LEAVE(env, ip); + return (ret); +} + +/* + * __dbc_del_pp -- + * DBC->del pre/post processing. + * + * PUBLIC: int __dbc_del_pp __P((DBC *, u_int32_t)); + */ +int +__dbc_del_pp(dbc, flags) + DBC *dbc; + u_int32_t flags; +{ + DB *dbp; + DB_THREAD_INFO *ip; + ENV *env; + int ret; + + dbp = dbc->dbp; + env = dbp->env; + + if ((ret = __dbc_del_arg(dbc, flags)) != 0) + return (ret); + + ENV_ENTER(env, ip); + + /* Check for consistent transaction usage. */ + if ((ret = __db_check_txn(dbp, dbc->txn, dbc->locker, 0)) != 0) + goto err; + + DEBUG_LWRITE(dbc, dbc->txn, "DBcursor->del", NULL, NULL, flags); + ret = __dbc_del(dbc, flags); + +err: ENV_LEAVE(env, ip); + return (ret); +} + +/* + * __dbc_del_arg -- + * Check DBC->del arguments. + */ +static int +__dbc_del_arg(dbc, flags) + DBC *dbc; + u_int32_t flags; +{ + DB *dbp; + ENV *env; + + dbp = dbc->dbp; + env = dbp->env; + + /* Check for changes to a read-only tree. */ + if (DB_IS_READONLY(dbp)) + return (__db_rdonly(env, "DBcursor->del")); + + /* Check for invalid function flags. */ + switch (flags) { + case 0: + break; + case DB_CONSUME: + if (dbp->type != DB_QUEUE) + return (__db_ferr(env, "DBC->del", 0)); + break; + case DB_UPDATE_SECONDARY: + DB_ASSERT(env, F_ISSET(dbp, DB_AM_SECONDARY)); + break; + default: + return (__db_ferr(env, "DBcursor->del", 0)); + } + + /* + * The cursor must be initialized, return EINVAL for an invalid cursor, + * otherwise 0. + */ + if (!IS_INITIALIZED(dbc)) + return (__db_curinval(env)); + + return (0); +} + +/* + * __dbc_dup_pp -- + * DBC->dup pre/post processing. + * + * PUBLIC: int __dbc_dup_pp __P((DBC *, DBC **, u_int32_t)); + */ +int +__dbc_dup_pp(dbc, dbcp, flags) + DBC *dbc, **dbcp; + u_int32_t flags; +{ + DB *dbp; + DB_THREAD_INFO *ip; + ENV *env; + int rep_blocked, ret; + + dbp = dbc->dbp; + env = dbp->env; + + /* + * !!! + * The actual argument checking is simple, do it inline, outside of + * the replication block. + */ + if (flags != 0 && flags != DB_POSITION) + return (__db_ferr(env, "DBcursor->dup", 0)); + + ENV_ENTER(env, ip); + rep_blocked = 0; + if (dbc->txn == NULL && IS_ENV_REPLICATED(env)) { + if ((ret = __op_rep_enter(env, 1, 1)) != 0) + goto err; + rep_blocked = 1; + } + ret = __dbc_dup(dbc, dbcp, flags); + + /* Register externally created cursors into the valid transaction. */ + DB_ASSERT(env, (*dbcp)->txn == dbc->txn); + if ((*dbcp)->txn != NULL && ret == 0) + TAILQ_INSERT_HEAD(&((*dbcp)->txn->my_cursors), *dbcp, + txn_cursors); +err: + if (ret != 0 && rep_blocked) + (void)__op_rep_exit(env); + + ENV_LEAVE(env, ip); + + return (ret); +} + +/* + * __dbc_get_pp -- + * DBC->get pre/post processing. + * + * PUBLIC: int __dbc_get_pp __P((DBC *, DBT *, DBT *, u_int32_t)); + */ +int +__dbc_get_pp(dbc, key, data, flags) + DBC *dbc; + DBT *key, *data; + u_int32_t flags; +{ + DB *dbp; + DB_THREAD_INFO *ip; + ENV *env; + int ignore_lease, ret; + + dbp = dbc->dbp; + env = dbp->env; + + ignore_lease = LF_ISSET(DB_IGNORE_LEASE) ? 1 : 0; + LF_CLR(DB_IGNORE_LEASE); + if ((ret = __dbc_get_arg(dbc, key, data, flags)) != 0) { + __dbt_userfree(env, key, NULL, data); + return (ret); + } + + ENV_ENTER(env, ip); + + DEBUG_LREAD(dbc, dbc->txn, "DBcursor->get", + flags == DB_SET || flags == DB_SET_RANGE ? key : NULL, NULL, flags); + ret = __dbc_get(dbc, key, data, flags); + + /* + * Check for master leases. + */ + if (ret == 0 && + IS_REP_MASTER(env) && IS_USING_LEASES(env) && !ignore_lease) + ret = __rep_lease_check(env, 1); + + ENV_LEAVE(env, ip); + __dbt_userfree(env, key, NULL, data); + return (ret); +} + +/* + * __dbc_get_arg -- + * Common DBC->get argument checking, used by both DBC->get and DBC->pget. + * PUBLIC: int __dbc_get_arg __P((DBC *, DBT *, DBT *, u_int32_t)); + */ +int +__dbc_get_arg(dbc, key, data, flags) + DBC *dbc; + DBT *key, *data; + u_int32_t flags; +{ + DB *dbp; + ENV *env; + int dirty, multi, ret; + + dbp = dbc->dbp; + env = dbp->env; + + /* + * Typically in checking routines that modify the flags, we have + * to save them and restore them, because the checking routine + * calls the work routine. However, this is a pure-checking + * routine which returns to a function that calls the work routine, + * so it's OK that we do not save and restore the flags, even though + * we modify them. + * + * Check for read-modify-write validity. DB_RMW doesn't make sense + * with CDB cursors since if you're going to write the cursor, you + * had to create it with DB_WRITECURSOR. Regardless, we check for + * LOCKING_ON and not STD_LOCKING, as we don't want to disallow it. + * If this changes, confirm that DB does not itself set the DB_RMW + * flag in a path where CDB may have been configured. + */ + dirty = 0; + if (LF_ISSET(DB_READ_COMMITTED | DB_READ_UNCOMMITTED | DB_RMW)) { + if (!LOCKING_ON(env)) + return (__db_fnl(env, "DBcursor->get")); + if (LF_ISSET(DB_READ_UNCOMMITTED)) + dirty = 1; + LF_CLR(DB_READ_COMMITTED | DB_READ_UNCOMMITTED | DB_RMW); + } + + multi = 0; + if (LF_ISSET(DB_MULTIPLE | DB_MULTIPLE_KEY)) { + multi = 1; + if (LF_ISSET(DB_MULTIPLE) && LF_ISSET(DB_MULTIPLE_KEY)) + goto multi_err; + LF_CLR(DB_MULTIPLE | DB_MULTIPLE_KEY); + } + + /* Check for invalid function flags. */ + switch (flags) { + case DB_CONSUME: + case DB_CONSUME_WAIT: + if (dirty) { + __db_errx(env, DB_STR("0619", +"DB_READ_UNCOMMITTED is not supported with DB_CONSUME or DB_CONSUME_WAIT")); + return (EINVAL); + } + if (dbp->type != DB_QUEUE) + goto err; + break; + case DB_CURRENT: + case DB_FIRST: + case DB_NEXT: + case DB_NEXT_DUP: + case DB_NEXT_NODUP: + break; + case DB_LAST: + case DB_PREV: + case DB_PREV_DUP: + case DB_PREV_NODUP: + if (multi) +multi_err: return (__db_ferr(env, "DBcursor->get", 1)); + break; + case DB_GET_BOTHC: + if (dbp->type == DB_QUEUE) + goto err; + /* FALLTHROUGH */ + case DB_GET_BOTH: + case DB_GET_BOTH_RANGE: + if ((ret = __dbt_usercopy(env, data)) != 0) + goto err; + /* FALLTHROUGH */ + case DB_SET: + case DB_SET_RANGE: + if ((ret = __dbt_usercopy(env, key)) != 0) + goto err; + break; + case DB_GET_RECNO: + /* + * The one situation in which this might be legal with a + * non-RECNUM dbp is if dbp is a secondary and its primary is + * DB_AM_RECNUM. + */ + if (!F_ISSET(dbp, DB_AM_RECNUM) && + (!F_ISSET(dbp, DB_AM_SECONDARY) || + !F_ISSET(dbp->s_primary, DB_AM_RECNUM))) + goto err; + break; + case DB_SET_RECNO: + if (!F_ISSET(dbp, DB_AM_RECNUM)) + goto err; + if ((ret = __dbt_usercopy(env, key)) != 0) + goto err; + break; + default: +err: __dbt_userfree(env, key, NULL, data); + return (__db_ferr(env, "DBcursor->get", 0)); + } + + /* Check for invalid key/data flags. */ + if ((ret = __dbt_ferr(dbp, "key", key, 0)) != 0) + return (ret); + if (F_ISSET(data, DB_DBT_READONLY)) { + __db_errx(env, DB_STR("0620", + "DB_DBT_READONLY should not be set on data DBT.")); + return (EINVAL); + } + if ((ret = __dbt_ferr(dbp, "data", data, 0)) != 0) + return (ret); + + if (multi) { + if (!F_ISSET(data, DB_DBT_USERMEM)) { + __db_errx(env, DB_STR("0621", + "DB_MULTIPLE/DB_MULTIPLE_KEY require DB_DBT_USERMEM be set")); + return (EINVAL); + } + if (F_ISSET(key, DB_DBT_PARTIAL) || + F_ISSET(data, DB_DBT_PARTIAL)) { + __db_errx(env, DB_STR("0622", + "DB_MULTIPLE/DB_MULTIPLE_KEY do not support DB_DBT_PARTIAL")); + return (EINVAL); + } + if (data->ulen < 1024 || + data->ulen < dbp->pgsize || data->ulen % 1024 != 0) { + __db_errx(env, DB_STR("0623", + "DB_MULTIPLE/DB_MULTIPLE_KEY buffers must be " + "aligned, at least page size and multiples of 1KB")); + return (EINVAL); + } + } + + /* Check compatible flags for partial key. */ + if (F_ISSET(key, DB_DBT_PARTIAL) && (flags == DB_GET_BOTH || + flags == DB_GET_BOTH_RANGE || flags == DB_SET)) { + __db_errx(env, DB_STR("0710", + "Invalid positioning flag combined with DB_DBT_PARTIAL")); + return (EINVAL); + } + + /* + * The cursor must be initialized for DB_CURRENT, DB_GET_RECNO, + * DB_PREV_DUP and DB_NEXT_DUP. Return EINVAL for an invalid + * cursor, otherwise 0. + */ + if (!IS_INITIALIZED(dbc) && (flags == DB_CURRENT || + flags == DB_GET_RECNO || + flags == DB_NEXT_DUP || flags == DB_PREV_DUP)) + return (__db_curinval(env)); + + /* Check for consistent transaction usage. */ + if (LF_ISSET(DB_RMW) && + (ret = __db_check_txn(dbp, dbc->txn, dbc->locker, 0)) != 0) + return (ret); + + return (0); +} + +/* + * __db_secondary_close_pp -- + * DB->close for secondaries + * + * PUBLIC: int __db_secondary_close_pp __P((DB *, u_int32_t)); + */ +int +__db_secondary_close_pp(dbp, flags) + DB *dbp; + u_int32_t flags; +{ + DB_THREAD_INFO *ip; + ENV *env; + int handle_check, ret, t_ret; + + env = dbp->env; + ret = 0; + + /* + * As a DB handle destructor, we can't fail. + * + * !!! + * The actual argument checking is simple, do it inline, outside of + * the replication block. + */ + if (flags != 0 && flags != DB_NOSYNC) + ret = __db_ferr(env, "DB->close", 0); + + ENV_ENTER(env, ip); + + /* Check for replication block. */ + handle_check = IS_ENV_REPLICATED(env); + if (handle_check && (t_ret = __db_rep_enter(dbp, 0, 0, 0)) != 0) { + handle_check = 0; + if (ret == 0) + ret = t_ret; + } + + if ((t_ret = __db_secondary_close(dbp, flags)) != 0 && ret == 0) + ret = t_ret; + + /* Release replication block. */ + if (handle_check && (t_ret = __env_db_rep_exit(env)) != 0 && ret == 0) + ret = t_ret; + + ENV_LEAVE(env, ip); + return (ret); +} + +/* + * __dbc_pget_pp -- + * DBC->pget pre/post processing. + * + * PUBLIC: int __dbc_pget_pp __P((DBC *, DBT *, DBT *, DBT *, u_int32_t)); + */ +int +__dbc_pget_pp(dbc, skey, pkey, data, flags) + DBC *dbc; + DBT *skey, *pkey, *data; + u_int32_t flags; +{ + DB *dbp; + DB_THREAD_INFO *ip; + ENV *env; + int ignore_lease, ret; + + dbp = dbc->dbp; + env = dbp->env; + + ignore_lease = LF_ISSET(DB_IGNORE_LEASE) ? 1 : 0; + LF_CLR(DB_IGNORE_LEASE); + if ((ret = __dbc_pget_arg(dbc, pkey, flags)) != 0 || + (ret = __dbc_get_arg(dbc, skey, data, flags)) != 0) { + __dbt_userfree(env, skey, pkey, data); + return (ret); + } + + ENV_ENTER(env, ip); + DEBUG_LREAD(dbc, dbc->txn, "DBcursor->pget", + flags == DB_SET || + flags == DB_SET_RANGE ? skey : NULL, NULL, flags); + ret = __dbc_pget(dbc, skey, pkey, data, flags); + /* + * Check for master leases. + */ + if (ret == 0 && + IS_REP_MASTER(env) && IS_USING_LEASES(env) && !ignore_lease) + ret = __rep_lease_check(env, 1); + + ENV_LEAVE(env, ip); + + __dbt_userfree(env, skey, pkey, data); + return (ret); +} + +/* + * __dbc_pget_arg -- + * Check DBC->pget arguments. + */ +static int +__dbc_pget_arg(dbc, pkey, flags) + DBC *dbc; + DBT *pkey; + u_int32_t flags; +{ + DB *dbp; + ENV *env; + int ret; + + dbp = dbc->dbp; + env = dbp->env; + + if (!F_ISSET(dbp, DB_AM_SECONDARY)) { + __db_errx(env, DB_STR("0624", + "DBcursor->pget may only be used on secondary indices")); + return (EINVAL); + } + + if (LF_ISSET(DB_MULTIPLE | DB_MULTIPLE_KEY)) { + __db_errx(env, DB_STR("0625", + "DB_MULTIPLE and DB_MULTIPLE_KEY may not be used on secondary indices")); + return (EINVAL); + } + + switch (LF_ISSET(DB_OPFLAGS_MASK)) { + case DB_CONSUME: + case DB_CONSUME_WAIT: + /* These flags make no sense on a secondary index. */ + return (__db_ferr(env, "DBcursor->pget", 0)); + case DB_GET_BOTH: + case DB_GET_BOTH_RANGE: + /* BOTH is "get both the primary and the secondary". */ + if (pkey == NULL) { + __db_errx(env, DB_STR_A("0626", + "%s requires both a secondary and a primary key", + "%s"), LF_ISSET(DB_GET_BOTH) ? + "DB_GET_BOTH" : "DB_GET_BOTH_RANGE"); + return (EINVAL); + } + if ((ret = __dbt_usercopy(env, pkey)) != 0) + return (ret); + break; + default: + /* __dbc_get_arg will catch the rest. */ + break; + } + + /* + * We allow the pkey field to be NULL, so that we can make the + * two-DBT get calls into wrappers for the three-DBT ones. + */ + if (pkey != NULL && + (ret = __dbt_ferr(dbp, "primary key", pkey, 0)) != 0) + return (ret); + + /* Check invalid partial pkey. */ + if (pkey != NULL && F_ISSET(pkey, DB_DBT_PARTIAL)) { + __db_errx(env, DB_STR("0711", + "The primary key returned by pget can't be partial.")); + return (EINVAL); + } + + /* But the pkey field can't be NULL if we're doing a DB_GET_BOTH. */ + if (pkey == NULL && (flags & DB_OPFLAGS_MASK) == DB_GET_BOTH) { + __db_errx(env, DB_STR("0627", + "DB_GET_BOTH on a secondary index requires a primary key")); + return (EINVAL); + } + + return (0); +} + +/* + * __dbc_put_pp -- + * DBC->put pre/post processing. + * + * PUBLIC: int __dbc_put_pp __P((DBC *, DBT *, DBT *, u_int32_t)); + */ +int +__dbc_put_pp(dbc, key, data, flags) + DBC *dbc; + DBT *key, *data; + u_int32_t flags; +{ + DB *dbp; + DB_THREAD_INFO *ip; + ENV *env; + int ret; + + dbp = dbc->dbp; + env = dbp->env; + + if ((ret = __dbc_put_arg(dbc, key, data, flags)) != 0) { + __dbt_userfree(env, key, NULL, data); + return (ret); + } + + ENV_ENTER(env, ip); + + /* Check for consistent transaction usage. */ + if ((ret = __db_check_txn(dbp, dbc->txn, dbc->locker, 0)) != 0) + goto err; + + DEBUG_LWRITE(dbc, dbc->txn, "DBcursor->put", + flags == DB_KEYFIRST || flags == DB_KEYLAST || + flags == DB_NODUPDATA || flags == DB_UPDATE_SECONDARY ? + key : NULL, data, flags); + ret = __dbc_put(dbc, key, data, flags); + +err: ENV_LEAVE(env, ip); + __dbt_userfree(env, key, NULL, data); + return (ret); +} + +/* + * __dbc_put_arg -- + * Check DBC->put arguments. + */ +static int +__dbc_put_arg(dbc, key, data, flags) + DBC *dbc; + DBT *key, *data; + u_int32_t flags; +{ + DB *dbp; + ENV *env; + int key_flags, ret; + + dbp = dbc->dbp; + env = dbp->env; + key_flags = 0; + + /* Check for changes to a read-only tree. */ + if (DB_IS_READONLY(dbp)) + return (__db_rdonly(env, "DBcursor->put")); + + /* Check for puts on a secondary. */ + if (F_ISSET(dbp, DB_AM_SECONDARY)) { + if (flags == DB_UPDATE_SECONDARY) + flags = 0; + else { + __db_errx(env, DB_STR("0628", + "DBcursor->put forbidden on secondary indices")); + return (EINVAL); + } + } + + if ((ret = __dbt_usercopy(env, data)) != 0) + return (ret); + + /* Check for invalid function flags. */ + switch (flags) { + case DB_AFTER: + case DB_BEFORE: + switch (dbp->type) { + case DB_BTREE: + case DB_HASH: /* Only with unsorted duplicates. */ + if (!F_ISSET(dbp, DB_AM_DUP)) + goto err; + if (dbp->dup_compare != NULL) + goto err; + break; + case DB_QUEUE: /* Not permitted. */ + goto err; + case DB_RECNO: /* Only with mutable record numbers. */ + if (!F_ISSET(dbp, DB_AM_RENUMBER)) + goto err; + key_flags = key == NULL ? 0 : 1; + break; + case DB_UNKNOWN: + default: + goto err; + } + break; + case DB_CURRENT: + /* + * If there is a comparison function, doing a DB_CURRENT + * must not change the part of the data item that is used + * for the comparison. + */ + break; + case DB_NODUPDATA: + if (!F_ISSET(dbp, DB_AM_DUPSORT)) + goto err; + /* FALLTHROUGH */ + case DB_KEYFIRST: + case DB_KEYLAST: + case DB_OVERWRITE_DUP: + key_flags = 1; + if ((ret = __dbt_usercopy(env, key)) != 0) + return (ret); + break; + default: +err: return (__db_ferr(env, "DBcursor->put", 0)); + } + + /* + * Check for invalid key/data flags. The key may reasonably be NULL + * if DB_AFTER or DB_BEFORE is set and the application doesn't care + * about the returned key, or if the DB_CURRENT flag is set. + */ + if (key_flags && (ret = __dbt_ferr(dbp, "key", key, 0)) != 0) + return (ret); + if ((ret = __dbt_ferr(dbp, "data", data, 0)) != 0) + return (ret); + + /* + * The key parameter should not be NULL or have the "partial" flag set + * in a put call unless the user doesn't care about a key value we'd + * return. The user tells us they don't care about the returned key by + * setting the key parameter to NULL or configuring the key DBT to not + * return any information. (Returned keys from a put are always record + * numbers, and returning part of a record number doesn't make sense: + * only accept a partial return if the length returned is 0.) + */ + if (key_flags && F_ISSET(key, DB_DBT_PARTIAL) && key->dlen != 0) + return (__db_ferr(env, "key DBT", 0)); + + /* + * The cursor must be initialized for anything other than DB_KEYFIRST, + * DB_KEYLAST or zero: return EINVAL for an invalid cursor, otherwise 0. + */ + if (!IS_INITIALIZED(dbc) && flags != 0 && flags != DB_KEYFIRST && + flags != DB_KEYLAST && flags != DB_NODUPDATA && + flags != DB_OVERWRITE_DUP) + return (__db_curinval(env)); + + return (0); +} + +/* + * __dbt_ferr -- + * Check a DBT for flag errors. + */ +static int +__dbt_ferr(dbp, name, dbt, check_thread) + const DB *dbp; + const char *name; + const DBT *dbt; + int check_thread; +{ + ENV *env; + int ret; + + env = dbp->env; + + /* + * Check for invalid DBT flags. We allow any of the flags to be + * specified to any DB or DBcursor call so that applications can + * set DB_DBT_MALLOC when retrieving a data item from a secondary + * database and then specify that same DBT as a key to a primary + * database, without having to clear flags. + */ + if ((ret = __db_fchk(env, name, dbt->flags, + DB_DBT_APPMALLOC | DB_DBT_BULK | DB_DBT_DUPOK | + DB_DBT_MALLOC | DB_DBT_REALLOC | DB_DBT_USERCOPY | + DB_DBT_USERMEM | DB_DBT_PARTIAL | DB_DBT_READONLY)) != 0) + return (ret); + switch (F_ISSET(dbt, DB_DBT_MALLOC | DB_DBT_REALLOC | + DB_DBT_USERCOPY | DB_DBT_USERMEM)) { + case 0: + case DB_DBT_MALLOC: + case DB_DBT_REALLOC: + case DB_DBT_USERCOPY: + case DB_DBT_USERMEM: + break; + default: + return (__db_ferr(env, name, 1)); + } + + if (F_ISSET(dbt, DB_DBT_BULK) && F_ISSET(dbt, DB_DBT_PARTIAL)) { + __db_errx(env, DB_STR_A("0629", + "Bulk and partial operations cannot be combined on %s DBT", + "%s"), name); + return (EINVAL); + } + + if (check_thread && DB_IS_THREADED(dbp) && + !F_ISSET(dbt, DB_DBT_MALLOC | DB_DBT_REALLOC | + DB_DBT_USERCOPY | DB_DBT_USERMEM | DB_DBT_READONLY)) { + __db_errx(env, DB_STR_A("0630", + "DB_THREAD mandates memory allocation flag on %s DBT", + "%s"), name); + return (EINVAL); + } + return (0); +} + +/* + * __db_curinval + * Report that a cursor is in an invalid state. + */ +static int +__db_curinval(env) + const ENV *env; +{ + __db_errx(env, DB_STR("0631", + "Cursor position must be set before performing this operation")); + return (EINVAL); +} + +/* + * __db_txn_auto_init -- + * Handle DB_AUTO_COMMIT initialization. + * + * PUBLIC: int __db_txn_auto_init __P((ENV *, DB_THREAD_INFO *, DB_TXN **)); + */ +int +__db_txn_auto_init(env, ip, txnidp) + ENV *env; + DB_THREAD_INFO *ip; + DB_TXN **txnidp; +{ + /* + * Method calls where applications explicitly specify DB_AUTO_COMMIT + * require additional validation: the DB_AUTO_COMMIT flag cannot be + * specified if a transaction cookie is also specified, nor can the + * flag be specified in a non-transactional environment. + */ + if (*txnidp != NULL && !F_ISSET(*txnidp, TXN_FAMILY)) { + __db_errx(env, DB_STR("0632", + "DB_AUTO_COMMIT may not be specified along with a transaction handle")); + return (EINVAL); + } + + if (!TXN_ON(env)) { + __db_errx(env, DB_STR("0633", + "DB_AUTO_COMMIT may not be specified in non-transactional environment")); + return (EINVAL); + } + + /* + * Our caller checked to see if replication is making a state change. + * Don't call the user-level API (which would repeat that check). + */ + return (__txn_begin(env, ip, *txnidp, txnidp, 0)); +} + +/* + * __db_txn_auto_resolve -- + * Resolve local transactions. + * + * PUBLIC: int __db_txn_auto_resolve __P((ENV *, DB_TXN *, int, int)); + */ +int +__db_txn_auto_resolve(env, txn, nosync, ret) + ENV *env; + DB_TXN *txn; + int nosync, ret; +{ + int t_ret; + + if (ret == 0) + return (__txn_commit(txn, nosync ? DB_TXN_NOSYNC : 0)); + + if ((t_ret = __txn_abort(txn)) != 0) + return (__env_panic(env, t_ret)); + return (ret); +} diff -r 000000000000 -r a1985f14b030 src/db/db_meta.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/db/db_meta.c Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,1126 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 1996, 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +/* + * Copyright (c) 1990, 1993, 1994, 1995, 1996 + * Keith Bostic. All rights reserved. + */ +/* + * Copyright (c) 1990, 1993, 1994, 1995 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Mike Olson. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $Id$ + */ + +#include "db_config.h" + +#include "db_int.h" +#include "dbinc/db_page.h" +#include "dbinc/lock.h" +#include "dbinc/log.h" +#include "dbinc/mp.h" +#include "dbinc/txn.h" +#include "dbinc/db_am.h" +#include "dbinc/hash.h" + +static void __db_init_meta __P((DB *, void *, db_pgno_t, u_int32_t)); +#ifdef HAVE_FTRUNCATE +static int __db_pglistcmp __P((const void *, const void *)); +static int __db_truncate_freelist __P((DBC *, DBMETA *, + PAGE *, db_pgno_t *, u_int32_t, u_int32_t)); +#endif + +/* + * __db_init_meta -- + * Helper function for __db_new that initializes the important fields in + * a meta-data page (used instead of P_INIT). We need to make sure that we + * retain the page number and LSN of the existing page. + */ +static void +__db_init_meta(dbp, p, pgno, pgtype) + DB *dbp; + void *p; + db_pgno_t pgno; + u_int32_t pgtype; +{ + DBMETA *meta; + DB_LSN save_lsn; + + meta = (DBMETA *)p; + save_lsn = meta->lsn; + memset(meta, 0, sizeof(DBMETA)); + meta->lsn = save_lsn; + meta->pagesize = dbp->pgsize; + if (F_ISSET(dbp, DB_AM_CHKSUM)) + FLD_SET(meta->metaflags, DBMETA_CHKSUM); + meta->pgno = pgno; + meta->type = (u_int8_t)pgtype; +} + +/* + * __db_new -- + * Get a new page, preferably from the freelist. + * + * PUBLIC: int __db_new __P((DBC *, u_int32_t, DB_LOCK *, PAGE **)); + */ +int +__db_new(dbc, type, lockp, pagepp) + DBC *dbc; + u_int32_t type; + DB_LOCK *lockp; + PAGE **pagepp; +{ + DB *dbp; + DBMETA *meta; + DB_LOCK metalock; + DB_LSN lsn; + DB_MPOOLFILE *mpf; + ENV *env; + PAGE *h; + db_pgno_t last, *list, pgno, newnext; + int extend, hash, ret; + + meta = NULL; + dbp = dbc->dbp; + env = dbp->env; + mpf = dbp->mpf; + h = NULL; + newnext = PGNO_INVALID; + if (lockp != NULL) + LOCK_INIT(*lockp); + + hash = 0; + ret = 0; + LOCK_INIT(metalock); + +#ifdef HAVE_HASH + if (dbp->type == DB_HASH) { + if ((ret = __ham_return_meta(dbc, DB_MPOOL_DIRTY, &meta)) != 0) + goto err; + if (meta != NULL) + hash = 1; + } +#endif + if (meta == NULL) { + pgno = PGNO_BASE_MD; + if ((ret = __db_lget(dbc, + LCK_ALWAYS, pgno, DB_LOCK_WRITE, 0, &metalock)) != 0) + goto err; + if ((ret = __memp_fget(mpf, &pgno, dbc->thread_info, dbc->txn, + DB_MPOOL_DIRTY, &meta)) != 0) + goto err; + } + + last = meta->last_pgno; + if (meta->free == PGNO_INVALID) { + if (FLD_ISSET(type, P_DONTEXTEND)) { + *pagepp = NULL; + goto err; + } + last = pgno = meta->last_pgno + 1; + ZERO_LSN(lsn); + extend = 1; + } else { + pgno = meta->free; + /* + * Lock the new page. Do this here because we must do it + * before getting the page and the caller may need the lock + * to keep readers from seeing the page before the transaction + * commits. We can do this because no one will hold a free + * page locked. + */ + if (lockp != NULL && (ret = + __db_lget(dbc, 0, pgno, DB_LOCK_WRITE, 0, lockp)) != 0) + goto err; + if ((ret = __memp_fget(mpf, &pgno, dbc->thread_info, dbc->txn, + DB_MPOOL_DIRTY, &h)) != 0) + goto err; + + /* + * We want to take the first page off the free list and + * then set meta->free to the that page's next_pgno, but + * we need to log the change first. + */ + newnext = h->next_pgno; + lsn = h->lsn; + extend = 0; + DB_ASSERT(env, TYPE(h) == P_INVALID); + + if (TYPE(h) != P_INVALID) { + __db_errx(env, DB_STR_A("0689", + "%s page %lu is on free list with type %lu", + "%s %lu %lu"), dbp->fname, (u_long)PGNO(h), + (u_long)TYPE(h)); + return (__env_panic(env, EINVAL)); + } + + } + + FLD_CLR(type, P_DONTEXTEND); + + /* + * Log the allocation before fetching the new page. If we + * don't have room in the log then we don't want to tell + * mpool to extend the file. + */ + if (DBC_LOGGING(dbc)) { + if ((ret = __db_pg_alloc_log(dbp, dbc->txn, &LSN(meta), 0, + &LSN(meta), PGNO_BASE_MD, &lsn, + pgno, (u_int32_t)type, newnext, meta->last_pgno)) != 0) + goto err; + } else + LSN_NOT_LOGGED(LSN(meta)); + + meta->free = newnext; + + if (extend == 1) { + if (lockp != NULL && (ret = + __db_lget(dbc, 0, pgno, DB_LOCK_WRITE, 0, lockp)) != 0) + goto err; + if ((ret = __memp_fget(mpf, &pgno, dbc->thread_info, dbc->txn, + DB_MPOOL_NEW, &h)) != 0) + goto err; + DB_ASSERT(env, last == pgno); + meta->last_pgno = pgno; + ZERO_LSN(h->lsn); + h->pgno = pgno; + + /* + * If the file was extended for the first time in this + * transaction, set the MPOOLFILE's file extension + * watermark. + */ + __txn_add_fe_watermark(dbc->txn, dbp, h->pgno); + + } + LSN(h) = LSN(meta); + + if (hash == 0 && (ret = __memp_fput(mpf, + dbc->thread_info, meta, dbc->priority)) != 0) + goto err; + meta = NULL; + + switch (type) { + case P_BTREEMETA: + case P_HASHMETA: + case P_QAMMETA: + __db_init_meta(dbp, h, h->pgno, type); + break; + default: + P_INIT(h, dbp->pgsize, + h->pgno, PGNO_INVALID, PGNO_INVALID, 0, type); + break; + } + + /* Fix up the sorted free list if necessary. */ +#ifdef HAVE_FTRUNCATE + if (extend == 0) { + u_int32_t nelems = 0; + + if ((ret = __memp_get_freelist(dbp->mpf, &nelems, &list)) != 0) + goto err; + if (nelems != 0) { + DB_ASSERT(env, h->pgno == list[0]); + memmove(list, &list[1], (nelems - 1) * sizeof(*list)); + if ((ret = __memp_extend_freelist( + dbp->mpf, nelems - 1, &list)) != 0) + goto err; + } + } +#else + COMPQUIET(list, NULL); +#endif + + if ((ret = __TLPUT(dbc, metalock)) != 0) + return (ret); + *pagepp = h; + PERFMON6(env, alloc, new, dbp->fname, dbp->dname, pgno, type, h, 0); + return (0); + +err: if (h != NULL) + (void)__memp_fput(mpf, dbc->thread_info, h, dbc->priority); + if (meta != NULL && hash == 0) + (void)__memp_fput(mpf, dbc->thread_info, meta, dbc->priority); + (void)__TLPUT(dbc, metalock); + if (lockp != NULL) + (void)__LPUT(dbc, *lockp); + /* Failure return - report 0 pgno, null page address. */ + PERFMON6(env, alloc, new, dbp->fname, dbp->dname, 0, type, NULL, ret); + return (ret); +} + +/* + * __db_free -- + * Add a page to the head of the freelist. + * + * PUBLIC: int __db_free __P((DBC *, PAGE *, u_int32_t)); + */ +int +__db_free(dbc, h, flags) + DBC *dbc; + PAGE *h; + u_int32_t flags; +{ + DB *dbp; + DBMETA *meta; + DBT ddbt, ldbt; + DB_LOCK metalock; + DB_LSN *lsnp; + DB_MPOOLFILE *mpf; + PAGE *prev; + db_pgno_t last_pgno, next_pgno, pgno, prev_pgno; + u_int32_t lflag; + int hash, ret, t_ret; +#ifdef HAVE_FTRUNCATE + db_pgno_t *list, *lp; + u_int32_t nelem, position, start; + int do_truncate; +#endif + + dbp = dbc->dbp; + mpf = dbp->mpf; + prev_pgno = PGNO_INVALID; + meta = NULL; + prev = NULL; + LOCK_INIT(metalock); +#ifdef HAVE_FTRUNCATE + lp = NULL; + nelem = 0; + do_truncate = 0; +#endif + + /* + * Retrieve the metadata page. If we are not keeping a sorted + * free list put the page at the head of the the free list. + * If we are keeping a sorted free list, for truncation, + * then figure out where this page belongs and either + * link it in or truncate the file as much as possible. + * If either the lock get or page get routines + * fail, then we need to put the page with which we were called + * back because our caller assumes we take care of it. + */ + hash = 0; + + pgno = PGNO_BASE_MD; + if ((ret = __db_lget(dbc, + LCK_ALWAYS, pgno, DB_LOCK_WRITE, 0, &metalock)) != 0) + goto err; + +#ifdef HAVE_HASH + if (dbp->type == DB_HASH) { + if ((ret = __ham_return_meta(dbc, +#ifdef HAVE_FTRUNCATE + 0, +#else + DB_MPOOL_DIRTY, +#endif + &meta)) != 0) + goto err; + if (meta != NULL) + hash = 1; + } +#endif + if (meta == NULL) { + /* If we support truncate, we might not dirty the meta page. */ + if ((ret = __memp_fget(mpf, &pgno, dbc->thread_info, dbc->txn, +#ifdef HAVE_FTRUNCATE + 0, +#else + DB_MPOOL_DIRTY, +#endif + &meta)) != 0) + goto err1; + } + + last_pgno = meta->last_pgno; + next_pgno = meta->free; + /* + * Assign lsnp here so it always initialized when + * HAVE_FTRUNCATE is not defined. + */ + lsnp = &LSN(meta); + + DB_ASSERT(dbp->env, h->pgno != next_pgno); + +#ifdef HAVE_FTRUNCATE + /* + * If we are maintaining a sorted free list see if we either have a + * new truncation point or the page goes somewhere in the middle of + * the list. If it goes in the middle of the list, we will drop the + * meta page and get the previous page. + */ + COMPQUIET(position, 0); + if ((ret = __memp_get_freelist(mpf, &nelem, &list)) != 0) + goto err1; + if (list == NULL) + goto no_sort; + + if (h->pgno != last_pgno) { + /* + * Put the page number in the sorted list. Find its + * position and the previous page. After logging we + * will extend the list, make room and insert the page in + * the list. + */ + position = 0; + if (nelem != 0) { + __db_freelist_pos(h->pgno, list, nelem, &position); + + DB_ASSERT(dbp->env, h->pgno != list[position]); + + /* Get the previous page if this is not the smallest. */ + if (position != 0 || h->pgno > list[0]) + prev_pgno = list[position]; + } + + } else if (nelem != 0) { + /* Find the truncation point. */ + for (lp = &list[nelem - 1]; lp >= list; lp--) + if (--last_pgno != *lp) + break; + if (lp < list || last_pgno < h->pgno - 1) + do_truncate = 1; + last_pgno = meta->last_pgno; + } + +no_sort: + if (prev_pgno == PGNO_INVALID) { +#ifdef HAVE_HASH + if (hash) { + if ((ret = + __ham_return_meta(dbc, DB_MPOOL_DIRTY, &meta)) != 0) + goto err1; + } else +#endif + if ((ret = __memp_dirty(mpf, + &meta, dbc->thread_info, dbc->txn, dbc->priority, 0)) != 0) + goto err1; + lsnp = &LSN(meta); + } else { + pgno = prev_pgno; + if ((ret = __memp_fget(mpf, &pgno, + dbc->thread_info, dbc->txn, DB_MPOOL_DIRTY, &prev)) != 0) + goto err1; + next_pgno = NEXT_PGNO(prev); + lsnp = &LSN(prev); + } +#endif + + /* + * Log the change. + * We are either logging an update to the metapage or to the + * previous page in the sorted list. + */ + if (DBC_LOGGING(dbc)) { + memset(&ldbt, 0, sizeof(ldbt)); + ldbt.data = h; + ldbt.size = P_OVERHEAD(dbp); + /* + * If we are removing pages from the file, we need to make + * sure the logging happens before the truncation. If we + * are truncating multiple pages we don't need to flush the + * log here as it will be flushed by __db_truncate_freelist. + */ + lflag = 0; + +#ifdef HAVE_FTRUNCATE + if (h->pgno == last_pgno && do_truncate == 0) + lflag = DB_FLUSH; +#endif + switch (h->type) { + case P_HASH: + case P_IBTREE: + case P_IRECNO: + case P_LBTREE: + case P_LRECNO: + case P_LDUP: + if (h->entries > 0 && (h->pgno == last_pgno || + !LF_ISSET(DB_LOG_NO_DATA))) { + ldbt.size += h->entries * sizeof(db_indx_t); + ddbt.data = (u_int8_t *)h + HOFFSET(h); + ddbt.size = dbp->pgsize - HOFFSET(h); + if ((ret = __db_pg_freedata_log(dbp, dbc->txn, + lsnp, lflag, + h->pgno, lsnp, pgno, + &ldbt, next_pgno, last_pgno, &ddbt)) != 0) + goto err1; + goto logged; + } + break; + case P_HASHMETA: + ldbt.size = sizeof(HMETA); + break; + case P_BTREEMETA: + ldbt.size = sizeof(BTMETA); + break; + case P_OVERFLOW: + ldbt.size += OV_LEN(h); + break; + default: + DB_ASSERT(dbp->env, h->type != P_QAMDATA); + } + + if ((ret = __db_pg_free_log(dbp, + dbc->txn, lsnp, lflag, h->pgno, + lsnp, pgno, &ldbt, next_pgno, last_pgno)) != 0) + goto err1; + } else + LSN_NOT_LOGGED(*lsnp); + +logged: +#ifdef HAVE_FTRUNCATE + if (do_truncate) { + start = (u_int32_t) (lp - list) + 1; + meta->last_pgno--; + ret = __db_truncate_freelist( + dbc, meta, h, list, start, nelem); + h = NULL; + } else if (h->pgno == last_pgno) { + /* + * We are going to throw this page away, but if we are + * using MVCC then this version may stick around and we + * might have to make a copy. + */ + if (atomic_read(&mpf->mfp->multiversion) && + (ret = __memp_dirty(mpf, + &h, dbc->thread_info, dbc->txn, dbc->priority, 0)) != 0) + goto err1; + LSN(h) = *lsnp; + P_INIT(h, dbp->pgsize, + h->pgno, PGNO_INVALID, next_pgno, 0, P_INVALID); + if ((ret = __memp_fput(mpf, + dbc->thread_info, h, DB_PRIORITY_VERY_LOW)) != 0) + goto err1; + h = NULL; + /* Give the page back to the OS. */ + if ((ret = __memp_ftruncate(mpf, dbc->txn, dbc->thread_info, + last_pgno, 0)) != 0) + goto err1; + DB_ASSERT(dbp->env, meta->pgno == PGNO_BASE_MD); + meta->last_pgno--; + } else { + if (list != NULL) { + /* Put the page number into the list. */ + if ((ret = + __memp_extend_freelist(mpf, nelem + 1, &list)) != 0) + goto err1; + if (prev_pgno != PGNO_INVALID) + lp = &list[position + 1]; + else + lp = list; + if (nelem != 0 && position != nelem) + memmove(lp + 1, lp, (size_t) + ((u_int8_t*)&list[nelem] - (u_int8_t*)lp)); + *lp = h->pgno; + } +#else + { +#endif + /* + * If we are not truncating the page then we + * reinitialize it and put it at the head of + * the free list. + */ + if ((ret = __memp_dirty(mpf, + &h, dbc->thread_info, dbc->txn, dbc->priority, 0)) != 0) + goto err1; + LSN(h) = *lsnp; + P_INIT(h, dbp->pgsize, + h->pgno, PGNO_INVALID, next_pgno, 0, P_INVALID); +#ifdef DIAGNOSTIC + memset((u_int8_t *) h + P_OVERHEAD(dbp), + CLEAR_BYTE, dbp->pgsize - P_OVERHEAD(dbp)); +#endif + if (prev_pgno == PGNO_INVALID) + meta->free = h->pgno; + else + NEXT_PGNO(prev) = h->pgno; + } + + /* Discard the metadata or previous page. */ +err1: if (hash == 0 && meta != NULL && (t_ret = __memp_fput(mpf, + dbc->thread_info, (PAGE *)meta, dbc->priority)) != 0 && ret == 0) + ret = t_ret; + if ((t_ret = __TLPUT(dbc, metalock)) != 0 && ret == 0) + ret = t_ret; + if (prev != (PAGE*) meta && prev != NULL && (t_ret = __memp_fput(mpf, + dbc->thread_info, prev, dbc->priority)) != 0 && ret == 0) + ret = t_ret; + + /* Discard the caller's page reference. */ +err: if (h != NULL && (t_ret = __memp_fput(mpf, + dbc->thread_info, h, dbc->priority)) != 0 && ret == 0) + ret = t_ret; + + PERFMON4(dbp->env, alloc, free, dbp->fname, dbp->dname, pgno, ret); + /* + * XXX + * We have to unlock the caller's page in the caller! + */ + return (ret); +} + +#ifdef HAVE_FTRUNCATE +/* + * __db_freelist_pos -- find the position of a page in the freelist. + * The list is sorted, we do a binary search. + * + * PUBLIC: #ifdef HAVE_FTRUNCATE + * PUBLIC: void __db_freelist_pos __P((db_pgno_t, + * PUBLIC: db_pgno_t *, u_int32_t, u_int32_t *)); + * PUBLIC: #endif + */ +void +__db_freelist_pos(pgno, list, nelem, posp) + db_pgno_t pgno; + db_pgno_t *list; + u_int32_t nelem; + u_int32_t *posp; +{ + u_int32_t base, indx, lim; + + indx = 0; + for (base = 0, lim = nelem; lim != 0; lim >>= 1) { + indx = base + (lim >> 1); + if (pgno == list[indx]) { + *posp = indx; + return; + } + if (pgno > list[indx]) { + base = indx + 1; + --lim; + } + } + if (base != 0) + base--; + *posp = base; + return; +} + +static int +__db_pglistcmp(a, b) + const void *a, *b; +{ + db_pglist_t *ap, *bp; + + ap = (db_pglist_t *)a; + bp = (db_pglist_t *)b; + + return ((ap->pgno > bp->pgno) ? 1 : (ap->pgno < bp->pgno) ? -1: 0); +} + +/* + * __db_freelist_sort -- sort a list of free pages. + * PUBLIC: void __db_freelist_sort __P((db_pglist_t *, u_int32_t)); + */ +void +__db_freelist_sort(list, nelems) + db_pglist_t *list; + u_int32_t nelems; +{ + qsort(list, (size_t)nelems, sizeof(db_pglist_t), __db_pglistcmp); +} + +/* + * __db_pg_truncate -- find the truncation point in a sorted freelist. + * + * PUBLIC: #ifdef HAVE_FTRUNCATE + * PUBLIC: int __db_pg_truncate __P((DBC *, DB_TXN *, + * PUBLIC: db_pglist_t *, DB_COMPACT *, u_int32_t *, + * PUBLIC: db_pgno_t , db_pgno_t *, DB_LSN *, int)); + * PUBLIC: #endif + */ +int +__db_pg_truncate(dbc, txn, + list, c_data, nelemp, free_pgno, last_pgno, lsnp, in_recovery) + DBC *dbc; + DB_TXN *txn; + db_pglist_t *list; + DB_COMPACT *c_data; + u_int32_t *nelemp; + db_pgno_t free_pgno, *last_pgno; + DB_LSN *lsnp; + int in_recovery; +{ + DB *dbp; + DBT ddbt; + DB_LSN null_lsn; + DB_MPOOLFILE *mpf; + PAGE *h; + db_pglist_t *lp, *slp; + db_pgno_t lpgno, pgno; + u_int32_t elems, log_size, tpoint; + int last, ret; + + ret = 0; + h = NULL; + + dbp = dbc->dbp; + mpf = dbp->mpf; + elems = tpoint = *nelemp; + + /* + * Figure out what (if any) pages can be truncated immediately and + * record the place from which we can truncate, so we can do the + * memp_ftruncate below. We also use this to avoid ever putting + * these pages on the freelist, which we are about to relink. + */ + pgno = *last_pgno; + lp = &list[elems - 1]; + last = 1; + while (tpoint != 0) { + if (lp->pgno != pgno) + break; + pgno--; + tpoint--; + lp--; + } + + lp = list; + slp = &list[elems]; + /* + * Log the sorted list. We log the whole list so it can be rebuilt. + * Don't overflow the log file. + */ +again: if (DBC_LOGGING(dbc)) { + last = 1; + lpgno = *last_pgno; + ddbt.size = elems * sizeof(*lp); + ddbt.data = lp; + log_size = ((LOG *)dbc->env-> + lg_handle->reginfo.primary)->log_size; + if (ddbt.size > log_size / 2) { + elems = (log_size / 2) / sizeof(*lp); + ddbt.size = elems * sizeof(*lp); + last = 0; + /* + * If we stopped after the truncation point + * then we need to truncate from here. + */ + if (lp + elems >= &list[tpoint]) + lpgno = lp[elems - 1].pgno; + } + /* + * If this is not the beginning of the list fetch the end + * of the previous segment. This page becomes the last_free + * page and will link to this segment if it is not truncated. + */ + if (lp != list) { + if ((ret = __memp_fget(mpf, &lp[-1].pgno, + dbc->thread_info, txn, 0, &h)) != 0) + goto err; + } + + slp = &lp[elems]; + + ZERO_LSN(null_lsn); + if ((ret = __db_pg_trunc_log(dbp, dbc->txn, + lsnp, last == 1 ? DB_FLUSH : 0, PGNO_BASE_MD, + lsnp, h != NULL ? PGNO(h) : PGNO_INVALID, + h != NULL ? &LSN(h) : &null_lsn, + free_pgno, lpgno, &ddbt)) != 0) + goto err; + if (h != NULL) { + LSN(h) = *lsnp; + if ((ret = __memp_fput(mpf, + dbc->thread_info, h, dbc->priority)) != 0) + goto err; + } + h = NULL; + } else if (!in_recovery) + LSN_NOT_LOGGED(*lsnp); + + for (; lp < slp && lp < &list[tpoint]; lp++) { + if ((ret = __memp_fget(mpf, &lp->pgno, dbc->thread_info, + txn, !in_recovery ? DB_MPOOL_DIRTY : 0, &h)) != 0) { + /* Page may have been truncated later. */ + if (in_recovery && ret == DB_PAGE_NOTFOUND) { + ret = 0; + continue; + } + goto err; + } + if (in_recovery) { + if (LOG_COMPARE(&LSN(h), &lp->lsn) == 0) { + if ((ret = __memp_dirty(mpf, &h, + dbc->thread_info, + txn, dbp->priority, 0)) != 0) { + (void)__memp_fput(mpf, + dbc->thread_info, h, dbp->priority); + goto err; + } + } else + goto skip; + } + + if (lp == &list[tpoint - 1]) + NEXT_PGNO(h) = PGNO_INVALID; + else + NEXT_PGNO(h) = lp[1].pgno; + DB_ASSERT(mpf->env, NEXT_PGNO(h) < *last_pgno); + + LSN(h) = *lsnp; +skip: if ((ret = __memp_fput(mpf, + dbc->thread_info, h, dbp->priority)) != 0) + goto err; + h = NULL; + } + + /* + * If we did not log everything try again. We start from slp and + * try to go to the end of the list. + */ + if (last == 0) { + elems = (u_int32_t)(&list[*nelemp] - slp); + lp = slp; + goto again; + } + + /* + * Truncate the file. Its possible that the last page is the + * only one that got truncated and that's done in the caller. + */ + if (pgno != *last_pgno) { + if (tpoint != *nelemp && + (ret = __memp_ftruncate(mpf, dbc->txn, dbc->thread_info, + pgno + 1, in_recovery ? MP_TRUNC_RECOVER : 0)) != 0) + goto err; + if (c_data) + c_data->compact_pages_truncated += *last_pgno - pgno; + *last_pgno = pgno; + } + *nelemp = tpoint; + + if (0) { +err: if (h != NULL) + (void)__memp_fput(mpf, + dbc->thread_info, h, dbc->priority); + } + return (ret); +} + +/* + * __db_free_truncate -- + * Build a sorted free list and truncate free pages at the end + * of the file. + * + * PUBLIC: #ifdef HAVE_FTRUNCATE + * PUBLIC: int __db_free_truncate __P((DB *, DB_THREAD_INFO *, DB_TXN *, + * PUBLIC: u_int32_t, DB_COMPACT *, db_pglist_t **, u_int32_t *, + * PUBLIC: db_pgno_t *)); + * PUBLIC: #endif + */ +int +__db_free_truncate(dbp, ip, txn, flags, c_data, listp, nelemp, last_pgnop) + DB *dbp; + DB_THREAD_INFO *ip; + DB_TXN *txn; + u_int32_t flags; + DB_COMPACT *c_data; + db_pglist_t **listp; + u_int32_t *nelemp; + db_pgno_t *last_pgnop; +{ + DBC *dbc; + DBMETA *meta; + DB_LOCK metalock; + DB_MPOOLFILE *mpf; + ENV *env; + PAGE *h; + db_pglist_t *list, *lp; + db_pgno_t pgno; + u_int32_t nelems; + int ret, t_ret; + size_t size; + + COMPQUIET(flags, 0); + list = NULL; + meta = NULL; + env = dbp->env; + mpf = dbp->mpf; + h = NULL; + nelems = 0; + if (listp != NULL) { + *listp = NULL; + DB_ASSERT(env, nelemp != NULL); + *nelemp = 0; + } + + if ((ret = __db_cursor(dbp, ip, txn, &dbc, DB_WRITELOCK)) != 0) + return (ret); + + pgno = PGNO_BASE_MD; + if ((ret = __db_lget(dbc, + LCK_ALWAYS, pgno, DB_LOCK_WRITE, 0, &metalock)) != 0) + goto err; + if ((ret = __memp_fget(mpf, &pgno, dbc->thread_info, dbc->txn, 0, + &meta)) != 0) + goto err; + + if (last_pgnop != NULL) + *last_pgnop = meta->last_pgno; + if ((pgno = meta->free) == PGNO_INVALID) + goto done; + + size = 128; + if ((ret = __os_malloc(env, size * sizeof(*list), &list)) != 0) + goto err; + lp = list; + + do { + if (lp == &list[size]) { + size *= 2; + if ((ret = __os_realloc(env, + size * sizeof(*list), &list)) != 0) + goto err; + lp = &list[size / 2]; + } + if ((ret = __memp_fget(mpf, &pgno, + dbc->thread_info, dbc->txn, 0, &h)) != 0) + goto err; + + lp->pgno = pgno; + lp->next_pgno = NEXT_PGNO(h); + lp->lsn = LSN(h); + pgno = NEXT_PGNO(h); + if ((ret = __memp_fput(mpf, + dbc->thread_info, h, dbc->priority)) != 0) + goto err; + lp++; + } while (pgno != PGNO_INVALID); + nelems = (u_int32_t)(lp - list); + + if ((ret = __memp_dirty(mpf, + &meta, dbc->thread_info, dbc->txn, dbc->priority, 0)) != 0) + goto err; + + /* Sort the list */ + __db_freelist_sort(list, nelems); + + if ((ret = __db_pg_truncate(dbc, txn, list, c_data, + &nelems, meta->free, &meta->last_pgno, &LSN(meta), 0)) != 0) + goto err; + + if (nelems == 0) + meta->free = PGNO_INVALID; + else + meta->free = list[0].pgno; + +done: if (last_pgnop != NULL) + *last_pgnop = meta->last_pgno; + + /* + * The truncate point is the number of pages in the free + * list back from the last page. The number of pages + * in the free list are the number that we can swap in. + * Adjust it down slightly so if we find higher numbered + * pages early and then free other pages later we can + * truncate them. + */ + if (c_data) { + c_data->compact_truncate = (u_int32_t)meta->last_pgno - nelems; + if (c_data->compact_truncate > nelems >> 2) + c_data->compact_truncate -= nelems >> 2; + } + + if (nelems != 0 && listp != NULL) { + *listp = list; + *nelemp = nelems; + list = NULL; + } + +err: if (list != NULL) + __os_free(env, list); + if (meta != NULL && (t_ret = __memp_fput(mpf, + dbc->thread_info, (PAGE *)meta, dbc->priority)) != 0 && ret == 0) + ret = t_ret; + if ((t_ret = __TLPUT(dbc, metalock)) != 0 && ret == 0) + ret = t_ret; + if ((t_ret = __dbc_close(dbc)) != 0 && ret == 0) + ret = t_ret; + return (ret); +} + +static int +__db_truncate_freelist(dbc, meta, h, list, start, nelem) + DBC *dbc; + DBMETA *meta; + PAGE *h; + db_pgno_t *list; + u_int32_t start, nelem; +{ + DB *dbp; + DBT ddbt; + DB_LSN null_lsn; + DB_MPOOLFILE *mpf; + PAGE *last_free, *pg; + db_pgno_t *lp, free_pgno, lpgno; + db_pglist_t *plist, *pp, *spp; + u_int32_t elem, log_size; + int last, ret; + + dbp = dbc->dbp; + mpf = dbp->mpf; + plist = NULL; + last_free = NULL; + pg = NULL; + + if (start != 0 && + (ret = __memp_fget(mpf, &list[start - 1], + dbc->thread_info, dbc->txn, DB_MPOOL_DIRTY, &last_free)) != 0) + goto err; + + if (DBC_LOGGING(dbc)) { + if ((ret = __os_malloc(dbp->env, + (nelem - start) * sizeof(*pp), &plist)) != 0) + goto err; + + pp = plist; + for (lp = &list[start]; lp < &list[nelem]; lp++) { + pp->pgno = *lp; + if ((ret = __memp_fget(mpf, lp, + dbc->thread_info, dbc->txn, 0, &pg)) != 0) + goto err; + pp->lsn = LSN(pg); + pp->next_pgno = NEXT_PGNO(pg); + if ((ret = __memp_fput(mpf, + dbc->thread_info, pg, DB_PRIORITY_VERY_LOW)) != 0) + goto err; + pg = NULL; + pp++; + } + ZERO_LSN(null_lsn); + pp = plist; + elem = nelem - start; + log_size = ((LOG *)dbc->env-> + lg_handle->reginfo.primary)->log_size; +again: ddbt.data = spp = pp; + free_pgno = pp->pgno; + lpgno = meta->last_pgno; + ddbt.size = elem * sizeof(*pp); + if (ddbt.size > log_size / 2) { + elem = (log_size / 2) / (u_int32_t)sizeof(*pp); + ddbt.size = elem * sizeof(*pp); + pp += elem; + elem = (nelem - start) - (u_int32_t)(pp - plist); + lpgno = pp[-1].pgno; + last = 0; + } else + last = 1; + /* + * Get the page which will link to this section if we abort. + * If this is the first segment then its last_free. + */ + if (spp == plist) + pg = last_free; + else if ((ret = __memp_fget(mpf, &spp[-1].pgno, + dbc->thread_info, dbc->txn, DB_MPOOL_DIRTY, &pg)) != 0) + goto err; + + if ((ret = __db_pg_trunc_log(dbp, dbc->txn, + &LSN(meta), last == 1 ? DB_FLUSH : 0, + PGNO(meta), &LSN(meta), + pg != NULL ? PGNO(pg) : PGNO_INVALID, + pg != NULL ? &LSN(pg) : &null_lsn, + free_pgno, lpgno, &ddbt)) != 0) + goto err; + if (pg != NULL) { + LSN(pg) = LSN(meta); + if (pg != last_free && (ret = __memp_fput(mpf, + dbc->thread_info, pg, DB_PRIORITY_VERY_LOW)) != 0) + goto err; + pg = NULL; + } + if (last == 0) + goto again; + } else + LSN_NOT_LOGGED(LSN(meta)); + + if ((ret = __memp_fput(mpf, + dbc->thread_info, h, DB_PRIORITY_VERY_LOW)) != 0) + goto err; + h = NULL; + if ((ret = __memp_ftruncate(mpf, dbc->txn, dbc->thread_info, + list[start], 0)) != 0) + goto err; + meta->last_pgno = list[start] - 1; + + if (start == 0) + meta->free = PGNO_INVALID; + else { + NEXT_PGNO(last_free) = PGNO_INVALID; + if ((ret = __memp_fput(mpf, + dbc->thread_info, last_free, dbc->priority)) != 0) + goto err; + last_free = NULL; + } + + /* Shrink the number of elements in the list. */ + ret = __memp_extend_freelist(mpf, start, &list); + +err: if (plist != NULL) + __os_free(dbp->env, plist); + + /* We need to put the page on error. */ + if (h != NULL) + (void)__memp_fput(mpf, dbc->thread_info, h, dbc->priority); + if (pg != NULL && pg != last_free) + (void)__memp_fput(mpf, dbc->thread_info, pg, dbc->priority); + if (last_free != NULL) + (void)__memp_fput(mpf, + dbc->thread_info, last_free, dbc->priority); + + return (ret); +} +#endif diff -r 000000000000 -r a1985f14b030 src/db/db_method.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/db/db_method.c Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,1272 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 1999, 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + * $Id$ + */ + +#include "db_config.h" + +#include "db_int.h" +#include "dbinc/crypto.h" +#include "dbinc/db_page.h" +#include "dbinc/btree.h" +#include "dbinc/hash.h" +#include "dbinc/heap.h" +#include "dbinc/lock.h" +#include "dbinc/mp.h" +#include "dbinc/qam.h" +#include "dbinc/txn.h" + +static int __db_get_byteswapped __P((DB *, int *)); +static int __db_get_dbname __P((DB *, const char **, const char **)); +static DB_ENV *__db_get_env __P((DB *)); +static void __db_get_msgcall + __P((DB *, void (**)(const DB_ENV *, const char *))); +static DB_MPOOLFILE *__db_get_mpf __P((DB *)); +static int __db_get_multiple __P((DB *)); +static int __db_get_transactional __P((DB *)); +static int __db_get_type __P((DB *, DBTYPE *dbtype)); +static int __db_init __P((DB *, u_int32_t)); +static int __db_get_alloc __P((DB *, void *(**)(size_t), + void *(**)(void *, size_t), void (**)(void *))); +static int __db_set_alloc __P((DB *, void *(*)(size_t), + void *(*)(void *, size_t), void (*)(void *))); +static int __db_get_append_recno __P((DB *, + int (**)(DB *, DBT *, db_recno_t))); +static int __db_set_append_recno __P((DB *, int (*)(DB *, DBT *, db_recno_t))); +static int __db_get_cachesize __P((DB *, u_int32_t *, u_int32_t *, int *)); +static int __db_set_cachesize __P((DB *, u_int32_t, u_int32_t, int)); +static int __db_get_create_dir __P((DB *, const char **)); +static int __db_set_create_dir __P((DB *, const char *)); +static int __db_get_dup_compare + __P((DB *, int (**)(DB *, const DBT *, const DBT *))); +static int __db_set_dup_compare + __P((DB *, int (*)(DB *, const DBT *, const DBT *))); +static int __db_set_encrypt __P((DB *, const char *, u_int32_t)); +static int __db_get_feedback __P((DB *, void (**)(DB *, int, int))); +static int __db_set_feedback __P((DB *, void (*)(DB *, int, int))); +static void __db_map_flags __P((DB *, u_int32_t *, u_int32_t *)); +static int __db_get_pagesize __P((DB *, u_int32_t *)); +static int __db_set_paniccall __P((DB *, void (*)(DB_ENV *, int))); +static int __db_set_priority __P((DB *, DB_CACHE_PRIORITY)); +static int __db_get_priority __P((DB *, DB_CACHE_PRIORITY *)); +static void __db_get_errcall __P((DB *, + void (**)(const DB_ENV *, const char *, const char *))); +static void __db_set_errcall + __P((DB *, void (*)(const DB_ENV *, const char *, const char *))); +static void __db_get_errfile __P((DB *, FILE **)); +static void __db_set_errfile __P((DB *, FILE *)); +static void __db_get_errpfx __P((DB *, const char **)); +static void __db_set_errpfx __P((DB *, const char *)); +static void __db_set_msgcall + __P((DB *, void (*)(const DB_ENV *, const char *))); +static void __db_get_msgfile __P((DB *, FILE **)); +static void __db_set_msgfile __P((DB *, FILE *)); +static int __db_get_assoc_flags __P((DB *, u_int32_t *)); +static void __dbh_err __P((DB *, int, const char *, ...)); +static void __dbh_errx __P((DB *, const char *, ...)); + +/* + * db_create -- + * DB constructor. + * + * EXTERN: int db_create __P((DB **, DB_ENV *, u_int32_t)); + */ +int +db_create(dbpp, dbenv, flags) + DB **dbpp; + DB_ENV *dbenv; + u_int32_t flags; +{ + DB_THREAD_INFO *ip; + ENV *env; + int ret; + + ip = NULL; + env = dbenv == NULL ? NULL : dbenv->env; + + /* Check for invalid function flags. */ + switch (flags) { + case 0: + break; + case DB_XA_CREATE: + if (dbenv != NULL) { + __db_errx(env, DB_STR("0504", + "XA applications may not specify an environment to db_create")); + return (EINVAL); + } + + /* + * If it's an XA database, open it within the XA environment, + * taken from the global list of environments. (When the XA + * transaction manager called our xa_start() routine the + * "current" environment was moved to the start of the list. + */ + env = TAILQ_FIRST(&DB_GLOBAL(envq)); + if (env == NULL) { + __db_errx(env, DB_STR("0505", + "Cannot open XA database before XA is enabled")); + return (EINVAL); + } + break; + default: + return (__db_ferr(env, "db_create", 0)); + } + + if (env != NULL) + ENV_ENTER(env, ip); + + /* + * If we are opening an XA database, make sure we don't have a global XA + * transaction running. + */ + if (LF_ISSET(DB_XA_CREATE)) { + XA_NO_TXN(ip, ret); + if (ret != 0) + goto err; + } + + ret = __db_create_internal(dbpp, env, flags); +err: if (env != NULL) + ENV_LEAVE(env, ip); + + return (ret); +} + +/* + * __db_create_internal -- + * DB constructor internal routine. + * + * PUBLIC: int __db_create_internal __P((DB **, ENV *, u_int32_t)); + */ +int +__db_create_internal(dbpp, env, flags) + DB **dbpp; + ENV *env; + u_int32_t flags; +{ + DB *dbp; + DB_ENV *dbenv; + DB_REP *db_rep; + int ret; + + *dbpp = NULL; + + /* If we don't have an environment yet, allocate a local one. */ + if (env == NULL) { + if ((ret = db_env_create(&dbenv, 0)) != 0) + return (ret); + env = dbenv->env; + F_SET(env, ENV_DBLOCAL); + } else + dbenv = env->dbenv; + + /* Allocate and initialize the DB handle. */ + if ((ret = __os_calloc(env, 1, sizeof(*dbp), &dbp)) != 0) + goto err; + + dbp->dbenv = env->dbenv; + dbp->env = env; + if ((ret = __db_init(dbp, flags)) != 0) + goto err; + + MUTEX_LOCK(env, env->mtx_dblist); + ++env->db_ref; + MUTEX_UNLOCK(env, env->mtx_dblist); + + /* + * Set the replication timestamp; it's 0 if we're not in a replicated + * environment. Don't acquire a lock to read the value, even though + * it's opaque: all we check later is value equality, nothing else. + */ + dbp->timestamp = REP_ON(env) ? + ((REGENV *)env->reginfo->primary)->rep_timestamp : 0; + /* + * Set the replication generation number for fid management; valid + * replication generations start at 1. Don't acquire a lock to + * read the value. All we check later is value equality. + */ + db_rep = env->rep_handle; + dbp->fid_gen = REP_ON(env) ? ((REP *)db_rep->region)->gen : 0; + + /* Open a backing DB_MPOOLFILE handle in the memory pool. */ + if ((ret = __memp_fcreate(env, &dbp->mpf)) != 0) + goto err; + + dbp->type = DB_UNKNOWN; + + *dbpp = dbp; + return (0); + +err: if (dbp != NULL) { + if (dbp->mpf != NULL) + (void)__memp_fclose(dbp->mpf, 0); + __os_free(env, dbp); + } + + if (dbp != NULL && F_ISSET(env, ENV_DBLOCAL)) + (void)__env_close(dbp->dbenv, 0); + + return (ret); +} + +/* + * __db_init -- + * Initialize a DB structure. + */ +static int +__db_init(dbp, flags) + DB *dbp; + u_int32_t flags; +{ + int ret; + + dbp->locker = NULL; + dbp->alt_close = NULL; + LOCK_INIT(dbp->handle_lock); + + TAILQ_INIT(&dbp->free_queue); + TAILQ_INIT(&dbp->active_queue); + TAILQ_INIT(&dbp->join_queue); + LIST_INIT(&dbp->s_secondaries); + + FLD_SET(dbp->am_ok, + DB_OK_BTREE | DB_OK_HASH | DB_OK_HEAP | DB_OK_QUEUE | DB_OK_RECNO); + + /* DB PUBLIC HANDLE LIST BEGIN */ + dbp->associate = __db_associate_pp; + dbp->close = __db_close_pp; + dbp->cursor = __db_cursor_pp; + dbp->del = __db_del_pp; + dbp->dump = __db_dump_pp; + dbp->err = __dbh_err; + dbp->errx = __dbh_errx; + dbp->exists = __db_exists; + dbp->fd = __db_fd_pp; + dbp->get = __db_get_pp; + dbp->get_alloc = __db_get_alloc; + dbp->get_append_recno = __db_get_append_recno; + dbp->get_assoc_flags = __db_get_assoc_flags; + dbp->get_byteswapped = __db_get_byteswapped; + dbp->get_cachesize = __db_get_cachesize; + dbp->get_create_dir = __db_get_create_dir; + dbp->get_dbname = __db_get_dbname; + dbp->get_dup_compare = __db_get_dup_compare; + dbp->get_env = __db_get_env; + dbp->get_errcall = __db_get_errcall; + dbp->get_errfile = __db_get_errfile; + dbp->get_errpfx = __db_get_errpfx; + dbp->get_feedback = __db_get_feedback; + dbp->get_flags = __db_get_flags; + dbp->get_lorder = __db_get_lorder; + dbp->get_mpf = __db_get_mpf; + dbp->get_msgcall = __db_get_msgcall; + dbp->get_msgfile = __db_get_msgfile; + dbp->get_multiple = __db_get_multiple; + dbp->get_open_flags = __db_get_open_flags; + dbp->get_pagesize = __db_get_pagesize; + dbp->get_priority = __db_get_priority; + dbp->get_transactional = __db_get_transactional; + dbp->get_type = __db_get_type; + dbp->key_range = __db_key_range_pp; + dbp->open = __db_open_pp; + dbp->pget = __db_pget_pp; + dbp->put = __db_put_pp; + dbp->remove = __db_remove_pp; + dbp->rename = __db_rename_pp; + dbp->set_alloc = __db_set_alloc; + dbp->set_append_recno = __db_set_append_recno; + dbp->set_cachesize = __db_set_cachesize; + dbp->set_create_dir = __db_set_create_dir; + dbp->set_dup_compare = __db_set_dup_compare; + dbp->set_encrypt = __db_set_encrypt; + dbp->set_errcall = __db_set_errcall; + dbp->set_errfile = __db_set_errfile; + dbp->set_errpfx = __db_set_errpfx; + dbp->set_feedback = __db_set_feedback; + dbp->set_flags = __db_set_flags; + dbp->set_lorder = __db_set_lorder; + dbp->set_msgcall = __db_set_msgcall; + dbp->set_msgfile = __db_set_msgfile; + dbp->set_pagesize = __db_set_pagesize; + dbp->set_paniccall = __db_set_paniccall; + dbp->set_priority = __db_set_priority; + dbp->sort_multiple = __db_sort_multiple; + dbp->stat = __db_stat_pp; + dbp->stat_print = __db_stat_print_pp; + dbp->sync = __db_sync_pp; + dbp->truncate = __db_truncate_pp; + dbp->verify = __db_verify_pp; + /* DB PUBLIC HANDLE LIST END */ + + /* Access method specific. */ + if ((ret = __bam_db_create(dbp)) != 0) + return (ret); + if ((ret = __ham_db_create(dbp)) != 0) + return (ret); + if ((ret = __heap_db_create(dbp)) != 0) + return (ret); + if ((ret = __qam_db_create(dbp)) != 0) + return (ret); + + COMPQUIET(flags, 0); + + return (0); +} + +/* + * __dbh_am_chk -- + * Error if an unreasonable method is called. + * + * PUBLIC: int __dbh_am_chk __P((DB *, u_int32_t)); + */ +int +__dbh_am_chk(dbp, flags) + DB *dbp; + u_int32_t flags; +{ + /* + * We start out allowing any access methods to be called, and as the + * application calls the methods the options become restricted. The + * idea is to quit as soon as an illegal method combination is called. + */ + if ((LF_ISSET(DB_OK_BTREE) && FLD_ISSET(dbp->am_ok, DB_OK_BTREE)) || + (LF_ISSET(DB_OK_HASH) && FLD_ISSET(dbp->am_ok, DB_OK_HASH)) || + (LF_ISSET(DB_OK_HEAP) && FLD_ISSET(dbp->am_ok, DB_OK_HEAP)) || + (LF_ISSET(DB_OK_QUEUE) && FLD_ISSET(dbp->am_ok, DB_OK_QUEUE)) || + (LF_ISSET(DB_OK_RECNO) && FLD_ISSET(dbp->am_ok, DB_OK_RECNO))) { + FLD_CLR(dbp->am_ok, ~flags); + return (0); + } + + __db_errx(dbp->env, DB_STR("0506", +"call implies an access method which is inconsistent with previous calls")); + return (EINVAL); +} + +/* + * __dbh_err -- + * Db.err method. + */ +static void +#ifdef STDC_HEADERS +__dbh_err(DB *dbp, int error, const char *fmt, ...) +#else +__dbh_err(dbp, error, fmt, va_alist) + DB *dbp; + int error; + const char *fmt; + va_dcl +#endif +{ + /* Message with error string, to stderr by default. */ + DB_REAL_ERR(dbp->dbenv, error, DB_ERROR_SET, 1, fmt); +} + +/* + * __dbh_errx -- + * Db.errx method. + */ +static void +#ifdef STDC_HEADERS +__dbh_errx(DB *dbp, const char *fmt, ...) +#else +__dbh_errx(dbp, fmt, va_alist) + DB *dbp; + const char *fmt; + va_dcl +#endif +{ + /* Message without error string, to stderr by default. */ + DB_REAL_ERR(dbp->dbenv, 0, DB_ERROR_NOT_SET, 1, fmt); +} + +/* + * __db_get_byteswapped -- + * Return if database requires byte swapping. + */ +static int +__db_get_byteswapped(dbp, isswapped) + DB *dbp; + int *isswapped; +{ + DB_ILLEGAL_BEFORE_OPEN(dbp, "DB->get_byteswapped"); + + *isswapped = F_ISSET(dbp, DB_AM_SWAP) ? 1 : 0; + return (0); +} + +/* + * __db_get_dbname -- + * Get the name of the database as passed to DB->open. + */ +static int +__db_get_dbname(dbp, fnamep, dnamep) + DB *dbp; + const char **fnamep, **dnamep; +{ + DB_ILLEGAL_BEFORE_OPEN(dbp, "DB->get_dbname"); + + if (fnamep != NULL) + *fnamep = dbp->fname; + if (dnamep != NULL) + *dnamep = dbp->dname; + return (0); +} + +/* + * __db_get_env -- + * Get the DB_ENV handle that was passed to db_create. + */ +static DB_ENV * +__db_get_env(dbp) + DB *dbp; +{ + return (dbp->dbenv); +} + +/* + * __db_get_mpf -- + * Get the underlying DB_MPOOLFILE handle. + */ +static DB_MPOOLFILE * +__db_get_mpf(dbp) + DB *dbp; +{ + return (dbp->mpf); +} + +/* + * get_multiple -- + * Return whether this DB handle references a physical file with multiple + * databases. + */ +static int +__db_get_multiple(dbp) + DB *dbp; +{ + DB_ILLEGAL_BEFORE_OPEN(dbp, "DB->get_multiple"); + + /* + * Only return TRUE if the handle is for the master database, not for + * any subdatabase in the physical file. If it's a Btree, with the + * subdatabases flag set, and the meta-data page has the right value, + * return TRUE. (We don't need to check it's a Btree, I suppose, but + * it doesn't hurt.) + */ + return (dbp->type == DB_BTREE && + F_ISSET(dbp, DB_AM_SUBDB) && + dbp->meta_pgno == PGNO_BASE_MD ? 1 : 0); +} + +/* + * get_transactional -- + * Return whether this database was created in a transaction. + */ +static int +__db_get_transactional(dbp) + DB *dbp; +{ + return (F_ISSET(dbp, DB_AM_TXN) ? 1 : 0); +} + +/* + * __db_get_type -- + * Return type of underlying database. + */ +static int +__db_get_type(dbp, dbtype) + DB *dbp; + DBTYPE *dbtype; +{ + DB_ILLEGAL_BEFORE_OPEN(dbp, "DB->get_type"); + + *dbtype = dbp->type; + return (0); +} + +/* + * __db_get_append_recno -- + * Get record number append routine. + */ +static int +__db_get_append_recno(dbp, funcp) + DB *dbp; + int (**funcp) __P((DB *, DBT *, db_recno_t)); +{ + DB_ILLEGAL_METHOD(dbp, DB_OK_QUEUE | DB_OK_RECNO); + if (funcp) + *funcp = dbp->db_append_recno; + + return (0); +} +/* + * __db_set_append_recno -- + * Set record number append routine. + */ +static int +__db_set_append_recno(dbp, func) + DB *dbp; + int (*func) __P((DB *, DBT *, db_recno_t)); +{ + DB_ILLEGAL_AFTER_OPEN(dbp, "DB->set_append_recno"); + DB_ILLEGAL_METHOD(dbp, DB_OK_QUEUE | DB_OK_RECNO); + + dbp->db_append_recno = func; + + return (0); +} + +/* + * __db_get_cachesize -- + * Get underlying cache size. + */ +static int +__db_get_cachesize(dbp, cache_gbytesp, cache_bytesp, ncachep) + DB *dbp; + u_int32_t *cache_gbytesp, *cache_bytesp; + int *ncachep; +{ + DB_ILLEGAL_IN_ENV(dbp, "DB->get_cachesize"); + + return (__memp_get_cachesize(dbp->dbenv, + cache_gbytesp, cache_bytesp, ncachep)); +} + +/* + * __db_set_cachesize -- + * Set underlying cache size. + */ +static int +__db_set_cachesize(dbp, cache_gbytes, cache_bytes, ncache) + DB *dbp; + u_int32_t cache_gbytes, cache_bytes; + int ncache; +{ + DB_ILLEGAL_IN_ENV(dbp, "DB->set_cachesize"); + DB_ILLEGAL_AFTER_OPEN(dbp, "DB->set_cachesize"); + + return (__memp_set_cachesize( + dbp->dbenv, cache_gbytes, cache_bytes, ncache)); +} + +static int +__db_set_create_dir(dbp, dir) + DB *dbp; + const char *dir; +{ + DB_ENV *dbenv; + int i; + + dbenv = dbp->dbenv; + + for (i = 0; i < dbenv->data_next; i++) + if (strcmp(dir, dbenv->db_data_dir[i]) == 0) + break; + + if (i == dbenv->data_next) { + __db_errx(dbp->env, DB_STR_A("0507", + "Directory %s not in environment list.", "%s"), dir); + return (EINVAL); + } + + dbp->dirname = dbenv->db_data_dir[i]; + return (0); +} + +static int +__db_get_create_dir(dbp, dirp) + DB *dbp; + const char **dirp; +{ + *dirp = dbp->dirname; + return (0); +} + +/* + * __db_get_dup_compare -- + * Get duplicate comparison routine. + */ +static int +__db_get_dup_compare(dbp, funcp) + DB *dbp; + int (**funcp) __P((DB *, const DBT *, const DBT *)); +{ + + DB_ILLEGAL_METHOD(dbp, DB_OK_BTREE | DB_OK_HASH); + + if (funcp != NULL) { +#ifdef HAVE_COMPRESSION + if (DB_IS_COMPRESSED(dbp)) { + *funcp = + ((BTREE *)dbp->bt_internal)->compress_dup_compare; + } else +#endif + *funcp = dbp->dup_compare; + } + + return (0); +} + +/* + * __db_set_dup_compare -- + * Set duplicate comparison routine. + */ +static int +__db_set_dup_compare(dbp, func) + DB *dbp; + int (*func) __P((DB *, const DBT *, const DBT *)); +{ + int ret; + + DB_ILLEGAL_AFTER_OPEN(dbp, "DB->set_dup_compare"); + DB_ILLEGAL_METHOD(dbp, DB_OK_BTREE | DB_OK_HASH); + + if ((ret = __db_set_flags(dbp, DB_DUPSORT)) != 0) + return (ret); + +#ifdef HAVE_COMPRESSION + if (DB_IS_COMPRESSED(dbp)) { + dbp->dup_compare = __bam_compress_dupcmp; + ((BTREE *)dbp->bt_internal)->compress_dup_compare = func; + } else +#endif + dbp->dup_compare = func; + + return (0); +} + +/* + * __db_set_encrypt -- + * Set database passwd. + */ +static int +__db_set_encrypt(dbp, passwd, flags) + DB *dbp; + const char *passwd; + u_int32_t flags; +{ + DB_CIPHER *db_cipher; + int ret; + + DB_ILLEGAL_IN_ENV(dbp, "DB->set_encrypt"); + DB_ILLEGAL_AFTER_OPEN(dbp, "DB->set_encrypt"); + + if ((ret = __env_set_encrypt(dbp->dbenv, passwd, flags)) != 0) + return (ret); + + /* + * In a real env, this gets initialized with the region. In a local + * env, we must do it here. + */ + db_cipher = dbp->env->crypto_handle; + if (!F_ISSET(db_cipher, CIPHER_ANY) && + (ret = db_cipher->init(dbp->env, db_cipher)) != 0) + return (ret); + + return (__db_set_flags(dbp, DB_ENCRYPT)); +} + +static void +__db_get_errcall(dbp, errcallp) + DB *dbp; + void (**errcallp) __P((const DB_ENV *, const char *, const char *)); +{ + __env_get_errcall(dbp->dbenv, errcallp); +} + +static void +__db_set_errcall(dbp, errcall) + DB *dbp; + void (*errcall) __P((const DB_ENV *, const char *, const char *)); +{ + __env_set_errcall(dbp->dbenv, errcall); +} + +static void +__db_get_errfile(dbp, errfilep) + DB *dbp; + FILE **errfilep; +{ + __env_get_errfile(dbp->dbenv, errfilep); +} + +static void +__db_set_errfile(dbp, errfile) + DB *dbp; + FILE *errfile; +{ + __env_set_errfile(dbp->dbenv, errfile); +} + +static void +__db_get_errpfx(dbp, errpfxp) + DB *dbp; + const char **errpfxp; +{ + __env_get_errpfx(dbp->dbenv, errpfxp); +} + +static void +__db_set_errpfx(dbp, errpfx) + DB *dbp; + const char *errpfx; +{ + __env_set_errpfx(dbp->dbenv, errpfx); +} + +static int +__db_get_feedback(dbp, feedbackp) + DB *dbp; + void (**feedbackp) __P((DB *, int, int)); +{ + if (feedbackp != NULL) + *feedbackp = dbp->db_feedback; + return (0); +} + +static int +__db_set_feedback(dbp, feedback) + DB *dbp; + void (*feedback) __P((DB *, int, int)); +{ + dbp->db_feedback = feedback; + return (0); +} + +/* + * __db_map_flags -- + * Maps between public and internal flag values. + * This function doesn't check for validity, so it can't fail. + */ +static void +__db_map_flags(dbp, inflagsp, outflagsp) + DB *dbp; + u_int32_t *inflagsp, *outflagsp; +{ + COMPQUIET(dbp, NULL); + + if (FLD_ISSET(*inflagsp, DB_CHKSUM)) { + FLD_SET(*outflagsp, DB_AM_CHKSUM); + FLD_CLR(*inflagsp, DB_CHKSUM); + } + if (FLD_ISSET(*inflagsp, DB_ENCRYPT)) { + FLD_SET(*outflagsp, DB_AM_ENCRYPT | DB_AM_CHKSUM); + FLD_CLR(*inflagsp, DB_ENCRYPT); + } + if (FLD_ISSET(*inflagsp, DB_TXN_NOT_DURABLE)) { + FLD_SET(*outflagsp, DB_AM_NOT_DURABLE); + FLD_CLR(*inflagsp, DB_TXN_NOT_DURABLE); + } +} + +/* + * __db_get_assoc_flags -- + */ +static int +__db_get_assoc_flags(dbp, flagsp) + DB *dbp; + u_int32_t *flagsp; +{ + DB_ILLEGAL_BEFORE_OPEN(dbp, "DB->get_assoc_flags"); + + *flagsp = dbp->s_assoc_flags; + return (0); +} + +/* + * __db_get_flags -- + * The DB->get_flags method. + * + * PUBLIC: int __db_get_flags __P((DB *, u_int32_t *)); + */ +int +__db_get_flags(dbp, flagsp) + DB *dbp; + u_int32_t *flagsp; +{ + static const u_int32_t db_flags[] = { + DB_CHKSUM, + DB_DUP, + DB_DUPSORT, + DB_ENCRYPT, +#ifdef HAVE_QUEUE + DB_INORDER, +#endif + DB_RECNUM, + DB_RENUMBER, + DB_REVSPLITOFF, + DB_SNAPSHOT, + DB_TXN_NOT_DURABLE, + 0 + }; + u_int32_t f, flags, mapped_flag; + int i; + + flags = 0; + for (i = 0; (f = db_flags[i]) != 0; i++) { + mapped_flag = 0; + __db_map_flags(dbp, &f, &mapped_flag); + __bam_map_flags(dbp, &f, &mapped_flag); + __ram_map_flags(dbp, &f, &mapped_flag); +#ifdef HAVE_QUEUE + __qam_map_flags(dbp, &f, &mapped_flag); +#endif + DB_ASSERT(dbp->env, f == 0); + if (F_ISSET(dbp, mapped_flag) == mapped_flag) + LF_SET(db_flags[i]); + } + + *flagsp = flags; + return (0); +} + +/* + * __db_set_flags -- + * DB->set_flags. + * + * PUBLIC: int __db_set_flags __P((DB *, u_int32_t)); + */ +int +__db_set_flags(dbp, flags) + DB *dbp; + u_int32_t flags; +{ + ENV *env; + int ret; + + env = dbp->env; + + if (LF_ISSET(DB_ENCRYPT) && !CRYPTO_ON(env)) { + __db_errx(env, DB_STR("0508", + "Database environment not configured for encryption")); + return (EINVAL); + } + if (LF_ISSET(DB_TXN_NOT_DURABLE)) + ENV_REQUIRES_CONFIG(env, + env->tx_handle, "DB_NOT_DURABLE", DB_INIT_TXN); + + __db_map_flags(dbp, &flags, &dbp->flags); + + if ((ret = __bam_set_flags(dbp, &flags)) != 0) + return (ret); + if ((ret = __ram_set_flags(dbp, &flags)) != 0) + return (ret); +#ifdef HAVE_QUEUE + if ((ret = __qam_set_flags(dbp, &flags)) != 0) + return (ret); +#endif + + return (flags == 0 ? 0 : __db_ferr(env, "DB->set_flags", 0)); +} + +/* + * __db_get_lorder -- + * Get whether lorder is swapped or not. + * + * PUBLIC: int __db_get_lorder __P((DB *, int *)); + */ +int +__db_get_lorder(dbp, db_lorderp) + DB *dbp; + int *db_lorderp; +{ + int ret; + + /* Flag if the specified byte order requires swapping. */ + switch (ret = __db_byteorder(dbp->env, 1234)) { + case 0: + *db_lorderp = F_ISSET(dbp, DB_AM_SWAP) ? 4321 : 1234; + break; + case DB_SWAPBYTES: + *db_lorderp = F_ISSET(dbp, DB_AM_SWAP) ? 1234 : 4321; + break; + default: + return (ret); + /* NOTREACHED */ + } + + return (0); +} + +/* + * __db_set_lorder -- + * Set whether lorder is swapped or not. + * + * PUBLIC: int __db_set_lorder __P((DB *, int)); + */ +int +__db_set_lorder(dbp, db_lorder) + DB *dbp; + int db_lorder; +{ + int ret; + + DB_ILLEGAL_AFTER_OPEN(dbp, "DB->set_lorder"); + + /* Flag if the specified byte order requires swapping. */ + switch (ret = __db_byteorder(dbp->env, db_lorder)) { + case 0: + F_CLR(dbp, DB_AM_SWAP); + break; + case DB_SWAPBYTES: + F_SET(dbp, DB_AM_SWAP); + break; + default: + return (ret); + /* NOTREACHED */ + } + return (0); +} + +static int +__db_get_alloc(dbp, mal_funcp, real_funcp, free_funcp) + DB *dbp; + void *(**mal_funcp) __P((size_t)); + void *(**real_funcp) __P((void *, size_t)); + void (**free_funcp) __P((void *)); +{ + DB_ILLEGAL_IN_ENV(dbp, "DB->get_alloc"); + + return (__env_get_alloc(dbp->dbenv, mal_funcp, + real_funcp, free_funcp)); +} + +static int +__db_set_alloc(dbp, mal_func, real_func, free_func) + DB *dbp; + void *(*mal_func) __P((size_t)); + void *(*real_func) __P((void *, size_t)); + void (*free_func) __P((void *)); +{ + DB_ILLEGAL_IN_ENV(dbp, "DB->set_alloc"); + DB_ILLEGAL_AFTER_OPEN(dbp, "DB->set_alloc"); + + return (__env_set_alloc(dbp->dbenv, mal_func, real_func, free_func)); +} + +static void +__db_get_msgcall(dbp, msgcallp) + DB *dbp; + void (**msgcallp) __P((const DB_ENV *, const char *)); +{ + __env_get_msgcall(dbp->dbenv, msgcallp); +} + +static void +__db_set_msgcall(dbp, msgcall) + DB *dbp; + void (*msgcall) __P((const DB_ENV *, const char *)); +{ + __env_set_msgcall(dbp->dbenv, msgcall); +} + +static void +__db_get_msgfile(dbp, msgfilep) + DB *dbp; + FILE **msgfilep; +{ + __env_get_msgfile(dbp->dbenv, msgfilep); +} + +static void +__db_set_msgfile(dbp, msgfile) + DB *dbp; + FILE *msgfile; +{ + __env_set_msgfile(dbp->dbenv, msgfile); +} + +static int +__db_get_pagesize(dbp, db_pagesizep) + DB *dbp; + u_int32_t *db_pagesizep; +{ + *db_pagesizep = dbp->pgsize; + return (0); +} + +/* + * __db_set_pagesize -- + * DB->set_pagesize + * + * PUBLIC: int __db_set_pagesize __P((DB *, u_int32_t)); + */ +int +__db_set_pagesize(dbp, db_pagesize) + DB *dbp; + u_int32_t db_pagesize; +{ + DB_ILLEGAL_AFTER_OPEN(dbp, "DB->set_pagesize"); + + if (db_pagesize < DB_MIN_PGSIZE) { + __db_errx(dbp->env, DB_STR_A("0509", + "page sizes may not be smaller than %lu", "%lu"), + (u_long)DB_MIN_PGSIZE); + return (EINVAL); + } + if (db_pagesize > DB_MAX_PGSIZE) { + __db_errx(dbp->env, DB_STR_A("0510", + "page sizes may not be larger than %lu", "%lu"), + (u_long)DB_MAX_PGSIZE); + return (EINVAL); + } + + /* + * We don't want anything that's not a power-of-2, as we rely on that + * for alignment of various types on the pages. + */ + if (!POWER_OF_TWO(db_pagesize)) { + __db_errx(dbp->env, DB_STR("0511", + "page sizes must be a power-of-2")); + return (EINVAL); + } + + /* + * XXX + * Should we be checking for a page size that's not a multiple of 512, + * so that we never try and write less than a disk sector? + */ + dbp->pgsize = db_pagesize; + + return (0); +} + +static int +__db_set_paniccall(dbp, paniccall) + DB *dbp; + void (*paniccall) __P((DB_ENV *, int)); +{ + return (__env_set_paniccall(dbp->dbenv, paniccall)); +} + +static int +__db_set_priority(dbp, priority) + DB *dbp; + DB_CACHE_PRIORITY priority; +{ + dbp->priority = priority; + return (0); +} + +static int +__db_get_priority(dbp, priority) + DB *dbp; + DB_CACHE_PRIORITY *priority; +{ + if (dbp->priority == DB_PRIORITY_UNCHANGED) + return (__memp_get_priority(dbp->mpf, priority)); + else + *priority = dbp->priority; + + return (0); +} + +/* + * __db_relink -- + * Relink around a deleted page. + * + * PUBLIC: int __db_relink __P((DBC *, PAGE *, PAGE *, db_pgno_t)); + * Otherp can be either the previous or the next page to use if + * the caller already holds that page. + */ +int +__db_relink(dbc, pagep, otherp, new_pgno) + DBC *dbc; + PAGE *pagep, *otherp; + db_pgno_t new_pgno; +{ + DB *dbp; + DB_LOCK npl, ppl; + DB_LSN *nlsnp, *plsnp, ret_lsn; + DB_MPOOLFILE *mpf; + PAGE *np, *pp; + int ret, t_ret; + + dbp = dbc->dbp; + np = pp = NULL; + LOCK_INIT(npl); + LOCK_INIT(ppl); + nlsnp = plsnp = NULL; + mpf = dbp->mpf; + ret = 0; + + /* + * Retrieve the one/two pages. The caller must have them locked + * because the parent is latched. For a remove, we may need + * two pages (the before and after). For an add, we only need one + * because, the split took care of the prev. + */ + if (pagep->next_pgno != PGNO_INVALID) { + if (((np = otherp) == NULL || + PGNO(otherp) != pagep->next_pgno) && + (ret = __memp_fget(mpf, &pagep->next_pgno, + dbc->thread_info, dbc->txn, DB_MPOOL_DIRTY, &np)) != 0) { + ret = __db_pgerr(dbp, pagep->next_pgno, ret); + goto err; + } + nlsnp = &np->lsn; + } + if (pagep->prev_pgno != PGNO_INVALID) { + if (((pp = otherp) == NULL || + PGNO(otherp) != pagep->prev_pgno) && + (ret = __memp_fget(mpf, &pagep->prev_pgno, + dbc->thread_info, dbc->txn, DB_MPOOL_DIRTY, &pp)) != 0) { + ret = __db_pgerr(dbp, pagep->prev_pgno, ret); + goto err; + } + plsnp = &pp->lsn; + } + + /* Log the change. */ + if (DBC_LOGGING(dbc)) { + if ((ret = __db_relink_log(dbp, dbc->txn, &ret_lsn, 0, + pagep->pgno, new_pgno, pagep->prev_pgno, plsnp, + pagep->next_pgno, nlsnp)) != 0) + goto err; + } else + LSN_NOT_LOGGED(ret_lsn); + if (np != NULL) + np->lsn = ret_lsn; + if (pp != NULL) + pp->lsn = ret_lsn; + + /* + * Modify and release the two pages. + */ + if (np != NULL) { + if (new_pgno == PGNO_INVALID) + np->prev_pgno = pagep->prev_pgno; + else + np->prev_pgno = new_pgno; + if (np != otherp) + ret = __memp_fput(mpf, + dbc->thread_info, np, dbc->priority); + if ((t_ret = __TLPUT(dbc, npl)) != 0 && ret == 0) + ret = t_ret; + if (ret != 0) + goto err; + } + + if (pp != NULL) { + if (new_pgno == PGNO_INVALID) + pp->next_pgno = pagep->next_pgno; + else + pp->next_pgno = new_pgno; + if (pp != otherp) + ret = __memp_fput(mpf, + dbc->thread_info, pp, dbc->priority); + if ((t_ret = __TLPUT(dbc, ppl)) != 0 && ret == 0) + ret = t_ret; + if (ret != 0) + goto err; + } + return (0); + +err: if (np != NULL && np != otherp) + (void)__memp_fput(mpf, dbc->thread_info, np, dbc->priority); + if (pp != NULL && pp != otherp) + (void)__memp_fput(mpf, dbc->thread_info, pp, dbc->priority); + return (ret); +} + +#ifdef DIAGNOSTIC +/* + * __db_haslock -- + * Determine if this locker holds a particular lock. + * Returns 0 if lock is held, non-zero otherwise. + * + * PUBLIC: #ifdef DIAGNOSTIC + * PUBLIC: int __db_haslock __P((ENV *, DB_LOCKER *, + * PUBLIC: DB_MPOOLFILE *, db_pgno_t, db_lockmode_t, u_int32_t)); + * PUBLIC: #endif + */ +int +__db_haslock(env, locker, dbmfp, pgno, mode, type) + ENV *env; + DB_LOCKER *locker; + DB_MPOOLFILE *dbmfp; + db_pgno_t pgno; + db_lockmode_t mode; + u_int32_t type; +{ + DBT lkdata; + DB_LOCK lock; + DB_LOCK_ILOCK ilock; + + memset(&lkdata, 0, sizeof(lkdata)); + lkdata.data = &ilock; + lkdata.size = sizeof(ilock); + + memcpy(ilock.fileid, dbmfp->fileid, DB_FILE_ID_LEN); + ilock.pgno = pgno; + ilock.type = type; + + return (__lock_get(env, locker, DB_LOCK_CHECK, &lkdata, mode, &lock)); +} + +/* + * __db_has_pagelock -- + * Determine if this locker holds a particular page lock. + * Returns 0 if lock is held, non-zero otherwise. + * + * PUBLIC: #ifdef DIAGNOSTIC + * PUBLIC: int __db_has_pagelock __P((ENV *, DB_LOCKER *, + * PUBLIC: DB_MPOOLFILE *, PAGE *, db_lockmode_t)); + * PUBLIC: #endif + */ +int +__db_has_pagelock(env, locker, dbmfp, pagep, mode) + ENV *env; + DB_LOCKER *locker; + DB_MPOOLFILE *dbmfp; + PAGE *pagep; + db_lockmode_t mode; +{ + int ret; + + switch (pagep->type) { + case P_OVERFLOW: + case P_INVALID: + case P_QAMDATA: + case P_QAMMETA: + case P_IHEAP: + return (0); + case P_HASH: + if (PREV_PGNO(pagep) != PGNO_INVALID) + return (0); + break; + default: + break; + } + if ((ret = __db_haslock(env, + locker, dbmfp, pagep->pgno, mode, DB_PAGE_LOCK)) != 0) + ret = __db_haslock(env, + locker, dbmfp, PGNO_BASE_MD, mode, DB_DATABASE_LOCK); + return (ret); +} +#endif diff -r 000000000000 -r a1985f14b030 src/db/db_open.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/db/db_open.c Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,879 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 1996, 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + * $Id$ + */ + +#include "db_config.h" + +#include "db_int.h" +#include "dbinc/db_page.h" +#include "dbinc/db_swap.h" +#include "dbinc/btree.h" +#include "dbinc/crypto.h" +#include "dbinc/hmac.h" +#include "dbinc/fop.h" +#include "dbinc/hash.h" +#include "dbinc/heap.h" +#include "dbinc/lock.h" +#include "dbinc/mp.h" +#include "dbinc/qam.h" +#include "dbinc/txn.h" + +static int __db_handle_lock __P((DB *)); + +/* + * __db_open -- + * DB->open method. + * + * This routine gets called in three different ways: + * + * 1. It can be called to open a file/database. In this case, subdb will + * be NULL and meta_pgno will be PGNO_BASE_MD. + * 2. It can be called to open a subdatabase during normal operation. In + * this case, name and subname will both be non-NULL and meta_pgno will + * be PGNO_BASE_MD (also PGNO_INVALID). + * 3. It can be called to open an in-memory database (name == NULL; + * subname = name). + * 4. It can be called during recovery to open a file/database, in which case + * name will be non-NULL, subname will be NULL, and meta-pgno will be + * PGNO_BASE_MD. + * 5. It can be called during recovery to open a subdatabase, in which case + * name will be non-NULL, subname may be NULL and meta-pgno will be + * a valid pgno (i.e., not PGNO_BASE_MD). + * 6. It can be called during recovery to open an in-memory database. + * + * PUBLIC: int __db_open __P((DB *, DB_THREAD_INFO *, DB_TXN *, + * PUBLIC: const char *, const char *, DBTYPE, u_int32_t, int, db_pgno_t)); + */ +int +__db_open(dbp, ip, txn, fname, dname, type, flags, mode, meta_pgno) + DB *dbp; + DB_THREAD_INFO *ip; + DB_TXN *txn; + const char *fname, *dname; + DBTYPE type; + u_int32_t flags; + int mode; + db_pgno_t meta_pgno; +{ + DB *tdbp; + ENV *env; + int ret; + u_int32_t id; + + env = dbp->env; + id = TXN_INVALID; + + /* + * We must flush any existing pages before truncating the file + * since they could age out of mpool and overwrite new pages. + */ + if (LF_ISSET(DB_TRUNCATE)) { + if ((ret = __db_create_internal(&tdbp, dbp->env, 0)) != 0) + goto err; + ret = __db_open(tdbp, ip, txn, fname, dname, DB_UNKNOWN, + DB_NOERROR | (flags & ~(DB_TRUNCATE|DB_CREATE)), + mode, meta_pgno); + if (ret == 0) + ret = __memp_ftruncate(tdbp->mpf, txn, ip, 0, 0); + (void)__db_close(tdbp, txn, DB_NOSYNC); + if (ret != 0 && ret != ENOENT && ret != EINVAL) + goto err; + ret = 0; + } + + DB_TEST_RECOVERY(dbp, DB_TEST_PREOPEN, ret, fname); + + /* + * If the environment was configured with threads, the DB handle + * must also be free-threaded, so we force the DB_THREAD flag on. + * (See SR #2033 for why this is a requirement--recovery needs + * to be able to grab a dbp using __db_fileid_to_dbp, and it has + * no way of knowing which dbp goes with which thread, so whichever + * one it finds has to be usable in any of them.) + */ + if (F_ISSET(env, ENV_THREAD)) + LF_SET(DB_THREAD); + + /* Convert any DB->open flags. */ + if (LF_ISSET(DB_RDONLY)) + F_SET(dbp, DB_AM_RDONLY); + if (LF_ISSET(DB_READ_UNCOMMITTED)) + F_SET(dbp, DB_AM_READ_UNCOMMITTED); + + if (IS_REAL_TXN(txn)) + F_SET(dbp, DB_AM_TXN); + + /* Fill in the type. */ + dbp->type = type; + + /* Save the file and database names. */ + if ((fname != NULL && + (ret = __os_strdup(env, fname, &dbp->fname)) != 0)) + goto err; + if ((dname != NULL && + (ret = __os_strdup(env, dname, &dbp->dname)) != 0)) + goto err; + + /* + * If both fname and subname are NULL, it's always a create, so make + * sure that we have both DB_CREATE and a type specified. It would + * be nice if this checking were done in __db_open where most of the + * interface checking is done, but this interface (__db_dbopen) is + * used by the recovery and limbo system, so we need to safeguard + * this interface as well. + */ + if (fname == NULL) { + if (dbp->p_internal != NULL) { + __db_errx(env, DB_STR("0634", + "Partitioned databases may not be in memory.")); + return (ENOENT); + } + if (dname == NULL) { + if (!LF_ISSET(DB_CREATE)) { + __db_errx(env, DB_STR("0635", + "DB_CREATE must be specified to create databases.")); + return (ENOENT); + } + + F_SET(dbp, DB_AM_INMEM); + F_SET(dbp, DB_AM_CREATED); + + if (dbp->type == DB_UNKNOWN) { + __db_errx(env, DB_STR("0636", + "DBTYPE of unknown without existing file")); + return (EINVAL); + } + + if (dbp->pgsize == 0) + dbp->pgsize = DB_DEF_IOSIZE; + + /* + * If the file is a temporary file and we're + * doing locking, then we have to create a + * unique file ID. We can't use our normal + * dev/inode pair (or whatever this OS uses + * in place of dev/inode pairs) because no + * backing file will be created until the + * mpool cache is filled forcing the buffers + * to disk. Grab a random locker ID to use + * as a file ID. The created ID must never + * match a potential real file ID -- we know + * it won't because real file IDs contain a + * time stamp after the dev/inode pair, and + * we're simply storing a 4-byte value. + + * !!! + * Store the locker in the file id structure + * -- we can get it from there as necessary, + * and it saves having two copies. + */ + if (LOCKING_ON(env) && (ret = __lock_id(env, + (u_int32_t *)dbp->fileid, NULL)) != 0) + return (ret); + } else + MAKE_INMEM(dbp); + + /* + * Normally we would do handle locking here, however, with + * in-memory files, we cannot do any database manipulation + * until the mpool is open, so it happens later. + */ + } else if (dname == NULL && meta_pgno == PGNO_BASE_MD) { + /* Open/create the underlying file. Acquire locks. */ + if ((ret = __fop_file_setup(dbp, ip, + txn, fname, mode, flags, &id)) != 0) + return (ret); + /* + * If we are creating the first sub-db then this is the + * call to create the master db and we tried to open it + * read-only. The create will force it to be read/write + * So clear the RDONLY flag if we just created it. + */ + if (!F_ISSET(dbp, DB_AM_RDONLY)) + LF_CLR(DB_RDONLY); + } else { + if (dbp->p_internal != NULL) { + __db_errx(env, DB_STR("0637", + "Partitioned databases may not be included with multiple databases.")); + return (ENOENT); + } + if ((ret = __fop_subdb_setup(dbp, ip, + txn, fname, dname, mode, flags)) != 0) + return (ret); + meta_pgno = dbp->meta_pgno; + } + + /* Set up the underlying environment. */ + if ((ret = __env_setup(dbp, txn, fname, dname, id, flags)) != 0) + return (ret); + + /* For in-memory databases, we now need to open/create the database. */ + if (F_ISSET(dbp, DB_AM_INMEM)) { + if (dname == NULL) + ret = __db_new_file(dbp, ip, txn, NULL, NULL); + else { + id = TXN_INVALID; + ret = __fop_file_setup(dbp, + ip, txn, dname, mode, flags, &id); + } + if (ret != 0) + goto err; + } + + /* + * Internal exclusive databases need to use the shared + * memory pool to lock out existing database handles before + * it gets its handle lock. So getting the lock is delayed + * until after the memory pool is allocated. + */ + if (F2_ISSET(dbp, DB2_AM_INTEXCL) && + (ret = __db_handle_lock(dbp)) != 0) + goto err; + + switch (dbp->type) { + case DB_BTREE: + ret = __bam_open(dbp, ip, txn, fname, meta_pgno, flags); + break; + case DB_HASH: + ret = __ham_open(dbp, ip, txn, fname, meta_pgno, flags); + break; + case DB_HEAP: + ret = __heap_open(dbp, + ip, txn, fname, meta_pgno, flags); + break; + case DB_RECNO: + ret = __ram_open(dbp, ip, txn, fname, meta_pgno, flags); + break; + case DB_QUEUE: + ret = __qam_open( + dbp, ip, txn, fname, meta_pgno, mode, flags); + break; + case DB_UNKNOWN: + return ( + __db_unknown_type(env, "__db_dbopen", dbp->type)); + } + if (ret != 0) + goto err; + +#ifdef HAVE_PARTITION + if (dbp->p_internal != NULL && (ret = + __partition_open(dbp, ip, txn, fname, type, flags, mode, 1)) != 0) + goto err; +#endif + DB_TEST_RECOVERY(dbp, DB_TEST_POSTOPEN, ret, fname); + + /* + * Temporary files don't need handle locks, so we only have to check + * for a handle lock downgrade or lockevent in the case of named + * files. + */ + if (!F_ISSET(dbp, DB_AM_RECOVER) && (fname != NULL || dname != NULL) && + LOCK_ISSET(dbp->handle_lock)) { + if (IS_REAL_TXN(txn)) + ret = __txn_lockevent(env, + txn, dbp, &dbp->handle_lock, dbp->locker); + else if (LOCKING_ON(env) && !F2_ISSET(dbp, DB2_AM_EXCL)) + /* + * Trade write handle lock for read handle lock, + * unless this is an exclusive database handle. + */ + ret = __lock_downgrade(env, + &dbp->handle_lock, DB_LOCK_READ, 0); + } +DB_TEST_RECOVERY_LABEL +err: + PERFMON4(env, + db, open, (char *) fname, (char *) dname, flags, &dbp->fileid[0]); + return (ret); +} + +/* + * __db_get_open_flags -- + * Accessor for flags passed into DB->open call + * + * PUBLIC: int __db_get_open_flags __P((DB *, u_int32_t *)); + */ +int +__db_get_open_flags(dbp, flagsp) + DB *dbp; + u_int32_t *flagsp; +{ + DB_ILLEGAL_BEFORE_OPEN(dbp, "DB->get_open_flags"); + + *flagsp = dbp->open_flags; + return (0); +} + +/* + * __db_new_file -- + * Create a new database file. + * + * PUBLIC: int __db_new_file __P((DB *, + * PUBLIC: DB_THREAD_INFO *, DB_TXN *, DB_FH *, const char *)); + */ +int +__db_new_file(dbp, ip, txn, fhp, name) + DB *dbp; + DB_THREAD_INFO *ip; + DB_TXN *txn; + DB_FH *fhp; + const char *name; +{ + int ret; + + /* + * For in-memory database, it is created by mpool and doesn't + * take any lock, so temporarily turn off the lock checking here. + */ + if (F_ISSET(dbp, DB_AM_INMEM)) + LOCK_CHECK_OFF(ip); + + switch (dbp->type) { + case DB_BTREE: + case DB_RECNO: + ret = __bam_new_file(dbp, ip, txn, fhp, name); + break; + case DB_HASH: + ret = __ham_new_file(dbp, ip, txn, fhp, name); + break; + case DB_HEAP: + ret = __heap_new_file(dbp, ip, txn, fhp, name); + break; + case DB_QUEUE: + ret = __qam_new_file(dbp, ip, txn, fhp, name); + break; + case DB_UNKNOWN: + default: + __db_errx(dbp->env, DB_STR_A("0638", + "%s: Invalid type %d specified", "%s %d"), + name, dbp->type); + ret = EINVAL; + break; + } + + DB_TEST_RECOVERY(dbp, DB_TEST_POSTLOGMETA, ret, name); + /* Sync the file in preparation for moving it into place. */ + if (ret == 0 && fhp != NULL) + ret = __os_fsync(dbp->env, fhp); + + DB_TEST_RECOVERY(dbp, DB_TEST_POSTSYNC, ret, name); + + if (F_ISSET(dbp, DB_AM_INMEM)) + LOCK_CHECK_ON(ip); + +DB_TEST_RECOVERY_LABEL + return (ret); +} + +/* + * __db_init_subdb -- + * Initialize the dbp for a subdb. + * + * PUBLIC: int __db_init_subdb __P((DB *, + * PUBLIC: DB *, const char *, DB_THREAD_INFO *, DB_TXN *)); + */ +int +__db_init_subdb(mdbp, dbp, name, ip, txn) + DB *mdbp, *dbp; + const char *name; + DB_THREAD_INFO *ip; + DB_TXN *txn; +{ + DBMETA *meta; + DB_MPOOLFILE *mpf; + int ret, t_ret; + + ret = 0; + if (!F_ISSET(dbp, DB_AM_CREATED)) { + /* Subdb exists; read meta-data page and initialize. */ + mpf = mdbp->mpf; + if ((ret = __memp_fget(mpf, &dbp->meta_pgno, + ip, txn, 0, &meta)) != 0) + goto err; + ret = __db_meta_setup(mdbp->env, dbp, name, meta, 0, 0); + if ((t_ret = __memp_fput(mpf, + ip, meta, dbp->priority)) != 0 && ret == 0) + ret = t_ret; + /* + * If __db_meta_setup found that the meta-page hadn't + * been written out during recovery, we can just return. + */ + if (ret == ENOENT) + ret = 0; + goto err; + } + + /* Handle the create case here. */ + switch (dbp->type) { + case DB_BTREE: + case DB_RECNO: + ret = __bam_new_subdb(mdbp, dbp, ip, txn); + break; + case DB_HASH: + ret = __ham_new_subdb(mdbp, dbp, ip, txn); + break; + case DB_QUEUE: + ret = EINVAL; + break; + case DB_UNKNOWN: + default: + __db_errx(dbp->env, DB_STR_A("0639", + "Invalid subdatabase type %d specified", "%d"), + dbp->type); + return (EINVAL); + } + +err: return (ret); +} + +/* + * __db_chk_meta -- + * Take a buffer containing a meta-data page and check it for a valid LSN, + * checksum (and verify the checksum if necessary) and possibly decrypt it. + * + * Return 0 on success, >0 (errno). + * + * PUBLIC: int __db_chk_meta __P((ENV *, DB *, DBMETA *, u_int32_t)); + */ +int +__db_chk_meta(env, dbp, meta, flags) + ENV *env; + DB *dbp; + DBMETA *meta; + u_int32_t flags; +{ + DB_LSN swap_lsn; + int is_hmac, ret, swapped; + u_int32_t magic, orig_chk; + u_int8_t *chksum; + + ret = 0; + swapped = 0; + + if (FLD_ISSET(meta->metaflags, DBMETA_CHKSUM)) { + if (dbp != NULL) + F_SET(dbp, DB_AM_CHKSUM); + + is_hmac = meta->encrypt_alg == 0 ? 0 : 1; + chksum = ((BTMETA *)meta)->chksum; + + /* + * If we need to swap, the checksum function overwrites the + * original checksum with 0, so we need to save a copy of the + * original for swapping later. + */ + orig_chk = *(u_int32_t *)chksum; + + /* + * We cannot add this to __db_metaswap because that gets done + * later after we've verified the checksum or decrypted. + */ + if (LF_ISSET(DB_CHK_META)) { + swapped = 0; +chk_retry: if ((ret = + __db_check_chksum(env, NULL, env->crypto_handle, + chksum, meta, DBMETASIZE, is_hmac)) != 0) { + if (is_hmac || swapped) + return (DB_CHKSUM_FAIL); + + M_32_SWAP(orig_chk); + swapped = 1; + *(u_int32_t *)chksum = orig_chk; + goto chk_retry; + } + } + } else if (dbp != NULL) + F_CLR(dbp, DB_AM_CHKSUM); + +#ifdef HAVE_CRYPTO + if (__crypto_decrypt_meta(env, + dbp, (u_int8_t *)meta, LF_ISSET(DB_CHK_META)) != 0) + ret = DB_CHKSUM_FAIL; + else +#endif + + /* Now that we're decrypted, we can check LSN. */ + if (LOGGING_ON(env) && !LF_ISSET(DB_CHK_NOLSN)) { + /* + * This gets called both before and after swapping, so we + * need to check ourselves. If we already swapped it above, + * we'll know that here. + */ + + swap_lsn = meta->lsn; + magic = meta->magic; +lsn_retry: + if (swapped) { + M_32_SWAP(swap_lsn.file); + M_32_SWAP(swap_lsn.offset); + M_32_SWAP(magic); + } + switch (magic) { + case DB_BTREEMAGIC: + case DB_HASHMAGIC: + case DB_HEAPMAGIC: + case DB_QAMMAGIC: + case DB_RENAMEMAGIC: + break; + default: + if (swapped) + return (EINVAL); + swapped = 1; + goto lsn_retry; + } + if (!IS_REP_CLIENT(env) && + !IS_NOT_LOGGED_LSN(swap_lsn) && !IS_ZERO_LSN(swap_lsn)) + /* Need to do check. */ + ret = __log_check_page_lsn(env, dbp, &swap_lsn); + } + return (ret); +} + +/* + * __db_meta_setup -- + * + * Take a buffer containing a meta-data page and figure out if it's + * valid, and if so, initialize the dbp from the meta-data page. + * + * PUBLIC: int __db_meta_setup __P((ENV *, + * PUBLIC: DB *, const char *, DBMETA *, u_int32_t, u_int32_t)); + */ +int +__db_meta_setup(env, dbp, name, meta, oflags, flags) + ENV *env; + DB *dbp; + const char *name; + DBMETA *meta; + u_int32_t oflags; + u_int32_t flags; +{ + u_int32_t magic; + int ret; + + ret = 0; + + /* + * Figure out what access method we're dealing with, and then + * call access method specific code to check error conditions + * based on conflicts between the found file and application + * arguments. A found file overrides some user information -- + * we don't consider it an error, for example, if the user set + * an expected byte order and the found file doesn't match it. + */ + F_CLR(dbp, DB_AM_SWAP | DB_AM_IN_RENAME); + magic = meta->magic; + +swap_retry: + switch (magic) { + case DB_BTREEMAGIC: + case DB_HASHMAGIC: + case DB_HEAPMAGIC: + case DB_QAMMAGIC: + case DB_RENAMEMAGIC: + break; + case 0: + /* + * The only time this should be 0 is if we're in the + * midst of opening a subdb during recovery and that + * subdatabase had its meta-data page allocated, but + * not yet initialized. + */ + if (F_ISSET(dbp, DB_AM_SUBDB) && ((IS_RECOVERING(env) && + F_ISSET(env->lg_handle, DBLOG_FORCE_OPEN)) || + meta->pgno != PGNO_INVALID)) + return (ENOENT); + + goto bad_format; + default: + if (F_ISSET(dbp, DB_AM_SWAP)) + goto bad_format; + + M_32_SWAP(magic); + F_SET(dbp, DB_AM_SWAP); + goto swap_retry; + } + + /* + * We can only check the meta page if we are sure we have a meta page. + * If it is random data, then this check can fail. So only now can we + * checksum and decrypt. Don't distinguish between configuration and + * checksum match errors here, because we haven't opened the database + * and even a checksum error isn't a reason to panic the environment. + * If DB_SKIP_CHK is set, it means the checksum was already checked + * and the page was already decrypted. + */ + if (!LF_ISSET(DB_SKIP_CHK) && + (ret = __db_chk_meta(env, dbp, meta, flags)) != 0) { + if (ret == DB_CHKSUM_FAIL) + __db_errx(env, DB_STR_A("0640", + "%s: metadata page checksum error", "%s"), name); + goto bad_format; + } + + switch (magic) { + case DB_BTREEMAGIC: + if (dbp->type != DB_UNKNOWN && + dbp->type != DB_RECNO && dbp->type != DB_BTREE) + goto bad_format; + + flags = meta->flags; + if (F_ISSET(dbp, DB_AM_SWAP)) + M_32_SWAP(flags); + if (LF_ISSET(BTM_RECNO)) + dbp->type = DB_RECNO; + else + dbp->type = DB_BTREE; + if ((oflags & DB_TRUNCATE) == 0 && (ret = + __bam_metachk(dbp, name, (BTMETA *)meta)) != 0) + return (ret); + break; + case DB_HASHMAGIC: + if (dbp->type != DB_UNKNOWN && dbp->type != DB_HASH) + goto bad_format; + + dbp->type = DB_HASH; + if ((oflags & DB_TRUNCATE) == 0 && (ret = + __ham_metachk(dbp, name, (HMETA *)meta)) != 0) + return (ret); + break; + case DB_HEAPMAGIC: + if (dbp->type != DB_UNKNOWN && dbp->type != DB_HEAP) + goto bad_format; + + dbp->type = DB_HEAP; + if ((oflags & DB_TRUNCATE) == 0 && (ret = + __heap_metachk(dbp, name, (HEAPMETA *)meta)) != 0) + return (ret); + break; + case DB_QAMMAGIC: + if (dbp->type != DB_UNKNOWN && dbp->type != DB_QUEUE) + goto bad_format; + dbp->type = DB_QUEUE; + if ((oflags & DB_TRUNCATE) == 0 && (ret = + __qam_metachk(dbp, name, (QMETA *)meta)) != 0) + return (ret); + break; + case DB_RENAMEMAGIC: + F_SET(dbp, DB_AM_IN_RENAME); + + /* Copy the file's ID. */ + memcpy(dbp->fileid, ((DBMETA *)meta)->uid, DB_FILE_ID_LEN); + + break; + default: + goto bad_format; + } + + if (FLD_ISSET(meta->metaflags, + DBMETA_PART_RANGE | DBMETA_PART_CALLBACK)) + if ((ret = + __partition_init(dbp, meta->metaflags)) != 0) + return (ret); + return (0); + +bad_format: + if (F_ISSET(dbp, DB_AM_RECOVER)) + ret = ENOENT; + else + __db_errx(env, DB_STR_A("0641", + "__db_meta_setup: %s: unexpected file type or format", + "%s"), name); + return (ret == 0 ? EINVAL : ret); +} + +/* + * __db_reopen -- + * Reopen a subdatabase if its meta/root pages move. + * PUBLIC: int __db_reopen __P((DBC *)); + */ +int +__db_reopen(arg_dbc) + DBC *arg_dbc; +{ + BTREE *bt; + DBC *dbc; + DB_TXN *txn; + HASH *ht; + DB *dbp, *mdbp; + DB_LOCK new_lock, old_lock; + PAGE *new_page, *old_page; + db_pgno_t newpgno, oldpgno; + int ret, t_ret; + + dbc = arg_dbc; + dbp = dbc->dbp; + old_page = new_page = NULL; + mdbp = NULL; + + COMPQUIET(bt, NULL); + COMPQUIET(ht, NULL); + COMPQUIET(txn, NULL); + LOCK_INIT(new_lock); + LOCK_INIT(old_lock); + + /* + * This must be done in the context of a transaction. If the + * requester does not have a transaction, create one. + */ + + if (TXN_ON(dbp->env) && (txn = dbc->txn) == NULL) { + if ((ret = __txn_begin(dbp->env, + dbc->thread_info, NULL, &txn, 0)) != 0) + return (ret); + if ((ret = __db_cursor(dbp, + dbc->thread_info, txn, &dbc, 0)) != 0) { + (void)__txn_abort(txn); + return (ret); + } + } + + /* + * Lock and latch the old metadata page before re-opening the + * database so that the information is stable. Then lock + * and latch the new page before getting the revision so that + * it cannot change. + */ + + if (dbp->type == DB_HASH) { + ht = (HASH*)dbp->h_internal; + oldpgno = ht->meta_pgno; + } else { + bt = (BTREE *)dbp->bt_internal; + oldpgno = bt->bt_root; + } + if (STD_LOCKING(dbc) && (ret = __db_lget(dbc, + 0, oldpgno, DB_LOCK_READ, 0, &old_lock)) != 0) + goto err; + + if ((ret = __memp_fget(dbp->mpf, &oldpgno, + dbc->thread_info, dbc->txn, 0, &old_page)) != 0 && + ret != DB_PAGE_NOTFOUND) + goto err; + + /* If the page is free we must not hold its lock. */ + if (ret == DB_PAGE_NOTFOUND || TYPE(old_page) == P_INVALID) { + if ((ret = __LPUT(dbc, old_lock)) != 0) + goto err; + /* Drop the latch too. */ + if (old_page != NULL && (ret = __memp_fput(dbp->mpf, + dbc->thread_info, old_page, dbc->priority)) != 0) + goto err; + old_page = NULL; + } + + if ((ret = __db_master_open(dbp, + dbc->thread_info, dbc->txn, dbp->fname, 0, 0, &mdbp)) != 0) + goto err; + + if ((ret = __db_master_update(mdbp, dbp, dbc->thread_info, + dbc->txn, dbp->dname, dbp->type, MU_OPEN, NULL, 0)) != 0) + goto err; + + if (dbp->type == DB_HASH) + newpgno = ht->meta_pgno = dbp->meta_pgno; + else { + bt->bt_meta = dbp->meta_pgno; + if ((ret = __bam_read_root(dbp, + dbc->thread_info, dbc->txn, bt->bt_meta, 0)) != 0) + goto err; + newpgno = bt->bt_root; + } + + if (oldpgno == newpgno) + goto done; + + if (STD_LOCKING(dbc) && (ret = __db_lget(dbc, + 0, newpgno, DB_LOCK_READ, 0, &new_lock)) != 0) + goto err; + + if ((ret = __memp_fget(dbp->mpf, &newpgno, + dbc->thread_info, dbc->txn, 0, &new_page)) != 0) + goto err; + +done: if (dbp->type == DB_HASH) + ht->revision = dbp->mpf->mfp->revision; + else + bt->revision = dbp->mpf->mfp->revision; + +err: if (old_page != NULL && (t_ret = __memp_fput(dbp->mpf, + dbc->thread_info, old_page, dbc->priority)) != 0 && ret == 0) + ret = t_ret; + if (new_page != NULL && (t_ret = __memp_fput(dbp->mpf, + dbc->thread_info, new_page, dbc->priority)) != 0 && ret == 0) + ret = t_ret; + + if (mdbp != NULL && + (t_ret = __db_close(mdbp, dbc->txn, DB_NOSYNC)) != 0 && ret == 0) + ret = t_ret; + + if (dbc != arg_dbc) { + if ((t_ret = __dbc_close(dbc)) != 0 && ret == 0) + ret = t_ret; + if ((t_ret = __txn_commit(txn, 0)) != 0 && ret == 0) + ret = t_ret; + } + return (ret); +} + +static int +__db_handle_lock(dbp) + DB *dbp; +{ + ENV *env; + int ret; + u_int32_t old_flags; + + env = dbp->env; + ret = 0; + old_flags = dbp->flags; + + /* + * Internal exclusive database handles need to get and hold + * their own handle locks so that the client cannot open any + * external handles on that database. + */ + F_CLR(dbp, DB_AM_RECOVER); + F_SET(dbp, DB_AM_NOT_DURABLE); + + /* Begin exclusive handle lockout. */ + dbp->mpf->mfp->excl_lockout = 1; + + if ((ret = __lock_id(env, NULL, &dbp->locker)) != 0) + goto err; + LOCK_INIT(dbp->handle_lock); + if ((ret = __fop_lock_handle(env, dbp, dbp->locker, DB_LOCK_WRITE, + NULL, 0))!= 0) + goto err; + +err: /* End exclusive handle lockout. */ + dbp->mpf->mfp->excl_lockout = 0; + dbp->flags = old_flags; + + return (ret); +} diff -r 000000000000 -r a1985f14b030 src/db/db_overflow.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/db/db_overflow.c Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,727 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 1996, 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +/* + * Copyright (c) 1990, 1993, 1994, 1995, 1996 + * Keith Bostic. All rights reserved. + */ +/* + * Copyright (c) 1990, 1993, 1994, 1995 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Mike Olson. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $Id$ + */ + +#include "db_config.h" + +#include "db_int.h" +#include "dbinc/db_page.h" +#include "dbinc/db_am.h" +#include "dbinc/mp.h" + +/* + * Big key/data code. + * + * Big key and data entries are stored on linked lists of pages. The initial + * reference is a structure with the total length of the item and the page + * number where it begins. Each entry in the linked list contains a pointer + * to the next page of data, and so on. + */ + +/* + * __db_goff -- + * Get an offpage item. + * + * PUBLIC: int __db_goff __P((DBC *, + * PUBLIC: DBT *, u_int32_t, db_pgno_t, void **, u_int32_t *)); + */ +int +__db_goff(dbc, dbt, tlen, pgno, bpp, bpsz) + DBC *dbc; + DBT *dbt; + u_int32_t tlen; + db_pgno_t pgno; + void **bpp; + u_int32_t *bpsz; +{ + DB *dbp; + DB_MPOOLFILE *mpf; + DB_TXN *txn; + DBC_INTERNAL *cp; + ENV *env; + PAGE *h; + DB_THREAD_INFO *ip; + db_indx_t bytes; + u_int32_t curoff, needed, start; + u_int8_t *p, *src; + int ret; + + dbp = dbc->dbp; + cp = dbc->internal; + env = dbp->env; + ip = dbc->thread_info; + mpf = dbp->mpf; + txn = dbc->txn; + + /* + * Check if the buffer is big enough; if it is not and we are + * allowed to malloc space, then we'll malloc it. If we are + * not (DB_DBT_USERMEM), then we'll set the dbt and return + * appropriately. + */ + if (F_ISSET(dbt, DB_DBT_PARTIAL)) { + start = dbt->doff; + if (start > tlen) + needed = 0; + else if (dbt->dlen > tlen - start) + needed = tlen - start; + else + needed = dbt->dlen; + } else { + start = 0; + needed = tlen; + } + + /* + * If the caller has not requested any data, return success. This + * "early-out" also avoids setting up the streaming optimization when + * no page would be retrieved. If it were removed, the streaming code + * should only initialize when needed is not 0. + */ + if (needed == 0) { + dbt->size = 0; + return (0); + } + + if (F_ISSET(dbt, DB_DBT_USERCOPY)) + goto skip_alloc; + + /* Allocate any necessary memory. */ + if (F_ISSET(dbt, DB_DBT_USERMEM)) { + if (needed > dbt->ulen) { + dbt->size = needed; + return (DB_BUFFER_SMALL); + } + } else if (F_ISSET(dbt, DB_DBT_MALLOC)) { + if ((ret = __os_umalloc(env, needed, &dbt->data)) != 0) + return (ret); + } else if (F_ISSET(dbt, DB_DBT_REALLOC)) { + if ((ret = __os_urealloc(env, needed, &dbt->data)) != 0) + return (ret); + } else if (bpsz != NULL && (*bpsz == 0 || *bpsz < needed)) { + if ((ret = __os_realloc(env, needed, bpp)) != 0) + return (ret); + *bpsz = needed; + dbt->data = *bpp; + } else if (bpp != NULL) + dbt->data = *bpp; + else { + DB_ASSERT(env, + F_ISSET(dbt, + DB_DBT_USERMEM | DB_DBT_MALLOC | DB_DBT_REALLOC) || + bpsz != NULL); + return (DB_BUFFER_SMALL); + } + +skip_alloc: + /* Set up a start page in the overflow chain if streaming. */ + if (cp->stream_start_pgno != PGNO_INVALID && + pgno == cp->stream_start_pgno && start >= cp->stream_off && + start < cp->stream_off + P_MAXSPACE(dbp, dbp->pgsize)) { + pgno = cp->stream_curr_pgno; + curoff = cp->stream_off; + } else { + cp->stream_start_pgno = cp->stream_curr_pgno = pgno; + cp->stream_off = curoff = 0; + } + + /* + * Step through the linked list of pages, copying the data on each + * one into the buffer. Never copy more than the total data length. + */ + dbt->size = needed; + for (p = dbt->data; pgno != PGNO_INVALID && needed > 0;) { + if ((ret = __memp_fget(mpf, + &pgno, ip, txn, 0, &h)) != 0) + return (ret); + DB_ASSERT(env, TYPE(h) == P_OVERFLOW); + + /* Check if we need any bytes from this page. */ + if (curoff + OV_LEN(h) >= start) { + bytes = OV_LEN(h); + src = (u_int8_t *)h + P_OVERHEAD(dbp); + if (start > curoff) { + src += start - curoff; + bytes -= start - curoff; + } + if (bytes > needed) + bytes = needed; + if (F_ISSET(dbt, DB_DBT_USERCOPY)) { + /* + * The offset into the DBT is the total size + * less the amount of data still needed. Care + * needs to be taken if doing a partial copy + * beginning at an offset other than 0. + */ + if ((ret = env->dbt_usercopy( + dbt, dbt->size - needed, + src, bytes, DB_USERCOPY_SETDATA)) != 0) { + (void)__memp_fput(mpf, + ip, h, dbp->priority); + return (ret); + } + } else + memcpy(p, src, bytes); + p += bytes; + needed -= bytes; + } + cp->stream_off = curoff; + curoff += OV_LEN(h); + cp->stream_curr_pgno = pgno; + pgno = h->next_pgno; + (void)__memp_fput(mpf, ip, h, dbp->priority); + } + + return (0); +} + +/* + * __db_poff -- + * Put an offpage item. + * + * PUBLIC: int __db_poff __P((DBC *, const DBT *, db_pgno_t *)); + */ +int +__db_poff(dbc, dbt, pgnop) + DBC *dbc; + const DBT *dbt; + db_pgno_t *pgnop; +{ + DB *dbp; + DBT tmp_dbt; + DB_LSN null_lsn; + DB_MPOOLFILE *mpf; + PAGE *pagep, *lastp; + db_indx_t pagespace; + db_pgno_t pgno; + u_int32_t space, sz, tlen; + u_int8_t *p; + int ret, t_ret; + + /* + * Allocate pages and copy the key/data item into them. Calculate the + * number of bytes we get for pages we fill completely with a single + * item. + */ + dbp = dbc->dbp; + lastp = NULL; + mpf = dbp->mpf; + pagespace = P_MAXSPACE(dbp, dbp->pgsize); + p = dbt->data; + sz = dbt->size; + + /* + * Check whether we are streaming at the end of the overflow item. + * If so, the last pgno and offset will be cached in the cursor. + */ + if (F_ISSET(dbt, DB_DBT_STREAMING)) { + tlen = dbt->size - dbt->dlen; + pgno = dbc->internal->stream_curr_pgno; + if ((ret = __memp_fget(mpf, &pgno, dbc->thread_info, + dbc->txn, DB_MPOOL_DIRTY, &lastp)) != 0) + return (ret); + + /* + * Calculate how much we can write on the last page of the + * overflow item. + */ + DB_ASSERT(dbp->env, + OV_LEN(lastp) == (tlen - dbc->internal->stream_off)); + space = pagespace - OV_LEN(lastp); + + /* Only copy as much data as we have. */ + if (space > dbt->dlen) + space = dbt->dlen; + + if (DBC_LOGGING(dbc)) { + tmp_dbt.data = dbt->data; + tmp_dbt.size = space; + ZERO_LSN(null_lsn); + if ((ret = __db_big_log(dbp, dbc->txn, &LSN(lastp), 0, + OP_SET(DB_APPEND_BIG, lastp), pgno, + PGNO_INVALID, PGNO_INVALID, &tmp_dbt, + &LSN(lastp), &null_lsn, &null_lsn)) != 0) + goto err; + } else + LSN_NOT_LOGGED(LSN(lastp)); + + memcpy((u_int8_t *)lastp + P_OVERHEAD(dbp) + OV_LEN(lastp), + dbt->data, space); + OV_LEN(lastp) += space; + sz -= space + dbt->doff; + p += space; + *pgnop = dbc->internal->stream_start_pgno; + } + + ret = 0; + for (; sz > 0; p += pagespace, sz -= pagespace) { + /* + * Reduce pagespace so we terminate the loop correctly and + * don't copy too much data. + */ + if (sz < pagespace) + pagespace = sz; + + /* + * Allocate and initialize a new page and copy all or part of + * the item onto the page. If sz is less than pagespace, we + * have a partial record. + */ + if ((ret = __db_new(dbc, P_OVERFLOW, NULL, &pagep)) != 0) + break; + if (DBC_LOGGING(dbc)) { + tmp_dbt.data = p; + tmp_dbt.size = pagespace; + ZERO_LSN(null_lsn); + if ((ret = __db_big_log(dbp, dbc->txn, &LSN(pagep), 0, + OP_SET(DB_ADD_BIG, pagep), + PGNO(pagep), lastp ? PGNO(lastp) : PGNO_INVALID, + PGNO_INVALID, &tmp_dbt, &LSN(pagep), + lastp == NULL ? &null_lsn : &LSN(lastp), + &null_lsn)) != 0) { + (void)__memp_fput(mpf, dbc->thread_info, + pagep, dbc->priority); + goto err; + } + } else + LSN_NOT_LOGGED(LSN(pagep)); + + /* Move LSN onto page. */ + if (lastp != NULL) + LSN(lastp) = LSN(pagep); + + OV_LEN(pagep) = pagespace; + OV_REF(pagep) = 1; + memcpy((u_int8_t *)pagep + P_OVERHEAD(dbp), p, pagespace); + + /* + * If this is the first entry, update the user's info and + * initialize the cursor to allow for streaming of subsequent + * updates. Otherwise, update the entry on the last page + * filled in and release that page. + */ + if (lastp == NULL) { + *pgnop = PGNO(pagep); + dbc->internal->stream_start_pgno = + dbc->internal->stream_curr_pgno = *pgnop; + dbc->internal->stream_off = 0; + } else { + lastp->next_pgno = PGNO(pagep); + pagep->prev_pgno = PGNO(lastp); + if ((ret = __memp_fput(mpf, + dbc->thread_info, lastp, dbc->priority)) != 0) { + lastp = NULL; + goto err; + } + } + lastp = pagep; + } +err: if (lastp != NULL) { + if (ret == 0) { + dbc->internal->stream_curr_pgno = PGNO(lastp); + dbc->internal->stream_off = dbt->size - OV_LEN(lastp); + } + + if ((t_ret = __memp_fput(mpf, dbc->thread_info, lastp, + dbc->priority)) != 0 && ret == 0) + ret = t_ret; + } + return (ret); +} + +/* + * __db_ovref -- + * Decrement the reference count on an overflow page. + * + * PUBLIC: int __db_ovref __P((DBC *, db_pgno_t)); + */ +int +__db_ovref(dbc, pgno) + DBC *dbc; + db_pgno_t pgno; +{ + DB *dbp; + DB_MPOOLFILE *mpf; + PAGE *h; + int ret; + + dbp = dbc->dbp; + mpf = dbp->mpf; + + if ((ret = __memp_fget(mpf, &pgno, + dbc->thread_info, dbc->txn, DB_MPOOL_DIRTY, &h)) != 0) + return (ret); + + if (DBC_LOGGING(dbc)) { + if ((ret = __db_ovref_log(dbp, + dbc->txn, &LSN(h), 0, h->pgno, -1, &LSN(h))) != 0) { + (void)__memp_fput(mpf, + dbc->thread_info, h, dbc->priority); + return (ret); + } + } else + LSN_NOT_LOGGED(LSN(h)); + + /* + * In BDB releases before 4.5, the overflow reference counts were + * incremented when an overflow item was split onto an internal + * page. There was a lock race in that code, and rather than fix + * the race, we changed BDB to copy overflow items when splitting + * them onto internal pages. The code to decrement reference + * counts remains so databases already in the field continue to + * work. + */ + --OV_REF(h); + + return (__memp_fput(mpf, dbc->thread_info, h, dbc->priority)); +} + +/* + * __db_doff -- + * Delete an offpage chain of overflow pages. + * + * PUBLIC: int __db_doff __P((DBC *, db_pgno_t)); + */ +int +__db_doff(dbc, pgno) + DBC *dbc; + db_pgno_t pgno; +{ + DB *dbp; + DBT tmp_dbt; + DB_LSN null_lsn; + DB_MPOOLFILE *mpf; + PAGE *pagep; + int ret; + + dbp = dbc->dbp; + mpf = dbp->mpf; + + do { + if ((ret = __memp_fget(mpf, &pgno, + dbc->thread_info, dbc->txn, 0, &pagep)) != 0) + return (ret); + + DB_ASSERT(dbp->env, TYPE(pagep) == P_OVERFLOW); + /* + * If it's referenced by more than one key/data item, + * decrement the reference count and return. + */ + if (OV_REF(pagep) > 1) { + (void)__memp_fput(mpf, + dbc->thread_info, pagep, dbc->priority); + return (__db_ovref(dbc, pgno)); + } + + if ((ret = __memp_dirty(mpf, &pagep, + dbc->thread_info, dbc->txn, dbc->priority, 0)) != 0) { + if (pagep != NULL) + (void)__memp_fput(mpf, + dbc->thread_info, pagep, dbc->priority); + return (ret); + } + + if (DBC_LOGGING(dbc)) { + tmp_dbt.data = (u_int8_t *)pagep + P_OVERHEAD(dbp); + tmp_dbt.size = OV_LEN(pagep); + ZERO_LSN(null_lsn); + if ((ret = __db_big_log(dbp, dbc->txn, &LSN(pagep), 0, + OP_SET(DB_REM_BIG, pagep), PGNO(pagep), + PREV_PGNO(pagep), NEXT_PGNO(pagep), &tmp_dbt, + &LSN(pagep), &null_lsn, &null_lsn)) != 0) { + (void)__memp_fput(mpf, + dbc->thread_info, pagep, dbc->priority); + return (ret); + } + } else + LSN_NOT_LOGGED(LSN(pagep)); + pgno = pagep->next_pgno; + OV_LEN(pagep) = 0; + if ((ret = __db_free(dbc, pagep, 0)) != 0) + return (ret); + } while (pgno != PGNO_INVALID); + + return (0); +} + +/* + * __db_moff -- + * Match on overflow pages. + * + * Given a starting page number and a key, return <0, 0, >0 to indicate if the + * key on the page is less than, equal to or greater than the key specified. + * We optimize this by doing chunk at a time comparison unless the user has + * specified a comparison function. In this case, we need to materialize + * the entire object and call their comparison routine. + * + * __db_moff and __db_coff are generic functions useful in searching and + * ordering off page items. __db_moff matches an overflow DBT with an offpage + * item. __db_coff compares two offpage items for lexicographic sort order. + * + * PUBLIC: int __db_moff __P((DBC *, const DBT *, db_pgno_t, u_int32_t, + * PUBLIC: int (*)(DB *, const DBT *, const DBT *), int *)); + */ +int +__db_moff(dbc, dbt, pgno, tlen, cmpfunc, cmpp) + DBC *dbc; + const DBT *dbt; + db_pgno_t pgno; + u_int32_t tlen; + int (*cmpfunc) __P((DB *, const DBT *, const DBT *)), *cmpp; +{ + DB *dbp; + DBT local_dbt; + DB_MPOOLFILE *mpf; + DB_THREAD_INFO *ip; + PAGE *pagep; + void *buf; + u_int32_t bufsize, cmp_bytes, key_left; + u_int8_t *p1, *p2; + int ret; + + dbp = dbc->dbp; + ip = dbc->thread_info; + mpf = dbp->mpf; + + /* + * If there is a user-specified comparison function, build a + * contiguous copy of the key, and call it. + */ + if (cmpfunc != NULL) { + memset(&local_dbt, 0, sizeof(local_dbt)); + buf = NULL; + bufsize = 0; + + if ((ret = __db_goff(dbc, + &local_dbt, tlen, pgno, &buf, &bufsize)) != 0) + return (ret); + /* Pass the key as the first argument */ + *cmpp = cmpfunc(dbp, dbt, &local_dbt); + __os_free(dbp->env, buf); + return (0); + } + + /* While there are both keys to compare. */ + for (*cmpp = 0, p1 = dbt->data, + key_left = dbt->size; key_left > 0 && pgno != PGNO_INVALID;) { + if ((ret = + __memp_fget(mpf, &pgno, ip, dbc->txn, 0, &pagep)) != 0) + return (ret); + + cmp_bytes = OV_LEN(pagep) < key_left ? OV_LEN(pagep) : key_left; + tlen -= cmp_bytes; + key_left -= cmp_bytes; + for (p2 = (u_int8_t *)pagep + P_OVERHEAD(dbp); + cmp_bytes-- > 0; ++p1, ++p2) + if (*p1 != *p2) { + *cmpp = (long)*p1 - (long)*p2; + break; + } + pgno = NEXT_PGNO(pagep); + if ((ret = __memp_fput(mpf, ip, pagep, dbp->priority)) != 0) + return (ret); + if (*cmpp != 0) + return (0); + } + if (key_left > 0) /* DBT is longer than the page key. */ + *cmpp = 1; + else if (tlen > 0) /* DBT is shorter than the page key. */ + *cmpp = -1; + else + *cmpp = 0; + + return (0); +} + +/* + * __db_coff -- + * Match two offpage dbts. + * + * The DBTs must both refer to offpage items. + * The match happens a chunk (page) at a time unless a user defined comparison + * function exists. It is not possible to optimize this comparison away when + * a lexicographic sort order is required on mismatch. + * + * NOTE: For now this function only works for H_OFFPAGE type items. It would + * be simple to extend it for use with B_OVERFLOW type items. It would only + * require extracting the total length, and page number, dependent on the + * DBT type. + * + * PUBLIC: int __db_coff __P((DBC *, const DBT *, const DBT *, + * PUBLIC: int (*)(DB *, const DBT *, const DBT *), int *)); + */ +int +__db_coff(dbc, dbt, match, cmpfunc, cmpp) + DBC *dbc; + const DBT *dbt, *match; + int (*cmpfunc) __P((DB *, const DBT *, const DBT *)), *cmpp; +{ + DB *dbp; + DB_THREAD_INFO *ip; + DB_MPOOLFILE *mpf; + DB_TXN *txn; + DBT local_key, local_match; + PAGE *dbt_pagep, *match_pagep; + db_pgno_t dbt_pgno, match_pgno; + u_int32_t cmp_bytes, dbt_bufsz, dbt_len, match_bufsz; + u_int32_t match_len, max_data, page_space; + u_int8_t *p1, *p2; + int ret; + void *dbt_buf, *match_buf; + + dbp = dbc->dbp; + ip = dbc->thread_info; + txn = dbc->txn; + mpf = dbp->mpf; + page_space = P_MAXSPACE(dbp, dbp->pgsize); + *cmpp = 0; + dbt_buf = match_buf = NULL; + + DB_ASSERT(dbp->env, HPAGE_PTYPE(dbt->data) == H_OFFPAGE); + DB_ASSERT(dbp->env, HPAGE_PTYPE(match->data) == H_OFFPAGE); + + /* Extract potentially unaligned length and pgno fields from DBTs */ + memcpy(&dbt_len, HOFFPAGE_TLEN(dbt->data), sizeof(u_int32_t)); + memcpy(&dbt_pgno, HOFFPAGE_PGNO(dbt->data), sizeof(db_pgno_t)); + memcpy(&match_len, HOFFPAGE_TLEN(match->data), sizeof(u_int32_t)); + memcpy(&match_pgno, HOFFPAGE_PGNO(match->data), sizeof(db_pgno_t)); + max_data = (dbt_len < match_len ? dbt_len : match_len); + + /* + * If there is a custom comparator, fully resolve both DBTs. + * Then call the users comparator. + */ + if (cmpfunc != NULL) { + memset(&local_key, 0, sizeof(local_key)); + memset(&local_match, 0, sizeof(local_match)); + dbt_buf = match_buf = NULL; + dbt_bufsz = match_bufsz = 0; + + if ((ret = __db_goff(dbc, &local_key, dbt_len, + dbt_pgno, &dbt_buf, &dbt_bufsz)) != 0) + goto err1; + if ((ret = __db_goff(dbc, &local_match, match_len, + match_pgno, &match_buf, &match_bufsz)) != 0) + goto err1; + /* The key needs to be the first argument for sort order */ + *cmpp = cmpfunc(dbp, &local_key, &local_match); + +err1: if (dbt_buf != NULL) + __os_free(dbp->env, dbt_buf); + if (match_buf != NULL) + __os_free(dbp->env, match_buf); + return (ret); + } + + /* Match the offpage DBTs a page at a time. */ + while (dbt_pgno != PGNO_INVALID && match_pgno != PGNO_INVALID) { + if ((ret = + __memp_fget(mpf, &dbt_pgno, ip, txn, 0, &dbt_pagep)) != 0) + return (ret); + if ((ret = + __memp_fget(mpf, &match_pgno, + ip, txn, 0, &match_pagep)) != 0) { + (void)__memp_fput( + mpf, ip, dbt_pagep, DB_PRIORITY_UNCHANGED); + return (ret); + } + cmp_bytes = page_space < max_data ? page_space : max_data; + for (p1 = (u_int8_t *)dbt_pagep + P_OVERHEAD(dbp), + p2 = (u_int8_t *)match_pagep + P_OVERHEAD(dbp); + cmp_bytes-- > 0; ++p1, ++p2) + if (*p1 != *p2) { + *cmpp = (long)*p1 - (long)*p2; + break; + } + + dbt_pgno = NEXT_PGNO(dbt_pagep); + match_pgno = NEXT_PGNO(match_pagep); + max_data -= page_space; + if ((ret = __memp_fput(mpf, + ip, dbt_pagep, DB_PRIORITY_UNCHANGED)) != 0) { + (void)__memp_fput(mpf, + ip, match_pagep, DB_PRIORITY_UNCHANGED); + return (ret); + } + if ((ret = __memp_fput(mpf, + ip, match_pagep, DB_PRIORITY_UNCHANGED)) != 0) + return (ret); + if (*cmpp != 0) + return (0); + } + + /* If a lexicographic mismatch was found, then the result has already + * been returned. If the DBTs matched, consider the lengths of the + * items, and return appropriately. + */ + if (dbt_len > match_len) /* DBT is longer than the match key. */ + *cmpp = 1; + else if (match_len > dbt_len) /* DBT is shorter than the match key. */ + *cmpp = -1; + else + *cmpp = 0; + + return (0); + +} diff -r 000000000000 -r a1985f14b030 src/db/db_ovfl_vrfy.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/db/db_ovfl_vrfy.c Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,432 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 1996, 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +/* + * Copyright (c) 1990, 1993, 1994, 1995, 1996 + * Keith Bostic. All rights reserved. + */ +/* + * Copyright (c) 1990, 1993, 1994, 1995 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Mike Olson. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $Id$ + */ + +#include "db_config.h" + +#include "db_int.h" +#include "dbinc/db_page.h" +#include "dbinc/db_am.h" +#include "dbinc/db_verify.h" +#include "dbinc/mp.h" + +/* + * __db_vrfy_overflow -- + * Verify overflow page. + * + * PUBLIC: int __db_vrfy_overflow __P((DB *, VRFY_DBINFO *, PAGE *, db_pgno_t, + * PUBLIC: u_int32_t)); + */ +int +__db_vrfy_overflow(dbp, vdp, h, pgno, flags) + DB *dbp; + VRFY_DBINFO *vdp; + PAGE *h; + db_pgno_t pgno; + u_int32_t flags; +{ + VRFY_PAGEINFO *pip; + int isbad, ret, t_ret; + + isbad = 0; + if ((ret = __db_vrfy_getpageinfo(vdp, pgno, &pip)) != 0) + return (ret); + + if ((ret = __db_vrfy_datapage(dbp, vdp, h, pgno, flags)) != 0) { + if (ret == DB_VERIFY_BAD) + isbad = 1; + else + goto err; + } + + pip->refcount = OV_REF(h); + if (pip->refcount < 1) { + EPRINT((dbp->env, DB_STR_A("0676", + "Page %lu: overflow page has zero reference count", "%lu"), + (u_long)pgno)); + isbad = 1; + } + + /* Just store for now. */ + pip->olen = HOFFSET(h); + +err: if ((t_ret = __db_vrfy_putpageinfo(dbp->env, vdp, pip)) != 0) + ret = t_ret; + return ((ret == 0 && isbad == 1) ? DB_VERIFY_BAD : ret); +} + +/* + * __db_vrfy_ovfl_structure -- + * Walk a list of overflow pages, avoiding cycles and marking + * pages seen. + * + * PUBLIC: int __db_vrfy_ovfl_structure + * PUBLIC: __P((DB *, VRFY_DBINFO *, db_pgno_t, u_int32_t, u_int32_t)); + */ +int +__db_vrfy_ovfl_structure(dbp, vdp, pgno, tlen, flags) + DB *dbp; + VRFY_DBINFO *vdp; + db_pgno_t pgno; + u_int32_t tlen; + u_int32_t flags; +{ + DB *pgset; + ENV *env; + VRFY_PAGEINFO *pip; + db_pgno_t next, prev; + int isbad, ret, seen_cnt, t_ret; + u_int32_t refcount; + + env = dbp->env; + pgset = vdp->pgset; + DB_ASSERT(env, pgset != NULL); + isbad = 0; + + /* This shouldn't happen, but just to be sure. */ + if (!IS_VALID_PGNO(pgno)) + return (DB_VERIFY_BAD); + + /* + * Check the first prev_pgno; it ought to be PGNO_INVALID, + * since there's no prev page. + */ + if ((ret = __db_vrfy_getpageinfo(vdp, pgno, &pip)) != 0) + return (ret); + + /* The refcount is stored on the first overflow page. */ + refcount = pip->refcount; + + if (pip->type != P_OVERFLOW) { + EPRINT((env, DB_STR_A("0677", + "Page %lu: overflow page of invalid type %lu", "%lu %lu"), + (u_long)pgno, (u_long)pip->type)); + ret = DB_VERIFY_BAD; + goto err; /* Unsafe to continue. */ + } + + prev = pip->prev_pgno; + if (prev != PGNO_INVALID) { + EPRINT((env, DB_STR_A("0678", + "Page %lu: first page in overflow chain has a prev_pgno %lu", + "%lu %lu"), (u_long)pgno, (u_long)prev)); + isbad = 1; + } + + for (;;) { + /* + * We may have seen this page elsewhere, if the overflow entry + * has been promoted to an internal page; we just want to + * make sure that each overflow page is seen exactly as many + * times as its refcount dictates. + * + * Note that this code also serves to keep us from looping + * infinitely if there's a cycle in an overflow chain. + */ + if ((ret = __db_vrfy_pgset_get(pgset, + vdp->thread_info, vdp->txn, pgno, &seen_cnt)) != 0) + goto err; + if ((u_int32_t)seen_cnt > refcount) { + EPRINT((env, DB_STR_A("0679", + "Page %lu: encountered too many times in overflow traversal", + "%lu"), (u_long)pgno)); + ret = DB_VERIFY_BAD; + goto err; + } + if ((ret = __db_vrfy_pgset_inc( + pgset, vdp->thread_info, vdp->txn, pgno)) != 0) + goto err; + + /* + * Each overflow page can be referenced multiple times, + * because it's possible for overflow Btree keys to get + * promoted to internal pages. We want to make sure that + * each page is referenced from a Btree leaf (or Hash data + * page, which we consider a "leaf" here) exactly once; if + * the parent was a leaf, set a flag to indicate that we've + * seen this page in a leaf context. + * + * If the parent is not a leaf--in which case it's a Btree + * internal page--we don't need to bother doing any further + * verification, as we'll do it when we hit the leaf (or + * complain that we never saw the leaf). Only the first + * page in an overflow chain should ever have a refcount + * greater than 1, and the combination of the LEAFSEEN check + * and the fact that we bail after the first page for + * non-leaves should ensure this. + * + * Note that each "child" of a page, such as an overflow page, + * is stored and verified in a structure check exactly once, + * so this code does not need to contend with the fact that + * overflow chains used as Btree duplicate keys may be + * referenced multiply from a single Btree leaf page. + */ + if (LF_ISSET(DB_ST_OVFL_LEAF)) { + if (F_ISSET(pip, VRFY_OVFL_LEAFSEEN)) { + EPRINT((env, DB_STR_A("0680", + "Page %lu: overflow page linked twice from leaf or data page", + "%lu"), (u_long)pgno)); + ret = DB_VERIFY_BAD; + goto err; + } + F_SET(pip, VRFY_OVFL_LEAFSEEN); + } + + /* + * We want to verify each overflow chain only once, and + * although no chain should be linked more than once from a + * leaf page, we can't guarantee that it'll be linked that + * once if it's linked from an internal page and the key + * is gone. + * + * seen_cnt is the number of times we'd encountered this page + * before calling this function. + */ + if (seen_cnt == 0) { + /* + * Keep a running tab on how much of the item we've + * seen. + */ + tlen -= pip->olen; + + /* Send the application feedback about our progress. */ + if (!LF_ISSET(DB_SALVAGE)) + __db_vrfy_struct_feedback(dbp, vdp); + } else + goto done; + + next = pip->next_pgno; + + /* Are we there yet? */ + if (next == PGNO_INVALID) + break; + + /* + * We've already checked this when we saved it, but just + * to be sure... + */ + if (!IS_VALID_PGNO(next)) { + EPRINT((env, DB_STR_A("0681", + "Page %lu: bad next_pgno %lu on overflow page", + "%lu %lu"), (u_long)pgno, (u_long)next)); + ret = DB_VERIFY_BAD; + goto err; + } + + if ((ret = __db_vrfy_putpageinfo(env, vdp, pip)) != 0 || + (ret = __db_vrfy_getpageinfo(vdp, next, &pip)) != 0) + return (ret); + if (pip->prev_pgno != pgno) { + EPRINT((env, DB_STR_A("0682", + "Page %lu: bad prev_pgno %lu on overflow page (should be %lu)", + "%lu %lu %lu"), (u_long)next, + (u_long)pip->prev_pgno, (u_long)pgno)); + isbad = 1; + /* + * It's safe to continue because we have separate + * cycle detection. + */ + } + + pgno = next; + } + + if (tlen > 0) { + isbad = 1; + EPRINT((env, DB_STR_A("0683", + "Page %lu: overflow item incomplete", "%lu"), + (u_long)pgno)); + } + +done: +err: if ((t_ret = + __db_vrfy_putpageinfo(env, vdp, pip)) != 0 && ret == 0) + ret = t_ret; + return ((ret == 0 && isbad == 1) ? DB_VERIFY_BAD : ret); +} + +/* + * __db_safe_goff -- + * Get an overflow item, very carefully, from an untrusted database, + * in the context of the salvager. + * + * PUBLIC: int __db_safe_goff __P((DB *, VRFY_DBINFO *, + * PUBLIC: db_pgno_t, DBT *, void *, u_int32_t *, u_int32_t)); + */ +int +__db_safe_goff(dbp, vdp, pgno, dbt, buf, bufsz, flags) + DB *dbp; + VRFY_DBINFO *vdp; + db_pgno_t pgno; + DBT *dbt; + void *buf; + u_int32_t *bufsz; + u_int32_t flags; +{ + DB_MPOOLFILE *mpf; + PAGE *h; + int ret, t_ret; + u_int32_t bytesgot, bytes; + u_int8_t *src, *dest; + + mpf = dbp->mpf; + h = NULL; + ret = t_ret = 0; + bytesgot = bytes = 0; + + DB_ASSERT(dbp->env, bufsz != NULL); + + /* + * Back up to the start of the overflow chain (if necessary) via the + * prev pointer of the overflow page. This guarantees we transverse the + * longest possible chains of overflow pages and won't be called again + * with a pgno earlier in the chain, stepping on ourselves. + */ + for (;;) { + if ((ret = __memp_fget( + mpf, &pgno, vdp->thread_info, NULL, 0, &h)) != 0) + return (ret); + + if (PREV_PGNO(h) == PGNO_INVALID || + !IS_VALID_PGNO(PREV_PGNO(h))) + break; + + pgno = PREV_PGNO(h); + + if ((ret = __memp_fput(mpf, + vdp->thread_info, h, DB_PRIORITY_UNCHANGED)) != 0) + return (ret); + } + if ((ret = __memp_fput( + mpf, vdp->thread_info, h, DB_PRIORITY_UNCHANGED)) != 0) + return (ret); + + h = NULL; + + while ((pgno != PGNO_INVALID) && (IS_VALID_PGNO(pgno))) { + /* + * Mark that we're looking at this page; if we've seen it + * already, quit. + */ + if ((ret = __db_salvage_markdone(vdp, pgno)) != 0) + break; + + if ((ret = __memp_fget(mpf, &pgno, + vdp->thread_info, NULL, 0, &h)) != 0) + break; + + /* + * Make sure it's really an overflow page, unless we're + * being aggressive, in which case we pretend it is. + */ + if (!LF_ISSET(DB_AGGRESSIVE) && TYPE(h) != P_OVERFLOW) { + ret = DB_VERIFY_BAD; + break; + } + + src = (u_int8_t *)h + P_OVERHEAD(dbp); + bytes = OV_LEN(h); + + if (bytes + P_OVERHEAD(dbp) > dbp->pgsize) + bytes = dbp->pgsize - P_OVERHEAD(dbp); + + /* + * Realloc if buf is too small + */ + if (bytesgot + bytes > *bufsz) { + if ((ret = + __os_realloc(dbp->env, bytesgot + bytes, buf)) != 0) + break; + *bufsz = bytesgot + bytes; + } + + dest = *(u_int8_t **)buf + bytesgot; + bytesgot += bytes; + + memcpy(dest, src, bytes); + + pgno = NEXT_PGNO(h); + + if ((ret = __memp_fput(mpf, + vdp->thread_info, h, DB_PRIORITY_UNCHANGED)) != 0) + break; + h = NULL; + } + + /* + * If we're being aggressive, salvage a partial datum if there + * was an error somewhere along the way. + */ + if (ret == 0 || LF_ISSET(DB_AGGRESSIVE)) { + dbt->size = bytesgot; + dbt->data = *(void **)buf; + } + + /* If we broke out on error, don't leave pages pinned. */ + if (h != NULL && (t_ret = __memp_fput(mpf, + vdp->thread_info, h, DB_PRIORITY_UNCHANGED)) != 0 && ret == 0) + ret = t_ret; + + return (ret); +} diff -r 000000000000 -r a1985f14b030 src/db/db_pr.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/db/db_pr.c Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,1978 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 1996, 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + * $Id$ + */ + +#include "db_config.h" + +#include "db_int.h" +#include "dbinc/db_page.h" +#include "dbinc/btree.h" +#include "dbinc/hash.h" +#include "dbinc/heap.h" +#include "dbinc/mp.h" +#include "dbinc/partition.h" +#include "dbinc/qam.h" +#include "dbinc/db_verify.h" + +static int __db_bmeta __P((ENV *, DB *, BTMETA *, u_int32_t)); +static int __db_heapmeta __P((ENV *, DB *, HEAPMETA *, u_int32_t)); +static int __db_heapint __P((DB *, HEAPPG *, u_int32_t)); +static int __db_hmeta __P((ENV *, DB *, HMETA *, u_int32_t)); +static void __db_meta __P((ENV *, DB *, DBMETA *, FN const *, u_int32_t)); +static void __db_proff __P((ENV *, DB_MSGBUF *, void *)); +static int __db_qmeta __P((ENV *, DB *, QMETA *, u_int32_t)); +#ifdef HAVE_STATISTICS +static void __db_prdb __P((DB *, u_int32_t)); +static int __db_prtree __P((DB *, DB_TXN *, + u_int32_t, db_pgno_t, db_pgno_t)); +#endif + +/* + * __db_loadme -- + * A nice place to put a breakpoint. + * + * PUBLIC: void __db_loadme __P((void)); + */ +void +__db_loadme() +{ + pid_t pid; + + __os_id(NULL, &pid, NULL); +} + +#ifdef HAVE_STATISTICS +/* + * __db_dumptree -- + * Dump the tree to a file. + * + * PUBLIC: int __db_dumptree __P((DB *, DB_TXN *, + * PUBLIC: char *, char *, db_pgno_t, db_pgno_t)); + */ +int +__db_dumptree(dbp, txn, op, name, first, last) + DB *dbp; + DB_TXN *txn; + char *op, *name; + db_pgno_t first, last; +{ + ENV *env; + FILE *fp, *orig_fp; + u_int32_t flags; + int ret; + + env = dbp->env; + + for (flags = 0; *op != '\0'; ++op) + switch (*op) { + case 'a': + LF_SET(DB_PR_PAGE); + break; + case 'h': + break; + case 'r': + LF_SET(DB_PR_RECOVERYTEST); + break; + default: + return (EINVAL); + } + + if (name != NULL) { + if ((fp = fopen(name, "w")) == NULL) + return (__os_get_errno()); + + orig_fp = dbp->dbenv->db_msgfile; + dbp->dbenv->db_msgfile = fp; + } else + fp = orig_fp = NULL; + + __db_prdb(dbp, flags); + + __db_msg(env, "%s", DB_GLOBAL(db_line)); + + ret = __db_prtree(dbp, txn, flags, first, last); + + if (fp != NULL) { + (void)fclose(fp); + env->dbenv->db_msgfile = orig_fp; + } + + return (ret); +} + +static const FN __db_flags_fn[] = { + { DB_AM_CHKSUM, "checksumming" }, + { DB_AM_COMPENSATE, "created by compensating transaction" }, + { DB_AM_CREATED, "database created" }, + { DB_AM_CREATED_MSTR, "encompassing file created" }, + { DB_AM_DBM_ERROR, "dbm/ndbm error" }, + { DB_AM_DELIMITER, "variable length" }, + { DB_AM_DISCARD, "discard cached pages" }, + { DB_AM_DUP, "duplicates" }, + { DB_AM_DUPSORT, "sorted duplicates" }, + { DB_AM_ENCRYPT, "encrypted" }, + { DB_AM_FIXEDLEN, "fixed-length records" }, + { DB_AM_INMEM, "in-memory" }, + { DB_AM_IN_RENAME, "file is being renamed" }, + { DB_AM_NOT_DURABLE, "changes not logged" }, + { DB_AM_OPEN_CALLED, "open called" }, + { DB_AM_PAD, "pad value" }, + { DB_AM_PGDEF, "default page size" }, + { DB_AM_RDONLY, "read-only" }, + { DB_AM_READ_UNCOMMITTED, "read-uncommitted" }, + { DB_AM_RECNUM, "Btree record numbers" }, + { DB_AM_RECOVER, "opened for recovery" }, + { DB_AM_RENUMBER, "renumber" }, + { DB_AM_REVSPLITOFF, "no reverse splits" }, + { DB_AM_SECONDARY, "secondary" }, + { DB_AM_SNAPSHOT, "load on open" }, + { DB_AM_SUBDB, "subdatabases" }, + { DB_AM_SWAP, "needswap" }, + { DB_AM_TXN, "transactional" }, + { DB_AM_VERIFYING, "verifier" }, + { 0, NULL } +}; + +/* + * __db_get_flags_fn -- + * Return the __db_flags_fn array. + * + * PUBLIC: const FN * __db_get_flags_fn __P((void)); + */ +const FN * +__db_get_flags_fn() +{ + return (__db_flags_fn); +} + +/* + * __db_prdb -- + * Print out the DB structure information. + */ +static void +__db_prdb(dbp, flags) + DB *dbp; + u_int32_t flags; +{ + BTREE *bt; + DB_MSGBUF mb; + ENV *env; + HASH *h; + QUEUE *q; + HEAP *hp; + + env = dbp->env; + + DB_MSGBUF_INIT(&mb); + __db_msg(env, "In-memory DB structure:"); + __db_msgadd(env, &mb, "%s: %#lx", + __db_dbtype_to_string(dbp->type), (u_long)dbp->flags); + __db_prflags(env, &mb, dbp->flags, __db_flags_fn, " (", ")"); + DB_MSGBUF_FLUSH(env, &mb); + + switch (dbp->type) { + case DB_BTREE: + case DB_RECNO: + bt = dbp->bt_internal; + __db_msg(env, "bt_meta: %lu bt_root: %lu", + (u_long)bt->bt_meta, (u_long)bt->bt_root); + __db_msg(env, "bt_minkey: %lu", (u_long)bt->bt_minkey); + if (!LF_ISSET(DB_PR_RECOVERYTEST)) + __db_msg(env, "bt_compare: %#lx bt_prefix: %#lx", + P_TO_ULONG(bt->bt_compare), + P_TO_ULONG(bt->bt_prefix)); +#ifdef HAVE_COMPRESSION + if (!LF_ISSET(DB_PR_RECOVERYTEST)) + __db_msg(env, "bt_compress: %#lx bt_decompress: %#lx", + P_TO_ULONG(bt->bt_compress), + P_TO_ULONG(bt->bt_decompress)); +#endif + __db_msg(env, "bt_lpgno: %lu", (u_long)bt->bt_lpgno); + if (dbp->type == DB_RECNO) { + __db_msg(env, + "re_pad: %#lx re_delim: %#lx re_len: %lu re_source: %s", + (u_long)bt->re_pad, (u_long)bt->re_delim, + (u_long)bt->re_len, + bt->re_source == NULL ? "" : bt->re_source); + __db_msg(env, + "re_modified: %d re_eof: %d re_last: %lu", + bt->re_modified, bt->re_eof, (u_long)bt->re_last); + } + break; + case DB_HASH: + h = dbp->h_internal; + __db_msg(env, "meta_pgno: %lu", (u_long)h->meta_pgno); + __db_msg(env, "h_ffactor: %lu", (u_long)h->h_ffactor); + __db_msg(env, "h_nelem: %lu", (u_long)h->h_nelem); + if (!LF_ISSET(DB_PR_RECOVERYTEST)) + __db_msg(env, "h_hash: %#lx", P_TO_ULONG(h->h_hash)); + break; + case DB_QUEUE: + q = dbp->q_internal; + __db_msg(env, "q_meta: %lu", (u_long)q->q_meta); + __db_msg(env, "q_root: %lu", (u_long)q->q_root); + __db_msg(env, "re_pad: %#lx re_len: %lu", + (u_long)q->re_pad, (u_long)q->re_len); + __db_msg(env, "rec_page: %lu", (u_long)q->rec_page); + __db_msg(env, "page_ext: %lu", (u_long)q->page_ext); + break; + case DB_HEAP: + hp = dbp->heap_internal; + __db_msg(env, "gbytes: %lu", (u_long)hp->gbytes); + __db_msg(env, "bytes: %lu", (u_long)hp->bytes); + __db_msg(env, "curregion: %lu", (u_long)hp->curregion); + __db_msg(env, "region_size: %lu", (u_long)hp->region_size); + __db_msg(env, "maxpgno: %lu", (u_long)hp->maxpgno); + break; + case DB_UNKNOWN: + default: + break; + } +} + +/* + * __db_prtree -- + * Print out the entire tree. + */ +static int +__db_prtree(dbp, txn, flags, first, last) + DB *dbp; + DB_TXN *txn; + u_int32_t flags; + db_pgno_t first, last; +{ + DB_MPOOLFILE *mpf; + PAGE *h; + db_pgno_t i; + int ret; + + mpf = dbp->mpf; + + if (dbp->type == DB_QUEUE) + return (__db_prqueue(dbp, flags)); + + /* + * Find out the page number of the last page in the database, then + * dump each page. + */ + if (last == PGNO_INVALID && + (ret = __memp_get_last_pgno(mpf, &last)) != 0) + return (ret); + for (i = first; i <= last; ++i) { + if ((ret = __memp_fget(mpf, &i, NULL, txn, 0, &h)) != 0) + return (ret); + (void)__db_prpage(dbp, h, flags); + if ((ret = __memp_fput(mpf, NULL, h, dbp->priority)) != 0) + return (ret); + } + + return (0); +} + +/* + * __db_prnpage + * -- Print out a specific page. + * + * PUBLIC: int __db_prnpage __P((DB *, DB_TXN *, db_pgno_t)); + */ +int +__db_prnpage(dbp, txn, pgno) + DB *dbp; + DB_TXN *txn; + db_pgno_t pgno; +{ + DB_MPOOLFILE *mpf; + PAGE *h; + int ret, t_ret; + + mpf = dbp->mpf; + + if ((ret = __memp_fget(mpf, &pgno, NULL, txn, 0, &h)) != 0) + return (ret); + + ret = __db_prpage(dbp, h, DB_PR_PAGE); + + if ((t_ret = __memp_fput(mpf, NULL, h, dbp->priority)) != 0 && ret == 0) + ret = t_ret; + + return (ret); +} + +/* + * __db_prpage + * -- Print out a page. + * + * PUBLIC: int __db_prpage __P((DB *, PAGE *, u_int32_t)); + */ +int +__db_prpage(dbp, h, flags) + DB *dbp; + PAGE *h; + u_int32_t flags; +{ + DB_MSGBUF mb; + u_int32_t pagesize; + /* + * !!! + * Find out the page size. We don't want to do it the "right" way, + * by reading the value from the meta-data page, that's going to be + * slow. Reach down into the mpool region. + */ + pagesize = (u_int32_t)dbp->mpf->mfp->pagesize; + DB_MSGBUF_INIT(&mb); + return (__db_prpage_int(dbp->env, + &mb, dbp, "", h, pagesize, NULL, flags)); +} + +/* + * __db_lockmode_to_string -- + * Return the name of the lock mode. + * + * PUBLIC: const char * __db_lockmode_to_string __P((db_lockmode_t)); + */ +const char * +__db_lockmode_to_string(mode) + db_lockmode_t mode; +{ + switch (mode) { + case DB_LOCK_NG: + return ("Not granted"); + case DB_LOCK_READ: + return ("Shared/read"); + case DB_LOCK_WRITE: + return ("Exclusive/write"); + case DB_LOCK_WAIT: + return ("Wait for event"); + case DB_LOCK_IWRITE: + return ("Intent exclusive/write"); + case DB_LOCK_IREAD: + return ("Intent shared/read"); + case DB_LOCK_IWR: + return ("Intent to read/write"); + case DB_LOCK_READ_UNCOMMITTED: + return ("Read uncommitted"); + case DB_LOCK_WWRITE: + return ("Was written"); + default: + break; + } + return ("UNKNOWN LOCK MODE"); +} + +#else /* !HAVE_STATISTICS */ + +/* + * __db_dumptree -- + * Dump the tree to a file. + * + * PUBLIC: int __db_dumptree __P((DB *, DB_TXN *, + * PUBLIC: char *, char *, db_pgno_t, db_pgno_t)); + */ +int +__db_dumptree(dbp, txn, op, name, first, last) + DB *dbp; + DB_TXN *txn; + char *op, *name; + db_pgno_t first, last; +{ + COMPQUIET(txn, NULL); + COMPQUIET(op, NULL); + COMPQUIET(name, NULL); + COMPQUIET(first, last); + + return (__db_stat_not_built(dbp->env)); +} + +/* + * __db_get_flags_fn -- + * Return the __db_flags_fn array. + * + * PUBLIC: const FN * __db_get_flags_fn __P((void)); + */ +const FN * +__db_get_flags_fn() +{ + /* + * !!! + * The Tcl API uses this interface, stub it off. + */ + return (NULL); +} +#endif + +/* + * __db_meta -- + * Print out common metadata information. + */ +static void +__db_meta(env, dbp, dbmeta, fn, flags) + DB *dbp; + ENV *env; + DBMETA *dbmeta; + FN const *fn; + u_int32_t flags; +{ + DB_MPOOLFILE *mpf; + DB_MSGBUF mb; + PAGE *h; + db_pgno_t pgno; + u_int8_t *p; + int cnt, ret; + const char *sep; + + DB_MSGBUF_INIT(&mb); + + __db_msg(env, "\tmagic: %#lx", (u_long)dbmeta->magic); + __db_msg(env, "\tversion: %lu", (u_long)dbmeta->version); + __db_msg(env, "\tpagesize: %lu", (u_long)dbmeta->pagesize); + __db_msg(env, "\ttype: %lu", (u_long)dbmeta->type); + __db_msg(env, "\tmetaflags %#lx", (u_long)dbmeta->metaflags); + __db_msg(env, "\tkeys: %lu\trecords: %lu", + (u_long)dbmeta->key_count, (u_long)dbmeta->record_count); + if (dbmeta->nparts) + __db_msg(env, "\tnparts: %lu", (u_long)dbmeta->nparts); + + /* + * If we're doing recovery testing, don't display the free list, + * it may have changed and that makes the dump diff not work. + */ + if (dbp != NULL && !LF_ISSET(DB_PR_RECOVERYTEST)) { + mpf = dbp->mpf; + __db_msgadd( + env, &mb, "\tfree list: %lu", (u_long)dbmeta->free); + for (pgno = dbmeta->free, + cnt = 0, sep = ", "; pgno != PGNO_INVALID;) { + if ((ret = __memp_fget(mpf, + &pgno, NULL, NULL, 0, &h)) != 0) { + DB_MSGBUF_FLUSH(env, &mb); + __db_msg(env, + "Unable to retrieve free-list page: %lu: %s", + (u_long)pgno, db_strerror(ret)); + break; + } + pgno = h->next_pgno; + (void)__memp_fput(mpf, NULL, h, dbp->priority); + __db_msgadd(env, &mb, "%s%lu", sep, (u_long)pgno); + if (++cnt % 10 == 0) { + DB_MSGBUF_FLUSH(env, &mb); + cnt = 0; + sep = "\t"; + } else + sep = ", "; + } + DB_MSGBUF_FLUSH(env, &mb); + __db_msg(env, "\tlast_pgno: %lu", (u_long)dbmeta->last_pgno); + } + + if (fn != NULL) { + DB_MSGBUF_FLUSH(env, &mb); + __db_msgadd(env, &mb, "\tflags: %#lx", (u_long)dbmeta->flags); + __db_prflags(env, &mb, dbmeta->flags, fn, " (", ")"); + } + + DB_MSGBUF_FLUSH(env, &mb); + __db_msgadd(env, &mb, "\tuid: "); + for (p = (u_int8_t *)dbmeta->uid, + cnt = 0; cnt < DB_FILE_ID_LEN; ++cnt) { + __db_msgadd(env, &mb, "%x", *p++); + if (cnt < DB_FILE_ID_LEN - 1) + __db_msgadd(env, &mb, " "); + } + DB_MSGBUF_FLUSH(env, &mb); +} + +/* + * __db_bmeta -- + * Print out the btree meta-data page. + */ +static int +__db_bmeta(env, dbp, h, flags) + ENV *env; + DB *dbp; + BTMETA *h; + u_int32_t flags; +{ + static const FN fn[] = { + { BTM_DUP, "duplicates" }, + { BTM_RECNO, "recno" }, + { BTM_RECNUM, "btree:recnum" }, + { BTM_FIXEDLEN, "recno:fixed-length" }, + { BTM_RENUMBER, "recno:renumber" }, + { BTM_SUBDB, "multiple-databases" }, + { BTM_DUPSORT, "sorted duplicates" }, + { BTM_COMPRESS, "compressed" }, + { 0, NULL } + }; + + __db_meta(env, dbp, (DBMETA *)h, fn, flags); + + __db_msg(env, "\tminkey: %lu", (u_long)h->minkey); + if (F_ISSET(&h->dbmeta, BTM_RECNO)) + __db_msg(env, "\tre_len: %#lx re_pad: %#lx", + (u_long)h->re_len, (u_long)h->re_pad); + __db_msg(env, "\troot: %lu", (u_long)h->root); + + return (0); +} + +/* + * __db_hmeta -- + * Print out the hash meta-data page. + */ +static int +__db_hmeta(env, dbp, h, flags) + ENV *env; + DB *dbp; + HMETA *h; + u_int32_t flags; +{ + static const FN fn[] = { + { DB_HASH_DUP, "duplicates" }, + { DB_HASH_SUBDB, "multiple-databases" }, + { DB_HASH_DUPSORT, "sorted duplicates" }, + { 0, NULL } + }; + DB_MSGBUF mb; + int i; + + DB_MSGBUF_INIT(&mb); + + __db_meta(env, dbp, (DBMETA *)h, fn, flags); + + __db_msg(env, "\tmax_bucket: %lu", (u_long)h->max_bucket); + __db_msg(env, "\thigh_mask: %#lx", (u_long)h->high_mask); + __db_msg(env, "\tlow_mask: %#lx", (u_long)h->low_mask); + __db_msg(env, "\tffactor: %lu", (u_long)h->ffactor); + __db_msg(env, "\tnelem: %lu", (u_long)h->nelem); + __db_msg(env, "\th_charkey: %#lx", (u_long)h->h_charkey); + __db_msgadd(env, &mb, "\tspare points:\n\t"); + for (i = 0; i < NCACHED; i++) { + __db_msgadd(env, &mb, "%lu (%lu) ", (u_long)h->spares[i], + (u_long)(h->spares[i] == 0 ? + 0 : h->spares[i] + (i == 0 ? 0 : 1 << (i-1)))); + if ((i + 1) % 8 == 0) + __db_msgadd(env, &mb, "\n\t"); + } + DB_MSGBUF_FLUSH(env, &mb); + + return (0); +} + +/* + * __db_qmeta -- + * Print out the queue meta-data page. + */ +static int +__db_qmeta(env, dbp, h, flags) + ENV *env; + DB *dbp; + QMETA *h; + u_int32_t flags; +{ + + __db_meta(env, dbp, (DBMETA *)h, NULL, flags); + + __db_msg(env, "\tfirst_recno: %lu", (u_long)h->first_recno); + __db_msg(env, "\tcur_recno: %lu", (u_long)h->cur_recno); + __db_msg(env, "\tre_len: %#lx re_pad: %lu", + (u_long)h->re_len, (u_long)h->re_pad); + __db_msg(env, "\trec_page: %lu", (u_long)h->rec_page); + __db_msg(env, "\tpage_ext: %lu", (u_long)h->page_ext); + + return (0); +} + +/* + * __db_heapmeta -- + * Print out the heap meta-data page. + */ +static int +__db_heapmeta(env, dbp, h, flags) + ENV *env; + DB *dbp; + HEAPMETA *h; + u_int32_t flags; +{ + __db_meta(env, dbp, (DBMETA *)h, NULL, flags); + + __db_msg(env, "\tcurregion: %lu", (u_long)h->curregion); + __db_msg(env, "\tregion_size: %lu", (u_long)h->region_size); + __db_msg(env, "\tnregions: %lu", (u_long)h->nregions); + __db_msg(env, "\tgbytes: %lu", (u_long)h->gbytes); + __db_msg(env, "\tbytes: %lu", (u_long)h->bytes); + + return (0); +} + +/* + * __db_heapint -- + * Print out the heap internal-data page. + */ +static int +__db_heapint(dbp, h, flags) + DB *dbp; + HEAPPG *h; + u_int32_t flags; +{ + DB_MSGBUF mb; + ENV *env; + int count, printed; + u_int32_t i, max; + u_int8_t avail; + + env = dbp->env; + DB_MSGBUF_INIT(&mb); + count = printed = 0; + COMPQUIET(flags, 0); + + __db_msgadd(env, &mb, "\thigh: %4lu\n", (u_long)h->high_pgno); + /* How many entries could there be on a page */ + max = HEAP_REGION_SIZE(dbp); + + for (i = 0; i < max; i++, count++) { + avail = HEAP_SPACE(dbp, h, i); + if (avail != 0) { + __db_msgadd(env, &mb, + "%5lu:%1lu ", (u_long)i, (u_long)avail); + printed = 1; + } + /* We get 10 entries per line this way */ + if (count == 9) { + DB_MSGBUF_FLUSH(env, &mb); + count = -1; + } + } + /* All pages were less than 33% full */ + if (printed == 0) + __db_msgadd(env, &mb, + "All pages in this region less than 33 percent full"); + + DB_MSGBUF_FLUSH(env, &mb); + return (0); +} + +/* + * For printing pages from the log we may be passed the data segment + * separate from the header, if so then it starts at HOFFSET. + */ +#define PR_ENTRY(dbp, h, i, data) \ + (data == NULL ? P_ENTRY(dbp, h, i) : \ + (u_int8_t *)data + P_INP(dbp, h)[i] - HOFFSET(h)) +/* + * __db_prpage_int + * -- Print out a page. + * + * PUBLIC: int __db_prpage_int __P((ENV *, DB_MSGBUF *, + * PUBLIC: DB *, char *, PAGE *, u_int32_t, u_int8_t *, u_int32_t)); + */ +int +__db_prpage_int(env, mbp, dbp, lead, h, pagesize, data, flags) + ENV *env; + DB_MSGBUF *mbp; + DB *dbp; + char *lead; + PAGE *h; + u_int32_t pagesize; + u_int8_t *data; + u_int32_t flags; +{ + BINTERNAL *bi; + BKEYDATA *bk; + HOFFPAGE a_hkd; + QAMDATA *qp, *qep; + RINTERNAL *ri; + HEAPHDR *hh; + HEAPSPLITHDR *hs; + db_indx_t dlen, len, i, *inp, max; + db_pgno_t pgno; + db_recno_t recno; + u_int32_t qlen; + u_int8_t *ep, *hk, *p; + int deleted, ret; + const char *s; + void *hdata, *sp; + + /* + * If we're doing recovery testing and this page is P_INVALID, + * assume it's a page that's on the free list, and don't display it. + */ + if (LF_ISSET(DB_PR_RECOVERYTEST) && TYPE(h) == P_INVALID) + return (0); + + if ((s = __db_pagetype_to_string(TYPE(h))) == NULL) { + __db_msg(env, "%sILLEGAL PAGE TYPE: page: %lu type: %lu", + lead, (u_long)h->pgno, (u_long)TYPE(h)); + return (EINVAL); + } + + /* Page number, page type. */ + __db_msgadd(env, mbp, "%spage %lu: %s:", lead, (u_long)h->pgno, s); + + /* + * LSNs on a metadata page will be different from the original after an + * abort, in some cases. Don't display them if we're testing recovery. + */ + if (!LF_ISSET(DB_PR_RECOVERYTEST) || + (TYPE(h) != P_BTREEMETA && TYPE(h) != P_HASHMETA && + TYPE(h) != P_QAMMETA && TYPE(h) != P_QAMDATA && + TYPE(h) != P_HEAPMETA)) + __db_msgadd(env, mbp, " LSN [%lu][%lu]:", + (u_long)LSN(h).file, (u_long)LSN(h).offset); + + /* + * Page level (only applicable for Btree/Recno, but we always display + * it, for no particular reason, except for Heap. + */ + if (!HEAPTYPE(h)) + __db_msgadd(env, mbp, " level %lu", (u_long)h->level); + + /* Record count. */ + if (TYPE(h) == P_IBTREE || TYPE(h) == P_IRECNO || + (dbp != NULL && TYPE(h) == P_LRECNO && + h->pgno == ((BTREE *)dbp->bt_internal)->bt_root)) + __db_msgadd(env, mbp, " records: %lu", (u_long)RE_NREC(h)); + DB_MSGBUF_FLUSH(env, mbp); + + switch (TYPE(h)) { + case P_BTREEMETA: + return (__db_bmeta(env, dbp, (BTMETA *)h, flags)); + case P_HASHMETA: + return (__db_hmeta(env, dbp, (HMETA *)h, flags)); + case P_QAMMETA: + return (__db_qmeta(env, dbp, (QMETA *)h, flags)); + case P_QAMDATA: /* Should be meta->start. */ + if (!LF_ISSET(DB_PR_PAGE) || dbp == NULL) + return (0); + + qlen = ((QUEUE *)dbp->q_internal)->re_len; + recno = (h->pgno - 1) * QAM_RECNO_PER_PAGE(dbp) + 1; + i = 0; + qep = (QAMDATA *)((u_int8_t *)h + pagesize - qlen); + for (qp = QAM_GET_RECORD(dbp, h, i); qp < qep; + recno++, i++, qp = QAM_GET_RECORD(dbp, h, i)) { + if (!F_ISSET(qp, QAM_SET)) + continue; + + __db_msgadd(env, mbp, "%s", + F_ISSET(qp, QAM_VALID) ? "\t" : " D"); + __db_msgadd(env, mbp, "[%03lu] %4lu ", (u_long)recno, + (u_long)((u_int8_t *)qp - (u_int8_t *)h)); + __db_prbytes(env, mbp, qp->data, qlen); + } + return (0); + case P_HEAPMETA: + return (__db_heapmeta(env, dbp, (HEAPMETA *)h, flags)); + case P_IHEAP: + if (!LF_ISSET(DB_PR_PAGE) || dbp == NULL) + return (0); + return (__db_heapint(dbp, (HEAPPG *)h, flags)); + default: + break; + } + + s = "\t"; + if (!HEAPTYPE(h) && TYPE(h) != P_IBTREE && TYPE(h) != P_IRECNO) { + __db_msgadd(env, mbp, "%sprev: %4lu next: %4lu", + s, (u_long)PREV_PGNO(h), (u_long)NEXT_PGNO(h)); + s = " "; + } + + if (HEAPTYPE(h)) { + __db_msgadd(env, mbp, "%shigh indx: %4lu free indx: %4lu", s, + (u_long)HEAP_HIGHINDX(h), (u_long)HEAP_FREEINDX(h)); + s = " "; + } + + if (TYPE(h) == P_OVERFLOW) { + __db_msgadd(env, mbp, + "%sref cnt: %4lu ", s, (u_long)OV_REF(h)); + if (dbp == NULL) + __db_msgadd(env, mbp, + " len: %4lu ", (u_long)OV_LEN(h)); + else + __db_prbytes(env, + mbp, (u_int8_t *)h + P_OVERHEAD(dbp), OV_LEN(h)); + return (0); + } + __db_msgadd(env, mbp, "%sentries: %4lu", s, (u_long)NUM_ENT(h)); + __db_msgadd(env, mbp, " offset: %4lu", (u_long)HOFFSET(h)); + DB_MSGBUF_FLUSH(env, mbp); + + if (dbp == NULL || TYPE(h) == P_INVALID || !LF_ISSET(DB_PR_PAGE)) + return (0); + + if (data != NULL) + pagesize += HOFFSET(h); + else if (pagesize < HOFFSET(h)) + return (0); + + ret = 0; + inp = P_INP(dbp, h); + max = TYPE(h) == P_HEAP ? HEAP_HIGHINDX(h) + 1 : NUM_ENT(h); + for (i = 0; i < max; i++) { + if (TYPE(h) == P_HEAP && inp[i] == 0) + continue; + if ((uintptr_t)(P_ENTRY(dbp, h, i) - (u_int8_t *)h) < + (uintptr_t)(P_OVERHEAD(dbp)) || + (size_t)(P_ENTRY(dbp, h, i) - (u_int8_t *)h) >= pagesize) { + __db_msg(env, + "ILLEGAL PAGE OFFSET: indx: %lu of %lu", + (u_long)i, (u_long)inp[i]); + ret = EINVAL; + continue; + } + deleted = 0; + switch (TYPE(h)) { + case P_HASH_UNSORTED: + case P_HASH: + case P_IBTREE: + case P_IRECNO: + sp = PR_ENTRY(dbp, h, i, data); + break; + case P_HEAP: + sp = P_ENTRY(dbp, h, i); + break; + case P_LBTREE: + sp = PR_ENTRY(dbp, h, i, data); + deleted = i % 2 == 0 && + B_DISSET(GET_BKEYDATA(dbp, h, i + O_INDX)->type); + break; + case P_LDUP: + case P_LRECNO: + sp = PR_ENTRY(dbp, h, i, data); + deleted = B_DISSET(GET_BKEYDATA(dbp, h, i)->type); + break; + default: + goto type_err; + } + __db_msgadd(env, mbp, "%s", deleted ? " D" : "\t"); + __db_msgadd( + env, mbp, "[%03lu] %4lu ", (u_long)i, (u_long)inp[i]); + switch (TYPE(h)) { + case P_HASH_UNSORTED: + case P_HASH: + hk = sp; + switch (HPAGE_PTYPE(hk)) { + case H_OFFDUP: + memcpy(&pgno, + HOFFDUP_PGNO(hk), sizeof(db_pgno_t)); + __db_msgadd(env, mbp, + "%4lu [offpage dups]", (u_long)pgno); + DB_MSGBUF_FLUSH(env, mbp); + break; + case H_DUPLICATE: + /* + * If this is the first item on a page, then + * we cannot figure out how long it is, so + * we only print the first one in the duplicate + * set. + */ + if (i != 0) + len = LEN_HKEYDATA(dbp, h, 0, i); + else + len = 1; + + __db_msgadd(env, mbp, "Duplicates:"); + DB_MSGBUF_FLUSH(env, mbp); + for (p = HKEYDATA_DATA(hk), + ep = p + len; p < ep;) { + memcpy(&dlen, p, sizeof(db_indx_t)); + p += sizeof(db_indx_t); + __db_msgadd(env, mbp, "\t\t"); + __db_prbytes(env, mbp, p, dlen); + p += sizeof(db_indx_t) + dlen; + } + break; + case H_KEYDATA: + __db_prbytes(env, mbp, HKEYDATA_DATA(hk), + LEN_HKEYDATA(dbp, h, i == 0 ? + pagesize : 0, i)); + break; + case H_OFFPAGE: + memcpy(&a_hkd, hk, HOFFPAGE_SIZE); + __db_msgadd(env, mbp, + "overflow: total len: %4lu page: %4lu", + (u_long)a_hkd.tlen, (u_long)a_hkd.pgno); + DB_MSGBUF_FLUSH(env, mbp); + break; + default: + DB_MSGBUF_FLUSH(env, mbp); + __db_msg(env, "ILLEGAL HASH PAGE TYPE: %lu", + (u_long)HPAGE_PTYPE(hk)); + ret = EINVAL; + break; + } + break; + case P_IBTREE: + bi = sp; + + if (F_ISSET(dbp, DB_AM_RECNUM)) + __db_msgadd(env, mbp, + "count: %4lu ", (u_long)bi->nrecs); + __db_msgadd(env, mbp, + "pgno: %4lu type: %lu ", + (u_long)bi->pgno, (u_long)bi->type); + switch (B_TYPE(bi->type)) { + case B_KEYDATA: + __db_prbytes(env, mbp, bi->data, bi->len); + break; + case B_DUPLICATE: + case B_OVERFLOW: + __db_proff(env, mbp, bi->data); + break; + default: + DB_MSGBUF_FLUSH(env, mbp); + __db_msg(env, "ILLEGAL BINTERNAL TYPE: %lu", + (u_long)B_TYPE(bi->type)); + ret = EINVAL; + break; + } + break; + case P_IRECNO: + ri = sp; + __db_msgadd(env, mbp, "entries %4lu pgno %4lu", + (u_long)ri->nrecs, (u_long)ri->pgno); + DB_MSGBUF_FLUSH(env, mbp); + break; + case P_LBTREE: + case P_LDUP: + case P_LRECNO: + bk = sp; + switch (B_TYPE(bk->type)) { + case B_KEYDATA: + __db_prbytes(env, mbp, bk->data, bk->len); + break; + case B_DUPLICATE: + case B_OVERFLOW: + __db_proff(env, mbp, bk); + break; + default: + DB_MSGBUF_FLUSH(env, mbp); + __db_msg(env, + "ILLEGAL DUPLICATE/LBTREE/LRECNO TYPE: %lu", + (u_long)B_TYPE(bk->type)); + ret = EINVAL; + break; + } + break; + case P_HEAP: + hh = sp; + if (!F_ISSET(hh,HEAP_RECSPLIT)) + hdata = (u_int8_t *)hh + sizeof(HEAPHDR); + else { + hs = sp; + __db_msgadd(env, mbp, + "split: 0x%02x tsize: %lu next: %lu.%lu ", + hh->flags, (u_long)hs->tsize, + (u_long)hs->nextpg, (u_long)hs->nextindx); + + hdata = (u_int8_t *)hh + sizeof(HEAPSPLITHDR); + } + __db_prbytes(env, mbp, hdata, hh->size); + break; + default: +type_err: DB_MSGBUF_FLUSH(env, mbp); + __db_msg(env, + "ILLEGAL PAGE TYPE: %lu", (u_long)TYPE(h)); + ret = EINVAL; + continue; + } + } + return (ret); +} + +/* + * __db_prbytes -- + * Print out a data element. + * + * PUBLIC: void __db_prbytes __P((ENV *, DB_MSGBUF *, u_int8_t *, u_int32_t)); + */ +void +__db_prbytes(env, mbp, bytes, len) + ENV *env; + DB_MSGBUF *mbp; + u_int8_t *bytes; + u_int32_t len; +{ + u_int8_t *p; + u_int32_t i, not_printable; + int msg_truncated; + + __db_msgadd(env, mbp, "len: %3lu", (u_long)len); + if (len != 0) { + __db_msgadd(env, mbp, " data: "); + + /* + * Print the first N bytes of the data. If that + * chunk is at least 3/4 printable characters, print + * it as text, else print it in hex. We have this + * heuristic because we're displaying things like + * lock objects that could be either text or data. + */ + if (len > env->data_len) { + len = env->data_len; + msg_truncated = 1; + } else + msg_truncated = 0; + not_printable = 0; + for (p = bytes, i = 0; i < len; ++i, ++p) { + if (!isprint((int)*p) && *p != '\t' && *p != '\n') { + if (i == len - 1 && *p == '\0') + break; + if (++not_printable >= (len >> 2)) + break; + } + } + if (not_printable < (len >> 2)) + for (p = bytes, i = len; i > 0; --i, ++p) { + if (isprint((int)*p)) + __db_msgadd(env, mbp, "%c", *p); + else + __db_msgadd(env, + mbp, "\\%x", (u_int)*p); + } + else + for (p = bytes, i = len; i > 0; --i, ++p) + __db_msgadd(env, mbp, "%.2x", (u_int)*p); + if (msg_truncated) + __db_msgadd(env, mbp, "..."); + } + DB_MSGBUF_FLUSH(env, mbp); +} + +/* + * __db_proff -- + * Print out an off-page element. + */ +static void +__db_proff(env, mbp, vp) + ENV *env; + DB_MSGBUF *mbp; + void *vp; +{ + BOVERFLOW *bo; + + bo = vp; + switch (B_TYPE(bo->type)) { + case B_OVERFLOW: + __db_msgadd(env, mbp, "overflow: total len: %4lu page: %4lu", + (u_long)bo->tlen, (u_long)bo->pgno); + break; + case B_DUPLICATE: + __db_msgadd( + env, mbp, "duplicate: page: %4lu", (u_long)bo->pgno); + break; + default: + /* NOTREACHED */ + break; + } + DB_MSGBUF_FLUSH(env, mbp); +} + +/* + * __db_prflags -- + * Print out flags values. + * + * PUBLIC: void __db_prflags __P((ENV *, DB_MSGBUF *, + * PUBLIC: u_int32_t, const FN *, const char *, const char *)); + */ +void +__db_prflags(env, mbp, flags, fn, prefix, suffix) + ENV *env; + DB_MSGBUF *mbp; + u_int32_t flags; + FN const *fn; + const char *prefix, *suffix; +{ + DB_MSGBUF mb; + const FN *fnp; + int found, standalone; + const char *sep; + + if (fn == NULL) + return; + + /* + * If it's a standalone message, output the suffix (which will be the + * label), regardless of whether we found anything or not, and flush + * the line. + */ + if (mbp == NULL) { + standalone = 1; + mbp = &mb; + DB_MSGBUF_INIT(mbp); + } else + standalone = 0; + + sep = prefix == NULL ? "" : prefix; + for (found = 0, fnp = fn; fnp->mask != 0; ++fnp) + if (LF_ISSET(fnp->mask)) { + __db_msgadd(env, mbp, "%s%s", sep, fnp->name); + sep = ", "; + found = 1; + } + + if ((standalone || found) && suffix != NULL) + __db_msgadd(env, mbp, "%s", suffix); + if (standalone) + DB_MSGBUF_FLUSH(env, mbp); +} + +/* + * __db_name_to_val -- + * Return the integral value associated with the string, or -1 if missing. + * It is intended for looking up string names of enums and single bit + * in order to get a numeric value. + * + * PUBLIC: int __db_name_to_val __P((FN const *, char *)); + */ +int +__db_name_to_val(strtable, s) + FN const *strtable; + char *s; +{ + if (s != NULL) { + do { + if (strcasecmp(strtable->name, s) == 0) + return ((int)strtable->mask); + } while ((++strtable)->name != NULL); + } + return (-1); +} + +/* + * __db_pagetype_to_string -- + * Return the name of the specified page type. + * PUBLIC: const char *__db_pagetype_to_string __P((u_int32_t)); + */ +const char * +__db_pagetype_to_string(type) + u_int32_t type; +{ + char *s; + + s = NULL; + switch (type) { + case P_BTREEMETA: + s = "btree metadata"; + break; + case P_LDUP: + s = "duplicate"; + break; + case P_HASH_UNSORTED: + s = "hash unsorted"; + break; + case P_HASH: + s = "hash"; + break; + case P_HASHMETA: + s = "hash metadata"; + break; + case P_IBTREE: + s = "btree internal"; + break; + case P_INVALID: + s = "invalid"; + break; + case P_IRECNO: + s = "recno internal"; + break; + case P_LBTREE: + s = "btree leaf"; + break; + case P_LRECNO: + s = "recno leaf"; + break; + case P_OVERFLOW: + s = "overflow"; + break; + case P_QAMMETA: + s = "queue metadata"; + break; + case P_QAMDATA: + s = "queue"; + break; + case P_HEAPMETA: + s = "heap metadata"; + break; + case P_HEAP: + s = "heap data"; + break; + case P_IHEAP: + s = "heap internal"; + break; + default: + /* Just return a NULL. */ + break; + } + return (s); +} + +/* + * __db_dump_pp -- + * DB->dump pre/post processing. + * + * PUBLIC: int __db_dump_pp __P((DB *, const char *, + * PUBLIC: int (*)(void *, const void *), void *, int, int)); + */ +int +__db_dump_pp(dbp, subname, callback, handle, pflag, keyflag) + DB *dbp; + const char *subname; + int (*callback) __P((void *, const void *)); + void *handle; + int pflag, keyflag; +{ + DB_THREAD_INFO *ip; + ENV *env; + int handle_check, ret, t_ret; + + env = dbp->env; + + DB_ILLEGAL_BEFORE_OPEN(dbp, "DB->dump"); + + ENV_ENTER(env, ip); + + /* Check for replication block. */ + handle_check = IS_ENV_REPLICATED(env); + if (handle_check && (ret = __db_rep_enter(dbp, 1, 0, 1)) != 0) { + handle_check = 0; + goto err; + } + + ret = __db_dump(dbp, subname, callback, handle, pflag, keyflag); + + /* Release replication block. */ + if (handle_check && (t_ret = __env_db_rep_exit(env)) != 0 && ret == 0) + ret = t_ret; + +err: ENV_LEAVE(env, ip); + return (ret); +} + +/* + * __db_dump -- + * DB->dump. + * + * PUBLIC: int __db_dump __P((DB *, const char *, + * PUBLIC: int (*)(void *, const void *), void *, int, int)); + */ +int +__db_dump(dbp, subname, callback, handle, pflag, keyflag) + DB *dbp; + const char *subname; + int (*callback) __P((void *, const void *)); + void *handle; + int pflag, keyflag; +{ + DBC *dbcp; + DBT key, data; + DBT keyret, dataret; + DB_HEAP_RID rid; + ENV *env; + db_recno_t recno; + int is_recno, is_heap, ret, t_ret; + void *pointer; + + env = dbp->env; + is_heap = 0; + + if ((ret = __db_prheader( + dbp, subname, pflag, keyflag, handle, callback, NULL, 0)) != 0) + return (ret); + + /* + * Get a cursor and step through the database, printing out each + * key/data pair. + */ + if ((ret = __db_cursor(dbp, NULL, NULL, &dbcp, 0)) != 0) + return (ret); + + memset(&key, 0, sizeof(key)); + memset(&data, 0, sizeof(data)); + if ((ret = __os_malloc(env, 1024 * 1024, &data.data)) != 0) + goto err; + data.ulen = 1024 * 1024; + data.flags = DB_DBT_USERMEM; + is_recno = (dbp->type == DB_RECNO || dbp->type == DB_QUEUE); + keyflag = is_recno ? keyflag : 1; + if (is_recno) { + keyret.data = &recno; + keyret.size = sizeof(recno); + } + + if (dbp->type == DB_HEAP) { + is_heap = 1; + key.data = &rid; + key.size = key.ulen = sizeof(DB_HEAP_RID); + key.flags = DB_DBT_USERMEM; + } + +retry: while ((ret = + __dbc_get(dbcp, &key, &data, + !is_heap ? DB_NEXT | DB_MULTIPLE_KEY : DB_NEXT )) == 0) { + if (is_heap) { + /* Never dump keys for HEAP */ + if ((ret = __db_prdbt( + &data, pflag, " ", handle, callback, 0, 0)) != 0) + goto err; + continue; + } + DB_MULTIPLE_INIT(pointer, &data); + for (;;) { + if (is_recno) + DB_MULTIPLE_RECNO_NEXT(pointer, &data, + recno, dataret.data, dataret.size); + else + DB_MULTIPLE_KEY_NEXT(pointer, &data, + keyret.data, keyret.size, + dataret.data, dataret.size); + + if (dataret.data == NULL) + break; + + if ((keyflag && + (ret = __db_prdbt(&keyret, pflag, " ", + handle, callback, is_recno, 0)) != 0) || + (ret = __db_prdbt(&dataret, pflag, " ", + handle, callback, 0, 0)) != 0) + goto err; + } + } + if (ret == DB_BUFFER_SMALL) { + data.size = (u_int32_t)DB_ALIGN(data.size, 1024); + if ((ret = __os_realloc(env, data.size, &data.data)) != 0) + goto err; + data.ulen = data.size; + goto retry; + } + if (ret == DB_NOTFOUND) + ret = 0; + + if ((t_ret = __db_prfooter(handle, callback)) != 0 && ret == 0) + ret = t_ret; + +err: if ((t_ret = __dbc_close(dbcp)) != 0 && ret == 0) + ret = t_ret; + if (data.data != NULL) + __os_free(env, data.data); + + return (ret); +} + +/* + * __db_prdbt -- + * Print out a DBT data element. + * + * PUBLIC: int __db_prdbt __P((DBT *, int, const char *, void *, + * PUBLIC: int (*)(void *, const void *), int, int)); + */ +int +__db_prdbt(dbtp, checkprint, prefix, handle, callback, is_recno, is_heap) + DBT *dbtp; + int checkprint; + const char *prefix; + void *handle; + int (*callback) __P((void *, const void *)); + int is_recno; + int is_heap; +{ + static const u_char hex[] = "0123456789abcdef"; + db_recno_t recno; + DB_HEAP_RID rid; + size_t len; + int ret; +#define DBTBUFLEN 100 + u_int8_t *p, *hp; + char buf[DBTBUFLEN], hbuf[DBTBUFLEN]; + + /* + * !!! + * This routine is the routine that dumps out items in the format + * used by db_dump(1) and db_load(1). This means that the format + * cannot change. + */ + if (prefix != NULL && (ret = callback(handle, prefix)) != 0) + return (ret); + if (is_recno) { + /* + * We're printing a record number, and this has to be done + * in a platform-independent way. So we use the numeral in + * straight ASCII. + */ + (void)__ua_memcpy(&recno, dbtp->data, sizeof(recno)); + snprintf(buf, DBTBUFLEN, "%lu", (u_long)recno); + + /* If we're printing data as hex, print keys as hex too. */ + if (!checkprint) { + for (len = strlen(buf), p = (u_int8_t *)buf, + hp = (u_int8_t *)hbuf; len-- > 0; ++p) { + *hp++ = hex[(u_int8_t)(*p & 0xf0) >> 4]; + *hp++ = hex[*p & 0x0f]; + } + *hp = '\0'; + ret = callback(handle, hbuf); + } else + ret = callback(handle, buf); + + if (ret != 0) + return (ret); + } else if (is_heap) { + /* + * We're printing a heap record number, and this has to be + * done in a platform-independent way. So we use the numeral + * in straight ASCII. + */ + (void)__ua_memcpy(&rid, dbtp->data, sizeof(rid)); + snprintf(buf, DBTBUFLEN, "%lu %hu", + (u_long)rid.pgno, (u_short)rid.indx); + + /* If we're printing data as hex, print keys as hex too. */ + if (!checkprint) { + for (len = strlen(buf), p = (u_int8_t *)buf, + hp = (u_int8_t *)hbuf; len-- > 0; ++p) { + *hp++ = hex[(u_int8_t)(*p & 0xf0) >> 4]; + *hp++ = hex[*p & 0x0f]; + } + *hp = '\0'; + ret = callback(handle, hbuf); + } else + ret = callback(handle, buf); + + if (ret != 0) + return (ret); + } else if (checkprint) { + for (len = dbtp->size, p = dbtp->data; len--; ++p) + if (isprint((int)*p)) { + if (*p == '\\' && + (ret = callback(handle, "\\")) != 0) + return (ret); + snprintf(buf, DBTBUFLEN, "%c", *p); + if ((ret = callback(handle, buf)) != 0) + return (ret); + } else { + snprintf(buf, DBTBUFLEN, "\\%c%c", + hex[(u_int8_t)(*p & 0xf0) >> 4], + hex[*p & 0x0f]); + if ((ret = callback(handle, buf)) != 0) + return (ret); + } + } else + for (len = dbtp->size, p = dbtp->data; len--; ++p) { + snprintf(buf, DBTBUFLEN, "%c%c", + hex[(u_int8_t)(*p & 0xf0) >> 4], + hex[*p & 0x0f]); + if ((ret = callback(handle, buf)) != 0) + return (ret); + } + + return (callback(handle, "\n")); +} + +/* + * __db_prheader -- + * Write out header information in the format expected by db_load. + * + * PUBLIC: int __db_prheader __P((DB *, const char *, int, int, void *, + * PUBLIC: int (*)(void *, const void *), VRFY_DBINFO *, db_pgno_t)); + */ +int +__db_prheader(dbp, subname, pflag, keyflag, handle, callback, vdp, meta_pgno) + DB *dbp; + const char *subname; + int pflag, keyflag; + void *handle; + int (*callback) __P((void *, const void *)); + VRFY_DBINFO *vdp; + db_pgno_t meta_pgno; +{ + DBT dbt; + DBTYPE dbtype; + ENV *env; + VRFY_PAGEINFO *pip; + u_int32_t flags, tmp_u_int32; + size_t buflen; + char *buf; + int using_vdp, ret, t_ret, tmp_int; +#ifdef HAVE_HEAP + u_int32_t tmp2_u_int32; +#endif + + ret = 0; + buf = NULL; + COMPQUIET(buflen, 0); + + /* + * If dbp is NULL, then pip is guaranteed to be non-NULL; we only ever + * call __db_prheader with a NULL dbp from one case inside __db_prdbt, + * and this is a special subdatabase for "lost" items. In this case + * we have a vdp (from which we'll get a pip). In all other cases, we + * will have a non-NULL dbp (and vdp may or may not be NULL depending + * on whether we're salvaging). + */ + if (dbp == NULL) + env = NULL; + else + env = dbp->env; + DB_ASSERT(env, dbp != NULL || vdp != NULL); + + /* + * If we've been passed a verifier statistics object, use that; we're + * being called in a context where dbp->stat is unsafe. + * + * Also, the verifier may set the pflag on a per-salvage basis. If so, + * respect that. + */ + if (vdp != NULL) { + if ((ret = __db_vrfy_getpageinfo(vdp, meta_pgno, &pip)) != 0) + return (ret); + + if (F_ISSET(vdp, SALVAGE_PRINTABLE)) + pflag = 1; + using_vdp = 1; + } else { + pip = NULL; + using_vdp = 0; + } + + /* + * If dbp is NULL, make it a btree. Otherwise, set dbtype to whatever + * appropriate type for the specified meta page, or the type of the dbp. + */ + if (dbp == NULL) + dbtype = DB_BTREE; + else if (using_vdp) + switch (pip->type) { + case P_BTREEMETA: + if (F_ISSET(pip, VRFY_IS_RECNO)) + dbtype = DB_RECNO; + else + dbtype = DB_BTREE; + break; + case P_HASHMETA: + dbtype = DB_HASH; + break; + case P_HEAPMETA: + dbtype = DB_HEAP; + break; + case P_QAMMETA: + dbtype = DB_QUEUE; + break; + default: + /* + * If the meta page is of a bogus type, it's because + * we have a badly corrupt database. (We must be in + * the verifier for pip to be non-NULL.) Pretend we're + * a Btree and salvage what we can. + */ + DB_ASSERT(env, F_ISSET(dbp, DB_AM_VERIFYING)); + dbtype = DB_BTREE; + break; + } + else + dbtype = dbp->type; + + if ((ret = callback(handle, "VERSION=3\n")) != 0) + goto err; + if (pflag) { + if ((ret = callback(handle, "format=print\n")) != 0) + goto err; + } else if ((ret = callback(handle, "format=bytevalue\n")) != 0) + goto err; + + /* + * 64 bytes is long enough, as a minimum bound, for any of the + * fields besides subname. Subname uses __db_prdbt and therefore + * does not need buffer space here. + */ + buflen = 64; + if ((ret = __os_malloc(env, buflen, &buf)) != 0) + goto err; + if (subname != NULL) { + snprintf(buf, buflen, "database="); + if ((ret = callback(handle, buf)) != 0) + goto err; + DB_INIT_DBT(dbt, subname, strlen(subname)); + if ((ret = __db_prdbt(&dbt, 1, + NULL, handle, callback, 0, 0)) != 0) + goto err; + } + switch (dbtype) { + case DB_BTREE: + if ((ret = callback(handle, "type=btree\n")) != 0) + goto err; + if (using_vdp) + tmp_int = F_ISSET(pip, VRFY_HAS_RECNUMS) ? 1 : 0; + else { + if ((ret = __db_get_flags(dbp, &flags)) != 0) { + __db_err(env, ret, "DB->get_flags"); + goto err; + } + tmp_int = F_ISSET(dbp, DB_AM_RECNUM) ? 1 : 0; + } + if (tmp_int && (ret = callback(handle, "recnum=1\n")) != 0) + goto err; + + if (using_vdp) + tmp_u_int32 = pip->bt_minkey; + else + if ((ret = + __bam_get_bt_minkey(dbp, &tmp_u_int32)) != 0) { + __db_err(env, ret, "DB->get_bt_minkey"); + goto err; + } + if (tmp_u_int32 != 0 && tmp_u_int32 != DEFMINKEYPAGE) { + snprintf(buf, buflen, + "bt_minkey=%lu\n", (u_long)tmp_u_int32); + if ((ret = callback(handle, buf)) != 0) + goto err; + } + break; + case DB_HASH: +#ifdef HAVE_HASH + if ((ret = callback(handle, "type=hash\n")) != 0) + goto err; + if (using_vdp) + tmp_u_int32 = pip->h_ffactor; + else + if ((ret = + __ham_get_h_ffactor(dbp, &tmp_u_int32)) != 0) { + __db_err(env, ret, "DB->get_h_ffactor"); + goto err; + } + if (tmp_u_int32 != 0) { + snprintf(buf, buflen, + "h_ffactor=%lu\n", (u_long)tmp_u_int32); + if ((ret = callback(handle, buf)) != 0) + goto err; + } + + if (using_vdp) + tmp_u_int32 = pip->h_nelem; + else + if ((ret = __ham_get_h_nelem(dbp, &tmp_u_int32)) != 0) { + __db_err(env, ret, "DB->get_h_nelem"); + goto err; + } + /* + * Hash databases have an h_nelem field of 0 or 1, neither + * of those values is interesting. + */ + if (tmp_u_int32 > 1) { + snprintf(buf, buflen, + "h_nelem=%lu\n", (u_long)tmp_u_int32); + if ((ret = callback(handle, buf)) != 0) + goto err; + } + break; +#else + ret = __db_no_hash_am(env); + goto err; +#endif + case DB_HEAP: +#ifdef HAVE_HEAP + if ((ret = callback(handle, "type=heap\n")) != 0) + goto err; + + if ((ret = __heap_get_heapsize( + dbp, &tmp_u_int32, &tmp2_u_int32)) != 0) { + __db_err(env, ret, "DB->get_heapsize"); + goto err; + } + if (tmp_u_int32 != 0) { + snprintf(buf, + buflen, "heap_gbytes=%lu\n", (u_long)tmp_u_int32); + if ((ret = callback(handle, buf)) != 0) + goto err; + } + if (tmp2_u_int32 != 0) { + snprintf(buf, + buflen, "heap_bytes=%lu\n", (u_long)tmp2_u_int32); + if ((ret = callback(handle, buf)) != 0) + goto err; + } + + if ((ret = + __heap_get_heap_regionsize(dbp, &tmp_u_int32)) != 0) { + __db_err(env, ret, "DB->get_heap_regionsize"); + goto err; + } + if (tmp_u_int32 != 0) { + snprintf(buf, buflen, + "heap_regionsize=%lu\n", (u_long)tmp_u_int32); + if ((ret = callback(handle, buf)) != 0) + goto err; + } + break; +#else + ret = __db_no_heap_am(env); + goto err; +#endif + case DB_QUEUE: +#ifdef HAVE_QUEUE + if ((ret = callback(handle, "type=queue\n")) != 0) + goto err; + if (using_vdp) + tmp_u_int32 = vdp->re_len; + else + if ((ret = __ram_get_re_len(dbp, &tmp_u_int32)) != 0) { + __db_err(env, ret, "DB->get_re_len"); + goto err; + } + snprintf(buf, buflen, "re_len=%lu\n", (u_long)tmp_u_int32); + if ((ret = callback(handle, buf)) != 0) + goto err; + + if (using_vdp) + tmp_int = (int)vdp->re_pad; + else + if ((ret = __ram_get_re_pad(dbp, &tmp_int)) != 0) { + __db_err(env, ret, "DB->get_re_pad"); + goto err; + } + if (tmp_int != 0 && tmp_int != ' ') { + snprintf(buf, buflen, "re_pad=%#x\n", tmp_int); + if ((ret = callback(handle, buf)) != 0) + goto err; + } + + if (using_vdp) + tmp_u_int32 = vdp->page_ext; + else + if ((ret = + __qam_get_extentsize(dbp, &tmp_u_int32)) != 0) { + __db_err(env, ret, "DB->get_q_extentsize"); + goto err; + } + if (tmp_u_int32 != 0) { + snprintf(buf, buflen, + "extentsize=%lu\n", (u_long)tmp_u_int32); + if ((ret = callback(handle, buf)) != 0) + goto err; + } + break; +#else + ret = __db_no_queue_am(env); + goto err; +#endif + case DB_RECNO: + if ((ret = callback(handle, "type=recno\n")) != 0) + goto err; + if (using_vdp) + tmp_int = F_ISSET(pip, VRFY_IS_RRECNO) ? 1 : 0; + else + tmp_int = F_ISSET(dbp, DB_AM_RENUMBER) ? 1 : 0; + if (tmp_int != 0 && + (ret = callback(handle, "renumber=1\n")) != 0) + goto err; + + if (using_vdp) + tmp_int = F_ISSET(pip, VRFY_IS_FIXEDLEN) ? 1 : 0; + else + tmp_int = F_ISSET(dbp, DB_AM_FIXEDLEN) ? 1 : 0; + if (tmp_int) { + if (using_vdp) + tmp_u_int32 = pip->re_len; + else + if ((ret = + __ram_get_re_len(dbp, &tmp_u_int32)) != 0) { + __db_err(env, ret, "DB->get_re_len"); + goto err; + } + snprintf(buf, buflen, + "re_len=%lu\n", (u_long)tmp_u_int32); + if ((ret = callback(handle, buf)) != 0) + goto err; + + if (using_vdp) + tmp_int = (int)pip->re_pad; + else + if ((ret = + __ram_get_re_pad(dbp, &tmp_int)) != 0) { + __db_err(env, ret, "DB->get_re_pad"); + goto err; + } + if (tmp_int != 0 && tmp_int != ' ') { + snprintf(buf, + buflen, "re_pad=%#x\n", (u_int)tmp_int); + if ((ret = callback(handle, buf)) != 0) + goto err; + } + } + break; + case DB_UNKNOWN: /* Impossible. */ + ret = __db_unknown_path(env, "__db_prheader"); + goto err; + } + + if (using_vdp) { + if (F_ISSET(pip, VRFY_HAS_CHKSUM)) + if ((ret = callback(handle, "chksum=1\n")) != 0) + goto err; + if (F_ISSET(pip, VRFY_HAS_DUPS)) + if ((ret = callback(handle, "duplicates=1\n")) != 0) + goto err; + if (F_ISSET(pip, VRFY_HAS_DUPSORT)) + if ((ret = callback(handle, "dupsort=1\n")) != 0) + goto err; +#ifdef HAVE_COMPRESSION + if (F_ISSET(pip, VRFY_HAS_COMPRESS)) + if ((ret = callback(handle, "compressed=1\n")) != 0) + goto err; +#endif + /* + * !!! + * We don't know if the page size was the default if we're + * salvaging. It doesn't seem that interesting to have, so + * we ignore it for now. + */ + } else { + if (F_ISSET(dbp, DB_AM_CHKSUM)) + if ((ret = callback(handle, "chksum=1\n")) != 0) + goto err; + if (F_ISSET(dbp, DB_AM_DUP)) + if ((ret = callback(handle, "duplicates=1\n")) != 0) + goto err; + if (F_ISSET(dbp, DB_AM_DUPSORT)) + if ((ret = callback(handle, "dupsort=1\n")) != 0) + goto err; +#ifdef HAVE_COMPRESSION + if (DB_IS_COMPRESSED(dbp)) + if ((ret = callback(handle, "compressed=1\n")) != 0) + goto err; +#endif + if (!F_ISSET(dbp, DB_AM_PGDEF)) { + snprintf(buf, buflen, + "db_pagesize=%lu\n", (u_long)dbp->pgsize); + if ((ret = callback(handle, buf)) != 0) + goto err; + } + } + +#ifdef HAVE_PARTITION + if (dbp != NULL && DB_IS_PARTITIONED(dbp) && + F_ISSET((DB_PARTITION *)dbp->p_internal, PART_RANGE)) { + DBT *keys; + u_int32_t i; + + if ((ret = __partition_get_keys(dbp, &tmp_u_int32, &keys)) != 0) + goto err; + if (tmp_u_int32 != 0) { + snprintf(buf, + buflen, "nparts=%lu\n", (u_long)tmp_u_int32); + if ((ret = callback(handle, buf)) != 0) + goto err; + for (i = 0; i < tmp_u_int32 - 1; i++) + if ((ret = __db_prdbt(&keys[i], + pflag, " ", handle, callback, 0, 0)) != 0) + goto err; + } + } +#endif + + if (keyflag && (ret = callback(handle, "keys=1\n")) != 0) + goto err; + + ret = callback(handle, "HEADER=END\n"); + +err: if (using_vdp && + (t_ret = __db_vrfy_putpageinfo(env, vdp, pip)) != 0 && ret == 0) + ret = t_ret; + if (buf != NULL) + __os_free(env, buf); + + return (ret); +} + +/* + * __db_prfooter -- + * Print the footer that marks the end of a DB dump. This is trivial, + * but for consistency's sake we don't want to put its literal contents + * in multiple places. + * + * PUBLIC: int __db_prfooter __P((void *, int (*)(void *, const void *))); + */ +int +__db_prfooter(handle, callback) + void *handle; + int (*callback) __P((void *, const void *)); +{ + return (callback(handle, "DATA=END\n")); +} + +/* + * __db_pr_callback -- + * Callback function for using pr_* functions from C. + * + * PUBLIC: int __db_pr_callback __P((void *, const void *)); + */ +int +__db_pr_callback(handle, str_arg) + void *handle; + const void *str_arg; +{ + char *str; + FILE *f; + + str = (char *)str_arg; + f = (FILE *)handle; + + if (fprintf(f, "%s", str) != (int)strlen(str)) + return (EIO); + + return (0); +} + +/* + * __db_dbtype_to_string -- + * Return the name of the database type. + * + * PUBLIC: const char * __db_dbtype_to_string __P((DBTYPE)); + */ +const char * +__db_dbtype_to_string(type) + DBTYPE type; +{ + switch (type) { + case DB_BTREE: + return ("btree"); + case DB_HASH: + return ("hash"); + case DB_RECNO: + return ("recno"); + case DB_QUEUE: + return ("queue"); + case DB_HEAP: + return ("heap"); + case DB_UNKNOWN: + default: + break; + } + return ("UNKNOWN TYPE"); +} diff -r 000000000000 -r a1985f14b030 src/db/db_reclaim.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/db/db_reclaim.c Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,267 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 1996, 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + * $Id$ + */ + +#include "db_config.h" + +#include "db_int.h" +#include "dbinc/db_page.h" +#include "dbinc/btree.h" +#include "dbinc/mp.h" + +/* + * __db_traverse_big + * Traverse a chain of overflow pages and call the callback routine + * on each one. The calling convention for the callback is: + * callback(dbc, page, cookie, did_put), + * where did_put is a return value indicating if the page in question has + * already been returned to the mpool. + * + * PUBLIC: int __db_traverse_big __P((DBC *, db_pgno_t, + * PUBLIC: int (*)(DBC *, PAGE *, void *, int *), void *)); + */ +int +__db_traverse_big(dbc, pgno, callback, cookie) + DBC *dbc; + db_pgno_t pgno; + int (*callback) __P((DBC *, PAGE *, void *, int *)); + void *cookie; +{ + DB_MPOOLFILE *mpf; + PAGE *p; + int did_put, ret; + + mpf = dbc->dbp->mpf; + + do { + did_put = 0; + if ((ret = __memp_fget(mpf, + &pgno, dbc->thread_info, dbc->txn, 0, &p)) != 0) + return (ret); + /* + * If we are freeing pages only process the overflow + * chain if the head of the chain has a refcount of 1. + */ + pgno = NEXT_PGNO(p); + if (callback == __db_truncate_callback && OV_REF(p) != 1) + pgno = PGNO_INVALID; + if ((ret = callback(dbc, p, cookie, &did_put)) == 0 && + !did_put) + ret = __memp_fput(mpf, + dbc->thread_info, p, dbc->priority); + } while (ret == 0 && pgno != PGNO_INVALID); + + return (ret); +} + +/* + * __db_reclaim_callback + * This is the callback routine used during a delete of a subdatabase. + * we are traversing a btree or hash table and trying to free all the + * pages. Since they share common code for duplicates and overflow + * items, we traverse them identically and use this routine to do the + * actual free. The reason that this is callback is because hash uses + * the same traversal code for statistics gathering. + * + * PUBLIC: int __db_reclaim_callback __P((DBC *, PAGE *, void *, int *)); + */ +int +__db_reclaim_callback(dbc, p, cookie, putp) + DBC *dbc; + PAGE *p; + void *cookie; + int *putp; +{ + DB *dbp; + int ret; + + dbp = dbc->dbp; + + /* + * We don't want to log the free of the root with the subdb. + * If we abort then the subdb may not be openable to undo + * the free. + */ + if ((dbp->type == DB_BTREE || dbp->type == DB_RECNO) && + PGNO(p) == ((BTREE *)dbp->bt_internal)->bt_root) + return (0); + if ((ret = __db_free(dbc, p, *(u_int32_t *)cookie)) != 0) + return (ret); + *putp = 1; + + return (0); +} + +/* + * __db_truncate_callback + * This is the callback routine used during a truncate. + * we are traversing a btree or hash table and trying to free all the + * pages. + * + * PUBLIC: int __db_truncate_callback __P((DBC *, PAGE *, void *, int *)); + */ +int +__db_truncate_callback(dbc, p, cookie, putp) + DBC *dbc; + PAGE *p; + void *cookie; + int *putp; +{ + DB *dbp; + DBT ddbt, ldbt; + DB_MPOOLFILE *mpf; + db_indx_t indx, len, off, tlen, top; + u_int8_t *hk, type; + u_int32_t *countp; + int ret; + + top = NUM_ENT(p); + dbp = dbc->dbp; + mpf = dbp->mpf; + countp = cookie; + *putp = 1; + + switch (TYPE(p)) { + case P_LBTREE: + /* Skip for off-page duplicates and deleted items. */ + for (indx = 0; indx < top; indx += P_INDX) { + type = GET_BKEYDATA(dbp, p, indx + O_INDX)->type; + if (!B_DISSET(type) && B_TYPE(type) != B_DUPLICATE) + ++*countp; + } + /* FALLTHROUGH */ + case P_IBTREE: + case P_IRECNO: + case P_INVALID: + if (dbp->type != DB_HASH && + ((BTREE *)dbp->bt_internal)->bt_root == PGNO(p)) { + type = dbp->type == DB_RECNO ? P_LRECNO : P_LBTREE; + goto reinit; + } + break; + case P_OVERFLOW: + if ((ret = __memp_dirty(mpf, + &p, dbc->thread_info, dbc->txn, dbc->priority, 0)) != 0) + return (ret); + if (DBC_LOGGING(dbc)) { + if ((ret = __db_ovref_log(dbp, dbc->txn, + &LSN(p), 0, p->pgno, -1, &LSN(p))) != 0) + return (ret); + } else + LSN_NOT_LOGGED(LSN(p)); + if (--OV_REF(p) != 0) + *putp = 0; + break; + case P_LRECNO: + for (indx = 0; indx < top; indx += O_INDX) { + type = GET_BKEYDATA(dbp, p, indx)->type; + if (!B_DISSET(type)) + ++*countp; + } + + if (((BTREE *)dbp->bt_internal)->bt_root == PGNO(p)) { + type = P_LRECNO; + goto reinit; + } + break; + case P_LDUP: + /* Correct for deleted items. */ + for (indx = 0; indx < top; indx += O_INDX) + if (!B_DISSET(GET_BKEYDATA(dbp, p, indx)->type)) + ++*countp; + + break; + case P_HASH: + /* Correct for on-page duplicates and deleted items. */ + for (indx = 0; indx < top; indx += P_INDX) { + switch (*H_PAIRDATA(dbp, p, indx)) { + case H_OFFDUP: + break; + case H_OFFPAGE: + case H_KEYDATA: + ++*countp; + break; + case H_DUPLICATE: + tlen = LEN_HDATA(dbp, p, 0, indx); + hk = H_PAIRDATA(dbp, p, indx); + for (off = 0; off < tlen; + off += len + 2 * sizeof(db_indx_t)) { + ++*countp; + memcpy(&len, + HKEYDATA_DATA(hk) + + off, sizeof(db_indx_t)); + } + break; + default: + return (__db_pgfmt(dbp->env, p->pgno)); + } + } + /* Don't free the head of the bucket. */ + if (PREV_PGNO(p) == PGNO_INVALID) { + type = P_HASH; + +reinit: if ((ret = __memp_dirty(mpf, &p, + dbc->thread_info, dbc->txn, dbc->priority, 0)) != 0) + return (ret); + *putp = 0; + if (DBC_LOGGING(dbc)) { + memset(&ldbt, 0, sizeof(ldbt)); + memset(&ddbt, 0, sizeof(ddbt)); + ldbt.data = p; + ldbt.size = P_OVERHEAD(dbp); + ldbt.size += p->entries * sizeof(db_indx_t); + ddbt.data = (u_int8_t *)p + HOFFSET(p); + ddbt.size = dbp->pgsize - HOFFSET(p); + if ((ret = __db_pg_init_log(dbp, + dbc->txn, &LSN(p), 0, + p->pgno, &ldbt, &ddbt)) != 0) + return (ret); + } else + LSN_NOT_LOGGED(LSN(p)); + + P_INIT(p, dbp->pgsize, PGNO(p), PGNO_INVALID, + PGNO_INVALID, type == P_HASH ? 0 : 1, type); + } + break; + default: + return (__db_pgfmt(dbp->env, p->pgno)); + } + + if (*putp == 1) { + if ((ret = __db_free(dbc, p, 0)) != 0) + return (ret); + } else { + if ((ret = __memp_fput(mpf, dbc->thread_info, p, + dbc->priority)) != 0) + return (ret); + *putp = 1; + } + + return (0); +} diff -r 000000000000 -r a1985f14b030 src/db/db_remove.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/db/db_remove.c Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,480 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 2001, 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + * $Id$ + */ + +#include "db_config.h" + +#include "db_int.h" +#include "dbinc/db_page.h" +#include "dbinc/fop.h" +#include "dbinc/btree.h" +#include "dbinc/hash.h" +#include "dbinc/lock.h" +#include "dbinc/mp.h" +#include "dbinc/txn.h" + +static int __db_subdb_remove __P((DB *, + DB_THREAD_INFO *, DB_TXN *, const char *, const char *, u_int32_t)); + +/* + * __env_dbremove_pp + * ENV->dbremove pre/post processing. + * + * PUBLIC: int __env_dbremove_pp __P((DB_ENV *, + * PUBLIC: DB_TXN *, const char *, const char *, u_int32_t)); + */ +int +__env_dbremove_pp(dbenv, txn, name, subdb, flags) + DB_ENV *dbenv; + DB_TXN *txn; + const char *name, *subdb; + u_int32_t flags; +{ + DB *dbp; + DB_THREAD_INFO *ip; + ENV *env; + int handle_check, ret, t_ret, txn_local; + + dbp = NULL; + env = dbenv->env; + txn_local = 0; + handle_check = 0; + + ENV_ILLEGAL_BEFORE_OPEN(env, "DB_ENV->dbremove"); + + /* + * The actual argument checking is simple, do it inline, outside of + * the replication block. + */ + if ((ret = __db_fchk(env, "DB->remove", flags, + DB_AUTO_COMMIT | DB_LOG_NO_DATA | + DB_NOSYNC | DB_TXN_NOT_DURABLE)) != 0) + return (ret); + + ENV_ENTER(env, ip); + XA_NO_TXN(ip, ret); + if (ret != 0) + goto err; + + /* Check for replication block. */ + handle_check = IS_ENV_REPLICATED(env); + if (handle_check && (ret = __env_rep_enter(env, 1)) != 0) { + handle_check = 0; + goto err; + } + + /* + * Create local transaction as necessary, check for consistent + * transaction usage. + */ + if (IS_ENV_AUTO_COMMIT(env, txn, flags)) { + if ((ret = __db_txn_auto_init(env, ip, &txn)) != 0) + goto err; + txn_local = 1; + } else if (txn != NULL && !TXN_ON(env) && + (!CDB_LOCKING(env) || !F_ISSET(txn, TXN_FAMILY))) { + ret = __db_not_txn_env(env); + goto err; + } else if (txn != NULL && LF_ISSET(DB_LOG_NO_DATA)) { + ret = EINVAL; + __db_errx(env, DB_STR("0690", + "DB_LOG_NO_DATA may not be specified within a transaction.")); + goto err; + } + LF_CLR(DB_AUTO_COMMIT); + + if ((ret = __db_create_internal(&dbp, env, 0)) != 0) + goto err; + if (LF_ISSET(DB_TXN_NOT_DURABLE) && + (ret = __db_set_flags(dbp, DB_TXN_NOT_DURABLE)) != 0) + goto err; + LF_CLR(DB_TXN_NOT_DURABLE); + + ret = __db_remove_int(dbp, ip, txn, name, subdb, flags); + + if (txn_local) { + /* + * We created the DBP here and when we commit/abort, we'll + * release all the transactional locks, including the handle + * lock; mark the handle cleared explicitly. + */ + LOCK_INIT(dbp->handle_lock); + dbp->locker = NULL; + } else if (IS_REAL_TXN(txn)) { + /* + * We created this handle locally so we need to close it + * and clean it up. Unfortunately, it's holding transactional + * locks that need to persist until the end of transaction. + * If we invalidate the locker id (dbp->locker), then the close + * won't free these locks prematurely. + */ + dbp->locker = NULL; + } + +err: if (txn_local && (t_ret = + __db_txn_auto_resolve(env, txn, 0, ret)) != 0 && ret == 0) + ret = t_ret; + + /* + * We never opened this dbp for real, so don't include a transaction + * handle, and use NOSYNC to avoid calling into mpool. + * + * !!! + * Note we're reversing the order of operations: we started the txn and + * then opened the DB handle; we're resolving the txn and then closing + * closing the DB handle -- a DB handle cannot be closed before + * resolving the txn. + */ + if (dbp != NULL && + (t_ret = __db_close(dbp, NULL, DB_NOSYNC)) != 0 && ret == 0) + ret = t_ret; + + if (handle_check && (t_ret = __env_db_rep_exit(env)) != 0 && ret == 0) + ret = t_ret; + + ENV_LEAVE(env, ip); + return (ret); +} + +/* + * __db_remove_pp + * DB->remove pre/post processing. + * + * PUBLIC: int __db_remove_pp + * PUBLIC: __P((DB *, const char *, const char *, u_int32_t)); + */ +int +__db_remove_pp(dbp, name, subdb, flags) + DB *dbp; + const char *name, *subdb; + u_int32_t flags; +{ + DB_THREAD_INFO *ip; + ENV *env; + int handle_check, ret, t_ret; + + env = dbp->env; + + /* + * Validate arguments, continuing to destroy the handle on failure. + * + * Cannot use DB_ILLEGAL_AFTER_OPEN directly because it returns. + * + * !!! + * We have a serious problem if we're here with a handle used to open + * a database -- we'll destroy the handle, and the application won't + * ever be able to close the database. + */ + if (F_ISSET(dbp, DB_AM_OPEN_CALLED)) + return (__db_mi_open(env, "DB->remove", 1)); + + /* Validate arguments. */ + if ((ret = __db_fchk(env, "DB->remove", flags, DB_NOSYNC)) != 0) + return (ret); + + /* Check for consistent transaction usage. */ + if ((ret = __db_check_txn(dbp, NULL, DB_LOCK_INVALIDID, 0)) != 0) + return (ret); + + ENV_ENTER(env, ip); + + handle_check = IS_ENV_REPLICATED(env); + if (handle_check && (ret = __db_rep_enter(dbp, 1, 1, 0)) != 0) { + handle_check = 0; + goto err; + } + + /* Remove the file. */ + ret = __db_remove(dbp, ip, NULL, name, subdb, flags); + + if (handle_check && (t_ret = __env_db_rep_exit(env)) != 0 && ret == 0) + ret = t_ret; + +err: ENV_LEAVE(env, ip); + return (ret); +} + +/* + * __db_remove + * DB->remove method. + * + * PUBLIC: int __db_remove __P((DB *, DB_THREAD_INFO *, + * PUBLIC: DB_TXN *, const char *, const char *, u_int32_t)); + */ +int +__db_remove(dbp, ip, txn, name, subdb, flags) + DB *dbp; + DB_THREAD_INFO *ip; + DB_TXN *txn; + const char *name, *subdb; + u_int32_t flags; +{ + int ret, t_ret; + + ret = __db_remove_int(dbp, ip, txn, name, subdb, flags); + + if ((t_ret = __db_close(dbp, txn, DB_NOSYNC)) != 0 && ret == 0) + ret = t_ret; + + return (ret); +} + +/* + * __db_remove_int + * Worker function for the DB->remove method. + * + * PUBLIC: int __db_remove_int __P((DB *, DB_THREAD_INFO *, + * PUBLIC: DB_TXN *, const char *, const char *, u_int32_t)); + */ +int +__db_remove_int(dbp, ip, txn, name, subdb, flags) + DB *dbp; + DB_THREAD_INFO *ip; + DB_TXN *txn; + const char *name, *subdb; + u_int32_t flags; +{ + ENV *env; + int ret; + char *real_name, *tmpname; + + env = dbp->env; + real_name = tmpname = NULL; + + if (name == NULL && subdb == NULL) { + __db_errx(env, DB_STR("0691", + "Remove on temporary files invalid")); + ret = EINVAL; + goto err; + } + + if (name == NULL) { + MAKE_INMEM(dbp); + real_name = (char *)subdb; + } else if (subdb != NULL) { + ret = __db_subdb_remove(dbp, ip, txn, name, subdb, flags); + goto err; + } + + /* Handle transactional file removes separately. */ + if (IS_REAL_TXN(txn)) { + ret = __db_dbtxn_remove(dbp, ip, txn, name, subdb); + goto err; + } + + /* + * The remaining case is a non-transactional file remove. + * + * Find the real name of the file. + */ + if (!F_ISSET(dbp, DB_AM_INMEM) && (ret = __db_appname(env, + DB_APP_DATA, name, &dbp->dirname, &real_name)) != 0) + goto err; + + /* + * If this is a file and force is set, remove the temporary file, which + * may have been left around. Ignore errors because the temporary file + * might not exist. + */ + if (!F_ISSET(dbp, DB_AM_INMEM) && LF_ISSET(DB_FORCE) && + (ret = __db_backup_name(env, real_name, NULL, &tmpname)) == 0) + (void)__os_unlink(env, tmpname, 0); + + if ((ret = __fop_remove_setup(dbp, NULL, real_name, 0)) != 0) + goto err; + + if (dbp->db_am_remove != NULL && + (ret = dbp->db_am_remove(dbp, ip, NULL, name, subdb, flags)) != 0) + goto err; + + ret = F_ISSET(dbp, DB_AM_INMEM) ? + __db_inmem_remove(dbp, NULL, real_name) : + __fop_remove(env, + NULL, dbp->fileid, name, &dbp->dirname, DB_APP_DATA, + F_ISSET(dbp, DB_AM_NOT_DURABLE) ? DB_LOG_NOT_DURABLE : 0); + +err: if (!F_ISSET(dbp, DB_AM_INMEM) && real_name != NULL) + __os_free(env, real_name); + if (tmpname != NULL) + __os_free(env, tmpname); + + return (ret); +} + +/* + * __db_inmem_remove -- + * Removal of a named in-memory database. + * + * PUBLIC: int __db_inmem_remove __P((DB *, DB_TXN *, const char *)); + */ +int +__db_inmem_remove(dbp, txn, name) + DB *dbp; + DB_TXN *txn; + const char *name; +{ + DBT fid_dbt, name_dbt; + DB_LOCKER *locker; + DB_LSN lsn; + ENV *env; + int ret; + + env = dbp->env; + locker = NULL; + + DB_ASSERT(env, name != NULL); + + /* This had better exist if we are trying to do a remove. */ + (void)__memp_set_flags(dbp->mpf, DB_MPOOL_NOFILE, 1); + if ((ret = __memp_fopen(dbp->mpf, NULL, + name, &dbp->dirname, 0, 0, 0)) != 0) + return (ret); + if ((ret = __memp_get_fileid(dbp->mpf, dbp->fileid)) != 0) + return (ret); + dbp->preserve_fid = 1; + + if (LOCKING_ON(env)) { + if (dbp->locker == NULL && + (ret = __lock_id(env, NULL, &dbp->locker)) != 0) + return (ret); + if (!CDB_LOCKING(env) && + txn != NULL && F_ISSET(txn, TXN_INFAMILY)) { + if ((ret = __lock_addfamilylocker(env, + txn->txnid, dbp->locker->id, 1)) != 0) + return (ret); + txn = NULL; + } + locker = txn == NULL ? dbp->locker : txn->locker; + } + + /* + * In a transactional environment, we'll play the same game we play + * for databases in the file system -- create a temporary database + * and put it in with the current name and then rename this one to + * another name. We'll then use a commit-time event to remove the + * entry. + */ + if ((ret = + __fop_lock_handle(env, dbp, locker, DB_LOCK_WRITE, NULL, 0)) != 0) + return (ret); + + if (!IS_REAL_TXN(txn)) + ret = __memp_nameop(env, dbp->fileid, NULL, name, NULL, 1); + else if (LOGGING_ON(env)) { + if (txn != NULL && (ret = + __txn_remevent(env, txn, name, dbp->fileid, 1)) != 0) + return (ret); + + DB_INIT_DBT(name_dbt, name, strlen(name) + 1); + DB_INIT_DBT(fid_dbt, dbp->fileid, DB_FILE_ID_LEN); + ret = __crdel_inmem_remove_log( + env, txn, &lsn, 0, &name_dbt, &fid_dbt); + } + + return (ret); +} + +/* + * __db_subdb_remove -- + * Remove a subdatabase. + */ +static int +__db_subdb_remove(dbp, ip, txn, name, subdb, flags) + DB *dbp; + DB_THREAD_INFO *ip; + DB_TXN *txn; + const char *name, *subdb; + u_int32_t flags; +{ + DB *mdbp, *sdbp; + int ret, t_ret; + + mdbp = sdbp = NULL; + + /* Open the subdatabase. */ + if ((ret = __db_create_internal(&sdbp, dbp->env, 0)) != 0) + goto err; + if (F_ISSET(dbp, DB_AM_NOT_DURABLE) && + (ret = __db_set_flags(sdbp, DB_TXN_NOT_DURABLE)) != 0) + goto err; + if ((ret = __db_open(sdbp, ip, + txn, name, subdb, DB_UNKNOWN, DB_WRITEOPEN, 0, PGNO_BASE_MD)) != 0) + goto err; + + DB_TEST_RECOVERY(sdbp, DB_TEST_PREDESTROY, ret, name); + + /* Have the handle locked so we will not lock pages. */ + LOCK_CHECK_OFF(ip); + + /* Free up the pages in the subdatabase. */ + switch (sdbp->type) { + case DB_BTREE: + case DB_RECNO: + if ((ret = __bam_reclaim(sdbp, ip, txn, flags)) != 0) + goto err; + break; + case DB_HASH: + if ((ret = __ham_reclaim(sdbp, ip, txn, flags)) != 0) + goto err; + break; + case DB_QUEUE: + case DB_UNKNOWN: + default: + ret = __db_unknown_type( + sdbp->env, "__db_subdb_remove", sdbp->type); + goto err; + } + + /* + * Remove the entry from the main database and free the subdatabase + * metadata page. + */ + if ((ret = __db_master_open(sdbp, ip, txn, name, 0, 0, &mdbp)) != 0) + goto err; + + if ((ret = __db_master_update(mdbp, + sdbp, ip, txn, subdb, sdbp->type, MU_REMOVE, NULL, 0)) != 0) + goto err; + + DB_TEST_RECOVERY(sdbp, DB_TEST_POSTDESTROY, ret, name); + +DB_TEST_RECOVERY_LABEL +err: + /* Close the main and subdatabases. */ + if ((t_ret = __db_close(sdbp, txn, DB_NOSYNC)) != 0 && ret == 0) + ret = t_ret; + + if (mdbp != NULL && (t_ret = __db_close(mdbp, txn, + (LF_ISSET(DB_NOSYNC) || txn != NULL) ? DB_NOSYNC : 0)) != 0 && + ret == 0) + ret = t_ret; + + LOCK_CHECK_ON(ip); + return (ret); +} diff -r 000000000000 -r a1985f14b030 src/db/db_rename.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/db/db_rename.c Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,405 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 2001, 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + * $Id$ + */ + +#include "db_config.h" + +#include "db_int.h" +#include "dbinc/db_page.h" +#include "dbinc/db_am.h" +#include "dbinc/fop.h" +#include "dbinc/lock.h" +#include "dbinc/mp.h" +#include "dbinc/txn.h" + +static int __db_rename __P((DB *, DB_THREAD_INFO *, + DB_TXN *, const char *, const char *, const char *, u_int32_t)); +static int __db_subdb_rename __P((DB *, DB_THREAD_INFO *, + DB_TXN *, const char *, const char *, const char *, u_int32_t)); + +/* + * __env_dbrename_pp + * ENV->dbrename pre/post processing. + * + * PUBLIC: int __env_dbrename_pp __P((DB_ENV *, DB_TXN *, + * PUBLIC: const char *, const char *, const char *, u_int32_t)); + */ +int +__env_dbrename_pp(dbenv, txn, name, subdb, newname, flags) + DB_ENV *dbenv; + DB_TXN *txn; + const char *name, *subdb, *newname; + u_int32_t flags; +{ + DB *dbp; + DB_THREAD_INFO *ip; + ENV *env; + int handle_check, ret, t_ret, txn_local; + + env = dbenv->env; + dbp = NULL; + txn_local = 0; + handle_check = 0; + + ENV_ILLEGAL_BEFORE_OPEN(env, "DB_ENV->dbrename"); + + /* + * The actual argument checking is simple, do it inline, outside of + * the replication block. + */ + if ((ret = __db_fchk(env, "DB->rename", flags, + DB_AUTO_COMMIT | DB_NOSYNC)) != 0) + return (ret); + + ENV_ENTER(env, ip); + XA_NO_TXN(ip, ret); + if (ret != 0) + goto err; + + /* Check for replication block. */ + handle_check = IS_ENV_REPLICATED(env); + if (handle_check && (ret = __env_rep_enter(env, 1)) != 0) { + handle_check = 0; + goto err; + } + + /* + * Create local transaction as necessary, check for consistent + * transaction usage. + */ + if (IS_ENV_AUTO_COMMIT(env, txn, flags)) { + if ((ret = __db_txn_auto_init(env, ip, &txn)) != 0) + goto err; + txn_local = 1; + } else + if (txn != NULL && !TXN_ON(env) && + (!CDB_LOCKING(env) || !F_ISSET(txn, TXN_FAMILY))) { + ret = __db_not_txn_env(env); + goto err; + } + + LF_CLR(DB_AUTO_COMMIT); + + if ((ret = __db_create_internal(&dbp, env, 0)) != 0) + goto err; + + ret = __db_rename_int(dbp, ip, txn, name, subdb, newname, flags); + + if (txn_local) { + /* + * We created the DBP here and when we commit/abort, we'll + * release all the transactional locks, including the handle + * lock; mark the handle cleared explicitly. + */ + LOCK_INIT(dbp->handle_lock); + dbp->locker = NULL; + } else if (IS_REAL_TXN(txn)) { + /* + * We created this handle locally so we need to close it and + * clean it up. Unfortunately, it's holding transactional + * or CDS group locks that need to persist until the end of + * transaction. If we invalidate the locker (dbp->locker), + * then the close won't free these locks prematurely. + */ + dbp->locker = NULL; + } + +err: if (txn_local && (t_ret = + __db_txn_auto_resolve(env, txn, 0, ret)) != 0 && ret == 0) + ret = t_ret; + + /* + * We never opened this dbp for real, so don't include a transaction + * handle, and use NOSYNC to avoid calling into mpool. + * + * !!! + * Note we're reversing the order of operations: we started the txn and + * then opened the DB handle; we're resolving the txn and then closing + * closing the DB handle -- it's safer. + */ + if (dbp != NULL && + (t_ret = __db_close(dbp, NULL, DB_NOSYNC)) != 0 && ret == 0) + ret = t_ret; + + if (handle_check && (t_ret = __env_db_rep_exit(env)) != 0 && ret == 0) + ret = t_ret; + + ENV_LEAVE(env, ip); + return (ret); +} + +/* + * __db_rename_pp + * DB->rename pre/post processing. + * + * PUBLIC: int __db_rename_pp __P((DB *, + * PUBLIC: const char *, const char *, const char *, u_int32_t)); + */ +int +__db_rename_pp(dbp, name, subdb, newname, flags) + DB *dbp; + const char *name, *subdb, *newname; + u_int32_t flags; +{ + DB_THREAD_INFO *ip; + ENV *env; + int handle_check, ret, t_ret; + + env = dbp->env; + handle_check = 0; + + /* + * Validate arguments, continuing to destroy the handle on failure. + * + * Cannot use DB_ILLEGAL_AFTER_OPEN directly because it returns. + * + * !!! + * We have a serious problem if we're here with a handle used to open + * a database -- we'll destroy the handle, and the application won't + * ever be able to close the database. + */ + if (F_ISSET(dbp, DB_AM_OPEN_CALLED)) + return (__db_mi_open(env, "DB->rename", 1)); + + /* Validate arguments. */ + if ((ret = __db_fchk(env, "DB->rename", flags, DB_NOSYNC)) != 0) + return (ret); + + /* Check for consistent transaction usage. */ + if ((ret = __db_check_txn(dbp, NULL, DB_LOCK_INVALIDID, 0)) != 0) + return (ret); + + ENV_ENTER(env, ip); + + handle_check = IS_ENV_REPLICATED(env); + if (handle_check && (ret = __db_rep_enter(dbp, 1, 1, 0)) != 0) { + handle_check = 0; + goto err; + } + + /* Rename the file. */ + ret = __db_rename(dbp, ip, NULL, name, subdb, newname, flags); + + if (handle_check && (t_ret = __env_db_rep_exit(env)) != 0 && ret == 0) + ret = t_ret; +err: ENV_LEAVE(env, ip); + return (ret); +} + +/* + * __db_rename + * DB->rename method. + * + */ +static int +__db_rename(dbp, ip, txn, name, subdb, newname, flags) + DB *dbp; + DB_THREAD_INFO *ip; + DB_TXN *txn; + const char *name, *subdb, *newname; + u_int32_t flags; +{ + int ret, t_ret; + + ret = __db_rename_int(dbp, ip, txn, name, subdb, newname, flags); + + if ((t_ret = __db_close(dbp, txn, DB_NOSYNC)) != 0 && ret == 0) + ret = t_ret; + + return (ret); +} + +/* + * __db_rename_int + * Worker function for DB->rename method; the close of the dbp is + * left in the wrapper routine. + * + * PUBLIC: int __db_rename_int __P((DB *, DB_THREAD_INFO *, + * PUBLIC: DB_TXN *, const char *, const char *, const char *, u_int32_t)); + */ +int +__db_rename_int(dbp, ip, txn, name, subdb, newname, flags) + DB *dbp; + DB_THREAD_INFO *ip; + DB_TXN *txn; + const char *name, *subdb, *newname; + u_int32_t flags; +{ + ENV *env; + int ret; + char *old, *real_name; + + env = dbp->env; + real_name = NULL; + + DB_TEST_RECOVERY(dbp, DB_TEST_PREDESTROY, ret, name); + + if (name == NULL && subdb == NULL) { + __db_errx(env, DB_STR("0503", + "Rename on temporary files invalid")); + ret = EINVAL; + goto err; + } + + if (name == NULL) + MAKE_INMEM(dbp); + else if (subdb != NULL) { + ret = __db_subdb_rename(dbp, ip, + txn, name, subdb, newname, flags); + goto err; + } + + /* + * From here on down, this pertains to files or in-memory databases. + * + * Find the real name of the file. + */ + if (F_ISSET(dbp, DB_AM_INMEM)) { + old = (char *)subdb; + real_name = (char *)subdb; + } else { + if ((ret = __db_appname(env, DB_APP_DATA, + name, &dbp->dirname, &real_name)) != 0) + goto err; + old = (char *)name; + } + DB_ASSERT(env, old != NULL); + + if ((ret = __fop_remove_setup(dbp, txn, real_name, 0)) != 0) + goto err; + + if (dbp->db_am_rename != NULL && + (ret = dbp->db_am_rename(dbp, ip, txn, name, subdb, newname)) != 0) + goto err; + + /* + * The transactional case and non-transactional case are + * quite different. In the non-transactional case, we simply + * do the rename. In the transactional case, since we need + * the ability to back out and maintain locking, we have to + * create a temporary object as a placeholder. This is all + * taken care of in the fop layer. + */ + if (IS_REAL_TXN(txn)) { + if ((ret = __fop_dummy(dbp, txn, old, newname)) != 0) + goto err; + } else { + if ((ret = __fop_dbrename(dbp, old, newname)) != 0) + goto err; + } + + /* + * I am pretty sure that we haven't gotten a dbreg id, so calling + * dbreg_filelist_update is not necessary. + */ + DB_ASSERT(env, dbp->log_filename == NULL || + dbp->log_filename->id == DB_LOGFILEID_INVALID); + + DB_TEST_RECOVERY(dbp, DB_TEST_POSTDESTROY, ret, newname); + +DB_TEST_RECOVERY_LABEL +err: if (!F_ISSET(dbp, DB_AM_INMEM) && real_name != NULL) + __os_free(env, real_name); + + return (ret); +} + +/* + * __db_subdb_rename -- + * Rename a subdatabase. + */ +static int +__db_subdb_rename(dbp, ip, txn, name, subdb, newname, flags) + DB *dbp; + DB_THREAD_INFO *ip; + DB_TXN *txn; + const char *name, *subdb, *newname; + u_int32_t flags; +{ + DB *mdbp; + ENV *env; + PAGE *meta; + int ret, t_ret; + + mdbp = NULL; + meta = NULL; + env = dbp->env; + + /* + * We have not opened this dbp so it isn't marked as a subdb, + * but it ought to be. + */ + F_SET(dbp, DB_AM_SUBDB); + + /* + * Rename the entry in the main database. We need to first + * get the meta-data page number (via MU_OPEN) so that we can + * read the meta-data page and obtain a handle lock. Once we've + * done that, we can proceed to do the rename in the master. + */ + if ((ret = __db_master_open(dbp, ip, txn, name, 0, 0, &mdbp)) != 0) + goto err; + + if ((ret = __db_master_update(mdbp, dbp, ip, txn, subdb, dbp->type, + MU_OPEN, NULL, 0)) != 0) + goto err; + + if ((ret = __memp_fget(mdbp->mpf, &dbp->meta_pgno, + ip, txn, 0, &meta)) != 0) + goto err; + memcpy(dbp->fileid, ((DBMETA *)meta)->uid, DB_FILE_ID_LEN); + if ((ret = __fop_lock_handle(env, dbp, + (mdbp->cur_locker != NULL) ? mdbp->cur_locker : mdbp->locker, + DB_LOCK_WRITE, NULL, NOWAIT_FLAG(txn))) != 0) + goto err; + + ret = __memp_fput(mdbp->mpf, ip, meta, dbp->priority); + meta = NULL; + if (ret != 0) + goto err; + + if ((ret = __db_master_update(mdbp, dbp, ip, txn, + subdb, dbp->type, MU_RENAME, newname, 0)) != 0) + goto err; + + DB_TEST_RECOVERY(dbp, DB_TEST_POSTDESTROY, ret, name); + +DB_TEST_RECOVERY_LABEL +err: + if (meta != NULL && (t_ret = + __memp_fput(mdbp->mpf, ip, meta, dbp->priority)) != 0 && ret == 0) + ret = t_ret; + + if (mdbp != NULL && (t_ret = __db_close(mdbp, txn, + (LF_ISSET(DB_NOSYNC) || txn != NULL) ? DB_NOSYNC : 0)) != 0 && + ret == 0) + ret = t_ret; + + return (ret); +} diff -r 000000000000 -r a1985f14b030 src/db/db_ret.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/db/db_ret.c Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,259 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 1996, 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + * $Id$ + */ + +#include "db_config.h" + +#include "db_int.h" +#include "dbinc/db_page.h" +#include "dbinc/db_am.h" +#include "dbinc/heap.h" + +/* + * __db_ret -- + * Build return DBT. + * + * PUBLIC: int __db_ret __P((DBC *, + * PUBLIC: PAGE *, u_int32_t, DBT *, void **, u_int32_t *)); + */ +int +__db_ret(dbc, h, indx, dbt, memp, memsize) + DBC *dbc; + PAGE *h; + u_int32_t indx; + DBT *dbt; + void **memp; + u_int32_t *memsize; +{ + BKEYDATA *bk; + BOVERFLOW *bo; + DB *dbp; + HEAPHDR *hdr; + HOFFPAGE ho; + u_int32_t len; + u_int8_t *hk; + void *data; + + if (F_ISSET(dbt, DB_DBT_READONLY)) + return (0); + dbp = dbc->dbp; + + switch (TYPE(h)) { + case P_HASH_UNSORTED: + case P_HASH: + hk = P_ENTRY(dbp, h, indx); + if (HPAGE_PTYPE(hk) == H_OFFPAGE) { + memcpy(&ho, hk, sizeof(HOFFPAGE)); + return (__db_goff(dbc, dbt, + ho.tlen, ho.pgno, memp, memsize)); + } + len = LEN_HKEYDATA(dbp, h, dbp->pgsize, indx); + data = HKEYDATA_DATA(hk); + break; + case P_HEAP: + hdr = (HEAPHDR *)P_ENTRY(dbp, h, indx); + if (F_ISSET(hdr,(HEAP_RECSPLIT | HEAP_RECFIRST))) + return (__heapc_gsplit(dbc, dbt, memp, memsize)); + len = hdr->size; + data = (u_int8_t *)hdr + sizeof(HEAPHDR); + break; + case P_LBTREE: + case P_LDUP: + case P_LRECNO: + bk = GET_BKEYDATA(dbp, h, indx); + if (B_TYPE(bk->type) == B_OVERFLOW) { + bo = (BOVERFLOW *)bk; + return (__db_goff(dbc, dbt, + bo->tlen, bo->pgno, memp, memsize)); + } + len = bk->len; + data = bk->data; + break; + default: + return (__db_pgfmt(dbp->env, h->pgno)); + } + + return (__db_retcopy(dbp->env, dbt, data, len, memp, memsize)); +} + +/* + * __db_retcopy -- + * Copy the returned data into the user's DBT, handling special flags. + * + * PUBLIC: int __db_retcopy __P((ENV *, DBT *, + * PUBLIC: void *, u_int32_t, void **, u_int32_t *)); + */ +int +__db_retcopy(env, dbt, data, len, memp, memsize) + ENV *env; + DBT *dbt; + void *data; + u_int32_t len; + void **memp; + u_int32_t *memsize; +{ + int ret; + + if (F_ISSET(dbt, DB_DBT_READONLY)) + return (0); + ret = 0; + + /* If returning a partial record, reset the length. */ + if (F_ISSET(dbt, DB_DBT_PARTIAL)) { + data = (u_int8_t *)data + dbt->doff; + if (len > dbt->doff) { + len -= dbt->doff; + if (len > dbt->dlen) + len = dbt->dlen; + } else + len = 0; + } + + /* + * Allocate memory to be owned by the application: DB_DBT_MALLOC, + * DB_DBT_REALLOC. + * + * !!! + * We always allocate memory, even if we're copying out 0 bytes. This + * guarantees consistency, i.e., the application can always free memory + * without concern as to how many bytes of the record were requested. + * + * Use the memory specified by the application: DB_DBT_USERMEM. + * + * !!! + * If the length we're going to copy is 0, the application-supplied + * memory pointer is allowed to be NULL. + */ + if (F_ISSET(dbt, DB_DBT_USERCOPY)) { + dbt->size = len; + return (len == 0 ? 0 : env->dbt_usercopy(dbt, 0, data, + len, DB_USERCOPY_SETDATA)); + + } else if (F_ISSET(dbt, DB_DBT_MALLOC)) + ret = __os_umalloc(env, len, &dbt->data); + else if (F_ISSET(dbt, DB_DBT_REALLOC)) { + if (dbt->data == NULL || dbt->size == 0 || dbt->size < len) + ret = __os_urealloc(env, len, &dbt->data); + } else if (F_ISSET(dbt, DB_DBT_USERMEM)) { + if (len != 0 && (dbt->data == NULL || dbt->ulen < len)) + ret = DB_BUFFER_SMALL; + } else if (memp == NULL || memsize == NULL) + ret = EINVAL; + else { + if (len != 0 && (*memsize == 0 || *memsize < len)) { + if ((ret = __os_realloc(env, len, memp)) == 0) + *memsize = len; + else + *memsize = 0; + } + if (ret == 0) + dbt->data = *memp; + } + + if (ret == 0 && len != 0) + memcpy(dbt->data, data, len); + + /* + * Return the length of the returned record in the DBT size field. + * This satisfies the requirement that if we're using user memory + * and insufficient memory was provided, return the amount necessary + * in the size field. + */ + dbt->size = len; + + return (ret); +} + +/* + * __db_dbt_clone -- + * Clone a DBT from another DBT. + * The input dest DBT must be a zero initialized DBT that will be populated. + * The function does not allocate a dest DBT to allow for cloning into stack + * or locally allocated variables. It is the callers responsibility to free + * the memory allocated in dest->data. + * + * PUBLIC: int __db_dbt_clone __P((ENV *, DBT *, const DBT *)); + */ +int +__db_dbt_clone(env, dest, src) + ENV *env; + DBT *dest; + const DBT *src; +{ + u_int32_t err_flags; + int ret; + + DB_ASSERT(env, dest->data == NULL); + + ret = 0; + + /* The function does not support the following DBT flags. */ + err_flags = DB_DBT_MALLOC | DB_DBT_REALLOC | + DB_DBT_MULTIPLE | DB_DBT_PARTIAL; + if (F_ISSET(src, err_flags)) { + __db_errx(env, DB_STR("0750", + "Unsupported flags when cloning the DBT.")); + return (EINVAL); + } + + if ((ret = __os_malloc(env, src->size, &dest->data)) != 0) + return (ret); + + memcpy(dest->data, src->data, src->size); + dest->ulen = src->size; + dest->size = src->size; + dest->flags = DB_DBT_USERMEM; + + return (ret); +} + +/* + * __db_dbt_clone_free -- + * Free a DBT cloned by __db_dbt_clone + * + * PUBLIC: int __db_dbt_clone_free __P((ENV *, DBT *)); + */ +int +__db_dbt_clone_free(env, dbt) + ENV *env; + DBT *dbt; +{ + /* Currently only DB_DBT_USERMEM is supported. */ + if (dbt->flags != DB_DBT_USERMEM) { + __db_errx(env, DB_STR("0751", + "Unsupported flags when freeing the cloned DBT.")); + return (EINVAL); + } + + if (dbt->data != NULL) + __os_free(env, dbt->data); + dbt->size = dbt->ulen = 0; + + return (0); +} diff -r 000000000000 -r a1985f14b030 src/db/db_setid.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/db/db_setid.c Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,235 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 2000, 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + * $Id$ + */ + +#include "db_config.h" + +#include "db_int.h" +#include "dbinc/db_page.h" +#include "dbinc/db_swap.h" +#include "dbinc/db_am.h" +#include "dbinc/mp.h" + +/* + * __env_fileid_reset_pp -- + * ENV->fileid_reset pre/post processing. + * + * PUBLIC: int __env_fileid_reset_pp __P((DB_ENV *, const char *, u_int32_t)); + */ +int +__env_fileid_reset_pp(dbenv, name, flags) + DB_ENV *dbenv; + const char *name; + u_int32_t flags; +{ + DB_THREAD_INFO *ip; + ENV *env; + int ret; + + env = dbenv->env; + + ENV_ILLEGAL_BEFORE_OPEN(env, "DB_ENV->fileid_reset"); + + /* + * !!! + * The actual argument checking is simple, do it inline, outside of + * the replication block. + */ + if (flags != 0 && flags != DB_ENCRYPT) + return (__db_ferr(env, "DB_ENV->fileid_reset", 0)); + + ENV_ENTER(env, ip); + REPLICATION_WRAP(env, + (__env_fileid_reset(env, ip, name, LF_ISSET(DB_ENCRYPT) ? 1 : 0)), + 1, ret); + ENV_LEAVE(env, ip); + return (ret); +} + +/* + * __env_fileid_reset -- + * Reset the file IDs for every database in the file. + * PUBLIC: int __env_fileid_reset + * PUBLIC: __P((ENV *, DB_THREAD_INFO *, const char *, int)); + */ +int +__env_fileid_reset(env, ip, name, encrypted) + ENV *env; + DB_THREAD_INFO *ip; + const char *name; + int encrypted; +{ + DB *dbp; + DBC *dbcp; + DBMETA *meta; + DBT key, data; + DB_FH *fhp; + DB_MPOOLFILE *mpf; + DB_PGINFO cookie; + db_pgno_t pgno; + int subdb, t_ret, ret; + size_t n; + char *real_name; + u_int8_t fileid[DB_FILE_ID_LEN], mbuf[DBMETASIZE]; + void *pagep; + + dbp = NULL; + dbcp = NULL; + fhp = NULL; + real_name = NULL; + + /* Get the real backing file name. */ + if ((ret = __db_appname(env, + DB_APP_DATA, name, NULL, &real_name)) != 0) + return (ret); + + /* Get a new file ID. */ + if ((ret = __os_fileid(env, real_name, 1, fileid)) != 0) + goto err; + + /* + * The user may have physically copied a file currently open in the + * cache, which means if we open this file through the cache before + * updating the file ID on page 0, we might connect to the file from + * which the copy was made. + */ + if ((ret = __os_open(env, real_name, 0, 0, 0, &fhp)) != 0) { + __db_err(env, ret, "%s", real_name); + goto err; + } + if ((ret = __os_read(env, fhp, mbuf, sizeof(mbuf), &n)) != 0) + goto err; + + if (n != sizeof(mbuf)) { + ret = EINVAL; + __db_errx(env, DB_STR_A("0675", + "__env_fileid_reset: %s: unexpected file type or format", + "%s"), real_name); + goto err; + } + + /* + * Create the DB object. + */ + if ((ret = __db_create_internal(&dbp, env, 0)) != 0) + goto err; + + /* If configured with a password, the databases are encrypted. */ + if (encrypted && (ret = __db_set_flags(dbp, DB_ENCRYPT)) != 0) + goto err; + + if ((ret = __db_meta_setup(env, + dbp, real_name, (DBMETA *)mbuf, 0, DB_CHK_META)) != 0) + goto err; + + meta = (DBMETA *)mbuf; + if (FLD_ISSET(meta->metaflags, + DBMETA_PART_RANGE | DBMETA_PART_CALLBACK) && (ret = + __part_fileid_reset(env, ip, name, meta->nparts, encrypted)) != 0) + goto err; + + subdb = meta->type == P_BTREEMETA && F_ISSET(meta, BTM_SUBDB); + + memcpy(meta->uid, fileid, DB_FILE_ID_LEN); + cookie.db_pagesize = sizeof(mbuf); + cookie.flags = dbp->flags; + cookie.type = dbp->type; + key.data = &cookie; + + if ((ret = __db_pgout(env->dbenv, 0, mbuf, &key)) != 0) + goto err; + if ((ret = __os_seek(env, fhp, 0, 0, 0)) != 0) + goto err; + if ((ret = __os_write(env, fhp, mbuf, sizeof(mbuf), &n)) != 0) + goto err; + if ((ret = __os_fsync(env, fhp)) != 0) + goto err; + + /* + * Page 0 of the file has an updated file ID, and we can open it in + * the cache without connecting to a different, existing file. Open + * the file in the cache, and update the file IDs for subdatabases. + */ + + /* + * If the database file doesn't support subdatabases, we only have + * to update a single metadata page. Otherwise, we have to open a + * cursor and step through the master database, and update all of + * the subdatabases' metadata pages. + */ + if (!subdb) + goto err; + + /* + * Open the DB file. + * + * !!! + * Note DB_RDWRMASTER flag, we need to open the master database file + * for writing in this case. + */ + if ((ret = __db_open(dbp, ip, NULL, + name, NULL, DB_UNKNOWN, DB_RDWRMASTER, 0, PGNO_BASE_MD)) != 0) + goto err; + + mpf = dbp->mpf; + memset(&key, 0, sizeof(key)); + memset(&data, 0, sizeof(data)); + if ((ret = __db_cursor(dbp, ip, NULL, &dbcp, 0)) != 0) + goto err; + while ((ret = __dbc_get(dbcp, &key, &data, DB_NEXT)) == 0) { + /* + * XXX + * We're handling actual data, not on-page meta-data, so it + * hasn't been converted to/from opposite endian architectures. + * Do it explicitly, now. + */ + memcpy(&pgno, data.data, sizeof(db_pgno_t)); + DB_NTOHL_SWAP(env, &pgno); + if ((ret = __memp_fget(mpf, &pgno, ip, NULL, + DB_MPOOL_DIRTY, &pagep)) != 0) + goto err; + memcpy(((DBMETA *)pagep)->uid, fileid, DB_FILE_ID_LEN); + if ((ret = __memp_fput(mpf, ip, pagep, dbcp->priority)) != 0) + goto err; + } + if (ret == DB_NOTFOUND) + ret = 0; + +err: if (dbcp != NULL && (t_ret = __dbc_close(dbcp)) != 0 && ret == 0) + ret = t_ret; + if (dbp != NULL && (t_ret = __db_close(dbp, NULL, 0)) != 0 && ret == 0) + ret = t_ret; + if (fhp != NULL && + (t_ret = __os_closehandle(env, fhp)) != 0 && ret == 0) + ret = t_ret; + if (real_name != NULL) + __os_free(env, real_name); + + return (ret); +} diff -r 000000000000 -r a1985f14b030 src/db/db_setlsn.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/db/db_setlsn.c Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,159 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 2000, 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + * $Id$ + */ + +#include "db_config.h" + +#include "db_int.h" +#include "dbinc/db_page.h" +#include "dbinc/db_am.h" +#include "dbinc/mp.h" +#include "dbinc/partition.h" +#include "dbinc/qam.h" + +static int __env_lsn_reset __P((ENV *, DB_THREAD_INFO *, const char *, int)); + +/* + * __env_lsn_reset_pp -- + * ENV->lsn_reset pre/post processing. + * + * PUBLIC: int __env_lsn_reset_pp __P((DB_ENV *, const char *, u_int32_t)); + */ +int +__env_lsn_reset_pp(dbenv, name, flags) + DB_ENV *dbenv; + const char *name; + u_int32_t flags; +{ + DB_THREAD_INFO *ip; + ENV *env; + int ret; + + env = dbenv->env; + + ENV_ILLEGAL_BEFORE_OPEN(env, "DB_ENV->lsn_reset"); + + /* + * !!! + * The actual argument checking is simple, do it inline, outside of + * the replication block. + */ + if (flags != 0 && flags != DB_ENCRYPT) + return (__db_ferr(env, "DB_ENV->lsn_reset", 0)); + + ENV_ENTER(env, ip); + REPLICATION_WRAP(env, + (__env_lsn_reset(env, ip, name, LF_ISSET(DB_ENCRYPT) ? 1 : 0)), + 1, ret); + ENV_LEAVE(env, ip); + return (ret); +} + +/* + * __env_lsn_reset -- + * Reset the LSNs for every page in the file. + */ +static int +__env_lsn_reset(env, ip, name, encrypted) + ENV *env; + DB_THREAD_INFO *ip; + const char *name; + int encrypted; +{ + DB *dbp; + int t_ret, ret; + + /* Create the DB object. */ + if ((ret = __db_create_internal(&dbp, env, 0)) != 0) + return (ret); + + /* If configured with a password, the databases are encrypted. */ + if (encrypted && (ret = __db_set_flags(dbp, DB_ENCRYPT)) != 0) + goto err; + + /* + * Open the DB file. + * + * !!! + * Note DB_RDWRMASTER flag, we need to open the master database file + * for writing in this case. + */ + if ((ret = __db_open(dbp, ip, NULL, + name, NULL, DB_UNKNOWN, DB_RDWRMASTER, 0, PGNO_BASE_MD)) != 0) { + __db_err(env, ret, "%s", name); + goto err; + } + + ret = __db_lsn_reset(dbp->mpf, ip); +#ifdef HAVE_PARTITION + if (ret == 0 && DB_IS_PARTITIONED(dbp)) + ret = __part_lsn_reset(dbp, ip); + else +#endif + if (ret == 0 && dbp->type == DB_QUEUE) +#ifdef HAVE_QUEUE + ret = __qam_lsn_reset(dbp, ip); +#else + ret = __db_no_queue_am(env); +#endif + +err: if ((t_ret = __db_close(dbp, NULL, 0)) != 0 && ret == 0) + ret = t_ret; + return (ret); +} + +/* + * __db_lsn_reset -- reset the lsn for a db mpool handle. + * PUBLIC: int __db_lsn_reset __P((DB_MPOOLFILE *, DB_THREAD_INFO *)); + */ +int +__db_lsn_reset(mpf, ip) + DB_MPOOLFILE *mpf; + DB_THREAD_INFO *ip; +{ + PAGE *pagep; + db_pgno_t pgno; + int ret; + + /* Reset the LSN on every page of the database file. */ + for (pgno = 0; + (ret = __memp_fget(mpf, + &pgno, ip, NULL, DB_MPOOL_DIRTY, &pagep)) == 0; + ++pgno) { + LSN_NOT_LOGGED(pagep->lsn); + if ((ret = __memp_fput(mpf, + ip, pagep, DB_PRIORITY_UNCHANGED)) != 0) + break; + } + + if (ret == DB_PAGE_NOTFOUND) + ret = 0; + + return (ret); +} diff -r 000000000000 -r a1985f14b030 src/db/db_sort_multiple.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/db/db_sort_multiple.c Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,349 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 1996, 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +#include "db_config.h" + +#include "db_int.h" +#include "dbinc/db_page.h" +#include "dbinc/btree.h" + +static int __db_quicksort __P((DB *, DBT *, DBT *, u_int32_t *, u_int32_t *, + u_int32_t *, u_int32_t *, u_int32_t)); + +/* + * __db_compare_both -- + * Use the comparison functions from db to compare akey and bkey, and if + * DB_DUPSORT adata and bdata. + * + * PUBLIC: int __db_compare_both __P((DB *, const DBT *, const DBT *, + * PUBLIC: const DBT *, const DBT *)); + */ +int +__db_compare_both(db, akey, adata, bkey, bdata) + DB *db; + const DBT *akey; + const DBT *adata; + const DBT *bkey; + const DBT *bdata; +{ + BTREE *t; + int cmp; + + t = (BTREE *)db->bt_internal; + + cmp = t->bt_compare(db, akey, bkey); + if (cmp != 0) return cmp; + if (!F_ISSET(db, DB_AM_DUPSORT)) + return (0); + + if (adata == 0) return bdata == 0 ? 0 : -1; + if (bdata == 0) return 1; + +#ifdef HAVE_COMPRESSION + if (DB_IS_COMPRESSED(db)) + return t->compress_dup_compare(db, adata, bdata); +#endif + return db->dup_compare(db, adata, bdata); +} + +#define DB_SORT_SWAP(a, ad, b, bd) \ +do { \ + tmp = (a)[0]; (a)[0] = (b)[0]; (b)[0] = tmp; \ + tmp = (a)[-1]; (a)[-1] = (b)[-1]; (b)[-1] = tmp; \ + if (data != NULL) { \ + tmp = (ad)[0]; (ad)[0] = (bd)[0]; (bd)[0] = tmp; \ + tmp = (ad)[-1]; (ad)[-1] = (bd)[-1]; (bd)[-1] = tmp; \ + } \ +} while (0) + +#define DB_SORT_LOAD_DBT(a, ad, aptr, adptr) \ +do { \ + (a).data = (u_int8_t*)key->data + (aptr)[0]; \ + (a).size = (aptr)[-1]; \ + if (data != NULL) { \ + (ad).data = (u_int8_t*)data->data + (adptr)[0]; \ + (ad).size = (adptr)[-1]; \ + } \ +} while (0) + +#define DB_SORT_COMPARE(a, ad, b, bd) (data != NULL ? \ + __db_compare_both(db, &(a), &(ad), &(b), &(bd)) : \ + __db_compare_both(db, &(a), 0, &(b), 0)) + +#define DB_SORT_STACKSIZE 32 + +/* + * __db_quicksort -- + * The quicksort implementation for __db_sort_multiple() and + * __db_sort_multiple_key(). + */ +static int +__db_quicksort(db, key, data, kstart, kend, dstart, dend, size) + DB *db; + DBT *key, *data; + u_int32_t *kstart, *kend, *dstart, *dend; + u_int32_t size; +{ + int ret, cmp; + u_int32_t tmp, len; + u_int32_t *kptr, *dptr, *kl, *dl, *kr, *dr; + DBT a, ad, b, bd, m, md; + ENV *env; + + struct DB_SORT_quicksort_stack { + u_int32_t *kstart; + u_int32_t *kend; + u_int32_t *dstart; + u_int32_t *dend; + } stackbuf[DB_SORT_STACKSIZE], *stack; + u_int32_t soff, slen; + + ret = 0; + env = db->env; + + memset(&a, 0, sizeof(DBT)); + memset(&ad, 0, sizeof(DBT)); + memset(&b, 0, sizeof(DBT)); + memset(&bd, 0, sizeof(DBT)); + memset(&m, 0, sizeof(DBT)); + memset(&md, 0, sizeof(DBT)); + + /* NB end is smaller than start */ + + stack = stackbuf; + soff = 0; + slen = DB_SORT_STACKSIZE; + + start: + if (kend >= kstart) goto pop; + + /* If there's only one value, it's already sorted */ + len = (u_int32_t)(kstart - kend) / size; + if (len == 1) goto pop; + + DB_SORT_LOAD_DBT(a, ad, kstart, dstart); + DB_SORT_LOAD_DBT(b, bd, kend + size, dend + size); + + if (len == 2) { + /* Special case the sorting of two value sequences */ + if (DB_SORT_COMPARE(a, ad, b, bd) > 0) { + DB_SORT_SWAP(kstart, dstart, kend + size, + dend + size); + } + goto pop; + } + + kptr = kstart - (len / 2) * size; + dptr = dstart - (len / 2) * size; + DB_SORT_LOAD_DBT(m, md, kptr, dptr); + + /* Find the median of three */ + if (DB_SORT_COMPARE(a, ad, b, bd) < 0) { + if (DB_SORT_COMPARE(m, md, a, ad) < 0) { + /* m < a < b */ + if (len == 3) { + DB_SORT_SWAP(kstart, dstart, kptr, dptr); + goto pop; + } + DB_SORT_SWAP(kstart, dstart, kend + size, dend + size); + } else if (DB_SORT_COMPARE(m, md, b, bd) < 0) { + /* a <= m < b */ + if (len == 3) { + goto pop; + } + DB_SORT_SWAP(kptr, dptr, kend + size, dend + size); + } else { + /* a < b <= m */ + if (len == 3) { + DB_SORT_SWAP(kptr, dptr, kend + size, + dend + size); + goto pop; + } + /* Do nothing */ + } + } else { + if (DB_SORT_COMPARE(a, ad, m, md) < 0) { + /* b <= a < m */ + DB_SORT_SWAP(kstart, dstart, kend + size, + dend + size); + if (len == 3) { + DB_SORT_SWAP(kptr, dptr, kend + size, + dend + size); + goto pop; + } + } else if (DB_SORT_COMPARE(b, bd, m, md) < 0) { + /* b < m <= a */ + if (len == 3) { + DB_SORT_SWAP(kstart, dstart, kend + size, + dend + size); + goto pop; + } + DB_SORT_SWAP(kptr, dptr, kend + size, dend + size); + } else { + /* m <= b <= a */ + if (len == 3) { + DB_SORT_SWAP(kstart, dstart, kptr, dptr); + DB_SORT_SWAP(kptr, dptr, kend + size, + dend + size); + goto pop; + } + /* Do nothing */ + } + } + + /* partition */ + DB_SORT_LOAD_DBT(b, bd, kend + size, dend + size); + kl = kstart; + dl = dstart; + kr = kend + size; + dr = dend + size; + kptr = kstart; + dptr = dstart; + while (kptr >= kr) { + DB_SORT_LOAD_DBT(a, ad, kptr, dptr); + cmp = DB_SORT_COMPARE(a, ad, b, bd); + if (cmp < 0) { + DB_SORT_SWAP(kl, dl, kptr, dptr); + kl -= size; + dl -= size; + kptr -= size; + dptr -= size; + } else if (cmp > 0) { + DB_SORT_SWAP(kr, dr, kptr, dptr); + kr += size; + dr += size; + } else { + kptr -= size; + dptr -= size; + } + } + + if (soff == slen) { + /* Grow the stack */ + slen = slen * 2; + if (stack == stackbuf) { + ret = __os_malloc(env, slen * + sizeof(struct DB_SORT_quicksort_stack), &stack); + if (ret != 0) goto error; + memcpy(stack, stackbuf, soff * + sizeof(struct DB_SORT_quicksort_stack)); + } else { + ret = __os_realloc(env, slen * + sizeof(struct DB_SORT_quicksort_stack), &stack); + if (ret != 0) goto error; + } + } + + /* divide and conquer */ + stack[soff].kstart = kr - size; + stack[soff].kend = kend; + stack[soff].dstart = dr - size; + stack[soff].dend = dend; + ++soff; + + kend = kl; + dend = dl; + + goto start; + + pop: + if (soff != 0) { + --soff; + kstart = stack[soff].kstart; + kend = stack[soff].kend; + dstart = stack[soff].dstart; + dend = stack[soff].dend; + goto start; + } + + error: + if (stack != stackbuf) + __os_free(env, stack); + + return (ret); +} + +#undef DB_SORT_SWAP +#undef DB_SORT_LOAD_DBT + +/* + * __db_sort_multiple -- + * If flags == DB_MULTIPLE_KEY, sorts a DB_MULTIPLE_KEY format DBT using + * the BTree comparison function and duplicate comparison function. + * + * If flags == DB_MULTIPLE, sorts one or two DB_MULTIPLE format DBTs using + * the BTree comparison function and duplicate comparison function. Will + * assume key and data specifies pairs of key/data to sort together. If + * data is NULL, will just sort key according to the btree comparison + * function. + * + * Uses an in-place quicksort algorithm, with median of three for the pivot + * point. + * + * PUBLIC: int __db_sort_multiple __P((DB *, DBT *, DBT *, u_int32_t)); + */ +int +__db_sort_multiple(db, key, data, flags) + DB *db; + DBT *key, *data; + u_int32_t flags; +{ + u_int32_t *kstart, *kend, *dstart, *dend; + + /* TODO: sanity checks on the DBTs */ + /* DB_ILLEGAL_METHOD(db, DB_OK_BTREE); */ + + kstart = (u_int32_t*)((u_int8_t *)key->data + key->ulen) - 1; + + switch (flags) { + case DB_MULTIPLE: + if (data != NULL) + dstart = (u_int32_t*)((u_int8_t *)data->data + + data->ulen) - 1; + else + dstart = kstart; + + /* Find the end */ + for (kend = kstart, dend = dstart; + *kend != (u_int32_t)-1 && *dend != (u_int32_t)-1; + kend -= 2, dend -= 2) + ; + + return (__db_quicksort(db, key, data, kstart, kend, dstart, + dend, 2)); + case DB_MULTIPLE_KEY: + /* Find the end */ + for (kend = kstart; *kend != (u_int32_t)-1; kend -= 4) + ; + + return (__db_quicksort(db, key, key, kstart, kend, kstart - 2, + kend - 2, 4)); + default: + return (__db_ferr(db->env, "DB->sort_multiple", 0)); + } +} diff -r 000000000000 -r a1985f14b030 src/db/db_stati.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/db/db_stati.c Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,524 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 1996, 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + * $Id$ + */ + +#include "db_config.h" + +#include "db_int.h" +#include "dbinc/db_page.h" +#include "dbinc/btree.h" +#include "dbinc/hash.h" +#include "dbinc/heap.h" +#include "dbinc/qam.h" +#include "dbinc/lock.h" +#include "dbinc/mp.h" +#include "dbinc/partition.h" + +#ifdef HAVE_STATISTICS +static int __db_print_all __P((DB *, u_int32_t)); +static int __db_print_citem __P((DBC *)); +static int __db_print_cursor __P((DB *)); +static int __db_print_stats __P((DB *, DB_THREAD_INFO *, u_int32_t)); +static int __db_stat __P((DB *, DB_THREAD_INFO *, DB_TXN *, void *, u_int32_t)); +static int __db_stat_arg __P((DB *, u_int32_t)); + +/* + * __db_stat_pp -- + * DB->stat pre/post processing. + * + * PUBLIC: int __db_stat_pp __P((DB *, DB_TXN *, void *, u_int32_t)); + */ +int +__db_stat_pp(dbp, txn, spp, flags) + DB *dbp; + DB_TXN *txn; + void *spp; + u_int32_t flags; +{ + DB_THREAD_INFO *ip; + ENV *env; + int handle_check, ret, t_ret; + + env = dbp->env; + + DB_ILLEGAL_BEFORE_OPEN(dbp, "DB->stat"); + + if ((ret = __db_stat_arg(dbp, flags)) != 0) + return (ret); + + ENV_ENTER(env, ip); + + /* Check for replication block. */ + handle_check = IS_ENV_REPLICATED(env); + if (handle_check && (ret = __db_rep_enter(dbp, 1, 0, + IS_REAL_TXN(txn))) != 0) { + handle_check = 0; + goto err; + } + + ret = __db_stat(dbp, ip, txn, spp, flags); + + /* Release replication block. */ + if (handle_check && (t_ret = __env_db_rep_exit(env)) != 0 && ret == 0) + ret = t_ret; + +err: ENV_LEAVE(env, ip); + return (ret); +} + +/* + * __db_stat -- + * DB->stat. + * + */ +static int +__db_stat(dbp, ip, txn, spp, flags) + DB *dbp; + DB_THREAD_INFO *ip; + DB_TXN *txn; + void *spp; + u_int32_t flags; +{ + DBC *dbc; + ENV *env; + int ret, t_ret; + + env = dbp->env; + + /* Acquire a cursor. */ + if ((ret = __db_cursor(dbp, ip, txn, + &dbc, LF_ISSET(DB_READ_COMMITTED | DB_READ_UNCOMMITTED))) != 0) + return (ret); + + DEBUG_LWRITE(dbc, NULL, "DB->stat", NULL, NULL, flags); + LF_CLR(DB_READ_COMMITTED | DB_READ_UNCOMMITTED); +#ifdef HAVE_PARTITION + if (DB_IS_PARTITIONED(dbp)) + ret = __partition_stat(dbc, spp, flags); + else +#endif + switch (dbp->type) { + case DB_BTREE: + case DB_RECNO: + ret = __bam_stat(dbc, spp, flags); + break; + case DB_HASH: + ret = __ham_stat(dbc, spp, flags); + break; + case DB_HEAP: + ret = __heap_stat(dbc, spp, flags); + break; + case DB_QUEUE: + ret = __qam_stat(dbc, spp, flags); + break; + case DB_UNKNOWN: + default: + ret = (__db_unknown_type(env, "DB->stat", dbp->type)); + break; + } + + if ((t_ret = __dbc_close(dbc)) != 0 && ret == 0) + ret = t_ret; + + return (ret); +} + +/* + * __db_stat_arg -- + * Check DB->stat arguments. + */ +static int +__db_stat_arg(dbp, flags) + DB *dbp; + u_int32_t flags; +{ + ENV *env; + + env = dbp->env; + + /* Check for invalid function flags. */ + LF_CLR(DB_READ_COMMITTED | DB_READ_UNCOMMITTED); + switch (flags) { + case 0: + case DB_FAST_STAT: + break; + default: + return (__db_ferr(env, "DB->stat", 0)); + } + + return (0); +} + +/* + * __db_stat_print_pp -- + * DB->stat_print pre/post processing. + * + * PUBLIC: int __db_stat_print_pp __P((DB *, u_int32_t)); + */ +int +__db_stat_print_pp(dbp, flags) + DB *dbp; + u_int32_t flags; +{ + DB_THREAD_INFO *ip; + ENV *env; + int handle_check, ret, t_ret; + + env = dbp->env; + + DB_ILLEGAL_BEFORE_OPEN(dbp, "DB->stat_print"); + + /* + * !!! + * The actual argument checking is simple, do it inline. + */ + if ((ret = __db_fchk(env, + "DB->stat_print", flags, DB_FAST_STAT | DB_STAT_ALL)) != 0) + return (ret); + + ENV_ENTER(env, ip); + + /* Check for replication block. */ + handle_check = IS_ENV_REPLICATED(env); + if (handle_check && (ret = __db_rep_enter(dbp, 1, 0, 0)) != 0) { + handle_check = 0; + goto err; + } + + ret = __db_stat_print(dbp, ip, flags); + + /* Release replication block. */ + if (handle_check && (t_ret = __env_db_rep_exit(env)) != 0 && ret == 0) + ret = t_ret; + +err: ENV_LEAVE(env, ip); + return (ret); +} + +/* + * __db_stat_print -- + * DB->stat_print. + * + * PUBLIC: int __db_stat_print __P((DB *, DB_THREAD_INFO *, u_int32_t)); + */ +int +__db_stat_print(dbp, ip, flags) + DB *dbp; + DB_THREAD_INFO *ip; + u_int32_t flags; +{ + time_t now; + int ret; + char time_buf[CTIME_BUFLEN]; + + (void)time(&now); + __db_msg(dbp->env, "%.24s\tLocal time", __os_ctime(&now, time_buf)); + + if (LF_ISSET(DB_STAT_ALL) && (ret = __db_print_all(dbp, flags)) != 0) + return (ret); + + if ((ret = __db_print_stats(dbp, ip, flags)) != 0) + return (ret); + + return (0); +} + +/* + * __db_print_stats -- + * Display default DB handle statistics. + */ +static int +__db_print_stats(dbp, ip, flags) + DB *dbp; + DB_THREAD_INFO *ip; + u_int32_t flags; +{ + DBC *dbc; + ENV *env; + int ret, t_ret; + + env = dbp->env; + + /* Acquire a cursor. */ + if ((ret = __db_cursor(dbp, ip, NULL, &dbc, 0)) != 0) + return (ret); + + DEBUG_LWRITE(dbc, NULL, "DB->stat_print", NULL, NULL, 0); + + switch (dbp->type) { + case DB_BTREE: + case DB_RECNO: + ret = __bam_stat_print(dbc, flags); + break; + case DB_HASH: + ret = __ham_stat_print(dbc, flags); + break; + case DB_HEAP: + ret = __heap_stat_print(dbc, flags); + break; + case DB_QUEUE: + ret = __qam_stat_print(dbc, flags); + break; + case DB_UNKNOWN: + default: + ret = (__db_unknown_type(env, "DB->stat_print", dbp->type)); + break; + } + + if ((t_ret = __dbc_close(dbc)) != 0 && ret == 0) + ret = t_ret; + + return (ret); +} + +/* + * __db_print_all -- + * Display debugging DB handle statistics. + */ +static int +__db_print_all(dbp, flags) + DB *dbp; + u_int32_t flags; +{ + static const FN fn[] = { + { DB_AM_CHKSUM, "DB_AM_CHKSUM" }, + { DB_AM_COMPENSATE, "DB_AM_COMPENSATE" }, + { DB_AM_CREATED, "DB_AM_CREATED" }, + { DB_AM_CREATED_MSTR, "DB_AM_CREATED_MSTR" }, + { DB_AM_DBM_ERROR, "DB_AM_DBM_ERROR" }, + { DB_AM_DELIMITER, "DB_AM_DELIMITER" }, + { DB_AM_DISCARD, "DB_AM_DISCARD" }, + { DB_AM_DUP, "DB_AM_DUP" }, + { DB_AM_DUPSORT, "DB_AM_DUPSORT" }, + { DB_AM_ENCRYPT, "DB_AM_ENCRYPT" }, + { DB_AM_FIXEDLEN, "DB_AM_FIXEDLEN" }, + { DB_AM_INMEM, "DB_AM_INMEM" }, + { DB_AM_IN_RENAME, "DB_AM_IN_RENAME" }, + { DB_AM_NOT_DURABLE, "DB_AM_NOT_DURABLE" }, + { DB_AM_OPEN_CALLED, "DB_AM_OPEN_CALLED" }, + { DB_AM_PAD, "DB_AM_PAD" }, + { DB_AM_PGDEF, "DB_AM_PGDEF" }, + { DB_AM_RDONLY, "DB_AM_RDONLY" }, + { DB_AM_READ_UNCOMMITTED, "DB_AM_READ_UNCOMMITTED" }, + { DB_AM_RECNUM, "DB_AM_RECNUM" }, + { DB_AM_RECOVER, "DB_AM_RECOVER" }, + { DB_AM_RENUMBER, "DB_AM_RENUMBER" }, + { DB_AM_REVSPLITOFF, "DB_AM_REVSPLITOFF" }, + { DB_AM_SECONDARY, "DB_AM_SECONDARY" }, + { DB_AM_SNAPSHOT, "DB_AM_SNAPSHOT" }, + { DB_AM_SUBDB, "DB_AM_SUBDB" }, + { DB_AM_SWAP, "DB_AM_SWAP" }, + { DB_AM_TXN, "DB_AM_TXN" }, + { DB_AM_VERIFYING, "DB_AM_VERIFYING" }, + { 0, NULL } + }; + ENV *env; + char time_buf[CTIME_BUFLEN]; + + env = dbp->env; + + __db_msg(env, "%s", DB_GLOBAL(db_line)); + __db_msg(env, "DB handle information:"); + STAT_ULONG("Page size", dbp->pgsize); + STAT_ISSET("Append recno", dbp->db_append_recno); + STAT_ISSET("Feedback", dbp->db_feedback); + STAT_ISSET("Dup compare", dbp->dup_compare); + STAT_ISSET("App private", dbp->app_private); + STAT_ISSET("DbEnv", dbp->env); + STAT_STRING("Type", __db_dbtype_to_string(dbp->type)); + + __mutex_print_debug_single(env, "Thread mutex", dbp->mutex, flags); + + STAT_STRING("File", dbp->fname); + STAT_STRING("Database", dbp->dname); + STAT_HEX("Open flags", dbp->open_flags); + + __db_print_fileid(env, dbp->fileid, "\tFile ID"); + + STAT_ULONG("Cursor adjust ID", dbp->adj_fileid); + STAT_ULONG("Meta pgno", dbp->meta_pgno); + if (dbp->locker != NULL) + STAT_ULONG("Locker ID", dbp->locker->id); + if (dbp->cur_locker != NULL) + STAT_ULONG("Handle lock", dbp->cur_locker->id); + if (dbp->associate_locker != NULL) + STAT_ULONG("Associate lock", dbp->associate_locker->id); + + __db_msg(env, + "%.24s\tReplication handle timestamp", + dbp->timestamp == 0 ? "0" : __os_ctime(&dbp->timestamp, time_buf)); + + STAT_ISSET("Secondary callback", dbp->s_callback); + STAT_ISSET("Primary handle", dbp->s_primary); + + STAT_ISSET("api internal", dbp->api_internal); + STAT_ISSET("Btree/Recno internal", dbp->bt_internal); + STAT_ISSET("Hash internal", dbp->h_internal); + STAT_ISSET("Queue internal", dbp->q_internal); + + __db_prflags(env, NULL, dbp->flags, fn, NULL, "\tFlags"); + + if (dbp->log_filename == NULL) + STAT_ISSET("File naming information", dbp->log_filename); + else + __dbreg_print_fname(env, dbp->log_filename); + + (void)__db_print_cursor(dbp); + + return (0); +} + +/* + * __db_print_cursor -- + * Display the cursor active and free queues. + */ +static int +__db_print_cursor(dbp) + DB *dbp; +{ + DBC *dbc; + ENV *env; + int ret, t_ret; + + env = dbp->env; + + __db_msg(env, "%s", DB_GLOBAL(db_line)); + __db_msg(env, "DB handle cursors:"); + + ret = 0; + MUTEX_LOCK(dbp->env, dbp->mutex); + __db_msg(env, "Active queue:"); + TAILQ_FOREACH(dbc, &dbp->active_queue, links) + if ((t_ret = __db_print_citem(dbc)) != 0 && ret == 0) + ret = t_ret; + __db_msg(env, "Join queue:"); + TAILQ_FOREACH(dbc, &dbp->join_queue, links) + if ((t_ret = __db_print_citem(dbc)) != 0 && ret == 0) + ret = t_ret; + __db_msg(env, "Free queue:"); + TAILQ_FOREACH(dbc, &dbp->free_queue, links) + if ((t_ret = __db_print_citem(dbc)) != 0 && ret == 0) + ret = t_ret; + MUTEX_UNLOCK(dbp->env, dbp->mutex); + + return (ret); +} + +static int +__db_print_citem(dbc) + DBC *dbc; +{ + static const FN fn[] = { + { DBC_ACTIVE, "DBC_ACTIVE" }, + { DBC_DONTLOCK, "DBC_DONTLOCK" }, + { DBC_MULTIPLE, "DBC_MULTIPLE" }, + { DBC_MULTIPLE_KEY, "DBC_MULTIPLE_KEY" }, + { DBC_OPD, "DBC_OPD" }, + { DBC_OWN_LID, "DBC_OWN_LID" }, + { DBC_READ_COMMITTED, "DBC_READ_COMMITTED" }, + { DBC_READ_UNCOMMITTED, "DBC_READ_UNCOMMITTED" }, + { DBC_RECOVER, "DBC_RECOVER" }, + { DBC_RMW, "DBC_RMW" }, + { DBC_TRANSIENT, "DBC_TRANSIENT" }, + { DBC_WAS_READ_COMMITTED,"DBC_WAS_READ_COMMITTED" }, + { DBC_WRITECURSOR, "DBC_WRITECURSOR" }, + { DBC_WRITER, "DBC_WRITER" }, + { 0, NULL } + }; + DB *dbp; + DBC_INTERNAL *cp; + ENV *env; + + dbp = dbc->dbp; + env = dbp->env; + cp = dbc->internal; + + STAT_POINTER("DBC", dbc); + STAT_POINTER("Associated dbp", dbc->dbp); + STAT_POINTER("Associated txn", dbc->txn); + STAT_POINTER("Internal", cp); + STAT_HEX("Default locker ID", dbc->lref == NULL ? 0 : dbc->lref->id); + STAT_HEX("Locker", dbc->locker == NULL ? 0 : dbc->locker->id); + STAT_STRING("Type", __db_dbtype_to_string(dbc->dbtype)); + + STAT_POINTER("Off-page duplicate cursor", cp->opd); + STAT_POINTER("Referenced page", cp->page); + STAT_ULONG("Root", cp->root); + STAT_ULONG("Page number", cp->pgno); + STAT_ULONG("Page index", cp->indx); + STAT_STRING("Lock mode", __db_lockmode_to_string(cp->lock_mode)); + __db_prflags(env, NULL, dbc->flags, fn, NULL, "\tFlags"); + + switch (dbc->dbtype) { + case DB_BTREE: + case DB_RECNO: + __bam_print_cursor(dbc); + break; + case DB_HASH: + __ham_print_cursor(dbc); + break; + case DB_HEAP: + __heap_print_cursor(dbc); + break; + case DB_UNKNOWN: + DB_ASSERT(env, dbp->type != DB_UNKNOWN); + /* FALLTHROUGH */ + case DB_QUEUE: + default: + break; + } + return (0); +} + +#else /* !HAVE_STATISTICS */ + +int +__db_stat_pp(dbp, txn, spp, flags) + DB *dbp; + DB_TXN *txn; + void *spp; + u_int32_t flags; +{ + COMPQUIET(spp, NULL); + COMPQUIET(txn, NULL); + COMPQUIET(flags, 0); + + return (__db_stat_not_built(dbp->env)); +} + +int +__db_stat_print_pp(dbp, flags) + DB *dbp; + u_int32_t flags; +{ + COMPQUIET(flags, 0); + + return (__db_stat_not_built(dbp->env)); +} +#endif diff -r 000000000000 -r a1985f14b030 src/db/db_truncate.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/db/db_truncate.c Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,255 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 2001, 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + * $Id$ + */ + +#include "db_config.h" + +#include "db_int.h" +#include "dbinc/db_page.h" +#include "dbinc/btree.h" +#include "dbinc/hash.h" +#include "dbinc/heap.h" +#include "dbinc/qam.h" +#include "dbinc/lock.h" +#include "dbinc/partition.h" +#include "dbinc/txn.h" + +static int __db_cursor_check_func + __P((DBC *, DBC *, u_int32_t *, db_pgno_t, u_int32_t, void *)); +static int __db_cursor_check __P((DB *)); + +/* + * __db_truncate_pp + * DB->truncate pre/post processing. + * + * PUBLIC: int __db_truncate_pp __P((DB *, DB_TXN *, u_int32_t *, u_int32_t)); + */ +int +__db_truncate_pp(dbp, txn, countp, flags) + DB *dbp; + DB_TXN *txn; + u_int32_t *countp, flags; +{ + DB_THREAD_INFO *ip; + ENV *env; + int handle_check, ret, t_ret, txn_local; + + env = dbp->env; + handle_check = txn_local = 0; + + STRIP_AUTO_COMMIT(flags); + + /* Check for invalid flags. */ + if (F_ISSET(dbp, DB_AM_SECONDARY)) { + __db_errx(env, DB_STR("0685", + "DB->truncate forbidden on secondary indices")); + return (EINVAL); + } + if ((ret = __db_fchk(env, "DB->truncate", flags, 0)) != 0) + return (ret); + + ENV_ENTER(env, ip); + XA_CHECK_TXN(ip, txn); + + /* + * Make sure there are no active cursors on this db. Since we drop + * pages we cannot really adjust cursors. + */ + if ((ret = __db_cursor_check(dbp)) != 0) { + __db_errx(env, DB_STR("0686", + "DB->truncate not permitted with active cursors")); + goto err; + } + +#ifdef CONFIG_TEST + if (IS_REP_MASTER(env)) + DB_TEST_WAIT(env, env->test_check); +#endif + /* Check for replication block. */ + handle_check = IS_ENV_REPLICATED(env); + if (handle_check && + (ret = __db_rep_enter(dbp, 1, 0, IS_REAL_TXN(txn))) != 0) { + handle_check = 0; + goto err; + } + + /* + * Check for changes to a read-only database. This must be after the + * replication block so that we cannot race master/client state changes. + */ + if (DB_IS_READONLY(dbp)) { + ret = __db_rdonly(env, "DB->truncate"); + goto err; + } + + /* + * Create local transaction as necessary, check for consistent + * transaction usage. + */ + if (IS_DB_AUTO_COMMIT(dbp, txn)) { + if ((ret = __txn_begin(env, ip, NULL, &txn, 0)) != 0) + goto err; + txn_local = 1; + } + + /* Check for consistent transaction usage. */ + if ((ret = __db_check_txn(dbp, txn, DB_LOCK_INVALIDID, 0)) != 0) + goto err; + + ret = __db_truncate(dbp, ip, txn, countp); + +err: if (txn_local && + (t_ret = __db_txn_auto_resolve(env, txn, 0, ret)) && ret == 0) + ret = t_ret; + + /* Release replication block. */ + if (handle_check && (t_ret = __env_db_rep_exit(env)) != 0 && ret == 0) + ret = t_ret; + + ENV_LEAVE(env, ip); + return (ret); +} + +/* + * __db_truncate + * DB->truncate. + * + * PUBLIC: int __db_truncate __P((DB *, DB_THREAD_INFO *, DB_TXN *, + * PUBLIC: u_int32_t *)); + */ +int +__db_truncate(dbp, ip, txn, countp) + DB *dbp; + DB_THREAD_INFO *ip; + DB_TXN *txn; + u_int32_t *countp; +{ + DB *sdbp; + DBC *dbc; + ENV *env; + u_int32_t scount; + int ret, t_ret; + + env = dbp->env; + dbc = NULL; + ret = 0; + + /* + * Run through all secondaries and truncate them first. The count + * returned is the count of the primary only. QUEUE uses normal + * processing to truncate so it will update the secondaries normally. + */ + if (dbp->type != DB_QUEUE && DB_IS_PRIMARY(dbp)) { + if ((ret = __db_s_first(dbp, &sdbp)) != 0) + return (ret); + for (; sdbp != NULL && ret == 0; ret = __db_s_next(&sdbp, txn)) + if ((ret = __db_truncate(sdbp, ip, txn, &scount)) != 0) + break; + if (sdbp != NULL) + (void)__db_s_done(sdbp, txn); + if (ret != 0) + return (ret); + } + + DB_TEST_RECOVERY(dbp, DB_TEST_PREDESTROY, ret, NULL); + + /* Acquire a cursor. */ + if ((ret = __db_cursor(dbp, ip, txn, &dbc, 0)) != 0) + return (ret); + + DEBUG_LWRITE(dbc, txn, "DB->truncate", NULL, NULL, 0); +#ifdef HAVE_PARTITION + if (DB_IS_PARTITIONED(dbp)) + ret = __part_truncate(dbc, countp); + else +#endif + switch (dbp->type) { + case DB_BTREE: + case DB_RECNO: + ret = __bam_truncate(dbc, countp); + break; + case DB_HASH: + ret = __ham_truncate(dbc, countp); + break; + case DB_HEAP: + ret = __heap_truncate(dbc, countp); + break; + case DB_QUEUE: + ret = __qam_truncate(dbc, countp); + break; + case DB_UNKNOWN: + default: + ret = __db_unknown_type(env, "DB->truncate", dbp->type); + break; + } + + /* Discard the cursor. */ + if (dbc != NULL && (t_ret = __dbc_close(dbc)) != 0 && ret == 0) + ret = t_ret; + + DB_TEST_RECOVERY(dbp, DB_TEST_POSTDESTROY, ret, NULL); + +DB_TEST_RECOVERY_LABEL + + return (ret); +} + +static int +__db_cursor_check_func(dbc, my_dbc, foundp, pgno, indx, args) + DBC *dbc, *my_dbc; + u_int32_t *foundp; + db_pgno_t pgno; + u_int32_t indx; + void *args; +{ + COMPQUIET(my_dbc, NULL); + COMPQUIET(args, NULL); + COMPQUIET(pgno, 0); + COMPQUIET(indx, 0); + if (IS_INITIALIZED(dbc)) { + *foundp = 1; + return (EEXIST); + } + return (0); +} +/* + * __db_cursor_check -- + * See if there are any active cursors on this db. + */ +static int +__db_cursor_check(dbp) + DB *dbp; +{ + int ret; + u_int32_t found; + + ret = __db_walk_cursors(dbp, NULL, + __db_cursor_check_func, &found, 0, 0, NULL); + return (ret == EEXIST ? EINVAL : ret); +} diff -r 000000000000 -r a1985f14b030 src/db/db_vrfy.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/db/db_vrfy.c Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,3081 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 2000, 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + * $Id$ + */ + +#include "db_config.h" + +#include "db_int.h" +#include "dbinc/db_page.h" +#include "dbinc/db_swap.h" +#include "dbinc/db_verify.h" +#include "dbinc/btree.h" +#include "dbinc/fop.h" +#include "dbinc/hash.h" +#include "dbinc/heap.h" +#include "dbinc/lock.h" +#include "dbinc/mp.h" +#include "dbinc/qam.h" +#include "dbinc/txn.h" + +/* + * This is the code for DB->verify, the DB database consistency checker. + * For now, it checks all subdatabases in a database, and verifies + * everything it knows how to (i.e. it's all-or-nothing, and one can't + * check only for a subset of possible problems). + */ + +static u_int __db_guesspgsize __P((ENV *, DB_FH *)); +static int __db_is_valid_magicno __P((u_int32_t, DBTYPE *)); +static int __db_meta2pgset + __P((DB *, VRFY_DBINFO *, db_pgno_t, u_int32_t, DB *)); +static int __db_salvage __P((DB *, VRFY_DBINFO *, + db_pgno_t, void *, int (*)(void *, const void *), u_int32_t)); +static int __db_salvage_subdbpg __P((DB *, VRFY_DBINFO *, + PAGE *, void *, int (*)(void *, const void *), u_int32_t)); +static int __db_salvage_all __P((DB *, VRFY_DBINFO *, void *, + int(*)(void *, const void *), u_int32_t, int *)); +static int __db_salvage_unknowns __P((DB *, VRFY_DBINFO *, void *, + int (*)(void *, const void *), u_int32_t)); +static int __db_verify_arg __P((DB *, const char *, void *, u_int32_t)); +static int __db_vrfy_freelist + __P((DB *, VRFY_DBINFO *, db_pgno_t, u_int32_t)); +static int __db_vrfy_getpagezero + __P((DB *, DB_FH *, const char *, u_int8_t *, u_int32_t)); +static int __db_vrfy_invalid + __P((DB *, VRFY_DBINFO *, PAGE *, db_pgno_t, u_int32_t)); +static int __db_vrfy_orderchkonly __P((DB *, + VRFY_DBINFO *, const char *, const char *, u_int32_t)); +static int __db_vrfy_pagezero __P((DB *, + VRFY_DBINFO *, DB_FH *, const char *, u_int32_t)); +static int __db_vrfy_subdbs + __P((DB *, VRFY_DBINFO *, const char *, u_int32_t)); +static int __db_vrfy_structure __P((DB *, VRFY_DBINFO *, + const char *, db_pgno_t, void *, void *, u_int32_t)); +static int __db_vrfy_walkpages __P((DB *, VRFY_DBINFO *, + void *, int (*)(void *, const void *), u_int32_t)); + +#define VERIFY_FLAGS \ + (DB_AGGRESSIVE | \ + DB_NOORDERCHK | DB_ORDERCHKONLY | DB_PRINTABLE | DB_SALVAGE | DB_UNREF) + +/* + * __db_verify_pp -- + * DB->verify public interface. + * + * PUBLIC: int __db_verify_pp + * PUBLIC: __P((DB *, const char *, const char *, FILE *, u_int32_t)); + */ +int +__db_verify_pp(dbp, file, database, outfile, flags) + DB *dbp; + const char *file, *database; + FILE *outfile; + u_int32_t flags; +{ + /* + * __db_verify_pp is a wrapper to __db_verify_internal, which lets + * us pass appropriate equivalents to FILE * in from the non-C APIs. + * That's why the usual ENV_ENTER macros are in __db_verify_internal, + * not here. + */ + return (__db_verify_internal(dbp, + file, database, outfile, __db_pr_callback, flags)); +} + +/* + * __db_verify_internal -- + * + * PUBLIC: int __db_verify_internal __P((DB *, const char *, + * PUBLIC: const char *, void *, int (*)(void *, const void *), u_int32_t)); + */ +int +__db_verify_internal(dbp, fname, dname, handle, callback, flags) + DB *dbp; + const char *fname, *dname; + void *handle; + int (*callback) __P((void *, const void *)); + u_int32_t flags; +{ + DB_THREAD_INFO *ip; + ENV *env; + int ret, t_ret; + + env = dbp->env; + + DB_ILLEGAL_AFTER_OPEN(dbp, "DB->verify"); + + if (!LF_ISSET(DB_SALVAGE)) + LF_SET(DB_UNREF); + + ENV_ENTER(env, ip); + + if ((ret = __db_verify_arg(dbp, dname, handle, flags)) == 0) + ret = __db_verify(dbp, ip, + fname, dname, handle, callback, NULL, NULL, flags); + + /* Db.verify is a DB handle destructor. */ + if ((t_ret = __db_close(dbp, NULL, 0)) != 0 && ret == 0) + ret = t_ret; + + ENV_LEAVE(env, ip); + return (ret); +} + +/* + * __db_verify_arg -- + * Check DB->verify arguments. + */ +static int +__db_verify_arg(dbp, dname, handle, flags) + DB *dbp; + const char *dname; + void *handle; + u_int32_t flags; +{ + ENV *env; + int ret; + + env = dbp->env; + + if ((ret = __db_fchk(env, "DB->verify", flags, VERIFY_FLAGS)) != 0) + return (ret); + + /* + * DB_SALVAGE is mutually exclusive with the other flags except + * DB_AGGRESSIVE, DB_PRINTABLE. + * + * DB_AGGRESSIVE and DB_PRINTABLE are only meaningful when salvaging. + * + * DB_SALVAGE requires an output stream. + */ + if (LF_ISSET(DB_SALVAGE)) { + if (LF_ISSET(~(DB_AGGRESSIVE | DB_PRINTABLE | DB_SALVAGE))) + return (__db_ferr(env, "DB->verify", 1)); + if (handle == NULL) { + __db_errx(env, DB_STR("0518", + "DB_SALVAGE requires a an output handle")); + return (EINVAL); + } + } else + if (LF_ISSET(DB_AGGRESSIVE | DB_PRINTABLE)) + return (__db_ferr(env, "DB->verify", 1)); + + /* + * DB_ORDERCHKONLY is mutually exclusive with DB_SALVAGE and + * DB_NOORDERCHK, and requires a database name. + */ + if ((ret = __db_fcchk(env, "DB->verify", flags, + DB_ORDERCHKONLY, DB_SALVAGE | DB_NOORDERCHK)) != 0) + return (ret); + if (LF_ISSET(DB_ORDERCHKONLY) && dname == NULL) { + __db_errx(env, DB_STR("0519", + "DB_ORDERCHKONLY requires a database name")); + return (EINVAL); + } + return (0); +} + +/* + * __db_verify -- + * Walk the entire file page-by-page, either verifying with or without + * dumping in db_dump -d format, or DB_SALVAGE-ing whatever key/data + * pairs can be found and dumping them in standard (db_load-ready) + * dump format. + * + * (Salvaging isn't really a verification operation, but we put it + * here anyway because it requires essentially identical top-level + * code.) + * + * flags may be 0, DB_NOORDERCHK, DB_ORDERCHKONLY, or DB_SALVAGE + * (and optionally DB_AGGRESSIVE). + * PUBLIC: int __db_verify __P((DB *, DB_THREAD_INFO *, const char *, + * PUBLIC: const char *, void *, int (*)(void *, const void *), + * PUBLIC: void *, void *, u_int32_t)); + */ +int +__db_verify(dbp, ip, name, subdb, handle, callback, lp, rp, flags) + DB *dbp; + DB_THREAD_INFO *ip; + const char *name, *subdb; + void *handle; + int (*callback) __P((void *, const void *)); + void *lp, *rp; + u_int32_t flags; +{ + DB_FH *fhp; + ENV *env; + VRFY_DBINFO *vdp; + u_int32_t sflags; + int has_subdbs, isbad, ret, t_ret; + char *real_name; + + env = dbp->env; + fhp = NULL; + vdp = NULL; + real_name = NULL; + has_subdbs = isbad = ret = t_ret = 0; + + F_SET(dbp, DB_AM_VERIFYING); + + /* Initialize any feedback function. */ + if (!LF_ISSET(DB_SALVAGE) && dbp->db_feedback != NULL) + dbp->db_feedback(dbp, DB_VERIFY, 0); + + /* + * We don't know how large the cache is, and if the database + * in question uses a small page size--which we don't know + * yet!--it may be uncomfortably small for the default page + * size [#2143]. However, the things we need temporary + * databases for in dbinfo are largely tiny, so using a + * 1024-byte pagesize is probably not going to be a big hit, + * and will make us fit better into small spaces. + */ + if ((ret = __db_vrfy_dbinfo_create(env, ip, 1024, &vdp)) != 0) + goto err; + + /* + * Note whether the user has requested that we use printable + * chars where possible. We won't get here with this flag if + * we're not salvaging. + */ + if (LF_ISSET(DB_PRINTABLE)) + F_SET(vdp, SALVAGE_PRINTABLE); + + if (name != NULL) { + /* Find the real name of the file. */ + if ((ret = __db_appname(env, + DB_APP_DATA, name, &dbp->dirname, &real_name)) != 0) + goto err; + + /* + * Our first order of business is to verify page 0, which is the + * metadata page for the master database of subdatabases or of + * the only database in the file. We want to do this by hand + * rather than just calling __db_open in case it's + * corrupt--various things in __db_open might act funny. + * + * Once we know the metadata page is healthy, I believe that + * it's safe to open the database normally and then use the page + * swapping code, which makes life easier. + */ + if ((ret = __os_open(env, + real_name, 0, DB_OSO_RDONLY, 0, &fhp)) != 0) + goto err; + } else { + MAKE_INMEM(dbp); + } + + /* Verify the metadata page 0; set pagesize and type. */ + if ((ret = __db_vrfy_pagezero(dbp, vdp, fhp, subdb, flags)) != 0) { + if (ret == DB_VERIFY_BAD) + isbad = 1; + else + goto err; + } + + /* + * We can assume at this point that dbp->pagesize and dbp->type are + * set correctly, or at least as well as they can be, and that + * locking, logging, and txns are not in use. Thus we can trust + * the memp code not to look at the page, and thus to be safe + * enough to use. + * + * The dbp is not open, but the file is open in the fhp, and we + * cannot assume that __db_open is safe. Call __env_setup, + * the [safe] part of __db_open that initializes the environment-- + * and the mpool--manually. + */ + if ((ret = __env_setup(dbp, NULL, + name, subdb, TXN_INVALID, DB_ODDFILESIZE | DB_RDONLY)) != 0) + goto err; + + /* + * Set our name in the Queue subsystem; we may need it later + * to deal with extents. In-memory databases are not allowed to have + * extents. + */ + if (dbp->type == DB_QUEUE && name != NULL && + (ret = __qam_set_ext_data(dbp, name)) != 0) + goto err; + + /* Mark the dbp as opened, so that we correctly handle its close. */ + F_SET(dbp, DB_AM_OPEN_CALLED); + + /* + * Find out the page number of the last page in the database. We'll + * use this later to verify the metadata page. We don't verify now + * because the data from __db_vrfy_pagezero could be stale. + */ + if ((ret = __memp_get_last_pgno(dbp->mpf, &vdp->last_pgno)) != 0) + goto err; + /* + * DB_ORDERCHKONLY is a special case; our file consists of + * several subdatabases, which use different hash, bt_compare, + * and/or dup_compare functions. Consequently, we couldn't verify + * sorting and hashing simply by calling DB->verify() on the file. + * DB_ORDERCHKONLY allows us to come back and check those things; it + * requires a subdatabase, and assumes that everything but that + * database's sorting/hashing is correct. + */ + if (LF_ISSET(DB_ORDERCHKONLY)) { + ret = __db_vrfy_orderchkonly(dbp, vdp, name, subdb, flags); + goto done; + } + + sflags = flags; + if (dbp->p_internal != NULL) + LF_CLR(DB_SALVAGE); + + /* + * When salvaging, we use a db to keep track of whether we've seen a + * given overflow or dup page in the course of traversing normal data. + * If in the end we have not, we assume its key got lost and print it + * with key "UNKNOWN". + */ + if (LF_ISSET(DB_SALVAGE)) { + if ((ret = __db_salvage_init(vdp)) != 0) + goto err; + + /* + * If we're not being aggressive, salvage by walking the tree + * and only printing the leaves we find. "has_subdbs" will + * indicate whether we found subdatabases. + */ + if (!LF_ISSET(DB_AGGRESSIVE) && __db_salvage_all( + dbp, vdp, handle, callback, flags, &has_subdbs) != 0) + isbad = 1; + + /* + * If we have subdatabases, flag if any keys are found that + * don't belong to a subdatabase -- they'll need to have an + * "__OTHER__" subdatabase header printed first. + */ + if (has_subdbs) { + F_SET(vdp, SALVAGE_PRINTHEADER); + F_SET(vdp, SALVAGE_HASSUBDBS); + } + } + + /* Walk all the pages, if a page cannot be read, verify structure. */ + if ((ret = + __db_vrfy_walkpages(dbp, vdp, handle, callback, flags)) != 0) { + if (ret == DB_VERIFY_BAD) + isbad = 1; + else if (ret != DB_PAGE_NOTFOUND) + goto err; + } + + /* If we're verifying, verify inter-page structure. */ + if (!LF_ISSET(DB_SALVAGE) && isbad == 0) + if ((t_ret = __db_vrfy_structure(dbp, + vdp, name, 0, lp, rp, flags)) != 0) { + if (t_ret == DB_VERIFY_BAD) + isbad = 1; + else + goto err; + } + + /* + * If we're salvaging, output with key UNKNOWN any overflow or dup pages + * we haven't been able to put in context. Then destroy the salvager's + * state-saving database. + */ + if (LF_ISSET(DB_SALVAGE)) { + if ((ret = __db_salvage_unknowns(dbp, + vdp, handle, callback, flags)) != 0) + isbad = 1; + } + + flags = sflags; + +#ifdef HAVE_PARTITION + if (t_ret == 0 && dbp->p_internal != NULL) + t_ret = __part_verify(dbp, vdp, name, handle, callback, flags); +#endif + + if (ret == 0) + ret = t_ret; + + /* Don't display a footer for a database holding other databases. */ + if (LF_ISSET(DB_SALVAGE | DB_VERIFY_PARTITION) == DB_SALVAGE && + (!has_subdbs || F_ISSET(vdp, SALVAGE_PRINTFOOTER))) + (void)__db_prfooter(handle, callback); + +done: err: + /* Send feedback that we're done. */ + if (!LF_ISSET(DB_SALVAGE) && dbp->db_feedback != NULL) + dbp->db_feedback(dbp, DB_VERIFY, 100); + + if (LF_ISSET(DB_SALVAGE) && + (t_ret = __db_salvage_destroy(vdp)) != 0 && ret == 0) + ret = t_ret; + if (fhp != NULL && + (t_ret = __os_closehandle(env, fhp)) != 0 && ret == 0) + ret = t_ret; + if (vdp != NULL && + (t_ret = __db_vrfy_dbinfo_destroy(env, vdp)) != 0 && ret == 0) + ret = t_ret; + if (real_name != NULL) + __os_free(env, real_name); + + /* + * DB_VERIFY_FATAL is a private error, translate to a public one. + * + * If we didn't find a page, it's probably a page number was corrupted. + * Return the standard corruption error. + * + * Otherwise, if we found corruption along the way, set the return. + */ + if (ret == DB_VERIFY_FATAL || + ret == DB_PAGE_NOTFOUND || (ret == 0 && isbad == 1)) + ret = DB_VERIFY_BAD; + + /* Make sure there's a public complaint if we found corruption. */ + if (ret != 0) + __db_err(env, ret, "%s", name); + + return (ret); +} + +/* + * __db_vrfy_getpagezero -- + * Store the master metadata page into a local buffer. For safety, skip + * the DB paging code and read the page directly from disk (via seek and + * read) or the mpool. + */ +static int +__db_vrfy_getpagezero(dbp, fhp, name, mbuf, flags) + DB *dbp; + DB_FH *fhp; + const char *name; + u_int8_t *mbuf; + u_int32_t flags; +{ + DB_MPOOLFILE *mpf; + ENV *env; + PAGE *h; + db_pgno_t pgno; + int ret, t_ret; + size_t nr; + + env = dbp->env; + + if (F_ISSET(dbp, DB_AM_INMEM)) { + /* + * Now get the metadata page from the cache, if possible. If + * we're verifying an in-memory db, this is the only metadata + * page we have. + * + * + * Open the in-memory db file and get the metadata page. + */ + if ((ret = __memp_fcreate_pp(env->dbenv, &mpf, DB_VERIFY)) != 0) + return (ret); + if ((ret = __memp_set_flags(mpf, DB_MPOOL_NOFILE, 1)) != 0) + goto mpf_err; + if ((ret = __memp_fopen_pp(mpf, + name, DB_ODDFILESIZE | DB_RDONLY, 0, 0)) != 0) + goto mpf_err; + pgno = PGNO_BASE_MD; + if ((ret = __memp_fget_pp(mpf, &pgno, NULL, 0, &h)) != 0) { + __db_err(env, ret, DB_STR_A("0747", + "Metadata page %lu cannot be read from mpool", + "%lu"), (u_long)pgno); + goto mpf_err; + } + memcpy(mbuf, (u_int8_t *)h, DBMETASIZE); + ret = __memp_fput_pp(mpf, h, DB_PRIORITY_UNCHANGED, 0); +mpf_err: if ((t_ret = __memp_fclose_pp(mpf, 0)) != 0 || ret != 0) { + return (ret == 0 ? t_ret : ret); + } + } else { + /* + * Seek to the metadata page. + * + * Note that if we're just starting a verification, dbp->pgsize + * may be zero; this is okay, as we want page zero anyway and + * 0*0 == 0. + */ + if ((ret = __os_seek(env, fhp, 0, 0, 0)) != 0 || + (ret = __os_read(env, fhp, mbuf, DBMETASIZE, &nr)) != 0) { + __db_err(env, ret, DB_STR_A("0520", + "Metadata page %lu cannot be read", "%lu"), + (u_long)PGNO_BASE_MD); + return (ret); + } + + if (nr != DBMETASIZE) { + EPRINT((env, DB_STR_A("0521", + "Page %lu: Incomplete metadata page", "%lu"), + (u_long)PGNO_BASE_MD)); + return (DB_VERIFY_FATAL); + } + } + + return (ret); +} + +/* + * __db_vrfy_pagezero -- + * Verify the master metadata page. Use seek, read, and a local buffer + * rather than the DB paging code, for safety. + * + * Must correctly (or best-guess) set dbp->type and dbp->pagesize. + */ +static int +__db_vrfy_pagezero(dbp, vdp, fhp, name, flags) + DB *dbp; + VRFY_DBINFO *vdp; + DB_FH *fhp; + const char *name; + u_int32_t flags; +{ + DBMETA *meta; + ENV *env; + VRFY_PAGEINFO *pip; + db_pgno_t freelist; + int isbad, ret, swapped; + u_int8_t mbuf[DBMETASIZE]; + + isbad = ret = swapped = 0; + freelist = 0; + env = dbp->env; + meta = (DBMETA *)mbuf; + dbp->type = DB_UNKNOWN; + + if ((ret = __db_vrfy_getpagezero(dbp, fhp, name, mbuf, flags)) != 0) + return (ret); + + if ((ret = __db_vrfy_getpageinfo(vdp, PGNO_BASE_MD, &pip)) != 0) + return (ret); + + if ((ret = __db_chk_meta(env, dbp, meta, 1)) != 0) { + EPRINT((env, DB_STR_A("0522", + "Page %lu: metadata page corrupted", "%lu"), + (u_long)PGNO_BASE_MD)); + isbad = 1; + if (ret != DB_CHKSUM_FAIL) { + EPRINT((env, DB_STR_A("0523", + "Page %lu: could not check metadata page", "%lu"), + (u_long)PGNO_BASE_MD)); + return (DB_VERIFY_FATAL); + } + } + + /* + * Check all of the fields that we can. + * + * 08-11: Current page number. Must == pgno. + * Note that endianness doesn't matter--it's zero. + */ + if (meta->pgno != PGNO_BASE_MD) { + isbad = 1; + EPRINT((env, DB_STR_A("0524", + "Page %lu: pgno incorrectly set to %lu", "%lu %lu"), + (u_long)PGNO_BASE_MD, (u_long)meta->pgno)); + } + + /* 12-15: Magic number. Must be one of valid set. */ + if (__db_is_valid_magicno(meta->magic, &dbp->type)) + swapped = 0; + else { + M_32_SWAP(meta->magic); + if (__db_is_valid_magicno(meta->magic, + &dbp->type)) + swapped = 1; + else { + isbad = 1; + EPRINT((env, DB_STR_A("0525", + "Page %lu: bad magic number %lu", "%lu %lu"), + (u_long)PGNO_BASE_MD, (u_long)meta->magic)); + } + } + + /* + * 16-19: Version. Must be current; for now, we + * don't support verification of old versions. + */ + if (swapped) + M_32_SWAP(meta->version); + if ((dbp->type == DB_BTREE && + (meta->version > DB_BTREEVERSION || + meta->version < DB_BTREEOLDVER)) || + (dbp->type == DB_HASH && + (meta->version > DB_HASHVERSION || + meta->version < DB_HASHOLDVER)) || + (dbp->type == DB_HEAP && + (meta->version > DB_HEAPVERSION || + meta->version < DB_HEAPOLDVER)) || + (dbp->type == DB_QUEUE && + (meta->version > DB_QAMVERSION || + meta->version < DB_QAMOLDVER))) { + isbad = 1; + EPRINT((env, DB_STR_A("0526", + "Page %lu: unsupported DB version %lu; extraneous errors may result", + "%lu %lu"), (u_long)PGNO_BASE_MD, (u_long)meta->version)); + } + + /* + * 20-23: Pagesize. Must be power of two, + * greater than 512, and less than 64K. + */ + if (swapped) + M_32_SWAP(meta->pagesize); + if (IS_VALID_PAGESIZE(meta->pagesize)) + dbp->pgsize = meta->pagesize; + else { + isbad = 1; + EPRINT((env, DB_STR_A("0527", "Page %lu: bad page size %lu", + "%lu %lu"), (u_long)PGNO_BASE_MD, (u_long)meta->pagesize)); + + /* + * Now try to settle on a pagesize to use. + * If the user-supplied one is reasonable, + * use it; else, guess. + */ + if (!IS_VALID_PAGESIZE(dbp->pgsize)) + dbp->pgsize = __db_guesspgsize(env, fhp); + } + + /* + * 25: Page type. Must be correct for dbp->type, + * which is by now set as well as it can be. + */ + /* Needs no swapping--only one byte! */ + if ((dbp->type == DB_BTREE && meta->type != P_BTREEMETA) || + (dbp->type == DB_HASH && meta->type != P_HASHMETA) || + (dbp->type == DB_HEAP && meta->type != P_HEAPMETA) || + (dbp->type == DB_QUEUE && meta->type != P_QAMMETA)) { + isbad = 1; + EPRINT((env, DB_STR_A("0528", "Page %lu: bad page type %lu", + "%lu %lu"), (u_long)PGNO_BASE_MD, (u_long)meta->type)); + } + + /* + * 26: Meta-flags. + */ + if (meta->metaflags != 0) { + if (FLD_ISSET(meta->metaflags, + ~(DBMETA_CHKSUM|DBMETA_PART_RANGE|DBMETA_PART_CALLBACK))) { + isbad = 1; + EPRINT((env, DB_STR_A("0529", + "Page %lu: bad meta-data flags value %#lx", + "%lu %#lx"), (u_long)PGNO_BASE_MD, + (u_long)meta->metaflags)); + } + if (FLD_ISSET(meta->metaflags, DBMETA_CHKSUM)) + F_SET(pip, VRFY_HAS_CHKSUM); + if (FLD_ISSET(meta->metaflags, DBMETA_PART_RANGE)) + F_SET(pip, VRFY_HAS_PART_RANGE); + if (FLD_ISSET(meta->metaflags, DBMETA_PART_CALLBACK)) + F_SET(pip, VRFY_HAS_PART_CALLBACK); + + if (FLD_ISSET(meta->metaflags, + DBMETA_PART_RANGE | DBMETA_PART_CALLBACK) && + (ret = __partition_init(dbp, meta->metaflags)) != 0) + return (ret); + } + + /* + * 28-31: Free list page number. + * 32-35: Last page in database file. + * We'll verify last_pgno once we open the db in the mpool; + * for now, just store it. + */ + if (swapped) + M_32_SWAP(meta->free); + freelist = meta->free; + if (swapped) + M_32_SWAP(meta->last_pgno); + vdp->meta_last_pgno = meta->last_pgno; + + /* + * Initialize vdp->pages to fit a single pageinfo structure for + * this one page. We'll realloc later when we know how many + * pages there are. + */ + pip->pgno = PGNO_BASE_MD; + pip->type = meta->type; + + /* + * Signal that we still have to check the info specific to + * a given type of meta page. + */ + F_SET(pip, VRFY_INCOMPLETE); + + pip->free = freelist; + + if ((ret = __db_vrfy_putpageinfo(env, vdp, pip)) != 0) + return (ret); + + /* Set up the dbp's fileid. We don't use the regular open path. */ + memcpy(dbp->fileid, meta->uid, DB_FILE_ID_LEN); + dbp->preserve_fid = 1; + + if (swapped == 1) + F_SET(dbp, DB_AM_SWAP); + + return (isbad ? DB_VERIFY_BAD : 0); +} + +/* + * __db_vrfy_walkpages -- + * Main loop of the verifier/salvager. Walks through, + * page by page, and verifies all pages and/or prints all data pages. + */ +static int +__db_vrfy_walkpages(dbp, vdp, handle, callback, flags) + DB *dbp; + VRFY_DBINFO *vdp; + void *handle; + int (*callback) __P((void *, const void *)); + u_int32_t flags; +{ + DB_MPOOLFILE *mpf; + ENV *env; + PAGE *h; + VRFY_PAGEINFO *pip; + db_pgno_t i; + int ret, t_ret, isbad; + + env = dbp->env; + mpf = dbp->mpf; + h = NULL; + ret = isbad = t_ret = 0; + + for (i = 0; i <= vdp->last_pgno; i++) { + /* + * If DB_SALVAGE is set, we inspect our database of completed + * pages, and skip any we've already printed in the subdb pass. + */ + if (LF_ISSET(DB_SALVAGE) && (__db_salvage_isdone(vdp, i) != 0)) + continue; + + /* + * An individual page get can fail if: + * * This is a hash database, it is expected to find + * empty buckets, which don't have allocated pages. Create + * a dummy page so the verification can proceed. + * * We are salvaging, flag the error and continue. + */ + if ((t_ret = __memp_fget(mpf, &i, + vdp->thread_info, NULL, 0, &h)) != 0) { + if (dbp->type == DB_HASH || + (dbp->type == DB_QUEUE && + F_ISSET(dbp, DB_AM_INMEM))) { + if ((t_ret = + __db_vrfy_getpageinfo(vdp, i, &pip)) != 0) + goto err1; + pip->type = P_INVALID; + pip->pgno = i; + F_CLR(pip, VRFY_IS_ALLZEROES); + F_SET(pip, VRFY_NONEXISTENT); + if ((t_ret = __db_vrfy_putpageinfo( + env, vdp, pip)) != 0) + goto err1; + continue; + } + if (t_ret == DB_PAGE_NOTFOUND) { + EPRINT((env, DB_STR_A("0530", + "Page %lu: beyond the end of the file, metadata page has last page as %lu", + "%lu %lu"), (u_long)i, + (u_long)vdp->last_pgno)); + if (ret == 0) + return (t_ret); + } + +err1: if (ret == 0) + ret = t_ret; + if (LF_ISSET(DB_SALVAGE)) + continue; + return (ret); + } + + if (LF_ISSET(DB_SALVAGE)) { + /* + * We pretty much don't want to quit unless a + * bomb hits. May as well return that something + * was screwy, however. + */ + if ((t_ret = __db_salvage_pg(dbp, + vdp, i, h, handle, callback, flags)) != 0) { + if (ret == 0) + ret = t_ret; + isbad = 1; + } + } else { + /* + * If we are not salvaging, and we get any error + * other than DB_VERIFY_BAD, return immediately; + * it may not be safe to proceed. If we get + * DB_VERIFY_BAD, keep going; listing more errors + * may make it easier to diagnose problems and + * determine the magnitude of the corruption. + * + * Verify info common to all page types. + */ + if (i != PGNO_BASE_MD) { + ret = __db_vrfy_common(dbp, vdp, h, i, flags); + if (ret == DB_VERIFY_BAD) + isbad = 1; + else if (ret != 0) + goto err; + } + + switch (TYPE(h)) { + case P_INVALID: + ret = __db_vrfy_invalid(dbp, vdp, h, i, flags); + break; + case __P_DUPLICATE: + isbad = 1; + EPRINT((env, DB_STR_A("0531", + "Page %lu: old-style duplicate page", + "%lu"), (u_long)i)); + break; + case P_HASH_UNSORTED: + case P_HASH: + ret = __ham_vrfy(dbp, vdp, h, i, flags); + break; + case P_HEAP: + case P_IHEAP: + ret = __heap_vrfy(dbp, vdp, h, i, flags); + break; + case P_IBTREE: + case P_IRECNO: + case P_LBTREE: + case P_LDUP: + ret = __bam_vrfy(dbp, vdp, h, i, flags); + break; + case P_LRECNO: + ret = __ram_vrfy_leaf(dbp, vdp, h, i, flags); + break; + case P_OVERFLOW: + ret = __db_vrfy_overflow(dbp, vdp, h, i, flags); + break; + case P_HASHMETA: + ret = __ham_vrfy_meta(dbp, + vdp, (HMETA *)h, i, flags); + break; + case P_HEAPMETA: + ret = __heap_vrfy_meta(dbp, + vdp, (HEAPMETA *)h, i, flags); + break; + case P_BTREEMETA: + ret = __bam_vrfy_meta(dbp, + vdp, (BTMETA *)h, i, flags); + break; + case P_QAMMETA: + ret = __qam_vrfy_meta(dbp, + vdp, (QMETA *)h, i, flags); + break; + case P_QAMDATA: + ret = __qam_vrfy_data(dbp, + vdp, (QPAGE *)h, i, flags); + break; + default: + EPRINT((env, DB_STR_A("0532", + "Page %lu: unknown page type %lu", + "%lu %lu"), (u_long)i, (u_long)TYPE(h))); + isbad = 1; + break; + } + + /* + * Set up error return. + */ + if (ret == DB_VERIFY_BAD) + isbad = 1; + else if (ret != 0) + goto err; + + /* + * Provide feedback to the application about our + * progress. The range 0-50% comes from the fact + * that this is the first of two passes through the + * database (front-to-back, then top-to-bottom). + */ + if (dbp->db_feedback != NULL) + dbp->db_feedback(dbp, DB_VERIFY, + (int)((i + 1) * 50 / (vdp->last_pgno + 1))); + } + + /* + * Just as with the page get, bail if and only if we're + * not salvaging. + */ + if ((t_ret = __memp_fput(mpf, + vdp->thread_info, h, dbp->priority)) != 0) { + if (ret == 0) + ret = t_ret; + if (!LF_ISSET(DB_SALVAGE)) + return (ret); + } + } + + /* + * If we've seen a Queue metadata page, we may need to walk Queue + * extent pages that won't show up between 0 and vdp->last_pgno. + */ + if (F_ISSET(vdp, VRFY_QMETA_SET) && (t_ret = + __qam_vrfy_walkqueue(dbp, vdp, handle, callback, flags)) != 0) { + if (ret == 0) + ret = t_ret; + if (t_ret == DB_VERIFY_BAD) + isbad = 1; + else if (!LF_ISSET(DB_SALVAGE)) + return (ret); + } + + if (0) { +err: if (h != NULL && (t_ret = __memp_fput(mpf, + vdp->thread_info, h, dbp->priority)) != 0) + return (ret == 0 ? t_ret : ret); + } + + return ((isbad == 1 && ret == 0) ? DB_VERIFY_BAD : ret); +} + +/* + * __db_vrfy_structure-- + * After a beginning-to-end walk through the database has been + * completed, put together the information that has been collected + * to verify the overall database structure. + * + * Should only be called if we want to do a database verification, + * i.e. if DB_SALVAGE is not set. + */ +static int +__db_vrfy_structure(dbp, vdp, dbname, meta_pgno, lp, rp, flags) + DB *dbp; + VRFY_DBINFO *vdp; + const char *dbname; + db_pgno_t meta_pgno; + void *lp, *rp; + u_int32_t flags; +{ + DB *pgset; + ENV *env; + VRFY_PAGEINFO *pip; + db_pgno_t i; + int ret, isbad, hassubs, p; + + isbad = 0; + pip = NULL; + env = dbp->env; + pgset = vdp->pgset; + + /* + * Providing feedback here is tricky; in most situations, + * we fetch each page one more time, but we do so in a top-down + * order that depends on the access method. Worse, we do this + * recursively in btree, such that on any call where we're traversing + * a subtree we don't know where that subtree is in the whole database; + * worse still, any given database may be one of several subdbs. + * + * The solution is to decrement a counter vdp->pgs_remaining each time + * we verify (and call feedback on) a page. We may over- or + * under-count, but the structure feedback function will ensure that we + * never give a percentage under 50 or over 100. (The first pass + * covered the range 0-50%.) + */ + if (dbp->db_feedback != NULL) + vdp->pgs_remaining = vdp->last_pgno + 1; + + /* + * Call the appropriate function to downwards-traverse the db type. + */ + switch (dbp->type) { + case DB_BTREE: + case DB_RECNO: + if ((ret = + __bam_vrfy_structure(dbp, vdp, 0, lp, rp, flags)) != 0) { + if (ret == DB_VERIFY_BAD) + isbad = 1; + else + goto err; + } + + /* + * If we have subdatabases and we know that the database is, + * thus far, sound, it's safe to walk the tree of subdatabases. + * Do so, and verify the structure of the databases within. + */ + if ((ret = __db_vrfy_getpageinfo(vdp, 0, &pip)) != 0) + goto err; + hassubs = F_ISSET(pip, VRFY_HAS_SUBDBS) ? 1 : 0; + if ((ret = __db_vrfy_putpageinfo(env, vdp, pip)) != 0) + goto err; + pip = NULL; + + if (isbad == 0 && hassubs) + if ((ret = + __db_vrfy_subdbs(dbp, vdp, dbname, flags)) != 0) { + if (ret == DB_VERIFY_BAD) + isbad = 1; + else + goto err; + } + break; + case DB_HASH: + if ((ret = __ham_vrfy_structure(dbp, vdp, 0, flags)) != 0) { + if (ret == DB_VERIFY_BAD) + isbad = 1; + else + goto err; + } + break; + case DB_HEAP: + if ((ret = __heap_vrfy_structure(dbp, vdp, flags)) != 0) { + if (ret == DB_VERIFY_BAD) + isbad = 1; + } + /* Skip the freelist check for heap, it doesn't apply. */ + goto err; + case DB_QUEUE: + if ((ret = __qam_vrfy_structure(dbp, vdp, flags)) != 0) { + if (ret == DB_VERIFY_BAD) + isbad = 1; + } + + /* + * Queue pages may be unreferenced and totally zeroed, if + * they're empty; queue doesn't have much structure, so + * this is unlikely to be wrong in any troublesome sense. + * Skip to "err". + */ + goto err; + case DB_UNKNOWN: + default: + ret = __db_unknown_path(env, "__db_vrfy_structure"); + goto err; + } + + /* Walk free list. */ + if ((ret = + __db_vrfy_freelist(dbp, vdp, meta_pgno, flags)) == DB_VERIFY_BAD) + isbad = 1; + + /* + * If structure checks up until now have failed, it's likely that + * checking what pages have been missed will result in oodles of + * extraneous error messages being EPRINTed. Skip to the end + * if this is the case; we're going to be printing at least one + * error anyway, and probably all the more salient ones. + */ + if (ret != 0 || isbad == 1) + goto err; + + /* + * Make sure no page has been missed and that no page is still marked + * "all zeroes" unless we are looking at unused hash bucket pages or + * pagesoff the end of database. + */ + for (i = 0; i < vdp->last_pgno + 1; i++) { + if ((ret = __db_vrfy_getpageinfo(vdp, i, &pip)) != 0) + goto err; + if ((ret = __db_vrfy_pgset_get(pgset, + vdp->thread_info, vdp->txn, i, &p)) != 0) + goto err; + if (pip->type == P_OVERFLOW) { + if ((u_int32_t)p != pip->refcount) { + EPRINT((env, DB_STR_A("0533", + "Page %lu: overflow refcount %lu, referenced %lu times", + "%lu %lu %lu"), (u_long)i, + (u_long)pip->refcount, (u_long)p)); + isbad = 1; + } + } else if (p == 0 && +#ifndef HAVE_FTRUNCATE + !(i > vdp->meta_last_pgno && + (F_ISSET(pip, VRFY_IS_ALLZEROES) || pip->type == P_HASH)) && +#endif + !(dbp->type == DB_HASH && + (pip->type == P_HASH || pip->type == P_INVALID))) { + /* + * It is OK for unreferenced hash buckets to be + * marked invalid and unreferenced. + */ + EPRINT((env, DB_STR_A("0534", + "Page %lu: unreferenced page", "%lu"), (u_long)i)); + isbad = 1; + } + + if (F_ISSET(pip, VRFY_IS_ALLZEROES) +#ifndef HAVE_FTRUNCATE + && i <= vdp->meta_last_pgno +#endif + ) { + EPRINT((env, DB_STR_A("0535", + "Page %lu: totally zeroed page", "%lu"), + (u_long)i)); + isbad = 1; + } + if ((ret = __db_vrfy_putpageinfo(env, vdp, pip)) != 0) + goto err; + pip = NULL; + } + +err: if (pip != NULL) + (void)__db_vrfy_putpageinfo(env, vdp, pip); + + return ((isbad == 1 && ret == 0) ? DB_VERIFY_BAD : ret); +} + +/* + * __db_is_valid_magicno + */ +static int +__db_is_valid_magicno(magic, typep) + u_int32_t magic; + DBTYPE *typep; +{ + switch (magic) { + case DB_BTREEMAGIC: + *typep = DB_BTREE; + return (1); + case DB_HASHMAGIC: + *typep = DB_HASH; + return (1); + case DB_HEAPMAGIC: + *typep = DB_HEAP; + return (1); + case DB_QAMMAGIC: + *typep = DB_QUEUE; + return (1); + default: + break; + } + *typep = DB_UNKNOWN; + return (0); +} + +/* + * __db_vrfy_common -- + * Verify info common to all page types. + * + * PUBLIC: int __db_vrfy_common + * PUBLIC: __P((DB *, VRFY_DBINFO *, PAGE *, db_pgno_t, u_int32_t)); + */ +int +__db_vrfy_common(dbp, vdp, h, pgno, flags) + DB *dbp; + VRFY_DBINFO *vdp; + PAGE *h; + db_pgno_t pgno; + u_int32_t flags; +{ + ENV *env; + VRFY_PAGEINFO *pip; + int ret, t_ret; + u_int8_t *p; + + env = dbp->env; + + if ((ret = __db_vrfy_getpageinfo(vdp, pgno, &pip)) != 0) + return (ret); + + pip->pgno = pgno; + F_CLR(pip, VRFY_IS_ALLZEROES); + + /* + * Hash expands the table by leaving some pages between the + * old last and the new last totally zeroed. These pages may + * not be all zero if they were used, freed and then reallocated. + * + * Queue will create sparse files if sparse record numbers are used. + */ + if (pgno != 0 && PGNO(h) == 0) { + F_SET(pip, VRFY_IS_ALLZEROES); + for (p = (u_int8_t *)h; p < (u_int8_t *)h + dbp->pgsize; p++) + if (*p != 0) { + F_CLR(pip, VRFY_IS_ALLZEROES); + break; + } + /* + * Mark it as a hash, and we'll + * check that that makes sense structurally later. + * (The queue verification doesn't care, since queues + * don't really have much in the way of structure.) + */ + if (dbp->type != DB_HEAP) + pip->type = P_HASH; + ret = 0; + goto err; /* well, not really an err. */ + } + + if (PGNO(h) != pgno) { + EPRINT((env, DB_STR_A("0536", "Page %lu: bad page number %lu", + "%lu %lu"), (u_long)pgno, (u_long)h->pgno)); + ret = DB_VERIFY_BAD; + } + + switch (h->type) { + case P_INVALID: /* Order matches ordinal value. */ + case P_HASH_UNSORTED: + case P_IBTREE: + case P_IRECNO: + case P_LBTREE: + case P_LRECNO: + case P_OVERFLOW: + case P_HASHMETA: + case P_BTREEMETA: + case P_QAMMETA: + case P_QAMDATA: + case P_LDUP: + case P_HASH: + case P_HEAP: + case P_IHEAP: + case P_HEAPMETA: + break; + default: + EPRINT((env, DB_STR_A("0537", "Page %lu: bad page type %lu", + "%lu %lu"), (u_long)pgno, (u_long)h->type)); + ret = DB_VERIFY_BAD; + } + pip->type = h->type; + +err: if ((t_ret = __db_vrfy_putpageinfo(env, vdp, pip)) != 0 && ret == 0) + ret = t_ret; + + return (ret); +} + +/* + * __db_vrfy_invalid -- + * Verify P_INVALID page. + * (Yes, there's not much to do here.) + */ +static int +__db_vrfy_invalid(dbp, vdp, h, pgno, flags) + DB *dbp; + VRFY_DBINFO *vdp; + PAGE *h; + db_pgno_t pgno; + u_int32_t flags; +{ + ENV *env; + VRFY_PAGEINFO *pip; + int ret, t_ret; + + env = dbp->env; + + if ((ret = __db_vrfy_getpageinfo(vdp, pgno, &pip)) != 0) + return (ret); + pip->next_pgno = pip->prev_pgno = 0; + + if (!IS_VALID_PGNO(NEXT_PGNO(h))) { + EPRINT((env, DB_STR_A("0538", "Page %lu: invalid next_pgno %lu", + "%lu %lu"), (u_long)pgno, (u_long)NEXT_PGNO(h))); + ret = DB_VERIFY_BAD; + } else + pip->next_pgno = NEXT_PGNO(h); + + if ((t_ret = __db_vrfy_putpageinfo(env, vdp, pip)) != 0 && ret == 0) + ret = t_ret; + return (ret); +} + +/* + * __db_vrfy_datapage -- + * Verify elements common to data pages (P_HASH, P_LBTREE, + * P_IBTREE, P_IRECNO, P_LRECNO, P_OVERFLOW, P_DUPLICATE)--i.e., + * those defined in the PAGE structure. + * + * Called from each of the per-page routines, after the + * all-page-type-common elements of pip have been verified and filled + * in. + * + * PUBLIC: int __db_vrfy_datapage + * PUBLIC: __P((DB *, VRFY_DBINFO *, PAGE *, db_pgno_t, u_int32_t)); + */ +int +__db_vrfy_datapage(dbp, vdp, h, pgno, flags) + DB *dbp; + VRFY_DBINFO *vdp; + PAGE *h; + db_pgno_t pgno; + u_int32_t flags; +{ + ENV *env; + VRFY_PAGEINFO *pip; + u_int32_t smallest_entry; + int isbad, ret, t_ret; + + env = dbp->env; + + if ((ret = __db_vrfy_getpageinfo(vdp, pgno, &pip)) != 0) + return (ret); + isbad = 0; + + /* + * prev_pgno and next_pgno: store for inter-page checks, + * verify that they point to actual pages and not to self. + * + * !!! + * Internal btree pages, as well as heap pages, do not maintain these + * fields (indeed, they overload them). Skip. + */ + if (TYPE(h) != P_IBTREE && + TYPE(h) != P_IRECNO && TYPE(h) != P_HEAP && TYPE(h) != P_IHEAP) { + if (!IS_VALID_PGNO(PREV_PGNO(h)) || PREV_PGNO(h) == pip->pgno) { + isbad = 1; + EPRINT((env, DB_STR_A("0539", + "Page %lu: invalid prev_pgno %lu", "%lu %lu"), + (u_long)pip->pgno, (u_long)PREV_PGNO(h))); + } + if (!IS_VALID_PGNO(NEXT_PGNO(h)) || NEXT_PGNO(h) == pip->pgno) { + isbad = 1; + EPRINT((env, DB_STR_A("0540", + "Page %lu: invalid next_pgno %lu", "%lu %lu"), + (u_long)pip->pgno, (u_long)NEXT_PGNO(h))); + } + pip->prev_pgno = PREV_PGNO(h); + pip->next_pgno = NEXT_PGNO(h); + } + + /* + * Verify the number of entries on the page: there's no good way to + * determine if this is accurate. The best we can do is verify that + * it's not more than can, in theory, fit on the page. Then, we make + * sure there are at least this many valid elements in inp[], and + * hope the test catches most cases. + */ + switch (TYPE(h)) { + case P_HASH_UNSORTED: + case P_HASH: + smallest_entry = HKEYDATA_PSIZE(0); + break; + case P_HEAP: + smallest_entry = sizeof(HEAPHDR) + sizeof(db_indx_t); + break; + case P_IHEAP: + /* Really high_pgno. */ + pip->prev_pgno = PREV_PGNO(h); + smallest_entry = 0; + break; + case P_IBTREE: + smallest_entry = BINTERNAL_PSIZE(0); + break; + case P_IRECNO: + smallest_entry = RINTERNAL_PSIZE; + break; + case P_LBTREE: + case P_LDUP: + case P_LRECNO: + smallest_entry = BKEYDATA_PSIZE(0); + break; + default: + smallest_entry = 0; + break; + } + if (smallest_entry * NUM_ENT(h) / 2 > dbp->pgsize) { + isbad = 1; + EPRINT((env, DB_STR_A("0541", + "Page %lu: too many entries: %lu", + "%lu %lu"), (u_long)pgno, (u_long)NUM_ENT(h))); + } + + if (TYPE(h) != P_OVERFLOW) + pip->entries = NUM_ENT(h); + + /* + * btree level. Should be zero unless we're a btree; + * if we are a btree, should be between LEAFLEVEL and MAXBTREELEVEL, + * and we need to save it off. + */ + switch (TYPE(h)) { + case P_IBTREE: + case P_IRECNO: + if (LEVEL(h) < LEAFLEVEL + 1) { + isbad = 1; + EPRINT((env, DB_STR_A("0542", + "Page %lu: bad btree level %lu", "%lu %lu"), + (u_long)pgno, (u_long)LEVEL(h))); + } + pip->bt_level = LEVEL(h); + break; + case P_LBTREE: + case P_LDUP: + case P_LRECNO: + if (LEVEL(h) != LEAFLEVEL) { + isbad = 1; + EPRINT((env, DB_STR_A("0543", + "Page %lu: btree leaf page has incorrect level %lu", + "%lu %lu"), (u_long)pgno, (u_long)LEVEL(h))); + } + break; + default: + if (LEVEL(h) != 0) { + isbad = 1; + EPRINT((env, DB_STR_A("0544", + "Page %lu: nonzero level %lu in non-btree database", + "%lu %lu"), (u_long)pgno, (u_long)LEVEL(h))); + } + break; + } + + /* + * Even though inp[] occurs in all PAGEs, we look at it in the + * access-method-specific code, since btree and hash treat + * item lengths very differently, and one of the most important + * things we want to verify is that the data--as specified + * by offset and length--cover the right part of the page + * without overlaps, gaps, or violations of the page boundary. + */ + if ((t_ret = __db_vrfy_putpageinfo(env, vdp, pip)) != 0 && ret == 0) + ret = t_ret; + + return ((ret == 0 && isbad == 1) ? DB_VERIFY_BAD : ret); +} + +/* + * __db_vrfy_meta -- + * Verify the access-method common parts of a meta page, using + * normal mpool routines. + * + * PUBLIC: int __db_vrfy_meta + * PUBLIC: __P((DB *, VRFY_DBINFO *, DBMETA *, db_pgno_t, u_int32_t)); + */ +int +__db_vrfy_meta(dbp, vdp, meta, pgno, flags) + DB *dbp; + VRFY_DBINFO *vdp; + DBMETA *meta; + db_pgno_t pgno; + u_int32_t flags; +{ + DBTYPE dbtype, magtype; + ENV *env; + VRFY_PAGEINFO *pip; + int isbad, ret, t_ret; + + isbad = 0; + env = dbp->env; + + if ((ret = __db_vrfy_getpageinfo(vdp, pgno, &pip)) != 0) + return (ret); + + /* type plausible for a meta page */ + switch (meta->type) { + case P_BTREEMETA: + dbtype = DB_BTREE; + break; + case P_HASHMETA: + dbtype = DB_HASH; + break; + case P_HEAPMETA: + dbtype = DB_HEAP; + break; + case P_QAMMETA: + dbtype = DB_QUEUE; + break; + default: + ret = __db_unknown_path(env, "__db_vrfy_meta"); + goto err; + } + + /* magic number valid */ + if (!__db_is_valid_magicno(meta->magic, &magtype)) { + isbad = 1; + EPRINT((env, DB_STR_A("0545", "Page %lu: invalid magic number", + "%lu"), (u_long)pgno)); + } + if (magtype != dbtype) { + isbad = 1; + EPRINT((env, DB_STR_A("0546", + "Page %lu: magic number does not match database type", + "%lu"), (u_long)pgno)); + } + + /* version */ + if ((dbtype == DB_BTREE && + (meta->version > DB_BTREEVERSION || + meta->version < DB_BTREEOLDVER)) || + (dbtype == DB_HASH && + (meta->version > DB_HASHVERSION || + meta->version < DB_HASHOLDVER)) || + (dbtype == DB_HEAP && + (meta->version > DB_HEAPVERSION || + meta->version < DB_HEAPOLDVER)) || + (dbtype == DB_QUEUE && + (meta->version > DB_QAMVERSION || + meta->version < DB_QAMOLDVER))) { + isbad = 1; + EPRINT((env, DB_STR_A("0547", + "Page %lu: unsupported database version %lu; extraneous errors may result", + "%lu %lu"), (u_long)pgno, (u_long)meta->version)); + } + + /* pagesize */ + if (meta->pagesize != dbp->pgsize) { + isbad = 1; + EPRINT((env, DB_STR_A("0548", "Page %lu: invalid pagesize %lu", + "%lu %lu"), (u_long)pgno, (u_long)meta->pagesize)); + } + + /* Flags */ + if (meta->metaflags != 0) { + if (FLD_ISSET(meta->metaflags, + ~(DBMETA_CHKSUM|DBMETA_PART_RANGE|DBMETA_PART_CALLBACK))) { + isbad = 1; + EPRINT((env, DB_STR_A("0549", + "Page %lu: bad meta-data flags value %#lx", + "%lu %#lx"), (u_long)PGNO_BASE_MD, + (u_long)meta->metaflags)); + } + if (FLD_ISSET(meta->metaflags, DBMETA_CHKSUM)) + F_SET(pip, VRFY_HAS_CHKSUM); + if (FLD_ISSET(meta->metaflags, DBMETA_PART_RANGE)) + F_SET(pip, VRFY_HAS_PART_RANGE); + if (FLD_ISSET(meta->metaflags, DBMETA_PART_CALLBACK)) + F_SET(pip, VRFY_HAS_PART_CALLBACK); + } + + /* + * Free list. + * + * If this is not the main, master-database meta page, it + * should not have a free list. + */ + if (pgno != PGNO_BASE_MD && meta->free != PGNO_INVALID) { + isbad = 1; + EPRINT((env, DB_STR_A("0550", + "Page %lu: nonempty free list on subdatabase metadata page", + "%lu"), (u_long)pgno)); + } + + /* Can correctly be PGNO_INVALID--that's just the end of the list. */ + if (IS_VALID_PGNO(meta->free)) + pip->free = meta->free; + else { + isbad = 1; + EPRINT((env, DB_STR_A("0551", + "Page %lu: nonsensical free list pgno %lu", "%lu %lu"), + (u_long)pgno, (u_long)meta->free)); + } + + /* + * Check that the meta page agrees with what we got from mpool. + * If we don't have FTRUNCATE then mpool could include some + * zeroed pages at the end of the file, we assume the meta page + * is correct. Queue does not update the meta page's last_pgno. + * + * We have seen one false positive after a failure while rolling the log + * forward, last_pgno was updated and the file had not yet been + * extended. [#18418] + */ + if (pgno == PGNO_BASE_MD && + dbtype != DB_QUEUE && meta->last_pgno != vdp->last_pgno) { +#ifdef HAVE_FTRUNCATE + isbad = 1; + EPRINT((env, DB_STR_A("0552", + "Page %lu: last_pgno is not correct: %lu != %lu", + "%lu %lu %lu"), (u_long)pgno, + (u_long)meta->last_pgno, (u_long)vdp->last_pgno)); +#endif + vdp->meta_last_pgno = meta->last_pgno; + } + + /* + * We have now verified the common fields of the metadata page. + * Clear the flag that told us they had been incompletely checked. + */ + F_CLR(pip, VRFY_INCOMPLETE); + +err: if ((t_ret = __db_vrfy_putpageinfo(env, vdp, pip)) != 0 && ret == 0) + ret = t_ret; + + return ((ret == 0 && isbad == 1) ? DB_VERIFY_BAD : ret); +} + +/* + * __db_vrfy_freelist -- + * Walk free list, checking off pages and verifying absence of + * loops. + */ +static int +__db_vrfy_freelist(dbp, vdp, meta, flags) + DB *dbp; + VRFY_DBINFO *vdp; + db_pgno_t meta; + u_int32_t flags; +{ + DB *pgset; + ENV *env; + VRFY_PAGEINFO *pip; + db_pgno_t cur_pgno, next_pgno; + int p, ret, t_ret; + + env = dbp->env; + pgset = vdp->pgset; + DB_ASSERT(env, pgset != NULL); + + if ((ret = __db_vrfy_getpageinfo(vdp, meta, &pip)) != 0) + return (ret); + for (next_pgno = pip->free; + next_pgno != PGNO_INVALID; next_pgno = pip->next_pgno) { + cur_pgno = pip->pgno; + if ((t_ret = __db_vrfy_putpageinfo(env, vdp, pip)) != 0) + return (t_ret); + + /* This shouldn't happen, but just in case. */ + if (!IS_VALID_PGNO(next_pgno)) { + EPRINT((env, DB_STR_A("0553", + "Page %lu: invalid next_pgno %lu on free list page", + "%lu %lu"), (u_long)cur_pgno, (u_long)next_pgno)); + return (DB_VERIFY_BAD); + } + + if (next_pgno > vdp->last_pgno) { + EPRINT((env, DB_STR_A("0713", + "Page %lu: page %lu on free list beyond last_pgno %lu", + "%lu %lu %lu"), (u_long)cur_pgno, + (u_long)next_pgno, (u_long)vdp->last_pgno)); + ret = DB_VERIFY_BAD; + } + /* Detect cycles. */ + if ((t_ret = __db_vrfy_pgset_get(pgset, + vdp->thread_info, vdp->txn, next_pgno, &p)) != 0) + return (t_ret); + if (p != 0) { + EPRINT((env, DB_STR_A("0554", + "Page %lu: page %lu encountered a second time on free list", + "%lu %lu"), (u_long)cur_pgno, (u_long)next_pgno)); + return (DB_VERIFY_BAD); + } + if ((t_ret = __db_vrfy_pgset_inc(pgset, + vdp->thread_info, vdp->txn, next_pgno)) != 0) + return (t_ret); + + if ((t_ret = __db_vrfy_getpageinfo(vdp, next_pgno, &pip)) != 0) + return (t_ret); + + if (pip->type != P_INVALID) { + EPRINT((env, DB_STR_A("0555", + "Page %lu: non-invalid page %lu on free list", + "%lu %lu"), (u_long)cur_pgno, (u_long)next_pgno)); + ret = DB_VERIFY_BAD; /* unsafe to continue */ + break; + } + } + + if ((t_ret = __db_vrfy_putpageinfo(env, vdp, pip)) != 0 && ret == 0) + ret = t_ret; + return (ret); +} + +/* + * __db_vrfy_subdbs -- + * Walk the known-safe master database of subdbs with a cursor, + * verifying the structure of each subdatabase we encounter. + */ +static int +__db_vrfy_subdbs(dbp, vdp, dbname, flags) + DB *dbp; + VRFY_DBINFO *vdp; + const char *dbname; + u_int32_t flags; +{ + DB *mdbp; + DBC *dbc; + DBT key, data; + ENV *env; + VRFY_PAGEINFO *pip; + db_pgno_t meta_pgno; + int ret, t_ret, isbad; + u_int8_t type; + + isbad = 0; + dbc = NULL; + env = dbp->env; + + if ((ret = __db_master_open(dbp, + vdp->thread_info, NULL, dbname, DB_RDONLY, 0, &mdbp)) != 0) + return (ret); + + if ((ret = __db_cursor_int(mdbp, NULL, + vdp->txn, DB_BTREE, PGNO_INVALID, 0, DB_LOCK_INVALIDID, &dbc)) != 0) + goto err; + + memset(&key, 0, sizeof(key)); + memset(&data, 0, sizeof(data)); + while ((ret = __dbc_get(dbc, &key, &data, DB_NEXT)) == 0) { + if (data.size != sizeof(db_pgno_t)) { + EPRINT((env, DB_STR("0556", + "Subdatabase entry not page-number size"))); + isbad = 1; + goto err; + } + memcpy(&meta_pgno, data.data, data.size); + /* + * Subdatabase meta pgnos are stored in network byte + * order for cross-endian compatibility. Swap if appropriate. + */ + DB_NTOHL_SWAP(env, &meta_pgno); + if (meta_pgno == PGNO_INVALID || meta_pgno > vdp->last_pgno) { + EPRINT((env, DB_STR_A("0557", + "Subdatabase entry references invalid page %lu", + "%lu"), (u_long)meta_pgno)); + isbad = 1; + goto err; + } + if ((ret = __db_vrfy_getpageinfo(vdp, meta_pgno, &pip)) != 0) + goto err; + type = pip->type; + if ((ret = __db_vrfy_putpageinfo(env, vdp, pip)) != 0) + goto err; + switch (type) { + case P_BTREEMETA: + if ((ret = __bam_vrfy_structure( + dbp, vdp, meta_pgno, NULL, NULL, flags)) != 0) { + if (ret == DB_VERIFY_BAD) + isbad = 1; + else + goto err; + } + break; + case P_HASHMETA: + if ((ret = __ham_vrfy_structure( + dbp, vdp, meta_pgno, flags)) != 0) { + if (ret == DB_VERIFY_BAD) + isbad = 1; + else + goto err; + } + break; + case P_QAMMETA: + default: + EPRINT((env, DB_STR_A("0558", + "Subdatabase entry references page %lu of invalid type %lu", + "%lu %lu"), (u_long)meta_pgno, (u_long)type)); + ret = DB_VERIFY_BAD; + goto err; + } + } + + if (ret == DB_NOTFOUND) + ret = 0; + +err: if (dbc != NULL && (t_ret = __dbc_close(dbc)) != 0 && ret == 0) + ret = t_ret; + + if ((t_ret = __db_close(mdbp, NULL, 0)) != 0 && ret == 0) + ret = t_ret; + + return ((ret == 0 && isbad == 1) ? DB_VERIFY_BAD : ret); +} + +/* + * __db_vrfy_struct_feedback -- + * Provide feedback during top-down database structure traversal. + * (See comment at the beginning of __db_vrfy_structure.) + * + * PUBLIC: void __db_vrfy_struct_feedback __P((DB *, VRFY_DBINFO *)); + */ +void +__db_vrfy_struct_feedback(dbp, vdp) + DB *dbp; + VRFY_DBINFO *vdp; +{ + int progress; + + if (dbp->db_feedback == NULL) + return; + + if (vdp->pgs_remaining > 0) + vdp->pgs_remaining--; + + /* Don't allow a feedback call of 100 until we're really done. */ + progress = 100 - (int)(vdp->pgs_remaining * 50 / (vdp->last_pgno + 1)); + dbp->db_feedback(dbp, DB_VERIFY, progress == 100 ? 99 : progress); +} + +/* + * __db_vrfy_orderchkonly -- + * Do an sort-order/hashing check on a known-otherwise-good subdb. + */ +static int +__db_vrfy_orderchkonly(dbp, vdp, name, subdb, flags) + DB *dbp; + VRFY_DBINFO *vdp; + const char *name, *subdb; + u_int32_t flags; +{ + BTMETA *btmeta; + DB *mdbp, *pgset; + DBC *pgsc; + DBT key, data; + DB_MPOOLFILE *mpf; + ENV *env; + HASH *h_internal; + HMETA *hmeta; + PAGE *h, *currpg; + db_pgno_t meta_pgno, p, pgno; + u_int32_t bucket; + int t_ret, ret; + + pgset = NULL; + pgsc = NULL; + env = dbp->env; + mpf = dbp->mpf; + currpg = h = NULL; + + LF_CLR(DB_NOORDERCHK); + + /* Open the master database and get the meta_pgno for the subdb. */ + if ((ret = __db_master_open(dbp, + vdp->thread_info, NULL, name, DB_RDONLY, 0, &mdbp)) != 0) + goto err; + + DB_INIT_DBT(key, subdb, strlen(subdb)); + memset(&data, 0, sizeof(data)); + if ((ret = __db_get(mdbp, + vdp->thread_info, NULL, &key, &data, 0)) != 0) { + if (ret == DB_NOTFOUND) + ret = ENOENT; + goto err; + } + + if (data.size != sizeof(db_pgno_t)) { + EPRINT((env, DB_STR("0559", + "Subdatabase entry of invalid size"))); + ret = DB_VERIFY_BAD; + goto err; + } + + memcpy(&meta_pgno, data.data, data.size); + + /* + * Subdatabase meta pgnos are stored in network byte + * order for cross-endian compatibility. Swap if appropriate. + */ + DB_NTOHL_SWAP(env, &meta_pgno); + + if ((ret = __memp_fget(mpf, + &meta_pgno, vdp->thread_info, NULL, 0, &h)) != 0) + goto err; + + if ((ret = __db_vrfy_pgset(env, + vdp->thread_info, dbp->pgsize, &pgset)) != 0) + goto err; + + switch (TYPE(h)) { + case P_BTREEMETA: + btmeta = (BTMETA *)h; + if (F_ISSET(&btmeta->dbmeta, BTM_RECNO)) { + /* Recnos have no order to check. */ + ret = 0; + goto err; + } + if ((ret = + __db_meta2pgset(dbp, vdp, meta_pgno, flags, pgset)) != 0) + goto err; + if ((ret = __db_cursor_int(pgset, NULL, vdp->txn, dbp->type, + PGNO_INVALID, 0, DB_LOCK_INVALIDID, &pgsc)) != 0) + goto err; + while ((ret = __db_vrfy_pgset_next(pgsc, &p)) == 0) { + if ((ret = __memp_fget(mpf, &p, + vdp->thread_info, NULL, 0, &currpg)) != 0) + goto err; + if ((ret = __bam_vrfy_itemorder(dbp, NULL, + vdp->thread_info, currpg, p, NUM_ENT(currpg), 1, + F_ISSET(&btmeta->dbmeta, BTM_DUP), flags)) != 0) + goto err; + if ((ret = __memp_fput(mpf, + vdp->thread_info, currpg, dbp->priority)) != 0) + goto err; + currpg = NULL; + } + + /* + * The normal exit condition for the loop above is DB_NOTFOUND. + * If we see that, zero it and continue on to cleanup. + * Otherwise, it's a real error and will be returned. + */ + if (ret == DB_NOTFOUND) + ret = 0; + break; + case P_HASHMETA: + hmeta = (HMETA *)h; + h_internal = (HASH *)dbp->h_internal; + /* + * Make sure h_charkey is right. + */ + if (h_internal == NULL) { + EPRINT((env, DB_STR_A("0560", + "Page %lu: DB->h_internal field is NULL", "%lu"), + (u_long)meta_pgno)); + ret = DB_VERIFY_BAD; + goto err; + } + if (h_internal->h_hash == NULL) + h_internal->h_hash = hmeta->dbmeta.version < 5 + ? __ham_func4 : __ham_func5; + if (hmeta->h_charkey != + h_internal->h_hash(dbp, CHARKEY, sizeof(CHARKEY))) { + EPRINT((env, DB_STR_A("0561", + "Page %lu: incorrect hash function for database", + "%lu"), (u_long)meta_pgno)); + ret = DB_VERIFY_BAD; + goto err; + } + + /* + * Foreach bucket, verify hashing on each page in the + * corresponding chain of pages. + */ + if ((ret = __db_cursor_int(dbp, NULL, vdp->txn, dbp->type, + PGNO_INVALID, 0, DB_LOCK_INVALIDID, &pgsc)) != 0) + goto err; + for (bucket = 0; bucket <= hmeta->max_bucket; bucket++) { + pgno = BS_TO_PAGE(bucket, hmeta->spares); + while (pgno != PGNO_INVALID) { + if ((ret = __memp_fget(mpf, &pgno, + vdp->thread_info, NULL, 0, &currpg)) != 0) + goto err; + if ((ret = __ham_vrfy_hashing(pgsc, + NUM_ENT(currpg), hmeta, bucket, pgno, + flags, h_internal->h_hash)) != 0) + goto err; + pgno = NEXT_PGNO(currpg); + if ((ret = __memp_fput(mpf, vdp->thread_info, + currpg, dbp->priority)) != 0) + goto err; + currpg = NULL; + } + } + break; + default: + EPRINT((env, DB_STR_A("0562", + "Page %lu: database metapage of bad type %lu", + "%lu %lu"), (u_long)meta_pgno, (u_long)TYPE(h))); + ret = DB_VERIFY_BAD; + break; + } + +err: if (pgsc != NULL && (t_ret = __dbc_close(pgsc)) != 0 && ret == 0) + ret = t_ret; + if (pgset != NULL && + (t_ret = __db_close(pgset, NULL, 0)) != 0 && ret == 0) + ret = t_ret; + if (h != NULL && (t_ret = __memp_fput(mpf, + vdp->thread_info, h, dbp->priority)) != 0) + ret = t_ret; + if (currpg != NULL && + (t_ret = __memp_fput(mpf, + vdp->thread_info, currpg, dbp->priority)) != 0) + ret = t_ret; + if ((t_ret = __db_close(mdbp, NULL, 0)) != 0) + ret = t_ret; + return (ret); +} + +/* + * __db_salvage_pg -- + * Walk through a page, salvaging all likely or plausible (w/ + * DB_AGGRESSIVE) key/data pairs and marking seen pages in vdp. + * + * PUBLIC: int __db_salvage_pg __P((DB *, VRFY_DBINFO *, db_pgno_t, + * PUBLIC: PAGE *, void *, int (*)(void *, const void *), u_int32_t)); + */ +int +__db_salvage_pg(dbp, vdp, pgno, h, handle, callback, flags) + DB *dbp; + VRFY_DBINFO *vdp; + db_pgno_t pgno; + PAGE *h; + void *handle; + int (*callback) __P((void *, const void *)); + u_int32_t flags; +{ + ENV *env; + VRFY_PAGEINFO *pip; + int keyflag, ret, t_ret; + + env = dbp->env; + DB_ASSERT(env, LF_ISSET(DB_SALVAGE)); + + /* + * !!! + * We dump record numbers when salvaging Queue databases, but not for + * immutable Recno databases. The problem is we can't figure out the + * record number from the database page in the Recno case, while the + * offset in the file is sufficient for Queue. + */ + keyflag = 0; + + /* If we got this page in the subdb pass, we can safely skip it. */ + if (__db_salvage_isdone(vdp, pgno)) + return (0); + + switch (TYPE(h)) { + case P_BTREEMETA: + ret = __bam_vrfy_meta(dbp, vdp, (BTMETA *)h, pgno, flags); + break; + case P_HASH: + case P_HASH_UNSORTED: + case P_HEAP: + case P_LBTREE: + case P_QAMDATA: + return (__db_salvage_leaf(dbp, + vdp, pgno, h, handle, callback, flags)); + case P_HASHMETA: + ret = __ham_vrfy_meta(dbp, vdp, (HMETA *)h, pgno, flags); + break; + case P_HEAPMETA: + ret = __heap_vrfy_meta(dbp, vdp, (HEAPMETA *)h, pgno, flags); + break; + case P_IBTREE: + /* + * We need to mark any overflow keys on internal pages as seen, + * so we don't print them out in __db_salvage_unknowns. But if + * we're an upgraded database, a P_LBTREE page may very well + * have a reference to the same overflow pages (this practice + * stopped somewhere around db4.5). To give P_LBTREEs a chance + * to print out any keys on shared pages, mark the page now and + * deal with it at the end. + */ + return (__db_salvage_markneeded(vdp, pgno, SALVAGE_IBTREE)); + case P_IHEAP: + /* + * There's nothing to salvage from heap region pages. Just mark + * that we've seen the page. + */ + return (__db_salvage_markdone(vdp, pgno)); + case P_LDUP: + return (__db_salvage_markneeded(vdp, pgno, SALVAGE_LDUP)); + case P_LRECNO: + /* + * Recno leaves are tough, because the leaf could be (1) a dup + * page, or it could be (2) a regular database leaf page. + * Fortunately, RECNO databases are not allowed to have + * duplicates. + * + * If there are no subdatabases, dump the page immediately if + * it's a leaf in a RECNO database, otherwise wait and hopefully + * it will be dumped by the leaf page that refers to it, + * otherwise we'll get it with the unknowns. + * + * If there are subdatabases, there might be mixed types and + * dbp->type can't be trusted. We'll only get here after + * salvaging each database, though, so salvaging this page + * immediately isn't important. If this page is a dup, it might + * get salvaged later on, otherwise the unknowns pass will pick + * it up. Note that SALVAGE_HASSUBDBS won't get set if we're + * salvaging aggressively. + * + * If we're salvaging aggressively, we don't know whether or not + * there's subdatabases, so we wait on all recno pages. + */ + if (!LF_ISSET(DB_AGGRESSIVE) && + !F_ISSET(vdp, SALVAGE_HASSUBDBS) && dbp->type == DB_RECNO) + return (__db_salvage_leaf(dbp, + vdp, pgno, h, handle, callback, flags)); + return (__db_salvage_markneeded(vdp, pgno, SALVAGE_LRECNODUP)); + case P_OVERFLOW: + return (__db_salvage_markneeded(vdp, pgno, SALVAGE_OVERFLOW)); + case P_QAMMETA: + keyflag = 1; + ret = __qam_vrfy_meta(dbp, vdp, (QMETA *)h, pgno, flags); + break; + case P_INVALID: + case P_IRECNO: + case __P_DUPLICATE: + default: + /* + * There's no need to display an error, the page type was + * already checked and reported on. + */ + return (0); + } + if (ret != 0) + return (ret); + + /* + * We have to display the dump header if it's a metadata page. It's + * our last chance as the page was marked "seen" in the vrfy routine, + * and we won't see the page again. We don't display headers for + * the first database in a multi-database file, that database simply + * contains a list of subdatabases. + */ + if ((ret = __db_vrfy_getpageinfo(vdp, pgno, &pip)) != 0) + return (ret); + if (!F_ISSET(pip, VRFY_HAS_SUBDBS) && !LF_ISSET(DB_VERIFY_PARTITION)) + ret = __db_prheader( + dbp, NULL, 0, keyflag, handle, callback, vdp, pgno); + if ((t_ret = __db_vrfy_putpageinfo(env, vdp, pip)) != 0 && ret == 0) + ret = t_ret; + return (ret); +} + +/* + * __db_salvage_leaf -- + * Walk through a leaf, salvaging all likely key/data pairs and marking + * seen pages in vdp. + * + * PUBLIC: int __db_salvage_leaf __P((DB *, VRFY_DBINFO *, db_pgno_t, + * PUBLIC: PAGE *, void *, int (*)(void *, const void *), u_int32_t)); + */ +int +__db_salvage_leaf(dbp, vdp, pgno, h, handle, callback, flags) + DB *dbp; + VRFY_DBINFO *vdp; + db_pgno_t pgno; + PAGE *h; + void *handle; + int (*callback) __P((void *, const void *)); + u_int32_t flags; +{ + ENV *env; + + env = dbp->env; + DB_ASSERT(env, LF_ISSET(DB_SALVAGE)); + + /* If we got this page in the subdb pass, we can safely skip it. */ + if (__db_salvage_isdone(vdp, pgno)) + return (0); + + switch (TYPE(h)) { + case P_HASH_UNSORTED: + case P_HASH: + return (__ham_salvage(dbp, vdp, + pgno, h, handle, callback, flags)); + case P_HEAP: + return (__heap_salvage(dbp, vdp, + pgno, h, handle, callback, flags)); + case P_LBTREE: + case P_LRECNO: + return (__bam_salvage(dbp, vdp, + pgno, TYPE(h), h, handle, callback, NULL, flags)); + case P_QAMDATA: + return (__qam_salvage(dbp, vdp, + pgno, h, handle, callback, flags)); + default: + /* + * There's no need to display an error, the page type was + * already checked and reported on. + */ + return (0); + } +} + +/* + * __db_salvage_unknowns -- + * Walk through the salvager database, printing with key "UNKNOWN" + * any pages we haven't dealt with. + */ +static int +__db_salvage_unknowns(dbp, vdp, handle, callback, flags) + DB *dbp; + VRFY_DBINFO *vdp; + void *handle; + int (*callback) __P((void *, const void *)); + u_int32_t flags; +{ + DBC *dbc; + DBT unkdbt, key, *dbt; + DB_MPOOLFILE *mpf; + ENV *env; + PAGE *h; + db_pgno_t pgno; + u_int32_t pgtype, ovfl_bufsz, tmp_flags; + int ret, t_ret; + void *ovflbuf; + + dbc = NULL; + env = dbp->env; + mpf = dbp->mpf; + + DB_INIT_DBT(unkdbt, "UNKNOWN", sizeof("UNKNOWN") - 1); + + if ((ret = __os_malloc(env, dbp->pgsize, &ovflbuf)) != 0) + return (ret); + ovfl_bufsz = dbp->pgsize; + + /* + * We make two passes -- in the first pass, skip SALVAGE_OVERFLOW + * pages, because they may be referenced by the standard database + * pages that we're resolving. + */ + while ((t_ret = + __db_salvage_getnext(vdp, &dbc, &pgno, &pgtype, 1)) == 0) { + if ((t_ret = __memp_fget(mpf, + &pgno, vdp->thread_info, NULL, 0, &h)) != 0) { + if (ret == 0) + ret = t_ret; + continue; + } + + dbt = NULL; + tmp_flags = 0; + switch (pgtype) { + case SALVAGE_LDUP: + case SALVAGE_LRECNODUP: + dbt = &unkdbt; + tmp_flags = DB_SA_UNKNOWNKEY; + /* FALLTHROUGH */ + case SALVAGE_IBTREE: + case SALVAGE_LBTREE: + case SALVAGE_LRECNO: + if ((t_ret = __bam_salvage( + dbp, vdp, pgno, pgtype, h, handle, + callback, dbt, tmp_flags | flags)) != 0 && ret == 0) + ret = t_ret; + break; + case SALVAGE_OVERFLOW: + DB_ASSERT(env, 0); /* Shouldn't ever happen. */ + break; + case SALVAGE_HASH: + if ((t_ret = __ham_salvage(dbp, vdp, + pgno, h, handle, callback, flags)) != 0 && ret == 0) + ret = t_ret; + break; + case SALVAGE_INVALID: + case SALVAGE_IGNORE: + default: + /* + * Shouldn't happen, but if it does, just do what the + * nice man says. + */ + DB_ASSERT(env, 0); + break; + } + if ((t_ret = __memp_fput(mpf, + vdp->thread_info, h, dbp->priority)) != 0 && ret == 0) + ret = t_ret; + } + + /* We should have reached the end of the database. */ + if (t_ret == DB_NOTFOUND) + t_ret = 0; + if (t_ret != 0 && ret == 0) + ret = t_ret; + + /* Re-open the cursor so we traverse the database again. */ + if ((t_ret = __dbc_close(dbc)) != 0 && ret == 0) + ret = t_ret; + dbc = NULL; + + /* Now, deal with any remaining overflow pages. */ + while ((t_ret = + __db_salvage_getnext(vdp, &dbc, &pgno, &pgtype, 0)) == 0) { + if ((t_ret = __memp_fget(mpf, + &pgno, vdp->thread_info, NULL, 0, &h)) != 0) { + if (ret == 0) + ret = t_ret; + continue; + } + + switch (pgtype) { + case SALVAGE_OVERFLOW: + /* + * XXX: + * This may generate multiple "UNKNOWN" keys in + * a database with no dups. What to do? + */ + if ((t_ret = __db_safe_goff(dbp, vdp, + pgno, &key, &ovflbuf, &ovfl_bufsz, flags)) != 0 || + ((vdp->type == DB_BTREE || vdp->type == DB_HASH) && + (t_ret = __db_vrfy_prdbt(&unkdbt, + 0, " ", handle, callback, 0, 0, vdp)) != 0) || + (t_ret = __db_vrfy_prdbt( + &key, 0, " ", handle, callback, 0, 0, vdp)) != 0) + if (ret == 0) + ret = t_ret; + break; + default: + DB_ASSERT(env, 0); /* Shouldn't ever happen. */ + break; + } + if ((t_ret = __memp_fput(mpf, + vdp->thread_info, h, dbp->priority)) != 0 && ret == 0) + ret = t_ret; + } + + /* We should have reached the end of the database. */ + if (t_ret == DB_NOTFOUND) + t_ret = 0; + if (t_ret != 0 && ret == 0) + ret = t_ret; + + if ((t_ret = __dbc_close(dbc)) != 0 && ret == 0) + ret = t_ret; + + __os_free(env, ovflbuf); + + return (ret); +} + +/* + * Offset of the ith inp array entry, which we can compare to the offset + * the entry stores. + */ +#define INP_OFFSET(dbp, h, i) \ + ((db_indx_t)((u_int8_t *)((P_INP(dbp,(h))) + (i)) - (u_int8_t *)(h))) + +/* + * __db_vrfy_inpitem -- + * Verify that a single entry in the inp array is sane, and update + * the high water mark and current item offset. (The former of these is + * used for state information between calls, and is required; it must + * be initialized to the pagesize before the first call.) + * + * Returns DB_VERIFY_FATAL if inp has collided with the data, + * since verification can't continue from there; returns DB_VERIFY_BAD + * if anything else is wrong. + * + * PUBLIC: int __db_vrfy_inpitem __P((DB *, PAGE *, + * PUBLIC: db_pgno_t, u_int32_t, int, u_int32_t, u_int32_t *, u_int32_t *)); + */ +int +__db_vrfy_inpitem(dbp, h, pgno, i, is_btree, flags, himarkp, offsetp) + DB *dbp; + PAGE *h; + db_pgno_t pgno; + u_int32_t i; + int is_btree; + u_int32_t flags, *himarkp, *offsetp; +{ + BKEYDATA *bk; + ENV *env; + db_indx_t *inp, offset, len; + + env = dbp->env; + + DB_ASSERT(env, himarkp != NULL); + inp = P_INP(dbp, h); + + /* + * Check that the inp array, which grows from the beginning of the + * page forward, has not collided with the data, which grow from the + * end of the page backward. + */ + if (inp + i >= (db_indx_t *)((u_int8_t *)h + *himarkp)) { + /* We've collided with the data. We need to bail. */ + EPRINT((env, DB_STR_A("0563", + "Page %lu: entries listing %lu overlaps data", + "%lu %lu"), (u_long)pgno, (u_long)i)); + return (DB_VERIFY_FATAL); + } + + offset = inp[i]; + + /* + * Check that the item offset is reasonable: it points somewhere + * after the inp array and before the end of the page. + */ + if (offset <= INP_OFFSET(dbp, h, i) || offset >= dbp->pgsize) { + EPRINT((env, DB_STR_A("0564", + "Page %lu: bad offset %lu at page index %lu", + "%lu %lu %lu"), (u_long)pgno, (u_long)offset, (u_long)i)); + return (DB_VERIFY_BAD); + } + + /* Update the high-water mark (what HOFFSET should be) */ + if (offset < *himarkp) + *himarkp = offset; + + if (is_btree) { + /* + * Check alignment; if it's unaligned, it's unsafe to + * manipulate this item. + */ + if (offset != DB_ALIGN(offset, sizeof(u_int32_t))) { + EPRINT((env, DB_STR_A("0565", + "Page %lu: unaligned offset %lu at page index %lu", + "%lu %lu %lu"), (u_long)pgno, (u_long)offset, + (u_long)i)); + return (DB_VERIFY_BAD); + } + + /* + * Check that the item length remains on-page. + */ + bk = GET_BKEYDATA(dbp, h, i); + + /* + * We need to verify the type of the item here; + * we can't simply assume that it will be one of the + * expected three. If it's not a recognizable type, + * it can't be considered to have a verifiable + * length, so it's not possible to certify it as safe. + */ + switch (B_TYPE(bk->type)) { + case B_KEYDATA: + len = bk->len; + break; + case B_DUPLICATE: + case B_OVERFLOW: + len = BOVERFLOW_SIZE; + break; + default: + EPRINT((env, DB_STR_A("0566", + "Page %lu: item %lu of unrecognizable type", + "%lu %lu"), (u_long)pgno, (u_long)i)); + return (DB_VERIFY_BAD); + } + + if ((size_t)(offset + len) > dbp->pgsize) { + EPRINT((env, DB_STR_A("0567", + "Page %lu: item %lu extends past page boundary", + "%lu %lu"), (u_long)pgno, (u_long)i)); + return (DB_VERIFY_BAD); + } + } + + if (offsetp != NULL) + *offsetp = offset; + return (0); +} + +/* + * __db_vrfy_duptype-- + * Given a page number and a set of flags to __bam_vrfy_subtree, + * verify that the dup tree type is correct--i.e., it's a recno + * if DUPSORT is not set and a btree if it is. + * + * PUBLIC: int __db_vrfy_duptype + * PUBLIC: __P((DB *, VRFY_DBINFO *, db_pgno_t, u_int32_t)); + */ +int +__db_vrfy_duptype(dbp, vdp, pgno, flags) + DB *dbp; + VRFY_DBINFO *vdp; + db_pgno_t pgno; + u_int32_t flags; +{ + ENV *env; + VRFY_PAGEINFO *pip; + int ret, isbad; + + env = dbp->env; + isbad = 0; + + if ((ret = __db_vrfy_getpageinfo(vdp, pgno, &pip)) != 0) + return (ret); + + switch (pip->type) { + case P_IBTREE: + case P_LDUP: + if (!LF_ISSET(DB_ST_DUPSORT)) { + EPRINT((env, DB_STR_A("0568", + "Page %lu: sorted duplicate set in unsorted-dup database", + "%lu"), (u_long)pgno)); + isbad = 1; + } + break; + case P_IRECNO: + case P_LRECNO: + if (LF_ISSET(DB_ST_DUPSORT)) { + EPRINT((env, DB_STR_A("0569", + "Page %lu: unsorted duplicate set in sorted-dup database", + "%lu"), (u_long)pgno)); + isbad = 1; + } + break; + default: + /* + * If the page is entirely zeroed, its pip->type will be a lie + * (we assumed it was a hash page, as they're allowed to be + * zeroed); handle this case specially. + */ + if (F_ISSET(pip, VRFY_IS_ALLZEROES)) + ZEROPG_ERR_PRINT(env, pgno, DB_STR_P("duplicate page")); + else + EPRINT((env, DB_STR_A("0570", + "Page %lu: duplicate page of inappropriate type %lu", + "%lu %lu"), (u_long)pgno, (u_long)pip->type)); + isbad = 1; + break; + } + + if ((ret = __db_vrfy_putpageinfo(env, vdp, pip)) != 0) + return (ret); + return (isbad == 1 ? DB_VERIFY_BAD : 0); +} + +/* + * __db_salvage_duptree -- + * Attempt to salvage a given duplicate tree, given its alleged root. + * + * The key that corresponds to this dup set has been passed to us + * in DBT *key. Because data items follow keys, though, it has been + * printed once already. + * + * The basic idea here is that pgno ought to be a P_LDUP, a P_LRECNO, a + * P_IBTREE, or a P_IRECNO. If it's an internal page, use the verifier + * functions to make sure it's safe; if it's not, we simply bail and the + * data will have to be printed with no key later on. if it is safe, + * recurse on each of its children. + * + * Whether or not it's safe, if it's a leaf page, __bam_salvage it. + * + * At all times, use the DB hanging off vdp to mark and check what we've + * done, so each page gets printed exactly once and we don't get caught + * in any cycles. + * + * PUBLIC: int __db_salvage_duptree __P((DB *, VRFY_DBINFO *, db_pgno_t, + * PUBLIC: DBT *, void *, int (*)(void *, const void *), u_int32_t)); + */ +int +__db_salvage_duptree(dbp, vdp, pgno, key, handle, callback, flags) + DB *dbp; + VRFY_DBINFO *vdp; + db_pgno_t pgno; + DBT *key; + void *handle; + int (*callback) __P((void *, const void *)); + u_int32_t flags; +{ + DB_MPOOLFILE *mpf; + PAGE *h; + int ret, t_ret; + + mpf = dbp->mpf; + + if (pgno == PGNO_INVALID || !IS_VALID_PGNO(pgno)) + return (DB_VERIFY_BAD); + + /* We have a plausible page. Try it. */ + if ((ret = __memp_fget(mpf, &pgno, vdp->thread_info, NULL, 0, &h)) != 0) + return (ret); + + switch (TYPE(h)) { + case P_IBTREE: + case P_IRECNO: + if ((ret = __db_vrfy_common(dbp, vdp, h, pgno, flags)) != 0) + goto err; + if ((ret = __bam_vrfy(dbp, + vdp, h, pgno, flags | DB_NOORDERCHK)) != 0 || + (ret = __db_salvage_markdone(vdp, pgno)) != 0) + goto err; + /* + * We have a known-healthy internal page. Walk it. + */ + if ((ret = __bam_salvage_walkdupint(dbp, vdp, h, key, + handle, callback, flags)) != 0) + goto err; + break; + case P_LRECNO: + case P_LDUP: + if ((ret = __bam_salvage(dbp, + vdp, pgno, TYPE(h), h, handle, callback, key, flags)) != 0) + goto err; + break; + default: + ret = DB_VERIFY_BAD; + goto err; + } + +err: if ((t_ret = __memp_fput(mpf, + vdp->thread_info, h, dbp->priority)) != 0 && ret == 0) + ret = t_ret; + return (ret); +} + +/* + * __db_salvage_all -- + * Salvage only the leaves we find by walking the tree. If we have subdbs, + * salvage each of them individually. + */ +static int +__db_salvage_all(dbp, vdp, handle, callback, flags, hassubsp) + DB *dbp; + VRFY_DBINFO *vdp; + void *handle; + int (*callback) __P((void *, const void *)); + u_int32_t flags; + int *hassubsp; +{ + DB *pgset; + DBC *pgsc; + DB_MPOOLFILE *mpf; + ENV *env; + PAGE *h; + VRFY_PAGEINFO *pip; + db_pgno_t p, meta_pgno; + int ret, t_ret; + + *hassubsp = 0; + + env = dbp->env; + pgset = NULL; + pgsc = NULL; + mpf = dbp->mpf; + h = NULL; + pip = NULL; + ret = 0; + + /* + * Check to make sure the page is OK and find out if it contains + * subdatabases. + */ + meta_pgno = PGNO_BASE_MD; + if ((t_ret = __memp_fget(mpf, + &meta_pgno, vdp->thread_info, NULL, 0, &h)) == 0 && + (t_ret = __db_vrfy_common(dbp, vdp, h, PGNO_BASE_MD, flags)) == 0 && + (t_ret = __db_salvage_pg( + dbp, vdp, PGNO_BASE_MD, h, handle, callback, flags)) == 0 && + (t_ret = __db_vrfy_getpageinfo(vdp, 0, &pip)) == 0) + if (F_ISSET(pip, VRFY_HAS_SUBDBS)) + *hassubsp = 1; + if (pip != NULL && + (t_ret = __db_vrfy_putpageinfo(env, vdp, pip)) != 0 && ret == 0) + ret = t_ret; + if (h != NULL) { + if ((t_ret = __memp_fput(mpf, + vdp->thread_info, h, dbp->priority)) != 0 && ret == 0) + ret = t_ret; + h = NULL; + } + if (ret != 0) + return (ret); + + /* Without subdatabases, we can just dump from the meta pgno. */ + if (*hassubsp == 0) + return (__db_salvage(dbp, + vdp, PGNO_BASE_MD, handle, callback, flags)); + + /* + * We have subdbs. Try to crack them. + * + * To do so, get a set of leaf pages in the master database, and then + * walk each of the valid ones, salvaging subdbs as we go. If any + * prove invalid, just drop them; we'll pick them up on a later pass. + */ + if ((ret = __db_vrfy_pgset(env, + vdp->thread_info, dbp->pgsize, &pgset)) != 0) + goto err; + if ((ret = __db_meta2pgset(dbp, vdp, PGNO_BASE_MD, flags, pgset)) != 0) + goto err; + if ((ret = __db_cursor(pgset, vdp->thread_info, NULL, &pgsc, 0)) != 0) + goto err; + while ((t_ret = __db_vrfy_pgset_next(pgsc, &p)) == 0) { + if ((t_ret = __memp_fget(mpf, + &p, vdp->thread_info, NULL, 0, &h)) == 0 && + (t_ret = __db_vrfy_common(dbp, vdp, h, p, flags)) == 0 && + (t_ret = + __bam_vrfy(dbp, vdp, h, p, flags | DB_NOORDERCHK)) == 0) + t_ret = __db_salvage_subdbpg( + dbp, vdp, h, handle, callback, flags); + if (t_ret != 0 && ret == 0) + ret = t_ret; + if (h != NULL) { + if ((t_ret = __memp_fput(mpf, vdp->thread_info, + h, dbp->priority)) != 0 && ret == 0) + ret = t_ret; + h = NULL; + } + } + + if (t_ret != DB_NOTFOUND && ret == 0) + ret = t_ret; + +err: if (pgsc != NULL && (t_ret = __dbc_close(pgsc)) != 0 && ret == 0) + ret = t_ret; + if (pgset != NULL && + (t_ret = __db_close(pgset, NULL, 0)) != 0 && ret ==0) + ret = t_ret; + if (h != NULL && + (t_ret = __memp_fput(mpf, + vdp->thread_info, h, dbp->priority)) != 0 && ret == 0) + ret = t_ret; + return (ret); +} + +/* + * __db_salvage_subdbpg -- + * Given a known-good leaf page in the master database, salvage all + * leaf pages corresponding to each subdb. + */ +static int +__db_salvage_subdbpg(dbp, vdp, master, handle, callback, flags) + DB *dbp; + VRFY_DBINFO *vdp; + PAGE *master; + void *handle; + int (*callback) __P((void *, const void *)); + u_int32_t flags; +{ + BKEYDATA *bkkey, *bkdata; + BOVERFLOW *bo; + DB *pgset; + DBC *pgsc; + DBT key; + DB_MPOOLFILE *mpf; + ENV *env; + PAGE *subpg; + db_indx_t i; + db_pgno_t meta_pgno; + int ret, err_ret, t_ret; + char *subdbname; + u_int32_t ovfl_bufsz; + + env = dbp->env; + mpf = dbp->mpf; + ret = err_ret = 0; + subdbname = NULL; + pgsc = NULL; + pgset = NULL; + ovfl_bufsz = 0; + + /* + * For each entry, get and salvage the set of pages + * corresponding to that entry. + */ + for (i = 0; i < NUM_ENT(master); i += P_INDX) { + bkkey = GET_BKEYDATA(dbp, master, i); + bkdata = GET_BKEYDATA(dbp, master, i + O_INDX); + + /* Get the subdatabase name. */ + if (B_TYPE(bkkey->type) == B_OVERFLOW) { + /* + * We can, in principle anyway, have a subdb + * name so long it overflows. Ick. + */ + bo = (BOVERFLOW *)bkkey; + if ((ret = __db_safe_goff(dbp, vdp, bo->pgno, + &key, &subdbname, &ovfl_bufsz, flags)) != 0) { + err_ret = DB_VERIFY_BAD; + continue; + } + + /* Nul-terminate it. */ + if (ovfl_bufsz < key.size + 1) { + if ((ret = __os_realloc(env, + key.size + 1, &subdbname)) != 0) + goto err; + ovfl_bufsz = key.size + 1; + } + subdbname[key.size] = '\0'; + } else if (B_TYPE(bkkey->type) == B_KEYDATA) { + if (ovfl_bufsz < (u_int32_t)bkkey->len + 1) { + if ((ret = __os_realloc(env, + bkkey->len + 1, &subdbname)) != 0) + goto err; + ovfl_bufsz = bkkey->len + 1; + } + DB_ASSERT(env, subdbname != NULL); + memcpy(subdbname, bkkey->data, bkkey->len); + subdbname[bkkey->len] = '\0'; + } + + /* Get the corresponding pgno. */ + if (bkdata->len != sizeof(db_pgno_t)) { + err_ret = DB_VERIFY_BAD; + continue; + } + memcpy(&meta_pgno, + (db_pgno_t *)bkdata->data, sizeof(db_pgno_t)); + + /* + * Subdatabase meta pgnos are stored in network byte + * order for cross-endian compatibility. Swap if appropriate. + */ + DB_NTOHL_SWAP(env, &meta_pgno); + + /* If we can't get the subdb meta page, just skip the subdb. */ + if (!IS_VALID_PGNO(meta_pgno) || (ret = __memp_fget(mpf, + &meta_pgno, vdp->thread_info, NULL, 0, &subpg)) != 0) { + err_ret = ret; + continue; + } + + /* + * Verify the subdatabase meta page. This has two functions. + * First, if it's bad, we have no choice but to skip the subdb + * and let the pages just get printed on a later pass. Second, + * the access-method-specific meta verification routines record + * the various state info (such as the presence of dups) + * that we need for __db_prheader(). + */ + if ((ret = + __db_vrfy_common(dbp, vdp, subpg, meta_pgno, flags)) != 0) { + err_ret = ret; + (void)__memp_fput(mpf, + vdp->thread_info, subpg, dbp->priority); + continue; + } + switch (TYPE(subpg)) { + case P_BTREEMETA: + if ((ret = __bam_vrfy_meta(dbp, + vdp, (BTMETA *)subpg, meta_pgno, flags)) != 0) { + err_ret = ret; + (void)__memp_fput(mpf, + vdp->thread_info, subpg, dbp->priority); + continue; + } + break; + case P_HASHMETA: + if ((ret = __ham_vrfy_meta(dbp, + vdp, (HMETA *)subpg, meta_pgno, flags)) != 0) { + err_ret = ret; + (void)__memp_fput(mpf, + vdp->thread_info, subpg, dbp->priority); + continue; + } + break; + default: + /* This isn't an appropriate page; skip this subdb. */ + err_ret = DB_VERIFY_BAD; + continue; + } + + if ((ret = __memp_fput(mpf, + vdp->thread_info, subpg, dbp->priority)) != 0) { + err_ret = ret; + continue; + } + + /* Print a subdatabase header. */ + if ((ret = __db_prheader(dbp, + subdbname, 0, 0, handle, callback, vdp, meta_pgno)) != 0) + goto err; + + /* Salvage meta_pgno's tree. */ + if ((ret = __db_salvage(dbp, + vdp, meta_pgno, handle, callback, flags)) != 0) + err_ret = ret; + + /* Print a subdatabase footer. */ + if ((ret = __db_prfooter(handle, callback)) != 0) + goto err; + } + +err: if (subdbname) + __os_free(env, subdbname); + + if (pgsc != NULL && (t_ret = __dbc_close(pgsc)) != 0) + ret = t_ret; + + if (pgset != NULL && (t_ret = __db_close(pgset, NULL, 0)) != 0) + ret = t_ret; + + if ((t_ret = __db_salvage_markdone(vdp, PGNO(master))) != 0) + return (t_ret); + + return ((err_ret != 0) ? err_ret : ret); +} + +/* + * __db_salvage -- + * Given a meta page number, salvage all data from leaf pages found by + * walking the meta page's tree. + */ +static int +__db_salvage(dbp, vdp, meta_pgno, handle, callback, flags) + DB *dbp; + VRFY_DBINFO *vdp; + db_pgno_t meta_pgno; + void *handle; + int (*callback) __P((void *, const void *)); + u_int32_t flags; + +{ + DB *pgset; + DBC *dbc, *pgsc; + DB_MPOOLFILE *mpf; + ENV *env; + PAGE *subpg; + db_pgno_t p; + int err_ret, ret, t_ret; + + env = dbp->env; + mpf = dbp->mpf; + err_ret = ret = t_ret = 0; + pgsc = NULL; + pgset = NULL; + dbc = NULL; + + if ((ret = __db_vrfy_pgset(env, + vdp->thread_info, dbp->pgsize, &pgset)) != 0) + goto err; + + /* Get all page numbers referenced from this meta page. */ + if ((ret = __db_meta2pgset(dbp, vdp, meta_pgno, + flags, pgset)) != 0) { + err_ret = ret; + goto err; + } + + if ((ret = __db_cursor(pgset, + vdp->thread_info, NULL, &pgsc, 0)) != 0) + goto err; + + if (dbp->type == DB_QUEUE && + (ret = __db_cursor(dbp, vdp->thread_info, NULL, &dbc, 0)) != 0) + goto err; + + /* Salvage every page in pgset. */ + while ((ret = __db_vrfy_pgset_next(pgsc, &p)) == 0) { + if (dbp->type == DB_QUEUE) { +#ifdef HAVE_QUEUE + ret = __qam_fget(dbc, &p, 0, &subpg); +#else + ret = __db_no_queue_am(env); +#endif + /* Don't report an error for pages not found in a queue. + * The pgset is a best guess, it doesn't know about + * deleted extents which leads to this error. + */ + if (ret == ENOENT || ret == DB_PAGE_NOTFOUND) + continue; + } else + ret = __memp_fget(mpf, + &p, vdp->thread_info, NULL, 0, &subpg); + if (ret != 0) { + err_ret = ret; + continue; + } + + if ((ret = __db_salvage_pg(dbp, vdp, p, subpg, + handle, callback, flags)) != 0) + err_ret = ret; + + if (dbp->type == DB_QUEUE) +#ifdef HAVE_QUEUE + ret = __qam_fput(dbc, p, subpg, dbp->priority); +#else + ret = __db_no_queue_am(env); +#endif + else + ret = __memp_fput(mpf, + vdp->thread_info, subpg, dbp->priority); + if (ret != 0) + err_ret = ret; + } + + if (ret == DB_NOTFOUND) + ret = 0; + +err: + if (dbc != NULL && (t_ret = __dbc_close(dbc)) != 0) + ret = t_ret; + if (pgsc != NULL && (t_ret = __dbc_close(pgsc)) != 0) + ret = t_ret; + if (pgset != NULL && (t_ret = __db_close(pgset, NULL, 0)) != 0) + ret = t_ret; + + return ((err_ret != 0) ? err_ret : ret); +} + +/* + * __db_meta2pgset -- + * Given a known-safe meta page number, return the set of pages + * corresponding to the database it represents. Return DB_VERIFY_BAD if + * it's not a suitable meta page or is invalid. + */ +static int +__db_meta2pgset(dbp, vdp, pgno, flags, pgset) + DB *dbp; + VRFY_DBINFO *vdp; + db_pgno_t pgno; + u_int32_t flags; + DB *pgset; +{ + DB_MPOOLFILE *mpf; + PAGE *h; + int ret, t_ret; + + mpf = dbp->mpf; + + if ((ret = __memp_fget(mpf, &pgno, vdp->thread_info, NULL, 0, &h)) != 0) + return (ret); + + switch (TYPE(h)) { + case P_BTREEMETA: + ret = __bam_meta2pgset(dbp, vdp, (BTMETA *)h, flags, pgset); + break; + case P_HASHMETA: + ret = __ham_meta2pgset(dbp, vdp, (HMETA *)h, flags, pgset); + break; + case P_HEAPMETA: + ret = __heap_meta2pgset(dbp, vdp, (HEAPMETA *)h, pgset); + break; + case P_QAMMETA: +#ifdef HAVE_QUEUE + ret = __qam_meta2pgset(dbp, vdp, pgset); + break; +#endif + default: + ret = DB_VERIFY_BAD; + break; + } + + if ((t_ret = __memp_fput(mpf, vdp->thread_info, h, dbp->priority)) != 0) + return (t_ret); + return (ret); +} + +/* + * __db_guesspgsize -- + * Try to guess what the pagesize is if the one on the meta page + * and the one in the db are invalid. + */ +static u_int +__db_guesspgsize(env, fhp) + ENV *env; + DB_FH *fhp; +{ + db_pgno_t i; + size_t nr; + u_int32_t guess; + u_int8_t type; + + for (guess = DB_MAX_PGSIZE; guess >= DB_MIN_PGSIZE; guess >>= 1) { + /* + * We try to read three pages ahead after the first one + * and make sure we have plausible types for all of them. + * If the seeks fail, continue with a smaller size; + * we're probably just looking past the end of the database. + * If they succeed and the types are reasonable, also continue + * with a size smaller; we may be looking at pages N, + * 2N, and 3N for some N > 1. + * + * As soon as we hit an invalid type, we stop and return + * our previous guess; that last one was probably the page size. + */ + for (i = 1; i <= 3; i++) { + if (__os_seek( + env, fhp, i, guess, SSZ(DBMETA, type)) != 0) + break; + if (__os_read(env, + fhp, &type, 1, &nr) != 0 || nr == 0) + break; + if (type == P_INVALID || type >= P_PAGETYPE_MAX) + return (guess << 1); + } + } + + /* + * If we're just totally confused--the corruption takes up most of the + * beginning pages of the database--go with the default size. + */ + return (DB_DEF_IOSIZE); +} diff -r 000000000000 -r a1985f14b030 src/db/db_vrfy_stub.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/db/db_vrfy_stub.c Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,142 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 1996, 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + * $Id$ + */ + +#include "db_config.h" +#ifndef HAVE_VERIFY + +#include "db_int.h" +#include "dbinc/db_page.h" +#include "dbinc/db_am.h" +#include "dbinc/db_verify.h" + +/* + * If the library wasn't compiled with the verification support, various + * routines aren't available. Stub them here, returning an appropriate + * error. + */ + +static int __db_novrfy __P((ENV *)); + +/* + * __db_novrfy -- + * Error when a Berkeley DB build doesn't include the access method. + */ +static int +__db_novrfy(env) + ENV *env; +{ + __db_errx(env, DB_STR("0571", + "library build did not include support for database verification")); + return (DB_OPNOTSUP); +} + +int +__db_verify_pp(dbp, file, database, outfile, flags) + DB *dbp; + const char *file, *database; + FILE *outfile; + u_int32_t flags; +{ + int ret; + + COMPQUIET(file, NULL); + COMPQUIET(database, NULL); + COMPQUIET(outfile, NULL); + COMPQUIET(flags, 0); + + ret = __db_novrfy(dbp->env); + + /* The verify method is a destructor. */ + (void)__db_close(dbp, NULL, 0); + + return (ret); +} + +int +__db_verify_internal(dbp, name, subdb, handle, callback, flags) + DB *dbp; + const char *name, *subdb; + void *handle; + int (*callback) __P((void *, const void *)); + u_int32_t flags; +{ + COMPQUIET(dbp, NULL); + COMPQUIET(name, NULL); + COMPQUIET(subdb, NULL); + COMPQUIET(handle, NULL); + COMPQUIET(callback, NULL); + COMPQUIET(flags, 0); + return (0); +} + +int +__db_vrfy_getpageinfo(vdp, pgno, pipp) + VRFY_DBINFO *vdp; + db_pgno_t pgno; + VRFY_PAGEINFO **pipp; +{ + COMPQUIET(pgno, 0); + COMPQUIET(pipp, NULL); + return (__db_novrfy(vdp->pgdbp->env)); +} + +int +__db_vrfy_putpageinfo(env, vdp, pip) + ENV *env; + VRFY_DBINFO *vdp; + VRFY_PAGEINFO *pip; +{ + COMPQUIET(vdp, NULL); + COMPQUIET(pip, NULL); + return (__db_novrfy(env)); +} + +int +__db_vrfy_prdbt(dbtp, checkprint, prefix, + handle, callback, is_recno, is_heap, vdp) + DBT *dbtp; + int checkprint; + const char *prefix; + void *handle; + int (*callback) __P((void *, const void *)); + int is_recno; + int is_heap; + VRFY_DBINFO *vdp; +{ + COMPQUIET(dbtp, NULL); + COMPQUIET(checkprint, 0); + COMPQUIET(prefix, NULL); + COMPQUIET(handle, NULL); + COMPQUIET(callback, NULL); + COMPQUIET(is_recno, 0); + COMPQUIET(is_heap, 0); + return (__db_novrfy(vdp->pgdbp->env)); +} +#endif /* !HAVE_VERIFY */ diff -r 000000000000 -r a1985f14b030 src/db/db_vrfyutil.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/db/db_vrfyutil.c Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,958 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 2000, 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + * $Id$ + */ + +#include "db_config.h" + +#include "db_int.h" +#include "dbinc/db_page.h" +#include "dbinc/db_verify.h" +#include "dbinc/db_am.h" + +static int __db_vrfy_childinc __P((DBC *, VRFY_CHILDINFO *)); +static int __db_vrfy_pageinfo_create __P((ENV *, VRFY_PAGEINFO **)); + +/* + * __db_vrfy_dbinfo_create -- + * Allocate and initialize a VRFY_DBINFO structure. + * + * PUBLIC: int __db_vrfy_dbinfo_create + * PUBLIC: __P((ENV *, DB_THREAD_INFO *, u_int32_t, VRFY_DBINFO **)); + */ +int +__db_vrfy_dbinfo_create(env, ip, pgsize, vdpp) + ENV *env; + DB_THREAD_INFO *ip; + u_int32_t pgsize; + VRFY_DBINFO **vdpp; +{ + DB *cdbp, *pgdbp, *pgset; + VRFY_DBINFO *vdp; + int ret; + + vdp = NULL; + cdbp = pgdbp = pgset = NULL; + + if ((ret = __os_calloc(NULL, 1, sizeof(VRFY_DBINFO), &vdp)) != 0) + goto err; + + if ((ret = __db_create_internal(&cdbp, env, 0)) != 0) + goto err; + + if ((ret = __db_set_flags(cdbp, DB_DUP)) != 0) + goto err; + + if ((ret = __db_set_pagesize(cdbp, pgsize)) != 0) + goto err; + + /* If transactional, make sure we don't log. */ + if (TXN_ON(env) && + (ret = __db_set_flags(cdbp, DB_TXN_NOT_DURABLE)) != 0) + goto err; + if ((ret = __db_open(cdbp, ip, + NULL, NULL, NULL, DB_BTREE, DB_CREATE, 0600, PGNO_BASE_MD)) != 0) + goto err; + + if ((ret = __db_create_internal(&pgdbp, env, 0)) != 0) + goto err; + + if ((ret = __db_set_pagesize(pgdbp, pgsize)) != 0) + goto err; + + /* If transactional, make sure we don't log. */ + if (TXN_ON(env) && + (ret = __db_set_flags(pgdbp, DB_TXN_NOT_DURABLE)) != 0) + goto err; + + if ((ret = __db_open(pgdbp, ip, + NULL, NULL, NULL, DB_BTREE, DB_CREATE, 0600, PGNO_BASE_MD)) != 0) + goto err; + + if ((ret = __db_vrfy_pgset(env, ip, pgsize, &pgset)) != 0) + goto err; + + if (CDB_LOCKING(env) && + (ret = __cdsgroup_begin(env, &vdp->txn)) != 0) + goto err; + + LIST_INIT(&vdp->subdbs); + LIST_INIT(&vdp->activepips); + + vdp->cdbp = cdbp; + vdp->pgdbp = pgdbp; + vdp->pgset = pgset; + vdp->thread_info = ip; + *vdpp = vdp; + return (0); + +err: if (cdbp != NULL) + (void)__db_close(cdbp, NULL, 0); + if (pgdbp != NULL) + (void)__db_close(pgdbp, NULL, 0); +#ifdef HAVE_TRANSACTIONS + if (vdp->txn != NULL) + (void)vdp->txn->commit(vdp->txn, 0); +#endif + if (vdp != NULL) + __os_free(env, vdp); + return (ret); +} + +/* + * __db_vrfy_dbinfo_destroy -- + * Destructor for VRFY_DBINFO. Destroys VRFY_PAGEINFOs and deallocates + * structure. + * + * PUBLIC: int __db_vrfy_dbinfo_destroy __P((ENV *, VRFY_DBINFO *)); + */ +int +__db_vrfy_dbinfo_destroy(env, vdp) + ENV *env; + VRFY_DBINFO *vdp; +{ + VRFY_CHILDINFO *c; + int t_ret, ret; + + ret = 0; + + /* + * Discard active page structures. Ideally there wouldn't be any, + * but in some error cases we may not have cleared them all out. + */ + while (LIST_FIRST(&vdp->activepips) != NULL) + if ((t_ret = __db_vrfy_putpageinfo( + env, vdp, LIST_FIRST(&vdp->activepips))) != 0) { + if (ret == 0) + ret = t_ret; + break; + } + + /* Discard subdatabase list structures. */ + while ((c = LIST_FIRST(&vdp->subdbs)) != NULL) { + LIST_REMOVE(c, links); + __os_free(NULL, c); + } + + if ((t_ret = __db_close(vdp->pgdbp, NULL, 0)) != 0) + ret = t_ret; + + if ((t_ret = __db_close(vdp->cdbp, NULL, 0)) != 0 && ret == 0) + ret = t_ret; + + if ((t_ret = __db_close(vdp->pgset, NULL, 0)) != 0 && ret == 0) + ret = t_ret; + +#ifdef HAVE_TRANSACTIONS + if (vdp->txn != NULL && + (t_ret = vdp->txn->commit(vdp->txn, 0)) != 0 && ret == 0) + ret = t_ret; +#endif + + if (vdp->extents != NULL) + __os_free(env, vdp->extents); + __os_free(env, vdp); + return (ret); +} + +/* + * __db_vrfy_getpageinfo -- + * Get a PAGEINFO structure for a given page, creating it if necessary. + * + * PUBLIC: int __db_vrfy_getpageinfo + * PUBLIC: __P((VRFY_DBINFO *, db_pgno_t, VRFY_PAGEINFO **)); + */ +int +__db_vrfy_getpageinfo(vdp, pgno, pipp) + VRFY_DBINFO *vdp; + db_pgno_t pgno; + VRFY_PAGEINFO **pipp; +{ + DB *pgdbp; + DBT key, data; + ENV *env; + VRFY_PAGEINFO *pip; + int ret; + + /* + * We want a page info struct. There are three places to get it from, + * in decreasing order of preference: + * + * 1. vdp->activepips. If it's already "checked out", we're + * already using it, we return the same exact structure with a + * bumped refcount. This is necessary because this code is + * replacing array accesses, and it's common for f() to make some + * changes to a pip, and then call g() and h() which each make + * changes to the same pip. vdps are never shared between threads + * (they're never returned to the application), so this is safe. + * 2. The pgdbp. It's not in memory, but it's in the database, so + * get it, give it a refcount of 1, and stick it on activepips. + * 3. malloc. It doesn't exist yet; create it, then stick it on + * activepips. We'll put it in the database when we putpageinfo + * later. + */ + + /* Case 1. */ + LIST_FOREACH(pip, &vdp->activepips, links) + if (pip->pgno == pgno) + goto found; + + /* Case 2. */ + pgdbp = vdp->pgdbp; + env = pgdbp->env; + memset(&key, 0, sizeof(DBT)); + memset(&data, 0, sizeof(DBT)); + F_SET(&data, DB_DBT_MALLOC); + key.data = &pgno; + key.size = sizeof(db_pgno_t); + + if ((ret = __db_get(pgdbp, + vdp->thread_info, vdp->txn, &key, &data, 0)) == 0) { + /* Found it. */ + DB_ASSERT(env, data.size == sizeof(VRFY_PAGEINFO)); + pip = data.data; + LIST_INSERT_HEAD(&vdp->activepips, pip, links); + goto found; + } else if (ret != DB_NOTFOUND) /* Something nasty happened. */ + return (ret); + + /* Case 3 */ + if ((ret = __db_vrfy_pageinfo_create(env, &pip)) != 0) + return (ret); + + LIST_INSERT_HEAD(&vdp->activepips, pip, links); +found: pip->pi_refcount++; + + *pipp = pip; + return (0); +} + +/* + * __db_vrfy_putpageinfo -- + * Put back a VRFY_PAGEINFO that we're done with. + * + * PUBLIC: int __db_vrfy_putpageinfo __P((ENV *, + * PUBLIC: VRFY_DBINFO *, VRFY_PAGEINFO *)); + */ +int +__db_vrfy_putpageinfo(env, vdp, pip) + ENV *env; + VRFY_DBINFO *vdp; + VRFY_PAGEINFO *pip; +{ + DB *pgdbp; + DBT key, data; + VRFY_PAGEINFO *p; + int ret; + + if (--pip->pi_refcount > 0) + return (0); + + pgdbp = vdp->pgdbp; + memset(&key, 0, sizeof(DBT)); + memset(&data, 0, sizeof(DBT)); + + key.data = &pip->pgno; + key.size = sizeof(db_pgno_t); + data.data = pip; + data.size = sizeof(VRFY_PAGEINFO); + + if ((ret = __db_put(pgdbp, + vdp->thread_info, vdp->txn, &key, &data, 0)) != 0) + return (ret); + + LIST_FOREACH(p, &vdp->activepips, links) + if (p == pip) + break; + if (p != NULL) + LIST_REMOVE(p, links); + + __os_ufree(env, p); + return (0); +} + +/* + * __db_vrfy_pgset -- + * Create a temporary database for the storing of sets of page numbers. + * (A mapping from page number to int, used by the *_meta2pgset functions, + * as well as for keeping track of which pages the verifier has seen.) + * + * PUBLIC: int __db_vrfy_pgset __P((ENV *, + * PUBLIC: DB_THREAD_INFO *, u_int32_t, DB **)); + */ +int +__db_vrfy_pgset(env, ip, pgsize, dbpp) + ENV *env; + DB_THREAD_INFO *ip; + u_int32_t pgsize; + DB **dbpp; +{ + DB *dbp; + int ret; + + if ((ret = __db_create_internal(&dbp, env, 0)) != 0) + return (ret); + if ((ret = __db_set_pagesize(dbp, pgsize)) != 0) + goto err; + + /* If transactional, make sure we don't log. */ + if (TXN_ON(env) && + (ret = __db_set_flags(dbp, DB_TXN_NOT_DURABLE)) != 0) + goto err; + if ((ret = __db_open(dbp, ip, + NULL, NULL, NULL, DB_BTREE, DB_CREATE, 0600, PGNO_BASE_MD)) == 0) + *dbpp = dbp; + else +err: (void)__db_close(dbp, NULL, 0); + + return (ret); +} + +/* + * __db_vrfy_pgset_get -- + * Get the value associated in a page set with a given pgno. Return + * a 0 value (and succeed) if we've never heard of this page. + * + * PUBLIC: int __db_vrfy_pgset_get __P((DB *, DB_THREAD_INFO *, DB_TXN *, + * PUBLIC: db_pgno_t, int *)); + */ +int +__db_vrfy_pgset_get(dbp, ip, txn, pgno, valp) + DB *dbp; + DB_THREAD_INFO *ip; + DB_TXN *txn; + db_pgno_t pgno; + int *valp; +{ + DBT key, data; + int ret, val; + + memset(&key, 0, sizeof(DBT)); + memset(&data, 0, sizeof(DBT)); + + key.data = &pgno; + key.size = sizeof(db_pgno_t); + data.data = &val; + data.ulen = sizeof(int); + F_SET(&data, DB_DBT_USERMEM); + + if ((ret = __db_get(dbp, ip, txn, &key, &data, 0)) == 0) { + DB_ASSERT(dbp->env, data.size == sizeof(int)); + } else if (ret == DB_NOTFOUND) + val = 0; + else + return (ret); + + *valp = val; + return (0); +} + +/* + * __db_vrfy_pgset_inc -- + * Increment the value associated with a pgno by 1. + * + * PUBLIC: int __db_vrfy_pgset_inc __P((DB *, DB_THREAD_INFO *, DB_TXN *, + * PUBLIC: db_pgno_t)); + */ +int +__db_vrfy_pgset_inc(dbp, ip, txn, pgno) + DB *dbp; + DB_THREAD_INFO *ip; + DB_TXN *txn; + db_pgno_t pgno; +{ + DBT key, data; + int ret; + int val; + + memset(&key, 0, sizeof(DBT)); + memset(&data, 0, sizeof(DBT)); + + val = 0; + + key.data = &pgno; + key.size = sizeof(db_pgno_t); + data.data = &val; + data.ulen = sizeof(int); + F_SET(&data, DB_DBT_USERMEM); + + if ((ret = __db_get(dbp, ip, txn, &key, &data, 0)) == 0) { + DB_ASSERT(dbp->env, data.size == sizeof(int)); + } else if (ret != DB_NOTFOUND) + return (ret); + + data.size = sizeof(int); + ++val; + + return (__db_put(dbp, ip, txn, &key, &data, 0)); +} + +/* + * __db_vrfy_pgset_next -- + * Given a cursor open in a pgset database, get the next page in the + * set. + * + * PUBLIC: int __db_vrfy_pgset_next __P((DBC *, db_pgno_t *)); + */ +int +__db_vrfy_pgset_next(dbc, pgnop) + DBC *dbc; + db_pgno_t *pgnop; +{ + DBT key, data; + db_pgno_t pgno; + int ret; + + memset(&key, 0, sizeof(DBT)); + memset(&data, 0, sizeof(DBT)); + /* We don't care about the data, just the keys. */ + F_SET(&data, DB_DBT_USERMEM | DB_DBT_PARTIAL); + F_SET(&key, DB_DBT_USERMEM); + key.data = &pgno; + key.ulen = sizeof(db_pgno_t); + + if ((ret = __dbc_get(dbc, &key, &data, DB_NEXT)) != 0) + return (ret); + + DB_ASSERT(dbc->env, key.size == sizeof(db_pgno_t)); + *pgnop = pgno; + + return (0); +} + +/* + * __db_vrfy_childcursor -- + * Create a cursor to walk the child list with. Returns with a nonzero + * final argument if the specified page has no children. + * + * PUBLIC: int __db_vrfy_childcursor __P((VRFY_DBINFO *, DBC **)); + */ +int +__db_vrfy_childcursor(vdp, dbcp) + VRFY_DBINFO *vdp; + DBC **dbcp; +{ + DB *cdbp; + DBC *dbc; + int ret; + + cdbp = vdp->cdbp; + + if ((ret = __db_cursor(cdbp, vdp->thread_info, vdp->txn, &dbc, 0)) == 0) + *dbcp = dbc; + + return (ret); +} + +/* + * __db_vrfy_childput -- + * Add a child structure to the set for a given page. + * + * PUBLIC: int __db_vrfy_childput + * PUBLIC: __P((VRFY_DBINFO *, db_pgno_t, VRFY_CHILDINFO *)); + */ +int +__db_vrfy_childput(vdp, pgno, cip) + VRFY_DBINFO *vdp; + db_pgno_t pgno; + VRFY_CHILDINFO *cip; +{ + DB *cdbp; + DBC *cc; + DBT key, data; + VRFY_CHILDINFO *oldcip; + int ret; + + cdbp = vdp->cdbp; + memset(&key, 0, sizeof(DBT)); + memset(&data, 0, sizeof(DBT)); + + key.data = &pgno; + key.size = sizeof(db_pgno_t); + + /* + * We want to avoid adding multiple entries for a single child page; + * we only need to verify each child once, even if a child (such + * as an overflow key) is multiply referenced. + * + * However, we also need to make sure that when walking the list + * of children, we encounter them in the order they're referenced + * on a page. (This permits us, for example, to verify the + * prev_pgno/next_pgno chain of Btree leaf pages.) + * + * Check the child database to make sure that this page isn't + * already a child of the specified page number. If it's not, + * put it at the end of the duplicate set. + */ + if ((ret = __db_vrfy_childcursor(vdp, &cc)) != 0) + return (ret); + for (ret = __db_vrfy_ccset(cc, pgno, &oldcip); ret == 0; + ret = __db_vrfy_ccnext(cc, &oldcip)) + if (oldcip->pgno == cip->pgno) { + /* + * Found a matching child. Increment its reference + * count--we've run into it again--but don't put it + * again. + */ + if ((ret = __db_vrfy_childinc(cc, oldcip)) != 0 || + (ret = __db_vrfy_ccclose(cc)) != 0) + return (ret); + return (0); + } + if (ret != DB_NOTFOUND) { + (void)__db_vrfy_ccclose(cc); + return (ret); + } + if ((ret = __db_vrfy_ccclose(cc)) != 0) + return (ret); + + cip->refcnt = 1; + data.data = cip; + data.size = sizeof(VRFY_CHILDINFO); + + return (__db_put(cdbp, vdp->thread_info, vdp->txn, &key, &data, 0)); +} + +/* + * __db_vrfy_childinc -- + * Increment the refcount of the VRFY_CHILDINFO struct that the child + * cursor is pointing to. (The caller has just retrieved this struct, and + * passes it in as cip to save us a get.) + */ +static int +__db_vrfy_childinc(dbc, cip) + DBC *dbc; + VRFY_CHILDINFO *cip; +{ + DBT key, data; + + memset(&key, 0, sizeof(DBT)); + memset(&data, 0, sizeof(DBT)); + + cip->refcnt++; + data.data = cip; + data.size = sizeof(VRFY_CHILDINFO); + + return (__dbc_put(dbc, &key, &data, DB_CURRENT)); +} + +/* + * __db_vrfy_ccset -- + * Sets a cursor created with __db_vrfy_childcursor to the first + * child of the given pgno, and returns it in the third arg. + * + * PUBLIC: int __db_vrfy_ccset __P((DBC *, db_pgno_t, VRFY_CHILDINFO **)); + */ +int +__db_vrfy_ccset(dbc, pgno, cipp) + DBC *dbc; + db_pgno_t pgno; + VRFY_CHILDINFO **cipp; +{ + DBT key, data; + int ret; + + memset(&key, 0, sizeof(DBT)); + memset(&data, 0, sizeof(DBT)); + + key.data = &pgno; + key.size = sizeof(db_pgno_t); + + if ((ret = __dbc_get(dbc, &key, &data, DB_SET)) != 0) + return (ret); + + DB_ASSERT(dbc->env, data.size == sizeof(VRFY_CHILDINFO)); + *cipp = (VRFY_CHILDINFO *)data.data; + + return (0); +} + +/* + * __db_vrfy_ccnext -- + * Gets the next child of the given cursor created with + * __db_vrfy_childcursor, and returns it in the memory provided in the + * second arg. + * + * PUBLIC: int __db_vrfy_ccnext __P((DBC *, VRFY_CHILDINFO **)); + */ +int +__db_vrfy_ccnext(dbc, cipp) + DBC *dbc; + VRFY_CHILDINFO **cipp; +{ + DBT key, data; + int ret; + + memset(&key, 0, sizeof(DBT)); + memset(&data, 0, sizeof(DBT)); + + if ((ret = __dbc_get(dbc, &key, &data, DB_NEXT_DUP)) != 0) + return (ret); + + DB_ASSERT(dbc->env, data.size == sizeof(VRFY_CHILDINFO)); + *cipp = (VRFY_CHILDINFO *)data.data; + + return (0); +} + +/* + * __db_vrfy_ccclose -- + * Closes the cursor created with __db_vrfy_childcursor. + * + * This doesn't actually do anything interesting now, but it's + * not inconceivable that we might change the internal database usage + * and keep the interfaces the same, and a function call here or there + * seldom hurts anyone. + * + * PUBLIC: int __db_vrfy_ccclose __P((DBC *)); + */ +int +__db_vrfy_ccclose(dbc) + DBC *dbc; +{ + + return (__dbc_close(dbc)); +} + +/* + * __db_vrfy_pageinfo_create -- + * Constructor for VRFY_PAGEINFO; allocates and initializes. + */ +static int +__db_vrfy_pageinfo_create(env, pipp) + ENV *env; + VRFY_PAGEINFO **pipp; +{ + VRFY_PAGEINFO *pip; + int ret; + + /* + * pageinfo structs are sometimes allocated here and sometimes + * allocated by fetching them from a database with DB_DBT_MALLOC. + * There's no easy way for the destructor to tell which was + * used, and so we always allocate with __os_umalloc so we can free + * with __os_ufree. + */ + if ((ret = __os_umalloc(env, sizeof(VRFY_PAGEINFO), &pip)) != 0) + return (ret); + memset(pip, 0, sizeof(VRFY_PAGEINFO)); + + *pipp = pip; + return (0); +} + +/* + * __db_salvage_init -- + * Set up salvager database. + * + * PUBLIC: int __db_salvage_init __P((VRFY_DBINFO *)); + */ +int +__db_salvage_init(vdp) + VRFY_DBINFO *vdp; +{ + DB *dbp; + int ret; + + if ((ret = __db_create_internal(&dbp, NULL, 0)) != 0) + return (ret); + + if ((ret = __db_set_pagesize(dbp, 1024)) != 0) + goto err; + + if ((ret = __db_open(dbp, vdp->thread_info, + NULL, NULL, NULL, DB_BTREE, DB_CREATE, 0, PGNO_BASE_MD)) != 0) + goto err; + + vdp->salvage_pages = dbp; + return (0); + +err: (void)__db_close(dbp, NULL, 0); + return (ret); +} + +/* + * __db_salvage_destroy -- + * Close salvager database. + * PUBLIC: int __db_salvage_destroy __P((VRFY_DBINFO *)); + */ +int +__db_salvage_destroy(vdp) + VRFY_DBINFO *vdp; +{ + return (vdp->salvage_pages == NULL ? 0 : + __db_close(vdp->salvage_pages, NULL, 0)); +} + +/* + * __db_salvage_getnext -- + * Get the next (first) unprinted page in the database of pages we need to + * print still. Delete entries for any already-printed pages we encounter + * in this search, as well as the page we're returning. + * + * PUBLIC: int __db_salvage_getnext + * PUBLIC: __P((VRFY_DBINFO *, DBC **, db_pgno_t *, u_int32_t *, int)); + */ +int +__db_salvage_getnext(vdp, dbcp, pgnop, pgtypep, skip_overflow) + VRFY_DBINFO *vdp; + DBC **dbcp; + db_pgno_t *pgnop; + u_int32_t *pgtypep; + int skip_overflow; +{ + DB *dbp; + DBT key, data; + int ret; + u_int32_t pgtype; + + dbp = vdp->salvage_pages; + + memset(&key, 0, sizeof(DBT)); + memset(&data, 0, sizeof(DBT)); + + if (*dbcp == NULL && + (ret = __db_cursor(dbp, vdp->thread_info, vdp->txn, dbcp, 0)) != 0) + return (ret); + + while ((ret = __dbc_get(*dbcp, &key, &data, DB_NEXT)) == 0) { + DB_ASSERT(dbp->env, data.size == sizeof(u_int32_t)); + memcpy(&pgtype, data.data, sizeof(pgtype)); + + if (skip_overflow && pgtype == SALVAGE_OVERFLOW) + continue; + + if ((ret = __dbc_del(*dbcp, 0)) != 0) + return (ret); + if (pgtype != SALVAGE_IGNORE) { + DB_ASSERT(dbp->env, key.size == sizeof(db_pgno_t)); + DB_ASSERT(dbp->env, data.size == sizeof(u_int32_t)); + + *pgnop = *(db_pgno_t *)key.data; + *pgtypep = *(u_int32_t *)data.data; + break; + } + } + + return (ret); +} + +/* + * __db_salvage_isdone -- + * Return whether or not the given pgno is already marked + * SALVAGE_IGNORE (meaning that we don't need to print it again). + * + * Returns DB_KEYEXIST if it is marked, 0 if not, or another error on + * error. + * + * PUBLIC: int __db_salvage_isdone __P((VRFY_DBINFO *, db_pgno_t)); + */ +int +__db_salvage_isdone(vdp, pgno) + VRFY_DBINFO *vdp; + db_pgno_t pgno; +{ + DB *dbp; + DBT key, data; + int ret; + u_int32_t currtype; + + dbp = vdp->salvage_pages; + + memset(&key, 0, sizeof(DBT)); + memset(&data, 0, sizeof(DBT)); + + currtype = SALVAGE_INVALID; + data.data = &currtype; + data.ulen = sizeof(u_int32_t); + data.flags = DB_DBT_USERMEM; + + key.data = &pgno; + key.size = sizeof(db_pgno_t); + + /* + * Put an entry for this page, with pgno as key and type as data, + * unless it's already there and is marked done. + * If it's there and is marked anything else, that's fine--we + * want to mark it done. + */ + if ((ret = __db_get(dbp, + vdp->thread_info, vdp->txn, &key, &data, 0)) == 0) { + /* + * The key's already here. Check and see if it's already + * marked done. If it is, return DB_KEYEXIST. If it's not, + * return 0. + */ + if (currtype == SALVAGE_IGNORE) + return (DB_KEYEXIST); + else + return (0); + } else if (ret != DB_NOTFOUND) + return (ret); + + /* The pgno is not yet marked anything; return 0. */ + return (0); +} + +/* + * __db_salvage_markdone -- + * Mark as done a given page. + * + * PUBLIC: int __db_salvage_markdone __P((VRFY_DBINFO *, db_pgno_t)); + */ +int +__db_salvage_markdone(vdp, pgno) + VRFY_DBINFO *vdp; + db_pgno_t pgno; +{ + DB *dbp; + DBT key, data; + int pgtype, ret; + u_int32_t currtype; + + pgtype = SALVAGE_IGNORE; + dbp = vdp->salvage_pages; + + memset(&key, 0, sizeof(DBT)); + memset(&data, 0, sizeof(DBT)); + + currtype = SALVAGE_INVALID; + data.data = &currtype; + data.ulen = sizeof(u_int32_t); + data.flags = DB_DBT_USERMEM; + + key.data = &pgno; + key.size = sizeof(db_pgno_t); + + /* + * Put an entry for this page, with pgno as key and type as data, + * unless it's already there and is marked done. + * If it's there and is marked anything else, that's fine--we + * want to mark it done, but db_salvage_isdone only lets + * us know if it's marked IGNORE. + * + * We don't want to return DB_KEYEXIST, though; this will + * likely get passed up all the way and make no sense to the + * application. Instead, use DB_VERIFY_BAD to indicate that + * we've seen this page already--it probably indicates a + * multiply-linked page. + */ + if ((ret = __db_salvage_isdone(vdp, pgno)) != 0) + return (ret == DB_KEYEXIST ? DB_VERIFY_BAD : ret); + + data.size = sizeof(u_int32_t); + data.data = &pgtype; + + return (__db_put(dbp, vdp->thread_info, vdp->txn, &key, &data, 0)); +} + +/* + * __db_salvage_markneeded -- + * If it has not yet been printed, make note of the fact that a page + * must be dealt with later. + * + * PUBLIC: int __db_salvage_markneeded + * PUBLIC: __P((VRFY_DBINFO *, db_pgno_t, u_int32_t)); + */ +int +__db_salvage_markneeded(vdp, pgno, pgtype) + VRFY_DBINFO *vdp; + db_pgno_t pgno; + u_int32_t pgtype; +{ + DB *dbp; + DBT key, data; + int ret; + + dbp = vdp->salvage_pages; + + memset(&key, 0, sizeof(DBT)); + memset(&data, 0, sizeof(DBT)); + + key.data = &pgno; + key.size = sizeof(db_pgno_t); + + data.data = &pgtype; + data.size = sizeof(u_int32_t); + + /* + * Put an entry for this page, with pgno as key and type as data, + * unless it's already there, in which case it's presumably + * already been marked done. + */ + ret = __db_put(dbp, + vdp->thread_info, vdp->txn, &key, &data, DB_NOOVERWRITE); + return (ret == DB_KEYEXIST ? 0 : ret); +} + +/* + * __db_vrfy_prdbt -- + * Print out a DBT data element from a verification routine. + * + * PUBLIC: int __db_vrfy_prdbt __P((DBT *, int, const char *, void *, + * PUBLIC: int (*)(void *, const void *), int, int, VRFY_DBINFO *)); + */ +int +__db_vrfy_prdbt(dbtp, checkprint, prefix, + handle, callback, is_recno, is_heap, vdp) + DBT *dbtp; + int checkprint; + const char *prefix; + void *handle; + int (*callback) __P((void *, const void *)); + int is_recno; + int is_heap; + VRFY_DBINFO *vdp; +{ + if (vdp != NULL) { + /* + * If vdp is non-NULL, we might be the first key in the + * "fake" subdatabase used for key/data pairs we can't + * associate with a known subdb. + * + * Check and clear the SALVAGE_PRINTHEADER flag; if + * it was set, print a subdatabase header. + */ + if (F_ISSET(vdp, SALVAGE_PRINTHEADER)) { + (void)__db_prheader( + NULL, "__OTHER__", 0, 0, handle, callback, vdp, 0); + F_CLR(vdp, SALVAGE_PRINTHEADER); + F_SET(vdp, SALVAGE_PRINTFOOTER); + } + + /* + * Even if the printable flag wasn't set by our immediate + * caller, it may be set on a salvage-wide basis. + */ + if (F_ISSET(vdp, SALVAGE_PRINTABLE)) + checkprint = 1; + } + return ( + __db_prdbt(dbtp, checkprint, + prefix, handle, callback, is_recno, is_heap)); +} diff -r 000000000000 -r a1985f14b030 src/db/partition_stub.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/db/partition_stub.c Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,153 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 1996, 2011 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + * $Id$ + */ + +#include "db_config.h" + +#include "db_int.h" + +/* + * If the library wasn't compiled with partitions support, various routines + * aren't available. Stub them here, returning an appropriate error. + */ + +/* + * __db_no_partition -- + * Error when a Berkeley DB build doesn't include partitioning. + * + * PUBLIC: int __db_no_partition __P((ENV *)); + */ +int +__db_no_partition(env) + ENV *env; +{ + __db_errx(env, DB_STR("0664", + "library build did not include support for the database partitioning")); + return (DB_OPNOTSUP); +} + +/* + * __partition_get_dirs -- + */ +int +__partition_get_dirs(dbp, dirpp) + DB *dbp; + const char ***dirpp; +{ + COMPQUIET(dirpp, NULL); + return (__db_no_partition(dbp->env)); +} + +/* + * __partition_get_callback -- + */ +int +__partition_get_callback(dbp, parts, callback) + DB *dbp; + u_int32_t *parts; + u_int32_t (**callback)(DB *, DBT *key); +{ + COMPQUIET(parts, NULL); + COMPQUIET(callback, NULL); + return (__db_no_partition(dbp->env)); +} + +/* + * __partition_get_keys -- + */ +int +__partition_get_keys(dbp, parts, keys) + DB *dbp; + u_int32_t *parts; + DBT **keys; +{ + COMPQUIET(parts, NULL); + COMPQUIET(keys, NULL); + return (__db_no_partition(dbp->env)); +} + +/* + * __partition_init -- + */ +int +__partition_init(dbp, flags) + DB *dbp; + u_int32_t flags; +{ + COMPQUIET(flags, 0); + return (__db_no_partition(dbp->env)); +} + +/* + * __partition_set -- + */ + +int +__partition_set(dbp, parts, keys, callback) + DB *dbp; + u_int32_t parts; + DBT *keys; + u_int32_t (*callback)(DB *, DBT *key); +{ + COMPQUIET(parts, 0); + COMPQUIET(keys, NULL); + COMPQUIET(callback, NULL); + return (__db_no_partition(dbp->env)); +} + +/* + * __partition_set_dirs -- + */ +int +__partition_set_dirs(dbp, dirp) + DB *dbp; + const char **dirp; +{ + COMPQUIET(dirp, NULL); + return (__db_no_partition(dbp->env)); +} + +/* + * __part_fileid_reset -- + */ +int +__part_fileid_reset(env, ip, fname, nparts, encrypted) + ENV *env; + DB_THREAD_INFO *ip; + const char *fname; + u_int32_t nparts; + int encrypted; +{ + COMPQUIET(ip, NULL); + COMPQUIET(fname, NULL); + COMPQUIET(nparts, 0); + COMPQUIET(encrypted, 0); + return (__db_no_partition(env)); +} + diff -r 000000000000 -r a1985f14b030 src/dbinc/atomic.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/dbinc/atomic.h Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,242 @@ +/* + * See the file LICENSE for redistribution information. + * + * Copyright (c) 2009, 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + * $Id$ + */ + +#ifndef _DB_ATOMIC_H_ +#define _DB_ATOMIC_H_ + +#if defined(__cplusplus) +extern "C" { +#endif + +/* + * Atomic operation support for Oracle Berkeley DB + * + * HAVE_ATOMIC_SUPPORT configures whether to use the assembly language + * or system calls to perform: + * + * atomic_inc(env, valueptr) + * Adds 1 to the db_atomic_t value, returning the new value. + * + * atomic_dec(env, valueptr) + * Subtracts 1 from the db_atomic_t value, returning the new value. + * + * atomic_compare_exchange(env, valueptr, oldval, newval) + * If the db_atomic_t's value is still oldval, set it to newval. + * It returns 1 for success or 0 for failure. + * + * The ENV * parameter is used only when HAVE_ATOMIC_SUPPORT is undefined. + * + * If the platform does not natively support any one of these operations, + * then atomic operations will be emulated with this sequence: + * MUTEX_LOCK() + * + * MUTEX_UNLOCK(); + * Uses where mutexes are not available (e.g. the environment has not yet + * attached to the mutex region) must be avoided. + */ +#if defined(DB_WIN32) +typedef DWORD atomic_value_t; +#else +typedef int32_t atomic_value_t; +#endif + +/* + * Windows CE has strange issues using the Interlocked APIs with variables + * stored in shared memory. It seems like the page needs to have been written + * prior to the API working as expected. Work around this by allocating an + * additional 32-bit value that can be harmlessly written for each value + * used in Interlocked instructions. + */ +#if defined(DB_WINCE) +typedef struct { + volatile atomic_value_t value; + volatile atomic_value_t dummy; +} db_atomic_t; +#else +typedef struct { + volatile atomic_value_t value; +} db_atomic_t; +#endif + +/* + * These macro hide the db_atomic_t structure layout and help detect + * non-atomic_t actual argument to the atomic_xxx() calls. DB requires + * aligned 32-bit reads to be atomic even outside of explicit 'atomic' calls. + * These have no memory barriers; the caller must include them when necessary. + */ +#define atomic_read(p) ((p)->value) +#define atomic_init(p, val) ((p)->value = (val)) + +#ifdef HAVE_ATOMIC_SUPPORT + +#if defined(DB_WIN32) +#if defined(DB_WINCE) +#define WINCE_ATOMIC_MAGIC(p) \ + /* \ + * Memory mapped regions on Windows CE cause problems with \ + * InterlockedXXX calls. Each page in a mapped region needs to \ + * have been written to prior to an InterlockedXXX call, or the \ + * InterlockedXXX call hangs. This does not seem to be \ + * documented anywhere. For now, read/write a non-critical \ + * piece of memory from the shared region prior to attempting \ + * shared region prior to attempting an InterlockedExchange \ + * InterlockedXXX operation. \ + */ \ + (p)->dummy = 0 +#else +#define WINCE_ATOMIC_MAGIC(p) 0 +#endif + +#if defined(DB_WINCE) || (defined(_MSC_VER) && _MSC_VER < 1300) +/* + * The Interlocked instructions on Windows CE have different parameter + * definitions. The parameters lost their 'volatile' qualifier, + * cast it away, to avoid compiler warnings. + * These definitions should match those in dbinc/mutex_int.h for tsl_t, except + * that the WINCE version drops the volatile qualifier. + */ +typedef PLONG interlocked_val; +#define atomic_inc(env, p) \ + (WINCE_ATOMIC_MAGIC(p), \ + InterlockedIncrement((interlocked_val)(&(p)->value))) + +#else +typedef LONG volatile *interlocked_val; +#define atomic_inc(env, p) \ + InterlockedIncrement((interlocked_val)(&(p)->value)) +#endif + +#define atomic_dec(env, p) \ + (WINCE_ATOMIC_MAGIC(p), \ + InterlockedDecrement((interlocked_val)(&(p)->value))) +#if defined(_MSC_VER) && _MSC_VER < 1300 +#define atomic_compare_exchange(env, p, oldval, newval) \ + (WINCE_ATOMIC_MAGIC(p), \ + (InterlockedCompareExchange((PVOID *)(&(p)->value), \ + (PVOID)(newval), (PVOID)(oldval)) == (PVOID)(oldval))) +#else +#define atomic_compare_exchange(env, p, oldval, newval) \ + (WINCE_ATOMIC_MAGIC(p), \ + (InterlockedCompareExchange((interlocked_val)(&(p)->value), \ + (newval), (oldval)) == (oldval))) +#endif +#endif + +#if defined(HAVE_ATOMIC_SOLARIS) +/* Solaris sparc & x86/64 */ +#include +#define atomic_inc(env, p) \ + atomic_inc_uint_nv((volatile unsigned int *) &(p)->value) +#define atomic_dec(env, p) \ + atomic_dec_uint_nv((volatile unsigned int *) &(p)->value) +#define atomic_compare_exchange(env, p, oval, nval) \ + (atomic_cas_32((volatile unsigned int *) &(p)->value, \ + (oval), (nval)) == (oval)) +#endif + +#if defined(HAVE_ATOMIC_X86_GCC_ASSEMBLY) +/* x86/x86_64 gcc */ +#define atomic_inc(env, p) __atomic_inc(p) +#define atomic_dec(env, p) __atomic_dec(p) +#define atomic_compare_exchange(env, p, o, n) \ + __atomic_compare_exchange((p), (o), (n)) +static inline int __atomic_inc(db_atomic_t *p) +{ + int temp; + + temp = 1; + __asm__ __volatile__("lock; xadd %0, (%1)" + : "+r"(temp) + : "r"(p)); + return (temp + 1); +} + +static inline int __atomic_dec(db_atomic_t *p) +{ + int temp; + + temp = -1; + __asm__ __volatile__("lock; xadd %0, (%1)" + : "+r"(temp) + : "r"(p)); + return (temp - 1); +} + +/* + * x86/gcc Compare exchange for shared latches. i486+ + * Returns 1 for success, 0 for failure + * + * GCC 4.1+ has an equivalent __sync_bool_compare_and_swap() as well as + * __sync_val_compare_and_swap() which returns the value read from *dest + * http://gcc.gnu.org/onlinedocs/gcc-4.1.0/gcc/Atomic-Builtins.html + * which configure could be changed to use. + */ +static inline int __atomic_compare_exchange( + db_atomic_t *p, atomic_value_t oldval, atomic_value_t newval) +{ + atomic_value_t was; + + if (p->value != oldval) /* check without expensive cache line locking */ + return 0; + __asm__ __volatile__("lock; cmpxchgl %1, (%2);" + :"=a"(was) + :"r"(newval), "r"(p), "a"(oldval) + :"memory", "cc"); + return (was == oldval); +} +#endif + +#else +/* + * No native hardware support for atomic increment, decrement, and + * compare-exchange. Emulate them when mutexes are supported; + * do them without concern for atomicity when no mutexes. + */ +#ifndef HAVE_MUTEX_SUPPORT +/* + * These minimal versions are correct to use only for single-threaded, + * single-process environments. + */ +#define atomic_inc(env, p) (++(p)->value) +#define atomic_dec(env, p) (--(p)->value) +#define atomic_compare_exchange(env, p, oldval, newval) \ + (DB_ASSERT(env, atomic_read(p) == (oldval)), \ + atomic_init(p, (newval)), 1) +#else +#define atomic_inc(env, p) __atomic_inc(env, p) +#define atomic_dec(env, p) __atomic_dec(env, p) +#endif +#endif + +#if defined(__cplusplus) +} +#endif + +#endif /* !_DB_ATOMIC_H_ */ diff -r 000000000000 -r a1985f14b030 src/dbinc/btree.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/dbinc/btree.h Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,575 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 1996, 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +/* + * Copyright (c) 1990, 1993, 1994, 1995, 1996 + * Keith Bostic. All rights reserved. + */ +/* + * Copyright (c) 1990, 1993, 1994, 1995 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Mike Olson. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $Id$ + */ +#ifndef _DB_BTREE_H_ +#define _DB_BTREE_H_ + +#if defined(__cplusplus) +extern "C" { +#endif + +/* Forward structure declarations. */ +struct __btree; typedef struct __btree BTREE; +struct __cursor; typedef struct __cursor BTREE_CURSOR; +struct __epg; typedef struct __epg EPG; + +#define DEFMINKEYPAGE (2) + +/* + * A recno order of 0 indicates that we don't have an order, not that we've + * an order less than 1. + */ +#define INVALID_ORDER 0 + +#define ISINTERNAL(p) (TYPE(p) == P_IBTREE || TYPE(p) == P_IRECNO) +#define ISLEAF(p) (TYPE(p) == P_LBTREE || \ + TYPE(p) == P_LRECNO || TYPE(p) == P_LDUP) + +/* Flags for __bam_cadjust_log(). */ +#define CAD_UPDATEROOT 0x01 /* Root page count was updated. */ + +/* Flags for __bam_split_log(). */ +#define SPL_NRECS 0x01 /* Split tree has record count. */ +#define SPL_RECNO 0x02 /* This is a Recno cursor. */ + +/* Flags for __bam_iitem(). */ +#define BI_DELETED 0x01 /* Key/data pair only placeholder. */ + +/* Flags for __bam_stkrel(). */ +#define STK_CLRDBC 0x01 /* Clear dbc->page reference. */ +#define STK_NOLOCK 0x02 /* Don't retain locks. */ +#define STK_PGONLY 0x04 + +/* Flags for __ram_ca(). These get logged, so make the values explicit. */ +typedef enum { + CA_DELETE = 0, /* Delete the current record. */ + CA_IAFTER = 1, /* Insert before the current record. */ + CA_IBEFORE = 2, /* Insert after the current record. */ + CA_ICURRENT = 3 /* Overwrite the current record. */ +} ca_recno_arg; + +/* + * Flags for __bam_search() and __bam_rsearch(). + * + * Note, internal page searches must find the largest record less than key in + * the tree so that descents work. Leaf page searches must find the smallest + * record greater than key so that the returned index is the record's correct + * position for insertion. + * + * The flags parameter to the search routines describes three aspects of the + * search: the type of locking required (including if we're locking a pair of + * pages), the item to return in the presence of duplicates and whether or not + * to return deleted entries. To simplify both the mnemonic representation + * and the code that checks for various cases, we construct a set of bitmasks. + */ +#define SR_READ 0x00001 /* Read locks. */ +#define SR_WRITE 0x00002 /* Write locks. */ + +#define SR_APPEND 0x00040 /* Append to the tree. */ +#define SR_DELNO 0x00080 /* Don't return deleted items. */ +#define SR_DUPFIRST 0x00100 /* Return first duplicate. */ +#define SR_DUPLAST 0x00200 /* Return last duplicate. */ +#define SR_EXACT 0x00400 /* Exact items only. */ +#define SR_PARENT 0x00800 /* Lock page pair. */ +#define SR_STACK 0x01000 /* Need a complete stack. */ +#define SR_PAST_EOF 0x02000 /* If doing insert search (or keyfirst + * or keylast operations), or a split + * on behalf of an insert, it's okay to + * return an entry one past end-of-page. + */ +#define SR_STK_ONLY 0x04000 /* Just return info in the stack */ +#define SR_MAX 0x08000 /* Get the right most key */ +#define SR_MIN 0x10000 /* Get the left most key */ +#define SR_NEXT 0x20000 /* Get the page after this key */ +#define SR_DEL 0x40000 /* Get the tree to delete this key. */ +#define SR_START 0x80000 /* Level to start stack. */ +#define SR_BOTH 0x100000 /* Get this and the NEXT page */ + +#define SR_DELETE \ + (SR_WRITE | SR_DUPFIRST | SR_DELNO | SR_EXACT | SR_STACK) +#define SR_FIND (SR_READ | SR_DUPFIRST | SR_DELNO) +#define SR_FIND_WR (SR_WRITE | SR_DUPFIRST | SR_DELNO) +#define SR_INSERT (SR_WRITE | SR_DUPLAST | SR_PAST_EOF | SR_STACK) +#define SR_KEYFIRST (SR_WRITE | SR_DUPFIRST | SR_PAST_EOF | SR_STACK) +#define SR_KEYLAST (SR_WRITE | SR_DUPLAST | SR_PAST_EOF | SR_STACK) +#define SR_WRPAIR (SR_WRITE | SR_DUPLAST | SR_PAST_EOF | SR_PARENT) + +/* + * Various routines pass around page references. A page reference is + * a pointer to the page, and the indx indicates an item on the page. + * Each page reference may include a lock. + */ +struct __epg { + PAGE *page; /* The page. */ + db_indx_t indx; /* The index on the page. */ + db_indx_t entries; /* The number of entries on page */ + DB_LOCK lock; /* The page's lock. */ + db_lockmode_t lock_mode; /* The lock mode. */ +}; + +/* + * We maintain a stack of the pages that we're locking in the tree. Grow + * the stack as necessary. + * + * XXX + * Temporary fix for #3243 -- clear the page and lock from the stack entry. + * The correct fix is to never release a stack that doesn't hold items. + */ +#define BT_STK_CLR(c) do { \ + (c)->csp = (c)->sp; \ + (c)->csp->page = NULL; \ + LOCK_INIT((c)->csp->lock); \ +} while (0) + +#define BT_STK_ENTER(env, c, pagep, page_indx, l, mode, ret) do { \ + if ((ret = ((c)->csp == (c)->esp ? \ + __bam_stkgrow(env, c) : 0)) == 0) { \ + (c)->csp->page = pagep; \ + (c)->csp->indx = (page_indx); \ + (c)->csp->entries = NUM_ENT(pagep); \ + (c)->csp->lock = l; \ + (c)->csp->lock_mode = mode; \ + } \ +} while (0) + +#define BT_STK_PUSH(env, c, pagep, page_indx, lock, mode, ret) do { \ + BT_STK_ENTER(env, c, pagep, page_indx, lock, mode, ret); \ + ++(c)->csp; \ +} while (0) + +#define BT_STK_NUM(env, c, pagep, page_indx, ret) do { \ + if ((ret = ((c)->csp == \ + (c)->esp ? __bam_stkgrow(env, c) : 0)) == 0) { \ + (c)->csp->page = NULL; \ + (c)->csp->indx = (page_indx); \ + (c)->csp->entries = NUM_ENT(pagep); \ + LOCK_INIT((c)->csp->lock); \ + (c)->csp->lock_mode = DB_LOCK_NG; \ + } \ +} while (0) + +#define BT_STK_NUMPUSH(env, c, pagep, page_indx, ret) do { \ + BT_STK_NUM(env, cp, pagep, page_indx, ret); \ + ++(c)->csp; \ +} while (0) + +#define BT_STK_POP(c) \ + ((c)->csp == (c)->sp ? NULL : --(c)->csp) + +/* + * Flags for __bam_dpages. + */ +#define BTD_UPDATE 0x0001 /* Update parents. */ +#define BTD_RELINK 0x0002 /* Relink leaf pages. */ + +/* + * TRY_LOCK + * When holding a stack we have pages latched but not locked so + * we must avoid an undetectable deadlock by not then blocking on a + * lock. + */ +#define TRY_LOCK(dbc, pgno, saved_pgno, saved_lock, lock_mode, label) \ + TRY_LOCK2(dbc, NULL, pgno, saved_pgno, saved_lock, lock_mode, label) +/* + * TRY_LOCK2 + * This is a special call for __bam_compact_int which uses 2 + * overlapping stacks. + */ + +#ifdef BTREE_DEBUG +#define TRY_LOCK2(dbc, ndbc, pgno, \ + saved_pgno, saved_lock, lock_mode, label) do { \ + static int BTcount = 0; \ + if ((pgno) != (saved_pgno) && \ + ((BTcount++ % 5) == 0 || \ + (ret = __db_lget(dbc, LCK_COUPLE_ALWAYS, pgno, \ + lock_mode, DB_LOCK_NOWAIT, &(saved_lock))) != 0)) { \ + if (ret != 0 && ret != DB_LOCK_NOTGRANTED && \ + ret != DB_LOCK_DEADLOCK) \ + break; \ + if ((ndbc) != NULL) { \ + BTREE_CURSOR *__cp; \ + __cp = (BTREE_CURSOR *) (dbc)->internal; \ + __cp->sp->page = NULL; \ + LOCK_INIT(__cp->sp->lock); \ + if ((ret = __bam_stkrel(ndbc, 0)) != 0) \ + break; \ + } \ + if ((ret = __bam_stkrel(dbc, 0)) != 0) \ + break; \ + if ((ret = __db_lget(dbc, LCK_COUPLE_ALWAYS, pgno, \ + lock_mode, 0, &(saved_lock))) != 0) \ + break; \ + saved_pgno = pgno; \ + goto label; \ + } \ + saved_pgno = pgno; \ +} while (0) +#else +#define TRY_LOCK2(dbc, ndbc, pgno, \ + saved_pgno, saved_lock, lock_mode, label) do { \ + if ((pgno) != (saved_pgno) && \ + (ret = __db_lget(dbc, LCK_COUPLE_ALWAYS, pgno, \ + lock_mode, DB_LOCK_NOWAIT, &(saved_lock))) != 0) { \ + if (ret != DB_LOCK_NOTGRANTED && \ + ret != DB_LOCK_DEADLOCK) \ + break; \ + if ((ndbc) != NULL) { \ + BTREE_CURSOR *__cp; \ + __cp = (BTREE_CURSOR *) (dbc)->internal; \ + __cp->sp->page = NULL; \ + LOCK_INIT(__cp->sp->lock); \ + if ((ret = __bam_stkrel(ndbc, 0)) != 0) \ + break; \ + } \ + if ((ret = __bam_stkrel(dbc, 0)) != 0) \ + break; \ + if ((ret = __db_lget(dbc, LCK_COUPLE_ALWAYS, pgno, \ + lock_mode, 0, &(saved_lock))) != 0) \ + break; \ + saved_pgno = pgno; \ + goto label; \ + } \ + saved_pgno = pgno; \ +} while (0) +#endif + +/* Btree/Recno cursor. */ +struct __cursor { + /* struct __dbc_internal */ + __DBC_INTERNAL + + /* btree private part */ + EPG *sp; /* Stack pointer. */ + EPG *csp; /* Current stack entry. */ + EPG *esp; /* End stack pointer. */ + EPG stack[5]; + + db_indx_t ovflsize; /* Maximum key/data on-page size. */ + + db_recno_t recno; /* Current record number. */ + u_int32_t order; /* Relative order among deleted curs. */ + +#ifdef HAVE_COMPRESSION + /* + * Compression: + * + * We need to hold the current compressed chunk, as well as the previous + * key/data, in order to decompress the next key/data. We do that by + * swapping whether prevKey/Data and currentKey/Data point to + * key1/data1, or key2/data2. + * + * We store prevcursor in order to be able to perform one level of + * DB_PREV by returning prevKey/prevData. We need prev2cursor to more + * efficiently do a subsequent DB_PREV with a linear search from the + * beginning of the compressed chunk. + * + * When we delete entries, we set the cursor to point to the next entry + * after the last deleted key, and set C_COMPRESS_DELETED. The del_key + * DBT holds the key of the deleted entry supposedly pointed to by a + * compressed cursor, and is used to implement DB_PREV_DUP, + * DB_PREV_NODUP, DB_NEXT_DUP, and DB_NEXT_NODUP on a deleted entry. + */ + DBT compressed; /* Current compressed chunk */ + DBT key1; /* Holds prevKey or currentKey */ + DBT key2; /* Holds prevKey or currentKey */ + DBT data1; /* Holds prevData or currentData */ + DBT data2; /* Holds prevData or currentData */ + DBT del_key; /* Holds key from the deleted entry */ + DBT del_data; /* Holds data from the deleted entry */ + DBT *prevKey; /* Previous key decompressed */ + DBT *prevData; /* Previous data decompressed */ + DBT *currentKey; /* Current key decompressed */ + DBT *currentData; /* Current data decompressed */ + u_int8_t *compcursor; /* Current position in compressed */ + u_int8_t *compend; /* End of compressed */ + u_int8_t *prevcursor; /* Previous current position */ + u_int8_t *prev2cursor; /* Previous previous current position */ +#endif + + /* + * Btree: + * We set a flag in the cursor structure if the underlying object has + * been deleted. It's not strictly necessary, we could get the same + * information by looking at the page itself, but this method doesn't + * require us to retrieve the page on cursor delete. + * + * Recno: + * When renumbering recno databases during deletes, cursors referencing + * "deleted" records end up positioned between two records, and so must + * be specially adjusted on the next operation. + */ +#define C_DELETED 0x0001 /* Record was deleted. */ + /* + * There are three tree types that require maintaining record numbers. + * Recno AM trees, Btree AM trees for which the DB_RECNUM flag was set, + * and Btree off-page duplicate trees. + */ +#define C_RECNUM 0x0002 /* Tree requires record counts. */ + /* + * Recno trees have immutable record numbers by default, but optionally + * support mutable record numbers. Off-page duplicate Recno trees have + * mutable record numbers. All Btrees with record numbers (including + * off-page duplicate trees) are mutable by design, no flag is needed. + */ +#define C_RENUMBER 0x0004 /* Tree records are mutable. */ + /* + * The current compressed key/data could be deleted, as well as the + * key/data that the underlying BTree cursor points to. + */ +#define C_COMPRESS_DELETED 0x0008 /* Compressed record was deleted. */ + /* + * The current compressed chunk has been modified by another DBC. A + * compressed cursor will have to seek it's position again if necessary + * when it is next accessed. + */ +#define C_COMPRESS_MODIFIED 0x0010 /* Compressed record was modified. */ + u_int32_t flags; +}; + +/* + * Threshhold value, as a function of bt_minkey, of the number of + * bytes a key/data pair can use before being placed on an overflow + * page. Assume every item requires the maximum alignment for + * padding, out of sheer paranoia. + */ +#define B_MINKEY_TO_OVFLSIZE(dbp, minkey, pgsize) \ + ((u_int16_t)(((pgsize) - P_OVERHEAD(dbp)) / ((minkey) * P_INDX) -\ + (BKEYDATA_PSIZE(0) + DB_ALIGN(1, sizeof(int32_t))))) + +/* + * The maximum space that a single item can ever take up on one page. + * Used by __bam_split to determine whether a split is still necessary. + */ +#define B_MAX(a,b) (((a) > (b)) ? (a) : (b)) +#define B_MAXSIZEONPAGE(ovflsize) \ + (B_MAX(BOVERFLOW_PSIZE, BKEYDATA_PSIZE(ovflsize))) + +/* + * BAM_GET_ROOT -- + * This macro is used to isolate the fact that the root page of + * a subdatabase may move if DB->compact is called on it. + * The dbp->mpf->mfp->revision will be incremented every time + * a subdatabase root or meta page moves. If this is the case then + * we must call __db_reopen to read the master database to find it. + * We leave the loop only by breaking out if we do not have a subdb + * or we are sure the have the right revision. + * + * It must be guaranteed that we cannot read an old root pgno and a + * current revision number. We note that the global revision number + * and DB handle information are only updated while holding the latches + * and locks of the master database pages. + * If another thread is synchronizing the DB handle with the master + * database it will exclusively latch both the old and new pages so we will + * synchronize on that. + */ +#define BAM_GET_ROOT(dbc, root_pgno, \ + page, get_mode, lock_mode, lock, ret) do { \ + BTREE *__t = (dbc)->dbp->bt_internal; \ + BTREE_CURSOR *__cp = (BTREE_CURSOR *)(dbc)->internal; \ + db_pgno_t __root; \ + u_int32_t __rev = 0; \ + if ((root_pgno) == PGNO_INVALID) { \ + if (__cp->root == PGNO_INVALID) { \ + __root = __t->bt_root; \ + __rev = __t->revision; \ + } else \ + __root = root_pgno = __cp->root; \ + } else \ + __root = root_pgno; \ + if (STD_LOCKING(dbc) && \ + ((lock_mode) == DB_LOCK_WRITE || F_ISSET(dbc, DBC_DOWNREV) \ + || dbc->dbtype == DB_RECNO || F_ISSET(__cp, C_RECNUM)) && \ + (ret = \ + __db_lget(dbc, 0, __root, lock_mode, 0, &(lock))) != 0) \ + break; \ + if ((ret = __memp_fget((dbc)->dbp->mpf, &__root, \ + (dbc)->thread_info, dbc->txn, get_mode, &page)) == 0) { \ + if (__root == root_pgno) \ + break; \ + if (F_ISSET(dbc, DBC_OPD) || \ + !F_ISSET((dbc)->dbp, DB_AM_SUBDB) || \ + (__t->bt_root == __root && \ + (LEVEL(page) == LEAFLEVEL || TYPE(page) == \ + (dbc->dbtype == DB_BTREE ? P_IBTREE : P_IRECNO)) &&\ + __rev == (dbc)->dbp->mpf->mfp->revision)) { \ + root_pgno = __root; \ + break; \ + } \ + if ((ret = __memp_fput((dbc)->dbp->mpf, \ + (dbc)->thread_info, page, (dbc)->priority)) != 0) \ + break; \ + } else if (ret != DB_PAGE_NOTFOUND) \ + break; \ + if ((ret = __LPUT(dbc, lock)) != 0) \ + break; \ + if ((ret = __db_reopen(dbc)) != 0) \ + break; \ +} while (1) + +/* + * Return the root of this tree. If this is an off page duplicate tree + * then its in the cursor, otherwise we must look in the db handle. + */ +#define BAM_ROOT_PGNO(dbc) \ + (((BTREE_CURSOR *)(dbc)->internal)->root == PGNO_INVALID ? \ + ((BTREE*)(dbc)->dbp->bt_internal)->bt_root : \ + ((BTREE_CURSOR *)(dbc)->internal)->root) + + + +/* + * The in-memory, per-tree btree/recno data structure. + */ +struct __btree { /* Btree access method. */ + /* + * These fields may change if this is a subdatabase and + * it gets compacted. + */ + db_pgno_t bt_meta; /* Database meta-data page. */ + db_pgno_t bt_root; /* Database root page. */ + u_int32_t revision; /* Revision of root/meta. */ + + u_int32_t bt_minkey; /* Minimum keys per page. */ + + /* Btree comparison function. */ + int (*bt_compare) __P((DB *, const DBT *, const DBT *)); + /* Btree prefix function. */ + size_t (*bt_prefix) __P((DB *, const DBT *, const DBT *)); + /* Btree compress function. */ +#ifdef HAVE_COMPRESSION + int (*bt_compress) __P((DB *, const DBT *, const DBT *, const DBT *, + const DBT *, DBT *)); + /* Btree decompress function. */ + int (*bt_decompress) __P((DB *, const DBT *, const DBT *, DBT *, DBT *, + DBT *)); + /* dup_compare for compression */ + int (*compress_dup_compare) __P((DB *, const DBT *, const DBT *)); +#endif + + /* Recno access method. */ + int re_pad; /* Fixed-length padding byte. */ + int re_delim; /* Variable-length delimiting byte. */ + u_int32_t re_len; /* Length for fixed-length records. */ + char *re_source; /* Source file name. */ + + /* + * !!! + * The bt_lpgno field is NOT protected by any mutex, and for this + * reason must be advisory only, so, while it is read/written by + * multiple threads, DB is completely indifferent to the quality + * of its information. + */ + db_pgno_t bt_lpgno; /* Last insert location. */ + DB_LSN bt_llsn; /* Last insert LSN. */ + + /* + * !!! + * The re_modified field is NOT protected by any mutex, and for this + * reason cannot be anything more complicated than a zero/non-zero + * value. The actual writing of the backing source file cannot be + * threaded, so clearing the flag isn't a problem. + */ + int re_modified; /* If the tree was modified. */ + + /* + * !!! + * These fields are ignored as far as multi-threading is concerned. + * There are no transaction semantics associated with backing files, + * nor is there any thread protection. + */ + FILE *re_fp; /* Source file handle. */ + int re_eof; /* Backing source file EOF reached. */ + db_recno_t re_last; /* Last record number read. */ + +}; + +/* + * Modes for the __bam_curadj recovery records (btree_curadj). + * These appear in log records, so we wire the values and + * do not leave it up to the compiler. + */ +typedef enum { + DB_CA_DI = 1, + DB_CA_DUP = 2, + DB_CA_RSPLIT = 3, + DB_CA_SPLIT = 4 +} db_ca_mode; + +/* + * Flags for __bam_pinsert. + */ +#define BPI_SPACEONLY 0x01 /* Only check for space to update. */ +#define BPI_NORECNUM 0x02 /* Not update the recnum on the left. */ +#define BPI_NOLOGGING 0x04 /* Don't log the update. */ +#define BPI_REPLACE 0x08 /* Replace the record. */ + +#if defined(__cplusplus) +} +#endif + +#include "dbinc_auto/btree_auto.h" +#include "dbinc_auto/btree_ext.h" +#include "dbinc/db_am.h" +#endif /* !_DB_BTREE_H_ */ diff -r 000000000000 -r a1985f14b030 src/dbinc/clock.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/dbinc/clock.h Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,153 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 2005, 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + * $Id$ + */ +/* + * Copyright (c) 1982, 1986, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)time.h 8.5 (Berkeley) 5/4/95 + * FreeBSD: src/sys/sys/time.h,v 1.65 2004/04/07 04:19:49 imp Exp + */ + +#ifndef _DB_CLOCK_H_ +#define _DB_CLOCK_H_ + +#if defined(__cplusplus) +extern "C" { +#endif + +/* + * This declaration is POSIX-compatible. Because there are lots of different + * time.h include file patterns out there, it's easier to declare our own name + * in all cases than to try and discover if a system has a struct timespec. + * For the same reason, and because we'd have to #include in db.h, + * we don't export any timespec structures in the DB API, even in places where + * it would make sense, like the replication statistics information. + */ +typedef struct { + time_t tv_sec; /* seconds */ +#ifdef HAVE_MIXED_SIZE_ADDRESSING + int32_t tv_nsec; +#else + long tv_nsec; /* nanoseconds */ +#endif +} db_timespec; + +/* Operations on timespecs */ +#undef timespecclear +#define timespecclear(tvp) ((tvp)->tv_sec = (tvp)->tv_nsec = 0) +#undef timespecisset +#define timespecisset(tvp) ((tvp)->tv_sec || (tvp)->tv_nsec) +#undef timespeccmp +#define timespeccmp(tvp, uvp, cmp) \ + (((tvp)->tv_sec == (uvp)->tv_sec) ? \ + ((tvp)->tv_nsec cmp (uvp)->tv_nsec) : \ + ((tvp)->tv_sec cmp (uvp)->tv_sec)) +#undef timespecadd +/* + * Note that using timespecadd to add to yourself (i.e. doubling) + * must be supported. + */ +#define timespecadd(vvp, uvp) \ + do { \ + (vvp)->tv_sec += (uvp)->tv_sec; \ + (vvp)->tv_nsec += (uvp)->tv_nsec; \ + if ((vvp)->tv_nsec >= 1000000000) { \ + (vvp)->tv_sec++; \ + (vvp)->tv_nsec -= 1000000000; \ + } \ + } while (0) +#undef timespecsub +#define timespecsub(vvp, uvp) \ + do { \ + (vvp)->tv_sec -= (uvp)->tv_sec; \ + (vvp)->tv_nsec -= (uvp)->tv_nsec; \ + if ((vvp)->tv_nsec < 0) { \ + (vvp)->tv_sec--; \ + (vvp)->tv_nsec += 1000000000; \ + } \ + } while (0) + +#undef timespecset +#define timespecset(vvp, sec, nsec) \ + do { \ + (vvp)->tv_sec = (time_t)(sec); \ + (vvp)->tv_nsec = (long)(nsec); \ + } while (0) + +#define DB_TIMEOUT_TO_TIMESPEC(t, vvp) \ + do { \ + (vvp)->tv_sec = (time_t)((t) / 1000000); \ + (vvp)->tv_nsec = (long)(((t) % 1000000) * 1000); \ + } while (0) + +#define DB_TIMESPEC_TO_TIMEOUT(t, vvp, prec) \ + do { \ + t = (u_long)((vvp)->tv_sec * 1000000); \ + t += (u_long)((vvp)->tv_nsec / 1000); \ + /* Add in 1 usec for lost nsec precision if wanted. */ \ + if (prec) \ + t++; \ + } while (0) + +#define TIMESPEC_ADD_DB_TIMEOUT(vvp, t) \ + do { \ + db_timespec __tmp; \ + DB_TIMEOUT_TO_TIMESPEC(t, &__tmp); \ + timespecadd((vvp), &__tmp); \ + } while (0) + +#if defined(__cplusplus) +} +#endif +#endif /* !_DB_CLOCK_H_ */ diff -r 000000000000 -r a1985f14b030 src/dbinc/crypto.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/dbinc/crypto.h Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,115 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 1996, 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + * $Id$ + */ + +#ifndef _DB_CRYPTO_H_ +#define _DB_CRYPTO_H_ + +#if defined(__cplusplus) +extern "C" { +#endif + +#ifdef HAVE_CRYPTO_IPP +#include +#endif + +/* + * !!! + * These are the internal representations of the algorithm flags. + * They are used in both the DB_CIPHER structure and the CIPHER + * structure so we can tell if users specified both passwd and alg + * correctly. + * + * CIPHER_ANY is used when an app joins an existing env but doesn't + * know the algorithm originally used. This is only valid in the + * DB_CIPHER structure until we open and can set the alg. + */ +/* + * We store the algorithm in an 8-bit field on the meta-page. So we + * use a numeric value, not bit fields. + * now we are limited to 8 algorithms before we cannot use bits and + * need numeric values. That should be plenty. It is okay for the + * CIPHER_ANY flag to go beyond that since that is never stored on disk. + */ + +/* + * This structure is per-process, not in shared memory. + */ +struct __db_cipher { + u_int (*adj_size) __P((size_t)); + int (*close) __P((ENV *, void *)); + int (*decrypt) __P((ENV *, void *, void *, u_int8_t *, size_t)); + int (*encrypt) __P((ENV *, void *, void *, u_int8_t *, size_t)); + int (*init) __P((ENV *, DB_CIPHER *)); + + u_int8_t mac_key[DB_MAC_KEY]; /* MAC key. */ + void *data; /* Algorithm-specific information */ + +#define CIPHER_AES 1 /* AES algorithm */ + u_int8_t alg; /* Algorithm used - See above */ + u_int8_t spare[3]; /* Spares */ + +#define CIPHER_ANY 0x00000001 /* Only for DB_CIPHER */ + u_int32_t flags; /* Other flags */ +}; + +#ifdef HAVE_CRYPTO + +#include "crypto/rijndael/rijndael-api-fst.h" + +/* + * Shared ciphering structure + * No mutex needed because all information is read-only after creation. + */ +typedef struct __cipher { + roff_t passwd; /* Offset to shared passwd */ + size_t passwd_len; /* Length of passwd */ + u_int32_t flags; /* Algorithm used - see above */ +} CIPHER; + +#define DB_AES_KEYLEN 128 /* AES key length */ +#define DB_AES_CHUNK 16 /* AES byte unit size */ + +typedef struct __aes_cipher { +#ifdef HAVE_CRYPTO_IPP + void *ipp_ctx; /* IPP key instance */ +#else + keyInstance decrypt_ki; /* Decryption key instance */ + keyInstance encrypt_ki; /* Encryption key instance */ +#endif + u_int32_t flags; /* AES-specific flags */ +} AES_CIPHER; + +#include "dbinc_auto/crypto_ext.h" +#endif /* HAVE_CRYPTO */ + +#if defined(__cplusplus) +} +#endif +#endif /* !_DB_CRYPTO_H_ */ diff -r 000000000000 -r a1985f14b030 src/dbinc/cxx_int.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/dbinc/cxx_int.h Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,99 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 1997, 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + * $Id$ + */ + +#ifndef _DB_CXX_INT_H_ +#define _DB_CXX_INT_H_ + +// private data structures known to the implementation only + +// +// Using FooImp classes will allow the implementation to change in the +// future without any modification to user code or even to header files +// that the user includes. FooImp * is just like void * except that it +// provides a little extra protection, since you cannot randomly assign +// any old pointer to a FooImp* as you can with void *. Currently, a +// pointer to such an opaque class is always just a pointer to the +// appropriate underlying implementation struct. These are converted +// back and forth using the various overloaded wrap()/unwrap() methods. +// This is essentially a use of the "Bridge" Design Pattern. +// +// WRAPPED_CLASS implements the appropriate wrap() and unwrap() methods +// for a wrapper class that has an underlying pointer representation. +// +#define WRAPPED_CLASS(_WRAPPER_CLASS, _IMP_CLASS, _WRAPPED_TYPE) \ + class _IMP_CLASS {}; \ + \ + inline _WRAPPED_TYPE *unwrap(_WRAPPER_CLASS *val) \ + { \ + if (!val) return (0); \ + return (val->get_##_WRAPPED_TYPE()); \ + } \ + \ + inline const _WRAPPED_TYPE *unwrapConst(const _WRAPPER_CLASS *val) \ + { \ + if (!val) return (0); \ + return (val->get_const_##_WRAPPED_TYPE()); \ + } + +WRAPPED_CLASS(Db, DbImp, DB) +WRAPPED_CLASS(DbChannel, DbChannelImp, DB_CHANNEL) +WRAPPED_CLASS(DbEnv, DbEnvImp, DB_ENV) +WRAPPED_CLASS(DbMpoolFile, DbMpoolFileImp, DB_MPOOLFILE) +WRAPPED_CLASS(DbSequence, DbSequenceImp, DB_SEQUENCE) +WRAPPED_CLASS(DbSite, DbSiteImp, DB_SITE) +WRAPPED_CLASS(DbTxn, DbTxnImp, DB_TXN) + +// A tristate integer value used by the DB_ERROR macro below. +// We chose not to make this an enumerated type so it can +// be kept private, even though methods that return the +// tristate int can be declared in db_cxx.h . +// +#define ON_ERROR_THROW 1 +#define ON_ERROR_RETURN 0 +#define ON_ERROR_UNKNOWN (-1) + +// Macros that handle detected errors, in case we want to +// change the default behavior. The 'policy' is one of +// the tristate values given above. If UNKNOWN is specified, +// the behavior is taken from the last initialized DbEnv. +// +#define DB_ERROR(dbenv, caller, ecode, policy) \ + DbEnv::runtime_error(dbenv, caller, ecode, policy) + +#define DB_ERROR_DBT(dbenv, caller, dbt, policy) \ + DbEnv::runtime_error_dbt(dbenv, caller, dbt, policy) + +#define DB_OVERFLOWED_DBT(dbt) \ + (F_ISSET(dbt, DB_DBT_USERMEM) && dbt->size > dbt->ulen) + +/* values for Db::flags_ */ +#define DB_CXX_PRIVATE_ENV 0x00000001 + +#endif /* !_DB_CXX_INT_H_ */ diff -r 000000000000 -r a1985f14b030 src/dbinc/db.in --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/dbinc/db.in Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,2595 @@ +/* + * See the file LICENSE for redistribution information. + * + * Copyright (c) 1996, 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + * $Id$ + * + * db.h include file layout: + * General. + * Database Environment. + * Locking subsystem. + * Logging subsystem. + * Shared buffer cache (mpool) subsystem. + * Transaction subsystem. + * Access methods. + * Access method cursors. + * Dbm/Ndbm, Hsearch historic interfaces. + */ + +#ifndef _DB_H_ +#define _DB_H_ + +#ifndef __NO_SYSTEM_INCLUDES +#include +@inttypes_h_decl@ +@stdint_h_decl@ +@stddef_h_decl@ +#include +@unistd_h_decl@ +@thread_h_decl@ +#endif + +@platform_header@ +#if defined(__cplusplus) +extern "C" { +#endif + +@DB_CONST@ +@DB_PROTO1@ +@DB_PROTO2@ + +/* + * Berkeley DB version information. + */ +#define DB_VERSION_FAMILY @DB_VERSION_FAMILY@ +#define DB_VERSION_RELEASE @DB_VERSION_RELEASE@ +#define DB_VERSION_MAJOR @DB_VERSION_MAJOR@ +#define DB_VERSION_MINOR @DB_VERSION_MINOR@ +#define DB_VERSION_PATCH @DB_VERSION_PATCH@ +#define DB_VERSION_STRING @DB_VERSION_STRING@ +#define DB_VERSION_FULL_STRING @DB_VERSION_FULL_STRING@ + +/* + * !!! + * Berkeley DB uses specifically sized types. If they're not provided by + * the system, typedef them here. + * + * We protect them against multiple inclusion using __BIT_TYPES_DEFINED__, + * as does BIND and Kerberos, since we don't know for sure what #include + * files the user is using. + * + * !!! + * We also provide the standard u_int, u_long etc., if they're not provided + * by the system. + */ +#ifndef __BIT_TYPES_DEFINED__ +#define __BIT_TYPES_DEFINED__ +@u_int8_decl@ +@int16_decl@ +@u_int16_decl@ +@int32_decl@ +@u_int32_decl@ +@int64_decl@ +@u_int64_decl@ +#endif + +@u_char_decl@ +@u_int_decl@ +@u_long_decl@ +@u_short_decl@ + +/* + * Missing ANSI types. + * + * uintmax_t -- + * Largest unsigned type, used to align structures in memory. We don't store + * floating point types in structures, so integral types should be sufficient + * (and we don't have to worry about systems that store floats in other than + * power-of-2 numbers of bytes). Additionally this fixes compilers that rewrite + * structure assignments and ANSI C memcpy calls to be in-line instructions + * that happen to require alignment. + * + * uintptr_t -- + * Unsigned type that's the same size as a pointer. There are places where + * DB modifies pointers by discarding the bottom bits to guarantee alignment. + * We can't use uintmax_t, it may be larger than the pointer, and compilers + * get upset about that. So far we haven't run on any machine where there's + * no unsigned type the same size as a pointer -- here's hoping. + */ +@uintmax_t_decl@ +@uintptr_t_decl@ + +@FILE_t_decl@ +@off_t_decl@ +@pid_t_decl@ +@size_t_decl@ +#ifdef HAVE_MIXED_SIZE_ADDRESSING +typedef u_int32_t db_size_t; +#else +typedef size_t db_size_t; +#endif +@ssize_t_decl@ +#ifdef HAVE_MIXED_SIZE_ADDRESSING +typedef int32_t db_ssize_t; +#else +typedef ssize_t db_ssize_t; +#endif +@time_t_decl@ + +/* + * Sequences are only available on machines with 64-bit integral types. + */ +@db_seq_decl@ + +/* Thread and process identification. */ +@db_threadid_t_decl@ + +/* Basic types that are exported or quasi-exported. */ +typedef u_int32_t db_pgno_t; /* Page number type. */ +typedef u_int16_t db_indx_t; /* Page offset type. */ +#define DB_MAX_PAGES 0xffffffff /* >= # of pages in a file */ + +typedef u_int32_t db_recno_t; /* Record number type. */ +#define DB_MAX_RECORDS 0xffffffff /* >= # of records in a tree */ + +typedef u_int32_t db_timeout_t; /* Type of a timeout. */ + +/* + * Region offsets are the difference between a pointer in a region and the + * region's base address. With private environments, both addresses are the + * result of calling malloc, and we can't assume anything about what malloc + * will return, so region offsets have to be able to hold differences between + * arbitrary pointers. + */ +typedef db_size_t roff_t; + +/* + * Forward structure declarations, so we can declare pointers and + * applications can get type checking. + */ +struct __channel; typedef struct __channel CHANNEL; +struct __db; typedef struct __db DB; +struct __db_bt_stat; typedef struct __db_bt_stat DB_BTREE_STAT; +struct __db_channel; typedef struct __db_channel DB_CHANNEL; +struct __db_cipher; typedef struct __db_cipher DB_CIPHER; +struct __db_compact; typedef struct __db_compact DB_COMPACT; +struct __db_dbt; typedef struct __db_dbt DBT; +struct __db_distab; typedef struct __db_distab DB_DISTAB; +struct __db_env; typedef struct __db_env DB_ENV; +struct __db_h_stat; typedef struct __db_h_stat DB_HASH_STAT; +struct __db_heap_rid; typedef struct __db_heap_rid DB_HEAP_RID; +struct __db_heap_stat; typedef struct __db_heap_stat DB_HEAP_STAT; +struct __db_ilock; typedef struct __db_ilock DB_LOCK_ILOCK; +struct __db_lock_hstat; typedef struct __db_lock_hstat DB_LOCK_HSTAT; +struct __db_lock_pstat; typedef struct __db_lock_pstat DB_LOCK_PSTAT; +struct __db_lock_stat; typedef struct __db_lock_stat DB_LOCK_STAT; +struct __db_lock_u; typedef struct __db_lock_u DB_LOCK; +struct __db_locker; typedef struct __db_locker DB_LOCKER; +struct __db_lockreq; typedef struct __db_lockreq DB_LOCKREQ; +struct __db_locktab; typedef struct __db_locktab DB_LOCKTAB; +struct __db_log; typedef struct __db_log DB_LOG; +struct __db_log_cursor; typedef struct __db_log_cursor DB_LOGC; +struct __db_log_stat; typedef struct __db_log_stat DB_LOG_STAT; +struct __db_lsn; typedef struct __db_lsn DB_LSN; +struct __db_mpool; typedef struct __db_mpool DB_MPOOL; +struct __db_mpool_fstat;typedef struct __db_mpool_fstat DB_MPOOL_FSTAT; +struct __db_mpool_stat; typedef struct __db_mpool_stat DB_MPOOL_STAT; +struct __db_mpoolfile; typedef struct __db_mpoolfile DB_MPOOLFILE; +struct __db_mutex_stat; typedef struct __db_mutex_stat DB_MUTEX_STAT; +struct __db_mutex_t; typedef struct __db_mutex_t DB_MUTEX; +struct __db_mutexmgr; typedef struct __db_mutexmgr DB_MUTEXMGR; +struct __db_preplist; typedef struct __db_preplist DB_PREPLIST; +struct __db_qam_stat; typedef struct __db_qam_stat DB_QUEUE_STAT; +struct __db_rep; typedef struct __db_rep DB_REP; +struct __db_rep_stat; typedef struct __db_rep_stat DB_REP_STAT; +struct __db_repmgr_conn_err; + typedef struct __db_repmgr_conn_err DB_REPMGR_CONN_ERR; +struct __db_repmgr_site;typedef struct __db_repmgr_site DB_REPMGR_SITE; +struct __db_repmgr_stat;typedef struct __db_repmgr_stat DB_REPMGR_STAT; +struct __db_seq_record; typedef struct __db_seq_record DB_SEQ_RECORD; +struct __db_seq_stat; typedef struct __db_seq_stat DB_SEQUENCE_STAT; +struct __db_site; typedef struct __db_site DB_SITE; +struct __db_sequence; typedef struct __db_sequence DB_SEQUENCE; +struct __db_thread_info;typedef struct __db_thread_info DB_THREAD_INFO; +struct __db_txn; typedef struct __db_txn DB_TXN; +struct __db_txn_active; typedef struct __db_txn_active DB_TXN_ACTIVE; +struct __db_txn_stat; typedef struct __db_txn_stat DB_TXN_STAT; +struct __db_txn_token; typedef struct __db_txn_token DB_TXN_TOKEN; +struct __db_txnmgr; typedef struct __db_txnmgr DB_TXNMGR; +struct __dbc; typedef struct __dbc DBC; +struct __dbc_internal; typedef struct __dbc_internal DBC_INTERNAL; +struct __env; typedef struct __env ENV; +struct __fh_t; typedef struct __fh_t DB_FH; +struct __fname; typedef struct __fname FNAME; +struct __key_range; typedef struct __key_range DB_KEY_RANGE; +struct __mpoolfile; typedef struct __mpoolfile MPOOLFILE; +struct __db_logvrfy_config; +typedef struct __db_logvrfy_config DB_LOG_VERIFY_CONFIG; + +/* + * The Berkeley DB API flags are automatically-generated -- the following flag + * names are no longer used, but remain for compatibility reasons. + */ +#define DB_DEGREE_2 DB_READ_COMMITTED +#define DB_DIRTY_READ DB_READ_UNCOMMITTED +#define DB_JOINENV 0x0 + +/* Key/data structure -- a Data-Base Thang. */ +struct __db_dbt { + void *data; /* Key/data */ + u_int32_t size; /* key/data length */ + + u_int32_t ulen; /* RO: length of user buffer. */ + u_int32_t dlen; /* RO: get/put record length. */ + u_int32_t doff; /* RO: get/put record offset. */ + + void *app_data; + +#define DB_DBT_APPMALLOC 0x001 /* Callback allocated memory. */ +#define DB_DBT_BULK 0x002 /* Internal: Insert if duplicate. */ +#define DB_DBT_DUPOK 0x004 /* Internal: Insert if duplicate. */ +#define DB_DBT_ISSET 0x008 /* Lower level calls set value. */ +#define DB_DBT_MALLOC 0x010 /* Return in malloc'd memory. */ +#define DB_DBT_MULTIPLE 0x020 /* References multiple records. */ +#define DB_DBT_PARTIAL 0x040 /* Partial put/get. */ +#define DB_DBT_REALLOC 0x080 /* Return in realloc'd memory. */ +#define DB_DBT_READONLY 0x100 /* Readonly, don't update. */ +#define DB_DBT_STREAMING 0x200 /* Internal: DBT is being streamed. */ +#define DB_DBT_USERCOPY 0x400 /* Use the user-supplied callback. */ +#define DB_DBT_USERMEM 0x800 /* Return in user's memory. */ + u_int32_t flags; +}; + +/******************************************************* + * Mutexes. + *******************************************************/ +/* + * When mixed size addressing is supported mutexes need to be the same size + * independent of the process address size is. + */ +#ifdef HAVE_MIXED_SIZE_ADDRESSING +typedef db_size_t db_mutex_t; +#else +typedef uintptr_t db_mutex_t; +#endif + +struct __db_mutex_stat { /* SHARED */ + /* The following fields are maintained in the region's copy. */ + u_int32_t st_mutex_align; /* Mutex alignment */ + u_int32_t st_mutex_tas_spins; /* Mutex test-and-set spins */ + u_int32_t st_mutex_init; /* Initial mutex count */ + u_int32_t st_mutex_cnt; /* Mutex count */ + u_int32_t st_mutex_max; /* Mutex max */ + u_int32_t st_mutex_free; /* Available mutexes */ + u_int32_t st_mutex_inuse; /* Mutexes in use */ + u_int32_t st_mutex_inuse_max; /* Maximum mutexes ever in use */ + + /* The following fields are filled-in from other places. */ +#ifndef __TEST_DB_NO_STATISTICS + uintmax_t st_region_wait; /* Region lock granted after wait. */ + uintmax_t st_region_nowait; /* Region lock granted without wait. */ + roff_t st_regsize; /* Region size. */ + roff_t st_regmax; /* Region max. */ +#endif +}; + +/* This is the length of the buffer passed to DB_ENV->thread_id_string() */ +#define DB_THREADID_STRLEN 128 + +/******************************************************* + * Locking. + *******************************************************/ +#define DB_LOCKVERSION 1 + +#define DB_FILE_ID_LEN 20 /* Unique file ID length. */ + +/* + * Deadlock detector modes; used in the DB_ENV structure to configure the + * locking subsystem. + */ +#define DB_LOCK_NORUN 0 +#define DB_LOCK_DEFAULT 1 /* Default policy. */ +#define DB_LOCK_EXPIRE 2 /* Only expire locks, no detection. */ +#define DB_LOCK_MAXLOCKS 3 /* Select locker with max locks. */ +#define DB_LOCK_MAXWRITE 4 /* Select locker with max writelocks. */ +#define DB_LOCK_MINLOCKS 5 /* Select locker with min locks. */ +#define DB_LOCK_MINWRITE 6 /* Select locker with min writelocks. */ +#define DB_LOCK_OLDEST 7 /* Select oldest locker. */ +#define DB_LOCK_RANDOM 8 /* Select random locker. */ +#define DB_LOCK_YOUNGEST 9 /* Select youngest locker. */ + +/* + * Simple R/W lock modes and for multi-granularity intention locking. + * + * !!! + * These values are NOT random, as they are used as an index into the lock + * conflicts arrays, i.e., DB_LOCK_IWRITE must be == 3, and DB_LOCK_IREAD + * must be == 4. + */ +typedef enum { + DB_LOCK_NG=0, /* Not granted. */ + DB_LOCK_READ=1, /* Shared/read. */ + DB_LOCK_WRITE=2, /* Exclusive/write. */ + DB_LOCK_WAIT=3, /* Wait for event */ + DB_LOCK_IWRITE=4, /* Intent exclusive/write. */ + DB_LOCK_IREAD=5, /* Intent to share/read. */ + DB_LOCK_IWR=6, /* Intent to read and write. */ + DB_LOCK_READ_UNCOMMITTED=7, /* Degree 1 isolation. */ + DB_LOCK_WWRITE=8 /* Was Written. */ +} db_lockmode_t; + +/* + * Request types. + */ +typedef enum { + DB_LOCK_DUMP=0, /* Display held locks. */ + DB_LOCK_GET=1, /* Get the lock. */ + DB_LOCK_GET_TIMEOUT=2, /* Get lock with a timeout. */ + DB_LOCK_INHERIT=3, /* Pass locks to parent. */ + DB_LOCK_PUT=4, /* Release the lock. */ + DB_LOCK_PUT_ALL=5, /* Release locker's locks. */ + DB_LOCK_PUT_OBJ=6, /* Release locker's locks on obj. */ + DB_LOCK_PUT_READ=7, /* Release locker's read locks. */ + DB_LOCK_TIMEOUT=8, /* Force a txn to timeout. */ + DB_LOCK_TRADE=9, /* Trade locker ids on a lock. */ + DB_LOCK_UPGRADE_WRITE=10 /* Upgrade writes for dirty reads. */ +} db_lockop_t; + +/* + * Status of a lock. + */ +typedef enum { + DB_LSTAT_ABORTED=1, /* Lock belongs to an aborted txn. */ + DB_LSTAT_EXPIRED=2, /* Lock has expired. */ + DB_LSTAT_FREE=3, /* Lock is unallocated. */ + DB_LSTAT_HELD=4, /* Lock is currently held. */ + DB_LSTAT_PENDING=5, /* Lock was waiting and has been + * promoted; waiting for the owner + * to run and upgrade it to held. */ + DB_LSTAT_WAITING=6 /* Lock is on the wait queue. */ +}db_status_t; + +/* Lock statistics structure. */ +struct __db_lock_stat { /* SHARED */ + u_int32_t st_id; /* Last allocated locker ID. */ + u_int32_t st_cur_maxid; /* Current maximum unused ID. */ + u_int32_t st_initlocks; /* Initial number of locks in table. */ + u_int32_t st_initlockers; /* Initial num of lockers in table. */ + u_int32_t st_initobjects; /* Initial num of objects in table. */ + u_int32_t st_locks; /* Current number of locks in table. */ + u_int32_t st_lockers; /* Current num of lockers in table. */ + u_int32_t st_objects; /* Current num of objects in table. */ + u_int32_t st_maxlocks; /* Maximum number of locks in table. */ + u_int32_t st_maxlockers; /* Maximum num of lockers in table. */ + u_int32_t st_maxobjects; /* Maximum num of objects in table. */ + u_int32_t st_partitions; /* number of partitions. */ + u_int32_t st_tablesize; /* Size of object hash table. */ + int32_t st_nmodes; /* Number of lock modes. */ + u_int32_t st_nlockers; /* Current number of lockers. */ +#ifndef __TEST_DB_NO_STATISTICS + u_int32_t st_nlocks; /* Current number of locks. */ + u_int32_t st_maxnlocks; /* Maximum number of locks so far. */ + u_int32_t st_maxhlocks; /* Maximum number of locks in any bucket. */ + uintmax_t st_locksteals; /* Number of lock steals so far. */ + uintmax_t st_maxlsteals; /* Maximum number steals in any partition. */ + u_int32_t st_maxnlockers; /* Maximum number of lockers so far. */ + u_int32_t st_nobjects; /* Current number of objects. */ + u_int32_t st_maxnobjects; /* Maximum number of objects so far. */ + u_int32_t st_maxhobjects; /* Maximum number of objectsin any bucket. */ + uintmax_t st_objectsteals; /* Number of objects steals so far. */ + uintmax_t st_maxosteals; /* Maximum number of steals in any partition. */ + uintmax_t st_nrequests; /* Number of lock gets. */ + uintmax_t st_nreleases; /* Number of lock puts. */ + uintmax_t st_nupgrade; /* Number of lock upgrades. */ + uintmax_t st_ndowngrade; /* Number of lock downgrades. */ + uintmax_t st_lock_wait; /* Lock conflicts w/ subsequent wait */ + uintmax_t st_lock_nowait; /* Lock conflicts w/o subsequent wait */ + uintmax_t st_ndeadlocks; /* Number of lock deadlocks. */ + db_timeout_t st_locktimeout; /* Lock timeout. */ + uintmax_t st_nlocktimeouts; /* Number of lock timeouts. */ + db_timeout_t st_txntimeout; /* Transaction timeout. */ + uintmax_t st_ntxntimeouts; /* Number of transaction timeouts. */ + uintmax_t st_part_wait; /* Partition lock granted after wait. */ + uintmax_t st_part_nowait; /* Partition lock granted without wait. */ + uintmax_t st_part_max_wait; /* Max partition lock granted after wait. */ + uintmax_t st_part_max_nowait; /* Max partition lock granted without wait. */ + uintmax_t st_objs_wait; /* Object lock granted after wait. */ + uintmax_t st_objs_nowait; /* Object lock granted without wait. */ + uintmax_t st_lockers_wait; /* Locker lock granted after wait. */ + uintmax_t st_lockers_nowait; /* Locker lock granted without wait. */ + uintmax_t st_region_wait; /* Region lock granted after wait. */ + uintmax_t st_region_nowait; /* Region lock granted without wait. */ + u_int32_t st_hash_len; /* Max length of bucket. */ + roff_t st_regsize; /* Region size. */ +#endif +}; + +struct __db_lock_hstat { /* SHARED */ + uintmax_t st_nrequests; /* Number of lock gets. */ + uintmax_t st_nreleases; /* Number of lock puts. */ + uintmax_t st_nupgrade; /* Number of lock upgrades. */ + uintmax_t st_ndowngrade; /* Number of lock downgrades. */ + u_int32_t st_nlocks; /* Current number of locks. */ + u_int32_t st_maxnlocks; /* Maximum number of locks so far. */ + u_int32_t st_nobjects; /* Current number of objects. */ + u_int32_t st_maxnobjects; /* Maximum number of objects so far. */ + uintmax_t st_lock_wait; /* Lock conflicts w/ subsequent wait */ + uintmax_t st_lock_nowait; /* Lock conflicts w/o subsequent wait */ + uintmax_t st_nlocktimeouts; /* Number of lock timeouts. */ + uintmax_t st_ntxntimeouts; /* Number of transaction timeouts. */ + u_int32_t st_hash_len; /* Max length of bucket. */ +}; + +struct __db_lock_pstat { /* SHARED */ + u_int32_t st_nlocks; /* Current number of locks. */ + u_int32_t st_maxnlocks; /* Maximum number of locks so far. */ + u_int32_t st_nobjects; /* Current number of objects. */ + u_int32_t st_maxnobjects; /* Maximum number of objects so far. */ + uintmax_t st_locksteals; /* Number of lock steals so far. */ + uintmax_t st_objectsteals; /* Number of objects steals so far. */ +}; + +/* + * DB_LOCK_ILOCK -- + * Internal DB access method lock. + */ +struct __db_ilock { /* SHARED */ + db_pgno_t pgno; /* Page being locked. */ + u_int8_t fileid[DB_FILE_ID_LEN];/* File id. */ +#define DB_HANDLE_LOCK 1 +#define DB_RECORD_LOCK 2 +#define DB_PAGE_LOCK 3 +#define DB_DATABASE_LOCK 4 + u_int32_t type; /* Type of lock. */ +}; + +/* + * DB_LOCK -- + * The structure is allocated by the caller and filled in during a + * lock_get request (or a lock_vec/DB_LOCK_GET). + */ +struct __db_lock_u { /* SHARED */ + roff_t off; /* Offset of the lock in the region */ + u_int32_t ndx; /* Index of the object referenced by + * this lock; used for locking. */ + u_int32_t gen; /* Generation number of this lock. */ + db_lockmode_t mode; /* mode of this lock. */ +}; + +/* Lock request structure. */ +struct __db_lockreq { + db_lockop_t op; /* Operation. */ + db_lockmode_t mode; /* Requested mode. */ + db_timeout_t timeout; /* Time to expire lock. */ + DBT *obj; /* Object being locked. */ + DB_LOCK lock; /* Lock returned. */ +}; + +/******************************************************* + * Logging. + *******************************************************/ +#define DB_LOGVERSION 20 /* Current log version. */ +#define DB_LOGVERSION_LATCHING 15 /* Log version using latching: db-4.8 */ +#define DB_LOGCHKSUM 12 /* Check sum headers: db-4.5 */ +#define DB_LOGOLDVER 8 /* Oldest version supported: db-4.2 */ +#define DB_LOGMAGIC 0x040988 + +/* + * A DB_LSN has two parts, a fileid which identifies a specific file, and an + * offset within that file. The fileid is an unsigned 4-byte quantity that + * uniquely identifies a file within the log directory -- currently a simple + * counter inside the log. The offset is also an unsigned 4-byte value. The + * log manager guarantees the offset is never more than 4 bytes by switching + * to a new log file before the maximum length imposed by an unsigned 4-byte + * offset is reached. + */ +struct __db_lsn { /* SHARED */ + u_int32_t file; /* File ID. */ + u_int32_t offset; /* File offset. */ +}; + +/* + * Application-specified log record types start at DB_user_BEGIN, and must not + * equal or exceed DB_debug_FLAG. + * + * DB_debug_FLAG is the high-bit of the u_int32_t that specifies a log record + * type. If the flag is set, it's a log record that was logged for debugging + * purposes only, even if it reflects a database change -- the change was part + * of a non-durable transaction. + */ +#define DB_user_BEGIN 10000 +#define DB_debug_FLAG 0x80000000 + +/* + * DB_LOGC -- + * Log cursor. + */ +struct __db_log_cursor { + ENV *env; /* Environment */ + + DB_FH *fhp; /* File handle. */ + DB_LSN lsn; /* Cursor: LSN */ + u_int32_t len; /* Cursor: record length */ + u_int32_t prev; /* Cursor: previous record's offset */ + + DBT dbt; /* Return DBT. */ + DB_LSN p_lsn; /* Persist LSN. */ + u_int32_t p_version; /* Persist version. */ + + u_int8_t *bp; /* Allocated read buffer. */ + u_int32_t bp_size; /* Read buffer length in bytes. */ + u_int32_t bp_rlen; /* Read buffer valid data length. */ + DB_LSN bp_lsn; /* Read buffer first byte LSN. */ + + u_int32_t bp_maxrec; /* Max record length in the log file. */ + + /* DB_LOGC PUBLIC HANDLE LIST BEGIN */ + int (*close) __P((DB_LOGC *, u_int32_t)); + int (*get) __P((DB_LOGC *, DB_LSN *, DBT *, u_int32_t)); + int (*version) __P((DB_LOGC *, u_int32_t *, u_int32_t)); + /* DB_LOGC PUBLIC HANDLE LIST END */ + +#define DB_LOG_DISK 0x01 /* Log record came from disk. */ +#define DB_LOG_LOCKED 0x02 /* Log region already locked */ +#define DB_LOG_SILENT_ERR 0x04 /* Turn-off error messages. */ + u_int32_t flags; +}; + +/* Log statistics structure. */ +struct __db_log_stat { /* SHARED */ + u_int32_t st_magic; /* Log file magic number. */ + u_int32_t st_version; /* Log file version number. */ + int32_t st_mode; /* Log file permissions mode. */ + u_int32_t st_lg_bsize; /* Log buffer size. */ + u_int32_t st_lg_size; /* Log file size. */ + u_int32_t st_wc_bytes; /* Bytes to log since checkpoint. */ + u_int32_t st_wc_mbytes; /* Megabytes to log since checkpoint. */ + u_int32_t st_fileid_init; /* Initial allocation for fileids. */ +#ifndef __TEST_DB_NO_STATISTICS + u_int32_t st_nfileid; /* Current number of fileids. */ + u_int32_t st_maxnfileid; /* Maximum number of fileids used. */ + uintmax_t st_record; /* Records entered into the log. */ + u_int32_t st_w_bytes; /* Bytes to log. */ + u_int32_t st_w_mbytes; /* Megabytes to log. */ + uintmax_t st_wcount; /* Total I/O writes to the log. */ + uintmax_t st_wcount_fill; /* Overflow writes to the log. */ + uintmax_t st_rcount; /* Total I/O reads from the log. */ + uintmax_t st_scount; /* Total syncs to the log. */ + uintmax_t st_region_wait; /* Region lock granted after wait. */ + uintmax_t st_region_nowait; /* Region lock granted without wait. */ + u_int32_t st_cur_file; /* Current log file number. */ + u_int32_t st_cur_offset; /* Current log file offset. */ + u_int32_t st_disk_file; /* Known on disk log file number. */ + u_int32_t st_disk_offset; /* Known on disk log file offset. */ + u_int32_t st_maxcommitperflush; /* Max number of commits in a flush. */ + u_int32_t st_mincommitperflush; /* Min number of commits in a flush. */ + roff_t st_regsize; /* Region size. */ +#endif +}; + +/* + * We need to record the first log record of a transaction. For user + * defined logging this macro returns the place to put that information, + * if it is need in rlsnp, otherwise it leaves it unchanged. We also + * need to track the last record of the transaction, this returns the + * place to put that info. + */ +#define DB_SET_TXN_LSNP(txn, blsnp, llsnp) \ + ((txn)->set_txn_lsnp(txn, blsnp, llsnp)) + +/* + * Definition of the structure which specifies marshalling of log records. + */ +typedef enum { + LOGREC_Done, + LOGREC_ARG, + LOGREC_HDR, + LOGREC_DATA, + LOGREC_DB, + LOGREC_DBOP, + LOGREC_DBT, + LOGREC_LOCKS, + LOGREC_OP, + LOGREC_PGDBT, + LOGREC_PGDDBT, + LOGREC_PGLIST, + LOGREC_POINTER, + LOGREC_TIME +} log_rec_type_t; + +typedef const struct __log_rec_spec { + log_rec_type_t type; + u_int32_t offset; + const char *name; + const char fmt[4]; +} DB_LOG_RECSPEC; + +/* + * Size of a DBT in a log record. + */ +#define LOG_DBT_SIZE(dbt) \ + (sizeof(u_int32_t) + ((dbt) == NULL ? 0 : (dbt)->size)) + +/******************************************************* + * Shared buffer cache (mpool). + *******************************************************/ +/* Priority values for DB_MPOOLFILE->{put,set_priority}. */ +typedef enum { + DB_PRIORITY_UNCHANGED=0, + DB_PRIORITY_VERY_LOW=1, + DB_PRIORITY_LOW=2, + DB_PRIORITY_DEFAULT=3, + DB_PRIORITY_HIGH=4, + DB_PRIORITY_VERY_HIGH=5 +} DB_CACHE_PRIORITY; + +/* Per-process DB_MPOOLFILE information. */ +struct __db_mpoolfile { + DB_FH *fhp; /* Underlying file handle. */ + + /* + * !!! + * The ref, pinref and q fields are protected by the region lock. + */ + u_int32_t ref; /* Reference count. */ + + u_int32_t pinref; /* Pinned block reference count. */ + + /* + * !!! + * Explicit representations of structures from queue.h. + * TAILQ_ENTRY(__db_mpoolfile) q; + */ + struct { + struct __db_mpoolfile *tqe_next; + struct __db_mpoolfile **tqe_prev; + } q; /* Linked list of DB_MPOOLFILE's. */ + + /* + * !!! + * The rest of the fields (with the exception of the MP_FLUSH flag) + * are not thread-protected, even when they may be modified at any + * time by the application. The reason is the DB_MPOOLFILE handle + * is single-threaded from the viewpoint of the application, and so + * the only fields needing to be thread-protected are those accessed + * by checkpoint or sync threads when using DB_MPOOLFILE structures + * to flush buffers from the cache. + */ + ENV *env; /* Environment */ + MPOOLFILE *mfp; /* Underlying MPOOLFILE. */ + + u_int32_t clear_len; /* Cleared length on created pages. */ + u_int8_t /* Unique file ID. */ + fileid[DB_FILE_ID_LEN]; + int ftype; /* File type. */ + int32_t lsn_offset; /* LSN offset in page. */ + u_int32_t gbytes, bytes; /* Maximum file size. */ + DBT *pgcookie; /* Byte-string passed to pgin/pgout. */ + int32_t priority; /* Cache priority. */ + + void *addr; /* Address of mmap'd region. */ + size_t len; /* Length of mmap'd region. */ + + u_int32_t config_flags; /* Flags to DB_MPOOLFILE->set_flags. */ + + /* DB_MPOOLFILE PUBLIC HANDLE LIST BEGIN */ + int (*close) __P((DB_MPOOLFILE *, u_int32_t)); + int (*get) + __P((DB_MPOOLFILE *, db_pgno_t *, DB_TXN *, u_int32_t, void *)); + int (*get_clear_len) __P((DB_MPOOLFILE *, u_int32_t *)); + int (*get_fileid) __P((DB_MPOOLFILE *, u_int8_t *)); + int (*get_flags) __P((DB_MPOOLFILE *, u_int32_t *)); + int (*get_ftype) __P((DB_MPOOLFILE *, int *)); + int (*get_last_pgno) __P((DB_MPOOLFILE *, db_pgno_t *)); + int (*get_lsn_offset) __P((DB_MPOOLFILE *, int32_t *)); + int (*get_maxsize) __P((DB_MPOOLFILE *, u_int32_t *, u_int32_t *)); + int (*get_pgcookie) __P((DB_MPOOLFILE *, DBT *)); + int (*get_priority) __P((DB_MPOOLFILE *, DB_CACHE_PRIORITY *)); + int (*open) __P((DB_MPOOLFILE *, const char *, u_int32_t, int, size_t)); + int (*put) __P((DB_MPOOLFILE *, void *, DB_CACHE_PRIORITY, u_int32_t)); + int (*set_clear_len) __P((DB_MPOOLFILE *, u_int32_t)); + int (*set_fileid) __P((DB_MPOOLFILE *, u_int8_t *)); + int (*set_flags) __P((DB_MPOOLFILE *, u_int32_t, int)); + int (*set_ftype) __P((DB_MPOOLFILE *, int)); + int (*set_lsn_offset) __P((DB_MPOOLFILE *, int32_t)); + int (*set_maxsize) __P((DB_MPOOLFILE *, u_int32_t, u_int32_t)); + int (*set_pgcookie) __P((DB_MPOOLFILE *, DBT *)); + int (*set_priority) __P((DB_MPOOLFILE *, DB_CACHE_PRIORITY)); + int (*sync) __P((DB_MPOOLFILE *)); + /* DB_MPOOLFILE PUBLIC HANDLE LIST END */ + + /* + * MP_FILEID_SET, MP_OPEN_CALLED and MP_READONLY do not need to be + * thread protected because they are initialized before the file is + * linked onto the per-process lists, and never modified. + * + * MP_FLUSH is thread protected because it is potentially read/set by + * multiple threads of control. + */ +#define MP_FILEID_SET 0x001 /* Application supplied a file ID. */ +#define MP_FLUSH 0x002 /* Was used to flush a buffer. */ +#define MP_FOR_FLUSH 0x004 /* Was opened to flush a buffer. */ +#define MP_MULTIVERSION 0x008 /* Opened for multiversion access. */ +#define MP_OPEN_CALLED 0x010 /* File opened. */ +#define MP_READONLY 0x020 /* File is readonly. */ +#define MP_DUMMY 0x040 /* File is dummy for __memp_fput. */ + u_int32_t flags; +}; + +/* Mpool statistics structure. */ +struct __db_mpool_stat { /* SHARED */ + u_int32_t st_gbytes; /* Total cache size: GB. */ + u_int32_t st_bytes; /* Total cache size: B. */ + u_int32_t st_ncache; /* Number of cache regions. */ + u_int32_t st_max_ncache; /* Maximum number of regions. */ + db_size_t st_mmapsize; /* Maximum file size for mmap. */ + int32_t st_maxopenfd; /* Maximum number of open fd's. */ + int32_t st_maxwrite; /* Maximum buffers to write. */ + db_timeout_t st_maxwrite_sleep; /* Sleep after writing max buffers. */ + u_int32_t st_pages; /* Total number of pages. */ +#ifndef __TEST_DB_NO_STATISTICS + u_int32_t st_map; /* Pages from mapped files. */ + uintmax_t st_cache_hit; /* Pages found in the cache. */ + uintmax_t st_cache_miss; /* Pages not found in the cache. */ + uintmax_t st_page_create; /* Pages created in the cache. */ + uintmax_t st_page_in; /* Pages read in. */ + uintmax_t st_page_out; /* Pages written out. */ + uintmax_t st_ro_evict; /* Clean pages forced from the cache. */ + uintmax_t st_rw_evict; /* Dirty pages forced from the cache. */ + uintmax_t st_page_trickle; /* Pages written by memp_trickle. */ + u_int32_t st_page_clean; /* Clean pages. */ + u_int32_t st_page_dirty; /* Dirty pages. */ + u_int32_t st_hash_buckets; /* Number of hash buckets. */ + u_int32_t st_hash_mutexes; /* Number of hash bucket mutexes. */ + u_int32_t st_pagesize; /* Assumed page size. */ + u_int32_t st_hash_searches; /* Total hash chain searches. */ + u_int32_t st_hash_longest; /* Longest hash chain searched. */ + uintmax_t st_hash_examined; /* Total hash entries searched. */ + uintmax_t st_hash_nowait; /* Hash lock granted with nowait. */ + uintmax_t st_hash_wait; /* Hash lock granted after wait. */ + uintmax_t st_hash_max_nowait; /* Max hash lock granted with nowait. */ + uintmax_t st_hash_max_wait; /* Max hash lock granted after wait. */ + uintmax_t st_region_nowait; /* Region lock granted with nowait. */ + uintmax_t st_region_wait; /* Region lock granted after wait. */ + uintmax_t st_mvcc_frozen; /* Buffers frozen. */ + uintmax_t st_mvcc_thawed; /* Buffers thawed. */ + uintmax_t st_mvcc_freed; /* Frozen buffers freed. */ + uintmax_t st_alloc; /* Number of page allocations. */ + uintmax_t st_alloc_buckets; /* Buckets checked during allocation. */ + uintmax_t st_alloc_max_buckets;/* Max checked during allocation. */ + uintmax_t st_alloc_pages; /* Pages checked during allocation. */ + uintmax_t st_alloc_max_pages; /* Max checked during allocation. */ + uintmax_t st_io_wait; /* Thread waited on buffer I/O. */ + uintmax_t st_sync_interrupted; /* Number of times sync interrupted. */ + uintmax_t st_oddfsize_detect; /* Odd file size detected. */ + uintmax_t st_oddfsize_resolve; /* Odd file size resolved. */ + roff_t st_regsize; /* Region size. */ + roff_t st_regmax; /* Region max. */ +#endif +}; + +/* + * Mpool file statistics structure. + * The first fields in this structure must mirror the __db_mpool_fstat_int + * structure, since content is mem copied between the two. + */ +struct __db_mpool_fstat { + u_int32_t st_pagesize; /* Page size. */ +#ifndef __TEST_DB_NO_STATISTICS + u_int32_t st_map; /* Pages from mapped files. */ + uintmax_t st_cache_hit; /* Pages found in the cache. */ + uintmax_t st_cache_miss; /* Pages not found in the cache. */ + uintmax_t st_page_create; /* Pages created in the cache. */ + uintmax_t st_page_in; /* Pages read in. */ + uintmax_t st_page_out; /* Pages written out. */ + uintmax_t st_backup_spins; /* Number of spins during a copy. */ +#endif + char *file_name; /* File name. */ +}; + +/******************************************************* + * Transactions and recovery. + *******************************************************/ +#define DB_TXNVERSION 1 + +typedef enum { + DB_TXN_ABORT=0, /* Public. */ + DB_TXN_APPLY=1, /* Public. */ + DB_TXN_BACKWARD_ROLL=3, /* Public. */ + DB_TXN_FORWARD_ROLL=4, /* Public. */ + DB_TXN_OPENFILES=5, /* Internal. */ + DB_TXN_POPENFILES=6, /* Internal. */ + DB_TXN_PRINT=7, /* Public. */ + DB_TXN_LOG_VERIFY=8 /* Internal. */ +} db_recops; + +/* + * BACKWARD_ALLOC is used during the forward pass to pick up any aborted + * allocations for files that were created during the forward pass. + * The main difference between _ALLOC and _ROLL is that the entry for + * the file not exist during the rollforward pass. + */ +#define DB_UNDO(op) ((op) == DB_TXN_ABORT || (op) == DB_TXN_BACKWARD_ROLL) +#define DB_REDO(op) ((op) == DB_TXN_FORWARD_ROLL || (op) == DB_TXN_APPLY) + +struct __db_txn { + DB_TXNMGR *mgrp; /* Pointer to transaction manager. */ + DB_TXN *parent; /* Pointer to transaction's parent. */ + DB_LOCKER *locker; /* Locker for this txn. */ + DB_THREAD_INFO *thread_info; /* Pointer to thread information. */ + + void *td; /* Detail structure within region. */ + db_timeout_t lock_timeout; /* Timeout for locks for this txn. */ + + /* + * !!! + * Explicit representations of structures from queue.h. + * TAILQ_HEAD(__kids, __db_txn) kids; + */ + struct __kids { + struct __db_txn *tqh_first; + struct __db_txn **tqh_last; + } kids; + + /* + * !!! + * Explicit representations of structures from queue.h. + * TAILQ_HEAD(__my_cursors, __dbc) my_cursors; + */ + struct __my_cursors { + struct __dbc *tqh_first; + struct __dbc **tqh_last; + } my_cursors; + u_int32_t cursors; /* Number of cursors open for txn */ + u_int32_t txnid; /* Unique transaction id. */ + + void *api_internal; /* C++ API private. */ + + /* + * !!! + * Explicit representations of structures from queue.h. + * TAILQ_HEAD(__femfs, MPOOLFILE) femfs; + * + * These are DBs involved in file extension in this transaction. + */ + struct __femfs { + DB *tqh_first; + DB **tqh_last; + } femfs; + + DB_TXN_TOKEN *token_buffer; /* User's commit token buffer. */ + void *xml_internal; /* XML API private. */ + +#define TXN_XA_THREAD_NOTA 0 +#define TXN_XA_THREAD_ASSOCIATED 1 +#define TXN_XA_THREAD_SUSPENDED 2 +#define TXN_XA_THREAD_UNASSOCIATED 3 + u_int32_t xa_thr_status; + +#define TXN_CHILDCOMMIT 0x00001 /* Txn has committed. */ +#define TXN_COMPENSATE 0x00002 /* Compensating transaction. */ +#define TXN_DEADLOCK 0x00004 /* Txn has deadlocked. */ +#define TXN_FAMILY 0x00008 /* Cursors/children are independent. */ +#define TXN_IGNORE_LEASE 0x00010 /* Skip lease check at commit time. */ +#define TXN_INFAMILY 0x00020 /* Part of a transaction family. */ +#define TXN_LOCKTIMEOUT 0x00040 /* Txn has a lock timeout. */ +#define TXN_MALLOC 0x00080 /* Structure allocated by TXN system. */ +#define TXN_NOSYNC 0x00100 /* Do not sync on prepare and commit. */ +#define TXN_NOWAIT 0x00200 /* Do not wait on locks. */ +#define TXN_PRIVATE 0x00400 /* Txn owned by cursor. */ +#define TXN_READONLY 0x00800 /* CDS group handle. */ +#define TXN_READ_COMMITTED 0x01000 /* Txn has degree 2 isolation. */ +#define TXN_READ_UNCOMMITTED 0x02000 /* Txn has degree 1 isolation. */ +#define TXN_RESTORED 0x04000 /* Txn has been restored. */ +#define TXN_SNAPSHOT 0x08000 /* Snapshot Isolation. */ +#define TXN_SYNC 0x10000 /* Write and sync on prepare/commit. */ +#define TXN_WRITE_NOSYNC 0x20000 /* Write only on prepare/commit. */ +#define TXN_BULK 0x40000 /* Enable bulk loading optimization. */ + u_int32_t flags; +}; + +#define TXN_SYNC_FLAGS (TXN_SYNC | TXN_NOSYNC | TXN_WRITE_NOSYNC) + +/* + * Structure used for two phase commit interface. + * We set the size of our global transaction id (gid) to be 128 in order + * to match that defined by the XA X/Open standard. + */ +#define DB_GID_SIZE 128 +struct __db_preplist { + DB_TXN *txn; + u_int8_t gid[DB_GID_SIZE]; +}; + +/* Transaction statistics structure. */ +struct __db_txn_active { + u_int32_t txnid; /* Transaction ID */ + u_int32_t parentid; /* Transaction ID of parent */ + pid_t pid; /* Process owning txn ID */ + db_threadid_t tid; /* Thread owning txn ID */ + + DB_LSN lsn; /* LSN when transaction began */ + + DB_LSN read_lsn; /* Read LSN for MVCC */ + u_int32_t mvcc_ref; /* MVCC reference count */ + + u_int32_t priority; /* Deadlock resolution priority */ + +#define TXN_ABORTED 1 +#define TXN_COMMITTED 2 +#define TXN_NEED_ABORT 3 +#define TXN_PREPARED 4 +#define TXN_RUNNING 5 + u_int32_t status; /* Status of the transaction */ + +#define TXN_XA_ACTIVE 1 +#define TXN_XA_DEADLOCKED 2 +#define TXN_XA_IDLE 3 +#define TXN_XA_PREPARED 4 +#define TXN_XA_ROLLEDBACK 5 + u_int32_t xa_status; /* XA status */ + + u_int8_t gid[DB_GID_SIZE]; /* Global transaction ID */ + char name[51]; /* 50 bytes of name, nul termination */ +}; + +struct __db_txn_stat { + u_int32_t st_nrestores; /* number of restored transactions + after recovery. */ +#ifndef __TEST_DB_NO_STATISTICS + DB_LSN st_last_ckp; /* lsn of the last checkpoint */ + time_t st_time_ckp; /* time of last checkpoint */ + u_int32_t st_last_txnid; /* last transaction id given out */ + u_int32_t st_inittxns; /* inital txns allocated */ + u_int32_t st_maxtxns; /* maximum txns possible */ + uintmax_t st_naborts; /* number of aborted transactions */ + uintmax_t st_nbegins; /* number of begun transactions */ + uintmax_t st_ncommits; /* number of committed transactions */ + u_int32_t st_nactive; /* number of active transactions */ + u_int32_t st_nsnapshot; /* number of snapshot transactions */ + u_int32_t st_maxnactive; /* maximum active transactions */ + u_int32_t st_maxnsnapshot; /* maximum snapshot transactions */ + uintmax_t st_region_wait; /* Region lock granted after wait. */ + uintmax_t st_region_nowait; /* Region lock granted without wait. */ + roff_t st_regsize; /* Region size. */ + DB_TXN_ACTIVE *st_txnarray; /* array of active transactions */ +#endif +}; + +#define DB_TXN_TOKEN_SIZE 20 +struct __db_txn_token { + u_int8_t buf[DB_TXN_TOKEN_SIZE]; +}; + +/******************************************************* + * Replication. + *******************************************************/ +/* Special, out-of-band environment IDs. */ +#define DB_EID_BROADCAST -1 +#define DB_EID_INVALID -2 +#define DB_EID_MASTER -3 + +#define DB_REP_DEFAULT_PRIORITY 100 + +/* Acknowledgement policies; 0 reserved as OOB. */ +#define DB_REPMGR_ACKS_ALL 1 +#define DB_REPMGR_ACKS_ALL_AVAILABLE 2 +#define DB_REPMGR_ACKS_ALL_PEERS 3 +#define DB_REPMGR_ACKS_NONE 4 +#define DB_REPMGR_ACKS_ONE 5 +#define DB_REPMGR_ACKS_ONE_PEER 6 +#define DB_REPMGR_ACKS_QUORUM 7 + +/* Replication timeout configuration values. */ +#define DB_REP_ACK_TIMEOUT 1 /* RepMgr acknowledgements. */ +#define DB_REP_CHECKPOINT_DELAY 2 /* Master checkpoint delay. */ +#define DB_REP_CONNECTION_RETRY 3 /* RepMgr connections. */ +#define DB_REP_ELECTION_RETRY 4 /* RepMgr elect retries. */ +#define DB_REP_ELECTION_TIMEOUT 5 /* Rep normal elections. */ +#define DB_REP_FULL_ELECTION_TIMEOUT 6 /* Rep full elections. */ +#define DB_REP_HEARTBEAT_MONITOR 7 /* RepMgr client HB monitor. */ +#define DB_REP_HEARTBEAT_SEND 8 /* RepMgr master send freq. */ +#define DB_REP_LEASE_TIMEOUT 9 /* Master leases. */ + +/* + * Event notification types. (Tcl testing interface currently assumes there are + * no more than 32 of these.) + */ +#define DB_EVENT_PANIC 0 +#define DB_EVENT_REG_ALIVE 1 +#define DB_EVENT_REG_PANIC 2 +#define DB_EVENT_REP_CLIENT 3 +#define DB_EVENT_REP_CONNECT_BROKEN 4 +#define DB_EVENT_REP_CONNECT_ESTD 5 +#define DB_EVENT_REP_CONNECT_TRY_FAILED 6 +#define DB_EVENT_REP_DUPMASTER 7 +#define DB_EVENT_REP_ELECTED 8 +#define DB_EVENT_REP_ELECTION_FAILED 9 +#define DB_EVENT_REP_INIT_DONE 10 +#define DB_EVENT_REP_JOIN_FAILURE 11 +#define DB_EVENT_REP_LOCAL_SITE_REMOVED 12 +#define DB_EVENT_REP_MASTER 13 +#define DB_EVENT_REP_MASTER_FAILURE 14 +#define DB_EVENT_REP_NEWMASTER 15 +#define DB_EVENT_REP_PERM_FAILED 16 +#define DB_EVENT_REP_SITE_ADDED 17 +#define DB_EVENT_REP_SITE_REMOVED 18 +#define DB_EVENT_REP_STARTUPDONE 19 +#define DB_EVENT_REP_WOULD_ROLLBACK 20 /* Undocumented; C API only. */ +#define DB_EVENT_WRITE_FAILED 21 +#define DB_EVENT_NO_SUCH_EVENT 0xffffffff /* OOB sentinel value */ + +/* Replication Manager site status. */ +struct __db_repmgr_site { + int eid; + char *host; + u_int port; + +#define DB_REPMGR_CONNECTED 1 +#define DB_REPMGR_DISCONNECTED 2 + u_int32_t status; + +#define DB_REPMGR_ISPEER 0x01 + u_int32_t flags; +}; + +/* Replication statistics. */ +struct __db_rep_stat { /* SHARED */ + /* !!! + * Many replication statistics fields cannot be protected by a mutex + * without an unacceptable performance penalty, since most message + * processing is done without the need to hold a region-wide lock. + * Fields whose comments end with a '+' may be updated without holding + * the replication or log mutexes (as appropriate), and thus may be + * off somewhat (or, on unreasonable architectures under unlucky + * circumstances, garbaged). + */ + u_int32_t st_startup_complete; /* Site completed client sync-up. */ +#ifndef __TEST_DB_NO_STATISTICS + uintmax_t st_log_queued; /* Log records currently queued.+ */ + u_int32_t st_status; /* Current replication status. */ + DB_LSN st_next_lsn; /* Next LSN to use or expect. */ + DB_LSN st_waiting_lsn; /* LSN we're awaiting, if any. */ + DB_LSN st_max_perm_lsn; /* Maximum permanent LSN. */ + db_pgno_t st_next_pg; /* Next pg we expect. */ + db_pgno_t st_waiting_pg; /* pg we're awaiting, if any. */ + + u_int32_t st_dupmasters; /* # of times a duplicate master + condition was detected.+ */ + db_ssize_t st_env_id; /* Current environment ID. */ + u_int32_t st_env_priority; /* Current environment priority. */ + uintmax_t st_bulk_fills; /* Bulk buffer fills. */ + uintmax_t st_bulk_overflows; /* Bulk buffer overflows. */ + uintmax_t st_bulk_records; /* Bulk records stored. */ + uintmax_t st_bulk_transfers; /* Transfers of bulk buffers. */ + uintmax_t st_client_rerequests;/* Number of forced rerequests. */ + uintmax_t st_client_svc_req; /* Number of client service requests + received by this client. */ + uintmax_t st_client_svc_miss; /* Number of client service requests + missing on this client. */ + u_int32_t st_gen; /* Current generation number. */ + u_int32_t st_egen; /* Current election gen number. */ + uintmax_t st_lease_chk; /* Lease validity checks. */ + uintmax_t st_lease_chk_misses; /* Lease checks invalid. */ + uintmax_t st_lease_chk_refresh; /* Lease refresh attempts. */ + uintmax_t st_lease_sends; /* Lease messages sent live. */ + + uintmax_t st_log_duplicated; /* Log records received multiply.+ */ + uintmax_t st_log_queued_max; /* Max. log records queued at once.+ */ + uintmax_t st_log_queued_total; /* Total # of log recs. ever queued.+ */ + uintmax_t st_log_records; /* Log records received and put.+ */ + uintmax_t st_log_requested; /* Log recs. missed and requested.+ */ + db_ssize_t st_master; /* Env. ID of the current master. */ + uintmax_t st_master_changes; /* # of times we've switched masters. */ + uintmax_t st_msgs_badgen; /* Messages with a bad generation #.+ */ + uintmax_t st_msgs_processed; /* Messages received and processed.+ */ + uintmax_t st_msgs_recover; /* Messages ignored because this site + was a client in recovery.+ */ + uintmax_t st_msgs_send_failures;/* # of failed message sends.+ */ + uintmax_t st_msgs_sent; /* # of successful message sends.+ */ + uintmax_t st_newsites; /* # of NEWSITE msgs. received.+ */ + u_int32_t st_nsites; /* Current number of sites we will + assume during elections. */ + uintmax_t st_nthrottles; /* # of times we were throttled. */ + uintmax_t st_outdated; /* # of times we detected and returned + an OUTDATED condition.+ */ + uintmax_t st_pg_duplicated; /* Pages received multiply.+ */ + uintmax_t st_pg_records; /* Pages received and stored.+ */ + uintmax_t st_pg_requested; /* Pages missed and requested.+ */ + uintmax_t st_txns_applied; /* # of transactions applied.+ */ + uintmax_t st_startsync_delayed;/* # of STARTSYNC msgs delayed.+ */ + + /* Elections generally. */ + uintmax_t st_elections; /* # of elections held.+ */ + uintmax_t st_elections_won; /* # of elections won by this site.+ */ + + /* Statistics about an in-progress election. */ + db_ssize_t st_election_cur_winner; /* Current front-runner. */ + u_int32_t st_election_gen; /* Election generation number. */ + u_int32_t st_election_datagen; /* Election data generation number. */ + DB_LSN st_election_lsn; /* Max. LSN of current winner. */ + u_int32_t st_election_nsites; /* # of "registered voters". */ + u_int32_t st_election_nvotes; /* # of "registered voters" needed. */ + u_int32_t st_election_priority; /* Current election priority. */ + int32_t st_election_status; /* Current election status. */ + u_int32_t st_election_tiebreaker;/* Election tiebreaker value. */ + u_int32_t st_election_votes; /* Votes received in this round. */ + u_int32_t st_election_sec; /* Last election time seconds. */ + u_int32_t st_election_usec; /* Last election time useconds. */ + u_int32_t st_max_lease_sec; /* Maximum lease timestamp seconds. */ + u_int32_t st_max_lease_usec; /* Maximum lease timestamp useconds. */ + + /* Undocumented statistics only used by the test system. */ +#ifdef CONFIG_TEST + u_int32_t st_filefail_cleanups; /* # of FILE_FAIL cleanups done. */ +#endif +#endif +}; + +/* Replication Manager statistics. */ +struct __db_repmgr_stat { /* SHARED */ + uintmax_t st_perm_failed; /* # of insufficiently ack'ed msgs. */ + uintmax_t st_msgs_queued; /* # msgs queued for network delay. */ + uintmax_t st_msgs_dropped; /* # msgs discarded due to excessive + queue length. */ + uintmax_t st_connection_drop; /* Existing connections dropped. */ + uintmax_t st_connect_fail; /* Failed new connection attempts. */ + uintmax_t st_elect_threads; /* # of active election threads. */ + uintmax_t st_max_elect_threads; /* Max concurrent e-threads ever. */ +}; + +/* Replication Manager connection error. */ +struct __db_repmgr_conn_err { + int eid; /* Replication Environment ID. */ + int error; /* System networking error code. */ +}; + +/******************************************************* + * Sequences. + *******************************************************/ +/* + * The storage record for a sequence. + */ +struct __db_seq_record { + u_int32_t seq_version; /* Version size/number. */ + u_int32_t flags; /* DB_SEQ_XXX Flags. */ + db_seq_t seq_value; /* Current value. */ + db_seq_t seq_max; /* Max permitted. */ + db_seq_t seq_min; /* Min permitted. */ +}; + +/* + * Handle for a sequence object. + */ +struct __db_sequence { + DB *seq_dbp; /* DB handle for this sequence. */ + db_mutex_t mtx_seq; /* Mutex if sequence is threaded. */ + DB_SEQ_RECORD *seq_rp; /* Pointer to current data. */ + DB_SEQ_RECORD seq_record; /* Data from DB_SEQUENCE. */ + int32_t seq_cache_size; /* Number of values cached. */ + db_seq_t seq_last_value; /* Last value cached. */ + db_seq_t seq_prev_value; /* Last value returned. */ + DBT seq_key; /* DBT pointing to sequence key. */ + DBT seq_data; /* DBT pointing to seq_record. */ + + /* API-private structure: used by C++ and Java. */ + void *api_internal; + + /* DB_SEQUENCE PUBLIC HANDLE LIST BEGIN */ + int (*close) __P((DB_SEQUENCE *, u_int32_t)); + int (*get) __P((DB_SEQUENCE *, + DB_TXN *, int32_t, db_seq_t *, u_int32_t)); + int (*get_cachesize) __P((DB_SEQUENCE *, int32_t *)); + int (*get_db) __P((DB_SEQUENCE *, DB **)); + int (*get_flags) __P((DB_SEQUENCE *, u_int32_t *)); + int (*get_key) __P((DB_SEQUENCE *, DBT *)); + int (*get_range) __P((DB_SEQUENCE *, + db_seq_t *, db_seq_t *)); + int (*initial_value) __P((DB_SEQUENCE *, db_seq_t)); + int (*open) __P((DB_SEQUENCE *, + DB_TXN *, DBT *, u_int32_t)); + int (*remove) __P((DB_SEQUENCE *, DB_TXN *, u_int32_t)); + int (*set_cachesize) __P((DB_SEQUENCE *, int32_t)); + int (*set_flags) __P((DB_SEQUENCE *, u_int32_t)); + int (*set_range) __P((DB_SEQUENCE *, db_seq_t, db_seq_t)); + int (*stat) __P((DB_SEQUENCE *, + DB_SEQUENCE_STAT **, u_int32_t)); + int (*stat_print) __P((DB_SEQUENCE *, u_int32_t)); + /* DB_SEQUENCE PUBLIC HANDLE LIST END */ +}; + +struct __db_seq_stat { /* SHARED */ + uintmax_t st_wait; /* Sequence lock granted w/o wait. */ + uintmax_t st_nowait; /* Sequence lock granted after wait. */ + db_seq_t st_current; /* Current value in db. */ + db_seq_t st_value; /* Current cached value. */ + db_seq_t st_last_value; /* Last cached value. */ + db_seq_t st_min; /* Minimum value. */ + db_seq_t st_max; /* Maximum value. */ + int32_t st_cache_size; /* Cache size. */ + u_int32_t st_flags; /* Flag value. */ +}; + +/******************************************************* + * Access methods. + *******************************************************/ +/* + * Any new methods need to retain the original numbering. The type + * is written in a log record so must be maintained. + */ +typedef enum { + DB_BTREE=1, + DB_HASH=2, + DB_HEAP=6, + DB_RECNO=3, + DB_QUEUE=4, + DB_UNKNOWN=5 /* Figure it out on open. */ +} DBTYPE; + +#define DB_RENAMEMAGIC 0x030800 /* File has been renamed. */ + +#define DB_BTREEVERSION 9 /* Current btree version. */ +#define DB_BTREEOLDVER 8 /* Oldest btree version supported. */ +#define DB_BTREEMAGIC 0x053162 + +#define DB_HASHVERSION 9 /* Current hash version. */ +#define DB_HASHOLDVER 7 /* Oldest hash version supported. */ +#define DB_HASHMAGIC 0x061561 + +#define DB_HEAPVERSION 1 /* Current heap version. */ +#define DB_HEAPOLDVER 1 /* Oldest heap version supported. */ +#define DB_HEAPMAGIC 0x074582 + +#define DB_QAMVERSION 4 /* Current queue version. */ +#define DB_QAMOLDVER 3 /* Oldest queue version supported. */ +#define DB_QAMMAGIC 0x042253 + +#define DB_SEQUENCE_VERSION 2 /* Current sequence version. */ +#define DB_SEQUENCE_OLDVER 1 /* Oldest sequence version supported. */ + +/* + * DB access method and cursor operation values. Each value is an operation + * code to which additional bit flags are added. + */ +#define DB_AFTER 1 /* Dbc.put */ +#define DB_APPEND 2 /* Db.put */ +#define DB_BEFORE 3 /* Dbc.put */ +#define DB_CONSUME 4 /* Db.get */ +#define DB_CONSUME_WAIT 5 /* Db.get */ +#define DB_CURRENT 6 /* Dbc.get, Dbc.put, DbLogc.get */ +#define DB_FIRST 7 /* Dbc.get, DbLogc->get */ +#define DB_GET_BOTH 8 /* Db.get, Dbc.get */ +#define DB_GET_BOTHC 9 /* Dbc.get (internal) */ +#define DB_GET_BOTH_RANGE 10 /* Db.get, Dbc.get */ +#define DB_GET_RECNO 11 /* Dbc.get */ +#define DB_JOIN_ITEM 12 /* Dbc.get; don't do primary lookup */ +#define DB_KEYFIRST 13 /* Dbc.put */ +#define DB_KEYLAST 14 /* Dbc.put */ +#define DB_LAST 15 /* Dbc.get, DbLogc->get */ +#define DB_NEXT 16 /* Dbc.get, DbLogc->get */ +#define DB_NEXT_DUP 17 /* Dbc.get */ +#define DB_NEXT_NODUP 18 /* Dbc.get */ +#define DB_NODUPDATA 19 /* Db.put, Dbc.put */ +#define DB_NOOVERWRITE 20 /* Db.put */ +#define DB_OVERWRITE_DUP 21 /* Dbc.put, Db.put; no DB_KEYEXIST */ +#define DB_POSITION 22 /* Dbc.dup */ +#define DB_PREV 23 /* Dbc.get, DbLogc->get */ +#define DB_PREV_DUP 24 /* Dbc.get */ +#define DB_PREV_NODUP 25 /* Dbc.get */ +#define DB_SET 26 /* Dbc.get, DbLogc->get */ +#define DB_SET_RANGE 27 /* Dbc.get */ +#define DB_SET_RECNO 28 /* Db.get, Dbc.get */ +#define DB_UPDATE_SECONDARY 29 /* Dbc.get, Dbc.del (internal) */ +#define DB_SET_LTE 30 /* Dbc.get (internal) */ +#define DB_GET_BOTH_LTE 31 /* Dbc.get (internal) */ + +/* This has to change when the max opcode hits 255. */ +#define DB_OPFLAGS_MASK 0x000000ff /* Mask for operations flags. */ + +/* + * DB (user visible) error return codes. + * + * !!! + * We don't want our error returns to conflict with other packages where + * possible, so pick a base error value that's hopefully not common. We + * document that we own the error name space from -30,800 to -30,999. + */ +/* DB (public) error return codes. */ +#define DB_BUFFER_SMALL (-30999)/* User memory too small for return. */ +#define DB_DONOTINDEX (-30998)/* "Null" return from 2ndary callbk. */ +#define DB_FOREIGN_CONFLICT (-30997)/* A foreign db constraint triggered. */ +#define DB_HEAP_FULL (-30996)/* No free space in a heap file. */ +#define DB_KEYEMPTY (-30995)/* Key/data deleted or never created. */ +#define DB_KEYEXIST (-30994)/* The key/data pair already exists. */ +#define DB_LOCK_DEADLOCK (-30993)/* Deadlock. */ +#define DB_LOCK_NOTGRANTED (-30992)/* Lock unavailable. */ +#define DB_LOG_BUFFER_FULL (-30991)/* In-memory log buffer full. */ +#define DB_LOG_VERIFY_BAD (-30990)/* Log verification failed. */ +#define DB_NOSERVER (-30989)/* Server panic return. */ +#define DB_NOTFOUND (-30988)/* Key/data pair not found (EOF). */ +#define DB_OLD_VERSION (-30987)/* Out-of-date version. */ +#define DB_PAGE_NOTFOUND (-30986)/* Requested page not found. */ +#define DB_REP_DUPMASTER (-30985)/* There are two masters. */ +#define DB_REP_HANDLE_DEAD (-30984)/* Rolled back a commit. */ +#define DB_REP_HOLDELECTION (-30983)/* Time to hold an election. */ +#define DB_REP_IGNORE (-30982)/* This msg should be ignored.*/ +#define DB_REP_ISPERM (-30981)/* Cached not written perm written.*/ +#define DB_REP_JOIN_FAILURE (-30980)/* Unable to join replication group. */ +#define DB_REP_LEASE_EXPIRED (-30979)/* Master lease has expired. */ +#define DB_REP_LOCKOUT (-30978)/* API/Replication lockout now. */ +#define DB_REP_NEWSITE (-30977)/* New site entered system. */ +#define DB_REP_NOTPERM (-30976)/* Permanent log record not written. */ +#define DB_REP_UNAVAIL (-30975)/* Site cannot currently be reached. */ +#define DB_REP_WOULDROLLBACK (-30974)/* UNDOC: rollback inhibited by app. */ +#define DB_RUNRECOVERY (-30973)/* Panic return. */ +#define DB_SECONDARY_BAD (-30972)/* Secondary index corrupt. */ +#define DB_TIMEOUT (-30971)/* Timed out on read consistency. */ +#define DB_VERIFY_BAD (-30970)/* Verify failed; bad format. */ +#define DB_VERSION_MISMATCH (-30969)/* Environment version mismatch. */ + +/* DB (private) error return codes. */ +#define DB_ALREADY_ABORTED (-30899) +#define DB_CHKSUM_FAIL (-30898)/* Checksum failed. */ +#define DB_DELETED (-30897)/* Recovery file marked deleted. */ +#define DB_EVENT_NOT_HANDLED (-30896)/* Forward event to application. */ +#define DB_NEEDSPLIT (-30895)/* Page needs to be split. */ +#define DB_REP_BULKOVF (-30894)/* Rep bulk buffer overflow. */ +#define DB_REP_LOGREADY (-30893)/* Rep log ready for recovery. */ +#define DB_REP_NEWMASTER (-30892)/* We have learned of a new master. */ +#define DB_REP_PAGEDONE (-30891)/* This page was already done. */ +#define DB_SURPRISE_KID (-30890)/* Child commit where parent + didn't know it was a parent. */ +#define DB_SWAPBYTES (-30889)/* Database needs byte swapping. */ +#define DB_TXN_CKP (-30888)/* Encountered ckp record in log. */ +#define DB_VERIFY_FATAL (-30887)/* DB->verify cannot proceed. */ + +/* Database handle. */ +struct __db { + /******************************************************* + * Public: owned by the application. + *******************************************************/ + u_int32_t pgsize; /* Database logical page size. */ + DB_CACHE_PRIORITY priority; /* Database priority in cache. */ + + /* Callbacks. */ + int (*db_append_recno) __P((DB *, DBT *, db_recno_t)); + void (*db_feedback) __P((DB *, int, int)); + int (*dup_compare) __P((DB *, const DBT *, const DBT *)); + + void *app_private; /* Application-private handle. */ + + /******************************************************* + * Private: owned by DB. + *******************************************************/ + DB_ENV *dbenv; /* Backing public environment. */ + ENV *env; /* Backing private environment. */ + + DBTYPE type; /* DB access method type. */ + + DB_MPOOLFILE *mpf; /* Backing buffer pool. */ + + db_mutex_t mutex; /* Synchronization for free threading */ + + char *fname, *dname; /* File/database passed to DB->open. */ + const char *dirname; /* Directory of DB file. */ + u_int32_t open_flags; /* Flags passed to DB->open. */ + + u_int8_t fileid[DB_FILE_ID_LEN];/* File's unique ID for locking. */ + + u_int32_t adj_fileid; /* File's unique ID for curs. adj. */ + +#define DB_LOGFILEID_INVALID -1 + FNAME *log_filename; /* File's naming info for logging. */ + + db_pgno_t meta_pgno; /* Meta page number */ + DB_LOCKER *locker; /* Locker for handle locking. */ + DB_LOCKER *cur_locker; /* Current handle lock holder. */ + DB_TXN *cur_txn; /* Opening transaction. */ + DB_LOCKER *associate_locker; /* Locker for DB->associate call. */ + DB_LOCK handle_lock; /* Lock held on this handle. */ + + time_t timestamp; /* Handle timestamp for replication. */ + u_int32_t fid_gen; /* Rep generation number for fids. */ + + /* + * Returned data memory for DB->get() and friends. + */ + DBT my_rskey; /* Secondary key. */ + DBT my_rkey; /* [Primary] key. */ + DBT my_rdata; /* Data. */ + + /* + * !!! + * Some applications use DB but implement their own locking outside of + * DB. If they're using fcntl(2) locking on the underlying database + * file, and we open and close a file descriptor for that file, we will + * discard their locks. The DB_FCNTL_LOCKING flag to DB->open is an + * undocumented interface to support this usage which leaves any file + * descriptors we open until DB->close. This will only work with the + * DB->open interface and simple caches, e.g., creating a transaction + * thread may open/close file descriptors this flag doesn't protect. + * Locking with fcntl(2) on a file that you don't own is a very, very + * unsafe thing to do. 'Nuff said. + */ + DB_FH *saved_open_fhp; /* Saved file handle. */ + + /* + * Linked list of DBP's, linked from the ENV, used to keep track + * of all open db handles for cursor adjustment. + * + * !!! + * Explicit representations of structures from queue.h. + * TAILQ_ENTRY(__db) dblistlinks; + */ + struct { + struct __db *tqe_next; + struct __db **tqe_prev; + } dblistlinks; + + /* + * Cursor queues. + * + * !!! + * Explicit representations of structures from queue.h. + * TAILQ_HEAD(__cq_fq, __dbc) free_queue; + * TAILQ_HEAD(__cq_aq, __dbc) active_queue; + * TAILQ_HEAD(__cq_jq, __dbc) join_queue; + */ + struct __cq_fq { + struct __dbc *tqh_first; + struct __dbc **tqh_last; + } free_queue; + struct __cq_aq { + struct __dbc *tqh_first; + struct __dbc **tqh_last; + } active_queue; + struct __cq_jq { + struct __dbc *tqh_first; + struct __dbc **tqh_last; + } join_queue; + + /* + * Secondary index support. + * + * Linked list of secondary indices -- set in the primary. + * + * !!! + * Explicit representations of structures from queue.h. + * LIST_HEAD(s_secondaries, __db); + */ + struct { + struct __db *lh_first; + } s_secondaries; + + /* + * List entries for secondaries, and reference count of how many + * threads are updating this secondary (see Dbc.put). + * + * !!! + * Note that these are synchronized by the primary's mutex, but + * filled in in the secondaries. + * + * !!! + * Explicit representations of structures from queue.h. + * LIST_ENTRY(__db) s_links; + */ + struct { + struct __db *le_next; + struct __db **le_prev; + } s_links; + u_int32_t s_refcnt; + + /* Secondary callback and free functions -- set in the secondary. */ + int (*s_callback) __P((DB *, const DBT *, const DBT *, DBT *)); + + /* Reference to primary -- set in the secondary. */ + DB *s_primary; + +#define DB_ASSOC_IMMUTABLE_KEY 0x00000001 /* Secondary key is immutable. */ +#define DB_ASSOC_CREATE 0x00000002 /* Secondary db populated on open. */ + + /* Flags passed to associate -- set in the secondary. */ + u_int32_t s_assoc_flags; + + /* + * Foreign key support. + * + * Linked list of primary dbs -- set in the foreign db + * + * !!! + * Explicit representations of structures from queue.h. + * LIST_HEAD(f_primaries, __db); + */ + struct { + struct __db_foreign_info *lh_first; + } f_primaries; + + /* + * !!! + * Explicit representations of structures from queue.h. + * TAILQ_ENTRY(__db) felink; + * + * Links in a list of DBs involved in file extension + * during a transaction. These are to be used only while the + * metadata is locked. + */ + struct { + struct __db *tqe_next; + struct __db **tqe_prev; + } felink; + + /* Reference to foreign -- set in the secondary. */ + DB *s_foreign; + + /* API-private structure: used by DB 1.85, C++, Java, Perl and Tcl */ + void *api_internal; + + /* Subsystem-private structure. */ + void *bt_internal; /* Btree/Recno access method. */ + void *h_internal; /* Hash access method. */ + void *heap_internal; /* Heap access method. */ + void *p_internal; /* Partition informaiton. */ + void *q_internal; /* Queue access method. */ + + /* DB PUBLIC HANDLE LIST BEGIN */ + int (*associate) __P((DB *, DB_TXN *, DB *, + int (*)(DB *, const DBT *, const DBT *, DBT *), u_int32_t)); + int (*associate_foreign) __P((DB *, DB *, + int (*)(DB *, const DBT *, DBT *, const DBT *, int *), + u_int32_t)); + int (*close) __P((DB *, u_int32_t)); + int (*cursor) __P((DB *, DB_TXN *, DBC **, u_int32_t)); + int (*del) __P((DB *, DB_TXN *, DBT *, u_int32_t)); + void (*err) __P((DB *, int, const char *, ...)); + void (*errx) __P((DB *, const char *, ...)); + int (*exists) __P((DB *, DB_TXN *, DBT *, u_int32_t)); + int (*fd) __P((DB *, int *)); + int (*get) __P((DB *, DB_TXN *, DBT *, DBT *, u_int32_t)); + int (*get_alloc) __P((DB *, void *(**)(size_t), + void *(**)(void *, size_t), void (**)(void *))); + int (*get_append_recno) __P((DB *, int (**)(DB *, DBT *, db_recno_t))); + int (*get_assoc_flags) __P((DB *, u_int32_t *)); + int (*get_bt_compare) + __P((DB *, int (**)(DB *, const DBT *, const DBT *))); + int (*get_bt_minkey) __P((DB *, u_int32_t *)); + int (*get_bt_prefix) + __P((DB *, size_t (**)(DB *, const DBT *, const DBT *))); + int (*get_byteswapped) __P((DB *, int *)); + int (*get_cachesize) __P((DB *, u_int32_t *, u_int32_t *, int *)); + int (*get_create_dir) __P((DB *, const char **)); + int (*get_dbname) __P((DB *, const char **, const char **)); + int (*get_dup_compare) + __P((DB *, int (**)(DB *, const DBT *, const DBT *))); + DB_ENV *(*get_env) __P((DB *)); + void (*get_errcall) __P((DB *, + void (**)(const DB_ENV *, const char *, const char *))); + void (*get_errfile) __P((DB *, FILE **)); + void (*get_errpfx) __P((DB *, const char **)); + int (*get_feedback) __P((DB *, void (**)(DB *, int, int))); + int (*get_flags) __P((DB *, u_int32_t *)); + int (*get_lorder) __P((DB *, int *)); + DB_MPOOLFILE *(*get_mpf) __P((DB *)); + void (*get_msgcall) __P((DB *, + void (**)(const DB_ENV *, const char *))); + void (*get_msgfile) __P((DB *, FILE **)); + int (*get_multiple) __P((DB *)); + int (*get_open_flags) __P((DB *, u_int32_t *)); + int (*get_pagesize) __P((DB *, u_int32_t *)); + int (*get_priority) __P((DB *, DB_CACHE_PRIORITY *)); + int (*get_re_delim) __P((DB *, int *)); + int (*get_re_len) __P((DB *, u_int32_t *)); + int (*get_re_pad) __P((DB *, int *)); + int (*get_re_source) __P((DB *, const char **)); + int (*get_transactional) __P((DB *)); + int (*get_type) __P((DB *, DBTYPE *)); + int (*key_range) + __P((DB *, DB_TXN *, DBT *, DB_KEY_RANGE *, u_int32_t)); + int (*open) __P((DB *, + DB_TXN *, const char *, const char *, DBTYPE, u_int32_t, int)); + int (*pget) __P((DB *, DB_TXN *, DBT *, DBT *, DBT *, u_int32_t)); + int (*put) __P((DB *, DB_TXN *, DBT *, DBT *, u_int32_t)); + int (*remove) __P((DB *, const char *, const char *, u_int32_t)); + int (*rename) __P((DB *, + const char *, const char *, const char *, u_int32_t)); + int (*set_alloc) __P((DB *, void *(*)(size_t), + void *(*)(void *, size_t), void (*)(void *))); + int (*set_append_recno) __P((DB *, int (*)(DB *, DBT *, db_recno_t))); + int (*set_bt_compare) + __P((DB *, int (*)(DB *, const DBT *, const DBT *))); + int (*set_bt_minkey) __P((DB *, u_int32_t)); + int (*set_bt_prefix) + __P((DB *, size_t (*)(DB *, const DBT *, const DBT *))); + int (*set_cachesize) __P((DB *, u_int32_t, u_int32_t, int)); + int (*set_create_dir) __P((DB *, const char *)); + int (*set_dup_compare) + __P((DB *, int (*)(DB *, const DBT *, const DBT *))); + int (*set_encrypt) __P((DB *, const char *, u_int32_t)); + void (*set_errcall) __P((DB *, + void (*)(const DB_ENV *, const char *, const char *))); + void (*set_errfile) __P((DB *, FILE *)); + void (*set_errpfx) __P((DB *, const char *)); + int (*set_feedback) __P((DB *, void (*)(DB *, int, int))); + int (*set_flags) __P((DB *, u_int32_t)); + int (*set_lorder) __P((DB *, int)); + void (*set_msgcall) __P((DB *, void (*)(const DB_ENV *, const char *))); + void (*set_msgfile) __P((DB *, FILE *)); + int (*set_pagesize) __P((DB *, u_int32_t)); + int (*set_paniccall) __P((DB *, void (*)(DB_ENV *, int))); + int (*set_partition) __P((DB *, + u_int32_t, DBT *, u_int32_t (*)(DB *, DBT *key))); + int (*set_partition_dirs) __P((DB *, const char **)); + int (*set_priority) __P((DB *, DB_CACHE_PRIORITY)); + int (*set_re_delim) __P((DB *, int)); + int (*set_re_len) __P((DB *, u_int32_t)); + int (*set_re_pad) __P((DB *, int)); + int (*set_re_source) __P((DB *, const char *)); + int (*sort_multiple) __P((DB *, DBT *, DBT *, u_int32_t)); + int (*stat) __P((DB *, DB_TXN *, void *, u_int32_t)); + int (*stat_print) __P((DB *, u_int32_t)); + int (*sync) __P((DB *, u_int32_t)); + int (*truncate) __P((DB *, DB_TXN *, u_int32_t *, u_int32_t)); + int (*verify) + __P((DB *, const char *, const char *, FILE *, u_int32_t)); + /* DB PUBLIC HANDLE LIST END */ + + /* DB PRIVATE HANDLE LIST BEGIN */ + int (*dump) __P((DB *, const char *, + int (*)(void *, const void *), void *, int, int)); + int (*db_am_remove) __P((DB *, DB_THREAD_INFO *, + DB_TXN *, const char *, const char *, u_int32_t)); + int (*db_am_rename) __P((DB *, DB_THREAD_INFO *, + DB_TXN *, const char *, const char *, const char *)); + /* DB PRIVATE HANDLE LIST END */ + + /* + * Never called; these are a place to save function pointers + * so that we can undo an associate. + */ + int (*stored_get) __P((DB *, DB_TXN *, DBT *, DBT *, u_int32_t)); + int (*stored_close) __P((DB *, u_int32_t)); + + /* Alternative handle close function, used by C++ API. */ + int (*alt_close) __P((DB *, u_int32_t)); + +#define DB_OK_BTREE 0x01 +#define DB_OK_HASH 0x02 +#define DB_OK_HEAP 0x04 +#define DB_OK_QUEUE 0x08 +#define DB_OK_RECNO 0x10 + u_int32_t am_ok; /* Legal AM choices. */ + + /* + * This field really ought to be an AM_FLAG, but we have + * have run out of bits. If/when we decide to split up + * the flags, we can incorporate it. + */ + int preserve_fid; /* Do not free fileid on close. */ + +#define DB_AM_CHKSUM 0x00000001 /* Checksumming */ +#define DB_AM_COMPENSATE 0x00000002 /* Created by compensating txn */ +#define DB_AM_COMPRESS 0x00000004 /* Compressed BTree */ +#define DB_AM_CREATED 0x00000008 /* Database was created upon open */ +#define DB_AM_CREATED_MSTR 0x00000010 /* Encompassing file was created */ +#define DB_AM_DBM_ERROR 0x00000020 /* Error in DBM/NDBM database */ +#define DB_AM_DELIMITER 0x00000040 /* Variable length delimiter set */ +#define DB_AM_DISCARD 0x00000080 /* Discard any cached pages */ +#define DB_AM_DUP 0x00000100 /* DB_DUP */ +#define DB_AM_DUPSORT 0x00000200 /* DB_DUPSORT */ +#define DB_AM_ENCRYPT 0x00000400 /* Encryption */ +#define DB_AM_FIXEDLEN 0x00000800 /* Fixed-length records */ +#define DB_AM_INMEM 0x00001000 /* In-memory; no sync on close */ +#define DB_AM_INORDER 0x00002000 /* DB_INORDER */ +#define DB_AM_IN_RENAME 0x00004000 /* File is being renamed */ +#define DB_AM_NOT_DURABLE 0x00008000 /* Do not log changes */ +#define DB_AM_OPEN_CALLED 0x00010000 /* DB->open called */ +#define DB_AM_PAD 0x00020000 /* Fixed-length record pad */ +#define DB_AM_PARTDB 0x00040000 /* Handle for a database partition */ +#define DB_AM_PGDEF 0x00080000 /* Page size was defaulted */ +#define DB_AM_RDONLY 0x00100000 /* Database is readonly */ +#define DB_AM_READ_UNCOMMITTED 0x00200000 /* Support degree 1 isolation */ +#define DB_AM_RECNUM 0x00400000 /* DB_RECNUM */ +#define DB_AM_RECOVER 0x00800000 /* DB opened by recovery routine */ +#define DB_AM_RENUMBER 0x01000000 /* DB_RENUMBER */ +#define DB_AM_REVSPLITOFF 0x02000000 /* DB_REVSPLITOFF */ +#define DB_AM_SECONDARY 0x04000000 /* Database is a secondary index */ +#define DB_AM_SNAPSHOT 0x08000000 /* DB_SNAPSHOT */ +#define DB_AM_SUBDB 0x10000000 /* Subdatabases supported */ +#define DB_AM_SWAP 0x20000000 /* Pages need to be byte-swapped */ +#define DB_AM_TXN 0x40000000 /* Opened in a transaction */ +#define DB_AM_VERIFYING 0x80000000 /* DB handle is in the verifier */ + u_int32_t orig_flags; /* Flags at open, for refresh */ + u_int32_t flags; + +#define DB2_AM_EXCL 0x00000001 /* Exclusively lock the handle */ +#define DB2_AM_INTEXCL 0x00000002 /* Internal exclusive lock. */ +#define DB2_AM_NOWAIT 0x00000004 /* Do not wait for handle lock */ + u_int32_t orig_flags2; /* Second flags word; for refresh */ + u_int32_t flags2; /* Second flags word */ +}; + +/* + * Macros for bulk operations. These are only intended for the C API. + * For C++, use DbMultiple*Iterator or DbMultiple*Builder. + * + * Bulk operations store multiple entries into a single DBT structure. The + * following macros assist with creating and reading these Multiple DBTs. + * + * The basic layout for single data items is: + * + * ------------------------------------------------------------------------- + * | data1 | ... | dataN | ..... |-1 | dNLen | dNOff | ... | d1Len | d1Off | + * ------------------------------------------------------------------------- + * + * For the DB_MULTIPLE_KEY* macros, the items are in key/data pairs, so data1 + * would be a key, and data2 its corresponding value (N is always even). + * + * For the DB_MULTIPLE_RECNO* macros, the record number is stored along with + * the len/off pair in the "header" section, and the list is zero terminated + * (since -1 is a valid record number): + * + * -------------------------------------------------------------------------- + * | d1 |..| dN |..| 0 | dNLen | dNOff | recnoN |..| d1Len | d1Off | recno1 | + * -------------------------------------------------------------------------- + */ +#define DB_MULTIPLE_INIT(pointer, dbt) \ + (pointer = (u_int8_t *)(dbt)->data + \ + (dbt)->ulen - sizeof(u_int32_t)) + +#define DB_MULTIPLE_NEXT(pointer, dbt, retdata, retdlen) \ + do { \ + u_int32_t *__p = (u_int32_t *)(pointer); \ + if (*__p == (u_int32_t)-1) { \ + retdata = NULL; \ + pointer = NULL; \ + break; \ + } \ + retdata = (u_int8_t *)(dbt)->data + *__p--; \ + retdlen = *__p--; \ + pointer = __p; \ + if (retdlen == 0 && retdata == (u_int8_t *)(dbt)->data) \ + retdata = NULL; \ + } while (0) + +#define DB_MULTIPLE_KEY_NEXT(pointer, dbt, retkey, retklen, retdata, retdlen) \ + do { \ + u_int32_t *__p = (u_int32_t *)(pointer); \ + if (*__p == (u_int32_t)-1) { \ + retdata = NULL; \ + retkey = NULL; \ + pointer = NULL; \ + break; \ + } \ + retkey = (u_int8_t *)(dbt)->data + *__p--; \ + retklen = *__p--; \ + retdata = (u_int8_t *)(dbt)->data + *__p--; \ + retdlen = *__p--; \ + pointer = __p; \ + } while (0) + +#define DB_MULTIPLE_RECNO_NEXT(pointer, dbt, recno, retdata, retdlen) \ + do { \ + u_int32_t *__p = (u_int32_t *)(pointer); \ + if (*__p == (u_int32_t)0) { \ + recno = 0; \ + retdata = NULL; \ + pointer = NULL; \ + break; \ + } \ + recno = *__p--; \ + retdata = (u_int8_t *)(dbt)->data + *__p--; \ + retdlen = *__p--; \ + pointer = __p; \ + } while (0) + +#define DB_MULTIPLE_WRITE_INIT(pointer, dbt) \ + do { \ + (dbt)->flags |= DB_DBT_BULK; \ + pointer = (u_int8_t *)(dbt)->data + \ + (dbt)->ulen - sizeof(u_int32_t); \ + *(u_int32_t *)(pointer) = (u_int32_t)-1; \ + } while (0) + +#define DB_MULTIPLE_RESERVE_NEXT(pointer, dbt, writedata, writedlen) \ + do { \ + u_int32_t *__p = (u_int32_t *)(pointer); \ + u_int32_t __off = ((pointer) == (u_int8_t *)(dbt)->data +\ + (dbt)->ulen - sizeof(u_int32_t)) ? 0 : __p[1] + __p[2];\ + if ((u_int8_t *)(dbt)->data + __off + (writedlen) > \ + (u_int8_t *)(__p - 2)) \ + writedata = NULL; \ + else { \ + writedata = (u_int8_t *)(dbt)->data + __off; \ + __p[0] = __off; \ + __p[-1] = (u_int32_t)(writedlen); \ + __p[-2] = (u_int32_t)-1; \ + pointer = __p - 2; \ + } \ + } while (0) + +#define DB_MULTIPLE_WRITE_NEXT(pointer, dbt, writedata, writedlen) \ + do { \ + void *__destd; \ + DB_MULTIPLE_RESERVE_NEXT((pointer), (dbt), \ + __destd, (writedlen)); \ + if (__destd == NULL) \ + pointer = NULL; \ + else \ + memcpy(__destd, (writedata), (writedlen)); \ + } while (0) + +#define DB_MULTIPLE_KEY_RESERVE_NEXT(pointer, dbt, writekey, writeklen, writedata, writedlen) \ + do { \ + u_int32_t *__p = (u_int32_t *)(pointer); \ + u_int32_t __off = ((pointer) == (u_int8_t *)(dbt)->data +\ + (dbt)->ulen - sizeof(u_int32_t)) ? 0 : __p[1] + __p[2];\ + if ((u_int8_t *)(dbt)->data + __off + (writeklen) + \ + (writedlen) > (u_int8_t *)(__p - 4)) { \ + writekey = NULL; \ + writedata = NULL; \ + } else { \ + writekey = (u_int8_t *)(dbt)->data + __off; \ + __p[0] = __off; \ + __p[-1] = (u_int32_t)(writeklen); \ + __p -= 2; \ + __off += (u_int32_t)(writeklen); \ + writedata = (u_int8_t *)(dbt)->data + __off; \ + __p[0] = __off; \ + __p[-1] = (u_int32_t)(writedlen); \ + __p[-2] = (u_int32_t)-1; \ + pointer = __p - 2; \ + } \ + } while (0) + +#define DB_MULTIPLE_KEY_WRITE_NEXT(pointer, dbt, writekey, writeklen, writedata, writedlen) \ + do { \ + void *__destk, *__destd; \ + DB_MULTIPLE_KEY_RESERVE_NEXT((pointer), (dbt), \ + __destk, (writeklen), __destd, (writedlen)); \ + if (__destk == NULL) \ + pointer = NULL; \ + else { \ + memcpy(__destk, (writekey), (writeklen)); \ + if (__destd != NULL) \ + memcpy(__destd, (writedata), (writedlen));\ + } \ + } while (0) + +#define DB_MULTIPLE_RECNO_WRITE_INIT(pointer, dbt) \ + do { \ + (dbt)->flags |= DB_DBT_BULK; \ + pointer = (u_int8_t *)(dbt)->data + \ + (dbt)->ulen - sizeof(u_int32_t); \ + *(u_int32_t *)(pointer) = 0; \ + } while (0) + +#define DB_MULTIPLE_RECNO_RESERVE_NEXT(pointer, dbt, recno, writedata, writedlen) \ + do { \ + u_int32_t *__p = (u_int32_t *)(pointer); \ + u_int32_t __off = ((pointer) == (u_int8_t *)(dbt)->data +\ + (dbt)->ulen - sizeof(u_int32_t)) ? 0 : __p[1] + __p[2]; \ + if (((u_int8_t *)(dbt)->data + __off) + (writedlen) > \ + (u_int8_t *)(__p - 3)) \ + writedata = NULL; \ + else { \ + writedata = (u_int8_t *)(dbt)->data + __off; \ + __p[0] = (u_int32_t)(recno); \ + __p[-1] = __off; \ + __p[-2] = (u_int32_t)(writedlen); \ + __p[-3] = 0; \ + pointer = __p - 3; \ + } \ + } while (0) + +#define DB_MULTIPLE_RECNO_WRITE_NEXT(pointer, dbt, recno, writedata, writedlen)\ + do { \ + void *__destd; \ + DB_MULTIPLE_RECNO_RESERVE_NEXT((pointer), (dbt), \ + (recno), __destd, (writedlen)); \ + if (__destd == NULL) \ + pointer = NULL; \ + else if ((writedlen) != 0) \ + memcpy(__destd, (writedata), (writedlen)); \ + } while (0) + +struct __db_heap_rid { + db_pgno_t pgno; /* Page number. */ + db_indx_t indx; /* Index in the offset table. */ +}; +#define DB_HEAP_RID_SZ (sizeof(db_pgno_t) + sizeof(db_indx_t)) + +/******************************************************* + * Access method cursors. + *******************************************************/ +struct __dbc { + DB *dbp; /* Backing database */ + DB_ENV *dbenv; /* Backing environment */ + ENV *env; /* Backing environment */ + + DB_THREAD_INFO *thread_info; /* Thread that owns this cursor. */ + DB_TXN *txn; /* Associated transaction. */ + DB_CACHE_PRIORITY priority; /* Priority in cache. */ + + /* + * Active/free cursor queues. + * + * !!! + * Explicit representations of structures from queue.h. + * TAILQ_ENTRY(__dbc) links; + */ + struct { + DBC *tqe_next; + DBC **tqe_prev; + } links; + + /* + * Cursor queue of the owning transaction. + * + * !!! + * Explicit representations of structures from queue.h. + * TAILQ_ENTRY(__dbc) txn_cursors; + */ + struct { + DBC *tqe_next; /* next element */ + DBC **tqe_prev; /* address of previous next element */ + } txn_cursors; + + /* + * The DBT *'s below are used by the cursor routines to return + * data to the user when DBT flags indicate that DB should manage + * the returned memory. They point at a DBT containing the buffer + * and length that will be used, and "belonging" to the handle that + * should "own" this memory. This may be a "my_*" field of this + * cursor--the default--or it may be the corresponding field of + * another cursor, a DB handle, a join cursor, etc. In general, it + * will be whatever handle the user originally used for the current + * DB interface call. + */ + DBT *rskey; /* Returned secondary key. */ + DBT *rkey; /* Returned [primary] key. */ + DBT *rdata; /* Returned data. */ + + DBT my_rskey; /* Space for returned secondary key. */ + DBT my_rkey; /* Space for returned [primary] key. */ + DBT my_rdata; /* Space for returned data. */ + + DB_LOCKER *lref; /* Reference to default locker. */ + DB_LOCKER *locker; /* Locker for this operation. */ + DBT lock_dbt; /* DBT referencing lock. */ + DB_LOCK_ILOCK lock; /* Object to be locked. */ + DB_LOCK mylock; /* CDB lock held on this cursor. */ + + DBTYPE dbtype; /* Cursor type. */ + + DBC_INTERNAL *internal; /* Access method private. */ + + /* DBC PUBLIC HANDLE LIST BEGIN */ + int (*close) __P((DBC *)); + int (*cmp) __P((DBC *, DBC *, int *, u_int32_t)); + int (*count) __P((DBC *, db_recno_t *, u_int32_t)); + int (*del) __P((DBC *, u_int32_t)); + int (*dup) __P((DBC *, DBC **, u_int32_t)); + int (*get) __P((DBC *, DBT *, DBT *, u_int32_t)); + int (*get_priority) __P((DBC *, DB_CACHE_PRIORITY *)); + int (*pget) __P((DBC *, DBT *, DBT *, DBT *, u_int32_t)); + int (*put) __P((DBC *, DBT *, DBT *, u_int32_t)); + int (*set_priority) __P((DBC *, DB_CACHE_PRIORITY)); + /* DBC PUBLIC HANDLE LIST END */ + + /* The following are the method names deprecated in the 4.6 release. */ + int (*c_close) __P((DBC *)); + int (*c_count) __P((DBC *, db_recno_t *, u_int32_t)); + int (*c_del) __P((DBC *, u_int32_t)); + int (*c_dup) __P((DBC *, DBC **, u_int32_t)); + int (*c_get) __P((DBC *, DBT *, DBT *, u_int32_t)); + int (*c_pget) __P((DBC *, DBT *, DBT *, DBT *, u_int32_t)); + int (*c_put) __P((DBC *, DBT *, DBT *, u_int32_t)); + + /* DBC PRIVATE HANDLE LIST BEGIN */ + int (*am_bulk) __P((DBC *, DBT *, u_int32_t)); + int (*am_close) __P((DBC *, db_pgno_t, int *)); + int (*am_del) __P((DBC *, u_int32_t)); + int (*am_destroy) __P((DBC *)); + int (*am_get) __P((DBC *, DBT *, DBT *, u_int32_t, db_pgno_t *)); + int (*am_put) __P((DBC *, DBT *, DBT *, u_int32_t, db_pgno_t *)); + int (*am_writelock) __P((DBC *)); + /* DBC PRIVATE HANDLE LIST END */ + +/* + * DBC_DONTLOCK and DBC_RECOVER are used during recovery and transaction + * abort. If a transaction is being aborted or recovered then DBC_RECOVER + * will be set and locking and logging will be disabled on this cursor. If + * we are performing a compensating transaction (e.g. free page processing) + * then DB_DONTLOCK will be set to inhibit locking, but logging will still + * be required. DB_DONTLOCK is also used if the whole database is locked. + */ +#define DBC_ACTIVE 0x00001 /* Cursor in use. */ +#define DBC_BULK 0x00002 /* Bulk update cursor. */ +#define DBC_DONTLOCK 0x00004 /* Don't lock on this cursor. */ +#define DBC_DOWNREV 0x00008 /* Down rev replication master. */ +#define DBC_DUPLICATE 0x00010 /* Create a duplicate cursor. */ +#define DBC_ERROR 0x00020 /* Error in this request. */ +#define DBC_FAMILY 0x00040 /* Part of a locker family. */ +#define DBC_FROM_DB_GET 0x00080 /* Called from the DB->get() method. */ +#define DBC_MULTIPLE 0x00100 /* Return Multiple data. */ +#define DBC_MULTIPLE_KEY 0x00200 /* Return Multiple keys and data. */ +#define DBC_OPD 0x00400 /* Cursor references off-page dups. */ +#define DBC_OWN_LID 0x00800 /* Free lock id on destroy. */ +#define DBC_PARTITIONED 0x01000 /* Cursor for a partitioned db. */ +#define DBC_READ_COMMITTED 0x02000 /* Cursor has degree 2 isolation. */ +#define DBC_READ_UNCOMMITTED 0x04000 /* Cursor has degree 1 isolation. */ +#define DBC_RECOVER 0x08000 /* Recovery cursor; don't log/lock. */ +#define DBC_RMW 0x10000 /* Acquire write flag in read op. */ +#define DBC_TRANSIENT 0x20000 /* Cursor is transient. */ +#define DBC_WAS_READ_COMMITTED 0x40000 /* Cursor holds a read commited lock. */ +#define DBC_WRITECURSOR 0x80000 /* Cursor may be used to write (CDB). */ +#define DBC_WRITER 0x100000 /* Cursor immediately writing (CDB). */ + u_int32_t flags; +}; + +/* Key range statistics structure */ +struct __key_range { + double less; + double equal; + double greater; +}; + +/* Btree/Recno statistics structure. */ +struct __db_bt_stat { /* SHARED */ + u_int32_t bt_magic; /* Magic number. */ + u_int32_t bt_version; /* Version number. */ + u_int32_t bt_metaflags; /* Metadata flags. */ + u_int32_t bt_nkeys; /* Number of unique keys. */ + u_int32_t bt_ndata; /* Number of data items. */ + u_int32_t bt_pagecnt; /* Page count. */ + u_int32_t bt_pagesize; /* Page size. */ + u_int32_t bt_minkey; /* Minkey value. */ + u_int32_t bt_re_len; /* Fixed-length record length. */ + u_int32_t bt_re_pad; /* Fixed-length record pad. */ + u_int32_t bt_levels; /* Tree levels. */ + u_int32_t bt_int_pg; /* Internal pages. */ + u_int32_t bt_leaf_pg; /* Leaf pages. */ + u_int32_t bt_dup_pg; /* Duplicate pages. */ + u_int32_t bt_over_pg; /* Overflow pages. */ + u_int32_t bt_empty_pg; /* Empty pages. */ + u_int32_t bt_free; /* Pages on the free list. */ + uintmax_t bt_int_pgfree; /* Bytes free in internal pages. */ + uintmax_t bt_leaf_pgfree; /* Bytes free in leaf pages. */ + uintmax_t bt_dup_pgfree; /* Bytes free in duplicate pages. */ + uintmax_t bt_over_pgfree; /* Bytes free in overflow pages. */ +}; + +struct __db_compact { + /* Input Parameters. */ + u_int32_t compact_fillpercent; /* Desired fillfactor: 1-100 */ + db_timeout_t compact_timeout; /* Lock timeout. */ + u_int32_t compact_pages; /* Max pages to process. */ + /* Output Stats. */ + u_int32_t compact_empty_buckets; /* Empty hash buckets found. */ + u_int32_t compact_pages_free; /* Number of pages freed. */ + u_int32_t compact_pages_examine; /* Number of pages examine. */ + u_int32_t compact_levels; /* Number of levels removed. */ + u_int32_t compact_deadlock; /* Number of deadlocks. */ + db_pgno_t compact_pages_truncated; /* Pages truncated to OS. */ + /* Internal. */ + db_pgno_t compact_truncate; /* Page number for truncation */ +}; + +/* Hash statistics structure. */ +struct __db_h_stat { /* SHARED */ + u_int32_t hash_magic; /* Magic number. */ + u_int32_t hash_version; /* Version number. */ + u_int32_t hash_metaflags; /* Metadata flags. */ + u_int32_t hash_nkeys; /* Number of unique keys. */ + u_int32_t hash_ndata; /* Number of data items. */ + u_int32_t hash_pagecnt; /* Page count. */ + u_int32_t hash_pagesize; /* Page size. */ + u_int32_t hash_ffactor; /* Fill factor specified at create. */ + u_int32_t hash_buckets; /* Number of hash buckets. */ + u_int32_t hash_free; /* Pages on the free list. */ + uintmax_t hash_bfree; /* Bytes free on bucket pages. */ + u_int32_t hash_bigpages; /* Number of big key/data pages. */ + uintmax_t hash_big_bfree; /* Bytes free on big item pages. */ + u_int32_t hash_overflows; /* Number of overflow pages. */ + uintmax_t hash_ovfl_free; /* Bytes free on ovfl pages. */ + u_int32_t hash_dup; /* Number of dup pages. */ + uintmax_t hash_dup_free; /* Bytes free on duplicate pages. */ +}; + +/* Heap statistics structure. */ +struct __db_heap_stat { /* SHARED */ + u_int32_t heap_magic; /* Magic number. */ + u_int32_t heap_version; /* Version number. */ + u_int32_t heap_metaflags; /* Metadata flags. */ + u_int32_t heap_nrecs; /* Number of records. */ + u_int32_t heap_pagecnt; /* Page count. */ + u_int32_t heap_pagesize; /* Page size. */ + u_int32_t heap_nregions; /* Number of regions. */ + u_int32_t heap_regionsize; /* Number of pages in a region. */ +}; + +/* Queue statistics structure. */ +struct __db_qam_stat { /* SHARED */ + u_int32_t qs_magic; /* Magic number. */ + u_int32_t qs_version; /* Version number. */ + u_int32_t qs_metaflags; /* Metadata flags. */ + u_int32_t qs_nkeys; /* Number of unique keys. */ + u_int32_t qs_ndata; /* Number of data items. */ + u_int32_t qs_pagesize; /* Page size. */ + u_int32_t qs_extentsize; /* Pages per extent. */ + u_int32_t qs_pages; /* Data pages. */ + u_int32_t qs_re_len; /* Fixed-length record length. */ + u_int32_t qs_re_pad; /* Fixed-length record pad. */ + u_int32_t qs_pgfree; /* Bytes free in data pages. */ + u_int32_t qs_first_recno; /* First not deleted record. */ + u_int32_t qs_cur_recno; /* Next available record number. */ +}; + +/******************************************************* + * Environment. + *******************************************************/ +#define DB_REGION_MAGIC 0x120897 /* Environment magic number. */ + +/* + * Database environment structure. + * + * This is the public database environment handle. The private environment + * handle is the ENV structure. The user owns this structure, the library + * owns the ENV structure. The reason there are two structures is because + * the user's configuration outlives any particular DB_ENV->open call, and + * separate structures allows us to easily discard internal information without + * discarding the user's configuration. + * + * Fields in the DB_ENV structure should normally be set only by application + * DB_ENV handle methods. + */ + +/* + * Memory configuration types. + */ +typedef enum { + DB_MEM_LOCK=1, + DB_MEM_LOCKOBJECT=2, + DB_MEM_LOCKER=3, + DB_MEM_LOGID=4, + DB_MEM_TRANSACTION=5, + DB_MEM_THREAD=6 +} DB_MEM_CONFIG; + +/* + * Backup configuration types. + */ +typedef enum { + DB_BACKUP_READ_COUNT = 1, + DB_BACKUP_READ_SLEEP = 2, + DB_BACKUP_SIZE = 3, + DB_BACKUP_WRITE_DIRECT = 4 +} DB_BACKUP_CONFIG; + +struct __db_env { + ENV *env; /* Linked ENV structure */ + + /* + * The DB_ENV structure can be used concurrently, so field access is + * protected. + */ + db_mutex_t mtx_db_env; /* DB_ENV structure mutex */ + + /* Error message callback */ + void (*db_errcall) __P((const DB_ENV *, const char *, const char *)); + FILE *db_errfile; /* Error message file stream */ + const char *db_errpfx; /* Error message prefix */ + + /* Other message callback */ + void (*db_msgcall) __P((const DB_ENV *, const char *)); + FILE *db_msgfile; /* Other message file stream */ + + /* Other application callback functions */ + int (*app_dispatch) __P((DB_ENV *, DBT *, DB_LSN *, db_recops)); + void (*db_event_func) __P((DB_ENV *, u_int32_t, void *)); + void (*db_feedback) __P((DB_ENV *, int, int)); + void (*db_free) __P((void *)); + void (*db_paniccall) __P((DB_ENV *, int)); + void *(*db_malloc) __P((size_t)); + void *(*db_realloc) __P((void *, size_t)); + int (*is_alive) __P((DB_ENV *, pid_t, db_threadid_t, u_int32_t)); + void (*thread_id) __P((DB_ENV *, pid_t *, db_threadid_t *)); + char *(*thread_id_string) __P((DB_ENV *, pid_t, db_threadid_t, char *)); + + /* Application specified paths */ + char *db_log_dir; /* Database log file directory */ + char *db_md_dir; /* Persistent metadata directory */ + char *db_tmp_dir; /* Database tmp file directory */ + + char *db_create_dir; /* Create directory for data files */ + char **db_data_dir; /* Database data file directories */ + int data_cnt; /* Database data file slots */ + int data_next; /* Next database data file slot */ + + char *intermediate_dir_mode; /* Intermediate directory perms */ + + long shm_key; /* shmget key */ + + char *passwd; /* Cryptography support */ + size_t passwd_len; + + /* Private handle references */ + void *app_private; /* Application-private handle */ + void *api1_internal; /* C++, Perl API private */ + void *api2_internal; /* Java API private */ + + u_int32_t verbose; /* DB_VERB_XXX flags */ + + /* Mutex configuration */ + u_int32_t mutex_align; /* Mutex alignment */ + u_int32_t mutex_cnt; /* Number of mutexes to configure */ + u_int32_t mutex_inc; /* Number of mutexes to add */ + u_int32_t mutex_max; /* Max number of mutexes */ + u_int32_t mutex_tas_spins;/* Test-and-set spin count */ + + /* Locking configuration */ + u_int8_t *lk_conflicts; /* Two dimensional conflict matrix */ + int lk_modes; /* Number of lock modes in table */ + u_int32_t lk_detect; /* Deadlock detect on all conflicts */ + u_int32_t lk_max; /* Maximum number of locks */ + u_int32_t lk_max_lockers;/* Maximum number of lockers */ + u_int32_t lk_max_objects;/* Maximum number of locked objects */ + u_int32_t lk_init; /* Initial number of locks */ + u_int32_t lk_init_lockers;/* Initial number of lockers */ + u_int32_t lk_init_objects;/* Initial number of locked objects */ + u_int32_t lk_partitions ;/* Number of object partitions */ + db_timeout_t lk_timeout; /* Lock timeout period */ + /* Used during initialization */ + u_int32_t locker_t_size; /* Locker hash table size. */ + u_int32_t object_t_size; /* Object hash table size. */ + + /* Logging configuration */ + u_int32_t lg_bsize; /* Buffer size */ + u_int32_t lg_fileid_init; /* Initial allocation for fname structs */ + int lg_filemode; /* Log file permission mode */ + u_int32_t lg_regionmax; /* Region size */ + u_int32_t lg_size; /* Log file size */ + u_int32_t lg_flags; /* Log configuration */ + + /* Memory pool configuration */ + u_int32_t mp_gbytes; /* Cache size: GB */ + u_int32_t mp_bytes; /* Cache size: bytes */ + u_int32_t mp_max_gbytes; /* Maximum cache size: GB */ + u_int32_t mp_max_bytes; /* Maximum cache size: bytes */ + size_t mp_mmapsize; /* Maximum file size for mmap */ + int mp_maxopenfd; /* Maximum open file descriptors */ + int mp_maxwrite; /* Maximum buffers to write */ + u_int mp_ncache; /* Initial number of cache regions */ + u_int32_t mp_pagesize; /* Average page size */ + u_int32_t mp_tablesize; /* Approximate hash table size */ + u_int32_t mp_mtxcount; /* Number of mutexs */ + /* Sleep after writing max buffers */ + db_timeout_t mp_maxwrite_sleep; + + /* Transaction configuration */ + u_int32_t tx_init; /* Initial number of transactions */ + u_int32_t tx_max; /* Maximum number of transactions */ + time_t tx_timestamp; /* Recover to specific timestamp */ + db_timeout_t tx_timeout; /* Timeout for transactions */ + + /* Thread tracking configuration */ + u_int32_t thr_init; /* Thread count */ + u_int32_t thr_max; /* Thread max */ + roff_t memory_max; /* Maximum region memory */ + + /* + * The following fields are not strictly user-owned, but they outlive + * the ENV structure, and so are stored here. + */ + DB_FH *registry; /* DB_REGISTER file handle */ + u_int32_t registry_off; /* + * Offset of our slot. We can't use + * off_t because its size depends on + * build settings. + */ + db_timeout_t envreg_timeout; /* DB_REGISTER wait timeout */ + +#define DB_ENV_AUTO_COMMIT 0x00000001 /* DB_AUTO_COMMIT */ +#define DB_ENV_CDB_ALLDB 0x00000002 /* CDB environment wide locking */ +#define DB_ENV_FAILCHK 0x00000004 /* Failchk is running */ +#define DB_ENV_DIRECT_DB 0x00000008 /* DB_DIRECT_DB set */ +#define DB_ENV_DSYNC_DB 0x00000010 /* DB_DSYNC_DB set */ +#define DB_ENV_DATABASE_LOCKING 0x00000020 /* Try database-level locking */ +#define DB_ENV_MULTIVERSION 0x00000040 /* DB_MULTIVERSION set */ +#define DB_ENV_NOLOCKING 0x00000080 /* DB_NOLOCKING set */ +#define DB_ENV_NOMMAP 0x00000100 /* DB_NOMMAP set */ +#define DB_ENV_NOPANIC 0x00000200 /* Okay if panic set */ +#define DB_ENV_OVERWRITE 0x00000400 /* DB_OVERWRITE set */ +#define DB_ENV_REGION_INIT 0x00000800 /* DB_REGION_INIT set */ +#define DB_ENV_TIME_NOTGRANTED 0x00001000 /* DB_TIME_NOTGRANTED set */ +#define DB_ENV_TXN_NOSYNC 0x00002000 /* DB_TXN_NOSYNC set */ +#define DB_ENV_TXN_NOWAIT 0x00004000 /* DB_TXN_NOWAIT set */ +#define DB_ENV_TXN_SNAPSHOT 0x00008000 /* DB_TXN_SNAPSHOT set */ +#define DB_ENV_TXN_WRITE_NOSYNC 0x00010000 /* DB_TXN_WRITE_NOSYNC set */ +#define DB_ENV_YIELDCPU 0x00020000 /* DB_YIELDCPU set */ +#define DB_ENV_HOTBACKUP 0x00040000 /* DB_HOTBACKUP_IN_PROGRESS set */ +#define DB_ENV_NOFLUSH 0x00080000 /* DB_NOFLUSH set */ + u_int32_t flags; + + /* DB_ENV PUBLIC HANDLE LIST BEGIN */ + int (*add_data_dir) __P((DB_ENV *, const char *)); + int (*close) __P((DB_ENV *, u_int32_t)); + void (*err) __P((const DB_ENV *, int, const char *, ...)); + void (*errx) __P((const DB_ENV *, const char *, ...)); + int (*get_alloc) __P((DB_ENV *, void *(**)(size_t), + void *(**)(void *, size_t), void (**)(void *))); + int (*get_cache_max) __P((DB_ENV *, u_int32_t *, u_int32_t *)); + int (*get_cachesize) __P((DB_ENV *, u_int32_t *, u_int32_t *, int *)); + int (*get_create_dir) __P((DB_ENV *, const char **)); + int (*get_data_dirs) __P((DB_ENV *, const char ***)); + int (*get_data_len) __P((DB_ENV *, u_int32_t *)); + void (*get_errcall) __P((DB_ENV *, + void (**)(const DB_ENV *, const char *, const char *))); + void (*get_errfile) __P((DB_ENV *, FILE **)); + void (*get_errpfx) __P((DB_ENV *, const char **)); + int (*get_flags) __P((DB_ENV *, u_int32_t *)); + int (*get_feedback) __P((DB_ENV *, void (**)(DB_ENV *, int, int))); + int (*get_home) __P((DB_ENV *, const char **)); + int (*get_intermediate_dir_mode) __P((DB_ENV *, const char **)); + int (*get_memory_init) __P((DB_ENV *, DB_MEM_CONFIG, u_int32_t *)); + int (*get_memory_max) __P((DB_ENV *, u_int32_t *, u_int32_t *)); + int (*get_metadata_dir) __P((DB_ENV *, const char **)); + int (*get_mp_max_openfd) __P((DB_ENV *, int *)); + int (*get_mp_max_write) __P((DB_ENV *, int *, db_timeout_t *)); + int (*get_mp_mmapsize) __P((DB_ENV *, size_t *)); + int (*get_mp_mtxcount) __P((DB_ENV *, u_int32_t *)); + int (*get_mp_pagesize) __P((DB_ENV *, u_int32_t *)); + int (*get_mp_tablesize) __P((DB_ENV *, u_int32_t *)); + void (*get_msgcall) + __P((DB_ENV *, void (**)(const DB_ENV *, const char *))); + void (*get_msgfile) __P((DB_ENV *, FILE **)); + int (*get_open_flags) __P((DB_ENV *, u_int32_t *)); + int (*get_shm_key) __P((DB_ENV *, long *)); + int (*get_thread_count) __P((DB_ENV *, u_int32_t *)); + int (*get_thread_id_fn) + __P((DB_ENV *, void (**)(DB_ENV *, pid_t *, db_threadid_t *))); + int (*get_thread_id_string_fn) __P((DB_ENV *, + char *(**)(DB_ENV *, pid_t, db_threadid_t, char *))); + int (*get_timeout) __P((DB_ENV *, db_timeout_t *, u_int32_t)); + int (*get_tmp_dir) __P((DB_ENV *, const char **)); + int (*get_verbose) __P((DB_ENV *, u_int32_t, int *)); + int (*is_bigendian) __P((void)); + int (*memp_fcreate) __P((DB_ENV *, DB_MPOOLFILE **, u_int32_t)); + int (*memp_register) __P((DB_ENV *, int, int (*)(DB_ENV *, db_pgno_t, + void *, DBT *), int (*)(DB_ENV *, db_pgno_t, void *, DBT *))); + int (*memp_stat) __P((DB_ENV *, + DB_MPOOL_STAT **, DB_MPOOL_FSTAT ***, u_int32_t)); + int (*memp_stat_print) __P((DB_ENV *, u_int32_t)); + int (*memp_sync) __P((DB_ENV *, DB_LSN *)); + int (*memp_trickle) __P((DB_ENV *, int, int *)); + int (*mutex_alloc) __P((DB_ENV *, u_int32_t, db_mutex_t *)); + int (*mutex_free) __P((DB_ENV *, db_mutex_t)); + int (*mutex_get_align) __P((DB_ENV *, u_int32_t *)); + int (*mutex_get_increment) __P((DB_ENV *, u_int32_t *)); + int (*mutex_get_init) __P((DB_ENV *, u_int32_t *)); + int (*mutex_get_max) __P((DB_ENV *, u_int32_t *)); + int (*mutex_get_tas_spins) __P((DB_ENV *, u_int32_t *)); + int (*mutex_lock) __P((DB_ENV *, db_mutex_t)); + int (*mutex_set_align) __P((DB_ENV *, u_int32_t)); + int (*mutex_set_increment) __P((DB_ENV *, u_int32_t)); + int (*mutex_set_init) __P((DB_ENV *, u_int32_t)); + int (*mutex_set_max) __P((DB_ENV *, u_int32_t)); + int (*mutex_set_tas_spins) __P((DB_ENV *, u_int32_t)); + int (*mutex_stat) __P((DB_ENV *, DB_MUTEX_STAT **, u_int32_t)); + int (*mutex_stat_print) __P((DB_ENV *, u_int32_t)); + int (*mutex_unlock) __P((DB_ENV *, db_mutex_t)); + int (*open) __P((DB_ENV *, const char *, u_int32_t, int)); + int (*remove) __P((DB_ENV *, const char *, u_int32_t)); + int (*set_alloc) __P((DB_ENV *, void *(*)(size_t), + void *(*)(void *, size_t), void (*)(void *))); + int (*set_cache_max) __P((DB_ENV *, u_int32_t, u_int32_t)); + int (*set_cachesize) __P((DB_ENV *, u_int32_t, u_int32_t, int)); + int (*set_create_dir) __P((DB_ENV *, const char *)); + int (*set_data_dir) __P((DB_ENV *, const char *)); + int (*set_data_len) __P((DB_ENV *, u_int32_t)); + int (*set_encrypt) __P((DB_ENV *, const char *, u_int32_t)); + void (*set_errcall) __P((DB_ENV *, + void (*)(const DB_ENV *, const char *, const char *))); + void (*set_errfile) __P((DB_ENV *, FILE *)); + void (*set_errpfx) __P((DB_ENV *, const char *)); + int (*set_event_notify) + __P((DB_ENV *, void (*)(DB_ENV *, u_int32_t, void *))); + int (*set_feedback) __P((DB_ENV *, void (*)(DB_ENV *, int, int))); + int (*set_flags) __P((DB_ENV *, u_int32_t, int)); + int (*set_intermediate_dir_mode) __P((DB_ENV *, const char *)); + int (*set_isalive) __P((DB_ENV *, + int (*)(DB_ENV *, pid_t, db_threadid_t, u_int32_t))); + int (*set_memory_init) __P((DB_ENV *, DB_MEM_CONFIG, u_int32_t)); + int (*set_memory_max) __P((DB_ENV *, u_int32_t, u_int32_t)); + int (*set_metadata_dir) __P((DB_ENV *, const char *)); + int (*set_mp_max_openfd) __P((DB_ENV *, int)); + int (*set_mp_max_write) __P((DB_ENV *, int, db_timeout_t)); + int (*set_mp_mmapsize) __P((DB_ENV *, size_t)); + int (*set_mp_mtxcount) __P((DB_ENV *, u_int32_t)); + int (*set_mp_pagesize) __P((DB_ENV *, u_int32_t)); + int (*set_mp_tablesize) __P((DB_ENV *, u_int32_t)); + void (*set_msgcall) + __P((DB_ENV *, void (*)(const DB_ENV *, const char *))); + void (*set_msgfile) __P((DB_ENV *, FILE *)); + int (*set_paniccall) __P((DB_ENV *, void (*)(DB_ENV *, int))); + int (*set_shm_key) __P((DB_ENV *, long)); + int (*set_thread_count) __P((DB_ENV *, u_int32_t)); + int (*set_thread_id) + __P((DB_ENV *, void (*)(DB_ENV *, pid_t *, db_threadid_t *))); + int (*set_thread_id_string) __P((DB_ENV *, + char *(*)(DB_ENV *, pid_t, db_threadid_t, char *))); + int (*set_timeout) __P((DB_ENV *, db_timeout_t, u_int32_t)); + int (*set_tmp_dir) __P((DB_ENV *, const char *)); + int (*set_verbose) __P((DB_ENV *, u_int32_t, int)); + int (*stat_print) __P((DB_ENV *, u_int32_t)); + /* DB_ENV PUBLIC HANDLE LIST END */ + + /* DB_ENV PRIVATE HANDLE LIST BEGIN */ + int (*prdbt) __P((DBT *, int, + const char *, void *, int (*)(void *, const void *), int, int)); + /* DB_ENV PRIVATE HANDLE LIST END */ +}; + +/* + * Dispatch structure for recovery, log verification and print routines. Since + * internal and external routines take different arguments (ENV versus DB_ENV), + * we need something more elaborate than a single pointer and size. + */ +struct __db_distab { + int (**int_dispatch) __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); + size_t int_size; + int (**ext_dispatch) __P((DB_ENV *, DBT *, DB_LSN *, db_recops)); + size_t ext_size; +}; + +/* + * Log verification configuration structure. + */ +struct __db_logvrfy_config { + int continue_after_fail, verbose; + u_int32_t cachesize; + const char *temp_envhome; + const char *dbfile, *dbname; + DB_LSN start_lsn, end_lsn; + time_t start_time, end_time; +}; + +struct __db_channel { + CHANNEL *channel; /* Pointer to internal state details. */ + int eid; /* Env. ID passed in constructor. */ + db_timeout_t timeout; + + /* DB_CHANNEL PUBLIC HANDLE LIST BEGIN */ + int (*close) __P((DB_CHANNEL *, u_int32_t)); + int (*send_msg) __P((DB_CHANNEL *, DBT *, u_int32_t, u_int32_t)); + int (*send_request) __P((DB_CHANNEL *, + DBT *, u_int32_t, DBT *, db_timeout_t, u_int32_t)); + int (*set_timeout) __P((DB_CHANNEL *, db_timeout_t)); + /* DB_CHANNEL PUBLIC HANDLE LIST END */ +}; + +struct __db_site { + ENV *env; + int eid; + const char *host; + u_int port; + u_int32_t flags; + + /* DB_SITE PUBLIC HANDLE LIST BEGIN */ + int (*get_address) __P((DB_SITE *, const char **, u_int *)); + int (*get_config) __P((DB_SITE *, u_int32_t, u_int32_t *)); + int (*get_eid) __P((DB_SITE *, int *)); + int (*set_config) __P((DB_SITE *, u_int32_t, u_int32_t)); + int (*remove) __P((DB_SITE *)); + int (*close) __P((DB_SITE *)); + /* DB_SITE PUBLIC HANDLE LIST END */ +}; + +#if DB_DBM_HSEARCH != 0 +/******************************************************* + * Dbm/Ndbm historic interfaces. + *******************************************************/ +typedef struct __db DBM; + +#define DBM_INSERT 0 /* Flags to dbm_store(). */ +#define DBM_REPLACE 1 + +/* + * The DB support for ndbm(3) always appends this suffix to the + * file name to avoid overwriting the user's original database. + */ +#define DBM_SUFFIX ".db" + +#if defined(_XPG4_2) +typedef struct { + char *dptr; + size_t dsize; +} datum; +#else +typedef struct { + char *dptr; + int dsize; +} datum; +#endif + +/* + * Translate NDBM calls into DB calls so that DB doesn't step on the + * application's name space. + */ +#define dbm_clearerr(a) __db_ndbm_clearerr@DB_VERSION_UNIQUE_NAME@(a) +#define dbm_close(a) __db_ndbm_close@DB_VERSION_UNIQUE_NAME@(a) +#define dbm_delete(a, b) __db_ndbm_delete@DB_VERSION_UNIQUE_NAME@(a, b) +#define dbm_dirfno(a) __db_ndbm_dirfno@DB_VERSION_UNIQUE_NAME@(a) +#define dbm_error(a) __db_ndbm_error@DB_VERSION_UNIQUE_NAME@(a) +#define dbm_fetch(a, b) __db_ndbm_fetch@DB_VERSION_UNIQUE_NAME@(a, b) +#define dbm_firstkey(a) __db_ndbm_firstkey@DB_VERSION_UNIQUE_NAME@(a) +#define dbm_nextkey(a) __db_ndbm_nextkey@DB_VERSION_UNIQUE_NAME@(a) +#define dbm_open(a, b, c) __db_ndbm_open@DB_VERSION_UNIQUE_NAME@(a, b, c) +#define dbm_pagfno(a) __db_ndbm_pagfno@DB_VERSION_UNIQUE_NAME@(a) +#define dbm_rdonly(a) __db_ndbm_rdonly@DB_VERSION_UNIQUE_NAME@(a) +#define dbm_store(a, b, c, d) \ + __db_ndbm_store@DB_VERSION_UNIQUE_NAME@(a, b, c, d) + +/* + * Translate DBM calls into DB calls so that DB doesn't step on the + * application's name space. + * + * The global variables dbrdonly, dirf and pagf were not retained when 4BSD + * replaced the dbm interface with ndbm, and are not supported here. + */ +#define dbminit(a) __db_dbm_init@DB_VERSION_UNIQUE_NAME@(a) +#define dbmclose __db_dbm_close@DB_VERSION_UNIQUE_NAME@ +#if !defined(__cplusplus) +#define delete(a) __db_dbm_delete@DB_VERSION_UNIQUE_NAME@(a) +#endif +#define fetch(a) __db_dbm_fetch@DB_VERSION_UNIQUE_NAME@(a) +#define firstkey __db_dbm_firstkey@DB_VERSION_UNIQUE_NAME@ +#define nextkey(a) __db_dbm_nextkey@DB_VERSION_UNIQUE_NAME@(a) +#define store(a, b) __db_dbm_store@DB_VERSION_UNIQUE_NAME@(a, b) + +/******************************************************* + * Hsearch historic interface. + *******************************************************/ +typedef enum { + FIND, ENTER +} ACTION; + +typedef struct entry { + char *key; + char *data; +} ENTRY; + +#define hcreate(a) __db_hcreate@DB_VERSION_UNIQUE_NAME@(a) +#define hdestroy __db_hdestroy@DB_VERSION_UNIQUE_NAME@ +#define hsearch(a, b) __db_hsearch@DB_VERSION_UNIQUE_NAME@(a, b) + +#endif /* DB_DBM_HSEARCH */ + +#if defined(__cplusplus) +} +#endif + +@platform_footer@ +#endif /* !_DB_H_ */ diff -r 000000000000 -r a1985f14b030 src/dbinc/db_185.in --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/dbinc/db_185.in Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,198 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 1996, 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +/* + * Copyright (c) 1990, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $Id$ + */ + +#ifndef _DB_185_H_ +#define _DB_185_H_ + +#include + +#include + +#if defined(__cplusplus) +extern "C" { +#endif + +/* + * XXX + * Handle function prototypes and the keyword "const". This steps on name + * space that DB doesn't control, but all of the other solutions are worse. + */ +#undef __P +#if defined(__STDC__) || defined(__cplusplus) +#define __P(protos) protos /* ANSI C prototypes */ +#else +#define const +#define __P(protos) () /* K&R C preprocessor */ +#endif + +#define RET_ERROR -1 /* Return values. */ +#define RET_SUCCESS 0 +#define RET_SPECIAL 1 + +#ifndef __BIT_TYPES_DEFINED__ +#define __BIT_TYPES_DEFINED__ +@u_int8_decl@ +@int16_decl@ +@u_int16_decl@ +@int32_decl@ +@u_int32_decl@ +#endif + +/* + * XXX + * SGI/IRIX already has a pgno_t. + */ +#ifdef __sgi +#define pgno_t db_pgno_t +#endif + +#define MAX_PAGE_NUMBER 0xffffffff /* >= # of pages in a file */ +typedef u_int32_t pgno_t; +#define MAX_PAGE_OFFSET 65535 /* >= # of bytes in a page */ +typedef u_int16_t indx_t; +#define MAX_REC_NUMBER 0xffffffff /* >= # of records in a tree */ +typedef u_int32_t recno_t; + +/* Key/data structure -- a Data-Base Thang. */ +typedef struct { + void *data; /* data */ + size_t size; /* data length */ +} DBT; + +/* Routine flags. */ +#define R_CURSOR 1 /* del, put, seq */ +#define __R_UNUSED 2 /* UNUSED */ +#define R_FIRST 3 /* seq */ +#define R_IAFTER 4 /* put (RECNO) */ +#define R_IBEFORE 5 /* put (RECNO) */ +#define R_LAST 6 /* seq (BTREE, RECNO) */ +#define R_NEXT 7 /* seq */ +#define R_NOOVERWRITE 8 /* put */ +#define R_PREV 9 /* seq (BTREE, RECNO) */ +#define R_SETCURSOR 10 /* put (RECNO) */ +#define R_RECNOSYNC 11 /* sync (RECNO) */ + +typedef enum { DB_BTREE, DB_HASH, DB_RECNO } DBTYPE; + +/* Access method description structure. */ +typedef struct __db { + DBTYPE type; /* Underlying db type. */ + int (*close) __P((struct __db *)); + int (*del) __P((const struct __db *, const DBT *, u_int)); + int (*get) __P((const struct __db *, const DBT *, DBT *, u_int)); + int (*put) __P((const struct __db *, DBT *, const DBT *, u_int)); + int (*seq) __P((const struct __db *, DBT *, DBT *, u_int)); + int (*sync) __P((const struct __db *, u_int)); + void *internal; /* Access method private. */ + int (*fd) __P((const struct __db *)); +} DB; + +#define BTREEMAGIC 0x053162 +#define BTREEVERSION 3 + +/* Structure used to pass parameters to the btree routines. */ +typedef struct { +#define R_DUP 0x01 /* duplicate keys */ + u_int32_t flags; + u_int32_t cachesize; /* bytes to cache */ + u_int32_t maxkeypage; /* maximum keys per page */ + u_int32_t minkeypage; /* minimum keys per page */ + u_int32_t psize; /* page size */ + int (*compare) /* comparison function */ + __P((const DBT *, const DBT *)); + size_t (*prefix) /* prefix function */ + __P((const DBT *, const DBT *)); + int lorder; /* byte order */ +} BTREEINFO; + +#define HASHMAGIC 0x061561 +#define HASHVERSION 2 + +/* Structure used to pass parameters to the hashing routines. */ +typedef struct { + u_int32_t bsize; /* bucket size */ + u_int32_t ffactor; /* fill factor */ + u_int32_t nelem; /* number of elements */ + u_int32_t cachesize; /* bytes to cache */ + u_int32_t /* hash function */ + (*hash) __P((const void *, size_t)); + int lorder; /* byte order */ +} HASHINFO; + +/* Structure used to pass parameters to the record routines. */ +typedef struct { +#define R_FIXEDLEN 0x01 /* fixed-length records */ +#define R_NOKEY 0x02 /* key not required */ +#define R_SNAPSHOT 0x04 /* snapshot the input */ + u_int32_t flags; + u_int32_t cachesize; /* bytes to cache */ + u_int32_t psize; /* page size */ + int lorder; /* byte order */ + size_t reclen; /* record length (fixed-length records) */ + u_char bval; /* delimiting byte (variable-length records */ + char *bfname; /* btree file name */ +} RECNOINFO; + +/* Re-define the user's dbopen calls. */ +#define dbopen __db185_open@DB_VERSION_UNIQUE_NAME@ + +#if defined(__cplusplus) +} +#endif + +#endif /* !_DB_185_H_ */ diff -r 000000000000 -r a1985f14b030 src/dbinc/db_am.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/dbinc/db_am.h Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,349 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 1996, 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + * $Id$ + */ +#ifndef _DB_AM_H_ +#define _DB_AM_H_ + +#if defined(__cplusplus) +extern "C" { +#endif + +struct __db_foreign_info; \ + typedef struct __db_foreign_info DB_FOREIGN_INFO; + +/* + * Keep track of information for foreign keys. Used to maintain a linked list + * of 'primary' DBs which reference this 'foreign' DB. + */ +struct __db_foreign_info { + DB *dbp; + u_int32_t flags; + int (*callback) __P((DB *, const DBT *, DBT *, const DBT *, int *)); + + /* + * List entries for foreign key. + * + * !!! + * Explicit representations of structures from queue.h. + * LIST_ENTRY(__db) s_links; + */ + struct { + struct __db_foreign_info *le_next; + struct __db_foreign_info **le_prev; + } f_links; +}; + +/* + * IS_ENV_AUTO_COMMIT -- + * Auto-commit test for enviroment operations: DbEnv::{open,remove,rename} + */ +#define IS_ENV_AUTO_COMMIT(env, txn, flags) \ + (LF_ISSET(DB_AUTO_COMMIT) || \ + (((txn) == NULL || F_ISSET((txn), TXN_FAMILY)) && \ + F_ISSET((env)->dbenv, DB_ENV_AUTO_COMMIT) && \ + !LF_ISSET(DB_NO_AUTO_COMMIT))) + +/* + * IS_DB_AUTO_COMMIT -- + * Auto-commit test for database operations. + */ +#define IS_DB_AUTO_COMMIT(dbp, txn) \ + (((txn) == NULL || F_ISSET((txn), TXN_FAMILY)) && \ + F_ISSET((dbp), DB_AM_TXN)) + +/* + * STRIP_AUTO_COMMIT -- + * Releases after 4.3 no longer requires DB operations to specify the + * AUTO_COMMIT flag, but the API continues to allow it to be specified. + */ +#define STRIP_AUTO_COMMIT(f) FLD_CLR((f), DB_AUTO_COMMIT) + +/* DB recovery operation codes. */ +#define DB_ADD_DUP 1 +#define DB_REM_DUP 2 +#define DB_ADD_BIG 3 +#define DB_REM_BIG 4 +#define DB_ADD_PAGE_COMPAT 5 /* Compatibility for 4.2 db_relink */ +#define DB_REM_PAGE_COMPAT 6 /* Compatibility for 4.2 db_relink */ +#define DB_APPEND_BIG 7 +#define DB_ADD_HEAP 8 +#define DB_REM_HEAP 9 + +#define OP_MODE_SHIFT 8 +#define OP_PAGE_MASK 0xff + +#define OP_SET(mode, page) (((mode) << OP_MODE_SHIFT) | (TYPE(page))) +#define OP_MODE_GET(mode) ((mode) >> OP_MODE_SHIFT) +#define OP_PAGE_GET(mode) ((mode) & OP_PAGE_MASK) + + +/* + * Standard initialization and shutdown macros for all recovery functions. + */ +#define REC_INTRO(func, ip, do_cursor) do { \ + argp = NULL; \ + dbc = NULL; \ + file_dbp = NULL; \ + COMPQUIET(mpf, NULL); /* Not all recovery routines use mpf. */\ + if ((ret = func(env, &file_dbp, \ + (info != NULL) ? ((DB_TXNHEAD *)info)->td : NULL, \ + dbtp->data, &argp)) != 0) { \ + if (ret == DB_DELETED) { \ + ret = 0; \ + goto done; \ + } \ + goto out; \ + } \ + if (do_cursor) { \ + if ((ret = __db_cursor(file_dbp, \ + ip, NULL, &dbc, DB_RECOVER)) != 0) \ + goto out; \ + } \ + mpf = file_dbp->mpf; \ +} while (0) + +#define REC_CLOSE { \ + int __t_ret; \ + if (argp != NULL) \ + __os_free(env, argp); \ + if (dbc != NULL && \ + (__t_ret = __dbc_close(dbc)) != 0 && ret == 0) \ + ret = __t_ret; \ + } \ + return (ret) + +/* + * No-op versions of the same macros. + */ +#define REC_NOOP_INTRO(func) do { \ + argp = NULL; \ + if ((ret = func(env, dbtp->data, &argp)) != 0) \ + return (ret); \ +} while (0) +#define REC_NOOP_CLOSE \ + if (argp != NULL) \ + __os_free(env, argp); \ + return (ret) + +/* + * Macro for reading pages during recovery. In most cases we + * want to avoid an error if the page is not found during rollback. + */ +#define REC_FGET(mpf, ip, pgno, pagep, cont) \ + if ((ret = __memp_fget(mpf, \ + &(pgno), ip, NULL, 0, pagep)) != 0) { \ + if (ret != DB_PAGE_NOTFOUND) { \ + ret = __db_pgerr(file_dbp, pgno, ret); \ + goto out; \ + } else \ + goto cont; \ + } +#define REC_DIRTY(mpf, ip, priority, pagep) \ + if ((ret = __memp_dirty(mpf, \ + pagep, ip, NULL, priority, DB_MPOOL_EDIT)) != 0) { \ + ret = __db_pgerr(file_dbp, PGNO(*(pagep)), ret); \ + goto out; \ + } + +/* + * Standard debugging macro for all recovery functions. + */ +#ifdef DEBUG_RECOVER +#define REC_PRINT(func) \ + (void)func(env, dbtp, lsnp, op, info); +#else +#define REC_PRINT(func) +#endif + +/* + * Actions to __db_lget + */ +#define LCK_ALWAYS 1 /* Lock even for off page dup cursors */ +#define LCK_COUPLE 2 /* Lock Couple */ +#define LCK_COUPLE_ALWAYS 3 /* Lock Couple even in txn. */ +#define LCK_DOWNGRADE 4 /* Downgrade the lock. (internal) */ +#define LCK_ROLLBACK 5 /* Lock even if in rollback */ + +/* + * If doing transactions we have to hold the locks associated with a data item + * from a page for the entire transaction. However, we don't have to hold the + * locks associated with walking the tree. Distinguish between the two so that + * we don't tie up the internal pages of the tree longer than necessary. + */ +#define __LPUT(dbc, lock) \ + __ENV_LPUT((dbc)->env, lock) + +#define __ENV_LPUT(env, lock) \ + (LOCK_ISSET(lock) ? __lock_put(env, &(lock)) : 0) + +/* + * __TLPUT -- transactional lock put + * If the lock is valid then + * If we are not in a transaction put the lock. + * Else if the cursor is doing dirty reads and this was a read then + * put the lock. + * Else if the db is supporting dirty reads and this is a write then + * downgrade it. + * Else do nothing. + */ +#define __TLPUT(dbc, lock) \ + (LOCK_ISSET(lock) ? __db_lput(dbc, &(lock)) : 0) + +/* + * Check whether a database is a primary (that is, has associated secondaries). + */ +#define DB_IS_PRIMARY(dbp) (LIST_FIRST(&dbp->s_secondaries) != NULL) +/* + * A database should be required to be readonly if it's been explicitly + * specified as such or if we're a client in a replicated environment + * and the user did not specify DB_TXN_NOT_DURABLE. + */ +#define DB_IS_READONLY(dbp) \ + (F_ISSET(dbp, DB_AM_RDONLY) || \ + (IS_REP_CLIENT((dbp)->env) && !F_ISSET((dbp), DB_AM_NOT_DURABLE))) + +#ifdef HAVE_COMPRESSION +/* + * Check whether a database is compressed (btree only) + */ +#define DB_IS_COMPRESSED(dbp) \ + (((BTREE *)(dbp)->bt_internal)->bt_compress != NULL) +#endif + +/* + * We copy the key out if there's any chance the key in the database is not + * the same as the user-specified key. If there is a custom comparator we + * return a key, as the user-specified key might be a partial key, containing + * only the unique identifier. [#13572] [#15770] + * + * The test for (flags != 0) is necessary for Db.{get,pget}, but it's not + * legal to pass a non-zero flags value to Dbc.{get,pget}. + * + * We need to split out the hash component, since it is possible to build + * without hash support enabled. Which would result in a null pointer access. + */ +#ifdef HAVE_HASH +#define DB_RETURNS_A_KEY_HASH(dbp) \ + ((HASH *)(dbp)->h_internal)->h_compare != NULL +#else +#define DB_RETURNS_A_KEY_HASH(dbp) 0 +#endif +#define DB_RETURNS_A_KEY(dbp, flags) \ + (((flags) != 0 && (flags) != DB_GET_BOTH && \ + (flags) != DB_GET_BOTH_RANGE && (flags) != DB_SET) || \ + ((BTREE *)(dbp)->bt_internal)->bt_compare != __bam_defcmp ||\ + DB_RETURNS_A_KEY_HASH(dbp)) + +/* + * For portability, primary keys that are record numbers are stored in + * secondaries in the same byte order as the secondary database. As a + * consequence, we need to swap the byte order of these keys before attempting + * to use them for lookups in the primary. We also need to swap user-supplied + * primary keys that are used in secondary lookups (for example, with the + * DB_GET_BOTH flag on a secondary get). + */ +#include "dbinc/db_swap.h" + +#define SWAP_IF_NEEDED(sdbp, pkey) \ + do { \ + if (((sdbp)->s_primary->type == DB_QUEUE || \ + (sdbp)->s_primary->type == DB_RECNO) && \ + F_ISSET((sdbp), DB_AM_SWAP)) \ + P_32_SWAP((pkey)->data); \ + } while (0) + +/* + * Cursor adjustment: + * Return the first DB handle in the sorted ENV list of DB + * handles that has a matching file ID. + */ +#define FIND_FIRST_DB_MATCH(env, dbp, tdbp) do { \ + for ((tdbp) = (dbp); \ + TAILQ_PREV((tdbp), __dblist, dblistlinks) != NULL && \ + TAILQ_PREV((tdbp), \ + __dblist, dblistlinks)->adj_fileid == (dbp)->adj_fileid;\ + (tdbp) = TAILQ_PREV((tdbp), __dblist, dblistlinks)) \ + ; \ +} while (0) + +/* + * Macros used to implement a binary search algorithm. Shared between the + * btree and hash implementations. + */ +#define DB_BINARY_SEARCH_FOR(base, limit, nument, adjust) \ + for (base = 0, limit = (nument) / (db_indx_t)(adjust); \ + (limit) != 0; (limit) >>= 1) + +#define DB_BINARY_SEARCH_INCR(index, base, limit, adjust) \ + index = (base) + (((limit) >> 1) * (adjust)) + +#define DB_BINARY_SEARCH_SHIFT_BASE(index, base, limit, adjust) do { \ + base = (index) + (adjust); \ + --(limit); \ +} while (0) + +/* + * Sequence macros, shared between sequence.c and seq_stat.c + */ +#define SEQ_IS_OPEN(seq) ((seq)->seq_key.data != NULL) + +#define SEQ_ILLEGAL_AFTER_OPEN(seq, name) \ + if (SEQ_IS_OPEN(seq)) \ + return (__db_mi_open((seq)->seq_dbp->env, name, 1)); + +#define SEQ_ILLEGAL_BEFORE_OPEN(seq, name) \ + if (!SEQ_IS_OPEN(seq)) \ + return (__db_mi_open((seq)->seq_dbp->env, name, 0)); + +/* + * Flags to __db_chk_meta. + */ +#define DB_CHK_META 0x01 /* Checksum the meta page. */ +#define DB_CHK_NOLSN 0x02 /* Don't check the LSN. */ +#define DB_CHK_ONLY 0x04 /* Only do the checksum. */ +#define DB_SKIP_CHK 0x08 /* Don't checksum or decrypt the meta page. */ + +/* + * Flags to __db_truncate_page. + */ +#define DB_EXCH_FREE 0x01 /* Free the old page. */ +#define DB_EXCH_PARENT 0x02 /* There is a parent to update. */ + +/* We usually want to do these operations. */ +#define DB_EXCH_DEFAULT (DB_EXCH_FREE | DB_EXCH_PARENT) + +#if defined(__cplusplus) +} +#endif + +#include "dbinc/db_dispatch.h" +#include "dbinc_auto/db_auto.h" +#include "dbinc_auto/crdel_auto.h" +#include "dbinc_auto/db_ext.h" +#endif /* !_DB_AM_H_ */ diff -r 000000000000 -r a1985f14b030 src/dbinc/db_cxx.in --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/dbinc/db_cxx.in Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,1545 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 1997, 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + * $Id$ + */ + +#ifndef _DB_CXX_H_ +#define _DB_CXX_H_ +// +// C++ assumptions: +// +// To ensure portability to many platforms, both new and old, we make +// few assumptions about the C++ compiler and library. For example, +// we do not expect STL, templates or namespaces to be available. The +// "newest" C++ feature used is exceptions, which are used liberally +// to transmit error information. Even the use of exceptions can be +// disabled at runtime, to do so, use the DB_CXX_NO_EXCEPTIONS flags +// with the DbEnv or Db constructor. +// +// C++ naming conventions: +// +// - All top level class names start with Db. +// - All class members start with lower case letter. +// - All private data members are suffixed with underscore. +// - Use underscores to divide names into multiple words. +// - Simple data accessors are named with get_ or set_ prefix. +// - All method names are taken from names of functions in the C +// layer of db (usually by dropping a prefix like "db_"). +// These methods have the same argument types and order, +// other than dropping the explicit arg that acts as "this". +// +// As a rule, each DbFoo object has exactly one underlying DB_FOO struct +// (defined in db.h) associated with it. In some cases, we inherit directly +// from the DB_FOO structure to make this relationship explicit. Often, +// the underlying C layer allocates and deallocates these structures, so +// there is no easy way to add any data to the DbFoo class. When you see +// a comment about whether data is permitted to be added, this is what +// is going on. Of course, if we need to add data to such C++ classes +// in the future, we will arrange to have an indirect pointer to the +// DB_FOO struct (as some of the classes already have). +// + +//////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////// +// +// Forward declarations +// + +#include + +@cxx_have_stdheaders@ +#ifdef HAVE_CXX_STDHEADERS +#include +#include +#define __DB_STD(x) std::x +#else +#include +#include +#define __DB_STD(x) x +#endif + +#include "db.h" + +class Db; // forward +class Dbc; // forward +class DbChannel; // forward +class DbEnv; // forward +class DbHeapRecordId; // forward +class DbInfo; // forward +class DbLock; // forward +class DbLogc; // forward +class DbLsn; // forward +class DbMpoolFile; // forward +class DbPreplist; // forward +class DbSequence; // forward +class DbSite; // forward +class Dbt; // forward +class DbTxn; // forward + +class DbMultipleIterator; // forward +class DbMultipleKeyDataIterator; // forward +class DbMultipleRecnoDataIterator; // forward +class DbMultipleDataIterator; // forward + +class DbException; // forward +class DbDeadlockException; // forward +class DbLockNotGrantedException; // forward +class DbMemoryException; // forward +class DbRepHandleDeadException; // forward +class DbRunRecoveryException; // forward + +//////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////// +// +// Turn off inappropriate compiler warnings +// + +#ifdef _MSC_VER + +// These are level 4 warnings that are explicitly disabled. +// With Visual C++, by default you do not see above level 3 unless +// you use /W4. But we like to compile with the highest level +// warnings to catch other errors. +// +// 4201: nameless struct/union +// triggered by standard include file +// +// 4514: unreferenced inline function has been removed +// certain include files in MSVC define methods that are not called +// +#pragma warning(push) +#pragma warning(disable: 4201 4514) + +#endif + +//////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////// +// +// Mechanisms for declaring classes +// + +// +// Every class defined in this file has an _exported next to the class name. +// This is needed for WinTel machines so that the class methods can +// be exported or imported in a DLL as appropriate. Users of the DLL +// use the define DB_USE_DLL. When the DLL is built, DB_CREATE_DLL +// must be defined. +// +#if defined(_MSC_VER) + +# if defined(DB_CREATE_DLL) +# define _exported __declspec(dllexport) // creator of dll +# elif defined(DB_USE_DLL) +# define _exported __declspec(dllimport) // user of dll +# else +# define _exported // static lib creator or user +# endif + +#else /* _MSC_VER */ + +# define _exported + +#endif /* _MSC_VER */ + +// Some interfaces can be customized by allowing users to define +// callback functions. For performance and logistical reasons, some +// callback functions must be declared in extern "C" blocks. For others, +// we allow you to declare the callbacks in C++ or C (or an extern "C" +// block) as you wish. See the set methods for the callbacks for +// the choices. +// +extern "C" { + typedef void * (*db_malloc_fcn_type) + (size_t); + typedef void * (*db_realloc_fcn_type) + (void *, size_t); + typedef void (*db_free_fcn_type) + (void *); + typedef int (*bt_compare_fcn_type) /*C++ version available*/ + (DB *, const DBT *, const DBT *); + typedef size_t (*bt_prefix_fcn_type) /*C++ version available*/ + (DB *, const DBT *, const DBT *); + typedef int (*dup_compare_fcn_type) /*C++ version available*/ + (DB *, const DBT *, const DBT *); + typedef int (*h_compare_fcn_type) /*C++ version available*/ + (DB *, const DBT *, const DBT *); + typedef u_int32_t (*h_hash_fcn_type) /*C++ version available*/ + (DB *, const void *, u_int32_t); + typedef int (*pgin_fcn_type) + (DB_ENV *dbenv, db_pgno_t pgno, void *pgaddr, DBT *pgcookie); + typedef int (*pgout_fcn_type) + (DB_ENV *dbenv, db_pgno_t pgno, void *pgaddr, DBT *pgcookie); +} + +// +// Represents a database table = a set of keys with associated values. +// +class _exported Db +{ + friend class DbEnv; + +public: + Db(DbEnv*, u_int32_t); // Create a Db object. + virtual ~Db(); // Calls close() if the user hasn't. + + // These methods exactly match those in the C interface. + // + virtual int associate(DbTxn *txn, Db *secondary, int (*callback) + (Db *, const Dbt *, const Dbt *, Dbt *), u_int32_t flags); + virtual int associate_foreign(Db *foreign, int (*callback) + (Db *, const Dbt *, Dbt *, const Dbt *, int *), u_int32_t flags); + virtual int close(u_int32_t flags); + virtual int compact(DbTxn *txnid, Dbt *start, + Dbt *stop, DB_COMPACT *c_data, u_int32_t flags, Dbt *end); + virtual int cursor(DbTxn *txnid, Dbc **cursorp, u_int32_t flags); + virtual int del(DbTxn *txnid, Dbt *key, u_int32_t flags); + virtual void err(int, const char *, ...); + virtual void errx(const char *, ...); + virtual int exists(DbTxn *txnid, Dbt *key, u_int32_t flags); + virtual int fd(int *fdp); + virtual int get(DbTxn *txnid, Dbt *key, Dbt *data, u_int32_t flags); + virtual int get_alloc( + db_malloc_fcn_type *, db_realloc_fcn_type *, db_free_fcn_type *); + virtual int get_append_recno(int (**)(Db *, Dbt *, db_recno_t)); + virtual int get_bt_compare(int (**)(Db *, const Dbt *, const Dbt *)); + virtual int get_bt_compress( + int (**)( + Db *, const Dbt *, const Dbt *, const Dbt *, const Dbt *, Dbt *), + int (**)(Db *, const Dbt *, const Dbt *, Dbt *, Dbt *, Dbt *)); + virtual int get_bt_minkey(u_int32_t *); + virtual int get_bt_prefix(size_t (**)(Db *, const Dbt *, const Dbt *)); + virtual int get_byteswapped(int *); + virtual int get_cachesize(u_int32_t *, u_int32_t *, int *); + virtual int get_create_dir(const char **); + virtual int get_dbname(const char **, const char **); + virtual int get_dup_compare(int (**)(Db *, const Dbt *, const Dbt *)); + virtual int get_encrypt_flags(u_int32_t *); + virtual void get_errcall( + void (**)(const DbEnv *, const char *, const char *)); + virtual void get_errfile(FILE **); + virtual void get_errpfx(const char **); + virtual int get_feedback(void (**)(Db *, int, int)); + virtual int get_flags(u_int32_t *); + virtual int get_heapsize(u_int32_t *, u_int32_t *); + virtual int get_heap_regionsize(u_int32_t *); + virtual int get_h_compare(int (**)(Db *, const Dbt *, const Dbt *)); + virtual int get_h_ffactor(u_int32_t *); + virtual int get_h_hash(u_int32_t (**)(Db *, const void *, u_int32_t)); + virtual int get_h_nelem(u_int32_t *); + virtual int get_lk_exclusive(bool *, bool *); + virtual int get_lorder(int *); + virtual void get_msgcall(void (**)(const DbEnv *, const char *)); + virtual void get_msgfile(FILE **); + virtual int get_multiple(); + virtual int get_open_flags(u_int32_t *); + virtual int get_pagesize(u_int32_t *); + virtual int get_partition_callback( + u_int32_t *, u_int32_t (**)(Db *, Dbt *key)); + virtual int get_partition_dirs(const char ***); + virtual int get_partition_keys(u_int32_t *, Dbt **); + virtual int get_priority(DB_CACHE_PRIORITY *); + virtual int get_q_extentsize(u_int32_t *); + virtual int get_re_delim(int *); + virtual int get_re_len(u_int32_t *); + virtual int get_re_pad(int *); + virtual int get_re_source(const char **); + virtual int get_transactional(); + virtual int get_type(DBTYPE *); + virtual int join(Dbc **curslist, Dbc **dbcp, u_int32_t flags); + virtual int key_range(DbTxn *, Dbt *, DB_KEY_RANGE *, u_int32_t); + virtual int open(DbTxn *txnid, + const char *, const char *subname, DBTYPE, u_int32_t, int); + virtual int pget(DbTxn *txnid, + Dbt *key, Dbt *pkey, Dbt *data, u_int32_t flags); + virtual int put(DbTxn *, Dbt *, Dbt *, u_int32_t); + virtual int remove(const char *, const char *, u_int32_t); + virtual int rename(const char *, const char *, const char *, u_int32_t); + virtual int set_alloc( + db_malloc_fcn_type, db_realloc_fcn_type, db_free_fcn_type); + virtual void set_app_private(void *); + virtual int set_append_recno(int (*)(Db *, Dbt *, db_recno_t)); + virtual int set_bt_compare(bt_compare_fcn_type); /*deprecated*/ + virtual int set_bt_compare(int (*)(Db *, const Dbt *, const Dbt *)); + virtual int set_bt_compress( + int (*) + (Db *, const Dbt *, const Dbt *, const Dbt *, const Dbt *, Dbt *), + int (*)(Db *, const Dbt *, const Dbt *, Dbt *, Dbt *, Dbt *)); + virtual int set_bt_minkey(u_int32_t); + virtual int set_bt_prefix(bt_prefix_fcn_type); /*deprecated*/ + virtual int set_bt_prefix(size_t (*)(Db *, const Dbt *, const Dbt *)); + virtual int set_cachesize(u_int32_t, u_int32_t, int); + virtual int set_create_dir(const char *); + virtual int set_dup_compare(dup_compare_fcn_type); /*deprecated*/ + virtual int set_dup_compare(int (*)(Db *, const Dbt *, const Dbt *)); + virtual int set_encrypt(const char *, u_int32_t); + virtual void set_errcall( + void (*)(const DbEnv *, const char *, const char *)); + virtual void set_errfile(FILE *); + virtual void set_errpfx(const char *); + virtual int set_feedback(void (*)(Db *, int, int)); + virtual int set_flags(u_int32_t); + virtual int set_heapsize(u_int32_t, u_int32_t); + virtual int set_heap_regionsize(u_int32_t); + virtual int set_h_compare(h_compare_fcn_type); /*deprecated*/ + virtual int set_h_compare(int (*)(Db *, const Dbt *, const Dbt *)); + virtual int set_h_ffactor(u_int32_t); + virtual int set_h_hash(h_hash_fcn_type); /*deprecated*/ + virtual int set_h_hash(u_int32_t (*)(Db *, const void *, u_int32_t)); + virtual int set_h_nelem(u_int32_t); + virtual int set_lk_exclusive(bool); + virtual int set_lorder(int); + virtual void set_msgcall(void (*)(const DbEnv *, const char *)); + virtual void set_msgfile(FILE *); + virtual int set_pagesize(u_int32_t); + virtual int set_paniccall(void (*)(DbEnv *, int)); + virtual int set_partition( + u_int32_t, Dbt *, u_int32_t (*)(Db *, Dbt *)); + virtual int set_partition_dirs(const char **); + virtual int set_priority(DB_CACHE_PRIORITY); + virtual int set_q_extentsize(u_int32_t); + virtual int set_re_delim(int); + virtual int set_re_len(u_int32_t); + virtual int set_re_pad(int); + virtual int set_re_source(const char *); + virtual int sort_multiple(Dbt *, Dbt *, u_int32_t); + virtual int stat(DbTxn *, void *sp, u_int32_t flags); + virtual int stat_print(u_int32_t flags); + virtual int sync(u_int32_t flags); + virtual int truncate(DbTxn *, u_int32_t *, u_int32_t); + virtual int upgrade(const char *name, u_int32_t flags); + virtual int verify( + const char *, const char *, __DB_STD(ostream) *, u_int32_t); + + // These additional methods are not in the C interface, and + // are only available for C++. + // + virtual void *get_app_private() const; + virtual __DB_STD(ostream) *get_error_stream(); + virtual void set_error_stream(__DB_STD(ostream) *); + virtual __DB_STD(ostream) *get_message_stream(); + virtual void set_message_stream(__DB_STD(ostream) *); + + virtual DbEnv *get_env(); + virtual DbMpoolFile *get_mpf(); + + virtual ENV *get_ENV() + { + return imp_->env; + } + + virtual DB *get_DB() + { + return imp_; + } + + virtual const DB *get_const_DB() const + { + return imp_; + } + + static Db* get_Db(DB *db) + { + return (Db *)db->api_internal; + } + + static const Db* get_const_Db(const DB *db) + { + return (const Db *)db->api_internal; + } + + u_int32_t get_create_flags() const + { + return construct_flags_; + } + +private: + // no copying + Db(const Db &); + Db &operator = (const Db &); + + void cleanup(); + int initialize(); + int error_policy(); + + // instance data + DB *imp_; + DbEnv *dbenv_; + DbMpoolFile *mpf_; + int construct_error_; + u_int32_t flags_; + u_int32_t construct_flags_; + + static int alt_close(DB *, u_int32_t); + +public: + // These are public only because they need to be called + // via C callback functions. They should never be used by + // external users of this class. + // + int (*append_recno_callback_)(Db *, Dbt *, db_recno_t); + int (*associate_callback_)(Db *, const Dbt *, const Dbt *, Dbt *); + int (*associate_foreign_callback_) + (Db *, const Dbt *, Dbt *, const Dbt *, int *); + int (*bt_compare_callback_)(Db *, const Dbt *, const Dbt *); + int (*bt_compress_callback_)( + Db *, const Dbt *, const Dbt *, const Dbt *, const Dbt *, Dbt *); + int (*bt_decompress_callback_)( + Db *, const Dbt *, const Dbt *, Dbt *, Dbt *, Dbt *); + size_t (*bt_prefix_callback_)(Db *, const Dbt *, const Dbt *); + u_int32_t (*db_partition_callback_)(Db *, Dbt *); + int (*dup_compare_callback_)(Db *, const Dbt *, const Dbt *); + void (*feedback_callback_)(Db *, int, int); + int (*h_compare_callback_)(Db *, const Dbt *, const Dbt *); + u_int32_t (*h_hash_callback_)(Db *, const void *, u_int32_t); +}; + +// +// Cursor +// +class _exported Dbc : protected DBC +{ + friend class Db; + +public: + int close(); + int cmp(Dbc *other_csr, int *result, u_int32_t flags); + int count(db_recno_t *countp, u_int32_t flags); + int del(u_int32_t flags); + int dup(Dbc** cursorp, u_int32_t flags); + int get(Dbt* key, Dbt *data, u_int32_t flags); + int get_priority(DB_CACHE_PRIORITY *priorityp); + int pget(Dbt* key, Dbt* pkey, Dbt *data, u_int32_t flags); + int put(Dbt* key, Dbt *data, u_int32_t flags); + int set_priority(DB_CACHE_PRIORITY priority); + +private: + // No data is permitted in this class (see comment at top) + + // Note: use Db::cursor() to get pointers to a Dbc, + // and call Dbc::close() rather than delete to release them. + // + Dbc(); + ~Dbc(); + + // no copying + Dbc(const Dbc &); + Dbc &operator = (const Dbc &); +}; + +// +// A channel in replication group +// +class _exported DbChannel +{ + friend class DbEnv; + +public: + int close(); + int send_msg(Dbt *msg, u_int32_t nmsg, u_int32_t flags); + int send_request(Dbt *request, u_int32_t nrequest, Dbt *response, + db_timeout_t timeout, u_int32_t flags); + int set_timeout(db_timeout_t timeout); + + virtual DB_CHANNEL *get_DB_CHANNEL() + { + return imp_; + } + + virtual const DB_CHANNEL *get_const_DB_CHANNEL() const + { + return imp_; + } + +private: + DbChannel(); + virtual ~DbChannel(); + + // no copying + DbChannel(const DbChannel &); + DbChannel &operator = (const DbChannel &); + DB_CHANNEL *imp_; + DbEnv *dbenv_; +}; + +// +// Berkeley DB environment class. Provides functions for opening databases. +// User of this library can use this class as a starting point for +// developing a DB application - derive their application class from +// this one, add application control logic. +// +// Note that if you use the default constructor, you must explicitly +// call appinit() before any other db activity (e.g. opening files) +// +class _exported DbEnv +{ + friend class Db; + friend class DbLock; + friend class DbMpoolFile; + +public: + // After using this constructor, you can set any needed + // parameters for the environment using the set_* methods. + // Then call open() to finish initializing the environment + // and attaching it to underlying files. + // + DbEnv(u_int32_t flags); + + virtual ~DbEnv(); + + // These methods match those in the C interface. + // + virtual int add_data_dir(const char *); + virtual int backup(const char *target, u_int32_t flags); + virtual int cdsgroup_begin(DbTxn **tid); + virtual int close(u_int32_t); + virtual int dbbackup( + const char *dbfile, const char *target, u_int32_t flags); + virtual int dbremove(DbTxn *txn, const char *name, const char *subdb, + u_int32_t flags); + virtual int dbrename(DbTxn *txn, const char *name, const char *subdb, + const char *newname, u_int32_t flags); + virtual void err(int, const char *, ...); + virtual void errx(const char *, ...); + virtual int failchk(u_int32_t); + virtual int fileid_reset(const char *, u_int32_t); + virtual int get_alloc(db_malloc_fcn_type *, db_realloc_fcn_type *, + db_free_fcn_type *); + virtual void *get_app_private() const; + virtual int get_home(const char **); + virtual int get_open_flags(u_int32_t *); + virtual int open(const char *, u_int32_t, int); + virtual int remove(const char *, u_int32_t); + virtual int stat_print(u_int32_t flags); + + virtual int set_alloc(db_malloc_fcn_type, db_realloc_fcn_type, + db_free_fcn_type); + virtual void set_app_private(void *); + virtual int get_backup_callbacks( + int (**)(DbEnv *, const char *, const char *, void **), + int (**)(DbEnv *, u_int32_t, u_int32_t, u_int32_t, u_int8_t *, void *), + int (**)(DbEnv *, const char *, void *)); + virtual int set_backup_callbacks( + int (*)(DbEnv *, const char *, const char *, void **), + int (*)(DbEnv *, u_int32_t, u_int32_t, u_int32_t, u_int8_t *, void *), + int (*)(DbEnv *, const char *, void *)); + virtual int get_backup_config(DB_BACKUP_CONFIG, u_int32_t *); + virtual int set_backup_config(DB_BACKUP_CONFIG, u_int32_t); + virtual int get_cachesize(u_int32_t *, u_int32_t *, int *); + virtual int set_cachesize(u_int32_t, u_int32_t, int); + virtual int get_cache_max(u_int32_t *, u_int32_t *); + virtual int set_cache_max(u_int32_t, u_int32_t); + virtual int get_create_dir(const char **); + virtual int set_create_dir(const char *); + virtual int get_data_dirs(const char ***); + virtual int set_data_dir(const char *); + virtual int get_encrypt_flags(u_int32_t *); + virtual int get_intermediate_dir_mode(const char **); + virtual int set_intermediate_dir_mode(const char *); + virtual int get_isalive( + int (**)(DbEnv *, pid_t, db_threadid_t, u_int32_t)); + virtual int set_isalive( + int (*)(DbEnv *, pid_t, db_threadid_t, u_int32_t)); + virtual int set_encrypt(const char *, u_int32_t); + virtual void get_errcall( + void (**)(const DbEnv *, const char *, const char *)); + virtual void set_errcall( + void (*)(const DbEnv *, const char *, const char *)); + virtual void get_errfile(FILE **); + virtual void set_errfile(FILE *); + virtual void get_errpfx(const char **); + virtual void set_errpfx(const char *); + virtual int set_event_notify(void (*)(DbEnv *, u_int32_t, void *)); + virtual int get_flags(u_int32_t *); + virtual int set_flags(u_int32_t, int); + virtual bool is_bigendian(); + virtual int lsn_reset(const char *, u_int32_t); + virtual int get_feedback(void (**)(DbEnv *, int, int)); + virtual int set_feedback(void (*)(DbEnv *, int, int)); + virtual int get_lg_bsize(u_int32_t *); + virtual int set_lg_bsize(u_int32_t); + virtual int get_lg_dir(const char **); + virtual int set_lg_dir(const char *); + virtual int get_lg_filemode(int *); + virtual int set_lg_filemode(int); + virtual int get_lg_max(u_int32_t *); + virtual int set_lg_max(u_int32_t); + virtual int get_lg_regionmax(u_int32_t *); + virtual int set_lg_regionmax(u_int32_t); + virtual int get_lk_conflicts(const u_int8_t **, int *); + virtual int set_lk_conflicts(u_int8_t *, int); + virtual int get_lk_detect(u_int32_t *); + virtual int set_lk_detect(u_int32_t); + virtual int get_lk_max_lockers(u_int32_t *); + virtual int set_lk_max_lockers(u_int32_t); + virtual int get_lk_max_locks(u_int32_t *); + virtual int set_lk_max_locks(u_int32_t); + virtual int get_lk_max_objects(u_int32_t *); + virtual int set_lk_max_objects(u_int32_t); + virtual int get_lk_partitions(u_int32_t *); + virtual int set_lk_partitions(u_int32_t); + virtual int get_lk_priority(u_int32_t, u_int32_t *); + virtual int set_lk_priority(u_int32_t, u_int32_t); + virtual int get_lk_tablesize(u_int32_t *); + virtual int set_lk_tablesize(u_int32_t); + virtual int get_memory_init(DB_MEM_CONFIG, u_int32_t *); + virtual int set_memory_init(DB_MEM_CONFIG, u_int32_t); + virtual int get_memory_max(u_int32_t *, u_int32_t *); + virtual int set_memory_max(u_int32_t, u_int32_t); + virtual int get_metadata_dir(const char **); + virtual int set_metadata_dir(const char *); + virtual int get_mp_mmapsize(size_t *); + virtual int set_mp_mmapsize(size_t); + virtual int get_mp_max_openfd(int *); + virtual int set_mp_max_openfd(int); + virtual int get_mp_max_write(int *, db_timeout_t *); + virtual int set_mp_max_write(int, db_timeout_t); + virtual int get_mp_pagesize(u_int32_t *); + virtual int set_mp_pagesize(u_int32_t); + virtual int get_mp_tablesize(u_int32_t *); + virtual int set_mp_tablesize(u_int32_t); + virtual void get_msgcall(void (**)(const DbEnv *, const char *)); + virtual void set_msgcall(void (*)(const DbEnv *, const char *)); + virtual void get_msgfile(FILE **); + virtual void set_msgfile(FILE *); + virtual int set_paniccall(void (*)(DbEnv *, int)); + virtual int get_shm_key(long *); + virtual int set_shm_key(long); + virtual int get_timeout(db_timeout_t *, u_int32_t); + virtual int set_timeout(db_timeout_t, u_int32_t); + virtual int get_tmp_dir(const char **); + virtual int set_tmp_dir(const char *); + virtual int get_tx_max(u_int32_t *); + virtual int set_tx_max(u_int32_t); + virtual int get_app_dispatch( + int (**)(DbEnv *, Dbt *, DbLsn *, db_recops)); + virtual int set_app_dispatch(int (*)(DbEnv *, + Dbt *, DbLsn *, db_recops)); + virtual int get_tx_timestamp(time_t *); + virtual int set_tx_timestamp(time_t *); + virtual int get_verbose(u_int32_t which, int *); + virtual int set_verbose(u_int32_t which, int); + + // Version information. Static methods, can be called at any time. + // + static char *version(int *major, int *minor, int *patch); + static char *full_version(int *family, int *release, + int *major, int *minor, int *patch); + + // Convert DB errors to strings + static char *strerror(int); + + // If an error is detected and the error call function + // or stream is set, a message is dispatched or printed. + // If a prefix is set, each message is prefixed. + // + // You can use set_errcall() or set_errfile() above to control + // error functionality. Alternatively, you can call + // set_error_stream() to force all errors to a C++ stream. + // It is unwise to mix these approaches. + // + virtual __DB_STD(ostream) *get_error_stream(); + virtual void set_error_stream(__DB_STD(ostream) *); + virtual __DB_STD(ostream) *get_message_stream(); + virtual void set_message_stream(__DB_STD(ostream) *); + + // used internally + static void runtime_error(DbEnv *dbenv, const char *caller, int err, + int error_policy); + static void runtime_error_dbt(DbEnv *dbenv, const char *caller, Dbt *dbt, + int error_policy); + static void runtime_error_lock_get(DbEnv *dbenv, const char *caller, + int err, db_lockop_t op, db_lockmode_t mode, + Dbt *obj, DbLock lock, int index, + int error_policy); + + // Lock functions + // + virtual int lock_detect(u_int32_t flags, u_int32_t atype, int *aborted); + virtual int lock_get(u_int32_t locker, u_int32_t flags, Dbt *obj, + db_lockmode_t lock_mode, DbLock *lock); + virtual int lock_id(u_int32_t *idp); + virtual int lock_id_free(u_int32_t id); + virtual int lock_put(DbLock *lock); + virtual int lock_stat(DB_LOCK_STAT **statp, u_int32_t flags); + virtual int lock_stat_print(u_int32_t flags); + virtual int lock_vec(u_int32_t locker, u_int32_t flags, + DB_LOCKREQ list[], int nlist, DB_LOCKREQ **elistp); + + // Log functions + // + virtual int log_archive(char **list[], u_int32_t flags); + static int log_compare(const DbLsn *lsn0, const DbLsn *lsn1); + virtual int log_cursor(DbLogc **cursorp, u_int32_t flags); + virtual int log_file(DbLsn *lsn, char *namep, size_t len); + virtual int log_flush(const DbLsn *lsn); + virtual int log_get_config(u_int32_t, int *); + virtual int log_put(DbLsn *lsn, const Dbt *data, u_int32_t flags); + virtual int log_printf(DbTxn *, const char *, ...); + virtual int log_set_config(u_int32_t, int); + virtual int log_stat(DB_LOG_STAT **spp, u_int32_t flags); + virtual int log_stat_print(u_int32_t flags); + virtual int log_verify(DB_LOG_VERIFY_CONFIG *); + + // Mpool functions + // + virtual int memp_fcreate(DbMpoolFile **dbmfp, u_int32_t flags); + virtual int memp_register(int ftype, + pgin_fcn_type pgin_fcn, + pgout_fcn_type pgout_fcn); + virtual int memp_stat(DB_MPOOL_STAT + **gsp, DB_MPOOL_FSTAT ***fsp, u_int32_t flags); + virtual int memp_stat_print(u_int32_t flags); + virtual int memp_sync(DbLsn *lsn); + virtual int memp_trickle(int pct, int *nwrotep); + + // Mpool functions + // + virtual int mutex_alloc(u_int32_t, db_mutex_t *); + virtual int mutex_free(db_mutex_t); + virtual int mutex_get_align(u_int32_t *); + virtual int mutex_get_increment(u_int32_t *); + virtual int mutex_get_init(u_int32_t *); + virtual int mutex_get_max(u_int32_t *); + virtual int mutex_get_tas_spins(u_int32_t *); + virtual int mutex_lock(db_mutex_t); + virtual int mutex_set_align(u_int32_t); + virtual int mutex_set_increment(u_int32_t); + virtual int mutex_set_init(u_int32_t); + virtual int mutex_set_max(u_int32_t); + virtual int mutex_set_tas_spins(u_int32_t); + virtual int mutex_stat(DB_MUTEX_STAT **, u_int32_t); + virtual int mutex_stat_print(u_int32_t); + virtual int mutex_unlock(db_mutex_t); + + // Transaction functions + // + virtual int txn_begin(DbTxn *pid, DbTxn **tid, u_int32_t flags); + virtual int txn_checkpoint(u_int32_t kbyte, u_int32_t min, + u_int32_t flags); + virtual int txn_recover(DbPreplist *preplist, long count, + long *retp, u_int32_t flags); + virtual int txn_stat(DB_TXN_STAT **statp, u_int32_t flags); + virtual int txn_stat_print(u_int32_t flags); + + // Replication functions + // + virtual int rep_elect(u_int32_t, u_int32_t, u_int32_t); + virtual int rep_flush(); + virtual int rep_process_message(Dbt *, Dbt *, int, DbLsn *); + virtual int rep_start(Dbt *, u_int32_t); + virtual int rep_stat(DB_REP_STAT **statp, u_int32_t flags); + virtual int rep_stat_print(u_int32_t flags); + virtual int rep_get_clockskew(u_int32_t *, u_int32_t *); + virtual int rep_set_clockskew(u_int32_t, u_int32_t); + virtual int rep_get_limit(u_int32_t *, u_int32_t *); + virtual int rep_set_limit(u_int32_t, u_int32_t); + virtual int rep_set_transport(int, int (*)(DbEnv *, + const Dbt *, const Dbt *, const DbLsn *, int, u_int32_t)); + virtual int rep_set_request(u_int32_t, u_int32_t); + virtual int rep_get_request(u_int32_t *, u_int32_t *); + virtual int get_thread_count(u_int32_t *); + virtual int set_thread_count(u_int32_t); + virtual int get_thread_id_fn( + void (**)(DbEnv *, pid_t *, db_threadid_t *)); + virtual int set_thread_id(void (*)(DbEnv *, pid_t *, db_threadid_t *)); + virtual int get_thread_id_string_fn( + char *(**)(DbEnv *, pid_t, db_threadid_t, char *)); + virtual int set_thread_id_string(char *(*)(DbEnv *, + pid_t, db_threadid_t, char *)); + virtual int rep_set_config(u_int32_t, int); + virtual int rep_get_config(u_int32_t, int *); + virtual int rep_sync(u_int32_t flags); + + // Advanced replication functions + // + virtual int rep_get_nsites(u_int32_t *n); + virtual int rep_set_nsites(u_int32_t n); + virtual int rep_get_priority(u_int32_t *priorityp); + virtual int rep_set_priority(u_int32_t priority); + virtual int rep_get_timeout(int which, db_timeout_t *timeout); + virtual int rep_set_timeout(int which, db_timeout_t timeout); + virtual int repmgr_channel(int eid, DbChannel **channel, + u_int32_t flags); + virtual int repmgr_get_ack_policy(int *policy); + virtual int repmgr_set_ack_policy(int policy); + virtual int repmgr_local_site(DbSite **site); + virtual int repmgr_msg_dispatch(void (*) (DbEnv *, + DbChannel *, Dbt *, u_int32_t, u_int32_t), u_int32_t flags); + virtual int repmgr_site(const char *host, u_int port, DbSite **site, + u_int32_t flags); + virtual int repmgr_site_by_eid(int eid, DbSite **site); + virtual int repmgr_site_list(u_int *countp, DB_REPMGR_SITE **listp); + virtual int repmgr_start(int nthreads, u_int32_t flags); + virtual int repmgr_stat(DB_REPMGR_STAT **statp, u_int32_t flags); + virtual int repmgr_stat_print(u_int32_t flags); + + // Conversion functions + // + virtual ENV *get_ENV() + { + return imp_->env; + } + + virtual DB_ENV *get_DB_ENV() + { + return imp_; + } + + virtual const DB_ENV *get_const_DB_ENV() const + { + return imp_; + } + + static DbEnv* get_DbEnv(DB_ENV *dbenv) + { + return dbenv ? (DbEnv *)dbenv->api1_internal : 0; + } + + static const DbEnv* get_const_DbEnv(const DB_ENV *dbenv) + { + return dbenv ? (const DbEnv *)dbenv->api1_internal : 0; + } + + u_int32_t get_create_flags() const + { + return construct_flags_; + } + + // For internal use only. + static DbEnv* wrap_DB_ENV(DB_ENV *dbenv); + + // These are public only because they need to be called + // via C functions. They should never be called by users + // of this class. + // + static int _app_dispatch_intercept(DB_ENV *dbenv, DBT *dbt, DB_LSN *lsn, + db_recops op); + static int _backup_close_intercept(DB_ENV *dbenv, + const char *dbname, void *handle); + static int _backup_open_intercept(DB_ENV *dbenv, + const char *dbname, const char *target, void **handle); + static int _backup_write_intercept(DB_ENV *dbenv, u_int32_t off_gbytes, + u_int32_t off_bytes, u_int32_t size, u_int8_t *buf, void *handle); + static void _paniccall_intercept(DB_ENV *dbenv, int errval); + static void _feedback_intercept(DB_ENV *dbenv, int opcode, int pct); + static void _event_func_intercept(DB_ENV *dbenv, u_int32_t, void *); + static int _isalive_intercept(DB_ENV *dbenv, pid_t pid, + db_threadid_t thrid, u_int32_t flags); + static int _rep_send_intercept(DB_ENV *dbenv, const DBT *cntrl, + const DBT *data, const DB_LSN *lsn, int id, u_int32_t flags); + static void _stream_error_function(const DB_ENV *dbenv, + const char *prefix, const char *message); + static void _stream_message_function(const DB_ENV *dbenv, + const char *message); + static void _thread_id_intercept(DB_ENV *dbenv, pid_t *pidp, + db_threadid_t *thridp); + static char *_thread_id_string_intercept(DB_ENV *dbenv, pid_t pid, + db_threadid_t thrid, char *buf); + static void _message_dispatch_intercept(DB_ENV *dbenv, + DB_CHANNEL *dbchannel, DBT *request, u_int32_t nrequest, + u_int32_t cb_flags); + +private: + void cleanup(); + int initialize(DB_ENV *dbenv); + int error_policy(); + + // For internal use only. + DbEnv(DB_ENV *, u_int32_t flags); + + // no copying + DbEnv(const DbEnv &); + void operator = (const DbEnv &); + + // instance data + DB_ENV *imp_; + int construct_error_; + u_int32_t construct_flags_; + __DB_STD(ostream) *error_stream_; + __DB_STD(ostream) *message_stream_; + + int (*app_dispatch_callback_)(DbEnv *, Dbt *, DbLsn *, db_recops); + int (*backup_close_callback_)(DbEnv *, const char *, void *); + int (*backup_open_callback_)( + DbEnv *, const char *, const char *, void **); + int (*backup_write_callback_)( + DbEnv *, u_int32_t, u_int32_t, u_int32_t, u_int8_t *, void *); + int (*isalive_callback_)(DbEnv *, pid_t, db_threadid_t, u_int32_t); + void (*error_callback_)(const DbEnv *, const char *, const char *); + void (*feedback_callback_)(DbEnv *, int, int); + void (*message_callback_)(const DbEnv *, const char *); + void (*paniccall_callback_)(DbEnv *, int); + void (*event_func_callback_)(DbEnv *, u_int32_t, void *); + int (*rep_send_callback_)(DbEnv *, const Dbt *, const Dbt *, + const DbLsn *, int, u_int32_t); + void (*thread_id_callback_)(DbEnv *, pid_t *, db_threadid_t *); + char *(*thread_id_string_callback_)(DbEnv *, pid_t, db_threadid_t, + char *); + void (*message_dispatch_callback_)(DbEnv *, DbChannel *, Dbt *, + u_int32_t, u_int32_t); +}; + +// +// Heap record id +// +class _exported DbHeapRecordId : private DB_HEAP_RID +{ +public: + db_pgno_t get_pgno() const { return pgno; } + void set_pgno(db_pgno_t value) { pgno = value; } + + db_indx_t get_indx() const { return indx; } + void set_indx(db_indx_t value) { indx = value; } + + DB_HEAP_RID *get_DB_HEAP_RID() { return (DB_HEAP_RID *)this; } + const DB_HEAP_RID *get_const_DB_HEAP_RID() const + { return (const DB_HEAP_RID *)this; } + + static DbHeapRecordId* get_DbHeapRecordId(DB_HEAP_RID *rid) + { return (DbHeapRecordId *)rid; } + static const DbHeapRecordId* get_const_DbHeapRecordId(DB_HEAP_RID *rid) + { return (const DbHeapRecordId *)rid; } + + DbHeapRecordId(db_pgno_t pgno, db_indx_t indx); + DbHeapRecordId(); + ~DbHeapRecordId(); + DbHeapRecordId(const DbHeapRecordId &); + DbHeapRecordId &operator = (const DbHeapRecordId &); +}; + +// +// Lock +// +class _exported DbLock +{ + friend class DbEnv; + +public: + DbLock(); + DbLock(const DbLock &); + DbLock &operator = (const DbLock &); + +protected: + // We can add data to this class if needed + // since its contained class is not allocated by db. + // (see comment at top) + + DbLock(DB_LOCK); + DB_LOCK lock_; +}; + +// +// Log cursor +// +class _exported DbLogc : protected DB_LOGC +{ + friend class DbEnv; + +public: + int close(u_int32_t _flags); + int get(DbLsn *lsn, Dbt *data, u_int32_t _flags); + int version(u_int32_t *versionp, u_int32_t _flags); + +private: + // No data is permitted in this class (see comment at top) + + // Note: use Db::cursor() to get pointers to a Dbc, + // and call Dbc::close() rather than delete to release them. + // + DbLogc(); + ~DbLogc(); + + // no copying + DbLogc(const Dbc &); + DbLogc &operator = (const Dbc &); +}; + +// +// Log sequence number +// +class _exported DbLsn : public DB_LSN +{ + friend class DbEnv; // friendship needed to cast to base class + friend class DbLogc; // friendship needed to cast to base class +}; + +// +// Memory pool file +// +class _exported DbMpoolFile +{ + friend class DbEnv; + friend class Db; + +public: + int close(u_int32_t flags); + int get(db_pgno_t *pgnoaddr, DbTxn *txn, u_int32_t flags, void *pagep); + int get_clear_len(u_int32_t *len); + int get_fileid(u_int8_t *fileid); + int get_flags(u_int32_t *flagsp); + int get_ftype(int *ftype); + int get_last_pgno(db_pgno_t *pgnop); + int get_lsn_offset(int32_t *offsetp); + int get_maxsize(u_int32_t *gbytes, u_int32_t *bytes); + int get_pgcookie(DBT *dbt); + int get_priority(DB_CACHE_PRIORITY *priorityp); + int get_transactional(void); + int open(const char *file, u_int32_t flags, int mode, size_t pagesize); + int put(void *pgaddr, DB_CACHE_PRIORITY priority, u_int32_t flags); + int set_clear_len(u_int32_t len); + int set_fileid(u_int8_t *fileid); + int set_flags(u_int32_t flags, int onoff); + int set_ftype(int ftype); + int set_lsn_offset(int32_t offset); + int set_maxsize(u_int32_t gbytes, u_int32_t bytes); + int set_pgcookie(DBT *dbt); + int set_priority(DB_CACHE_PRIORITY priority); + int sync(); + + virtual DB_MPOOLFILE *get_DB_MPOOLFILE() + { + return imp_; + } + + virtual const DB_MPOOLFILE *get_const_DB_MPOOLFILE() const + { + return imp_; + } + +private: + DB_MPOOLFILE *imp_; + + // We can add data to this class if needed + // since it is implemented via a pointer. + // (see comment at top) + + // Note: use DbEnv::memp_fcreate() to get pointers to a DbMpoolFile, + // and call DbMpoolFile::close() rather than delete to release them. + // + DbMpoolFile(); + + // Shut g++ up. +protected: + virtual ~DbMpoolFile(); + +private: + // no copying + DbMpoolFile(const DbMpoolFile &); + void operator = (const DbMpoolFile &); +}; + +// +// This is filled in and returned by the DbEnv::txn_recover() method. +// +class _exported DbPreplist +{ +public: + DbTxn *txn; + u_int8_t gid[DB_GID_SIZE]; +}; + +// +// A sequence record in a database +// +class _exported DbSequence +{ +public: + DbSequence(Db *db, u_int32_t flags); + virtual ~DbSequence(); + + int open(DbTxn *txnid, Dbt *key, u_int32_t flags); + int initial_value(db_seq_t value); + int close(u_int32_t flags); + int remove(DbTxn *txnid, u_int32_t flags); + int stat(DB_SEQUENCE_STAT **sp, u_int32_t flags); + int stat_print(u_int32_t flags); + + int get(DbTxn *txnid, int32_t delta, db_seq_t *retp, u_int32_t flags); + int get_cachesize(int32_t *sizep); + int set_cachesize(int32_t size); + int get_flags(u_int32_t *flagsp); + int set_flags(u_int32_t flags); + int get_range(db_seq_t *minp, db_seq_t *maxp); + int set_range(db_seq_t min, db_seq_t max); + + Db *get_db(); + Dbt *get_key(); + + virtual DB_SEQUENCE *get_DB_SEQUENCE() + { + return imp_; + } + + virtual const DB_SEQUENCE *get_const_DB_SEQUENCE() const + { + return imp_; + } + + static DbSequence* get_DbSequence(DB_SEQUENCE *seq) + { + return (DbSequence *)seq->api_internal; + } + + static const DbSequence* get_const_DbSequence(const DB_SEQUENCE *seq) + { + return (const DbSequence *)seq->api_internal; + } + + // For internal use only. + static DbSequence* wrap_DB_SEQUENCE(DB_SEQUENCE *seq); + +private: + DbSequence(DB_SEQUENCE *seq); + // no copying + DbSequence(const DbSequence &); + DbSequence &operator = (const DbSequence &); + + DB_SEQUENCE *imp_; + DBT key_; +}; + +// +// A site in replication group +// +class _exported DbSite +{ + friend class DbEnv; + +public: + int close(); + int get_address(const char **hostp, u_int *port); + int get_config(u_int32_t which, u_int32_t *value); + int get_eid(int *eidp); + int remove(); + int set_config(u_int32_t which, u_int32_t value); + + virtual DB_SITE *get_DB_SITE() + { + return imp_; + } + + virtual const DB_SITE *get_const_DB_SITE() const + { + return imp_; + } + +private: + DbSite(); + virtual ~DbSite(); + + // no copying + DbSite(const DbSite &); + DbSite &operator = (const DbSite &); + DB_SITE *imp_; +}; + +// +// Transaction +// +class _exported DbTxn +{ + friend class DbEnv; + +public: + int abort(); + int commit(u_int32_t flags); + int discard(u_int32_t flags); + u_int32_t id(); + int get_name(const char **namep); + int get_priority(u_int32_t *priorityp); + int prepare(u_int8_t *gid); + int set_name(const char *name); + int set_priority(u_int32_t priority); + int set_timeout(db_timeout_t timeout, u_int32_t flags); + + virtual DB_TXN *get_DB_TXN() + { + return imp_; + } + + virtual const DB_TXN *get_const_DB_TXN() const + { + return imp_; + } + + static DbTxn* get_DbTxn(DB_TXN *txn) + { + return (DbTxn *)txn->api_internal; + } + + static const DbTxn* get_const_DbTxn(const DB_TXN *txn) + { + return (const DbTxn *)txn->api_internal; + } + + // For internal use only. + static DbTxn* wrap_DB_TXN(DB_TXN *txn); + void remove_child_txn(DbTxn *kid); + void add_child_txn(DbTxn *kid); + + void set_parent(DbTxn *ptxn) + { + parent_txn_ = ptxn; + } + +private: + DB_TXN *imp_; + + // We use a TAILQ to store this object's kids of DbTxn objects, and + // each kid has a "parent_txn_" to point to this DbTxn object. + // + // If imp_ has a parent transaction which is not wrapped by DbTxn + // class, parent_txn_ will be NULL since we don't need to maintain + // this parent-kid relationship. This relationship only helps to + // delete unresolved kids when the parent is resolved. + DbTxn *parent_txn_; + + // We can add data to this class if needed + // since it is implemented via a pointer. + // (see comment at top) + + // Note: use DbEnv::txn_begin() to get pointers to a DbTxn, + // and call DbTxn::abort() or DbTxn::commit rather than + // delete to release them. + // + DbTxn(DbTxn *ptxn); + // For internal use only. + DbTxn(DB_TXN *txn, DbTxn *ptxn); + virtual ~DbTxn(); + + // no copying + DbTxn(const DbTxn &); + void operator = (const DbTxn &); + + /* + * !!! + * Explicit representations of structures from queue.h. + * TAILQ_HEAD(__children, DbTxn) children; + */ + struct __children { + DbTxn *tqh_first; + DbTxn **tqh_last; + } children; + + /* + * !!! + * Explicit representations of structures from queue.h. + * TAILQ_ENTRY(DbTxn) child_entry; + */ + struct { + DbTxn *tqe_next; + DbTxn **tqe_prev; + } child_entry; +}; + +// +// A chunk of data, maybe a key or value. +// +class _exported Dbt : private DBT +{ + friend class Db; + friend class Dbc; + friend class DbEnv; + friend class DbLogc; + friend class DbSequence; + +public: + // key/data + void *get_data() const { return data; } + void set_data(void *value) { data = value; } + + // key/data length + u_int32_t get_size() const { return size; } + void set_size(u_int32_t value) { size = value; } + + // RO: length of user buffer. + u_int32_t get_ulen() const { return ulen; } + void set_ulen(u_int32_t value) { ulen = value; } + + // RO: get/put record length. + u_int32_t get_dlen() const { return dlen; } + void set_dlen(u_int32_t value) { dlen = value; } + + // RO: get/put record offset. + u_int32_t get_doff() const { return doff; } + void set_doff(u_int32_t value) { doff = value; } + + // flags + u_int32_t get_flags() const { return flags; } + void set_flags(u_int32_t value) { flags = value; } + + // Conversion functions + DBT *get_DBT() { return (DBT *)this; } + const DBT *get_const_DBT() const { return (const DBT *)this; } + + static Dbt* get_Dbt(DBT *dbt) { return (Dbt *)dbt; } + static const Dbt* get_const_Dbt(const DBT *dbt) + { return (const Dbt *)dbt; } + + Dbt(void *data, u_int32_t size); + Dbt(); + ~Dbt(); + Dbt(const Dbt &); + Dbt &operator = (const Dbt &); + +private: + // Note: no extra data appears in this class (other than + // inherited from DBT) since we need DBT and Dbt objects + // to have interchangable pointers. + // + // When subclassing this class, remember that callback + // methods like bt_compare, bt_prefix, dup_compare may + // internally manufacture DBT objects (which later are + // cast to Dbt), so such callbacks might receive objects + // not of your subclassed type. +}; + +//////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////// +// +// multiple key/data/recno iterator classes +// + +// DbMultipleIterator is a shared private base class for the three types +// of bulk-return Iterator; it should never be instantiated directly, +// but it handles the functionality shared by its subclasses. +class _exported DbMultipleIterator +{ +public: + DbMultipleIterator(const Dbt &dbt); +protected: + u_int8_t *data_; + u_int32_t *p_; +}; + +class _exported DbMultipleKeyDataIterator : private DbMultipleIterator +{ +public: + DbMultipleKeyDataIterator(const Dbt &dbt) : DbMultipleIterator(dbt) {} + bool next(Dbt &key, Dbt &data); +}; + +class _exported DbMultipleRecnoDataIterator : private DbMultipleIterator +{ +public: + DbMultipleRecnoDataIterator(const Dbt &dbt) : DbMultipleIterator(dbt) {} + bool next(db_recno_t &recno, Dbt &data); +}; + +class _exported DbMultipleDataIterator : private DbMultipleIterator +{ +public: + DbMultipleDataIterator(const Dbt &dbt) : DbMultipleIterator(dbt) {} + bool next(Dbt &data); +}; + +//////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////// +// +// multiple key/data/recno builder classes +// + +// DbMultipleBuilder is a shared private base class for the three types +// of bulk buffer builders; it should never be instantiated directly, +// but it handles the functionality shared by its subclasses. +class _exported DbMultipleBuilder +{ +public: + DbMultipleBuilder(Dbt &dbt); +protected: + Dbt &dbt_; + void *p_; +}; + +class _exported DbMultipleDataBuilder : DbMultipleBuilder +{ +public: + DbMultipleDataBuilder(Dbt &dbt) : DbMultipleBuilder(dbt) {} + bool append(void *dbuf, size_t dlen); + bool reserve(void *&ddest, size_t dlen); +}; + +class _exported DbMultipleKeyDataBuilder : DbMultipleBuilder +{ +public: + DbMultipleKeyDataBuilder(Dbt &dbt) : DbMultipleBuilder(dbt) {} + bool append(void *kbuf, size_t klen, void *dbuf, size_t dlen); + bool reserve(void *&kdest, size_t klen, void *&ddest, size_t dlen); +}; + +class _exported DbMultipleRecnoDataBuilder +{ +public: + DbMultipleRecnoDataBuilder(Dbt &dbt); + bool append(db_recno_t recno, void *dbuf, size_t dlen); + bool reserve(db_recno_t recno, void *&ddest, size_t dlen); +protected: + Dbt &dbt_; + void *p_; +}; + +//////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////// +// +// Exception classes +// + +// Almost any error in the DB library throws a DbException. +// Every exception should be considered an abnormality +// (e.g. bug, misuse of DB, file system error). +// +class _exported DbException : public __DB_STD(exception) +{ +public: + virtual ~DbException() throw(); + DbException(int err); + DbException(const char *description); + DbException(const char *description, int err); + DbException(const char *prefix, const char *description, int err); + int get_errno() const; + virtual const char *what() const throw(); + DbEnv *get_env() const; + void set_env(DbEnv *dbenv); + + DbException(const DbException &); + DbException &operator = (const DbException &); + +private: + void describe(const char *prefix, const char *description); + + char *what_; + int err_; // errno + DbEnv *dbenv_; +}; + +// +// A specific sort of exception that occurs when +// an operation is aborted to resolve a deadlock. +// +class _exported DbDeadlockException : public DbException +{ +public: + virtual ~DbDeadlockException() throw(); + DbDeadlockException(const char *description); + + DbDeadlockException(const DbDeadlockException &); + DbDeadlockException &operator = (const DbDeadlockException &); +}; + +// +// A specific sort of exception that occurs when +// a lock is not granted, e.g. by lock_get or lock_vec. +// Note that the Dbt is only live as long as the Dbt used +// in the offending call. +// +class _exported DbLockNotGrantedException : public DbException +{ +public: + virtual ~DbLockNotGrantedException() throw(); + DbLockNotGrantedException(const char *prefix, db_lockop_t op, + db_lockmode_t mode, const Dbt *obj, const DbLock lock, int index); + DbLockNotGrantedException(const char *description); + + DbLockNotGrantedException(const DbLockNotGrantedException &); + DbLockNotGrantedException &operator = + (const DbLockNotGrantedException &); + + db_lockop_t get_op() const; + db_lockmode_t get_mode() const; + const Dbt* get_obj() const; + DbLock *get_lock() const; + int get_index() const; + +private: + db_lockop_t op_; + db_lockmode_t mode_; + const Dbt *obj_; + DbLock *lock_; + int index_; +}; + +// +// A specific sort of exception that occurs when +// user declared memory is insufficient in a Dbt. +// +class _exported DbMemoryException : public DbException +{ +public: + virtual ~DbMemoryException() throw(); + DbMemoryException(Dbt *dbt); + DbMemoryException(const char *prefix, Dbt *dbt); + + DbMemoryException(const DbMemoryException &); + DbMemoryException &operator = (const DbMemoryException &); + + Dbt *get_dbt() const; +private: + Dbt *dbt_; +}; + +// +// A specific sort of exception that occurs when a change of replication +// master requires that all handles be re-opened. +// +class _exported DbRepHandleDeadException : public DbException +{ +public: + virtual ~DbRepHandleDeadException() throw(); + DbRepHandleDeadException(const char *description); + + DbRepHandleDeadException(const DbRepHandleDeadException &); + DbRepHandleDeadException &operator = (const DbRepHandleDeadException &); +}; + +// +// A specific sort of exception that occurs when +// recovery is required before continuing DB activity. +// +class _exported DbRunRecoveryException : public DbException +{ +public: + virtual ~DbRunRecoveryException() throw(); + DbRunRecoveryException(const char *description); + + DbRunRecoveryException(const DbRunRecoveryException &); + DbRunRecoveryException &operator = (const DbRunRecoveryException &); +}; + +// +// A specific sort of exception that occurs when + +//////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////// +// +// Restore default compiler warnings +// +#ifdef _MSC_VER +#pragma warning(pop) +#endif + +#endif /* !_DB_CXX_H_ */ diff -r 000000000000 -r a1985f14b030 src/dbinc/db_dispatch.h diff -r 000000000000 -r a1985f14b030 src/dbinc/db_int.in --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/dbinc/db_int.in Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,1184 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 1996, 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + * $Id$ + */ + +#ifndef _DB_INT_H_ +#define _DB_INT_H_ + +/******************************************************* + * Berkeley DB ANSI/POSIX include files. + *******************************************************/ +#ifdef HAVE_SYSTEM_INCLUDE_FILES +#include +#ifdef DIAG_MVCC +#include +#endif +#include + +#if defined(HAVE_REPLICATION_THREADS) +#ifdef HAVE_SYS_SELECT_H +#include +#endif +#ifdef HAVE_VXWORKS +#include +#endif +#endif + +#if TIME_WITH_SYS_TIME +#include +#include +#else +#if HAVE_SYS_TIME_H +#include +#else +#include +#endif +#endif + +#ifdef HAVE_VXWORKS +#include +#else +#include +#endif + +#if defined(HAVE_REPLICATION_THREADS) +#ifdef HAVE_SYS_SOCKET_H +#include +#endif +#include +#include +#include +#endif + +#if defined(STDC_HEADERS) || defined(__cplusplus) +#include +#else +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#endif /* !HAVE_SYSTEM_INCLUDE_FILES */ + +#ifdef DB_WIN32 +#include "dbinc/win_db.h" +#endif + +#ifdef HAVE_DBM +#undef DB_DBM_HSEARCH +#define DB_DBM_HSEARCH 1 +#endif + +#include "db.h" +#include "clib_port.h" + +#include "dbinc/queue.h" +#include "dbinc/shqueue.h" +#include "dbinc/perfmon.h" + +#if defined(__cplusplus) +extern "C" { +#endif + +/* + * The Windows compiler needs to be told about structures that are available + * outside a dll. + */ +#if defined(DB_WIN32) && defined(_MSC_VER) && \ + !defined(DB_CREATE_DLL) && !defined(_LIB) +#define __DB_IMPORT __declspec(dllimport) +#else +#define __DB_IMPORT +#endif + +/******************************************************* + * Forward structure declarations. + *******************************************************/ +struct __db_commit_info; typedef struct __db_commit_info DB_COMMIT_INFO; +struct __db_reginfo_t; typedef struct __db_reginfo_t REGINFO; +struct __db_txnhead; typedef struct __db_txnhead DB_TXNHEAD; +struct __db_txnlist; typedef struct __db_txnlist DB_TXNLIST; +struct __vrfy_childinfo;typedef struct __vrfy_childinfo VRFY_CHILDINFO; +struct __vrfy_dbinfo; typedef struct __vrfy_dbinfo VRFY_DBINFO; +struct __vrfy_pageinfo; typedef struct __vrfy_pageinfo VRFY_PAGEINFO; + +struct __db_log_verify_info; +struct __txn_verify_info; +struct __lv_filereg_info; +struct __lv_ckp_info; +struct __lv_timestamp_info; +typedef struct __db_log_verify_info DB_LOG_VRFY_INFO; +typedef struct __txn_verify_info VRFY_TXN_INFO; +typedef struct __lv_filereg_info VRFY_FILEREG_INFO; +typedef struct __lv_filelife VRFY_FILELIFE; +typedef struct __lv_ckp_info VRFY_CKP_INFO; +typedef struct __lv_timestamp_info VRFY_TIMESTAMP_INFO; + +/* + * TXNINFO_HANDLER -- + * Callback function pointer type for __iterate_txninfo. + */ +typedef int (*TXNINFO_HANDLER) __P((DB_LOG_VRFY_INFO *, VRFY_TXN_INFO *, void *)); + +typedef SH_TAILQ_HEAD(__hash_head) DB_HASHTAB; + +/******************************************************* + * General purpose constants and macros. + *******************************************************/ +#undef FALSE +#define FALSE 0 +#undef TRUE +#define TRUE (!FALSE) + +#define MEGABYTE 1048576 +#define GIGABYTE 1073741824 + +#define NS_PER_MS 1000000 /* Nanoseconds in a millisecond */ +#define NS_PER_US 1000 /* Nanoseconds in a microsecond */ +#define NS_PER_SEC 1000000000 /* Nanoseconds in a second */ +#define US_PER_MS 1000 /* Microseconds in a millisecond */ +#define US_PER_SEC 1000000 /* Microseconds in a second */ +#define MS_PER_SEC 1000 /* Milliseconds in a second */ + +#define RECNO_OOB 0 /* Illegal record number. */ + +/* + * Define a macro which has no runtime effect, yet avoids triggering empty + * statement compiler warnings. Use it as the text of conditionally-null macros. + */ +#define NOP_STATEMENT do { } while (0) + +/* Test for a power-of-two (tests true for zero, which doesn't matter here). */ +#define POWER_OF_TWO(x) (((x) & ((x) - 1)) == 0) + +/* Test for valid page sizes. */ +#define DB_MIN_PGSIZE 0x000200 /* Minimum page size (512). */ +#define DB_MAX_PGSIZE 0x010000 /* Maximum page size (65536). */ +#define IS_VALID_PAGESIZE(x) \ + (POWER_OF_TWO(x) && (x) >= DB_MIN_PGSIZE && ((x) <= DB_MAX_PGSIZE)) + +/* Minimum number of pages cached, by default. */ +#define DB_MINPAGECACHE 16 + +/* + * If we are unable to determine the underlying filesystem block size, use + * 8K on the grounds that most OS's use less than 8K for a VM page size. + */ +#define DB_DEF_IOSIZE (8 * 1024) + +/* Align an integer to a specific boundary. */ +#undef DB_ALIGN +#define DB_ALIGN(v, bound) \ + (((v) + (bound) - 1) & ~(((uintmax_t)(bound)) - 1)) + +/* Increment a pointer to a specific boundary. */ +#undef ALIGNP_INC +#define ALIGNP_INC(p, bound) \ + (void *)(((uintptr_t)(p) + (bound) - 1) & ~(((uintptr_t)(bound)) - 1)) + +/* + * DB_ALIGN8 adjusts structure alignments to make sure shared structures have + * fixed size and filed offset on both 32bit and 64bit platforms when + * HAVE_MIXED_SIZE_ADDRESSING is defined. + */ +#ifdef HAVE_MIXED_SIZE_ADDRESSING +#define DB_ALIGN8 @DB_STRUCT_ALIGN8@ +#else +#define DB_ALIGN8 +#endif + +/* + * Berkeley DB uses the va_copy macro from C99, not all compilers include + * it, so add a dumb implementation compatible with pre C99 implementations. + */ +#ifndef va_copy +#define va_copy(d, s) ((d) = (s)) +#endif + +/* + * Print an address as a u_long (a u_long is the largest type we can print + * portably). Most 64-bit systems have made longs 64-bits, so this should + * work. + */ +#define P_TO_ULONG(p) ((u_long)(uintptr_t)(p)) + +/* + * Convert a pointer to an integral value. + * + * The (u_int16_t)(uintptr_t) cast avoids warnings: the (uintptr_t) cast + * converts the value to an integral type, and the (u_int16_t) cast converts + * it to a small integral type so we don't get complaints when we assign the + * final result to an integral type smaller than uintptr_t. + */ +#define P_TO_UINT32(p) ((u_int32_t)(uintptr_t)(p)) +#define P_TO_UINT16(p) ((u_int16_t)(uintptr_t)(p)) +#define P_TO_ROFF(p) ((roff_t)(uintptr_t)(p)) + +/* The converse of P_TO_ROFF() above. */ +#define ROFF_TO_P(roff) ((void *)(uintptr_t)(roff)) + +/* + * There are several on-page structures that are declared to have a number of + * fields followed by a variable length array of items. The structure size + * without including the variable length array or the address of the first of + * those elements can be found using SSZ. + * + * This macro can also be used to find the offset of a structure element in a + * structure. This is used in various places to copy structure elements from + * unaligned memory references, e.g., pointers into a packed page. + * + * There are two versions because compilers object if you take the address of + * an array. + */ +#undef SSZ +#define SSZ(name, field) P_TO_UINT16(&(((name *)0)->field)) + +#undef SSZA +#define SSZA(name, field) P_TO_UINT16(&(((name *)0)->field[0])) + +/* Structure used to print flag values. */ +typedef struct __fn { + u_int32_t mask; /* Flag value. */ + const char *name; /* Flag name. */ +} FN; + +/* Set, clear and test flags. */ +#define FLD_CLR(fld, f) (fld) &= ~(f) +#define FLD_ISSET(fld, f) ((fld) & (f)) +#define FLD_SET(fld, f) (fld) |= (f) +#define F_CLR(p, f) (p)->flags &= ~(f) +#define F_ISSET(p, f) ((p)->flags & (f)) +#define F_SET(p, f) (p)->flags |= (f) +#define F2_CLR(p, f) ((p)->flags2 &= ~(f)) +#define F2_ISSET(p, f) ((p)->flags2 & (f)) +#define F2_SET(p, f) ((p)->flags2 |= (f)) +#define LF_CLR(f) ((flags) &= ~(f)) +#define LF_ISSET(f) ((flags) & (f)) +#define LF_SET(f) ((flags) |= (f)) + +/* + * Calculate a percentage. The values can overflow 32-bit integer arithmetic + * so we use floating point. + * + * When calculating a bytes-vs-page size percentage, we're getting the inverse + * of the percentage in all cases, that is, we want 100 minus the percentage we + * calculate. + */ +#define DB_PCT(v, total) \ + ((int)((total) == 0 ? 0 : ((double)(v) * 100) / (total))) +#define DB_PCT_PG(v, total, pgsize) \ + ((int)((total) == 0 ? 0 : \ + 100 - ((double)(v) * 100) / (((double)total) * (pgsize)))) + +/* + * Statistics update shared memory and so are expensive -- don't update the + * values unless we're going to display the results. + * When performance monitoring is enabled, the changed value can be published + * (via DTrace or SystemTap) along with another associated value or two. + */ +#undef STAT +#ifdef HAVE_STATISTICS +#define STAT(x) x +#define STAT_ADJUST(env, cat, subcat, val, amount, id) \ + do { \ + (val) += (amount); \ + STAT_PERFMON2((env), cat, subcat, (val), (id)); \ + } while (0) +#define STAT_ADJUST_VERB(env, cat, subcat, val, amount, id1, id2) \ + do { \ + (val) += (amount); \ + STAT_PERFMON3((env), cat, subcat, (val), (id1), (id2)); \ + } while (0) +#define STAT_INC(env, cat, subcat, val, id) \ + STAT_ADJUST(env, cat, subcat, (val), 1, (id)) +#define STAT_INC_VERB(env, cat, subcat, val, id1, id2) \ + STAT_ADJUST_VERB((env), cat, subcat, (val), 1, (id1), (id2)) +/* + * STAT_DEC() subtracts one rather than adding (-1) with STAT_ADJUST(); the + * latter might generate a compilation warning for an unsigned value. + */ +#define STAT_DEC(env, cat, subcat, val, id) \ + do { \ + (val)--; \ + STAT_PERFMON2((env), cat, subcat, (val), (id)); \ + } while (0) +/* N.B.: Add a verbose version of STAT_DEC() when needed. */ + +#define STAT_SET(env, cat, subcat, val, newval, id) \ + do { \ + (val) = (newval); \ + STAT_PERFMON2((env), cat, subcat, (val), (id)); \ + } while (0) +#define STAT_SET_VERB(env, cat, subcat, val, newval, id1, id2) \ + do { \ + (val) = (newval); \ + STAT_PERFMON3((env), cat, subcat, (val), (id1), (id2)); \ + } while (0) +#else +#define STAT(x) NOP_STATEMENT +#define STAT_ADJUST(env, cat, subcat, val, amt, id) NOP_STATEMENT +#define STAT_ADJUST_VERB(env, cat, subcat, val, amt, id1, id2) NOP_STATEMENT +#define STAT_INC(env, cat, subcat, val, id) NOP_STATEMENT +#define STAT_INC_VERB(env, cat, subcat, val, id1, id2) NOP_STATEMENT +#define STAT_DEC(env, cat, subcat, val, id) NOP_STATEMENT +#define STAT_SET(env, cat, subcat, val, newval, id) NOP_STATEMENT +#define STAT_SET_VERB(env, cat, subcat, val, newval, id1, id2) NOP_STATEMENT +#endif + +#if defined HAVE_SIMPLE_THREAD_TYPE +#define DB_THREADID_INIT(t) COMPQUIET((t), 0) +#else +#define DB_THREADID_INIT(t) memset(&(t), 0, sizeof(t)) +#endif + +/* + * These macros are used when an error condition is first noticed. They allow + * one to be notified (via e.g. DTrace, SystemTap, ...) when an error occurs + * deep inside DB, rather than when it is returned back through the API. + * + * The second actual argument to these is the second part of the error or + * warning event name. They work when 'errcode' is a symbolic name e.g. + * EINVAL or DB_LOCK_DEALOCK, not a variable. Noticing system call failures + * would be handled by tracing on syscall exit; when e.g., it returns < 0. + */ +#define ERR_ORIGIN(env, errcode) \ + (PERFMON0(env, error, errcode), errcode) + +#define ERR_ORIGIN_MSG(env, errcode, msg) \ + (PERFMON1(env, error, errcode, msg), errcode) + +#define WARNING_ORIGIN(env, errcode) \ + (PERFMON0(env, warning, errcode), errcode) + +/* + * Structure used for callback message aggregation. + * + * Display values in XXX_stat_print calls. + */ +typedef struct __db_msgbuf { + char *buf; /* Heap allocated buffer. */ + char *cur; /* Current end of message. */ + size_t len; /* Allocated length of buffer. */ +} DB_MSGBUF; +#define DB_MSGBUF_INIT(a) do { \ + (a)->buf = (a)->cur = NULL; \ + (a)->len = 0; \ +} while (0) +#define DB_MSGBUF_FLUSH(env, a) do { \ + if ((a)->buf != NULL) { \ + if ((a)->cur != (a)->buf) \ + __db_msg(env, "%s", (a)->buf); \ + __os_free(env, (a)->buf); \ + DB_MSGBUF_INIT(a); \ + } \ +} while (0) +#define DB_MSGBUF_REP_FLUSH(env, a, diag_msg, regular_msg) do { \ + if ((a)->buf != NULL) { \ + if ((a)->cur != (a)->buf && diag_msg) \ + __db_repmsg(env, "%s", (a)->buf); \ + if (regular_msg) \ + DB_MSGBUF_FLUSH(env, a); \ + else { \ + __os_free(env, (a)->buf); \ + DB_MSGBUF_INIT(a); \ + } \ + } \ +} while (0) +#define STAT_FMT(msg, fmt, type, v) do { \ + DB_MSGBUF __mb; \ + DB_MSGBUF_INIT(&__mb); \ + __db_msgadd(env, &__mb, fmt, (type)(v)); \ + __db_msgadd(env, &__mb, "\t%s", msg); \ + DB_MSGBUF_FLUSH(env, &__mb); \ +} while (0) +#define STAT_HEX(msg, v) \ + __db_msg(env, "%#lx\t%s", (u_long)(v), msg) +#define STAT_ISSET(msg, p) \ + __db_msg(env, "%sSet\t%s", (p) == NULL ? "!" : " ", msg) +#define STAT_LONG(msg, v) \ + __db_msg(env, "%ld\t%s", (long)(v), msg) +#define STAT_LSN(msg, lsnp) \ + __db_msg(env, "%lu/%lu\t%s", \ + (u_long)(lsnp)->file, (u_long)(lsnp)->offset, msg) +#define STAT_POINTER(msg, v) \ + __db_msg(env, "%#lx\t%s", P_TO_ULONG(v), msg) +#define STAT_STRING(msg, p) do { \ + const char *__p = p; /* p may be a function call. */ \ + __db_msg(env, "%s\t%s", __p == NULL ? "!Set" : __p, msg); \ +} while (0) +#define STAT_ULONG(msg, v) \ + __db_msg(env, "%lu\t%s", (u_long)(v), msg) + +/* + * The following macros are used to control how error and message strings are + * output by Berkeley DB. There are essentially three different controls + * available: + * - Default behavior is to output error strings with its unique identifier. + * - If HAVE_STRIPPED_MESSAGES is enabled, a unique identifier along with any + * parameters to the error string will be output. + * - If HAVE_LOCALIZATION is defined, and the '_()' macro is implemented, a + * gettext or ICU style translation will be done. + * + * Each new string that will be output should be wrapped in a DB_STR* macro. + * There are three versions of this macro for different scenarions: + * - DB_STR for strings that need an identifier, and don't have any argument. + * - DB_STR_A for strings that need an identifier, and have argument(s). + * - DB_STR_P for strings that don't need an identifier, and don't have + * arguments. + * + * Error message IDs are automatically assigned by dist/s_message_id script. + */ +#ifdef HAVE_LOCALIZATION +#define _(msg) msg /* Replace with localization function. */ +#else +#define _(msg) msg +#endif + +#ifdef HAVE_STRIPPED_MESSAGES +#define DB_STR_C(msg, fmt) fmt +#else +#define DB_STR_C(msg, fmt) _(msg) +#endif + +#define DB_MSGID(id) "BDB" id + +#define DB_STR(id, msg) DB_MSGID(id) " " DB_STR_C(msg, "") + +#define DB_STR_A(id, msg, fmt) DB_MSGID(id) " " DB_STR_C(msg, fmt) + +#define DB_STR_P(msg) _(msg) + +/* + * There are quite a few places in Berkeley DB where we want to initialize + * a DBT from a string or other random pointer type, using a length typed + * to size_t in most cases. This macro avoids a lot of casting. The macro + * comes in two flavors because we often want to clear the DBT first. + */ +#define DB_SET_DBT(dbt, d, s) do { \ + (dbt).data = (void *)(d); \ + (dbt).size = (u_int32_t)(s); \ +} while (0) +#define DB_INIT_DBT(dbt, d, s) do { \ + memset(&(dbt), 0, sizeof(dbt)); \ + DB_SET_DBT(dbt, d, s); \ +} while (0) + +/******************************************************* + * API return values + *******************************************************/ +/* + * Return values that are OK for each different call. Most calls have a + * standard 'return of 0 is only OK value', but some, like db->get have + * DB_NOTFOUND as a return value, but it really isn't an error. + */ +#define DB_RETOK_STD(ret) ((ret) == 0) +#define DB_RETOK_DBCDEL(ret) ((ret) == 0 || (ret) == DB_KEYEMPTY || \ + (ret) == DB_NOTFOUND) +#define DB_RETOK_DBCGET(ret) ((ret) == 0 || (ret) == DB_KEYEMPTY || \ + (ret) == DB_NOTFOUND) +#define DB_RETOK_DBCPUT(ret) ((ret) == 0 || (ret) == DB_KEYEXIST || \ + (ret) == DB_NOTFOUND) +#define DB_RETOK_DBDEL(ret) DB_RETOK_DBCDEL(ret) +#define DB_RETOK_DBGET(ret) DB_RETOK_DBCGET(ret) +#define DB_RETOK_DBPUT(ret) ((ret) == 0 || (ret) == DB_KEYEXIST) +#define DB_RETOK_EXISTS(ret) DB_RETOK_DBCGET(ret) +#define DB_RETOK_LGGET(ret) ((ret) == 0 || (ret) == DB_NOTFOUND) +#define DB_RETOK_MPGET(ret) ((ret) == 0 || (ret) == DB_PAGE_NOTFOUND) +#define DB_RETOK_REPPMSG(ret) ((ret) == 0 || \ + (ret) == DB_REP_IGNORE || \ + (ret) == DB_REP_ISPERM || \ + (ret) == DB_REP_NEWMASTER || \ + (ret) == DB_REP_NEWSITE || \ + (ret) == DB_REP_NOTPERM || \ + (ret) == DB_REP_WOULDROLLBACK) +#define DB_RETOK_REPMGR_LOCALSITE(ret) ((ret) == 0 || (ret) == DB_NOTFOUND) +#define DB_RETOK_REPMGR_START(ret) ((ret) == 0 || (ret) == DB_REP_IGNORE) +#define DB_RETOK_TXNAPPLIED(ret) ((ret) == 0 || \ + (ret) == DB_NOTFOUND || \ + (ret) == DB_TIMEOUT || \ + (ret) == DB_KEYEMPTY) + +/* Find a reasonable operation-not-supported error. */ +#ifdef EOPNOTSUPP +#define DB_OPNOTSUP EOPNOTSUPP +#else +#ifdef ENOTSUP +#define DB_OPNOTSUP ENOTSUP +#else +#define DB_OPNOTSUP EINVAL +#endif +#endif + +/******************************************************* + * Files. + *******************************************************/ +/* + * We use 1024 as the maximum path length. It's too hard to figure out what + * the real path length is, as it was traditionally stored in , + * and that file isn't always available. + */ +#define DB_MAXPATHLEN 1024 + +#define PATH_DOT "." /* Current working directory. */ + /* Path separator character(s). */ +#define PATH_SEPARATOR "@PATH_SEPARATOR@" + +/******************************************************* + * Environment. + *******************************************************/ +/* Type passed to __db_appname(). */ +typedef enum { + DB_APP_NONE=0, /* No type (region). */ + DB_APP_DATA, /* Data file. */ + DB_APP_LOG, /* Log file. */ + DB_APP_META, /* Persistent metadata file. */ + DB_APP_RECOVER, /* We are in recovery. */ + DB_APP_TMP /* Temporary file. */ +} APPNAME; + +/* + * A set of macros to check if various functionality has been configured. + * + * ALIVE_ON The is_alive function is configured. + * CDB_LOCKING CDB product locking. + * CRYPTO_ON Security has been configured. + * LOCKING_ON Locking has been configured. + * LOGGING_ON Logging has been configured. + * MUTEX_ON Mutexes have been configured. + * MPOOL_ON Memory pool has been configured. + * REP_ON Replication has been configured. + * TXN_ON Transactions have been configured. + * + * REP_ON is more complex than most: if the BDB library was compiled without + * replication support, ENV->rep_handle will be NULL; if the BDB library has + * replication support, but it was not configured, the region reference will + * be NULL. + */ +#define ALIVE_ON(env) ((env)->dbenv->is_alive != NULL) +#define CDB_LOCKING(env) F_ISSET(env, ENV_CDB) +#define CRYPTO_ON(env) ((env)->crypto_handle != NULL) +#define LOCKING_ON(env) ((env)->lk_handle != NULL) +#define LOGGING_ON(env) ((env)->lg_handle != NULL) +#define MPOOL_ON(env) ((env)->mp_handle != NULL) +#define MUTEX_ON(env) ((env)->mutex_handle != NULL) +#define REP_ON(env) \ + ((env)->rep_handle != NULL && (env)->rep_handle->region != NULL) +#define TXN_ON(env) ((env)->tx_handle != NULL) + +/* + * STD_LOCKING Standard locking, that is, locking was configured and CDB + * was not. We do not do locking in off-page duplicate trees, + * so we check for that in the cursor first. + */ +#define STD_LOCKING(dbc) \ + (!F_ISSET(dbc, DBC_OPD) && \ + !CDB_LOCKING((dbc)->env) && LOCKING_ON((dbc)->env)) + +/* + * IS_RECOVERING: The system is running recovery. + */ +#define IS_RECOVERING(env) \ + (LOGGING_ON(env) && F_ISSET((env)->lg_handle, DBLOG_RECOVER)) + +/* Initialization methods are often illegal before/after open is called. */ +#define ENV_ILLEGAL_AFTER_OPEN(env, name) \ + if (F_ISSET((env), ENV_OPEN_CALLED)) \ + return (__db_mi_open(env, name, 1)); +#define ENV_ILLEGAL_BEFORE_OPEN(env, name) \ + if (!F_ISSET((env), ENV_OPEN_CALLED)) \ + return (__db_mi_open(env, name, 0)); + +/* We're not actually user hostile, honest. */ +#define ENV_REQUIRES_CONFIG(env, handle, i, flags) \ + if (handle == NULL) \ + return (__env_not_config(env, i, flags)); +#define ENV_REQUIRES_CONFIG_XX(env, handle, i, flags) \ + if ((env)->handle->region == NULL) \ + return (__env_not_config(env, i, flags)); +#define ENV_NOT_CONFIGURED(env, handle, i, flags) \ + if (F_ISSET((env), ENV_OPEN_CALLED)) \ + ENV_REQUIRES_CONFIG(env, handle, i, flags) + +#define ENV_ENTER_RET(env, ip, ret) do { \ + ret = 0; \ + PANIC_CHECK_RET(env, ret); \ + if (ret == 0) { \ + if ((env)->thr_hashtab == NULL) \ + ip = NULL; \ + else \ + ret = __env_set_state(env, &(ip), THREAD_ACTIVE);\ + } \ +} while (0) + +#define ENV_ENTER(env, ip) do { \ + int __ret; \ + ip = NULL; \ + ENV_ENTER_RET(env, ip, __ret); \ + if (__ret != 0) \ + return (__ret); \ +} while (0) + +#define FAILCHK_THREAD(env, ip) do { \ + if ((ip) != NULL) \ + (ip)->dbth_state = THREAD_FAILCHK; \ +} while (0) + +#define ENV_GET_THREAD_INFO(env, ip) ENV_ENTER(env, ip) + +#ifdef DIAGNOSTIC +#define ENV_LEAVE(env, ip) do { \ + if ((ip) != NULL) { \ + DB_ASSERT(env, ((ip)->dbth_state == THREAD_ACTIVE || \ + (ip)->dbth_state == THREAD_FAILCHK)); \ + (ip)->dbth_state = THREAD_OUT; \ + } \ +} while (0) +#else +#define ENV_LEAVE(env, ip) do { \ + if ((ip) != NULL) \ + (ip)->dbth_state = THREAD_OUT; \ +} while (0) +#endif +#ifdef DIAGNOSTIC +#define CHECK_THREAD(env) do { \ + if ((env)->thr_hashtab != NULL) \ + (void)__env_set_state(env, NULL, THREAD_VERIFY); \ +} while (0) +#ifdef HAVE_STATISTICS +#define CHECK_MTX_THREAD(env, mtx) do { \ + if (mtx->alloc_id != MTX_MUTEX_REGION && \ + mtx->alloc_id != MTX_ENV_REGION && \ + mtx->alloc_id != MTX_APPLICATION) \ + CHECK_THREAD(env); \ +} while (0) +#else +#define CHECK_MTX_THREAD(env, mtx) NOP_STATEMENT +#endif +#else +#define CHECK_THREAD(env) NOP_STATEMENT +#define CHECK_MTX_THREAD(env, mtx) NOP_STATEMENT +#endif + +typedef enum { + THREAD_SLOT_NOT_IN_USE=0, + THREAD_OUT, + THREAD_ACTIVE, + THREAD_BLOCKED, + THREAD_BLOCKED_DEAD, + THREAD_FAILCHK, + THREAD_VERIFY +} DB_THREAD_STATE; + +typedef struct __pin_list { + roff_t b_ref; /* offset to buffer. */ + int region; /* region containing buffer. */ +} PIN_LIST; +#define PINMAX 4 + +struct __db_thread_info { /* SHARED */ + pid_t dbth_pid; + db_threadid_t dbth_tid; + DB_THREAD_STATE dbth_state; + SH_TAILQ_ENTRY dbth_links; + /* + * The next field contains the (process local) reference to the XA + * transaction currently associated with this thread of control. + */ + SH_TAILQ_HEAD(__dbth_xatxn) dbth_xatxn; + u_int32_t dbth_xa_status; + /* + * The following fields track which buffers this thread of + * control has pinned in the mpool buffer cache. + */ + u_int16_t dbth_pincount; /* Number of pins for this thread. */ + u_int16_t dbth_pinmax; /* Number of slots allocated. */ + roff_t dbth_pinlist; /* List of pins. */ + PIN_LIST dbth_pinarray[PINMAX]; /* Initial array of slots. */ +#ifdef DIAGNOSTIC + roff_t dbth_locker; /* Current locker for this thread. */ + u_int32_t dbth_check_off; /* Count of number of LOCK_OFF calls. */ +#endif +}; +#ifdef DIAGNOSTIC +#define LOCK_CHECK_OFF(ip) if ((ip) != NULL) \ + (ip)->dbth_check_off++ + +#define LOCK_CHECK_ON(ip) if ((ip) != NULL) \ + (ip)->dbth_check_off-- + +#define LOCK_CHECK(dbc, pgno, mode, type) \ + DB_ASSERT((dbc)->dbp->env, (dbc)->locker == NULL || \ + __db_haslock((dbc)->dbp->env, \ + (dbc)->locker, (dbc)->dbp->mpf, pgno, mode, type) == 0) +#else +#define LOCK_CHECK_OFF(ip) NOP_STATEMENT +#define LOCK_CHECK_ON(ip) NOP_STATEMENT +#define LOCK_CHECK(dbc, pgno, mode) NOP_STATEMENT +#endif + +typedef struct __env_thread_info { + u_int32_t thr_count; + u_int32_t thr_init; + u_int32_t thr_max; + u_int32_t thr_nbucket; + roff_t thr_hashoff; +} THREAD_INFO; + +#define DB_EVENT(env, e, einfo) do { \ + DB_ENV *__dbenv = (env)->dbenv; \ + if (__dbenv->db_event_func != NULL) \ + __dbenv->db_event_func(__dbenv, e, einfo); \ +} while (0) + +typedef struct __flag_map { + u_int32_t inflag, outflag; +} FLAG_MAP; + +typedef struct __db_backup_handle { + int (*open) __P((DB_ENV *, const char *, const char *, void **)); + int (*write) __P((DB_ENV *, + u_int32_t, u_int32_t, u_int32_t, u_int8_t *, void *)); + int (*close) __P((DB_ENV *, const char *, void *)); + u_int32_t size; + u_int32_t read_count; + u_int32_t read_sleep; +#define BACKUP_WRITE_DIRECT 0x0001 + int flags; +} DB_BACKUP; + +/* + * Internal database environment structure. + * + * This is the private database environment handle. The public environment + * handle is the DB_ENV structure. The library owns this structure, the user + * owns the DB_ENV structure. The reason there are two structures is because + * the user's configuration outlives any particular DB_ENV->open call, and + * separate structures allows us to easily discard internal information without + * discarding the user's configuration. + */ +struct __env { + DB_ENV *dbenv; /* Linked DB_ENV structure */ + + /* + * The ENV structure can be used concurrently, so field access is + * protected. + */ + db_mutex_t mtx_env; /* ENV structure mutex */ + + /* + * Some fields are included in the ENV structure rather than in the + * DB_ENV structure because they are only set as arguments to the + * DB_ENV->open method. In other words, because of the historic API, + * not for any rational reason. + * + * Arguments to DB_ENV->open. + */ + char *db_home; /* Database home */ + u_int32_t open_flags; /* Flags */ + int db_mode; /* Default open permissions */ + + pid_t pid_cache; /* Cached process ID */ + + DB_FH *lockfhp; /* fcntl(2) locking file handle */ + + DB_LOCKER *env_lref; /* Locker in non-threaded handles */ + + DB_DISTAB recover_dtab; /* Dispatch table for recover funcs */ + + int dir_mode; /* Intermediate directory perms. */ + +#define ENV_DEF_DATA_LEN 100 + u_int32_t data_len; /* Data length in __db_prbytes. */ + + /* Thread tracking */ + u_int32_t thr_nbucket; /* Number of hash buckets */ + DB_HASHTAB *thr_hashtab; /* Hash table of DB_THREAD_INFO */ + + /* + * List of open DB handles for this ENV, used for cursor + * adjustment. Must be protected for multi-threaded support. + */ + db_mutex_t mtx_dblist; + int db_ref; /* DB handle reference count */ + TAILQ_HEAD(__dblist, __db) dblist; + + /* + * List of open file handles for this ENV. Must be protected + * for multi-threaded support. + */ + TAILQ_HEAD(__fdlist, __fh_t) fdlist; + + db_mutex_t mtx_mt; /* Mersenne Twister mutex */ + int mti; /* Mersenne Twister index */ + u_long *mt; /* Mersenne Twister state vector */ + + DB_CIPHER *crypto_handle; /* Crypto handle */ + DB_LOCKTAB *lk_handle; /* Lock handle */ + DB_LOG *lg_handle; /* Log handle */ + DB_MPOOL *mp_handle; /* Mpool handle */ + DB_MUTEXMGR *mutex_handle; /* Mutex handle */ + DB_REP *rep_handle; /* Replication handle */ + DB_TXNMGR *tx_handle; /* Txn handle */ + + DB_BACKUP *backup_handle; /* database copy configuration. */ + + /* + * XA support. + */ + int xa_rmid; /* XA Resource Manager ID */ + int xa_ref; /* XA Reference count */ + TAILQ_ENTRY(__env) links; /* XA environments */ + + /* Application callback to copy data to/from a custom data source */ +#define DB_USERCOPY_GETDATA 0x0001 +#define DB_USERCOPY_SETDATA 0x0002 + int (*dbt_usercopy) + __P((DBT *, u_int32_t, void *, u_int32_t, u_int32_t)); + + int (*log_verify_wrap) __P((ENV *, const char *, u_int32_t, + const char *, const char *, time_t, time_t, u_int32_t, u_int32_t, + u_int32_t, u_int32_t, int, int)); + + REGINFO *reginfo; /* REGINFO structure reference */ + +#define DB_TEST_ELECTINIT 1 /* after __rep_elect_init */ +#define DB_TEST_ELECTVOTE1 2 /* after sending VOTE1 */ +#define DB_TEST_NO_PAGES 3 /* before sending PAGE */ +#define DB_TEST_POSTDESTROY 4 /* after destroy op */ +#define DB_TEST_POSTLOG 5 /* after logging all pages */ +#define DB_TEST_POSTLOGMETA 6 /* after logging meta in btree */ +#define DB_TEST_POSTOPEN 7 /* after __os_open */ +#define DB_TEST_POSTSYNC 8 /* after syncing the log */ +#define DB_TEST_PREDESTROY 9 /* before destroy op */ +#define DB_TEST_PREOPEN 10 /* before __os_open */ +#define DB_TEST_REPMGR_PERM 11 /* repmgr perm/archiving tests */ +#define DB_TEST_SUBDB_LOCKS 12 /* subdb locking tests */ + int test_abort; /* Abort value for testing */ + int test_check; /* Checkpoint value for testing */ + int test_copy; /* Copy value for testing */ + +#define ENV_CDB 0x00000001 /* DB_INIT_CDB */ +#define ENV_DBLOCAL 0x00000002 /* Environment for a private DB */ +#define ENV_LITTLEENDIAN 0x00000004 /* Little endian system. */ +#define ENV_LOCKDOWN 0x00000008 /* DB_LOCKDOWN set */ +#define ENV_NO_OUTPUT_SET 0x00000010 /* No output channel set */ +#define ENV_OPEN_CALLED 0x00000020 /* DB_ENV->open called */ +#define ENV_PRIVATE 0x00000040 /* DB_PRIVATE set */ +#define ENV_RECOVER_FATAL 0x00000080 /* Doing fatal recovery in env */ +#define ENV_REF_COUNTED 0x00000100 /* Region references this handle */ +#define ENV_SYSTEM_MEM 0x00000200 /* DB_SYSTEM_MEM set */ +#define ENV_THREAD 0x00000400 /* DB_THREAD set */ +#define ENV_FORCE_TXN_BULK 0x00000800 /* Txns use bulk mode-for testing */ + u_int32_t flags; +}; + +/******************************************************* + * Database Access Methods. + *******************************************************/ +/* + * DB_IS_THREADED -- + * The database handle is free-threaded (was opened with DB_THREAD). + */ +#define DB_IS_THREADED(dbp) \ + ((dbp)->mutex != MUTEX_INVALID) + +/* Initialization methods are often illegal before/after open is called. */ +#define DB_ILLEGAL_AFTER_OPEN(dbp, name) \ + if (F_ISSET((dbp), DB_AM_OPEN_CALLED)) \ + return (__db_mi_open((dbp)->env, name, 1)); +#define DB_ILLEGAL_BEFORE_OPEN(dbp, name) \ + if (!F_ISSET((dbp), DB_AM_OPEN_CALLED)) \ + return (__db_mi_open((dbp)->env, name, 0)); +/* Some initialization methods are illegal if environment isn't local. */ +#define DB_ILLEGAL_IN_ENV(dbp, name) \ + if (!F_ISSET((dbp)->env, ENV_DBLOCAL)) \ + return (__db_mi_env((dbp)->env, name)); +#define DB_ILLEGAL_METHOD(dbp, flags) { \ + int __ret; \ + if ((__ret = __dbh_am_chk(dbp, flags)) != 0) \ + return (__ret); \ +} + +/* + * Common DBC->internal fields. Each access method adds additional fields + * to this list, but the initial fields are common. + */ +#define __DBC_INTERNAL \ + DBC *opd; /* Off-page duplicate cursor. */\ + DBC *pdbc; /* Pointer to parent cursor. */ \ + \ + void *page; /* Referenced page. */ \ + u_int32_t part; /* Partition number. */ \ + db_pgno_t root; /* Tree root. */ \ + db_pgno_t pgno; /* Referenced page number. */ \ + db_indx_t indx; /* Referenced key item index. */\ + \ + /* Streaming -- cache last position. */ \ + db_pgno_t stream_start_pgno; /* Last start pgno. */ \ + u_int32_t stream_off; /* Current offset. */ \ + db_pgno_t stream_curr_pgno; /* Current overflow page. */ \ + \ + DB_LOCK lock; /* Cursor lock. */ \ + db_lockmode_t lock_mode; /* Lock mode. */ + +struct __dbc_internal { + __DBC_INTERNAL +}; + +/* Actions that __db_master_update can take. */ +typedef enum { MU_REMOVE, MU_RENAME, MU_OPEN, MU_MOVE } mu_action; + +/* + * Access-method-common macro for determining whether a cursor + * has been initialized. + */ +#ifdef HAVE_PARTITION +#define IS_INITIALIZED(dbc) (DB_IS_PARTITIONED((dbc)->dbp) ? \ + ((PART_CURSOR *)(dbc)->internal)->sub_cursor != NULL && \ + ((PART_CURSOR *)(dbc)->internal)->sub_cursor-> \ + internal->pgno != PGNO_INVALID : \ + (dbc)->internal->pgno != PGNO_INVALID) +#else +#define IS_INITIALIZED(dbc) ((dbc)->internal->pgno != PGNO_INVALID) +#endif + +/* Free the callback-allocated buffer, if necessary, hanging off of a DBT. */ +#define FREE_IF_NEEDED(env, dbt) \ + if (F_ISSET((dbt), DB_DBT_APPMALLOC)) { \ + __os_ufree((env), (dbt)->data); \ + F_CLR((dbt), DB_DBT_APPMALLOC); \ + } + +/* + * Use memory belonging to object "owner" to return the results of + * any no-DBT-flag get ops on cursor "dbc". + */ +#define SET_RET_MEM(dbc, owner) \ + do { \ + (dbc)->rskey = &(owner)->my_rskey; \ + (dbc)->rkey = &(owner)->my_rkey; \ + (dbc)->rdata = &(owner)->my_rdata; \ + } while (0) + +/* Use the return-data memory src is currently set to use in dest as well. */ +#define COPY_RET_MEM(src, dest) \ + do { \ + (dest)->rskey = (src)->rskey; \ + (dest)->rkey = (src)->rkey; \ + (dest)->rdata = (src)->rdata; \ + } while (0) + +/* Reset the returned-memory pointers to their defaults. */ +#define RESET_RET_MEM(dbc) \ + do { \ + (dbc)->rskey = &(dbc)->my_rskey; \ + (dbc)->rkey = &(dbc)->my_rkey; \ + (dbc)->rdata = &(dbc)->my_rdata; \ + } while (0) + +#define COMPACT_TRUNCATE(c_data) do { \ + if (c_data->compact_truncate > 1) \ + c_data->compact_truncate--; \ +} while (0) + +/******************************************************* + * Mpool. + *******************************************************/ +/* + * File types for DB access methods. Negative numbers are reserved to DB. + */ +#define DB_FTYPE_SET -1 /* Call pgin/pgout functions. */ +#define DB_FTYPE_NOTSET 0 /* Don't call... */ +#define DB_LSN_OFF_NOTSET -1 /* Not yet set. */ +#define DB_CLEARLEN_NOTSET UINT32_MAX /* Not yet set. */ + +/* Structure used as the DB pgin/pgout pgcookie. */ +typedef struct __dbpginfo { + u_int32_t db_pagesize; /* Underlying page size. */ + u_int32_t flags; /* Some DB_AM flags needed. */ + DBTYPE type; /* DB type */ +} DB_PGINFO; + +/******************************************************* + * Log. + *******************************************************/ +/* Initialize an LSN to 'zero'. */ +#define ZERO_LSN(LSN) do { \ + (LSN).file = 0; \ + (LSN).offset = 0; \ +} while (0) +#define IS_ZERO_LSN(LSN) ((LSN).file == 0 && (LSN).offset == 0) + +#define IS_INIT_LSN(LSN) ((LSN).file == 1 && (LSN).offset == 0) +#define INIT_LSN(LSN) do { \ + (LSN).file = 1; \ + (LSN).offset = 0; \ +} while (0) + +#define MAX_LSN(LSN) do { \ + (LSN).file = UINT32_MAX; \ + (LSN).offset = UINT32_MAX; \ +} while (0) +#define IS_MAX_LSN(LSN) \ + ((LSN).file == UINT32_MAX && (LSN).offset == UINT32_MAX) + +/* If logging is turned off, smash the lsn. */ +#define LSN_NOT_LOGGED(LSN) do { \ + (LSN).file = 0; \ + (LSN).offset = 1; \ +} while (0) +#define IS_NOT_LOGGED_LSN(LSN) \ + ((LSN).file == 0 && (LSN).offset == 1) + +/* + * LOG_COMPARE -- compare two LSNs. + */ + +#define LOG_COMPARE(lsn0, lsn1) \ + ((lsn0)->file != (lsn1)->file ? \ + ((lsn0)->file < (lsn1)->file ? -1 : 1) : \ + ((lsn0)->offset != (lsn1)->offset ? \ + ((lsn0)->offset < (lsn1)->offset ? -1 : 1) : 0)) + +/******************************************************* + * Txn. + *******************************************************/ +#define DB_NONBLOCK(C) ((C)->txn != NULL && F_ISSET((C)->txn, TXN_NOWAIT)) +#define NOWAIT_FLAG(txn) \ + ((txn) != NULL && F_ISSET((txn), TXN_NOWAIT) ? DB_LOCK_NOWAIT : 0) +#define IS_REAL_TXN(txn) \ + ((txn) != NULL && !F_ISSET(txn, TXN_FAMILY)) +#define IS_SUBTRANSACTION(txn) \ + ((txn) != NULL && (txn)->parent != NULL) + +/* Checks for existence of an XA transaction in access method interfaces. */ +#define XA_CHECK_TXN(ip, txn) \ + if ((ip) != NULL && (txn) == NULL) { \ + (txn) = SH_TAILQ_FIRST(&(ip)->dbth_xatxn, __db_txn); \ + DB_ASSERT(env, txn == NULL || \ + txn->xa_thr_status == TXN_XA_THREAD_ASSOCIATED); \ + } + +/* Ensure that there is no XA transaction active. */ +#define XA_NO_TXN(ip, retval) { \ + DB_TXN *__txn; \ + retval = 0; \ + if ((ip) != NULL) { \ + __txn = SH_TAILQ_FIRST(&(ip)->dbth_xatxn, __db_txn); \ + if (__txn != NULL && \ + __txn->xa_thr_status == TXN_XA_THREAD_ASSOCIATED) \ + retval = EINVAL; \ + } \ +} + +/******************************************************* + * Crypto. + *******************************************************/ +#define DB_IV_BYTES 16 /* Bytes per IV */ +#define DB_MAC_KEY 20 /* Bytes per MAC checksum */ + +/******************************************************* + * Compression + *******************************************************/ +#define CMP_INT_SPARE_VAL 0xFC /* Smallest byte value that the integer + compression algorithm doesn't use */ + +#if defined(__cplusplus) +} +#endif + +/******************************************************* + * Remaining general DB includes. + *******************************************************/ +@db_int_def@ + +#include "dbinc/globals.h" +#include "dbinc/clock.h" +#include "dbinc/debug.h" +#include "dbinc/region.h" +#include "dbinc_auto/env_ext.h" +#include "dbinc/mutex.h" +#ifdef HAVE_REPLICATION_THREADS +#include "dbinc/repmgr.h" +#endif +#include "dbinc/rep.h" +#include "dbinc/os.h" +#include "dbinc_auto/clib_ext.h" +#include "dbinc_auto/common_ext.h" + +/******************************************************* + * Remaining Log. + * These need to be defined after the general includes + * because they need rep.h from above. + *******************************************************/ +/* + * Test if the environment is currently logging changes. If we're in recovery + * or we're a replication client, we don't need to log changes because they're + * already in the log, even though we have a fully functional log system. + */ +#define DBENV_LOGGING(env) \ + (LOGGING_ON(env) && !IS_REP_CLIENT(env) && (!IS_RECOVERING(env))) + +/* + * Test if we need to log a change. By default, we don't log operations without + * associated transactions, unless DIAGNOSTIC, DEBUG_ROP or DEBUG_WOP are on. + * This is because we want to get log records for read/write operations, and, if + * we are trying to debug something, more information is always better. + * + * The DBC_RECOVER flag is set when we're in abort, as well as during recovery; + * thus DBC_LOGGING may be false for a particular dbc even when DBENV_LOGGING + * is true. + * + * We explicitly use LOGGING_ON/IS_REP_CLIENT here because we don't want to pull + * in the log headers, which IS_RECOVERING (and thus DBENV_LOGGING) rely on, and + * because DBC_RECOVER should be set anytime IS_RECOVERING would be true. + * + * If we're not in recovery (master - doing an abort or a client applying + * a txn), then a client's only path through here is on an internal + * operation, and a master's only path through here is a transactional + * operation. Detect if either is not the case. + */ +#if defined(DIAGNOSTIC) || defined(DEBUG_ROP) || defined(DEBUG_WOP) +#define DBC_LOGGING(dbc) __dbc_logging(dbc) +#else +#define DBC_LOGGING(dbc) \ + ((dbc)->txn != NULL && LOGGING_ON((dbc)->env) && \ + !F_ISSET((dbc), DBC_RECOVER) && !IS_REP_CLIENT((dbc)->env)) +#endif + +#endif /* !_DB_INT_H_ */ diff -r 000000000000 -r a1985f14b030 src/dbinc/db_join.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/dbinc/db_join.h Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,59 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 1998, 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + * $Id$ + */ + +#ifndef _DB_JOIN_H_ +#define _DB_JOIN_H_ + +#if defined(__cplusplus) +extern "C" { +#endif + +/* + * Joins use a join cursor that is similar to a regular DB cursor except + * that it only supports c_get and c_close functionality. Also, it does + * not support the full range of flags for get. + */ +typedef struct __join_cursor { + u_int8_t *j_exhausted; /* Array of flags; is cursor i exhausted? */ + DBC **j_curslist; /* Array of cursors in the join: constant. */ + DBC **j_fdupcurs; /* Cursors w/ first instances of current dup. */ + DBC **j_workcurs; /* Scratch cursor copies to muck with. */ + DB *j_primary; /* Primary dbp. */ + DBT j_key; /* Used to do lookups. */ + DBT j_rdata; /* Memory used for data return. */ + u_int32_t j_ncurs; /* How many cursors do we have? */ +#define JOIN_RETRY 0x01 /* Error on primary get; re-return same key. */ + u_int32_t flags; +} JOIN_CURSOR; + +#if defined(__cplusplus) +} +#endif +#endif /* !_DB_JOIN_H_ */ diff -r 000000000000 -r a1985f14b030 src/dbinc/db_page.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/dbinc/db_page.h Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,863 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 1996, 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + * $Id$ + */ + +#ifndef _DB_PAGE_H_ +#define _DB_PAGE_H_ + +#if defined(__cplusplus) +extern "C" { +#endif + +/* + * DB page formats. + * + * !!! + * This implementation requires that values within the following structures + * NOT be padded -- note, ANSI C permits random padding within structures. + * If your compiler pads randomly you can just forget ever making DB run on + * your system. In addition, no data type can require larger alignment than + * its own size, e.g., a 4-byte data element may not require 8-byte alignment. + * + * Note that key/data lengths are often stored in db_indx_t's -- this is + * not accidental, nor does it limit the key/data size. If the key/data + * item fits on a page, it's guaranteed to be small enough to fit into a + * db_indx_t, and storing it in one saves space. + */ + +#define PGNO_INVALID 0 /* Invalid page number in any database. */ +#define PGNO_BASE_MD 0 /* Base database: metadata page number. */ + +/* Page types. */ +#define P_INVALID 0 /* Invalid page type. */ +#define __P_DUPLICATE 1 /* Duplicate. DEPRECATED in 3.1 */ +#define P_HASH_UNSORTED 2 /* Hash pages created pre 4.6. DEPRECATED */ +#define P_IBTREE 3 /* Btree internal. */ +#define P_IRECNO 4 /* Recno internal. */ +#define P_LBTREE 5 /* Btree leaf. */ +#define P_LRECNO 6 /* Recno leaf. */ +#define P_OVERFLOW 7 /* Overflow. */ +#define P_HASHMETA 8 /* Hash metadata page. */ +#define P_BTREEMETA 9 /* Btree metadata page. */ +#define P_QAMMETA 10 /* Queue metadata page. */ +#define P_QAMDATA 11 /* Queue data page. */ +#define P_LDUP 12 /* Off-page duplicate leaf. */ +#define P_HASH 13 /* Sorted hash page. */ +#define P_HEAPMETA 14 /* Heap metadata page. */ +#define P_HEAP 15 /* Heap data page. */ +#define P_IHEAP 16 /* Heap internal. */ +#define P_PAGETYPE_MAX 17 +/* Flag to __db_new */ +#define P_DONTEXTEND 0x8000 /* Don't allocate if there are no free pages. */ + +/* + * When we create pages in mpool, we ask mpool to clear some number of bytes + * in the header. This number must be at least as big as the regular page + * headers and cover enough of the btree and hash meta-data pages to obliterate + * the page type. + */ +#define DB_PAGE_DB_LEN 32 +#define DB_PAGE_QUEUE_LEN 0 + +/************************************************************************ + GENERIC METADATA PAGE HEADER + * + * !!! + * The magic and version numbers have to be in the same place in all versions + * of the metadata page as the application may not have upgraded the database. + ************************************************************************/ +typedef struct _dbmeta33 { + DB_LSN lsn; /* 00-07: LSN. */ + db_pgno_t pgno; /* 08-11: Current page number. */ + u_int32_t magic; /* 12-15: Magic number. */ + u_int32_t version; /* 16-19: Version. */ + u_int32_t pagesize; /* 20-23: Pagesize. */ + u_int8_t encrypt_alg; /* 24: Encryption algorithm. */ + u_int8_t type; /* 25: Page type. */ +#define DBMETA_CHKSUM 0x01 +#define DBMETA_PART_RANGE 0x02 +#define DBMETA_PART_CALLBACK 0x04 + u_int8_t metaflags; /* 26: Meta-only flags */ + u_int8_t unused1; /* 27: Unused. */ + u_int32_t free; /* 28-31: Free list page number. */ + db_pgno_t last_pgno; /* 32-35: Page number of last page in db. */ + u_int32_t nparts; /* 36-39: Number of partitions. */ + u_int32_t key_count; /* 40-43: Cached key count. */ + u_int32_t record_count; /* 44-47: Cached record count. */ + u_int32_t flags; /* 48-51: Flags: unique to each AM. */ + /* 52-71: Unique file ID. */ + u_int8_t uid[DB_FILE_ID_LEN]; +} DBMETA33, DBMETA; + +/************************************************************************ + BTREE METADATA PAGE LAYOUT + ************************************************************************/ +typedef struct _btmeta33 { +#define BTM_DUP 0x001 /* Duplicates. */ +#define BTM_RECNO 0x002 /* Recno tree. */ +#define BTM_RECNUM 0x004 /* Btree: maintain record count. */ +#define BTM_FIXEDLEN 0x008 /* Recno: fixed length records. */ +#define BTM_RENUMBER 0x010 /* Recno: renumber on insert/delete. */ +#define BTM_SUBDB 0x020 /* Subdatabases. */ +#define BTM_DUPSORT 0x040 /* Duplicates are sorted. */ +#define BTM_COMPRESS 0x080 /* Compressed. */ +#define BTM_MASK 0x0ff + DBMETA dbmeta; /* 00-71: Generic meta-data header. */ + + u_int32_t unused1; /* 72-75: Unused space. */ + u_int32_t minkey; /* 76-79: Btree: Minkey. */ + u_int32_t re_len; /* 80-83: Recno: fixed-length record length. */ + u_int32_t re_pad; /* 84-87: Recno: fixed-length record pad. */ + u_int32_t root; /* 88-91: Root page. */ + u_int32_t unused2[92]; /* 92-459: Unused space. */ + u_int32_t crypto_magic; /* 460-463: Crypto magic number */ + u_int32_t trash[3]; /* 464-475: Trash space - Do not use */ + u_int8_t iv[DB_IV_BYTES]; /* 476-495: Crypto IV */ + u_int8_t chksum[DB_MAC_KEY]; /* 496-511: Page chksum */ + + /* + * Minimum page size is 512. + */ +} BTMETA33, BTMETA; + +/************************************************************************ + HASH METADATA PAGE LAYOUT + ************************************************************************/ +typedef struct _hashmeta33 { +#define DB_HASH_DUP 0x01 /* Duplicates. */ +#define DB_HASH_SUBDB 0x02 /* Subdatabases. */ +#define DB_HASH_DUPSORT 0x04 /* Duplicates are sorted. */ + DBMETA dbmeta; /* 00-71: Generic meta-data page header. */ + + u_int32_t max_bucket; /* 72-75: ID of Maximum bucket in use */ + u_int32_t high_mask; /* 76-79: Modulo mask into table */ + u_int32_t low_mask; /* 80-83: Modulo mask into table lower half */ + u_int32_t ffactor; /* 84-87: Fill factor */ + u_int32_t nelem; /* 88-91: Number of keys in hash table */ + u_int32_t h_charkey; /* 92-95: Value of hash(CHARKEY) */ +#define NCACHED 32 /* number of spare points */ + /* 96-223: Spare pages for overflow */ + u_int32_t spares[NCACHED]; + u_int32_t unused[59]; /* 224-459: Unused space */ + u_int32_t crypto_magic; /* 460-463: Crypto magic number */ + u_int32_t trash[3]; /* 464-475: Trash space - Do not use */ + u_int8_t iv[DB_IV_BYTES]; /* 476-495: Crypto IV */ + u_int8_t chksum[DB_MAC_KEY]; /* 496-511: Page chksum */ + + /* + * Minimum page size is 512. + */ +} HMETA33, HMETA; + +/************************************************************************ + HEAP METADATA PAGE LAYOUT +*************************************************************************/ +/* + * Heap Meta data page structure + * + */ +typedef struct _heapmeta { + DBMETA dbmeta; /* 00-71: Generic meta-data header. */ + + db_pgno_t curregion; /* 72-75: Current region pgno. */ + u_int32_t nregions; /* 76-79: Number of regions. */ + u_int32_t gbytes; /* 80-83: GBytes for fixed size heap. */ + u_int32_t bytes; /* 84-87: Bytes for fixed size heap. */ + u_int32_t region_size; /* 88-91: Max region size. */ + u_int32_t unused2[92]; /* 92-459: Unused space.*/ + u_int32_t crypto_magic; /* 460-463: Crypto magic number */ + u_int32_t trash[3]; /* 464-475: Trash space - Do not use */ + u_int8_t iv[DB_IV_BYTES]; /* 476-495: Crypto IV */ + u_int8_t chksum[DB_MAC_KEY]; /* 496-511: Page chksum */ + + + /* + * Minimum page size is 512. + */ +} HEAPMETA; + +/************************************************************************ + QUEUE METADATA PAGE LAYOUT + ************************************************************************/ +/* + * QAM Meta data page structure + * + */ +typedef struct _qmeta33 { + DBMETA dbmeta; /* 00-71: Generic meta-data header. */ + + u_int32_t first_recno; /* 72-75: First not deleted record. */ + u_int32_t cur_recno; /* 76-79: Next recno to be allocated. */ + u_int32_t re_len; /* 80-83: Fixed-length record length. */ + u_int32_t re_pad; /* 84-87: Fixed-length record pad. */ + u_int32_t rec_page; /* 88-91: Records Per Page. */ + u_int32_t page_ext; /* 92-95: Pages per extent */ + + u_int32_t unused[91]; /* 96-459: Unused space */ + u_int32_t crypto_magic; /* 460-463: Crypto magic number */ + u_int32_t trash[3]; /* 464-475: Trash space - Do not use */ + u_int8_t iv[DB_IV_BYTES]; /* 476-495: Crypto IV */ + u_int8_t chksum[DB_MAC_KEY]; /* 496-511: Page chksum */ + /* + * Minimum page size is 512. + */ +} QMETA33, QMETA; + +/* + * DBMETASIZE is a constant used by __db_file_setup and DB->verify + * as a buffer which is guaranteed to be larger than any possible + * metadata page size and smaller than any disk sector. + */ +#define DBMETASIZE 512 + +/************************************************************************ + BTREE/HASH MAIN PAGE LAYOUT + ************************************************************************/ +/* + * +-----------------------------------+ + * | lsn | pgno | prev pgno | + * +-----------------------------------+ + * | next pgno | entries | hf offset | + * +-----------------------------------+ + * | level | type | chksum | + * +-----------------------------------+ + * | iv | index | free --> | + * +-----------+-----------------------+ + * | F R E E A R E A | + * +-----------------------------------+ + * | <-- free | item | + * +-----------------------------------+ + * | item | item | item | + * +-----------------------------------+ + * + * sizeof(PAGE) == 26 bytes + possibly 20 bytes of checksum and possibly + * 16 bytes of IV (+ 2 bytes for alignment), and the following indices + * are guaranteed to be two-byte aligned. If we aren't doing crypto or + * checksumming the bytes are reclaimed for data storage. + * + * For hash and btree leaf pages, index items are paired, e.g., inp[0] is the + * key for inp[1]'s data. All other types of pages only contain single items. + */ +typedef struct __pg_chksum { + u_int8_t unused[2]; /* 26-27: For alignment */ + u_int8_t chksum[4]; /* 28-31: Checksum */ +} PG_CHKSUM; + +typedef struct __pg_crypto { + u_int8_t unused[2]; /* 26-27: For alignment */ + u_int8_t chksum[DB_MAC_KEY]; /* 28-47: Checksum */ + u_int8_t iv[DB_IV_BYTES]; /* 48-63: IV */ + /* !!! + * Must be 16-byte aligned for crypto + */ +} PG_CRYPTO; + +typedef struct _db_page { + DB_LSN lsn; /* 00-07: Log sequence number. */ + db_pgno_t pgno; /* 08-11: Current page number. */ + db_pgno_t prev_pgno; /* 12-15: Previous page number. */ + db_pgno_t next_pgno; /* 16-19: Next page number. */ + db_indx_t entries; /* 20-21: Number of items on the page. */ + db_indx_t hf_offset; /* 22-23: High free byte page offset. */ + + /* + * The btree levels are numbered from the leaf to the root, starting + * with 1, so the leaf is level 1, its parent is level 2, and so on. + * We maintain this level on all btree pages, but the only place that + * we actually need it is on the root page. It would not be difficult + * to hide the byte on the root page once it becomes an internal page, + * so we could get this byte back if we needed it for something else. + */ +#define LEAFLEVEL 1 +#define MAXBTREELEVEL 255 + u_int8_t level; /* 24: Btree tree level. */ + u_int8_t type; /* 25: Page type. */ +} PAGE; + +/* + * With many compilers sizeof(PAGE) == 28, while SIZEOF_PAGE == 26. + * We add in other things directly after the page header and need + * the SIZEOF_PAGE. When giving the sizeof(), many compilers will + * pad it out to the next 4-byte boundary. + */ +#define SIZEOF_PAGE 26 +/* + * !!! + * DB_AM_ENCRYPT always implies DB_AM_CHKSUM so that must come first. + */ +#define P_INP(dbp, pg) \ + ((db_indx_t *)((u_int8_t *)(pg) + SIZEOF_PAGE + \ + (F_ISSET((dbp), DB_AM_ENCRYPT) ? sizeof(PG_CRYPTO) : \ + (F_ISSET((dbp), DB_AM_CHKSUM) ? sizeof(PG_CHKSUM) : 0)))) + +#define P_IV(dbp, pg) \ + (F_ISSET((dbp), DB_AM_ENCRYPT) ? ((u_int8_t *)(pg) + \ + SIZEOF_PAGE + SSZA(PG_CRYPTO, iv)) \ + : NULL) + +#define P_CHKSUM(dbp, pg) \ + (F_ISSET((dbp), DB_AM_ENCRYPT) ? ((u_int8_t *)(pg) + \ + SIZEOF_PAGE + SSZA(PG_CRYPTO, chksum)) : \ + (F_ISSET((dbp), DB_AM_CHKSUM) ? ((u_int8_t *)(pg) + \ + SIZEOF_PAGE + SSZA(PG_CHKSUM, chksum)) \ + : NULL)) + +/* PAGE element macros. */ +#define LSN(p) (((PAGE *)p)->lsn) +#define PGNO(p) (((PAGE *)p)->pgno) +#define PREV_PGNO(p) (((PAGE *)p)->prev_pgno) +#define NEXT_PGNO(p) (((PAGE *)p)->next_pgno) +#define NUM_ENT(p) (((PAGE *)p)->entries) +#define HOFFSET(p) (((PAGE *)p)->hf_offset) +#define LEVEL(p) (((PAGE *)p)->level) +#define TYPE(p) (((PAGE *)p)->type) + +/************************************************************************ + HEAP PAGE LAYOUT + ************************************************************************/ +#define HEAPPG_NORMAL 26 +#define HEAPPG_CHKSUM 48 +#define HEAPPG_SEC 64 + +/* + * +0-----------2------------4-----------6-----------7+ + * | lsn | + * +-------------------------+------------------------+ + * | pgno | unused0 | + * +-------------+-----------+-----------+------------+ + * | high_indx | free_indx | entries | hf offset | + * +-------+-----+-----------+-----------+------------+ + * |unused2|type | unused3 | ...chksum... | + * +-------+-----+-----------+------------------------+ + * | ...iv... | offset table / free space map | + * +-------------+------------------------------------+ + * |free-> F R E E A R E A | + * +--------------------------------------------------+ + * | <-- free | item | + * +-------------------------+------------------------+ + * | item | item | + * +-------------------------+------------------------+ + * + * The page layout of both heap internal and data pages. If not using + * crypto, iv will be overwritten with data. If not using checksumming, + * unused3 and chksum will also be overwritten with data and data will start at + * 26. Note that this layout lets us re-use a lot of the PAGE element macros + * defined above. + */ +typedef struct _heappg { + DB_LSN lsn; /* 00-07: Log sequence number. */ + db_pgno_t pgno; /* 08-11: Current page number. */ + u_int32_t high_pgno; /* 12-15: Highest page in region. */ + u_int16_t high_indx; /* 16-17: Highest index in the offset table. */ + db_indx_t free_indx; /* 18-19: First available index. */ + db_indx_t entries; /* 20-21: Number of items on the page. */ + db_indx_t hf_offset; /* 22-23: High free byte page offset. */ + u_int8_t unused2[1]; /* 24: Unused. */ + u_int8_t type; /* 25: Page type. */ + u_int8_t unused3[2]; /* 26-27: Never used, just checksum alignment. */ + u_int8_t chksum[DB_MAC_KEY]; /* 28-47: Checksum */ + u_int8_t iv[DB_IV_BYTES]; /* 48-63: IV */ +} HEAPPG; + +/* Define first possible data page for heap, 0 is metapage, 1 is region page */ +#define FIRST_HEAP_RPAGE 1 +#define FIRST_HEAP_DPAGE 2 + +typedef struct __heaphdr { +#define HEAP_RECSPLIT 0x01 /* Heap data record is split */ +#define HEAP_RECFIRST 0x02 /* First piece of a split record */ +#define HEAP_RECLAST 0x04 /* Last piece of a split record */ + u_int8_t flags; /* 00: Flags describing record. */ + u_int8_t unused; /* 01: Padding. */ + u_int16_t size; /* 02-03: The size of the stored data piece. */ +} HEAPHDR; + +typedef struct __heaphdrsplt { + HEAPHDR std_hdr; /* 00-03: The standard data header */ + u_int32_t tsize; /* 04-07: Total record size, 1st piece only */ + db_pgno_t nextpg; /* 08-11: RID.pgno of the next record piece */ + db_indx_t nextindx; /* 12-13: RID.indx of the next record piece */ + u_int16_t unused; /* 14-15: Padding. */ +} HEAPSPLITHDR; + +#define HEAP_HDRSIZE(hdr) \ + (F_ISSET((hdr), HEAP_RECSPLIT) ? sizeof(HEAPSPLITHDR) : sizeof(HEAPHDR)) + +#define HEAPPG_SZ(dbp) \ + (F_ISSET((dbp), DB_AM_ENCRYPT) ? HEAPPG_SEC : \ + F_ISSET((dbp), DB_AM_CHKSUM) ? HEAPPG_CHKSUM : HEAPPG_NORMAL) + +/* Each byte in the bitmap describes 4 pages (2 bits per page.) */ +#define HEAP_REGION_COUNT(dbp, size) (((size) - HEAPPG_SZ(dbp)) * 4) +#define HEAP_DEFAULT_REGION_MAX(dbp) \ + (HEAP_REGION_COUNT(dbp, (u_int32_t)8 * 1024)) +#define HEAP_REGION_SIZE(dbp) (((HEAP*) (dbp)->heap_internal)->region_size) + +/* Figure out which region a given page belongs to. */ +#define HEAP_REGION_PGNO(dbp, p) \ + ((((p) - 1) / (HEAP_REGION_SIZE(dbp) + 1)) * \ + (HEAP_REGION_SIZE(dbp) + 1) + 1) +/* Translate a region pgno to region number */ +#define HEAP_REGION_NUM(dbp, pgno) \ + ((((pgno) - 1) / (HEAP_REGION_SIZE((dbp)) + 1)) + 1) +/* + * Given an internal heap page and page number relative to that page, return the + * bits from map describing free space on the nth page. Each byte in the map + * describes 4 pages. Point at the correct byte and mask the correct 2 bits. + */ +#define HEAP_SPACE(dbp, pg, n) \ + (HEAP_SPACEMAP((dbp), (pg))[(n) / 4] >> (2 * ((n) % 4)) & 3) + +#define HEAP_SETSPACE(dbp, pg, n, b) do { \ + HEAP_SPACEMAP((dbp), (pg))[(n) / 4] &= ~(3 << (2 * ((n) % 4))); \ + HEAP_SPACEMAP((dbp), (pg))[(n) / 4] |= ((b & 3) << (2 * ((n) % 4))); \ +} while (0) + +/* Return the bitmap describing free space on heap data pages. */ +#define HEAP_SPACEMAP(dbp, pg) ((u_int8_t *)P_INP((dbp), (pg))) + +/* Return the offset table for a heap data page. */ +#define HEAP_OFFSETTBL(dbp, pg) P_INP((dbp), (pg)) + +/* + * Calculate the % of a page a given size occupies and translate that to the + * corresponding bitmap value. + */ +#define HEAP_CALCSPACEBITS(dbp, sz, space) do { \ + (space) = 100 * (sz) / (dbp)->pgsize; \ + if ((space) <= HEAP_PG_FULL_PCT) \ + (space) = HEAP_PG_FULL; \ + else if ((space) <= HEAP_PG_GT66_PCT) \ + (space) = HEAP_PG_GT66; \ + else if ((space) <= HEAP_PG_GT33_PCT) \ + (space) = HEAP_PG_GT33; \ + else \ + (space) = HEAP_PG_LT33; \ +} while (0) + +/* Return the amount of free space on a heap data page. */ +#define HEAP_FREESPACE(dbp, p) \ + (HOFFSET(p) - HEAPPG_SZ(dbp) - \ + (NUM_ENT(p) == 0 ? 0 : ((HEAP_HIGHINDX(p) + 1) * sizeof(db_indx_t)))) + +/* The maximum amount of data that can fit on an empty heap data page. */ +#define HEAP_MAXDATASIZE(dbp) \ + ((dbp)->pgsize - HEAPPG_SZ(dbp) - sizeof(db_indx_t)) + +#define HEAP_FREEINDX(p) (((HEAPPG *)p)->free_indx) +#define HEAP_HIGHINDX(p) (((HEAPPG *)p)->high_indx) + +/* True if we have a page that deals with heap */ +#define HEAPTYPE(h) \ + (TYPE(h) == P_HEAPMETA || TYPE(h) == P_HEAP || TYPE(h) == P_IHEAP) + +/************************************************************************ + QUEUE MAIN PAGE LAYOUT + ************************************************************************/ +/* + * Sizes of page below. Used to reclaim space if not doing + * crypto or checksumming. If you change the QPAGE below you + * MUST adjust this too. + */ +#define QPAGE_NORMAL 28 +#define QPAGE_CHKSUM 48 +#define QPAGE_SEC 64 + +typedef struct _qpage { + DB_LSN lsn; /* 00-07: Log sequence number. */ + db_pgno_t pgno; /* 08-11: Current page number. */ + u_int32_t unused0[3]; /* 12-23: Unused. */ + u_int8_t unused1[1]; /* 24: Unused. */ + u_int8_t type; /* 25: Page type. */ + u_int8_t unused2[2]; /* 26-27: Unused. */ + u_int8_t chksum[DB_MAC_KEY]; /* 28-47: Checksum */ + u_int8_t iv[DB_IV_BYTES]; /* 48-63: IV */ +} QPAGE; + +#define QPAGE_SZ(dbp) \ + (F_ISSET((dbp), DB_AM_ENCRYPT) ? QPAGE_SEC : \ + F_ISSET((dbp), DB_AM_CHKSUM) ? QPAGE_CHKSUM : QPAGE_NORMAL) +/* + * !!! + * The next_pgno and prev_pgno fields are not maintained for btree and recno + * internal pages. Doing so only provides a minor performance improvement, + * it's hard to do when deleting internal pages, and it increases the chance + * of deadlock during deletes and splits because we have to re-link pages at + * more than the leaf level. + * + * !!! + * The btree/recno access method needs db_recno_t bytes of space on the root + * page to specify how many records are stored in the tree. (The alternative + * is to store the number of records in the meta-data page, which will create + * a second hot spot in trees being actively modified, or recalculate it from + * the BINTERNAL fields on each access.) Overload the PREV_PGNO field. + */ +#define RE_NREC(p) \ + ((TYPE(p) == P_IBTREE || TYPE(p) == P_IRECNO) ? PREV_PGNO(p) : \ + (db_pgno_t)(TYPE(p) == P_LBTREE ? NUM_ENT(p) / 2 : NUM_ENT(p))) +#define RE_NREC_ADJ(p, adj) \ + PREV_PGNO(p) += adj; +#define RE_NREC_SET(p, num) \ + PREV_PGNO(p) = (num); + +/* + * Initialize a page. + * + * !!! + * Don't modify the page's LSN, code depends on it being unchanged after a + * P_INIT call. + */ +#define P_INIT(pg, pg_size, n, pg_prev, pg_next, btl, pg_type) do { \ + PGNO(pg) = (n); \ + PREV_PGNO(pg) = (pg_prev); \ + NEXT_PGNO(pg) = (pg_next); \ + NUM_ENT(pg) = (0); \ + HOFFSET(pg) = (db_indx_t)(pg_size); \ + LEVEL(pg) = (btl); \ + TYPE(pg) = (pg_type); \ +} while (0) + +/* Page header length (offset to first index). */ +#define P_OVERHEAD(dbp) P_TO_UINT16(P_INP(dbp, 0)) + +/* First free byte. */ +#define LOFFSET(dbp, pg) \ + (P_OVERHEAD(dbp) + NUM_ENT(pg) * sizeof(db_indx_t)) + +/* Free space on a regular page. */ +#define P_FREESPACE(dbp, pg) (HOFFSET(pg) - LOFFSET(dbp, pg)) + +/* Get a pointer to the bytes at a specific index. */ +#define P_ENTRY(dbp, pg, indx) ((u_int8_t *)pg + P_INP(dbp, pg)[indx]) + +/************************************************************************ + OVERFLOW PAGE LAYOUT + ************************************************************************/ + +/* + * Overflow items are referenced by HOFFPAGE and BOVERFLOW structures, which + * store a page number (the first page of the overflow item) and a length + * (the total length of the overflow item). The overflow item consists of + * some number of overflow pages, linked by the next_pgno field of the page. + * A next_pgno field of PGNO_INVALID flags the end of the overflow item. + * + * Overflow page overloads: + * The amount of overflow data stored on each page is stored in the + * hf_offset field. + * + * The implementation reference counts overflow items as it's possible + * for them to be promoted onto btree internal pages. The reference + * count is stored in the entries field. + */ +#define OV_LEN(p) (((PAGE *)p)->hf_offset) +#define OV_REF(p) (((PAGE *)p)->entries) + +/* Maximum number of bytes that you can put on an overflow page. */ +#define P_MAXSPACE(dbp, psize) ((psize) - P_OVERHEAD(dbp)) + +/* Free space on an overflow page. */ +#define P_OVFLSPACE(dbp, psize, pg) (P_MAXSPACE(dbp, psize) - HOFFSET(pg)) + +/************************************************************************ + HASH PAGE LAYOUT + ************************************************************************/ + +/* Each index references a group of bytes on the page. */ +#define H_KEYDATA 1 /* Key/data item. */ +#define H_DUPLICATE 2 /* Duplicate key/data item. */ +#define H_OFFPAGE 3 /* Overflow key/data item. */ +#define H_OFFDUP 4 /* Overflow page of duplicates. */ + +/* + * !!! + * Items on hash pages are (potentially) unaligned, so we can never cast the + * (page + offset) pointer to an HKEYDATA, HOFFPAGE or HOFFDUP structure, as + * we do with B+tree on-page structures. Because we frequently want the type + * field, it requires no alignment, and it's in the same location in all three + * structures, there's a pair of macros. + */ +#define HPAGE_PTYPE(p) (*(u_int8_t *)p) +#define HPAGE_TYPE(dbp, pg, indx) (*P_ENTRY(dbp, pg, indx)) + +/* + * The first and second types are H_KEYDATA and H_DUPLICATE, represented + * by the HKEYDATA structure: + * + * +-----------------------------------+ + * | type | key/data ... | + * +-----------------------------------+ + * + * For duplicates, the data field encodes duplicate elements in the data + * field: + * + * +---------------------------------------------------------------+ + * | type | len1 | element1 | len1 | len2 | element2 | len2 | + * +---------------------------------------------------------------+ + * + * Thus, by keeping track of the offset in the element, we can do both + * backward and forward traversal. + */ +typedef struct _hkeydata { + u_int8_t type; /* 00: Page type. */ + u_int8_t data[1]; /* Variable length key/data item. */ +} HKEYDATA; +#define HKEYDATA_DATA(p) (((u_int8_t *)p) + SSZA(HKEYDATA, data)) + +/* + * The length of any HKEYDATA item. Note that indx is an element index, + * not a PAIR index. + */ +#define LEN_HITEM(dbp, pg, pgsize, indx) \ + (((indx) == 0 ? (pgsize) : \ + (P_INP(dbp, pg)[(indx) - 1])) - (P_INP(dbp, pg)[indx])) + +#define LEN_HKEYDATA(dbp, pg, psize, indx) \ + (db_indx_t)(LEN_HITEM(dbp, pg, psize, indx) - HKEYDATA_SIZE(0)) + +/* + * Page space required to add a new HKEYDATA item to the page, with and + * without the index value. + */ +#define HKEYDATA_SIZE(len) \ + ((len) + SSZA(HKEYDATA, data)) +#define HKEYDATA_PSIZE(len) \ + (HKEYDATA_SIZE(len) + sizeof(db_indx_t)) + +/* Put a HKEYDATA item at the location referenced by a page entry. */ +#define PUT_HKEYDATA(pe, kd, len, etype) { \ + ((HKEYDATA *)(pe))->type = etype; \ + memcpy((u_int8_t *)(pe) + sizeof(u_int8_t), kd, len); \ +} + +/* + * Macros the describe the page layout in terms of key-data pairs. + */ +#define H_NUMPAIRS(pg) (NUM_ENT(pg) / 2) +#define H_KEYINDEX(indx) (indx) +#define H_DATAINDEX(indx) ((indx) + 1) +#define H_PAIRKEY(dbp, pg, indx) P_ENTRY(dbp, pg, H_KEYINDEX(indx)) +#define H_PAIRDATA(dbp, pg, indx) P_ENTRY(dbp, pg, H_DATAINDEX(indx)) +#define H_PAIRSIZE(dbp, pg, psize, indx) \ + (LEN_HITEM(dbp, pg, psize, H_KEYINDEX(indx)) + \ + LEN_HITEM(dbp, pg, psize, H_DATAINDEX(indx))) +#define LEN_HDATA(dbp, p, psize, indx) \ + LEN_HKEYDATA(dbp, p, psize, H_DATAINDEX(indx)) +#define LEN_HKEY(dbp, p, psize, indx) \ + LEN_HKEYDATA(dbp, p, psize, H_KEYINDEX(indx)) + +/* + * The third type is the H_OFFPAGE, represented by the HOFFPAGE structure: + */ +typedef struct _hoffpage { + u_int8_t type; /* 00: Page type and delete flag. */ + u_int8_t unused[3]; /* 01-03: Padding, unused. */ + db_pgno_t pgno; /* 04-07: Offpage page number. */ + u_int32_t tlen; /* 08-11: Total length of item. */ +} HOFFPAGE; + +#define HOFFPAGE_PGNO(p) (((u_int8_t *)p) + SSZ(HOFFPAGE, pgno)) +#define HOFFPAGE_TLEN(p) (((u_int8_t *)p) + SSZ(HOFFPAGE, tlen)) + +/* + * Page space required to add a new HOFFPAGE item to the page, with and + * without the index value. + */ +#define HOFFPAGE_SIZE (sizeof(HOFFPAGE)) +#define HOFFPAGE_PSIZE (HOFFPAGE_SIZE + sizeof(db_indx_t)) + +/* + * The fourth type is H_OFFDUP represented by the HOFFDUP structure: + */ +typedef struct _hoffdup { + u_int8_t type; /* 00: Page type and delete flag. */ + u_int8_t unused[3]; /* 01-03: Padding, unused. */ + db_pgno_t pgno; /* 04-07: Offpage page number. */ +} HOFFDUP; +#define HOFFDUP_PGNO(p) (((u_int8_t *)p) + SSZ(HOFFDUP, pgno)) + +/* + * Page space required to add a new HOFFDUP item to the page, with and + * without the index value. + */ +#define HOFFDUP_SIZE (sizeof(HOFFDUP)) + +/************************************************************************ + BTREE PAGE LAYOUT + ************************************************************************/ + +/* Each index references a group of bytes on the page. */ +#define B_KEYDATA 1 /* Key/data item. */ +#define B_DUPLICATE 2 /* Duplicate key/data item. */ +#define B_OVERFLOW 3 /* Overflow key/data item. */ + +/* + * We have to store a deleted entry flag in the page. The reason is complex, + * but the simple version is that we can't delete on-page items referenced by + * a cursor -- the return order of subsequent insertions might be wrong. The + * delete flag is an overload of the top bit of the type byte. + */ +#define B_DELETE (0x80) +#define B_DCLR(t) (t) &= ~B_DELETE +#define B_DSET(t) (t) |= B_DELETE +#define B_DISSET(t) ((t) & B_DELETE) + +#define B_TYPE(t) ((t) & ~B_DELETE) +#define B_TSET(t, type) ((t) = B_TYPE(type)) +#define B_TSET_DELETED(t, type) ((t) = (type) | B_DELETE) + +/* + * The first type is B_KEYDATA, represented by the BKEYDATA structure: + */ +typedef struct _bkeydata { + db_indx_t len; /* 00-01: Key/data item length. */ + u_int8_t type; /* 02: Page type AND DELETE FLAG. */ + u_int8_t data[1]; /* Variable length key/data item. */ +} BKEYDATA; + +/* Get a BKEYDATA item for a specific index. */ +#define GET_BKEYDATA(dbp, pg, indx) \ + ((BKEYDATA *)P_ENTRY(dbp, pg, indx)) + +/* + * Page space required to add a new BKEYDATA item to the page, with and + * without the index value. The (u_int16_t) cast avoids warnings: DB_ALIGN + * casts to uintmax_t, the cast converts it to a small integral type so we + * don't get complaints when we assign the final result to an integral type + * smaller than uintmax_t. + */ +#define BKEYDATA_SIZE(len) \ + (u_int16_t)DB_ALIGN((len) + SSZA(BKEYDATA, data), sizeof(u_int32_t)) +#define BKEYDATA_PSIZE(len) \ + (BKEYDATA_SIZE(len) + sizeof(db_indx_t)) + +/* + * The second and third types are B_DUPLICATE and B_OVERFLOW, represented + * by the BOVERFLOW structure. + */ +typedef struct _boverflow { + db_indx_t unused1; /* 00-01: Padding, unused. */ + u_int8_t type; /* 02: Page type AND DELETE FLAG. */ + u_int8_t unused2; /* 03: Padding, unused. */ + db_pgno_t pgno; /* 04-07: Next page number. */ + u_int32_t tlen; /* 08-11: Total length of item. */ +} BOVERFLOW; + +/* Get a BOVERFLOW item for a specific index. */ +#define GET_BOVERFLOW(dbp, pg, indx) \ + ((BOVERFLOW *)P_ENTRY(dbp, pg, indx)) + +/* + * Page space required to add a new BOVERFLOW item to the page, with and + * without the index value. + */ +#define BOVERFLOW_SIZE \ + ((u_int16_t)DB_ALIGN(sizeof(BOVERFLOW), sizeof(u_int32_t))) +#define BOVERFLOW_PSIZE \ + (BOVERFLOW_SIZE + sizeof(db_indx_t)) + +#define BITEM_SIZE(bk) \ + (B_TYPE((bk)->type) != B_KEYDATA ? BOVERFLOW_SIZE : \ + BKEYDATA_SIZE((bk)->len)) + +#define BITEM_PSIZE(bk) \ + (B_TYPE((bk)->type) != B_KEYDATA ? BOVERFLOW_PSIZE : \ + BKEYDATA_PSIZE((bk)->len)) + +/* + * Btree leaf and hash page layouts group indices in sets of two, one for the + * key and one for the data. Everything else does it in sets of one to save + * space. Use the following macros so that it's real obvious what's going on. + */ +#define O_INDX 1 +#define P_INDX 2 + +/************************************************************************ + BTREE INTERNAL PAGE LAYOUT + ************************************************************************/ + +/* + * Btree internal entry. + */ +typedef struct _binternal { + db_indx_t len; /* 00-01: Key/data item length. */ + u_int8_t type; /* 02: Page type AND DELETE FLAG. */ + u_int8_t unused; /* 03: Padding, unused. */ + db_pgno_t pgno; /* 04-07: Page number of referenced page. */ + db_recno_t nrecs; /* 08-11: Subtree record count. */ + u_int8_t data[1]; /* Variable length key item. */ +} BINTERNAL; + +/* Get a BINTERNAL item for a specific index. */ +#define GET_BINTERNAL(dbp, pg, indx) \ + ((BINTERNAL *)P_ENTRY(dbp, pg, indx)) + +/* + * Page space required to add a new BINTERNAL item to the page, with and + * without the index value. + */ +#define BINTERNAL_SIZE(len) \ + (u_int16_t)DB_ALIGN((len) + SSZA(BINTERNAL, data), sizeof(u_int32_t)) +#define BINTERNAL_PSIZE(len) \ + (BINTERNAL_SIZE(len) + sizeof(db_indx_t)) + +/************************************************************************ + RECNO INTERNAL PAGE LAYOUT + ************************************************************************/ + +/* + * The recno internal entry. + */ +typedef struct _rinternal { + db_pgno_t pgno; /* 00-03: Page number of referenced page. */ + db_recno_t nrecs; /* 04-07: Subtree record count. */ +} RINTERNAL; + +/* Get a RINTERNAL item for a specific index. */ +#define GET_RINTERNAL(dbp, pg, indx) \ + ((RINTERNAL *)P_ENTRY(dbp, pg, indx)) + +/* + * Page space required to add a new RINTERNAL item to the page, with and + * without the index value. + */ +#define RINTERNAL_SIZE \ + (u_int16_t)DB_ALIGN(sizeof(RINTERNAL), sizeof(u_int32_t)) +#define RINTERNAL_PSIZE \ + (RINTERNAL_SIZE + sizeof(db_indx_t)) + +typedef struct __pglist { + db_pgno_t pgno, next_pgno; + DB_LSN lsn; +} db_pglist_t; + +#if defined(__cplusplus) +} +#endif + +#endif /* !_DB_PAGE_H_ */ diff -r 000000000000 -r a1985f14b030 src/dbinc/db_swap.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/dbinc/db_swap.h Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,284 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 1996, 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +/* + * Copyright (c) 1990, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $Id$ + */ + +#ifndef _DB_SWAP_H_ +#define _DB_SWAP_H_ + +#if defined(__cplusplus) +extern "C" { +#endif + +/* + * Little endian <==> big endian 64-bit swap macros. + * M_64_SWAP swap a memory location + * P_64_COPY copy potentially unaligned 4 byte quantities + * P_64_SWAP swap a referenced memory location + */ +#undef M_64_SWAP +#define M_64_SWAP(a) { \ + u_int64_t _tmp; \ + _tmp = (u_int64_t)a; \ + ((u_int8_t *)&a)[0] = ((u_int8_t *)&_tmp)[7]; \ + ((u_int8_t *)&a)[1] = ((u_int8_t *)&_tmp)[6]; \ + ((u_int8_t *)&a)[2] = ((u_int8_t *)&_tmp)[5]; \ + ((u_int8_t *)&a)[3] = ((u_int8_t *)&_tmp)[4]; \ + ((u_int8_t *)&a)[4] = ((u_int8_t *)&_tmp)[3]; \ + ((u_int8_t *)&a)[5] = ((u_int8_t *)&_tmp)[2]; \ + ((u_int8_t *)&a)[6] = ((u_int8_t *)&_tmp)[1]; \ + ((u_int8_t *)&a)[7] = ((u_int8_t *)&_tmp)[0]; \ +} +#undef P_64_COPY +#define P_64_COPY(a, b) { \ + ((u_int8_t *)b)[0] = ((u_int8_t *)a)[0]; \ + ((u_int8_t *)b)[1] = ((u_int8_t *)a)[1]; \ + ((u_int8_t *)b)[2] = ((u_int8_t *)a)[2]; \ + ((u_int8_t *)b)[3] = ((u_int8_t *)a)[3]; \ + ((u_int8_t *)b)[4] = ((u_int8_t *)a)[4]; \ + ((u_int8_t *)b)[5] = ((u_int8_t *)a)[5]; \ + ((u_int8_t *)b)[6] = ((u_int8_t *)a)[6]; \ + ((u_int8_t *)b)[7] = ((u_int8_t *)a)[7]; \ +} +#undef P_64_SWAP +#define P_64_SWAP(a) { \ + u_int64_t _tmp; \ + P_64_COPY(a, &_tmp); \ + ((u_int8_t *)a)[0] = ((u_int8_t *)&_tmp)[7]; \ + ((u_int8_t *)a)[1] = ((u_int8_t *)&_tmp)[6]; \ + ((u_int8_t *)a)[2] = ((u_int8_t *)&_tmp)[5]; \ + ((u_int8_t *)a)[3] = ((u_int8_t *)&_tmp)[4]; \ + ((u_int8_t *)a)[4] = ((u_int8_t *)&_tmp)[3]; \ + ((u_int8_t *)a)[5] = ((u_int8_t *)&_tmp)[2]; \ + ((u_int8_t *)a)[6] = ((u_int8_t *)&_tmp)[1]; \ + ((u_int8_t *)a)[7] = ((u_int8_t *)&_tmp)[0]; \ +} + +/* + * Little endian <==> big endian 32-bit swap macros. + * P_32_COPY copy potentially unaligned 4 byte quantities + * P_32_COPYSWAP copy and swap potentially unaligned 4 byte quantities + * P_32_SWAP swap a referenced memory location + * M_32_SWAP swap a memory location + */ +#undef P_32_COPY +#define P_32_COPY(a, b) do { \ + ((u_int8_t *)b)[0] = ((u_int8_t *)a)[0]; \ + ((u_int8_t *)b)[1] = ((u_int8_t *)a)[1]; \ + ((u_int8_t *)b)[2] = ((u_int8_t *)a)[2]; \ + ((u_int8_t *)b)[3] = ((u_int8_t *)a)[3]; \ +} while (0) +#undef P_32_COPYSWAP +#define P_32_COPYSWAP(a, b) do { \ + ((u_int8_t *)b)[0] = ((u_int8_t *)a)[3]; \ + ((u_int8_t *)b)[1] = ((u_int8_t *)a)[2]; \ + ((u_int8_t *)b)[2] = ((u_int8_t *)a)[1]; \ + ((u_int8_t *)b)[3] = ((u_int8_t *)a)[0]; \ +} while (0) +#undef P_32_SWAP +#define P_32_SWAP(a) do { \ + u_int32_t _tmp; \ + P_32_COPY(a, &_tmp); \ + P_32_COPYSWAP(&_tmp, a); \ +} while (0) +#undef M_32_SWAP +#define M_32_SWAP(a) P_32_SWAP(&a) + +/* + * Little endian <==> big endian 16-bit swap macros. + * P_16_COPY copy potentially unaligned 2 byte quantities + * P_16_COPYSWAP copy and swap potentially unaligned 2 byte quantities + * P_16_SWAP swap a referenced memory location + * M_16_SWAP swap a memory location + */ +#undef P_16_COPY +#define P_16_COPY(a, b) do { \ + ((u_int8_t *)b)[0] = ((u_int8_t *)a)[0]; \ + ((u_int8_t *)b)[1] = ((u_int8_t *)a)[1]; \ +} while (0) +#undef P_16_COPYSWAP +#define P_16_COPYSWAP(a, b) do { \ + ((u_int8_t *)b)[0] = ((u_int8_t *)a)[1]; \ + ((u_int8_t *)b)[1] = ((u_int8_t *)a)[0]; \ +} while (0) +#undef P_16_SWAP +#define P_16_SWAP(a) do { \ + u_int16_t _tmp; \ + P_16_COPY(a, &_tmp); \ + P_16_COPYSWAP(&_tmp, a); \ +} while (0) +#undef M_16_SWAP +#define M_16_SWAP(a) P_16_SWAP(&a) + +#undef SWAP32 +#define SWAP32(p) { \ + P_32_SWAP(p); \ + (p) += sizeof(u_int32_t); \ +} +#undef SWAP16 +#define SWAP16(p) { \ + P_16_SWAP(p); \ + (p) += sizeof(u_int16_t); \ +} + +/* + * Berkeley DB has local versions of htonl() and ntohl() that operate on + * pointers to the right size memory locations; the portability magic for + * finding the real system functions isn't worth the effort. + */ +#undef DB_HTONL_SWAP +#define DB_HTONL_SWAP(env, p) do { \ + if (F_ISSET((env), ENV_LITTLEENDIAN)) \ + P_32_SWAP(p); \ +} while (0) +#undef DB_NTOHL_SWAP +#define DB_NTOHL_SWAP(env, p) do { \ + if (F_ISSET((env), ENV_LITTLEENDIAN)) \ + P_32_SWAP(p); \ +} while (0) + +#undef DB_NTOHL_COPYIN +#define DB_NTOHL_COPYIN(env, i, p) do { \ + u_int8_t *tmp; \ + tmp = (u_int8_t *)&(i); \ + if (F_ISSET(env, ENV_LITTLEENDIAN)) { \ + tmp[3] = *p++; \ + tmp[2] = *p++; \ + tmp[1] = *p++; \ + tmp[0] = *p++; \ + } else { \ + memcpy(&i, p, sizeof(u_int32_t)); \ + p = (u_int8_t *)p + sizeof(u_int32_t); \ + } \ +} while (0) + +#undef DB_NTOHS_COPYIN +#define DB_NTOHS_COPYIN(env, i, p) do { \ + u_int8_t *tmp; \ + tmp = (u_int8_t *)&(i); \ + if (F_ISSET(env, ENV_LITTLEENDIAN)) { \ + tmp[1] = *p++; \ + tmp[0] = *p++; \ + } else { \ + memcpy(&i, p, sizeof(u_int16_t)); \ + p = (u_int8_t *)p + sizeof(u_int16_t); \ + } \ +} while (0) + +#undef DB_HTONL_COPYOUT +#define DB_HTONL_COPYOUT(env, p, i) do { \ + u_int8_t *tmp; \ + tmp = (u_int8_t *)p; \ + if (F_ISSET(env, ENV_LITTLEENDIAN)) { \ + *tmp++ = ((u_int8_t *)&(i))[3]; \ + *tmp++ = ((u_int8_t *)&(i))[2]; \ + *tmp++ = ((u_int8_t *)&(i))[1]; \ + *tmp++ = ((u_int8_t *)&(i))[0]; \ + } else \ + memcpy(p, &i, sizeof(u_int32_t)); \ + p = (u_int8_t *)p + sizeof(u_int32_t); \ +} while (0) + +#undef DB_HTONS_COPYOUT +#define DB_HTONS_COPYOUT(env, p, i) do { \ + u_int8_t *tmp; \ + tmp = (u_int8_t *)p; \ + if (F_ISSET(env, ENV_LITTLEENDIAN)) { \ + *tmp++ = ((u_int8_t *)&(i))[1]; \ + *tmp++ = ((u_int8_t *)&(i))[0]; \ + } else \ + memcpy(p, &i, sizeof(u_int16_t)); \ + p = (u_int8_t *)p + sizeof(u_int16_t); \ +} while (0) + +/* + * Helper macros for swapped logs. We write logs in little endian format to + * minimize disruption on x86 when upgrading from native byte order to + * platform-independent logs. + */ +#define LOG_SWAPPED(env) !F_ISSET(env, ENV_LITTLEENDIAN) + +#define LOGCOPY_32(env, x, p) do { \ + if (LOG_SWAPPED(env)) \ + P_32_COPYSWAP((p), (x)); \ + else \ + memcpy((x), (p), sizeof(u_int32_t)); \ +} while (0) + +#define LOGCOPY_16(env, x, p) do { \ + if (LOG_SWAPPED(env)) \ + P_16_COPYSWAP((p), (x)); \ + else \ + memcpy((x), (p), sizeof(u_int16_t)); \ +} while (0) + +#define LOGCOPY_TOLSN(env, lsnp, p) do { \ + LOGCOPY_32((env), &(lsnp)->file, (p)); \ + LOGCOPY_32((env), &(lsnp)->offset, \ + (u_int8_t *)(p) + sizeof(u_int32_t)); \ +} while (0) + +#define LOGCOPY_FROMLSN(env, p, lsnp) do { \ + LOGCOPY_32((env), (p), &(lsnp)->file); \ + LOGCOPY_32((env), \ + (u_int8_t *)(p) + sizeof(u_int32_t), &(lsnp)->offset); \ +} while (0) + +#if defined(__cplusplus) +} +#endif + +#endif /* !_DB_SWAP_H_ */ diff -r 000000000000 -r a1985f14b030 src/dbinc/db_upgrade.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/dbinc/db_upgrade.h Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,270 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 1996, 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + * $Id$ + */ + +#ifndef _DB_UPGRADE_H_ +#define _DB_UPGRADE_H_ + +#if defined(__cplusplus) +extern "C" { +#endif + +/* + * This file defines the metadata pages from the previous release. + * These structures are only used to upgrade old versions of databases. + */ + +/* Structures from the 3.1 release */ +typedef struct _dbmeta31 { + DB_LSN lsn; /* 00-07: LSN. */ + db_pgno_t pgno; /* 08-11: Current page number. */ + u_int32_t magic; /* 12-15: Magic number. */ + u_int32_t version; /* 16-19: Version. */ + u_int32_t pagesize; /* 20-23: Pagesize. */ + u_int8_t unused1[1]; /* 24: Unused. */ + u_int8_t type; /* 25: Page type. */ + u_int8_t unused2[2]; /* 26-27: Unused. */ + u_int32_t free; /* 28-31: Free list page number. */ + DB_LSN unused3; /* 36-39: Unused. */ + u_int32_t key_count; /* 40-43: Cached key count. */ + u_int32_t record_count; /* 44-47: Cached record count. */ + u_int32_t flags; /* 48-51: Flags: unique to each AM. */ + /* 52-71: Unique file ID. */ + u_int8_t uid[DB_FILE_ID_LEN]; +} DBMETA31; + +typedef struct _btmeta31 { + DBMETA31 dbmeta; /* 00-71: Generic meta-data header. */ + + u_int32_t maxkey; /* 72-75: Btree: Maxkey. */ + u_int32_t minkey; /* 76-79: Btree: Minkey. */ + u_int32_t re_len; /* 80-83: Recno: fixed-length record length. */ + u_int32_t re_pad; /* 84-87: Recno: fixed-length record pad. */ + u_int32_t root; /* 88-92: Root page. */ + + /* + * Minimum page size is 128. + */ +} BTMETA31; + +/************************************************************************ + HASH METADATA PAGE LAYOUT + ************************************************************************/ +typedef struct _hashmeta31 { + DBMETA31 dbmeta; /* 00-71: Generic meta-data page header. */ + + u_int32_t max_bucket; /* 72-75: ID of Maximum bucket in use */ + u_int32_t high_mask; /* 76-79: Modulo mask into table */ + u_int32_t low_mask; /* 80-83: Modulo mask into table lower half */ + u_int32_t ffactor; /* 84-87: Fill factor */ + u_int32_t nelem; /* 88-91: Number of keys in hash table */ + u_int32_t h_charkey; /* 92-95: Value of hash(CHARKEY) */ +#define NCACHED 32 /* number of spare points */ + /* 96-223: Spare pages for overflow */ + u_int32_t spares[NCACHED]; + + /* + * Minimum page size is 256. + */ +} HMETA31; + +/* + * QAM Meta data page structure + * + */ +typedef struct _qmeta31 { + DBMETA31 dbmeta; /* 00-71: Generic meta-data header. */ + + u_int32_t start; /* 72-75: Start offset. */ + u_int32_t first_recno; /* 76-79: First not deleted record. */ + u_int32_t cur_recno; /* 80-83: Last recno allocated. */ + u_int32_t re_len; /* 84-87: Fixed-length record length. */ + u_int32_t re_pad; /* 88-91: Fixed-length record pad. */ + u_int32_t rec_page; /* 92-95: Records Per Page. */ + + /* + * Minimum page size is 128. + */ +} QMETA31; +/* Structures from the 3.2 release */ +typedef struct _qmeta32 { + DBMETA31 dbmeta; /* 00-71: Generic meta-data header. */ + + u_int32_t first_recno; /* 72-75: First not deleted record. */ + u_int32_t cur_recno; /* 76-79: Last recno allocated. */ + u_int32_t re_len; /* 80-83: Fixed-length record length. */ + u_int32_t re_pad; /* 84-87: Fixed-length record pad. */ + u_int32_t rec_page; /* 88-91: Records Per Page. */ + u_int32_t page_ext; /* 92-95: Pages per extent */ + + /* + * Minimum page size is 128. + */ +} QMETA32; + +/* Structures from the 3.0 release */ + +typedef struct _dbmeta30 { + DB_LSN lsn; /* 00-07: LSN. */ + db_pgno_t pgno; /* 08-11: Current page number. */ + u_int32_t magic; /* 12-15: Magic number. */ + u_int32_t version; /* 16-19: Version. */ + u_int32_t pagesize; /* 20-23: Pagesize. */ + u_int8_t unused1[1]; /* 24: Unused. */ + u_int8_t type; /* 25: Page type. */ + u_int8_t unused2[2]; /* 26-27: Unused. */ + u_int32_t free; /* 28-31: Free list page number. */ + u_int32_t flags; /* 32-35: Flags: unique to each AM. */ + /* 36-55: Unique file ID. */ + u_int8_t uid[DB_FILE_ID_LEN]; +} DBMETA30; + +/************************************************************************ + BTREE METADATA PAGE LAYOUT + ************************************************************************/ +typedef struct _btmeta30 { + DBMETA30 dbmeta; /* 00-55: Generic meta-data header. */ + + u_int32_t maxkey; /* 56-59: Btree: Maxkey. */ + u_int32_t minkey; /* 60-63: Btree: Minkey. */ + u_int32_t re_len; /* 64-67: Recno: fixed-length record length. */ + u_int32_t re_pad; /* 68-71: Recno: fixed-length record pad. */ + u_int32_t root; /* 72-75: Root page. */ + + /* + * Minimum page size is 128. + */ +} BTMETA30; + +/************************************************************************ + HASH METADATA PAGE LAYOUT + ************************************************************************/ +typedef struct _hashmeta30 { + DBMETA30 dbmeta; /* 00-55: Generic meta-data page header. */ + + u_int32_t max_bucket; /* 56-59: ID of Maximum bucket in use */ + u_int32_t high_mask; /* 60-63: Modulo mask into table */ + u_int32_t low_mask; /* 64-67: Modulo mask into table lower half */ + u_int32_t ffactor; /* 68-71: Fill factor */ + u_int32_t nelem; /* 72-75: Number of keys in hash table */ + u_int32_t h_charkey; /* 76-79: Value of hash(CHARKEY) */ +#define NCACHED30 32 /* number of spare points */ + /* 80-207: Spare pages for overflow */ + u_int32_t spares[NCACHED30]; + + /* + * Minimum page size is 256. + */ +} HMETA30; + +/************************************************************************ + QUEUE METADATA PAGE LAYOUT + ************************************************************************/ +/* + * QAM Meta data page structure + * + */ +typedef struct _qmeta30 { + DBMETA30 dbmeta; /* 00-55: Generic meta-data header. */ + + u_int32_t start; /* 56-59: Start offset. */ + u_int32_t first_recno; /* 60-63: First not deleted record. */ + u_int32_t cur_recno; /* 64-67: Last recno allocated. */ + u_int32_t re_len; /* 68-71: Fixed-length record length. */ + u_int32_t re_pad; /* 72-75: Fixed-length record pad. */ + u_int32_t rec_page; /* 76-79: Records Per Page. */ + + /* + * Minimum page size is 128. + */ +} QMETA30; + +/* Structures from Release 2.x */ + +/************************************************************************ + BTREE METADATA PAGE LAYOUT + ************************************************************************/ + +/* + * Btree metadata page layout: + */ +typedef struct _btmeta2X { + DB_LSN lsn; /* 00-07: LSN. */ + db_pgno_t pgno; /* 08-11: Current page number. */ + u_int32_t magic; /* 12-15: Magic number. */ + u_int32_t version; /* 16-19: Version. */ + u_int32_t pagesize; /* 20-23: Pagesize. */ + u_int32_t maxkey; /* 24-27: Btree: Maxkey. */ + u_int32_t minkey; /* 28-31: Btree: Minkey. */ + u_int32_t free; /* 32-35: Free list page number. */ + u_int32_t flags; /* 36-39: Flags. */ + u_int32_t re_len; /* 40-43: Recno: fixed-length record length. */ + u_int32_t re_pad; /* 44-47: Recno: fixed-length record pad. */ + /* 48-67: Unique file ID. */ + u_int8_t uid[DB_FILE_ID_LEN]; +} BTMETA2X; + +/************************************************************************ + HASH METADATA PAGE LAYOUT + ************************************************************************/ + +/* + * Hash metadata page layout: + */ +/* Hash Table Information */ +typedef struct hashhdr { /* Disk resident portion */ + DB_LSN lsn; /* 00-07: LSN of the header page */ + db_pgno_t pgno; /* 08-11: Page number (btree compatibility). */ + u_int32_t magic; /* 12-15: Magic NO for hash tables */ + u_int32_t version; /* 16-19: Version ID */ + u_int32_t pagesize; /* 20-23: Bucket/Page Size */ + u_int32_t ovfl_point; /* 24-27: Overflow page allocation location */ + u_int32_t last_freed; /* 28-31: Last freed overflow page pgno */ + u_int32_t max_bucket; /* 32-35: ID of Maximum bucket in use */ + u_int32_t high_mask; /* 36-39: Modulo mask into table */ + u_int32_t low_mask; /* 40-43: Modulo mask into table lower half */ + u_int32_t ffactor; /* 44-47: Fill factor */ + u_int32_t nelem; /* 48-51: Number of keys in hash table */ + u_int32_t h_charkey; /* 52-55: Value of hash(CHARKEY) */ + u_int32_t flags; /* 56-59: Allow duplicates. */ +#define NCACHED2X 32 /* number of spare points */ + /* 60-187: Spare pages for overflow */ + u_int32_t spares[NCACHED2X]; + /* 188-207: Unique file ID. */ + u_int8_t uid[DB_FILE_ID_LEN]; + + /* + * Minimum page size is 256. + */ +} HASHHDR; + +#if defined(__cplusplus) +} +#endif +#endif /* !_DB_UPGRADE_H_ */ diff -r 000000000000 -r a1985f14b030 src/dbinc/db_verify.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/dbinc/db_verify.h Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,232 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 1999, 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + * $Id$ + */ + +#ifndef _DB_VERIFY_H_ +#define _DB_VERIFY_H_ + +#if defined(__cplusplus) +extern "C" { +#endif + +/* + * Structures and macros for the storage and retrieval of all information + * needed for inter-page verification of a database. + */ + +/* + * EPRINT is the macro for error printing. Takes as an arg the arg set + * for DB->err. + */ +#define EPRINT(x) do { \ + if (!LF_ISSET(DB_SALVAGE)) \ + __db_errx x; \ +} while (0) + +/* Complain about a totally zeroed page where we don't expect one. */ +#define ZEROPG_ERR_PRINT(dbenv, pgno, str) do { \ + EPRINT(((dbenv), DB_STR_A("0501", \ + "Page %lu: %s is of inappropriate type %lu", "%lu %s %lu"), \ + (u_long)(pgno), str, (u_long)P_INVALID)); \ + EPRINT(((dbenv), DB_STR_A("0502", \ + "Page %lu: totally zeroed page", \ + "%lu"), (u_long)(pgno))); \ +} while (0) + +/* + * Note that 0 is, in general, a valid pgno, despite equaling PGNO_INVALID; + * we have to test it separately where it's not appropriate. + */ +#define IS_VALID_PGNO(x) ((x) <= vdp->last_pgno) + +/* + * VRFY_DBINFO is the fundamental structure; it either represents the database + * of subdatabases, or the sole database if there are no subdatabases. + */ +struct __vrfy_dbinfo { + DB_THREAD_INFO *thread_info; + /* Info about this database in particular. */ + DBTYPE type; + + /* List of subdatabase meta pages, if any. */ + LIST_HEAD(__subdbs, __vrfy_childinfo) subdbs; + + /* Transaction handle for CDS group. */ + DB_TXN *txn; + + /* File-global info--stores VRFY_PAGEINFOs for each page. */ + DB *pgdbp; + + /* Child database--stores VRFY_CHILDINFOs of each page. */ + DB *cdbp; + + /* Page info structures currently in use. */ + LIST_HEAD(__activepips, __vrfy_pageinfo) activepips; + + /* + * DB we use to keep track of which pages are linked somehow + * during verification. 0 is the default, "unseen"; 1 is seen. + */ + DB *pgset; + + /* + * This is a database we use during salvaging to keep track of which + * overflow and dup pages we need to come back to at the end and print + * with key "UNKNOWN". Pages which print with a good key get set + * to SALVAGE_IGNORE; others get set, as appropriate, to SALVAGE_LDUP, + * SALVAGE_LRECNODUP, SALVAGE_OVERFLOW for normal db overflow pages, + * and SALVAGE_BTREE, SALVAGE_LRECNO, and SALVAGE_HASH for subdb + * pages. + */ +#define SALVAGE_INVALID 0 +#define SALVAGE_IGNORE 1 +#define SALVAGE_LDUP 2 +#define SALVAGE_IBTREE 3 +#define SALVAGE_OVERFLOW 4 +#define SALVAGE_LBTREE 5 +#define SALVAGE_HASH 6 +#define SALVAGE_LRECNO 7 +#define SALVAGE_LRECNODUP 8 + DB *salvage_pages; + + db_pgno_t last_pgno; + db_pgno_t meta_last_pgno; + db_pgno_t pgs_remaining; /* For dbp->db_feedback(). */ + + /* + * These are used during __bam_vrfy_subtree to keep track, while + * walking up and down the Btree structure, of the prev- and next-page + * chain of leaf pages and verify that it's intact. Also, make sure + * that this chain contains pages of only one type. + */ + db_pgno_t prev_pgno; + db_pgno_t next_pgno; + u_int8_t leaf_type; + + /* Queue needs these to verify data pages in the first pass. */ + u_int32_t re_pad; /* Record pad character. */ + u_int32_t re_len; /* Record length. */ + u_int32_t rec_page; + u_int32_t page_ext; + u_int32_t first_recno; + u_int32_t last_recno; + int nextents; + db_pgno_t *extents; + +#define SALVAGE_PRINTABLE 0x01 /* Output printable chars literally. */ +#define SALVAGE_PRINTHEADER 0x02 /* Print the unknown-key header. */ +#define SALVAGE_PRINTFOOTER 0x04 /* Print the unknown-key footer. */ +#define SALVAGE_HASSUBDBS 0x08 /* There are subdatabases to salvage. */ +#define VRFY_LEAFCHAIN_BROKEN 0x10 /* Lost one or more Btree leaf pgs. */ +#define VRFY_QMETA_SET 0x20 /* We've seen a QUEUE meta page and + set things up for it. */ + u_int32_t flags; +}; /* VRFY_DBINFO */ + +/* + * The amount of state information we need per-page is small enough that + * it's not worth the trouble to define separate structures for each + * possible type of page, and since we're doing verification with these we + * have to be open to the possibility that page N will be of a completely + * unexpected type anyway. So we define one structure here with all the + * info we need for inter-page verification. + */ +struct __vrfy_pageinfo { + u_int8_t type; + u_int8_t bt_level; + u_int8_t unused1; + u_int8_t unused2; + db_pgno_t pgno; + db_pgno_t prev_pgno; + db_pgno_t next_pgno; + + /* meta pages */ + db_pgno_t root; + db_pgno_t free; /* Free list head. */ + + db_indx_t entries; /* Actual number of entries. */ + u_int16_t unused; + db_recno_t rec_cnt; /* Record count. */ + u_int32_t re_pad; /* Record pad character. */ + u_int32_t re_len; /* Record length. */ + u_int32_t bt_minkey; + u_int32_t h_ffactor; + u_int32_t h_nelem; + + /* overflow pages */ + /* + * Note that refcount is the refcount for an overflow page; pi_refcount + * is this structure's own refcount! + */ + u_int32_t refcount; + u_int32_t olen; + +#define VRFY_DUPS_UNSORTED 0x0001 /* Have to flag the negative! */ +#define VRFY_HAS_CHKSUM 0x0002 +#define VRFY_HAS_DUPS 0x0004 +#define VRFY_HAS_DUPSORT 0x0008 /* Has the flag set. */ +#define VRFY_HAS_PART_RANGE 0x0010 /* Has the flag set. */ +#define VRFY_HAS_PART_CALLBACK 0x0020 /* Has the flag set. */ +#define VRFY_HAS_RECNUMS 0x0040 +#define VRFY_HAS_SUBDBS 0x0080 +#define VRFY_INCOMPLETE 0x0100 /* Meta or item order checks incomp. */ +#define VRFY_IS_ALLZEROES 0x0200 /* Hash page we haven't touched? */ +#define VRFY_IS_FIXEDLEN 0x0400 +#define VRFY_IS_RECNO 0x0800 +#define VRFY_IS_RRECNO 0x1000 +#define VRFY_OVFL_LEAFSEEN 0x2000 +#define VRFY_HAS_COMPRESS 0x4000 +#define VRFY_NONEXISTENT 0x8000 + u_int32_t flags; + + LIST_ENTRY(__vrfy_pageinfo) links; + u_int32_t pi_refcount; +}; /* VRFY_PAGEINFO */ + +struct __vrfy_childinfo { + /* The following fields are set by the caller of __db_vrfy_childput. */ + db_pgno_t pgno; + +#define V_DUPLICATE 1 /* off-page dup metadata */ +#define V_OVERFLOW 2 /* overflow page */ +#define V_RECNO 3 /* btree internal or leaf page */ + u_int32_t type; + db_recno_t nrecs; /* record count on a btree subtree */ + u_int32_t tlen; /* ovfl. item total size */ + + /* The following field is maintained by __db_vrfy_childput. */ + u_int32_t refcnt; /* # of times parent points to child. */ + + LIST_ENTRY(__vrfy_childinfo) links; +}; /* VRFY_CHILDINFO */ + +#if defined(__cplusplus) +} +#endif +#endif /* !_DB_VERIFY_H_ */ diff -r 000000000000 -r a1985f14b030 src/dbinc/debug.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/dbinc/debug.h Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,305 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 1998, 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + * $Id$ + */ + +#ifndef _DB_DEBUG_H_ +#define _DB_DEBUG_H_ + +#if defined(__cplusplus) +extern "C" { +#endif + +/* + * Turn on additional error checking in gcc 3.X. + */ +#if !defined(__GNUC__) || __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 5) +#define __attribute__(s) +#endif + +/* + * When running with #DIAGNOSTIC defined, we smash memory and do memory + * guarding with a special byte value. + */ +#define CLEAR_BYTE 0xdb +#define GUARD_BYTE 0xdc + +/* + * DB assertions. + * + * Use __STDC__ rather than STDC_HEADERS, the #e construct is ANSI C specific. + */ +#if defined(DIAGNOSTIC) && defined(__STDC__) +#define DB_ASSERT(env, e) \ + ((e) ? (void)0 : __db_assert(env, #e, __FILE__, __LINE__)) +#else +#define DB_ASSERT(env, e) NOP_STATEMENT +#endif + +/* + * "Shut that bloody compiler up!" + * + * Unused, or not-used-yet variable. We need to write and then read the + * variable, some compilers are too bloody clever by half. + */ +#define COMPQUIET(n, v) do { \ + (n) = (v); \ + (n) = (n); \ +} while (0) + +/* + * Purify and other run-time tools complain about uninitialized reads/writes + * of structure fields whose only purpose is padding, as well as when heap + * memory that was never initialized is written to disk. + */ +#ifdef UMRW +#define UMRW_SET(v) (v) = 0 +#else +#define UMRW_SET(v) NOP_STATEMENT +#endif + +/* + * Errors are in one of two areas: a Berkeley DB error, or a system-level + * error. We use db_strerror to translate the former and __os_strerror to + * translate the latter. + */ +typedef enum { + DB_ERROR_NOT_SET=0, + DB_ERROR_SET=1, + DB_ERROR_SYSTEM=2 +} db_error_set_t; + +/* + * Message handling. Use a macro instead of a function because va_list + * references to variadic arguments cannot be reset to the beginning of the + * variadic argument list (and then rescanned), by functions other than the + * original routine that took the variadic list of arguments. + */ +#if defined(STDC_HEADERS) || defined(__cplusplus) +#define DB_REAL_ERR(dbenv, error, error_set, app_call, fmt) { \ + va_list __ap; \ + \ + /* Call the application's callback function, if specified. */ \ + va_start(__ap, fmt); \ + if ((dbenv) != NULL && (dbenv)->db_errcall != NULL) \ + __db_errcall(dbenv, error, error_set, fmt, __ap); \ + va_end(__ap); \ + \ + /* \ + * If the application specified a file descriptor, write to it. \ + * If we wrote to neither the application's callback routine or \ + * its file descriptor, and it's an application error message \ + * using {DbEnv,Db}.{err,errx} or the application has never \ + * configured an output channel, default by writing to stderr. \ + */ \ + va_start(__ap, fmt); \ + if ((dbenv) == NULL || \ + (dbenv)->db_errfile != NULL || \ + ((dbenv)->db_errcall == NULL && \ + ((app_call) || F_ISSET((dbenv)->env, ENV_NO_OUTPUT_SET)))) \ + __db_errfile(dbenv, error, error_set, fmt, __ap); \ + va_end(__ap); \ +} +#else +#define DB_REAL_ERR(dbenv, error, error_set, app_call, fmt) { \ + va_list __ap; \ + \ + /* Call the application's callback function, if specified. */ \ + va_start(__ap); \ + if ((dbenv) != NULL && (dbenv)->db_errcall != NULL) \ + __db_errcall(dbenv, error, error_set, fmt, __ap); \ + va_end(__ap); \ + \ + /* \ + * If the application specified a file descriptor, write to it. \ + * If we wrote to neither the application's callback routine or \ + * its file descriptor, and it's an application error message \ + * using {DbEnv,Db}.{err,errx} or the application has never \ + * configured an output channel, default by writing to stderr. \ + */ \ + va_start(__ap); \ + if ((dbenv) == NULL || \ + (dbenv)->db_errfile != NULL || \ + ((dbenv)->db_errcall == NULL && \ + ((app_call) || F_ISSET((dbenv)->env, ENV_NO_OUTPUT_SET)))) \ + __db_errfile(env, error, error_set, fmt, __ap); \ + va_end(__ap); \ +} +#endif +#if defined(STDC_HEADERS) || defined(__cplusplus) +#define DB_REAL_MSG(dbenv, fmt) { \ + va_list __ap; \ + \ + /* Call the application's callback function, if specified. */ \ + va_start(__ap, fmt); \ + if ((dbenv) != NULL && (dbenv)->db_msgcall != NULL) \ + __db_msgcall(dbenv, fmt, __ap); \ + va_end(__ap); \ + \ + /* \ + * If the application specified a file descriptor, write to it. \ + * If we wrote to neither the application's callback routine or \ + * its file descriptor, write to stdout. \ + */ \ + va_start(__ap, fmt); \ + if ((dbenv) == NULL || \ + (dbenv)->db_msgfile != NULL || \ + (dbenv)->db_msgcall == NULL) { \ + __db_msgfile(dbenv, fmt, __ap); \ + } \ + va_end(__ap); \ +} +#else +#define DB_REAL_MSG(dbenv, fmt) { \ + va_list __ap; \ + \ + /* Call the application's callback function, if specified. */ \ + va_start(__ap); \ + if ((dbenv) != NULL && (dbenv)->db_msgcall != NULL) \ + __db_msgcall(dbenv, fmt, __ap); \ + va_end(__ap); \ + \ + /* \ + * If the application specified a file descriptor, write to it. \ + * If we wrote to neither the application's callback routine or \ + * its file descriptor, write to stdout. \ + */ \ + va_start(__ap); \ + if ((dbenv) == NULL || \ + (dbenv)->db_msgfile != NULL || \ + (dbenv)->db_msgcall == NULL) { \ + __db_msgfile(dbenv, fmt, __ap); \ + } \ + va_end(__ap); \ +} +#endif + +/* + * Debugging macro to log operations. + * If DEBUG_WOP is defined, log operations that modify the database. + * If DEBUG_ROP is defined, log operations that read the database. + * + * D dbp + * T txn + * O operation (string) + * K key + * A data + * F flags + */ +#define LOG_OP(C, T, O, K, A, F) { \ + DB_LSN __lsn; \ + DBT __op; \ + if (DBC_LOGGING((C))) { \ + memset(&__op, 0, sizeof(__op)); \ + __op.data = O; \ + __op.size = (u_int32_t)strlen(O) + 1; \ + (void)__db_debug_log((C)->env, T, &__lsn, 0, \ + &__op, (C)->dbp->log_filename->id, K, A, F); \ + } \ +} +#ifdef DEBUG_ROP +#define DEBUG_LREAD(C, T, O, K, A, F) LOG_OP(C, T, O, K, A, F) +#else +#define DEBUG_LREAD(C, T, O, K, A, F) +#endif +#ifdef DEBUG_WOP +#define DEBUG_LWRITE(C, T, O, K, A, F) LOG_OP(C, T, O, K, A, F) +#else +#define DEBUG_LWRITE(C, T, O, K, A, F) +#endif + +/* + * Hook for testing recovery at various places in the create/delete paths. + * Hook for testing subdb locks. + */ +#if CONFIG_TEST +#define DB_TEST_SUBLOCKS(env, flags) do { \ + if ((env)->test_abort == DB_TEST_SUBDB_LOCKS) \ + (flags) |= DB_LOCK_NOWAIT; \ +} while (0) + +#define DB_ENV_TEST_RECOVERY(env, val, ret, name) do { \ + int __ret; \ + PANIC_CHECK((env)); \ + if ((env)->test_copy == (val)) { \ + /* COPY the FILE */ \ + if ((__ret = __db_testcopy((env), NULL, (name))) != 0) \ + (ret) = __env_panic((env), __ret); \ + } \ + if ((env)->test_abort == (val)) { \ + /* ABORT the TXN */ \ + (env)->test_abort = 0; \ + (ret) = EINVAL; \ + goto db_tr_err; \ + } \ +} while (0) + +#define DB_TEST_RECOVERY(dbp, val, ret, name) do { \ + ENV *__env = (dbp)->env; \ + int __ret; \ + PANIC_CHECK(__env); \ + if (__env->test_copy == (val)) { \ + /* Copy the file. */ \ + if (F_ISSET((dbp), \ + DB_AM_OPEN_CALLED) && (dbp)->mpf != NULL) \ + (void)__db_sync(dbp); \ + if ((__ret = \ + __db_testcopy(__env, (dbp), (name))) != 0) \ + (ret) = __env_panic(__env, __ret); \ + } \ + if (__env->test_abort == (val)) { \ + /* Abort the transaction. */ \ + __env->test_abort = 0; \ + (ret) = EINVAL; \ + goto db_tr_err; \ + } \ +} while (0) + +#define DB_TEST_RECOVERY_LABEL db_tr_err: + +#define DB_TEST_SET(field, val) do { \ + if (field == (val)) \ + goto db_tr_err; \ +} while (0) + +#define DB_TEST_WAIT(env, val) \ + if ((val) != 0) \ + __os_yield((env), (u_long)(val), 0) +#else +#define DB_TEST_SUBLOCKS(env, flags) +#define DB_ENV_TEST_RECOVERY(env, val, ret, name) +#define DB_TEST_RECOVERY(dbp, val, ret, name) +#define DB_TEST_RECOVERY_LABEL +#define DB_TEST_SET(env, val) +#define DB_TEST_WAIT(env, val) +#endif + +#if defined(__cplusplus) +} +#endif +#endif /* !_DB_DEBUG_H_ */ diff -r 000000000000 -r a1985f14b030 src/dbinc/fop.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/dbinc/fop.h Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,54 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 2001, 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + * $Id$ + */ + +#ifndef _DB_FOP_H_ +#define _DB_FOP_H_ + +#if defined(__cplusplus) +extern "C" { +#endif + +#define MAKE_INMEM(D) do { \ + F_SET((D), DB_AM_INMEM); \ + (void)__memp_set_flags((D)->mpf, DB_MPOOL_NOFILE, 1); \ +} while (0) + +#define CLR_INMEM(D) do { \ + F_CLR((D), DB_AM_INMEM); \ + (void)__memp_set_flags((D)->mpf, DB_MPOOL_NOFILE, 0); \ +} while (0) + +#include "dbinc_auto/fileops_auto.h" +#include "dbinc_auto/fileops_ext.h" + +#if defined(__cplusplus) +} +#endif +#endif /* !_DB_FOP_H_ */ diff -r 000000000000 -r a1985f14b030 src/dbinc/globals.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/dbinc/globals.h Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,127 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 1996, 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + * $Id$ + */ + +#ifndef _DB_GLOBALS_H_ +#define _DB_GLOBALS_H_ + +#if defined(__cplusplus) +extern "C" { +#endif + +/******************************************************* + * Global variables. + * + * Held in a single structure to minimize the name-space pollution. + *******************************************************/ +#ifdef HAVE_VXWORKS +#include "semLib.h" +#endif + +typedef struct __db_globals { +#ifdef HAVE_VXWORKS + u_int32_t db_global_init; /* VxWorks: inited */ + SEM_ID db_global_lock; /* VxWorks: global semaphore */ +#endif +#ifdef DB_WIN32 +#ifndef DB_WINCE + /* + * These fields are used by the Windows implementation of mutexes. + * Usually they are initialized by the first DB API call to lock a + * mutex. If that would result in the mutexes being inaccessible by + * other threads (e.g., ones which have lesser privileges) the + * application may first call db_env_set_win_security(). + */ + SECURITY_DESCRIPTOR win_default_sec_desc; + SECURITY_ATTRIBUTES win_default_sec_attr; +#endif + SECURITY_ATTRIBUTES *win_sec_attr; +#endif + + /* TAILQ_HEAD(__envq, __dbenv) envq; */ + struct __envq { + struct __env *tqh_first; + struct __env **tqh_last; + } envq; + + char *db_line; /* DB display string. */ + + char error_buf[40]; /* Error string buffer. */ + + int uid_init; /* srand set in UID generator */ + + u_long rand_next; /* rand/srand value */ + + u_int32_t fid_serial; /* file id counter */ + + int db_errno; /* Errno value if not available */ + + size_t num_active_pids; /* number of entries in active_pids */ + + size_t size_active_pids; /* allocated size of active_pids */ + + pid_t *active_pids; /* array active pids */ + + char *saved_errstr; /* saved error string from backup */ + + /* Underlying OS interface jump table.*/ + void (*j_assert) __P((const char *, const char *, int)); + int (*j_close) __P((int)); + void (*j_dirfree) __P((char **, int)); + int (*j_dirlist) __P((const char *, char ***, int *)); + int (*j_exists) __P((const char *, int *)); + void (*j_free) __P((void *)); + int (*j_fsync) __P((int)); + int (*j_ftruncate) __P((int, off_t)); + int (*j_ioinfo) __P((const char *, + int, u_int32_t *, u_int32_t *, u_int32_t *)); + void *(*j_malloc) __P((size_t)); + int (*j_file_map) __P((DB_ENV *, char *, size_t, int, void **)); + int (*j_file_unmap) __P((DB_ENV *, void *)); + int (*j_open) __P((const char *, int, ...)); + ssize_t (*j_pread) __P((int, void *, size_t, off_t)); + ssize_t (*j_pwrite) __P((int, const void *, size_t, off_t)); + ssize_t (*j_read) __P((int, void *, size_t)); + void *(*j_realloc) __P((void *, size_t)); + int (*j_region_map) __P((DB_ENV *, char *, size_t, int *, void **)); + int (*j_region_unmap) __P((DB_ENV *, void *)); + int (*j_rename) __P((const char *, const char *)); + int (*j_seek) __P((int, off_t, int)); + int (*j_unlink) __P((const char *)); + ssize_t (*j_write) __P((int, const void *, size_t)); + int (*j_yield) __P((u_long, u_long)); +} DB_GLOBALS; + +extern DB_GLOBALS __db_global_values; +#define DB_GLOBAL(v) __db_global_values.v + +#if defined(__cplusplus) +} +#endif +#endif /* !_DB_GLOBALS_H_ */ diff -r 000000000000 -r a1985f14b030 src/dbinc/hash.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/dbinc/hash.h Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,195 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 1996, 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +/* + * Copyright (c) 1990, 1993, 1994 + * Margo Seltzer. All rights reserved. + */ +/* + * Copyright (c) 1990, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Margo Seltzer. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $Id$ + */ + +#ifndef _DB_HASH_H_ +#define _DB_HASH_H_ + +#if defined(__cplusplus) +extern "C" { +#endif + +/* Hash internal structure. */ +typedef struct hash_t { + db_pgno_t meta_pgno; /* Page number of the meta data page. */ + u_int32_t revision; /* Revision of subdb metadata. */ + u_int32_t h_ffactor; /* Fill factor. */ + u_int32_t h_nelem; /* Number of elements. */ + /* Hash and compare functions. */ + u_int32_t (*h_hash) __P((DB *, const void *, u_int32_t)); + int (*h_compare) __P((DB *, const DBT *, const DBT *)); +} HASH; + +/* Cursor structure definitions. */ +typedef struct cursor_t { + /* struct __dbc_internal */ + __DBC_INTERNAL + + /* Hash private part */ + + /* Per-thread information */ + DB_LOCK hlock; /* Metadata page lock. */ + HMETA *hdr; /* Pointer to meta-data page. */ + PAGE *split_buf; /* Temporary buffer for splits. */ + + /* Hash cursor information */ + db_pgno_t bucket; /* Bucket we are traversing. */ + db_pgno_t lbucket; /* Bucket for which we are locked. */ + db_indx_t dup_off; /* Offset within a duplicate set. */ + db_indx_t dup_len; /* Length of current duplicate. */ + db_indx_t dup_tlen; /* Total length of duplicate entry. */ + u_int32_t seek_size; /* Number of bytes we need for add. */ + db_pgno_t seek_found_page;/* Page on which we can insert. */ + db_indx_t seek_found_indx;/* Insert position for item. */ + u_int32_t order; /* Relative order among deleted curs. */ + +#define H_CONTINUE 0x0001 /* Join--search strictly fwd for data */ +#define H_CONTRACT 0x0002 /* Table contracted.*/ +#define H_DELETED 0x0004 /* Cursor item is deleted. */ +#define H_DUPONLY 0x0008 /* Dups only; do not change key. */ +#define H_EXPAND 0x0010 /* Table expanded. */ +#define H_ISDUP 0x0020 /* Cursor is within duplicate set. */ +#define H_NEXT_NODUP 0x0040 /* Get next non-dup entry. */ +#define H_NOMORE 0x0080 /* No more entries in bucket. */ +#define H_OK 0x0100 /* Request succeeded. */ + u_int32_t flags; +} HASH_CURSOR; + +/* Test string. */ +#define CHARKEY "%$sniglet^&" + +/* Overflow management */ +/* + * The spares table indicates the page number at which each doubling begins. + * From this page number we subtract the number of buckets already allocated + * so that we can do a simple addition to calculate the page number here. + */ +#define BS_TO_PAGE(bucket, spares) \ + ((bucket) + (spares)[__db_log2((bucket) + 1)]) +#define BUCKET_TO_PAGE(I, B) (BS_TO_PAGE((B), (I)->hdr->spares)) + +/* Constraints about much data goes on a page. */ + +#define MINFILL 4 +#define ISBIG(I, N) (((N) > ((I)->hdr->dbmeta.pagesize / MINFILL)) ? 1 : 0) + +/* Shorthands for accessing structure */ +#define NDX_INVALID 0xFFFF +#define BUCKET_INVALID 0xFFFFFFFF + +/* On page duplicates are stored as a string of size-data-size triples. */ +#define DUP_SIZE(len) ((len) + 2 * sizeof(db_indx_t)) + +/* Log messages types (these are subtypes within a record type) */ +/* These bits are obsolete and are only needed for down rev logs. */ +#define PAIR_KEYMASK 0x1 +#define PAIR_DATAMASK 0x2 +#define PAIR_DUPMASK 0x4 +#define PAIR_MASK 0xf +#define PAIR_ISKEYBIG(N) (N & PAIR_KEYMASK) +#define PAIR_ISDATABIG(N) (N & PAIR_DATAMASK) +#define PAIR_ISDATADUP(N) (N & PAIR_DUPMASK) +#define OPCODE_OF(N) (N & ~PAIR_MASK) + +/* Operators for hash recover routines. */ +#define PUTPAIR 0x20 +#define DELPAIR 0x30 +#define PUTOVFL 0x40 +#define DELOVFL 0x50 +#define HASH_UNUSED1 0x60 +#define HASH_UNUSED2 0x70 +#define SPLITOLD 0x80 +#define SPLITNEW 0x90 +#define SORTPAGE 0x100 + +/* Flags to control behavior of __ham_del_pair */ +#define HAM_DEL_NO_CURSOR 0x01 /* Don't do any cursor adjustment */ +#define HAM_DEL_NO_RECLAIM 0x02 /* Don't reclaim empty pages */ +/* Just delete onpage items (even if they are references to off-page items). */ +#define HAM_DEL_IGNORE_OFFPAGE 0x04 + +typedef enum { + DB_HAM_CURADJ_DEL = 1, + DB_HAM_CURADJ_ADD = 2, + DB_HAM_CURADJ_ADDMOD = 3, + DB_HAM_CURADJ_DELMOD = 4 +} db_ham_curadj; + +typedef enum { + DB_HAM_CHGPG = 1, + DB_HAM_DELFIRSTPG = 2, + DB_HAM_DELMIDPG = 3, + DB_HAM_DELLASTPG = 4, + DB_HAM_DUP = 5, + DB_HAM_SPLIT = 6 +} db_ham_mode; + +#if defined(__cplusplus) +} +#endif + +#include "dbinc_auto/hash_auto.h" +#include "dbinc_auto/hash_ext.h" +#include "dbinc/db_am.h" +#endif /* !_DB_HASH_H_ */ diff -r 000000000000 -r a1985f14b030 src/dbinc/heap.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/dbinc/heap.h Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,81 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 2010, 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +#ifndef _DB_HEAP_H_ +#define _DB_HEAP_H_ + +#if defined(__cplusplus) +extern "C" { +#endif + +/* Forward structure declarations. */ +struct __heap; typedef struct __heap HEAP; +struct __heap_cursor; typedef struct __heap_cursor HEAP_CURSOR; + +/* + * The in-memory, per-heap data structure. + */ +struct __heap { /* Heap access method. */ + + u_int32_t gbytes; /* Initial heap size. */ + u_int32_t bytes; /* Initial heap size. */ + u_int32_t region_size; /* Size of each region. */ + + db_pgno_t curregion; /* The region of the next insert. */ + db_pgno_t maxpgno; /* Maximum page number of a fixed size heap. */ + int curpgindx; /* The last used offset in the region's space bitmap. */ +}; + +struct __heap_cursor { + /* struct __dbc_internal */ + __DBC_INTERNAL + + /* Heap private part */ + + u_int32_t flags; +}; + +#define HEAP_PG_FULL 3 /* No space on page. */ +#define HEAP_PG_GT66 2 /* Page greater than 66% full */ +#define HEAP_PG_GT33 1 /* Page greater than 33% full */ +#define HEAP_PG_LT33 0 /* Page less than 33% full */ + +#define HEAP_PG_FULL_PCT 5 /* Less than 5% of page is free. */ +#define HEAP_PG_GT66_PCT 33 /* Less than 33% of page is free. */ +#define HEAP_PG_GT33_PCT 66 /* Less than 66% of page is free. */ + +#if defined(__cplusplus) +} +#endif + +#include "dbinc_auto/heap_auto.h" +#include "dbinc_auto/heap_ext.h" +#include "dbinc/db_am.h" +#endif + + diff -r 000000000000 -r a1985f14b030 src/dbinc/hmac.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/dbinc/hmac.h Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,61 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 1996, 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + * $Id$ + */ + +#ifndef _DB_HMAC_H_ +#define _DB_HMAC_H_ + +#if defined(__cplusplus) +extern "C" { +#endif + +/* + * Algorithm specific information. + */ +/* + * SHA1 checksumming + */ +typedef struct { + u_int32_t state[5]; + u_int32_t count[2]; + unsigned char buffer[64]; +} SHA1_CTX; + +/* + * AES assumes the SHA1 checksumming (also called MAC) + */ +#define DB_MAC_MAGIC "mac derivation key magic value" +#define DB_ENC_MAGIC "encryption and decryption key value magic" + +#if defined(__cplusplus) +} +#endif + +#include "dbinc_auto/hmac_ext.h" +#endif /* !_DB_HMAC_H_ */ diff -r 000000000000 -r a1985f14b030 src/dbinc/lock.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/dbinc/lock.h Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,348 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 1996, 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + * $Id$ + */ + +#ifndef _DB_LOCK_H_ +#define _DB_LOCK_H_ + +#if defined(__cplusplus) +extern "C" { +#endif + +#define DB_LOCK_DEFAULT_N 1000 /* Default # of locks in region. */ + +/* + * The locker id space is divided between the transaction manager and the lock + * manager. Lock IDs start at 1 and go to DB_LOCK_MAXID. Txn IDs start at + * DB_LOCK_MAXID + 1 and go up to TXN_MAXIMUM. + */ +#define DB_LOCK_INVALIDID 0 +#define DB_LOCK_MAXID 0x7fffffff + +/* + * A locker's deadlock resolution priority is stored as a 32 bit unsigned + * integer. The maximum priority is DB_LOCK_MAXPRIORITY and the default + * priority is DB_LOCK_DEFPRIORITY. + */ +#define DB_LOCK_DEFPRIORITY 100 +#define DB_LOCK_MAXPRIORITY UINT32_MAX + +/* + * Out of band value for a lock. Locks contain an offset into a lock region, + * so we use an invalid region offset to indicate an invalid or unset lock. + */ +#define LOCK_INVALID INVALID_ROFF +#define LOCK_ISSET(lock) ((lock).off != LOCK_INVALID) +#define LOCK_INIT(lock) ((lock).off = LOCK_INVALID) + +/* + * Macro to identify a write lock for the purpose of counting locks + * for the NUMWRITES option to deadlock detection. + */ +#define IS_WRITELOCK(m) \ + ((m) == DB_LOCK_WRITE || (m) == DB_LOCK_WWRITE || \ + (m) == DB_LOCK_IWRITE || (m) == DB_LOCK_IWR) + +/* + * Macros to lock/unlock the lock region as a whole. Mostly used for + * initialization. + */ +#define LOCK_REGION_LOCK(env) \ + MUTEX_LOCK(env, ((DB_LOCKREGION *) \ + (env)->lk_handle->reginfo.primary)->mtx_region) +#define LOCK_REGION_UNLOCK(env) \ + MUTEX_UNLOCK(env, ((DB_LOCKREGION *) \ + (env)->lk_handle->reginfo.primary)->mtx_region) + +/* + * DB_LOCKREGION -- + * The lock shared region. + */ + +typedef struct __db_lockregion { /* SHARED */ + db_mutex_t mtx_region; /* Region mutex. */ + + u_int32_t need_dd; /* flag for deadlock detector */ + u_int32_t detect; /* run dd on every conflict */ + db_timespec next_timeout; /* next time to expire a lock */ + db_mutex_t mtx_dd; /* mutex for lock object dd list. */ + db_mutex_t mtx_lockers; /* mutex for locker allocation. */ + SH_TAILQ_HEAD(__dobj) dd_objs; /* objects with waiters */ + /* free locker header */ + roff_t locker_mem_off; /* block memory for lockers */ + SH_TAILQ_HEAD(__flocker) free_lockers; + SH_TAILQ_HEAD(__lkrs) lockers; /* list of lockers */ + + db_timeout_t lk_timeout; /* timeout for locks. */ + db_timeout_t tx_timeout; /* timeout for txns. */ + + u_int32_t locker_t_size; /* size of locker hash table */ + u_int32_t object_t_size; /* size of object hash table */ + u_int32_t part_t_size; /* number of partitions */ + + roff_t conf_off; /* offset of conflicts array */ + roff_t obj_off; /* offset of object hash table */ + roff_t part_off; /* offset of partition array */ + roff_t stat_off; /* offset to object hash stats */ + roff_t locker_off; /* offset of locker hash table */ + + u_int32_t lock_id; /* Current lock(er) id to allocate. */ + u_int32_t cur_maxid; /* Current max lock(er) id. */ + u_int32_t nlockers; /* Current number of lockers. */ + int32_t nmodes; /* Number of modes in conflict table. */ + DB_LOCK_STAT stat; /* stats about locking. */ +} DB_LOCKREGION; + +/* + * Since we will store DBTs in shared memory, we need the equivalent of a + * DBT that will work in shared memory. + */ +typedef struct __sh_dbt { /* SHARED */ + u_int32_t size; /* Byte length. */ + roff_t off; /* Region offset. */ +} SH_DBT; + +#define SH_DBT_PTR(p) ((void *)(((u_int8_t *)(p)) + (p)->off)) + +/* + * Object structures; these live in the object hash table. + */ +typedef struct __db_lockobj { /* SHARED */ + u_int32_t indx; /* Hash index of this object. */ + u_int32_t generation; /* Generation of this object. */ + SH_DBT lockobj; /* Identifies object locked. */ + SH_TAILQ_ENTRY links; /* Links for free list or hash list. */ + SH_TAILQ_ENTRY dd_links; /* Links for dd list. */ + SH_TAILQ_HEAD(__waitl) waiters; /* List of waiting locks. */ + SH_TAILQ_HEAD(__holdl) holders; /* List of held locks. */ + /* Declare room in the object to hold + * typical DB lock structures so that + * we do not have to allocate them from + * shalloc at run-time. */ + u_int8_t objdata[sizeof(struct __db_ilock)]; +} DB_LOCKOBJ; + +/* + * Locker structures; these live in the locker hash table. + */ +struct __db_locker { /* SHARED */ + u_int32_t id; /* Locker id. */ + + pid_t pid; /* Process owning locker ID */ + db_threadid_t tid; /* Thread owning locker ID */ + db_mutex_t mtx_locker; /* Mutex to block on. */ + + u_int32_t dd_id; /* Deadlock detector id. */ + + u_int32_t nlocks; /* Number of locks held. */ + u_int32_t nwrites; /* Number of write locks held. */ + u_int32_t priority; /* Deadlock resolution priority. */ + u_int32_t nrequest; /* number of requests. */ + + roff_t master_locker; /* Locker of master transaction. */ + roff_t parent_locker; /* Parent of this child. */ + SH_LIST_HEAD(_child) child_locker; /* List of descendant txns; + only used in a "master" + txn. */ + SH_LIST_ENTRY child_link; /* Links transactions in the family; + elements of the child_locker + list. */ + SH_TAILQ_ENTRY links; /* Links for free and hash list. */ + SH_TAILQ_ENTRY ulinks; /* Links in-use list. */ + SH_LIST_HEAD(_held) heldby; /* Locks held by this locker. */ + db_timespec lk_expire; /* When current lock expires. */ + db_timespec tx_expire; /* When this txn expires. */ + db_timeout_t lk_timeout; /* How long do we let locks live. */ + +#define DB_LOCKER_DIRTY 0x0001 /* Has write locks. */ +#define DB_LOCKER_INABORT 0x0002 /* Is aborting, don't abort again. */ +#define DB_LOCKER_TIMEOUT 0x0004 /* Has timeout set. */ +#define DB_LOCKER_FAMILY_LOCKER 0x0008 /* Part of a family of lockers. */ +#define DB_LOCKER_HANDLE_LOCKER 0x0010 /* Not associated with a thread. */ + u_int32_t flags; +}; + +/* + * Map a hash index into a partition. + */ +#define LOCK_PART(reg, ndx) (ndx % (reg)->part_t_size) + +/* + * Structure that contains information about a lock table partition. + */ +typedef struct __db_lockpart{ /* SHARED */ + db_mutex_t mtx_part; /* mutex for partition*/ + /* free lock header */ + SH_TAILQ_HEAD(__flock) free_locks; + /* free obj header */ + SH_TAILQ_HEAD(__fobj) free_objs; + roff_t lock_mem_off; /* block memory for locks */ + roff_t lockobj_mem_off;/* block memory for lockobjs */ +#ifdef HAVE_STATISTICS + DB_LOCK_PSTAT part_stat; /* Partition stats. */ +#endif +} DB_LOCKPART; + +#define FREE_LOCKS(lt, part) ((lt)->part_array[part].free_locks) +#define FREE_OBJS(lt, part) ((lt)->part_array[part].free_objs) + +/* + * DB_LOCKTAB -- + * The primary library lock data structure (i.e., the one referenced + * by the environment, as opposed to the internal one laid out in the region.) + */ +struct __db_locktab { + ENV *env; /* Environment. */ + REGINFO reginfo; /* Region information. */ + u_int8_t *conflicts; /* Pointer to conflict matrix. */ + DB_LOCKPART *part_array; /* Beginning of partition array. */ +#ifdef HAVE_STATISTICS + DB_LOCK_HSTAT *obj_stat; /* Object hash stats array. */ +#endif + DB_HASHTAB *obj_tab; /* Beginning of object hash table. */ + DB_HASHTAB *locker_tab; /* Beginning of locker hash table. */ +}; + +/* + * Test for conflicts. + * + * Cast HELD and WANTED to ints, they are usually db_lockmode_t enums. + */ +#define CONFLICTS(T, R, HELD, WANTED) \ + (T)->conflicts[((int)HELD) * (R)->nmodes + ((int)WANTED)] + +#define OBJ_LINKS_VALID(L) ((L)->links.stqe_prev != -1) + +struct __db_lock { /* SHARED */ + /* + * Wait on mutex to wait on lock. You reference your own mutex with + * ID 0 and others reference your mutex with ID 1. + */ + db_mutex_t mtx_lock; + + roff_t holder; /* Who holds this lock. */ + u_int32_t gen; /* Generation count. */ + SH_TAILQ_ENTRY links; /* Free or holder/waiter list. */ + SH_LIST_ENTRY locker_links; /* List of locks held by a locker. */ + u_int32_t refcount; /* Reference count the lock. */ + db_lockmode_t mode; /* What sort of lock. */ + roff_t obj; /* Relative offset of object struct. */ + u_int32_t indx; /* Hash index of this object. */ + db_status_t status; /* Status of this lock. */ +}; + +/* + * Flag values for __lock_put_internal: + * DB_LOCK_DOALL: Unlock all references in this lock (instead of only 1). + * DB_LOCK_FREE: Free the lock (used in checklocker). + * DB_LOCK_NOPROMOTE: Don't bother running promotion when releasing locks + * (used by __lock_put_internal). + * DB_LOCK_UNLINK: Remove from the locker links (used in checklocker). + * Make sure that these do not conflict with the interface flags because + * we pass some of those around. + */ +#define DB_LOCK_DOALL 0x010000 +#define DB_LOCK_FREE 0x040000 +#define DB_LOCK_NOPROMOTE 0x080000 +#define DB_LOCK_UNLINK 0x100000 +#define DB_LOCK_ONEWAITER 0x400000 + +/* + * Macros to get/release different types of mutexes. + */ +/* + * Operations on lock objects must be protected by a mutex, either on their + * partition or on the lock region. Lock structures associated with that + * object are protected as well. Each partition has a free list of objects + * and lock structures protected by that mutex. We want to avoid getting + * multiple mutexes, particularly in __lock_vec, when there is only a + * single partition. If there is only one partition, then all the calls + * to LOCK_SYSTEM_LOCK(UNLOCK) actually acquire(release) a lock system + * wide mutex and MUTEX_LOCK(UNLOCK)_PARTITION are no-ops. If the number + * of partitions is greater than one, then LOCK_SYSTEM_LOCK(UNLOCK) is a + * no-op, and MUTEX_LOCK(UNLOCK)_PARTITION acquire a mutex on a particular + * partition of the lock table. + */ +#define LOCK_SYSTEM_LOCK(lt, reg) do { \ + if ((reg)->part_t_size == 1) \ + MUTEX_LOCK((lt)->env, (reg)->mtx_region); \ +} while (0) +#define LOCK_SYSTEM_UNLOCK(lt, reg) do { \ + if ((reg)->part_t_size == 1) \ + MUTEX_UNLOCK((lt)->env, (reg)->mtx_region); \ +} while (0) +#define MUTEX_LOCK_PARTITION(lt, reg, p) do { \ + if ((reg)->part_t_size != 1) \ + MUTEX_LOCK((lt)->env, (lt)->part_array[p].mtx_part); \ +} while (0) +#define MUTEX_UNLOCK_PARTITION(lt, reg, p) do { \ + if ((reg)->part_t_size != 1) \ + MUTEX_UNLOCK((lt)->env, (lt)->part_array[p].mtx_part); \ +} while (0) + +#define OBJECT_LOCK(lt, reg, obj, ndx) do { \ + ndx = __lock_ohash(obj) % (reg)->object_t_size; \ + MUTEX_LOCK_PARTITION(lt, reg, LOCK_PART(reg, ndx)); \ +} while (0) + +#define OBJECT_LOCK_NDX(lt, reg, ndx) \ + MUTEX_LOCK_PARTITION(lt, reg, LOCK_PART(reg, ndx)); + +#define OBJECT_UNLOCK(lt, reg, ndx) \ + MUTEX_UNLOCK_PARTITION(lt, reg, LOCK_PART(reg, ndx)); + +/* + * Protect the object deadlock detector queue and the locker allocation + * and active queues + */ +#define LOCK_DD(env, region) \ + MUTEX_LOCK(env, (region)->mtx_dd) +#define UNLOCK_DD(env, region) \ + MUTEX_UNLOCK(env, (region)->mtx_dd) +#define LOCK_LOCKERS(env, region) \ + MUTEX_LOCK(env, (region)->mtx_lockers) +#define UNLOCK_LOCKERS(env, region) \ + MUTEX_UNLOCK(env, (region)->mtx_lockers) + +/* + * __lock_locker_hash -- + * Hash function for entering lockers into the locker hash table. + * Since these are simply 32-bit unsigned integers at the moment, + * just return the locker value. + */ +#define __lock_locker_hash(locker) (locker) +#define LOCKER_HASH(lt, reg, locker, ndx) \ + ndx = __lock_locker_hash(locker) % (reg)->locker_t_size; + +#if defined(__cplusplus) +} +#endif + +#include "dbinc_auto/lock_ext.h" +#endif /* !_DB_LOCK_H_ */ diff -r 000000000000 -r a1985f14b030 src/dbinc/log.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/dbinc/log.h Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,485 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 1996, 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + * $Id$ + */ + +#ifndef _DB_LOG_H_ +#define _DB_LOG_H_ + +#include "dbinc/db_swap.h" + +#if defined(__cplusplus) +extern "C" { +#endif + +/******************************************************* + * DBREG: + * The DB file register code keeps track of open files. It's stored + * in the log subsystem's shared region, and so appears in the log.h + * header file, but is logically separate. + * The dbp may not be open if we are recovering the abort of a create. + *******************************************************/ +/* + * The per-process table that maps log file-id's to DB structures. + */ +typedef struct __db_entry { + DB *dbp; /* Open dbp for this file id. */ + int deleted; /* File was not found during open. */ +} DB_ENTRY; + +/* + * FNAME -- + * File name and id. + */ +struct __fname { + SH_TAILQ_ENTRY q; /* File name queue. */ + + pid_t pid; /* Process that owns this. */ + int32_t id; /* Logging file id. */ + int32_t old_id; /* Saved logging file id. */ + DBTYPE s_type; /* Saved DB type. */ + + roff_t fname_off; /* File name offset. */ + roff_t dname_off; /* Database name offset. */ + db_pgno_t meta_pgno; /* Page number of the meta page. */ + u_int8_t ufid[DB_FILE_ID_LEN]; /* Unique file id. */ + + u_int32_t create_txnid; /* + * Txn ID of the DB create, stored so + * we can log it at register time. + */ + db_mutex_t mutex; /* mutex from db handle. */ + /* number of txn referencing + 1 for the db handle. */ + u_int32_t txn_ref; + +#define DB_FNAME_CLOSED 0x01 /* DBP was closed. */ +#define DB_FNAME_DURABLE 0x02 /* File is durable. */ +#define DB_FNAME_INMEM 0x04 /* File is in memory. */ +#define DB_FNAME_NOTLOGGED 0x08 /* Log of close failed. */ +#define DB_FNAME_RECOVER 0x10 /* File was opened by recovery code. */ +#define DB_FNAME_RESTORED 0x20 /* File may be in restored txn. */ +#define DB_FNAME_DBREG_MASK 0xf000 /* These bits come from DBREG below. */ + u_int32_t flags; +}; + +/* File open/close register log record opcodes. */ +#define DBREG_CHKPNT 1 /* Checkpoint: file name/id dump. */ +#define DBREG_CLOSE 2 /* File close. */ +#define DBREG_OPEN 3 /* File open. */ +#define DBREG_PREOPEN 4 /* Open in mpool only. */ +#define DBREG_RCLOSE 5 /* File close after recovery. */ +#define DBREG_REOPEN 6 /* Open for in-memory database. */ +#define DBREG_XCHKPNT 7 /* Checkpoint of exclusive file. */ +#define DBREG_XOPEN 8 /* File exclusive open. */ +#define DBREG_XREOPEN 9 /* File exclusive open in-memory. */ + +/* These bits are logged so db_printlog can handle page data. */ +#define DBREG_OP_MASK 0xf /* Opcode mask */ +#define DBREG_BIGEND 0x1000 /* Db Big endian. */ +#define DBREG_CHKSUM 0x2000 /* Db is checksummed. */ +#define DBREG_ENCRYPT 0x4000 /* Db is encrypted. */ +#define DBREG_EXCL 0x8000 /* Db is exclusive. */ + +/******************************************************* + * LOG: + * The log subsystem information. + *******************************************************/ +struct __hdr; typedef struct __hdr HDR; +struct __log; typedef struct __log LOG; +struct __log_persist; typedef struct __log_persist LOGP; + +#define LFPREFIX "log." /* Log file name prefix. */ +#define LFNAME "log.%010d" /* Log file name template. */ +#define LFNAME_V1 "log.%05d" /* Log file name template, rev 1. */ +#define IS_LOG_FILE(name) (strncmp(name, LFPREFIX, sizeof(LFPREFIX) - 1) == 0) + +#define LG_MAX_DEFAULT (10 * MEGABYTE) /* 10 MB. */ +#define LG_MAX_INMEM (256 * 1024) /* 256 KB. */ +#define LG_BSIZE_INMEM (1 * MEGABYTE) /* 1 MB. */ + +/* + * Allocate a few bytes under a power-of-two value. BDB doesn't care if it's + * a power-of-two or not, and requesting slightly under a power-of-two allows + * stupid allocators to avoid wasting space. + */ +#define LG_BASE_REGION_SIZE (130000) /* 128KB - 1072B */ +#define LG_BSIZE_DEFAULT (32000) /* 32 KB - 768B */ +#define LG_CURSOR_BUF_SIZE (32000) /* 32 KB - 768B */ + +/* + * DB_LOG + * Per-process log structure. + */ +struct __db_log { + /* + * These fields need to be protected for multi-threaded support. + */ + db_mutex_t mtx_dbreg; /* Mutex for thread protection. */ + + DB_ENTRY *dbentry; /* Recovery file-id mapping. */ +#define DB_GROW_SIZE 64 + int32_t dbentry_cnt; /* Entries. Grows by DB_GROW_SIZE. */ + + /* + * These fields are only accessed when the region lock is held, so + * they do not have to be protected by the thread lock as well. + */ + u_int32_t lfname; /* Log file "name". */ + DB_FH *lfhp; /* Log file handle. */ + time_t lf_timestamp; /* Log file timestamp. */ + + u_int8_t *bufp; /* Region buffer. */ + + /* These fields are not thread protected. */ + ENV *env; /* Environment */ + REGINFO reginfo; /* Region information. */ + +#define DBLOG_AUTOREMOVE 0x01 /* Autoremove log files. */ +#define DBLOG_DIRECT 0x02 /* Do direct I/O on the log. */ +#define DBLOG_DSYNC 0x04 /* Set OS_DSYNC on the log. */ +#define DBLOG_FORCE_OPEN 0x08 /* Force the DB open even if it appears + * to be deleted. */ +#define DBLOG_INMEMORY 0x10 /* Logging is in memory. */ +#define DBLOG_OPENFILES 0x20 /* Prepared files need to be open. */ +#define DBLOG_RECOVER 0x40 /* We are in recovery. */ +#define DBLOG_ZERO 0x80 /* Zero fill the log. */ +#define DBLOG_VERIFYING 0x100 /* The log is being verified. */ + u_int32_t flags; +}; + +/* + * HDR -- + * Log record header. + */ +struct __hdr { + u_int32_t prev; /* Previous offset. */ + u_int32_t len; /* Current length. */ + u_int8_t chksum[DB_MAC_KEY]; /* Current checksum. */ + u_int8_t iv[DB_IV_BYTES]; /* IV */ + u_int32_t orig_size; /* Original size of log record */ + /* !!! - 'size' is not written to log, must be last in hdr */ + size_t size; /* Size of header to use */ +}; + +/* + * LOG_HDR_SUM -- XOR in prev and len + * This helps avoids the race misreading the log while it + * it is being updated. + */ +#define LOG_HDR_SUM(crypto, hdr, sum) do { \ + if (crypto) { \ + ((u_int32_t *)sum)[0] ^= ((HDR *)hdr)->prev; \ + ((u_int32_t *)sum)[1] ^= ((HDR *)hdr)->len; \ + } else { \ + ((u_int32_t *)sum)[0] ^= \ + ((HDR *)hdr)->prev ^ ((HDR *)hdr)->len; \ + } \ +} while (0) + +/* + * We use HDR internally, and then when we write out, we write out + * prev, len, and then a 4-byte checksum if normal operation or + * a crypto-checksum and IV and original size if running in crypto + * mode. We must store the original size in case we pad. Set the + * size when we set up the header. We compute a DB_MAC_KEY size + * checksum regardless, but we can safely just use the first 4 bytes. + */ +#define HDR_NORMAL_SZ 12 +#define HDR_CRYPTO_SZ 12 + DB_MAC_KEY + DB_IV_BYTES + +struct __log_persist { + u_int32_t magic; /* DB_LOGMAGIC */ + u_int32_t version; /* DB_LOGVERSION */ + + u_int32_t log_size; /* Log file size. */ + u_int32_t notused; /* Historically the log file mode. */ +}; + +/* Macros to lock/unlock the log region as a whole. */ +#define LOG_SYSTEM_LOCK(env) \ + MUTEX_LOCK(env, ((LOG *) \ + (env)->lg_handle->reginfo.primary)->mtx_region) +#define LOG_SYSTEM_UNLOCK(env) \ + MUTEX_UNLOCK(env, ((LOG *) \ + (env)->lg_handle->reginfo.primary)->mtx_region) + +/* + * LOG -- + * Shared log region. One of these is allocated in shared memory, + * and describes the log. + */ +struct __log { /* SHARED */ + db_mutex_t mtx_region; /* Region mutex. */ + + db_mutex_t mtx_filelist; /* Mutex guarding file name list. */ + + LOGP persist; /* Persistent information. */ + + SH_TAILQ_HEAD(__fq1) fq; /* List of file names. */ + int32_t fid_max; /* Max fid allocated. */ + roff_t free_fid_stack; /* Stack of free file ids. */ + u_int32_t free_fids; /* Height of free fid stack. */ + u_int32_t free_fids_alloced; /* N free fid slots allocated. */ + + /* + * The lsn LSN is the file offset that we're about to write and which + * we will return to the user. + */ + DB_LSN lsn; /* LSN at current file offset. */ + + /* + * The f_lsn LSN is the LSN (returned to the user) that "owns" the + * first byte of the buffer. If the record associated with the LSN + * spans buffers, it may not reflect the physical file location of + * the first byte of the buffer. + */ + DB_LSN f_lsn; /* LSN of first byte in the buffer. */ + db_size_t b_off; /* Current offset in the buffer. */ + u_int32_t w_off; /* Current write offset in the file. */ + u_int32_t len; /* Length of the last record. */ + + DB_LSN active_lsn; /* Oldest active LSN in the buffer. */ + db_size_t a_off; /* Offset in the buffer of first active + file. */ + + /* + * The s_lsn LSN is the last LSN that we know is on disk, not just + * written, but synced. This field is protected by the flush mutex + * rather than by the region mutex. + */ + db_mutex_t mtx_flush; /* Mutex guarding flushing. */ + int32_t in_flush; /* Log flush in progress. */ + DB_LSN s_lsn; /* LSN of the last sync. */ + + DB_LOG_STAT stat; /* Log statistics. */ + + /* + * This timestamp is updated anytime someone unlinks log + * files. This can happen when calling __log_vtruncate + * or replication internal init when it unlinks log files. + * + * The timestamp is used so that other processes that might + * have file handles to log files know to close/reopen them + * so they're not potentially writing to now-removed files. + */ + time_t timestamp; /* Log trunc timestamp. */ + + /* + * !!! + * NOTE: the next group of fields are NOT protected by the log + * region lock. They are protected by REP->mtx_clientdb. If you + * need access to both, you must acquire REP->mtx_clientdb + * before acquiring the log region lock. + * + * The waiting_lsn is used by the replication system. It is the + * first LSN that we are holding without putting in the log, because + * we received one or more log records out of order. Associated with + * the waiting_lsn is the number of log records that we still have to + * receive before we decide that we should request it again. + * + * The max_wait_lsn is used to control retransmission in the face + * of dropped messages. If we are requesting all records from the + * current gap (i.e., chunk of the log that we are missing), then + * the max_wait_lsn contains the first LSN that we are known to have + * in the __db.rep.db. If we requested only a single record, then + * the max_wait_lsn has the LSN of that record we requested. + */ + /* BEGIN fields protected by rep->mtx_clientdb. */ + DB_LSN waiting_lsn; /* First log record after a gap. */ + DB_LSN verify_lsn; /* LSN we are waiting to verify. */ + DB_LSN prev_ckp; /* LSN of ckp preceding verify_lsn. */ + DB_LSN max_wait_lsn; /* Maximum LSN requested. */ + DB_LSN max_perm_lsn; /* Maximum PERMANENT LSN processed. */ + db_timespec max_lease_ts; /* Maximum Lease timestamp seen. */ + db_timespec wait_ts; /* Time to wait before requesting. */ + db_timespec rcvd_ts; /* Initial received time to wait. */ + db_timespec last_ts; /* Last time of insert in temp db. */ + /* + * The ready_lsn is also used by the replication system. It is the + * next LSN we expect to receive. It's normally equal to "lsn", + * except at the beginning of a log file, at which point it's set + * to the LSN of the first record of the new file (after the + * header), rather than to 0. + */ + DB_LSN ready_lsn; + /* + * The bulk_buf is used by replication for bulk transfer. While this + * is protected by REP->mtx_clientdb, this doesn't contend with the + * above fields because the above are used by clients and the bulk + * fields below are used by a master. + */ + roff_t bulk_buf; /* Bulk transfer buffer in region. */ + roff_t bulk_off; /* Current offset into bulk buffer. */ + u_int32_t bulk_len; /* Length of buffer. */ + u_int32_t bulk_flags; /* Bulk buffer flags. */ + /* END fields protected by rep->mtx_clientdb. */ + + /* + * During initialization, the log system walks forward through the + * last log file to find its end. If it runs into a checkpoint + * while it's doing so, it caches it here so that the transaction + * system doesn't need to walk through the file again on its + * initialization. + */ + DB_LSN cached_ckp_lsn; + + u_int32_t regionmax; /* Configured size of the region. */ + + roff_t buffer_off; /* Log buffer offset in the region. */ + u_int32_t buffer_size; /* Log buffer size. */ + + u_int32_t log_size; /* Log file's size. */ + u_int32_t log_nsize; /* Next log file's size. */ + + int filemode; /* Log file permissions mode. */ + + /* + * DB_LOG_AUTOREMOVE and DB_LOG_INMEMORY: not protected by a mutex, + * all we care about is if they're zero or non-zero. + */ + int32_t db_log_autoremove; + int32_t db_log_inmemory; + + u_int32_t ncommit; /* Number of txns waiting to commit. */ + DB_LSN t_lsn; /* LSN of first commit */ + SH_TAILQ_HEAD(__commit) commits;/* list of txns waiting to commit. */ + SH_TAILQ_HEAD(__free) free_commits;/* free list of commit structs. */ + + /* + * In-memory logs maintain a list of the start positions of all log + * files currently active in the in-memory buffer. This is to make the + * lookup from LSN to log buffer offset efficient. + */ + SH_TAILQ_HEAD(__logfile) logfiles; + SH_TAILQ_HEAD(__free_logfile) free_logfiles; +}; + +/* + * __db_commit structure -- + * One of these is allocated for each transaction waiting to commit. + */ +struct __db_commit { + db_mutex_t mtx_txnwait; /* Mutex for txn to wait on. */ + DB_LSN lsn; /* LSN of commit record. */ + SH_TAILQ_ENTRY links; /* Either on free or waiting list. */ + +#define DB_COMMIT_FLUSH 0x0001 /* Flush the log when you wake up. */ + u_int32_t flags; +}; + +/* + * Check for the proper progression of Log Sequence Numbers. + * If we are rolling forward the LSN on the page must be greater + * than or equal to the previous LSN in log record. + * We ignore NOT LOGGED LSNs. The user did an unlogged update. + * We should eventually see a log record that matches and continue + * forward. + * A ZERO LSN implies a page that was allocated prior to the recovery + * start point and then truncated later in the log. An allocation of a + * page after this page will extend the file, leaving a hole. We want to + * ignore this page until it is truncated again. + * + */ + +#define CHECK_LSN(e, redo, cmp, lsn, prev) \ + if (DB_REDO(redo) && (cmp) < 0 && \ + ((!IS_NOT_LOGGED_LSN(*(lsn)) && !IS_ZERO_LSN(*(lsn))) || \ + IS_REP_CLIENT(e))) { \ + ret = __db_check_lsn(e, lsn, prev); \ + goto out; \ + } +#define CHECK_ABORT(e, redo, cmp, lsn, prev) \ + if (redo == DB_TXN_ABORT && (cmp) != 0 && \ + ((!IS_NOT_LOGGED_LSN(*(lsn)) && !IS_ZERO_LSN(*(lsn))) || \ + IS_REP_CLIENT(e))) { \ + ret = __db_check_lsn(e, lsn, prev); \ + goto out; \ + } + +/* + * Helper for in-memory logs -- check whether an offset is in range + * in a ring buffer (inclusive of start, exclusive of end). + */ +struct __db_filestart { + u_int32_t file; + size_t b_off; + + SH_TAILQ_ENTRY links; /* Either on free or waiting list. */ +}; + +#define RINGBUF_LEN(lp, start, end) \ + ((start) < (end) ? \ + (end) - (start) : (lp)->buffer_size - ((start) - (end))) + +/* + * Internal macro to set pointer to the begin_lsn for generated + * logging routines. If begin_lsn is already set then do nothing. + * Return a pointer to the last lsn too. + */ +#undef DB_SET_TXN_LSNP +#define DB_SET_TXN_LSNP(txn, blsnp, llsnp) do { \ + DB_LSN *__lsnp; \ + TXN_DETAIL *__td; \ + __td = (txn)->td; \ + *(llsnp) = &__td->last_lsn; \ + while (__td->parent != INVALID_ROFF) \ + __td = R_ADDR(&(txn)->mgrp->reginfo, __td->parent); \ + __lsnp = &__td->begin_lsn; \ + if (IS_ZERO_LSN(*__lsnp)) \ + *(blsnp) = __lsnp; \ +} while (0) + +/* + * Status codes indicating the validity of a log file examined by + * __log_valid(). + */ +typedef enum { + DB_LV_INCOMPLETE, + DB_LV_NONEXISTENT, + DB_LV_NORMAL, + DB_LV_OLD_READABLE, + DB_LV_OLD_UNREADABLE +} logfile_validity; + +/* + * All log records have these fields. + */ +typedef struct __log_rec_hdr { + u_int32_t type; + DB_TXN *txnp; + DB_LSN prev_lsn; +} LOG_REC_HEADER; + +#if defined(__cplusplus) +} +#endif + +#include "dbinc_auto/log_ext.h" +#include "dbinc_auto/dbreg_auto.h" +#include "dbinc_auto/dbreg_ext.h" +#endif /* !_DB_LOG_H_ */ diff -r 000000000000 -r a1985f14b030 src/dbinc/log_verify.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/dbinc/log_verify.h Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,229 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 1996, 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + * $Id$ + */ +#ifndef _DB_LOG_VERIFY_H_ +#define _DB_LOG_VERIFY_H_ + +#include "db_config.h" +#include "db_int.h" + +/* + * Log verification handle, such a handle is shared among all verification + * functions during one verification process. + */ +struct __db_log_verify_info { + DB_ENV *dbenv; /* The database environment. */ + DB *txninfo; /* (txnid, __txn_verify_info) map. */ + DB *ckps; /* (ckp lrid, __ckpinfo) map. */ + DB *fileregs; /* (file-uid, __file_reg_info) map. */ + DB *fnameuid; /* (fname, fuid), secondary db of fileregs. */ + /* (dbreg-id, __file_reg_info) map, NOT the sec db for fileregs. */ + DB *dbregids; + DB *pgtxn; /* (fileid-pageno, txnid) map. */ + DB *txnpg; /* (txnid, fileid-pageno), sec db of pgtxn. */ + /* lsn, (time-stamp, logtype(txn_regop or txn_ckp)) map. */ + DB *lsntime; + /* Secondary db of lsntime, use timestamp as secindex. */ + DB *timelsn; + + /* Time range database, (u_int32_t, __lv_txnrange) db. */ + DB *txnrngs; + /* Store abort txn (lsn, txnid) map. */ + DB *txnaborts; + DB_LSN last_lsn; /* Lsn of last log record we verified. */ + /* The number of active, abort, commit and prepared txns. */ + u_int32_t ntxn_active, ntxn_abort, ntxn_commit, ntxn_prep; + u_int32_t nckp; /* The number of checkpoint log records. */ + /* + * Target database file unique id. Set if only verify log records + * of a database. + */ + u_int8_t target_dbid[DB_FILE_ID_LEN]; + u_int32_t non_txnup_cnt;/* Number of non-txnal log records. */ + u_int32_t unknown_logrec_cnt;/* Number of unknown log record. */ + u_int32_t external_logrec_cnt;/* Number of external log record. */ + /* + * (Log type, number of record) map. typeids are continuous + * integers, 256 is a big enough number. + */ + u_int32_t lrtypes[256]; + u_int32_t aborted_txnid;/* The last aborted txnid. */ + DB_LSN aborted_txnlsn; /* Last aborted txn's last log. */ + DB_LSN valid_lsn; /* When reach this log,unset DB_LOG_VERIFY_PARTIAL. */ + char *logtype_names[256];/* The type name string of each type of log.*/ + const DB_LOG_VERIFY_CONFIG *lv_config; + DB_THREAD_INFO *ip; + u_int32_t flags; /* The result of the verification. */ +}; + +/* Transaction information. */ +struct __txn_verify_info { +#define TXN_VERIFY_INFO_FIXSIZE (4 * sizeof(DB_LSN) + 9 * sizeof(u_int32_t)) +#define TXN_VERIFY_INFO_TOTSIZE(s) \ + (TXN_VERIFY_INFO_FIXSIZE + (s).num_recycle * sizeof(DB_LSN) + \ + __lv_dbt_arrsz((s).fileups, (s).filenum) + \ + sizeof(int32_t) * (s).filenum) + + u_int32_t txnid; /* The key, also stored in data here. */ + u_int32_t ptxnid; /* The parent txn id. */ + + DB_LSN first_lsn; /* Lsn of the first log record of this txn. */ + DB_LSN last_lsn; /* Last lsn of the txn. */ + DB_LSN prep_lsn; /* txn_prepare's lsn.*/ + DB_LSN cur_lsn; /* The lsn of the latest db op of this txn. */ + + u_int32_t num_recycle; /* The number of recycle lsns. */ + u_int32_t filenum; /* The number of files updated. */ + +#define TXN_STAT_ACTIVE 0 +#define TXN_STAT_ABORT 1 +#define TXN_STAT_COMMIT 2 +#define TXN_STAT_PREPARE 3 + u_int32_t status; /* Txn status */ + + /* The number of active, abort and commit children. */ + u_int32_t nchild_active; + u_int32_t nchild_abort; + u_int32_t nchild_commit; + + u_int32_t flags; /* Copied from the DB_TXN::flags member. */ + + DB_LSN *recycle_lsns; /* The array of txn_recycle records' lsns. */ + /* The array of file unique ids of files updated by this txn. */ + DBT *fileups; + int32_t *dbregid;/* The array of dbreg file ids updated by this txn. */ +}; + +/* Database file information. */ +struct __lv_filereg_info { +#define FILE_REG_INFO_FIXSIZE (sizeof(u_int32_t)) +#define FILE_REG_INFO_TOTSIZE(s) (FILE_REG_INFO_FIXSIZE + (s).fileid.size + \ + sizeof((s).fileid.size) + sizeof(int32_t) * (s).regcnt + \ + strlen((s).fname) + 1) + + u_int32_t regcnt; /* The number of dbregids for this file-uid. */ + int32_t *dbregids; + DBT fileid; /* The file unique id. */ + char *fname; /* Database file name. */ +}; + +/* Database file dbreg_register information. */ +struct __lv_filelife { + int32_t dbregid; /* The primary key. */ + DBTYPE dbtype; /* The database type. */ + u_int32_t lifetime; /* DBREG_CHKPNT, DBREG_CLOSE, DBREG_OPEN, DBREG_XCHKPNT, DBREG_XOPEN */ + db_pgno_t meta_pgno; /* The meta_pgno; */ + u_int8_t fileid[DB_FILE_ID_LEN]; + DB_LSN lsn; /* The lsn of log updating lifetime. */ +}; + +/* Checkpoint information. */ +struct __lv_ckp_info { + int32_t timestamp; + DB_LSN lsn, ckplsn; /* Lsn member is the primary key. */ +}; + +/* + * General information from log records which have timestamps. + * We use it to do time range verifications. Such information is + * acquired when backward-playing the logs before verification. + */ +struct __lv_timestamp_info { + DB_LSN lsn; /* The primary key. */ + int32_t timestamp; /* The secondary key. */ + + /* + * The log types containing a time stamp, so far only txn_ckp + * and txn_regop types. + */ + u_int32_t logtype; +}; + +/* + * Transaction ranges. Such information is acquired when backward-playing the + * logs before verification. Can be used to find aborted txns. + */ +struct __lv_txnrange { + /* + * Transaction ID, the primary key. The db storing records of this + * type should allow dup since txnids maybe reused. + */ + u_int32_t txnid; + + /* + * The parent txn id, ptxnid is the parent of txnid + * during [begin, end]. + */ + u_int32_t ptxnid; + + /* + * The first and last lsn, end is used to sort dup data because it's + * seen prior to begin in a backward playback, and [begin, end] + * intervals won't overlap. + */ + DB_LSN begin, end; + + int32_t when_commit;/* The time of the commit, 0 if aborted. */ +}; + + +/* Parameter types for __iterate_txninfo function. */ +struct __add_recycle_params { + u_int32_t min, max;/* The recycled txnid range. */ + /* The array of txn info to update into db. */ + VRFY_TXN_INFO **ti2u; + u_int32_t ti2ui, ti2ul;/* The effective length and array length. */ + DB_LSN recycle_lsn; +}; + +struct __ckp_verify_params { + DB_LSN lsn, ckp_lsn; + ENV *env; +}; + +/* Helper macros. */ +#define LOGTYPE_NAME(lvh, type) (lvh->logtype_names[type] == NULL ? \ + NULL : lvh->logtype_names[type] + 3) +#define NUMCMP(i1, i2) ((i1) > (i2) ? 1 : ((i1) < (i2) ? -1 : 0)) + +#define INVAL_DBREGID -1 + +/* + * During recovery, DBREG_CHKPNT and DBREG_XCHKPNT can be seen as open, + * and it's followed by a DBREG_RCLOSE or DBREG_CLOSE. + */ +#define IS_DBREG_OPEN(opcode) (opcode == DBREG_OPEN || opcode == \ + DBREG_PREOPEN || opcode == DBREG_REOPEN || opcode == DBREG_CHKPNT \ + || opcode == DBREG_XCHKPNT || opcode == DBREG_XOPEN || \ + opcode == DBREG_XREOPEN) +#define IS_DBREG_CLOSE(opcode) (opcode == DBREG_CLOSE || opcode == DBREG_RCLOSE) + +#define IS_LOG_VRFY_SUPPORTED(version) ((version) == DB_LOGVERSION) + +#endif /* !_DB_LOG_VERIFY_H_*/ diff -r 000000000000 -r a1985f14b030 src/dbinc/mp.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/dbinc/mp.h Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,694 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 1996, 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + * $Id$ + */ + +#ifndef _DB_MP_H_ +#define _DB_MP_H_ + +#include "dbinc/atomic.h" + +#if defined(__cplusplus) +extern "C" { +#endif + +struct __bh; typedef struct __bh BH; +struct __bh_frozen_p; typedef struct __bh_frozen_p BH_FROZEN_PAGE; +struct __bh_frozen_a; typedef struct __bh_frozen_a BH_FROZEN_ALLOC; +struct __db_mpool_hash; typedef struct __db_mpool_hash DB_MPOOL_HASH; +struct __db_mpool_fstat_int; +typedef struct __db_mpool_fstat_int DB_MPOOL_FSTAT_INT; +struct __db_mpreg; typedef struct __db_mpreg DB_MPREG; +struct __mpool; typedef struct __mpool MPOOL; + + /* We require at least 20KB of cache. */ +#define DB_CACHESIZE_MIN (20 * 1024) + +/* + * DB_MPOOLFILE initialization methods cannot be called after open is called, + * other methods cannot be called before open is called + */ +#define MPF_ILLEGAL_AFTER_OPEN(dbmfp, name) \ + if (F_ISSET(dbmfp, MP_OPEN_CALLED)) \ + return (__db_mi_open((dbmfp)->env, name, 1)); +#define MPF_ILLEGAL_BEFORE_OPEN(dbmfp, name) \ + if (!F_ISSET(dbmfp, MP_OPEN_CALLED)) \ + return (__db_mi_open((dbmfp)->env, name, 0)); + +/* + * Cache flush operations, plus modifiers. + */ +#define DB_SYNC_ALLOC 0x0001 /* Flush for allocation. */ +#define DB_SYNC_CACHE 0x0002 /* Flush entire cache. */ +#define DB_SYNC_CHECKPOINT 0x0004 /* Checkpoint. */ +#define DB_SYNC_FILE 0x0008 /* Flush file. */ +#define DB_SYNC_INTERRUPT_OK 0x0010 /* Allow interrupt and return OK. */ +#define DB_SYNC_QUEUE_EXTENT 0x0020 /* Flush a queue file with extents. */ +#define DB_SYNC_SUPPRESS_WRITE 0x0040 /* Ignore max-write configuration. */ +#define DB_SYNC_TRICKLE 0x0080 /* Trickle sync. */ + +/* + * DB_MPOOL -- + * Per-process memory pool structure. + */ +struct __db_mpool { + /* These fields need to be protected for multi-threaded support. */ + db_mutex_t mutex; /* Thread mutex. */ + + /* + * DB_MPREG structure for the DB pgin/pgout routines. + * + * Linked list of application-specified pgin/pgout routines. + */ + DB_MPREG *pg_inout; + LIST_HEAD(__db_mpregh, __db_mpreg) dbregq; + + /* List of DB_MPOOLFILE's. */ + TAILQ_HEAD(__db_mpoolfileh, __db_mpoolfile) dbmfq; + + /* + * The env and reginfo fields are not thread protected, as they are + * initialized during mpool creation, and not modified again. + */ + ENV *env; /* Enclosing environment. */ + REGINFO *reginfo; /* Underlying cache regions. */ +}; + +/* + * DB_MPREG -- + * DB_MPOOL registry of pgin/pgout functions. + */ +struct __db_mpreg { + LIST_ENTRY(__db_mpreg) q; /* Linked list. */ + + int32_t ftype; /* File type. */ + /* Pgin, pgout routines. */ + int (*pgin) __P((DB_ENV *, db_pgno_t, void *, DBT *)); + int (*pgout) __P((DB_ENV *, db_pgno_t, void *, DBT *)); +}; + +/* + * File hashing -- + * We hash each file to hash bucket based on its fileid + * or, in the case of in memory files, its name. + */ + +/* Number of file hash buckets, a small prime number */ +#define MPOOL_FILE_BUCKETS 17 + +#define FHASH(id, len) __ham_func5(NULL, id, (u_int32_t)(len)) + +#define FNBUCKET(id, len) \ + (FHASH(id, len) % MPOOL_FILE_BUCKETS) + +/* Macros to lock/unlock the mpool region as a whole. */ +#define MPOOL_SYSTEM_LOCK(env) \ + MUTEX_LOCK(env, ((MPOOL *) \ + (env)->mp_handle->reginfo[0].primary)->mtx_region) +#define MPOOL_SYSTEM_UNLOCK(env) \ + MUTEX_UNLOCK(env, ((MPOOL *) \ + (env)->mp_handle->reginfo[0].primary)->mtx_region) + +/* Macros to lock/unlock a specific mpool region. */ +#define MPOOL_REGION_LOCK(env, infop) \ + MUTEX_LOCK(env, ((MPOOL *)(infop)->primary)->mtx_region) +#define MPOOL_REGION_UNLOCK(env, infop) \ + MUTEX_UNLOCK(env, ((MPOOL *)(infop)->primary)->mtx_region) + +/* + * MPOOL -- + * Shared memory pool region. + */ +struct __mpool { /* SHARED */ + /* + * The memory pool can be broken up into individual pieces/files. + * There are two reasons for this: firstly, on Solaris you can allocate + * only a little more than 2GB of memory in a contiguous chunk, + * and I expect to see more systems with similar issues. Secondly, + * applications can add / remove pieces to dynamically resize the + * cache. + * + * While this structure is duplicated in each piece of the cache, + * the first of these pieces/files describes the entire pool, the + * second only describe a piece of the cache. + */ + db_mutex_t mtx_region; /* Region mutex. */ + db_mutex_t mtx_resize; /* Resizing mutex. */ + + /* + * The lsn field and list of underlying MPOOLFILEs are thread protected + * by the region lock. + */ + DB_LSN lsn; /* Maximum checkpoint LSN. */ + + /* Configuration information: protected by the region lock. */ + u_int32_t max_nreg; /* Maximum number of regions. */ + u_int32_t gbytes; /* Number of gigabytes in cache. */ + u_int32_t bytes; /* Number of bytes in cache. */ + u_int32_t pagesize; /* Default page size. */ + db_size_t mp_mmapsize; /* Maximum file size for mmap. */ + int32_t mp_maxopenfd; /* Maximum open file descriptors. */ + int32_t mp_maxwrite; /* Maximum buffers to write. */ + db_timeout_t mp_maxwrite_sleep; /* Sleep after writing max buffers. */ + + /* + * The number of regions and the total number of hash buckets across + * all regions. + * These fields are not protected by a mutex because we assume that we + * can read a 32-bit value atomically. They are only modified by cache + * resizing which holds the mpool resizing mutex to ensure that + * resizing is single-threaded. See the comment in mp_resize.c for + * more information. + */ + u_int32_t nreg; /* Number of underlying REGIONS. */ + u_int32_t nbuckets; /* Total number of hash buckets. */ + + /* + * The regid field is protected by the resize mutex. + */ + roff_t regids; /* Array of underlying REGION Ids. */ + + roff_t ftab; /* Hash table of files. */ + + /* + * The following fields describe the per-cache portion of the region. + * + * The htab and htab_buckets fields are not thread protected as they + * are initialized during mpool creation, and not modified again. + * + * The last_checked, lru_priority, and lru_generation fields are thread + * protected by the region lock. + */ + roff_t htab; /* Hash table offset. */ + u_int32_t htab_buckets; /* Number of hash table entries. */ + u_int32_t last_checked; /* Last bucket checked for free. */ + u_int32_t lru_priority; /* Priority counter for buffer LRU. */ + u_int32_t lru_generation; /* Allocation race condition detector. */ + u_int32_t htab_mutexes; /* Number of hash mutexes per region. */ + + /* + * The pages field keeps track of the number of pages in the cache + * and is protected by the region lock. It is accessed for reading + * without the lock to return statistics. + */ + u_int32_t pages; /* Number of pages in the cache. */ + + /* + * The stat fields are not thread protected, and cannot be trusted. + */ + DB_MPOOL_STAT stat; /* Per-cache mpool statistics. */ + + /* + * We track page puts so that we can decide when allocation is never + * going to succeed. We don't lock the field, all we care about is + * if it changes. + */ + u_int32_t put_counter; /* Count of page put calls. */ + + /* + * Cache flush operations take a long time... + * + * Some cache flush operations want to ignore the app's configured + * max-write parameters (they are trying to quickly shut down an + * environment, for example). We can't specify that as an argument + * to the cache region functions, because we may decide to ignore + * the max-write configuration after the cache operation has begun. + * If the variable suppress_maxwrite is set, ignore the application + * max-write config. + * + * We may want to interrupt cache flush operations in high-availability + * configurations. + */ +#define DB_MEMP_SUPPRESS_WRITE 0x01 +#define DB_MEMP_SYNC_INTERRUPT 0x02 + u_int32_t config_flags; + + /* Free frozen buffer headers, protected by the region lock. */ + SH_TAILQ_HEAD(__free_frozen) free_frozen; + + /* Allocated blocks of frozen buffer headers. */ + SH_TAILQ_HEAD(__alloc_frozen) alloc_frozen; +}; + +/* + * NREGION -- + * Select a cache region given the bucket number. + */ +#define NREGION(mp, bucket) \ + ((bucket) / (mp)->htab_buckets) + +/* + * MP_HASH -- + * We make the assumption that early pages of the file are more likely + * to be retrieved than the later pages, which means the top bits will + * be more interesting for hashing as they're less likely to collide. + * That said, as 512 8K pages represents a 4MB file, so only reasonably + * large files will have page numbers with any other than the bottom 9 + * bits set. We XOR in the MPOOL offset of the MPOOLFILE that backs the + * page, since that should also be unique for the page. We don't want + * to do anything very fancy -- speed is more important to us than using + * good hashing. + * + * Since moving to a dynamic hash, which boils down to using some of the + * least significant bits of the hash value, we no longer want to use a + * simple shift here, because it's likely with a bit shift that mf_offset + * will be ignored, and pages from different files end up in the same + * hash bucket. Use a nearby prime instead. + */ +#define MP_HASH(mf_offset, pgno) \ + ((((pgno) << 8) ^ (pgno)) ^ (((u_int32_t) mf_offset) * 509)) + +/* + * Inline the calculation of the mask, since we can't reliably store the mask + * with the number of buckets in the region. + * + * This is equivalent to: + * mask = (1 << __db_log2(nbuckets)) - 1; + */ +#define MP_MASK(nbuckets, mask) do { \ + for (mask = 1; mask < (nbuckets); mask = (mask << 1) | 1) \ + ; \ +} while (0) + +#define MP_HASH_BUCKET(hash, nbuckets, mask, bucket) do { \ + (bucket) = (hash) & (mask); \ + if ((bucket) >= (nbuckets)) \ + (bucket) &= ((mask) >> 1); \ +} while (0) + +#define MP_BUCKET(mf_offset, pgno, nbuckets, bucket) do { \ + u_int32_t __mask; \ + MP_MASK(nbuckets, __mask); \ + MP_HASH_BUCKET(MP_HASH(mf_offset, pgno), nbuckets, \ + __mask, bucket); \ +} while (0) + +/* + * MP_GET_REGION -- + * Select the region for a given page. + */ +#define MP_GET_REGION(dbmfp, pgno, infopp, ret) do { \ + DB_MPOOL *__t_dbmp; \ + MPOOL *__t_mp; \ + \ + __t_dbmp = dbmfp->env->mp_handle; \ + __t_mp = __t_dbmp->reginfo[0].primary; \ + if (__t_mp->max_nreg == 1) { \ + *(infopp) = &__t_dbmp->reginfo[0]; \ + } else \ + ret = __memp_get_bucket((dbmfp)->env, \ + (dbmfp)->mfp, (pgno), (infopp), NULL, NULL); \ +} while (0) + +/* + * MP_GET_BUCKET -- + * Select and lock the bucket for a given page. + */ +#define MP_GET_BUCKET(env, mfp, pgno, infopp, hp, bucket, ret) do { \ + DB_MPOOL *__t_dbmp; \ + MPOOL *__t_mp; \ + roff_t __t_mf_offset; \ + \ + __t_dbmp = (env)->mp_handle; \ + __t_mp = __t_dbmp->reginfo[0].primary; \ + if (__t_mp->max_nreg == 1) { \ + *(infopp) = &__t_dbmp->reginfo[0]; \ + __t_mf_offset = R_OFFSET(*(infopp), (mfp)); \ + MP_BUCKET(__t_mf_offset, \ + (pgno), __t_mp->nbuckets, bucket); \ + (hp) = R_ADDR(*(infopp), __t_mp->htab); \ + (hp) = &(hp)[bucket]; \ + MUTEX_READLOCK(env, (hp)->mtx_hash); \ + ret = 0; \ + } else \ + ret = __memp_get_bucket((env), \ + (mfp), (pgno), (infopp), &(hp), &(bucket)); \ +} while (0) + +struct __db_mpool_hash { + db_mutex_t mtx_hash; /* Per-bucket mutex. */ + + DB_HASHTAB hash_bucket; /* Head of bucket. */ + + db_atomic_t hash_page_dirty;/* Count of dirty pages. */ + +#ifndef __TEST_DB_NO_STATISTICS + u_int32_t hash_io_wait; /* Count of I/O waits. */ + u_int32_t hash_frozen; /* Count of frozen buffers. */ + u_int32_t hash_thawed; /* Count of thawed buffers. */ + u_int32_t hash_frozen_freed;/* Count of freed frozen buffers. */ +#endif + + DB_LSN old_reader; /* Oldest snapshot reader (cached). */ + + u_int32_t flags; +}; + +/* + * Mpool file statistics structure for use in shared memory. + * This structure must contain the same fields as the __db_mpool_fstat struct + * except for any pointer fields that are filled in only when the struct is + * being populated for output through the API. + */ +struct __db_mpool_fstat_int { /* SHARED */ + u_int32_t st_pagesize; /* Page size. */ +#ifndef __TEST_DB_NO_STATISTICS + u_int32_t st_map; /* Pages from mapped files. */ + uintmax_t st_cache_hit; /* Pages found in the cache. */ + uintmax_t st_cache_miss; /* Pages not found in the cache. */ + uintmax_t st_page_create; /* Pages created in the cache. */ + uintmax_t st_page_in; /* Pages read in. */ + uintmax_t st_page_out; /* Pages written out. */ + uintmax_t st_backup_spins; /* Number of spins by a backup. */ +#endif +}; + +/* + * The base mpool priority is 1/4th of the name space, or just under 2^30. When + * the LRU priority counter is about to wrap (within a 128-entry 'red zone' + * area) we adjust everybody down so that no one is larger than the new LRU + * priority. + */ +#define MPOOL_LRU_MAX UINT32_MAX +#define MPOOL_LRU_REDZONE (MPOOL_LRU_MAX - 128) +#define MPOOL_LRU_BASE (MPOOL_LRU_MAX / 4) +#define MPOOL_LRU_DECREMENT (MPOOL_LRU_MAX - MPOOL_LRU_BASE) + +/* + * Mpool priorities from low to high. Defined in terms of fractions of the + * buffers in the pool. + */ +#define MPOOL_PRI_VERY_LOW -1 /* Dead duck. Check and set to 0. */ +#define MPOOL_PRI_LOW -2 /* Low. */ +#define MPOOL_PRI_DEFAULT 0 /* No adjustment -- special case.*/ +#define MPOOL_PRI_HIGH 10 /* With the dirty buffers. */ +#define MPOOL_PRI_DIRTY 10 /* Dirty gets a 10% boost. */ +#define MPOOL_PRI_VERY_HIGH 1 /* Add number of buffers in pool. */ + +/* + * MPOOLFILE -- + * Shared DB_MPOOLFILE information. + */ +struct __mpoolfile { /* SHARED */ + db_mutex_t mutex; /* MPOOLFILE mutex. */ + +#ifndef HAVE_ATOMICFILEREAD + /* Information to synchronize backups. */ + u_int32_t backup_in_progress; /* Backup running. */ + pid_t pid; /* Process doing backup. */ + db_threadid_t tid; /* Thread doing backup. */ + db_atomic_t writers; /* Number of current writers. */ + db_mutex_t mtx_write; /* block writers while updating.*/ + db_pgno_t low_pgno, high_pgno;/* Low and high backup range.*/ +#endif + + /* Protected by MPOOLFILE mutex. */ + u_int32_t revision; /* Bumped on any movement subdbs. */ + u_int32_t mpf_cnt; /* Ref count: DB_MPOOLFILEs. */ + u_int32_t neutral_cnt; /* Ref count: refs that don't care about + * MVCC or DURABLE. That is, read-only + * or write behind references. + */ + u_int32_t block_cnt; /* Ref count: blocks in cache. */ + db_pgno_t last_pgno; /* Last page in the file. */ + db_pgno_t last_flushed_pgno; /* Last page flushed to disk. */ + db_pgno_t orig_last_pgno; /* Original last page in the file. */ + db_pgno_t maxpgno; /* Maximum page number. */ + u_int8_t excl_lockout; /* Internal exclusive db lockout. */ + + roff_t path_off; /* File name location. */ + + /* Protected by hash bucket mutex. */ + SH_TAILQ_ENTRY q; /* List of MPOOLFILEs */ + + /* + * The following are used for file compaction processing. + * They are only used when a thread is in the process + * of trying to move free pages to the end of the file. + * Other threads may look here when freeing a page. + * Protected by a lock on the metapage. + */ + u_int32_t free_ref; /* Refcount to freelist. */ + u_int32_t free_cnt; /* Count of free pages. */ + db_size_t free_size; /* Allocated size of free list. */ + roff_t free_list; /* Offset to free list. */ + + /* + * We normally don't lock the deadfile field when we read it since we + * only care if the field is zero or non-zero. We do lock on read when + * searching for a matching MPOOLFILE -- see that code for more detail. + */ + int32_t deadfile; /* Dirty pages can be discarded. */ + + u_int32_t bucket; /* hash bucket for this file. */ + + /* + * None of the following fields are thread protected. + * + * There are potential races with the ftype field because it's read + * without holding a lock. However, it has to be set before adding + * any buffers to the cache that depend on it being set, so there + * would need to be incorrect operation ordering to have a problem. + */ + int32_t ftype; /* File type. */ + + /* + * There are potential races with the priority field because it's read + * without holding a lock. However, a collision is unlikely and if it + * happens is of little consequence. + */ + int32_t priority; /* Priority when unpinning buffer. */ + + /* + * There are potential races with the file_written field (many threads + * may be writing blocks at the same time), and with no_backing_file + * and unlink_on_close fields, as they may be set while other threads + * are reading them. However, we only care if the field value is zero + * or non-zero, so don't lock the memory. + * + * !!! + * Theoretically, a 64-bit architecture could put two of these fields + * in a single memory operation and we could race. I have never seen + * an architecture where that's a problem, and I believe Java requires + * that to never be the case. + * + * File_written is set whenever a buffer is marked dirty in the cache. + * It can be cleared in some cases, after all dirty buffers have been + * written AND the file has been flushed to disk. + */ + int32_t file_written; /* File was written. */ + int32_t no_backing_file; /* Never open a backing file. */ + int32_t unlink_on_close; /* Unlink file on last close. */ + db_atomic_t multiversion; /* Number of DB_MULTIVERSION handles. */ + + /* + * We do not protect the statistics in "stat" because of the cost of + * the mutex in the get/put routines. There is a chance that a count + * will get lost. + */ + DB_MPOOL_FSTAT_INT stat; /* Per-file mpool statistics. */ + + /* + * The remaining fields are initialized at open and never subsequently + * modified. + */ + int32_t lsn_off; /* Page's LSN offset. */ + u_int32_t clear_len; /* Bytes to clear on page create. */ + + roff_t fileid_off; /* File ID string location. */ + + u_int32_t pagesize; /* Underlying pagesize. */ + roff_t pgcookie_len; /* Pgin/pgout cookie length. */ + roff_t pgcookie_off; /* Pgin/pgout cookie location. */ + + /* + * The flags are initialized at open and never subsequently modified. + */ +#define MP_CAN_MMAP 0x001 /* If the file can be mmap'd. */ +#define MP_DATABASE_LOCKING 0x002 /* Lock in exclusive mode. */ +#define MP_DIRECT 0x004 /* No OS buffering. */ +#define MP_DURABLE_UNKNOWN 0x008 /* We don't care about durability. */ +#define MP_EXTENT 0x010 /* Extent file. */ +#define MP_FAKE_DEADFILE 0x020 /* Deadfile field: fake flag. */ +#define MP_FAKE_FILEWRITTEN 0x040 /* File_written field: fake flag. */ +#define MP_FAKE_NB 0x080 /* No_backing_file field: fake flag. */ +#define MP_FAKE_UOC 0x100 /* Unlink_on_close field: fake flag. */ +#define MP_NOT_DURABLE 0x200 /* File is not durable. */ +#define MP_TEMP 0x400 /* Backing file is a temporary. */ + u_int32_t flags; + + db_pgno_t fe_watermark; /* File extension watermark. */ + u_int32_t fe_txnid; /* Transaction that set watermark. */ + u_int32_t fe_nlws; /* Number of log writes suppressed. */ +}; + +/* + * Flags to __memp_bh_free. + */ +#define BH_FREE_FREEMEM 0x01 +#define BH_FREE_REUSE 0x02 +#define BH_FREE_UNLOCKED 0x04 + +/* + * BH -- + * Buffer header. + */ +struct __bh { /* SHARED */ + db_mutex_t mtx_buf; /* Shared/Exclusive mutex */ + db_atomic_t ref; /* Reference count. */ +#define BH_REFCOUNT(bhp) atomic_read(&(bhp)->ref) + +#define BH_CALLPGIN 0x001 /* Convert the page before use. */ +#define BH_DIRTY 0x002 /* Page is modified. */ +#define BH_DIRTY_CREATE 0x004 /* Page is modified. */ +#define BH_DISCARD 0x008 /* Page is useless. */ +#define BH_EXCLUSIVE 0x010 /* Exclusive access acquired. */ +#define BH_FREED 0x020 /* Page was freed. */ +#define BH_FROZEN 0x040 /* Frozen buffer: allocate & re-read. */ +#define BH_TRASH 0x080 /* Page is garbage. */ +#define BH_THAWED 0x100 /* Page was thawed. */ + u_int16_t flags; + + u_int32_t priority; /* Priority. */ + SH_TAILQ_ENTRY hq; /* MPOOL hash bucket queue. */ + + db_pgno_t pgno; /* Underlying MPOOLFILE page number. */ + roff_t mf_offset; /* Associated MPOOLFILE offset. */ + u_int32_t bucket; /* Hash bucket containing header. */ + int region; /* Region containing header. */ + + roff_t td_off; /* MVCC: creating TXN_DETAIL offset. */ + SH_CHAIN_ENTRY vc; /* MVCC: version chain. */ +#ifdef DIAG_MVCC + u_int16_t align_off; /* Alignment offset for diagnostics.*/ +#endif + + /* + * !!! + * This array must be at least size_t aligned -- the DB access methods + * put PAGE and other structures into it, and then access them directly. + * (We guarantee size_t alignment to applications in the documentation, + * too.) + */ + DB_ALIGN8 u_int8_t buf[1]; /* Variable length data. */ +}; + +/* + * BH_FROZEN_PAGE -- + * Data used to find a frozen buffer header. + */ +struct __bh_frozen_p { + BH header; + db_pgno_t spgno; /* Page number in freezer file. */ +}; + +/* + * BH_FROZEN_ALLOC -- + * Frozen buffer headers are allocated a page at a time in general. This + * structure is allocated at the beginning of the page so that the + * allocation chunks can be tracked and freed (for private environments). + */ +struct __bh_frozen_a { + SH_TAILQ_ENTRY links; +}; + +#define MULTIVERSION(dbp) atomic_read(&(dbp)->mpf->mfp->multiversion) + +#define PAGE_TO_BH(p) (BH *)((u_int8_t *)(p) - SSZA(BH, buf)) +#define IS_DIRTY(p) \ + (F_ISSET(PAGE_TO_BH(p), BH_DIRTY|BH_EXCLUSIVE) == (BH_DIRTY|BH_EXCLUSIVE)) + +#define BH_OWNER(env, bhp) ((TXN_DETAIL *) NULL) + +#define BH_OWNED_BY(env, bhp, txn) FALSE + +#define VISIBLE_LSN(env, bhp) \ + (&BH_OWNER(env, bhp)->visible_lsn) + +/* + * Make a copy of the buffer's visible LSN, one field at a time. We rely on the + * 32-bit operations being atomic. The visible_lsn starts at MAX_LSN and is + * set during commit or abort to the current LSN. + * + * If we race with a commit / abort, we may see either the file or the offset + * still at UINT32_MAX, so vlsn is guaranteed to be in the future. That's OK, + * since we had to take the log region lock to allocate the read LSN so we were + * never going to see this buffer anyway. + */ +/* Without transactions -- and hence MVCC -- buffers are always visible. */ +#define BH_VISIBLE(env, bhp, read_lsnp, vlsn) TRUE + +#define BH_OBSOLETE(bhp, old_lsn, vlsn) FALSE + +#define MVCC_SKIP_CURADJ(dbc, pgno) FALSE + +#if defined(DIAG_MVCC) && defined(HAVE_MPROTECT) +#define VM_PAGESIZE 4096 +#define MVCC_BHSIZE(mfp, sz) do { \ + sz += VM_PAGESIZE + sizeof(BH); \ + if (mfp->pagesize < VM_PAGESIZE) \ + sz += VM_PAGESIZE - mfp->pagesize; \ +} while (0) + +#define MVCC_BHALIGN(p) NOP_STATEMENT + +#define MVCC_BHUNALIGN(bhp) NOP_STATEMENT + +#ifdef linux +#define MVCC_MPROTECT(buf, sz, mode) do { \ + int __ret = mprotect((buf), (sz), (mode)); \ + DB_ASSERT(env, __ret == 0); \ +} while (0) +#else +#define MVCC_MPROTECT(buf, sz, mode) do { \ + if (!F_ISSET(env, ENV_PRIVATE | ENV_SYSTEM_MEM)) { \ + int __ret = mprotect((buf), (sz), (mode)); \ + DB_ASSERT(env, __ret == 0); \ + } \ +} while (0) +#endif /* linux */ + +#else /* defined(DIAG_MVCC) && defined(HAVE_MPROTECT) */ +#define MVCC_BHSIZE(mfp, sz) do {} while (0) +#define MVCC_BHALIGN(p) do {} while (0) +#define MVCC_BHUNALIGN(bhp) do {} while (0) +#define MVCC_MPROTECT(buf, size, mode) do {} while (0) +#endif + +/* + * Flags to __memp_ftruncate. + */ +#define MP_TRUNC_NOCACHE 0x01 +#define MP_TRUNC_RECOVER 0x02 + +#if defined(__cplusplus) +} +#endif + +#include "dbinc_auto/mp_ext.h" +#endif /* !_DB_MP_H_ */ diff -r 000000000000 -r a1985f14b030 src/dbinc/mutex.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/dbinc/mutex.h Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,341 @@ +/* + * See the file LICENSE for redistribution information. + * + * Copyright (c) 1996, 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + * $Id$ + */ + +#ifndef _DB_MUTEX_H_ +#define _DB_MUTEX_H_ + +#ifdef HAVE_MUTEX_SUPPORT +/* The inlined trylock calls need access to the details of mutexes. */ +#define LOAD_ACTUAL_MUTEX_CODE +#include "dbinc/mutex_int.h" + +#ifndef HAVE_SHARED_LATCHES + #error "Shared latches are required in DB 4.8 and above" +#endif +#endif + +#if defined(__cplusplus) +extern "C" { +#endif + +/* + * By default, spin 50 times per processor if fail to acquire a test-and-set + * mutex, we have anecdotal evidence it's a reasonable value. + */ +#define MUTEX_SPINS_PER_PROCESSOR 50 + +/* + * Mutexes are represented by unsigned, 32-bit integral values. As the + * OOB value is 0, mutexes can be initialized by zero-ing out the memory + * in which they reside. + */ +#define MUTEX_INVALID 0 + +/* + * We track mutex allocations by ID. + */ +#define MTX_APPLICATION 1 +#define MTX_ATOMIC_EMULATION 2 +#define MTX_DB_HANDLE 3 +#define MTX_ENV_DBLIST 4 +#define MTX_ENV_EXCLDBLIST 5 +#define MTX_ENV_HANDLE 6 +#define MTX_ENV_REGION 7 +#define MTX_LOCK_REGION 8 +#define MTX_LOGICAL_LOCK 9 +#define MTX_LOG_FILENAME 10 +#define MTX_LOG_FLUSH 11 +#define MTX_LOG_HANDLE 12 +#define MTX_LOG_REGION 13 +#define MTX_MPOOLFILE_HANDLE 14 +#define MTX_MPOOL_BH 15 +#define MTX_MPOOL_FH 16 +#define MTX_MPOOL_FILE_BUCKET 17 +#define MTX_MPOOL_HANDLE 18 +#define MTX_MPOOL_HASH_BUCKET 19 +#define MTX_MPOOL_REGION 20 +#define MTX_MUTEX_REGION 21 +#define MTX_MUTEX_TEST 22 +#define MTX_REP_CHKPT 23 +#define MTX_REP_DATABASE 24 +#define MTX_REP_DIAG 25 +#define MTX_REP_EVENT 26 +#define MTX_REP_REGION 27 +#define MTX_REP_START 28 +#define MTX_REP_WAITER 29 +#define MTX_REPMGR 30 +#define MTX_SEQUENCE 31 +#define MTX_TWISTER 32 +#define MTX_TCL_EVENTS 33 +#define MTX_TXN_ACTIVE 34 +#define MTX_TXN_CHKPT 35 +#define MTX_TXN_COMMIT 36 +#define MTX_TXN_MVCC 37 +#define MTX_TXN_REGION 38 + +#define MTX_MAX_ENTRY 38 + +/* The following macros are defined on some platforms, e.g. QNX. */ +#undef __mutex_init +#undef __mutex_lock +#undef __mutex_timedlock +#undef __mutex_unlock +#undef __mutex_destroy +#undef __mutex_trylock + +/* Redirect mutex calls to the correct functions. */ +#if !defined(HAVE_MUTEX_HYBRID) && ( \ + defined(HAVE_MUTEX_PTHREADS) || \ + defined(HAVE_MUTEX_SOLARIS_LWP) || \ + defined(HAVE_MUTEX_UI_THREADS)) +#define __mutex_init(a, b, c) __db_pthread_mutex_init(a, b, c) +#define __mutex_lock(a, b) __db_pthread_mutex_lock(a, b, 0) +#define __mutex_timedlock(a, b, c) __db_pthread_mutex_lock(a, b, c) +#define __mutex_unlock(a, b) __db_pthread_mutex_unlock(a, b) +#define __mutex_destroy(a, b) __db_pthread_mutex_destroy(a, b) +#define __mutex_trylock(a, b) __db_pthread_mutex_trylock(a, b) +/* + * These trylock versions do not support DB_ENV_FAILCHK. Callers which loop + * checking mutexes which are held by dead processes or threads might spin. + * These have ANSI-style definitions because this file can be included by + * C++ files, and extern "C" affects linkage only, not argument typing. + */ +static inline int __db_pthread_mutex_trylock(ENV *env, db_mutex_t mutex) +{ + int ret; + DB_MUTEX *mutexp; + if (!MUTEX_ON(env) || F_ISSET(env->dbenv, DB_ENV_NOLOCKING)) + return (0); + mutexp = MUTEXP_SET(env, mutex); +#ifdef HAVE_SHARED_LATCHES + if (F_ISSET(mutexp, DB_MUTEX_SHARED)) + ret = pthread_rwlock_trywrlock(&mutexp->u.rwlock); + else +#endif + ret = pthread_mutex_trylock(&mutexp->u.m.mutex); + if (ret == EBUSY) + ret = DB_LOCK_NOTGRANTED; + else if (ret == 0) { + F_SET(mutexp, DB_MUTEX_LOCKED); + env->dbenv->thread_id(env->dbenv, &mutexp->pid, &mutexp->tid); + STAT_INC(env, + mutex, set_nowait, mutexp->mutex_set_nowait, mutex); + } + return (ret); +} +#ifdef HAVE_SHARED_LATCHES +#define __mutex_rdlock(a, b) __db_pthread_mutex_readlock(a, b) +#define __mutex_tryrdlock(a, b) __db_pthread_mutex_tryreadlock(a, b) +static inline int __db_pthread_mutex_tryreadlock(ENV *env, db_mutex_t mutex) +{ + int ret; + DB_MUTEX *mutexp; + if (!MUTEX_ON(env) || F_ISSET(env->dbenv, DB_ENV_NOLOCKING)) + return (0); + mutexp = MUTEXP_SET(env, mutex); + if (F_ISSET(mutexp, DB_MUTEX_SHARED)) + ret = pthread_rwlock_tryrdlock(&mutexp->u.rwlock); + else + return (EINVAL); + if (ret == EBUSY) + ret = DB_LOCK_NOTGRANTED; +#ifdef HAVE_STATISTICS + if (ret == 0) + STAT_INC(env, + mutex, set_rd_nowait, mutexp->mutex_set_nowait, mutex); +#endif + return (ret); +} +#endif +#elif defined(HAVE_MUTEX_WIN32) || defined(HAVE_MUTEX_WIN32_GCC) +#define __mutex_init(a, b, c) __db_win32_mutex_init(a, b, c) +#define __mutex_lock(a, b) __db_win32_mutex_lock(a, b, 0) +#define __mutex_timedlock(a, b, c) __db_win32_mutex_lock(a, b, c) +#define __mutex_trylock(a, b) __db_win32_mutex_trylock(a, b) +#define __mutex_unlock(a, b) __db_win32_mutex_unlock(a, b) +#define __mutex_destroy(a, b) __db_win32_mutex_destroy(a, b) +#ifdef HAVE_SHARED_LATCHES +#define __mutex_rdlock(a, b) __db_win32_mutex_readlock(a, b) +#define __mutex_tryrdlock(a, b) __db_win32_mutex_tryreadlock(a, b) +#endif +#elif defined(HAVE_MUTEX_FCNTL) +#define __mutex_init(a, b, c) __db_fcntl_mutex_init(a, b, c) +#define __mutex_lock(a, b) __db_fcntl_mutex_lock(a, b, 0) +#define __mutex_timedlock(a, b, c) __db_fcntl_lock(a, b, c) +#define __mutex_trylock(a, b) __db_fcntl_mutex_trylock(a, b) +#define __mutex_unlock(a, b) __db_fcntl_mutex_unlock(a, b) +#define __mutex_destroy(a, b) __db_fcntl_mutex_destroy(a, b) +#else +#define __mutex_init(a, b, c) __db_tas_mutex_init(a, b, c) +#define __mutex_lock(a, b) __db_tas_mutex_lock(a, b, 0) +#define __mutex_timedlock(a, b, c) __db_tas_mutex_lock(a, b, c) +#define __mutex_trylock(a, b) __db_tas_mutex_trylock(a, b) +#define __mutex_unlock(a, b) __db_tas_mutex_unlock(a, b) +#define __mutex_destroy(a, b) __db_tas_mutex_destroy(a, b) +#if defined(HAVE_SHARED_LATCHES) +#define __mutex_rdlock(a, b) __db_tas_mutex_readlock(a, b) +#define __mutex_tryrdlock(a,b) __db_tas_mutex_tryreadlock(a, b) +#endif +#endif + +/* + * When there is no method to get a shared latch, fall back to + * implementing __mutex_rdlock() as getting an exclusive one. + * This occurs either when !HAVE_SHARED_LATCHES or HAVE_MUTEX_FCNTL. + */ +#ifndef __mutex_rdlock +#define __mutex_rdlock(a, b) __mutex_lock(a, b) +#endif +#ifndef __mutex_tryrdlock +#define __mutex_tryrdlock(a, b) __mutex_trylock(a, b) +#endif + +/* + * Lock/unlock a mutex. If the mutex was never required, the thread of + * control can proceed without it. + * + * We never fail to acquire or release a mutex without panicing. Simplify + * the macros to always return a panic value rather than saving the actual + * return value of the mutex routine. + */ +#ifdef HAVE_MUTEX_SUPPORT +#define MUTEX_LOCK(env, mutex) do { \ + if ((mutex) != MUTEX_INVALID && \ + __mutex_lock(env, mutex) != 0) \ + return (DB_RUNRECOVERY); \ +} while (0) + +/* + * Always check the return value of MUTEX_TRYLOCK()! Expect 0 on success, + * or DB_LOCK_NOTGRANTED, or possibly DB_RUNRECOVERY for failchk. + */ +#define MUTEX_TRYLOCK(env, mutex) \ + (((mutex) == MUTEX_INVALID) ? 0 : __mutex_trylock(env, mutex)) + +/* + * Acquire a DB_MUTEX_SHARED "mutex" in shared mode. + */ +#define MUTEX_READLOCK(env, mutex) do { \ + if ((mutex) != MUTEX_INVALID && \ + __mutex_rdlock(env, mutex) != 0) \ + return (DB_RUNRECOVERY); \ +} while (0) +#define MUTEX_TRY_READLOCK(env, mutex) \ + ((mutex) != MUTEX_INVALID ? __mutex_tryrdlock(env, mutex) : 0) + +#define MUTEX_UNLOCK(env, mutex) do { \ + if ((mutex) != MUTEX_INVALID && \ + __mutex_unlock(env, mutex) != 0) \ + return (DB_RUNRECOVERY); \ +} while (0) + +#define MUTEX_WAIT(env, mutex, duration) do { \ + int __ret; \ + if ((mutex) != MUTEX_INVALID && \ + (__ret = __mutex_timedlock(env, mutex, duration)) != 0 && \ + __ret != DB_TIMEOUT) \ + return (DB_RUNRECOVERY); \ +} while (0) + +/* + * Check that a particular mutex is exclusively held at least by someone, not + * necessarily the current thread. + */ +#define MUTEX_IS_OWNED(env, mutex) \ + (mutex == MUTEX_INVALID || !MUTEX_ON(env) || \ + F_ISSET(env->dbenv, DB_ENV_NOLOCKING) || \ + F_ISSET(MUTEXP_SET(env, mutex), DB_MUTEX_LOCKED)) +#else +/* + * There are calls to lock/unlock mutexes outside of #ifdef's -- replace + * the call with something the compiler can discard, but which will make + * if-then-else blocks work correctly. + */ +#define MUTEX_LOCK(env, mutex) (mutex) = (mutex) +#define MUTEX_TRYLOCK(env, mutex) (mutex) = (mutex) +#define MUTEX_READLOCK(env, mutex) (mutex) = (mutex) +#define MUTEX_TRY_READLOCK(env, mutex) (mutex) = (mutex) +#define MUTEX_UNLOCK(env, mutex) (mutex) = (mutex) +#define MUTEX_REQUIRED(env, mutex) (mutex) = (mutex) +#define MUTEX_REQUIRED_READ(env, mutex) (mutex) = (mutex) +#define MUTEX_WAIT(env, mutex, duration) (mutex) = (mutex) +/* + * Every MUTEX_IS_OWNED() caller expects to own it. When there is no mutex + * support, act as if we have ownership. + */ +#define MUTEX_IS_OWNED(env, mutex) 1 +#endif + +/* + * Berkeley DB ports may require single-threading at places in the code. + */ +#ifdef HAVE_MUTEX_VXWORKS +#include "taskLib.h" +/* + * Use the taskLock() mutex to eliminate a race where two tasks are + * trying to initialize the global lock at the same time. + */ +#define DB_BEGIN_SINGLE_THREAD do { \ + if (DB_GLOBAL(db_global_init)) \ + (void)semTake(DB_GLOBAL(db_global_lock), WAIT_FOREVER); \ + else { \ + taskLock(); \ + if (DB_GLOBAL(db_global_init)) { \ + taskUnlock(); \ + (void)semTake(DB_GLOBAL(db_global_lock), \ + WAIT_FOREVER); \ + continue; \ + } \ + DB_GLOBAL(db_global_lock) = \ + semBCreate(SEM_Q_FIFO, SEM_EMPTY); \ + if (DB_GLOBAL(db_global_lock) != NULL) \ + DB_GLOBAL(db_global_init) = 1; \ + taskUnlock(); \ + } \ +} while (DB_GLOBAL(db_global_init) == 0) +#define DB_END_SINGLE_THREAD (void)semGive(DB_GLOBAL(db_global_lock)) +#endif + +/* + * Single-threading defaults to a no-op. + */ +#ifndef DB_BEGIN_SINGLE_THREAD +#define DB_BEGIN_SINGLE_THREAD +#endif +#ifndef DB_END_SINGLE_THREAD +#define DB_END_SINGLE_THREAD +#endif + +#if defined(__cplusplus) +} +#endif + +#include "dbinc_auto/mutex_ext.h" +#endif /* !_DB_MUTEX_H_ */ diff -r 000000000000 -r a1985f14b030 src/dbinc/mutex_int.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/dbinc/mutex_int.h Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,1079 @@ +/* + * See the file LICENSE for redistribution information. + * + * Copyright (c) 1996, 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + * $Id$ + */ + +#ifndef _DB_MUTEX_INT_H_ +#define _DB_MUTEX_INT_H_ + +#include "dbinc/atomic.h" + +#if defined(__cplusplus) +extern "C" { +#endif + +/* + * Mutexes and Shared Latches + * + * Mutexes may be test-and-set (spinning & yielding when busy), + * native versions (pthreads, WaitForSingleObject) + * or a hybrid which has the lower no-contention overhead of test-and-set + * mutexes, using operating system calls only to block and wakeup. + * + * Hybrid exclusive-only mutexes include a 'tas' field. + * Hybrid DB_MUTEX_SHARED latches also include a 'shared' field. + */ + +/********************************************************************* + * POSIX.1 pthreads interface. + *********************************************************************/ +#if defined(HAVE_MUTEX_PTHREADS) +/* + * Pthreads-based mutexes (exclusive-only) and latches (possibly shared) + * have the same MUTEX_FIELDS union. Different parts of the union are used + * depending on: + * - whether HAVE_SHARED_LATCHES is defined, and + * - if HAVE_SHARED_LATCHES, whether this particular instance of a mutex + * is a shared mutexDB_MUTEX_SHARED. + * + * The rwlock part of the union is used *only* for non-hybrid shared latches; + * in all other cases the mutex and cond fields are the only ones used. + * + * configuration & Who uses the field + * mutex + * mutex cond rwlock tas + * Native mutex y y + * Hybrid mutexes y y y + * Native sharedlatches y + * Hybrid sharedlatches y y y + * + * They all have a condition variable which is used only for + * DB_MUTEX_SELF_BLOCK waits. + * + * There can be no self-blocking shared latches: the pthread_cond_wait() would + * require getting a pthread_mutex_t, also it would not make sense. + */ +#define MUTEX_FIELDS \ + union { \ + struct { \ + pthread_mutex_t mutex; /* Mutex */ \ + pthread_cond_t cond; /* Condition variable */ \ + } m; \ + pthread_rwlock_t rwlock; /* Read/write lock */ \ + } u; + +#if defined(HAVE_SHARED_LATCHES) && !defined(HAVE_MUTEX_HYBRID) +#define RET_SET_PTHREAD_LOCK(mutexp, ret) do { \ + if (F_ISSET(mutexp, DB_MUTEX_SHARED)) \ + RET_SET((pthread_rwlock_wrlock(&(mutexp)->u.rwlock)), \ + ret); \ + else \ + RET_SET((pthread_mutex_lock(&(mutexp)->u.m.mutex)), ret); \ +} while (0) +#define RET_SET_PTHREAD_TRYLOCK(mutexp, ret) do { \ + if (F_ISSET(mutexp, DB_MUTEX_SHARED)) \ + RET_SET((pthread_rwlock_trywrlock(&(mutexp)->u.rwlock)), \ + ret); \ + else \ + RET_SET((pthread_mutex_trylock(&(mutexp)->u.m.mutex)), \ + ret); \ +} while (0) +#else +#define RET_SET_PTHREAD_LOCK(mutexp, ret) \ + RET_SET(pthread_mutex_lock(&(mutexp)->u.m.mutex), ret); +#define RET_SET_PTHREAD_TRYLOCK(mutexp, ret) \ + RET_SET(pthread_mutex_trylock(&(mutexp)->u.m.mutex), ret); +#endif +#endif + +#ifdef HAVE_MUTEX_UI_THREADS +#include +#endif + +/********************************************************************* + * Solaris lwp threads interface. + * + * !!! + * We use LWP mutexes on Solaris instead of UI or POSIX mutexes (both of + * which are available), for two reasons. First, the Solaris C library + * includes versions of the both UI and POSIX thread mutex interfaces, but + * they are broken in that they don't support inter-process locking, and + * there's no way to detect it, e.g., calls to configure the mutexes for + * inter-process locking succeed without error. So, we use LWP mutexes so + * that we don't fail in fairly undetectable ways because the application + * wasn't linked with the appropriate threads library. Second, there were + * bugs in SunOS 5.7 (Solaris 7) where if an application loaded the C library + * before loading the libthread/libpthread threads libraries (e.g., by using + * dlopen to load the DB library), the pwrite64 interface would be translated + * into a call to pwrite and DB would drop core. + *********************************************************************/ +#ifdef HAVE_MUTEX_SOLARIS_LWP +/* + * XXX + * Don't change to -- although lwp.h is listed in the + * Solaris manual page as the correct include to use, it causes the Solaris + * compiler on SunOS 2.6 to fail. + */ +#include + +#define MUTEX_FIELDS \ + lwp_mutex_t mutex; /* Mutex. */ \ + lwp_cond_t cond; /* Condition variable. */ +#endif + +/********************************************************************* + * Solaris/Unixware threads interface. + *********************************************************************/ +#ifdef HAVE_MUTEX_UI_THREADS +#include +#include + +#define MUTEX_FIELDS \ + mutex_t mutex; /* Mutex. */ \ + cond_t cond; /* Condition variable. */ +#endif + +/********************************************************************* + * AIX C library functions. + *********************************************************************/ +#ifdef HAVE_MUTEX_AIX_CHECK_LOCK +#include +typedef int tsl_t; + +#ifdef LOAD_ACTUAL_MUTEX_CODE +#define MUTEX_INIT(x) 0 +#define MUTEX_SET(x) (!_check_lock(x, 0, 1)) +#define MUTEX_UNSET(x) _clear_lock(x, 0) +#endif +#endif + +/********************************************************************* + * Apple/Darwin library functions. + *********************************************************************/ +#ifdef HAVE_MUTEX_DARWIN_SPIN_LOCK_TRY +typedef u_int32_t tsl_t; + +#ifdef LOAD_ACTUAL_MUTEX_CODE +extern int _spin_lock_try(tsl_t *); +extern void _spin_unlock(tsl_t *); +#define MUTEX_SET(tsl) _spin_lock_try(tsl) +#define MUTEX_UNSET(tsl) _spin_unlock(tsl) +#define MUTEX_INIT(tsl) (MUTEX_UNSET(tsl), 0) +#endif +#endif + +/********************************************************************* + * General C library functions (msemaphore). + * + * !!! + * Check for HPPA as a special case, because it requires unusual alignment, + * and doesn't support semaphores in malloc(3) or shmget(2) memory. + * + * !!! + * Do not remove the MSEM_IF_NOWAIT flag. The problem is that if a single + * process makes two msem_lock() calls in a row, the second one returns an + * error. We depend on the fact that we can lock against ourselves in the + * locking subsystem, where we set up a mutex so that we can block ourselves. + * Tested on OSF1 v4.0. + *********************************************************************/ +#ifdef HAVE_MUTEX_HPPA_MSEM_INIT +#define MUTEX_ALIGN 16 +#endif + +#if defined(HAVE_MUTEX_MSEM_INIT) || defined(HAVE_MUTEX_HPPA_MSEM_INIT) +#include +typedef msemaphore tsl_t; + +#ifdef LOAD_ACTUAL_MUTEX_CODE +#define MUTEX_INIT(x) (msem_init(x, MSEM_UNLOCKED) <= (msemaphore *)0) +#define MUTEX_SET(x) (!msem_lock(x, MSEM_IF_NOWAIT)) +#define MUTEX_UNSET(x) msem_unlock(x, 0) +#endif +#endif + +/********************************************************************* + * Plan 9 library functions. + *********************************************************************/ +#ifdef HAVE_MUTEX_PLAN9 +typedef Lock tsl_t; + +#define MUTEX_INIT(x) (memset(x, 0, sizeof(Lock)), 0) +#define MUTEX_SET(x) canlock(x) +#define MUTEX_UNSET(x) unlock(x) +#endif + +/********************************************************************* + * Reliant UNIX C library functions. + *********************************************************************/ +#ifdef HAVE_MUTEX_RELIANTUNIX_INITSPIN +#include +typedef spinlock_t tsl_t; + +#ifdef LOAD_ACTUAL_MUTEX_CODE +#define MUTEX_INIT(x) (initspin(x, 1), 0) +#define MUTEX_SET(x) (cspinlock(x) == 0) +#define MUTEX_UNSET(x) spinunlock(x) +#endif +#endif + +/********************************************************************* + * General C library functions (POSIX 1003.1 sema_XXX). + * + * !!! + * Never selected by autoconfig in this release (semaphore calls are known + * to not work in Solaris 5.5). + *********************************************************************/ +#ifdef HAVE_MUTEX_SEMA_INIT +#include +typedef sema_t tsl_t; + +#ifdef LOAD_ACTUAL_MUTEX_CODE +#define MUTEX_DESTROY(x) sema_destroy(x) +#define MUTEX_INIT(x) (sema_init(x, 1, USYNC_PROCESS, NULL) != 0) +#define MUTEX_SET(x) (sema_wait(x) == 0) +#define MUTEX_UNSET(x) sema_post(x) +#endif +#endif + +/********************************************************************* + * SGI C library functions. + *********************************************************************/ +#ifdef HAVE_MUTEX_SGI_INIT_LOCK +#include +typedef abilock_t tsl_t; + +#ifdef LOAD_ACTUAL_MUTEX_CODE +#define MUTEX_INIT(x) (init_lock(x) != 0) +#define MUTEX_SET(x) (!acquire_lock(x)) +#define MUTEX_UNSET(x) release_lock(x) +#endif +#endif + +/********************************************************************* + * Solaris C library functions. + * + * !!! + * These are undocumented functions, but they're the only ones that work + * correctly as far as we know. + *********************************************************************/ +#ifdef HAVE_MUTEX_SOLARIS_LOCK_TRY +#include +#define MUTEX_MEMBAR(x) membar_enter() +#define MEMBAR_ENTER() membar_enter() +#define MEMBAR_EXIT() membar_exit() +#include +typedef lock_t tsl_t; + +/* + * The functions are declared in , but under #ifdef KERNEL. + * Re-declare them here to avoid warnings. + */ +extern int _lock_try(lock_t *); +extern void _lock_clear(lock_t *); + +#ifdef LOAD_ACTUAL_MUTEX_CODE +#define MUTEX_INIT(x) 0 +#define MUTEX_SET(x) _lock_try(x) +#define MUTEX_UNSET(x) _lock_clear(x) +#endif +#endif + +/********************************************************************* + * VMS. + *********************************************************************/ +#ifdef HAVE_MUTEX_VMS +#include +#include +typedef volatile unsigned char tsl_t; + +#ifdef LOAD_ACTUAL_MUTEX_CODE +#ifdef __ALPHA +#define MUTEX_SET(tsl) (!__TESTBITSSI(tsl, 0)) +#else /* __VAX */ +#define MUTEX_SET(tsl) (!(int)_BBSSI(0, tsl)) +#endif +#define MUTEX_UNSET(tsl) (*(tsl) = 0) +#define MUTEX_INIT(tsl) (MUTEX_UNSET(tsl), 0) +#endif +#endif + +/********************************************************************* + * VxWorks + * Use basic binary semaphores in VxWorks, as we currently do not need + * any special features. We do need the ability to single-thread the + * entire system, however, because VxWorks doesn't support the open(2) + * flag O_EXCL, the mechanism we normally use to single thread access + * when we're first looking for a DB environment. + *********************************************************************/ +#ifdef HAVE_MUTEX_VXWORKS +#include "taskLib.h" +typedef SEM_ID tsl_t; + +#ifdef LOAD_ACTUAL_MUTEX_CODE +/* + * Uses of this MUTEX_SET() need to have a local 'nowait' variable, + * which determines whether to return right away when the semaphore + * is busy or to wait until it is available. + */ +#define MUTEX_SET(tsl) \ + (semTake((*(tsl)), nowait ? NO_WAIT : WAIT_FOREVER) == OK) +#define MUTEX_UNSET(tsl) (semGive((*tsl))) +#define MUTEX_INIT(tsl) \ + ((*(tsl) = semBCreate(SEM_Q_FIFO, SEM_FULL)) == NULL) +#define MUTEX_DESTROY(tsl) semDelete(*tsl) +#endif +#endif + +/********************************************************************* + * Win16 + * + * Win16 spinlocks are simple because we cannot possibly be preempted. + * + * !!! + * We should simplify this by always returning a no-need-to-lock lock + * when we initialize the mutex. + *********************************************************************/ +#ifdef HAVE_MUTEX_WIN16 +typedef unsigned int tsl_t; + +#ifdef LOAD_ACTUAL_MUTEX_CODE +#define MUTEX_INIT(x) 0 +#define MUTEX_SET(tsl) (*(tsl) = 1) +#define MUTEX_UNSET(tsl) (*(tsl) = 0) +#endif +#endif + +/********************************************************************* + * Win32 - always a hybrid mutex + *********************************************************************/ +#if defined(HAVE_MUTEX_WIN32) || defined(HAVE_MUTEX_WIN32_GCC) +typedef LONG volatile tsl_t; +#define MUTEX_FIELDS \ + LONG nwaiters; \ + u_int32_t id; /* ID used for creating events */ \ + +#if defined(LOAD_ACTUAL_MUTEX_CODE) +#define MUTEX_SET(tsl) (!InterlockedExchange((PLONG)tsl, 1)) +#define MUTEX_UNSET(tsl) InterlockedExchange((PLONG)tsl, 0) +#define MUTEX_INIT(tsl) MUTEX_UNSET(tsl) + +/* + * From Intel's performance tuning documentation (and see SR #6975): + * ftp://download.intel.com/design/perftool/cbts/appnotes/sse2/w_spinlock.pdf + * + * "For this reason, it is highly recommended that you insert the PAUSE + * instruction into all spin-wait code immediately. Using the PAUSE + * instruction does not affect the correctness of programs on existing + * platforms, and it improves performance on Pentium 4 processor platforms." + */ +#ifdef HAVE_MUTEX_WIN32 +#if !defined(_WIN64) && !defined(DB_WINCE) +#define MUTEX_PAUSE {__asm{_emit 0xf3}; __asm{_emit 0x90}} +#endif +#endif +#ifdef HAVE_MUTEX_WIN32_GCC +#define MUTEX_PAUSE __asm__ volatile ("rep; nop" : : ); +#endif +#endif +#endif + +/********************************************************************* + * 68K/gcc assembly. + *********************************************************************/ +#ifdef HAVE_MUTEX_68K_GCC_ASSEMBLY +typedef unsigned char tsl_t; + +#ifdef LOAD_ACTUAL_MUTEX_CODE +/* gcc/68K: 0 is clear, 1 is set. */ +#define MUTEX_SET(tsl) ({ \ + register tsl_t *__l = (tsl); \ + int __r; \ + __asm__ volatile("tas %1; \n \ + seq %0" \ + : "=dm" (__r), "=m" (*__l) \ + : "1" (*__l) \ + ); \ + __r & 1; \ +}) + +#define MUTEX_UNSET(tsl) (*(tsl) = 0) +#define MUTEX_INIT(tsl) (MUTEX_UNSET(tsl), 0) +#endif +#endif + +/********************************************************************* + * ALPHA/gcc assembly. + *********************************************************************/ +#ifdef HAVE_MUTEX_ALPHA_GCC_ASSEMBLY +typedef u_int32_t tsl_t; + +#define MUTEX_ALIGN 4 + +#ifdef LOAD_ACTUAL_MUTEX_CODE +/* + * For gcc/alpha. Should return 0 if could not acquire the lock, 1 if + * lock was acquired properly. + */ +static inline int +MUTEX_SET(tsl_t *tsl) { + register tsl_t *__l = tsl; + register tsl_t __r; + __asm__ volatile( + "1: ldl_l %0,%2\n" + " blbs %0,2f\n" + " or $31,1,%0\n" + " stl_c %0,%1\n" + " beq %0,3f\n" + " mb\n" + " br 3f\n" + "2: xor %0,%0\n" + "3:" + : "=&r"(__r), "=m"(*__l) : "1"(*__l) : "memory"); + return __r; +} + +/* + * Unset mutex. Judging by Alpha Architecture Handbook, the mb instruction + * might be necessary before unlocking + */ +static inline int +MUTEX_UNSET(tsl_t *tsl) { + __asm__ volatile(" mb\n"); + return *tsl = 0; +} + +#define MUTEX_INIT(tsl) MUTEX_UNSET(tsl) +#endif +#endif + +/********************************************************************* + * Tru64/cc assembly. + *********************************************************************/ +#ifdef HAVE_MUTEX_TRU64_CC_ASSEMBLY +typedef volatile u_int32_t tsl_t; + +#define MUTEX_ALIGN 4 + +#ifdef LOAD_ACTUAL_MUTEX_CODE +#include +#define MUTEX_SET(tsl) (__LOCK_LONG_RETRY((tsl), 1) != 0) +#define MUTEX_UNSET(tsl) (__UNLOCK_LONG(tsl)) + +#define MUTEX_INIT(tsl) (MUTEX_UNSET(tsl), 0) +#endif +#endif + +/********************************************************************* + * ARM/gcc assembly. + *********************************************************************/ +#ifdef HAVE_MUTEX_ARM_GCC_ASSEMBLY +typedef unsigned char tsl_t; + +#ifdef LOAD_ACTUAL_MUTEX_CODE +/* gcc/arm: 0 is clear, 1 is set. */ +#define MUTEX_SET(tsl) ({ \ + int __r; \ + __asm__ volatile( \ + "swpb %0, %1, [%2]\n\t" \ + "eor %0, %0, #1\n\t" \ + : "=&r" (__r) \ + : "r" (1), "r" (tsl) \ + ); \ + __r & 1; \ +}) + +#define MUTEX_UNSET(tsl) (*(volatile tsl_t *)(tsl) = 0) +#define MUTEX_INIT(tsl) (MUTEX_UNSET(tsl), 0) +#endif +#endif + +/********************************************************************* + * HPPA/gcc assembly. + *********************************************************************/ +#ifdef HAVE_MUTEX_HPPA_GCC_ASSEMBLY +typedef u_int32_t tsl_t; + +#define MUTEX_ALIGN 16 + +#ifdef LOAD_ACTUAL_MUTEX_CODE +/* + * The PA-RISC has a "load and clear" instead of a "test and set" instruction. + * The 32-bit word used by that instruction must be 16-byte aligned. We could + * use the "aligned" attribute in GCC but that doesn't work for stack variables. + */ +#define MUTEX_SET(tsl) ({ \ + register tsl_t *__l = (tsl); \ + int __r; \ + __asm__ volatile("ldcws 0(%1),%0" : "=r" (__r) : "r" (__l)); \ + __r & 1; \ +}) + +#define MUTEX_UNSET(tsl) (*(volatile tsl_t *)(tsl) = -1) +#define MUTEX_INIT(tsl) (MUTEX_UNSET(tsl), 0) +#endif +#endif + +/********************************************************************* + * IA64/gcc assembly. + *********************************************************************/ +#ifdef HAVE_MUTEX_IA64_GCC_ASSEMBLY +typedef volatile unsigned char tsl_t; + +#ifdef LOAD_ACTUAL_MUTEX_CODE +/* gcc/ia64: 0 is clear, 1 is set. */ +#define MUTEX_SET(tsl) ({ \ + register tsl_t *__l = (tsl); \ + long __r; \ + __asm__ volatile("xchg1 %0=%1,%2" : \ + "=r"(__r), "+m"(*__l) : "r"(1)); \ + __r ^ 1; \ +}) + +/* + * Store through a "volatile" pointer so we get a store with "release" + * semantics. + */ +#define MUTEX_UNSET(tsl) (*(tsl_t *)(tsl) = 0) +#define MUTEX_INIT(tsl) (MUTEX_UNSET(tsl), 0) +#endif +#endif + +/********************************************************************* + * PowerPC/gcc assembly. + *********************************************************************/ +#if defined(HAVE_MUTEX_PPC_GCC_ASSEMBLY) +typedef u_int32_t tsl_t; + +#ifdef LOAD_ACTUAL_MUTEX_CODE +/* + * The PowerPC does a sort of pseudo-atomic locking. You set up a + * 'reservation' on a chunk of memory containing a mutex by loading the + * mutex value with LWARX. If the mutex has an 'unlocked' (arbitrary) + * value, you then try storing into it with STWCX. If no other process or + * thread broke your 'reservation' by modifying the memory containing the + * mutex, then the STCWX succeeds; otherwise it fails and you try to get + * a reservation again. + * + * While mutexes are explicitly 4 bytes, a 'reservation' applies to an + * entire cache line, normally 32 bytes, aligned naturally. If the mutex + * lives near data that gets changed a lot, there's a chance that you'll + * see more broken reservations than you might otherwise. The only + * situation in which this might be a problem is if one processor is + * beating on a variable in the same cache block as the mutex while another + * processor tries to acquire the mutex. That's bad news regardless + * because of the way it bashes caches, but if you can't guarantee that a + * mutex will reside in a relatively quiescent cache line, you might + * consider padding the mutex to force it to live in a cache line by + * itself. No, you aren't guaranteed that cache lines are 32 bytes. Some + * embedded processors use 16-byte cache lines, while some 64-bit + * processors use 128-bit cache lines. But assuming a 32-byte cache line + * won't get you into trouble for now. + * + * If mutex locking is a bottleneck, then you can speed it up by adding a + * regular LWZ load before the LWARX load, so that you can test for the + * common case of a locked mutex without wasting cycles making a reservation. + * + * gcc/ppc: 0 is clear, 1 is set. + */ +static inline int +MUTEX_SET(int *tsl) { + int __r; + __asm__ volatile ( +"0: \n\t" +" lwarx %0,0,%1 \n\t" +" cmpwi %0,0 \n\t" +" bne- 1f \n\t" +" stwcx. %1,0,%1 \n\t" +" isync \n\t" +" beq+ 2f \n\t" +" b 0b \n\t" +"1: \n\t" +" li %1,0 \n\t" +"2: \n\t" + : "=&r" (__r), "+r" (tsl) + : + : "cr0", "memory"); + return (int)tsl; +} + +static inline int +MUTEX_UNSET(tsl_t *tsl) { + __asm__ volatile("sync" : : : "memory"); + return *tsl = 0; +} +#define MUTEX_INIT(tsl) MUTEX_UNSET(tsl) +#endif +#endif + +/********************************************************************* + * OS/390 C. + *********************************************************************/ +#ifdef HAVE_MUTEX_S390_CC_ASSEMBLY +typedef int tsl_t; + +#ifdef LOAD_ACTUAL_MUTEX_CODE +/* + * cs() is declared in but is built in to the compiler. + * Must use LANGLVL(EXTENDED) to get its declaration. + */ +#define MUTEX_SET(tsl) (!cs(&zero, (tsl), 1)) +#define MUTEX_UNSET(tsl) (*(tsl) = 0) +#define MUTEX_INIT(tsl) (MUTEX_UNSET(tsl), 0) +#endif +#endif + +/********************************************************************* + * S/390 32-bit assembly. + *********************************************************************/ +#ifdef HAVE_MUTEX_S390_GCC_ASSEMBLY +typedef int tsl_t; + +#ifdef LOAD_ACTUAL_MUTEX_CODE +/* gcc/S390: 0 is clear, 1 is set. */ +static inline int +MUTEX_SET(tsl_t *tsl) { \ + register tsl_t *__l = (tsl); \ + int __r; \ + __asm__ volatile( \ + " la 1,%1\n" \ + " lhi 0,1\n" \ + " l %0,%1\n" \ + "0: cs %0,0,0(1)\n" \ + " jl 0b" \ + : "=&d" (__r), "+m" (*__l) \ + : : "0", "1", "cc"); \ + return !__r; \ +} + +#define MUTEX_UNSET(tsl) (*(tsl) = 0) +#define MUTEX_INIT(tsl) (MUTEX_UNSET(tsl), 0) +#endif +#endif + +/********************************************************************* + * SCO/cc assembly. + *********************************************************************/ +#ifdef HAVE_MUTEX_SCO_X86_CC_ASSEMBLY +typedef unsigned char tsl_t; + +#ifdef LOAD_ACTUAL_MUTEX_CODE +/* + * UnixWare has threads in libthread, but OpenServer doesn't (yet). + * + * cc/x86: 0 is clear, 1 is set. + */ +#if defined(__USLC__) +asm int +_tsl_set(void *tsl) +{ +%mem tsl + movl tsl, %ecx + movl $1, %eax + lock + xchgb (%ecx),%al + xorl $1,%eax +} +#endif + +#define MUTEX_SET(tsl) _tsl_set(tsl) +#define MUTEX_UNSET(tsl) (*(tsl) = 0) +#define MUTEX_INIT(tsl) (MUTEX_UNSET(tsl), 0) +#endif +#endif + +/********************************************************************* + * Sparc/gcc assembly. + *********************************************************************/ +#ifdef HAVE_MUTEX_SPARC_GCC_ASSEMBLY +typedef unsigned char tsl_t; + +#define MUTEX_ALIGN 8 + +#ifdef LOAD_ACTUAL_MUTEX_CODE +/* + * The ldstub instruction takes the location specified by its first argument + * (a register containing a memory address) and loads its contents into its + * second argument (a register) and atomically sets the contents the location + * specified by its first argument to a byte of 1s. (The value in the second + * argument is never read, but only overwritten.) + * + * Hybrid mutexes require membar #StoreLoad and #LoadStore ordering on multi- + * processor v9 systems. + * + * gcc/sparc: 0 is clear, 1 is set. + */ +#define MUTEX_SET(tsl) ({ \ + register tsl_t *__l = (tsl); \ + register tsl_t __r; \ + __asm__ volatile \ + ("ldstub [%1],%0; stbar" \ + : "=r"( __r) : "r" (__l)); \ + !__r; \ +}) + +#define MUTEX_UNSET(tsl) (*(tsl) = 0, MUTEX_MEMBAR(tsl)) +#define MUTEX_INIT(tsl) (MUTEX_UNSET(tsl), 0) +#define MUTEX_MEMBAR(x) \ + ({ __asm__ volatile ("membar #StoreStore|#StoreLoad|#LoadStore"); }) +#define MEMBAR_ENTER() \ + ({ __asm__ volatile ("membar #StoreStore|#StoreLoad"); }) +#define MEMBAR_EXIT() \ + ({ __asm__ volatile ("membar #StoreStore|#LoadStore"); }) +#endif +#endif + +/********************************************************************* + * UTS/cc assembly. + *********************************************************************/ +#ifdef HAVE_MUTEX_UTS_CC_ASSEMBLY +typedef int tsl_t; + +#ifdef LOAD_ACTUAL_MUTEX_CODE +#define MUTEX_INIT(x) 0 +#define MUTEX_SET(x) (!uts_lock(x, 1)) +#define MUTEX_UNSET(x) (*(x) = 0) +#endif +#endif + +/********************************************************************* + * MIPS/gcc assembly. + *********************************************************************/ +#ifdef HAVE_MUTEX_MIPS_GCC_ASSEMBLY +typedef u_int32_t tsl_t; + +#define MUTEX_ALIGN 4 + +#ifdef LOAD_ACTUAL_MUTEX_CODE +/* + * For gcc/MIPS. Should return 0 if could not acquire the lock, 1 if + * lock was acquired properly. + */ +static inline int +MUTEX_SET(tsl_t *tsl) { + register tsl_t *__l = tsl; + register tsl_t __r, __t; + __asm__ volatile( + " .set push \n" + " .set mips2 \n" + " .set noreorder \n" + " .set nomacro \n" + "1: ll %0, %3 \n" + " ori %2, %0, 1 \n" + " sc %2, %1 \n" + " beqzl %2, 1b \n" + " nop \n" + " andi %2, %0, 1 \n" + " sync \n" + " .set reorder \n" + " .set pop \n" + : "=&r" (__t), "=m" (*tsl), "=&r" (__r) + : "m" (*tsl) + : "memory"); + return (!__r); +} + +static inline void +MUTEX_UNSET(tsl_t *tsl) { + __asm__ volatile( + " .set noreorder \n" + " sync \n" + " sw $0, %0 \n" + " .set reorder \n" + : "=m" (*tsl) + : "m" (*tsl) + : "memory"); +} + +#define MUTEX_INIT(tsl) (*(tsl) = 0) +#endif +#endif + +/********************************************************************* + * x86/gcc (32- and 64-bit) assembly. + *********************************************************************/ +#if defined(HAVE_MUTEX_X86_GCC_ASSEMBLY) || \ + defined(HAVE_MUTEX_X86_64_GCC_ASSEMBLY) +typedef volatile unsigned char tsl_t; + +#ifdef LOAD_ACTUAL_MUTEX_CODE +/* gcc/x86: 0 is clear, 1 is set. */ +#define MUTEX_SET(tsl) ({ \ + tsl_t __r; \ + __asm__ volatile("movb $1, %b0\n\t" \ + "xchgb %b0,%1" \ + : "=&q" (__r) \ + : "m" (*(tsl_t *)(tsl)) \ + : "memory", "cc"); \ + !__r; /* return 1 on success, 0 on failure */ \ +}) + +#define MUTEX_UNSET(tsl) (*(tsl_t *)(tsl) = 0) +#define MUTEX_INIT(tsl) (MUTEX_UNSET(tsl), 0) +/* + * We need to pass a valid address to generate the memory barrier + * otherwise PURIFY will complain. Use something referenced recently + * and initialized. + */ +#if defined(HAVE_MUTEX_X86_GCC_ASSEMBLY) +#define MUTEX_MEMBAR(addr) \ + ({ __asm__ volatile ("lock; addl $0, %0" ::"m" (addr): "memory"); 1; }) +#else +#define MUTEX_MEMBAR(addr) \ + ({ __asm__ volatile ("mfence" ::: "memory"); 1; }) +#endif + +/* + * From Intel's performance tuning documentation (and see SR #6975): + * ftp://download.intel.com/design/perftool/cbts/appnotes/sse2/w_spinlock.pdf + * + * "For this reason, it is highly recommended that you insert the PAUSE + * instruction into all spin-wait code immediately. Using the PAUSE + * instruction does not affect the correctness of programs on existing + * platforms, and it improves performance on Pentium 4 processor platforms." + */ +#define MUTEX_PAUSE __asm__ volatile ("rep; nop" : : ); +#endif +#endif + +/* End of operating system & hardware architecture-specific definitions */ + +/* + * Mutex alignment defaults to sizeof(unsigned int). + * + * !!! + * Various systems require different alignments for mutexes (the worst we've + * seen so far is 16-bytes on some HP architectures). Malloc(3) is assumed + * to return reasonable alignment, all other mutex users must ensure proper + * alignment locally. + */ +#ifndef MUTEX_ALIGN +#define MUTEX_ALIGN sizeof(unsigned int) +#endif + +/* + * Mutex destruction defaults to a no-op. + */ +#ifndef MUTEX_DESTROY +#define MUTEX_DESTROY(x) +#endif + +/* + * Mutex pause defaults to a no-op. + */ +#ifndef MUTEX_PAUSE +#define MUTEX_PAUSE +#endif + +/* + * If no native atomic support is available then use mutexes to + * emulate atomic increment, decrement, and compare-and-exchange. + * The address of the atomic value selects which of a small number + * of mutexes to use to protect the updates. + * The number of mutexes should be somewhat larger than the number of + * processors in the system in order to minimize unnecessary contention. + * It defaults to 8 to handle most small (1-4) cpu systems, if it hasn't + * already been defined (e.g. in db_config.h) + */ +#if !defined(HAVE_ATOMIC_SUPPORT) && defined(HAVE_MUTEX_SUPPORT) && \ + !defined(MAX_ATOMIC_MUTEXES) +#define MAX_ATOMIC_MUTEXES 1 +#endif + +/* + * DB_MUTEXMGR -- + * The mutex manager encapsulates the mutex system. + */ +struct __db_mutexmgr { + /* These fields are never updated after creation, so not protected. */ + DB_ENV *dbenv; /* Environment */ + REGINFO reginfo; /* Region information */ + + void *mutex_array; /* Base of the mutex array */ +}; + +/* Macros to lock/unlock the mutex region as a whole. */ +#define MUTEX_SYSTEM_LOCK(dbenv) \ + MUTEX_LOCK(dbenv, ((DB_MUTEXREGION *) \ + (dbenv)->mutex_handle->reginfo.primary)->mtx_region) +#define MUTEX_SYSTEM_UNLOCK(dbenv) \ + MUTEX_UNLOCK(dbenv, ((DB_MUTEXREGION *) \ + (dbenv)->mutex_handle->reginfo.primary)->mtx_region) + +/* + * DB_MUTEXREGION -- + * The primary mutex data structure in the shared memory region. + */ +typedef struct __db_mutexregion { /* SHARED */ + /* These fields are initialized at create time and never modified. */ + roff_t mutex_off_alloc;/* Offset of mutex array */ + roff_t mutex_off; /* Adjusted offset of mutex array */ + db_size_t mutex_size; /* Size of the aligned mutex */ + roff_t thread_off; /* Offset of the thread area. */ + + db_mutex_t mtx_region; /* Region mutex. */ + + /* Protected using the region mutex. */ + db_mutex_t mutex_next; /* Next free mutex */ + +#if !defined(HAVE_ATOMIC_SUPPORT) && defined(HAVE_MUTEX_SUPPORT) + /* Mutexes for emulating atomic operations. */ + db_mutex_t mtx_atomic[MAX_ATOMIC_MUTEXES]; +#endif + + DB_MUTEX_STAT stat; /* Mutex statistics */ +} DB_MUTEXREGION; + +#ifdef HAVE_MUTEX_SUPPORT +struct __db_mutex_t { /* SHARED */ /* Mutex. */ +#ifdef MUTEX_FIELDS + MUTEX_FIELDS /* Opaque thread mutex structures. */ +#endif +#ifndef HAVE_MUTEX_FCNTL +#if defined(HAVE_MUTEX_HYBRID) || \ + (defined(HAVE_SHARED_LATCHES) && !defined(HAVE_MUTEX_PTHREADS)) + /* + * For hybrid and test-and-set shared latches it is a counter: + * 0 means it is free, + * -1 is exclusively locked, + * > 0 is the number of shared readers. + * Pthreads shared latches use pthread_rwlock instead. + */ + tsl_t tas; + db_atomic_t sharecount; +#elif !defined(MUTEX_FIELDS) + /* + * This is the Test and Set flag for exclusive latches (mutexes): + * there is a free value (often 0, 1, or -1) and a set value. + */ + tsl_t tas; +#endif +#endif +#ifdef HAVE_MUTEX_HYBRID + volatile u_int32_t wait; /* Count of waiters. */ +#endif + pid_t pid; /* Process owning mutex */ + db_threadid_t tid; /* Thread owning mutex */ + + db_mutex_t mutex_next_link; /* Linked list of free mutexes. */ + +#ifdef HAVE_STATISTICS + int alloc_id; /* Allocation ID. */ + + u_int32_t mutex_set_wait; /* Granted after wait. */ + u_int32_t mutex_set_nowait; /* Granted without waiting. */ +#ifdef HAVE_SHARED_LATCHES + u_int32_t mutex_set_rd_wait; /* Granted shared lock after wait. */ + u_int32_t mutex_set_rd_nowait; /* Granted shared lock w/out waiting. */ +#endif +#ifdef HAVE_MUTEX_HYBRID + u_int32_t hybrid_wait; + u_int32_t hybrid_wakeup; /* for counting spurious wakeups */ +#endif +#endif + + /* + * A subset of the flag arguments for __mutex_alloc(). + * + * Flags should be an unsigned integer even if it's not required by + * the possible flags values, getting a single byte on some machines + * is expensive, and the mutex structure is a MP hot spot. + */ + volatile u_int32_t flags; /* MUTEX_XXX */ +}; +#endif + +/* Macro to get a reference to a specific mutex. */ +#define MUTEXP_SET(env, indx) \ + (F_ISSET(env, ENV_PRIVATE) ? (DB_MUTEX *) indx : \ + (DB_MUTEX *)((u_int8_t *)env->mutex_handle->mutex_array + \ + (indx) * \ + ((DB_MUTEXREGION *)env->mutex_handle->reginfo.primary)->mutex_size)) + +#if defined(HAVE_MUTEX_HYBRID) || defined(DB_WIN32) || \ + (defined(HAVE_SHARED_LATCHES) && !defined(HAVE_MUTEX_PTHREADS)) +#define MUTEXP_IS_BUSY(mutexp) \ + (F_ISSET(mutexp, DB_MUTEX_SHARED) ? \ + (atomic_read(&(mutexp)->sharecount) != 0) : \ + F_ISSET(mutexp, DB_MUTEX_LOCKED)) +#define MUTEXP_BUSY_FIELD(mutexp) \ + (F_ISSET(mutexp, DB_MUTEX_SHARED) ? \ + (atomic_read(&(mutexp)->sharecount)) : (mutexp)->flags) +#else +/* Pthread_rwlocks don't have an low-cost 'is it being shared?' predicate. */ +#define MUTEXP_IS_BUSY(mutexp) (F_ISSET((mutexp), DB_MUTEX_LOCKED)) +#define MUTEXP_BUSY_FIELD(mutexp) ((mutexp)->flags) +#endif + +#define MUTEX_IS_BUSY(env, mutex) \ + (mutex == MUTEX_INVALID || !MUTEX_ON(env) || \ + F_ISSET(env->dbenv, DB_ENV_NOLOCKING) || \ + MUTEXP_IS_BUSY(MUTEXP_SET(env, mutex))) + +#define MUTEX_REQUIRED(env, mutex) \ + DB_ASSERT(env, MUTEX_IS_OWNED(env, mutex)) + +#define MUTEX_REQUIRED_READ(env, mutex) \ + DB_ASSERT(env, MUTEX_IS_OWNED(env, mutex) || MUTEX_IS_BUSY(env, mutex)) + +/* + * Test and set (and thus hybrid) shared latches use compare & exchange + * to acquire; the others the mutex-setting primitive defined above. + */ +#ifdef LOAD_ACTUAL_MUTEX_CODE + +#if defined(HAVE_SHARED_LATCHES) +/* This is the value of the 'sharecount' of an exclusively held tas latch. + * The particular value is not special; it is just unlikely to be caused + * by releasing or acquiring a shared latch too many times. + */ +#define MUTEX_SHARE_ISEXCLUSIVE (-1024) + +/* + * Get an exclusive lock on a possibly sharable latch. We use the native + * MUTEX_SET() operation for non-sharable latches; it usually is faster. + */ +#define MUTEXP_ACQUIRE(mutexp) \ + (F_ISSET(mutexp, DB_MUTEX_SHARED) ? \ + atomic_compare_exchange(env, \ + &(mutexp)->sharecount, 0, MUTEX_SHARE_ISEXCLUSIVE) : \ + MUTEX_SET(&(mutexp)->tas)) +#else +#define MUTEXP_ACQUIRE(mutexp) MUTEX_SET(&(mutexp)->tas) +#endif + +#ifndef MEMBAR_ENTER +#define MEMBAR_ENTER() +#define MEMBAR_EXIT() +#endif + +#endif + +#if defined(__cplusplus) +} +#endif +#endif /* !_DB_MUTEX_INT_H_ */ diff -r 000000000000 -r a1985f14b030 src/dbinc/os.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/dbinc/os.h Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,200 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 1997, 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + * $Id$ + */ + +#ifndef _DB_OS_H_ +#define _DB_OS_H_ + +#if defined(__cplusplus) +extern "C" { +#endif + +/* Number of times to retry system calls that return EINTR or EBUSY. */ +#define DB_RETRY 100 + +#ifdef __TANDEM +/* + * OSS Tandem problem: fsync can return a Guardian file system error of 70, + * which has no symbolic name in OSS. HP says to retry the fsync. [#12957] + */ +#define RETRY_CHK(op, ret) do { \ + int __retries, __t_ret; \ + for ((ret) = 0, __retries = DB_RETRY;;) { \ + if ((op) == 0) \ + break; \ + (ret) = __os_get_syserr(); \ + if (((__t_ret = __os_posix_err(ret)) == EAGAIN || \ + __t_ret == EBUSY || __t_ret == EINTR || \ + __t_ret == EIO || __t_ret == 70) && --__retries > 0)\ + continue; \ + break; \ + } \ +} while (0) +#else +#define RETRY_CHK(op, ret) do { \ + int __retries, __t_ret; \ + for ((ret) = 0, __retries = DB_RETRY;;) { \ + if ((op) == 0) \ + break; \ + (ret) = __os_get_syserr(); \ + if (((__t_ret = __os_posix_err(ret)) == EAGAIN || \ + __t_ret == EBUSY || __t_ret == EINTR || \ + __t_ret == EIO) && --__retries > 0) \ + continue; \ + break; \ + } \ +} while (0) +#endif + +#define RETRY_CHK_EINTR_ONLY(op, ret) do { \ + int __retries; \ + for ((ret) = 0, __retries = DB_RETRY;;) { \ + if ((op) == 0) \ + break; \ + (ret) = __os_get_syserr(); \ + if (__os_posix_err(ret) == EINTR && --__retries > 0) \ + continue; \ + break; \ + } \ +} while (0) + +/* + * Flags understood by __os_open. + */ +#define DB_OSO_ABSMODE 0x0001 /* Absolute mode specified. */ +#define DB_OSO_CREATE 0x0002 /* POSIX: O_CREAT */ +#define DB_OSO_DIRECT 0x0004 /* Don't buffer the file in the OS. */ +#define DB_OSO_DSYNC 0x0008 /* POSIX: O_DSYNC. */ +#define DB_OSO_EXCL 0x0010 /* POSIX: O_EXCL */ +#define DB_OSO_RDONLY 0x0020 /* POSIX: O_RDONLY */ +#define DB_OSO_REGION 0x0040 /* Opening a region file. */ +#define DB_OSO_SEQ 0x0080 /* Expected sequential access. */ +#define DB_OSO_TEMP 0x0100 /* Remove after last close. */ +#define DB_OSO_TRUNC 0x0200 /* POSIX: O_TRUNC */ + +/* + * File modes. + */ +#define DB_MODE_400 (S_IRUSR) +#define DB_MODE_600 (S_IRUSR|S_IWUSR) +#define DB_MODE_660 (S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP) +#define DB_MODE_666 (S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH) +#define DB_MODE_700 (S_IRUSR|S_IWUSR|S_IXUSR) + +/* + * We group certain seek/write calls into a single function so that we + * can use pread(2)/pwrite(2) where they're available. + */ +#define DB_IO_READ 1 +#define DB_IO_WRITE 2 + +/* + * Make a last "panic" check. Imagine a thread of control running in Berkeley + * DB, going to sleep. Another thread of control decides to run recovery + * because the environment is broken. The first thing recovery does is panic + * the existing environment, but we only check the panic flag when crossing the + * public API. If the sleeping thread wakes up and writes something, we could + * have two threads of control writing the log files at the same time. So, + * before reading or writing, make a last panic check. Obviously, there's still + * a window, but it's very, very small. + */ +#define LAST_PANIC_CHECK_BEFORE_IO(env) \ + PANIC_CHECK(env); \ + if (env != NULL && \ + F_ISSET((env)->dbenv, DB_ENV_NOFLUSH)) \ + return (0) \ + \ +/* DB filehandle. */ +struct __fh_t { + /* + * Linked list of DB_FH's, linked from the DB_ENV, used to keep track + * of all open file handles for resource cleanup. + */ + TAILQ_ENTRY(__fh_t) q; + + /* + * The file-handle mutex is only used to protect the handle/fd + * across seek and read/write pairs, it does not protect the + * the reference count, or any other fields in the structure. + */ + db_mutex_t mtx_fh; /* Mutex to lock. */ + + int ref; /* Reference count. */ + +#if defined(DB_WIN32) + HANDLE handle; /* Windows/32 file handle. */ + HANDLE trunc_handle; /* Handle for truncate calls. */ +#endif + int fd; /* POSIX file descriptor. */ + + char *name; /* File name at open. */ + + /* + * Last seek statistics, used for zero-filling on filesystems + * that don't support it directly. + */ + db_pgno_t pgno; + u_int32_t pgsize; + off_t offset; + +#ifdef HAVE_STATISTICS + u_int32_t seek_count; /* I/O statistics */ + u_int32_t read_count; + u_int32_t write_count; +#endif + +#define DB_FH_ENVLINK 0x01 /* We're linked on the DB_ENV. */ +#define DB_FH_NOSYNC 0x02 /* Handle doesn't need to be sync'd. */ +#define DB_FH_OPENED 0x04 /* Handle is valid. */ +#define DB_FH_UNLINK 0x08 /* Unlink on close */ +#define DB_FH_REGION 0x10 /* Opened to contain a region */ + u_int8_t flags; +}; + +/* Standard buffer size for ctime/ctime_r function calls. */ +#define CTIME_BUFLEN 26 + +/* + * VxWorks requires we cast (const char *) variables to (char *) in order to + * pass them to system calls like stat, read and write. + */ +#ifdef HAVE_VXWORKS +#define CHAR_STAR_CAST (char *) +#define VOID_STAR_CAST (void *) +#else +#define CHAR_STAR_CAST +#define VOID_STAR_CAST +#endif + +#if defined(__cplusplus) +} +#endif + +#include "dbinc_auto/os_ext.h" +#endif /* !_DB_OS_H_ */ diff -r 000000000000 -r a1985f14b030 src/dbinc/partition.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/dbinc/partition.h Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,79 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 1996, 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +/* + * $Id$ + */ +#ifndef _DB_PART_H_ +#define _DB_PART_H_ + +#if defined(__cplusplus) +extern "C" { +#endif + +typedef struct __db_partition { + u_int32_t nparts; /* number of partitions. */ + DBT *keys; /* array of range keys. */ + void *data; /* the partition info. */ + const char **dirs; /* locations for partitions. */ + DB **handles; /* array of partition handles. */ + u_int32_t (*callback) (DB *, DBT *); +#define PART_CALLBACK 0x01 +#define PART_RANGE 0x02 + u_int32_t flags; +} DB_PARTITION; + +/* + * Internal part of a partitioned cursor. + */ +typedef struct __part_internal { + __DBC_INTERNAL + u_int32_t part_id; + DBC *sub_cursor; +} PART_CURSOR; + +#ifdef HAVE_PARTITION +#define PART_NAME "__dbp.%s.%03d" +#define PART_LEN (strlen("__dbp..")+3) +#define PART_PREFIX "__dbp." +#define IS_PARTITION_DB_FILE(name) (strncmp(name, PART_PREFIX, \ + sizeof(PART_PREFIX) - 1) == 0) + +#define DB_IS_PARTITIONED(dbp) \ + (dbp->p_internal != NULL && \ + ((DB_PARTITION *)dbp->p_internal)->handles != NULL) + +#define DBC_PART_REFRESH(dbc) (F_SET(dbc, DBC_PARTITIONED)) +#else +#define DBC_PART_REFRESH(dbc) +#define DB_IS_PARTITIONED(dbp) (0) +#endif + +#if defined(__cplusplus) +} +#endif +#endif diff -r 000000000000 -r a1985f14b030 src/dbinc/perfmon.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/dbinc/perfmon.h Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,125 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 2010, 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + * $Id$ + */ + +#ifndef _DB_PERFMON_H_ +#define _DB_PERFMON_H_ + +/******************************************************* + * Oracle Berkeley DB Performance Event Monitoring + * + * Some events inside of Oracle Berkeley DB can be 'published' + * to the operating environment's performance tracing system + * as they occur. Current support includes + * --enable-dtrace + * Solaris + * Linux (via SystemTap's dtrace wrappers) + * Darwin (Mac OS X) + * QNX(?) + * + ******************************************************/ + +/* + * The performance monitoring system can display many of the statistics which + * are obtainable through the {DB,DB_ENV}->xxx_stat() functions. By default + * they are excluded. They can be enabled with --enable-perfmon-statistics. + */ +#ifdef HAVE_PERFMON_STATISTICS +#define STAT_PERFMON1(env, cat, id, a1) PERFMON1(env, cat, id, (a1)) +#define STAT_PERFMON2(env, cat, id, a1, a2) \ + PERFMON2(env, cat, id, (a1), (a2)) +#define STAT_PERFMON3(env, cat, id, a1, a2, a3) \ + PERFMON3(env, cat, id, (a1), (a2), (a3)) +#else +#define STAT_PERFMON1(env, cat, id, a1) NOP_STATEMENT +#define STAT_PERFMON2(env, cat, id, a1, a2) NOP_STATEMENT +#define STAT_PERFMON3(env, cat, id, a1, a2, a3) NOP_STATEMENT +#endif + + +#if defined(HAVE_PERFMON) && defined(HAVE_STATISTICS) +/* + * The DTrace macros which are generated at configure time in db_provider.h can + * have full function signatures. These declarations are needed for compilation + * when DTrace support is enabled. It is "too early" in the include sequence + * to include the header files which define these structs. + */ +struct _db_page; +struct __bh; +struct __db_dbt; +struct __sh_dbt; +struct __db_mutex_t; + +#if defined(HAVE_DTRACE) +/* + * Solaris 10, Darwin/Mac OS X starting in 10.6 (Snow Leopard), Linux with + * the DTrace-compatible version of SystemTap, possibly QNX. + */ +#include "db_provider.h" + +#define PERFMON0(env, cat, id) bdb_##cat##_##id() +#define PERFMON1(env, cat, id, a1) bdb_##cat##_##id(a1) +#define PERFMON2(env, cat, id, a1, a2) \ + bdb_##cat##_##id((a1), (a2)) +#define PERFMON3(env, cat, id, a1, a2, a3) \ + do { \ + if (PERFMON_ENABLED(env, cat, id)) \ + bdb_##cat##_##id((a1), (a2), (a3)); \ + } while (0) +#define PERFMON4(env, cat, id, a1, a2, a3, a4) \ + do { \ + if (PERFMON_ENABLED(env, cat, id)) \ + bdb_##cat##_##id((a1), (a2), (a3), (a4)); \ + } while (0) +#define PERFMON5(env, cat, id, a1, a2, a3, a4, a5) \ + do { \ + if (PERFMON_ENABLED(env, cat, id)) \ + bdb_##cat##_##id((a1), (a2), (a3), (a4), (a5)); \ + } while (0) +#define PERFMON6(env, cat, id, a1, a2, a3, a4, a5, a6) \ + do { \ + if (PERFMON_ENABLED(env, cat, id)) \ + bdb_##cat##_##id((a1), (a2), (a3), (a4), (a5), (a6)); \ + } while (0) +#define PERFMON_ENABLED(env, cat, id) bdb_##cat##_##id##_enabled() +#endif + +#else +/* Without HAVE_PERFMON or HAVE_STATISTICS these macros map to null bodies. */ +#define PERFMON0(env, cat, id) NOP_STATEMENT +#define PERFMON1(env, cat, id, a1) NOP_STATEMENT +#define PERFMON2(env, cat, id, a1, a2) NOP_STATEMENT +#define PERFMON3(env, cat, id, a1, a2, a3) NOP_STATEMENT +#define PERFMON4(env, cat, id, a1, a2, a3, a4) NOP_STATEMENT +#define PERFMON5(env, cat, id, a1, a2, a3, a4, a5) NOP_STATEMENT +#define PERFMON6(env, cat, id, a1, a2, a3, a4, a5, a6) NOP_STATEMENT +#define PERFMON_ENABLED(env, cat, id) FALSE +#endif + +#endif diff -r 000000000000 -r a1985f14b030 src/dbinc/qam.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/dbinc/qam.h Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,225 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 1999, 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + * $Id$ + */ + +#ifndef _DB_QAM_H_ +#define _DB_QAM_H_ + +#if defined(__cplusplus) +extern "C" { +#endif + +/* + * QAM data elements: a status field and the data. + */ +typedef struct _qamdata { + u_int8_t flags; /* 00: delete bit. */ +#define QAM_VALID 0x01 +#define QAM_SET 0x02 + u_int8_t data[1]; /* Record. */ +} QAMDATA; + +struct __queue; typedef struct __queue QUEUE; +struct __qcursor; typedef struct __qcursor QUEUE_CURSOR; + +struct __qcursor { + /* struct __dbc_internal */ + __DBC_INTERNAL + + /* Queue private part */ + + /* Per-thread information: queue private. */ + db_recno_t recno; /* Current record number. */ + + u_int32_t flags; +}; + +typedef struct __mpfarray { + u_int32_t n_extent; /* Number of extents in table. */ + u_int32_t low_extent; /* First extent open. */ + u_int32_t hi_extent; /* Last extent open. */ + struct __qmpf { + int pinref; + DB_MPOOLFILE *mpf; + } *mpfarray; /* Array of open extents. */ +} MPFARRAY; + +/* + * The in-memory, per-tree queue data structure. + */ +struct __queue { + db_pgno_t q_meta; /* Database meta-data page. */ + db_pgno_t q_root; /* Database root page. */ + + int re_pad; /* Fixed-length padding byte. */ + u_int32_t re_len; /* Length for fixed-length records. */ + u_int32_t rec_page; /* records per page */ + u_int32_t page_ext; /* Pages per extent */ + MPFARRAY array1, array2; /* File arrays. */ + + /* Extent file configuration: */ + DBT pgcookie; /* Initialized pgcookie. */ + DB_PGINFO pginfo; /* Initialized pginfo struct. */ + + char *path; /* Space allocated to file pathname. */ + char *name; /* The name of the file. */ + char *dir; /* The dir of the file. */ + int mode; /* Mode to open extents. */ +}; + +/* Format for queue extent names. */ +#define QUEUE_EXTENT "%s%c__dbq.%s.%d" +#define QUEUE_EXTENT_HEAD "__dbq.%s." +#define QUEUE_EXTENT_PREFIX "__dbq." + +typedef struct __qam_filelist { + DB_MPOOLFILE *mpf; + u_int32_t id; +} QUEUE_FILELIST; + +/* + * Calculate the page number of a recno. + * + * Number of records per page = + * Divide the available space on the page by the record len + header. + * + * Page number for record = + * divide the physical record number by the records per page + * add the root page number + * For now the root page will always be 1, but we might want to change + * in the future (e.g. multiple fixed len queues per file). + * + * Index of record on page = + * physical record number, less the logical pno times records/page + */ +#define CALC_QAM_RECNO_PER_PAGE(dbp) \ + (((dbp)->pgsize - QPAGE_SZ(dbp)) / \ + (u_int32_t)DB_ALIGN((uintmax_t)SSZA(QAMDATA, data) + \ + ((QUEUE *)(dbp)->q_internal)->re_len, sizeof(u_int32_t))) + +#define QAM_RECNO_PER_PAGE(dbp) (((QUEUE*)(dbp)->q_internal)->rec_page) + +#define QAM_RECNO_PAGE(dbp, recno) \ + (((QUEUE *)(dbp)->q_internal)->q_root \ + + (((recno) - 1) / QAM_RECNO_PER_PAGE(dbp))) + +#define QAM_PAGE_EXTENT(dbp, pgno) \ + (((pgno) - 1) / ((QUEUE *)(dbp)->q_internal)->page_ext) + +#define QAM_RECNO_EXTENT(dbp, recno) \ + QAM_PAGE_EXTENT(dbp, QAM_RECNO_PAGE(dbp, recno)) + +#define QAM_RECNO_INDEX(dbp, pgno, recno) \ + (u_int32_t)(((recno) - 1) - (QAM_RECNO_PER_PAGE(dbp) \ + * (pgno - ((QUEUE *)(dbp)->q_internal)->q_root))) + +#define QAM_GET_RECORD(dbp, page, index) \ + ((QAMDATA *)((u_int8_t *)(page) + (QPAGE_SZ(dbp) + \ + (DB_ALIGN((uintmax_t)SSZA(QAMDATA, data) + \ + ((QUEUE *)(dbp)->q_internal)->re_len, sizeof(u_int32_t)) * index)))) + +#define QAM_OUTSIDE_QUEUE(meta, recno) \ + (((meta)->cur_recno >= (meta)->first_recno ? \ + ((recno) < (meta)->first_recno || \ + (recno) > (meta)->cur_recno) : \ + ((recno) > (meta)->cur_recno && \ + (recno) < (meta)->first_recno))) + +#define QAM_AFTER_CURRENT(meta, recno) \ + ((recno) == (meta)->cur_recno || \ + (QAM_OUTSIDE_QUEUE(meta, recno) && \ + ((recno) - (meta)->cur_recno) <= ((meta)->first_recno - (recno)))) + +#define QAM_BEFORE_FIRST(meta, recno) \ + (QAM_OUTSIDE_QUEUE(meta, recno) && \ + ((meta)->first_recno - (recno)) < ((recno) - (meta)->cur_recno)) + +#define QAM_NOT_VALID(meta, recno) \ + (recno == RECNO_OOB || \ + QAM_BEFORE_FIRST(meta, recno) || QAM_AFTER_CURRENT(meta, recno)) + +#define QAM_WAKEUP(dbc, ret) do { \ + if (STD_LOCKING(dbc)) { \ + dbc->lock.pgno = PGNO_INVALID; \ + dbc->lock.type = DB_PAGE_LOCK; \ + ret = __lock_wakeup((dbc)->dbp->env, &(dbc)->lock_dbt); \ + } else \ + ret = 0; \ +} while (0) + +/* Handle wrap around. */ +#define QAM_INC_RECNO(recno) do { \ + recno++; \ +} while (recno == RECNO_OOB) + +#define QAM_DEC_RECNO(recno) do { \ + recno--; \ +} while (recno == RECNO_OOB) + + +/* + * Log opcodes for the mvptr routine. + */ +#define QAM_SETFIRST 0x01 +#define QAM_SETCUR 0x02 +#define QAM_TRUNCATE 0x04 + +typedef enum { + QAM_PROBE_GET, + QAM_PROBE_PUT, + QAM_PROBE_DIRTY, + QAM_PROBE_MPF +} qam_probe_mode; + +/* + * Ops for __qam_nameop. + */ +typedef enum { + QAM_NAME_DISCARD, + QAM_NAME_RENAME, + QAM_NAME_REMOVE +} qam_name_op; + +#define __qam_fget(dbc, pgnoaddr, flags, addrp) \ + __qam_fprobe(dbc, *pgnoaddr, \ + addrp, QAM_PROBE_GET, DB_PRIORITY_UNCHANGED, flags) + +#define __qam_fput(dbc, pgno, addrp, priority) \ + __qam_fprobe(dbc, pgno, addrp, QAM_PROBE_PUT, priority, 0) + +#define __qam_dirty(dbc, pgno, pagep, priority) \ + __qam_fprobe(dbc, pgno, pagep, QAM_PROBE_DIRTY, priority, 0) + +#if defined(__cplusplus) +} +#endif + +#include "dbinc_auto/qam_auto.h" +#include "dbinc_auto/qam_ext.h" +#endif /* !_DB_QAM_H_ */ diff -r 000000000000 -r a1985f14b030 src/dbinc/queue.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/dbinc/queue.h Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,592 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 1996, 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +/* + * Copyright (c) 1991, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)queue.h 8.5 (Berkeley) 8/20/94 + * $FreeBSD: src/sys/sys/queue.h,v 1.54 2002/08/05 05:18:43 alfred Exp $ + */ + +#ifndef _DB_QUEUE_H_ +#define _DB_QUEUE_H_ + +#if defined(__cplusplus) +extern "C" { +#endif + +/* + * This file defines four types of data structures: singly-linked lists, + * singly-linked tail queues, lists and tail queues. + * + * A singly-linked list is headed by a single forward pointer. The elements + * are singly linked for minimum space and pointer manipulation overhead at + * the expense of O(n) removal for arbitrary elements. New elements can be + * added to the list after an existing element or at the head of the list. + * Elements being removed from the head of the list should use the explicit + * macro for this purpose for optimum efficiency. A singly-linked list may + * only be traversed in the forward direction. Singly-linked lists are ideal + * for applications with large datasets and few or no removals or for + * implementing a LIFO queue. + * + * A singly-linked tail queue is headed by a pair of pointers, one to the + * head of the list and the other to the tail of the list. The elements are + * singly linked for minimum space and pointer manipulation overhead at the + * expense of O(n) removal for arbitrary elements. New elements can be added + * to the list after an existing element, at the head of the list, or at the + * end of the list. Elements being removed from the head of the tail queue + * should use the explicit macro for this purpose for optimum efficiency. + * A singly-linked tail queue may only be traversed in the forward direction. + * Singly-linked tail queues are ideal for applications with large datasets + * and few or no removals or for implementing a FIFO queue. + * + * A list is headed by a single forward pointer (or an array of forward + * pointers for a hash table header). The elements are doubly linked + * so that an arbitrary element can be removed without a need to + * traverse the list. New elements can be added to the list before + * or after an existing element or at the head of the list. A list + * may only be traversed in the forward direction. + * + * A tail queue is headed by a pair of pointers, one to the head of the + * list and the other to the tail of the list. The elements are doubly + * linked so that an arbitrary element can be removed without a need to + * traverse the list. New elements can be added to the list before or + * after an existing element, at the head of the list, or at the end of + * the list. A tail queue may be traversed in either direction. + * + * For details on the use of these macros, see the queue(3) manual page. + * + * + * SLIST LIST STAILQ TAILQ + * _HEAD + + + + + * _HEAD_INITIALIZER + + + + + * _ENTRY + + + + + * _INIT + + + + + * _EMPTY + + + + + * _FIRST + + + + + * _NEXT + + + + + * _PREV - - - + + * _LAST - - + + + * _FOREACH + + + + + * _FOREACH_REVERSE - - - + + * _INSERT_HEAD + + + + + * _INSERT_BEFORE - + - + + * _INSERT_AFTER + + + + + * _INSERT_TAIL - - + + + * _CONCAT - - + + + * _REMOVE_HEAD + - + - + * _REMOVE + + + + + * + */ + +/* + * XXX + * We #undef all of the macros because there are incompatible versions of this + * file and these macros on various systems. What makes the problem worse is + * they are included and/or defined by system include files which we may have + * already loaded into Berkeley DB before getting here. For example, FreeBSD's + * includes its system , and VxWorks UnixLib.h defines + * several of the LIST_XXX macros. Visual C.NET 7.0 also defines some of these + * same macros in Vc7\PlatformSDK\Include\WinNT.h. Make sure we use ours. + */ +#undef LIST_EMPTY +#undef LIST_ENTRY +#undef LIST_FIRST +#undef LIST_FOREACH +#undef LIST_HEAD +#undef LIST_HEAD_INITIALIZER +#undef LIST_INIT +#undef LIST_INSERT_AFTER +#undef LIST_INSERT_BEFORE +#undef LIST_INSERT_HEAD +#undef LIST_NEXT +#undef LIST_REMOVE +#undef QMD_TRACE_ELEM +#undef QMD_TRACE_HEAD +#undef QUEUE_MACRO_DEBUG +#undef SLIST_EMPTY +#undef SLIST_ENTRY +#undef SLIST_FIRST +#undef SLIST_FOREACH +#undef SLIST_FOREACH_PREVPTR +#undef SLIST_HEAD +#undef SLIST_HEAD_INITIALIZER +#undef SLIST_INIT +#undef SLIST_INSERT_AFTER +#undef SLIST_INSERT_HEAD +#undef SLIST_NEXT +#undef SLIST_REMOVE +#undef SLIST_REMOVE_HEAD +#undef STAILQ_CONCAT +#undef STAILQ_EMPTY +#undef STAILQ_ENTRY +#undef STAILQ_FIRST +#undef STAILQ_FOREACH +#undef STAILQ_HEAD +#undef STAILQ_HEAD_INITIALIZER +#undef STAILQ_INIT +#undef STAILQ_INSERT_AFTER +#undef STAILQ_INSERT_HEAD +#undef STAILQ_INSERT_TAIL +#undef STAILQ_LAST +#undef STAILQ_NEXT +#undef STAILQ_REMOVE +#undef STAILQ_REMOVE_HEAD +#undef STAILQ_REMOVE_HEAD_UNTIL +#undef TAILQ_CONCAT +#undef TAILQ_EMPTY +#undef TAILQ_ENTRY +#undef TAILQ_FIRST +#undef TAILQ_FOREACH +#undef TAILQ_FOREACH_REVERSE +#undef TAILQ_HEAD +#undef TAILQ_HEAD_INITIALIZER +#undef TAILQ_INIT +#undef TAILQ_INSERT_AFTER +#undef TAILQ_INSERT_BEFORE +#undef TAILQ_INSERT_HEAD +#undef TAILQ_INSERT_TAIL +#undef TAILQ_LAST +#undef TAILQ_NEXT +#undef TAILQ_PREV +#undef TAILQ_REMOVE +#undef TRACEBUF +#undef TRASHIT + +#define QUEUE_MACRO_DEBUG 0 +#if QUEUE_MACRO_DEBUG +/* Store the last 2 places the queue element or head was altered */ +struct qm_trace { + char * lastfile; + int lastline; + char * prevfile; + int prevline; +}; + +#define TRACEBUF struct qm_trace trace; +#define TRASHIT(x) do {(x) = (void *)-1;} while (0) + +#define QMD_TRACE_HEAD(head) do { \ + (head)->trace.prevline = (head)->trace.lastline; \ + (head)->trace.prevfile = (head)->trace.lastfile; \ + (head)->trace.lastline = __LINE__; \ + (head)->trace.lastfile = __FILE__; \ +} while (0) + +#define QMD_TRACE_ELEM(elem) do { \ + (elem)->trace.prevline = (elem)->trace.lastline; \ + (elem)->trace.prevfile = (elem)->trace.lastfile; \ + (elem)->trace.lastline = __LINE__; \ + (elem)->trace.lastfile = __FILE__; \ +} while (0) + +#else +#define QMD_TRACE_ELEM(elem) +#define QMD_TRACE_HEAD(head) +#define TRACEBUF +#define TRASHIT(x) +#endif /* QUEUE_MACRO_DEBUG */ + +/* + * Singly-linked List declarations. + */ +#define SLIST_HEAD(name, type) \ +struct name { \ + struct type *slh_first; /* first element */ \ +} + +#define SLIST_HEAD_INITIALIZER(head) \ + { NULL } + +#define SLIST_ENTRY(type) \ +struct { \ + struct type *sle_next; /* next element */ \ +} + +/* + * Singly-linked List functions. + */ +#define SLIST_EMPTY(head) ((head)->slh_first == NULL) + +#define SLIST_FIRST(head) ((head)->slh_first) + +#define SLIST_FOREACH(var, head, field) \ + for ((var) = SLIST_FIRST((head)); \ + (var); \ + (var) = SLIST_NEXT((var), field)) + +#define SLIST_FOREACH_PREVPTR(var, varp, head, field) \ + for ((varp) = &SLIST_FIRST((head)); \ + ((var) = *(varp)) != NULL; \ + (varp) = &SLIST_NEXT((var), field)) + +#define SLIST_INIT(head) do { \ + SLIST_FIRST((head)) = NULL; \ +} while (0) + +#define SLIST_INSERT_AFTER(slistelm, elm, field) do { \ + SLIST_NEXT((elm), field) = SLIST_NEXT((slistelm), field); \ + SLIST_NEXT((slistelm), field) = (elm); \ +} while (0) + +#define SLIST_INSERT_HEAD(head, elm, field) do { \ + SLIST_NEXT((elm), field) = SLIST_FIRST((head)); \ + SLIST_FIRST((head)) = (elm); \ +} while (0) + +#define SLIST_NEXT(elm, field) ((elm)->field.sle_next) + +#define SLIST_REMOVE(head, elm, type, field) do { \ + if (SLIST_FIRST((head)) == (elm)) { \ + SLIST_REMOVE_HEAD((head), field); \ + } \ + else { \ + struct type *curelm = SLIST_FIRST((head)); \ + while (curelm != NULL && \ + SLIST_NEXT(curelm, field) != (elm)) \ + curelm = SLIST_NEXT(curelm, field); \ + if (curelm != NULL) \ + SLIST_NEXT(curelm, field) = \ + SLIST_NEXT(SLIST_NEXT(curelm, field), field);\ + } \ +} while (0) + +#define SLIST_REMOVE_HEAD(head, field) do { \ + SLIST_FIRST((head)) = SLIST_NEXT(SLIST_FIRST((head)), field); \ +} while (0) + +/* + * Singly-linked Tail queue declarations. + */ +#define STAILQ_HEAD(name, type) \ +struct name { \ + struct type *stqh_first;/* first element */ \ + struct type **stqh_last;/* addr of last next element */ \ +} + +#define STAILQ_HEAD_INITIALIZER(head) \ + { NULL, &(head).stqh_first } + +#define STAILQ_ENTRY(type) \ +struct { \ + struct type *stqe_next; /* next element */ \ +} + +/* + * Singly-linked Tail queue functions. + */ +#define STAILQ_CONCAT(head1, head2) do { \ + if (!STAILQ_EMPTY((head2))) { \ + *(head1)->stqh_last = (head2)->stqh_first; \ + (head1)->stqh_last = (head2)->stqh_last; \ + STAILQ_INIT((head2)); \ + } \ +} while (0) + +#define STAILQ_EMPTY(head) ((head)->stqh_first == NULL) + +#define STAILQ_FIRST(head) ((head)->stqh_first) + +#define STAILQ_FOREACH(var, head, field) \ + for ((var) = STAILQ_FIRST((head)); \ + (var); \ + (var) = STAILQ_NEXT((var), field)) + +#define STAILQ_INIT(head) do { \ + STAILQ_FIRST((head)) = NULL; \ + (head)->stqh_last = &STAILQ_FIRST((head)); \ +} while (0) + +#define STAILQ_INSERT_AFTER(head, tqelm, elm, field) do { \ + if ((STAILQ_NEXT((elm), field) = STAILQ_NEXT((tqelm), field)) == NULL)\ + (head)->stqh_last = &STAILQ_NEXT((elm), field); \ + STAILQ_NEXT((tqelm), field) = (elm); \ +} while (0) + +#define STAILQ_INSERT_HEAD(head, elm, field) do { \ + if ((STAILQ_NEXT((elm), field) = STAILQ_FIRST((head))) == NULL) \ + (head)->stqh_last = &STAILQ_NEXT((elm), field); \ + STAILQ_FIRST((head)) = (elm); \ +} while (0) + +#define STAILQ_INSERT_TAIL(head, elm, field) do { \ + STAILQ_NEXT((elm), field) = NULL; \ + *(head)->stqh_last = (elm); \ + (head)->stqh_last = &STAILQ_NEXT((elm), field); \ +} while (0) + +#define STAILQ_LAST(head, type, field) \ + (STAILQ_EMPTY((head)) ? \ + NULL : \ + ((struct type *) \ + ((char *)((head)->stqh_last) - __offsetof(struct type, field)))) + +#define STAILQ_NEXT(elm, field) ((elm)->field.stqe_next) + +#define STAILQ_REMOVE(head, elm, type, field) do { \ + if (STAILQ_FIRST((head)) == (elm)) { \ + STAILQ_REMOVE_HEAD((head), field); \ + } \ + else { \ + struct type *curelm = STAILQ_FIRST((head)); \ + while (STAILQ_NEXT(curelm, field) != (elm)) \ + curelm = STAILQ_NEXT(curelm, field); \ + if ((STAILQ_NEXT(curelm, field) = \ + STAILQ_NEXT(STAILQ_NEXT(curelm, field), field)) == NULL)\ + (head)->stqh_last = &STAILQ_NEXT((curelm), field);\ + } \ +} while (0) + +#define STAILQ_REMOVE_HEAD(head, field) do { \ + if ((STAILQ_FIRST((head)) = \ + STAILQ_NEXT(STAILQ_FIRST((head)), field)) == NULL) \ + (head)->stqh_last = &STAILQ_FIRST((head)); \ +} while (0) + +#define STAILQ_REMOVE_HEAD_UNTIL(head, elm, field) do { \ + if ((STAILQ_FIRST((head)) = STAILQ_NEXT((elm), field)) == NULL) \ + (head)->stqh_last = &STAILQ_FIRST((head)); \ +} while (0) + +/* + * List declarations. + */ +#define LIST_HEAD(name, type) \ +struct name { \ + struct type *lh_first; /* first element */ \ +} + +#define LIST_HEAD_INITIALIZER(head) \ + { NULL } + +#define LIST_ENTRY(type) \ +struct { \ + struct type *le_next; /* next element */ \ + struct type **le_prev; /* address of previous next element */ \ +} + +/* + * List functions. + */ + +#define LIST_EMPTY(head) ((head)->lh_first == NULL) + +#define LIST_FIRST(head) ((head)->lh_first) + +#define LIST_FOREACH(var, head, field) \ + for ((var) = LIST_FIRST((head)); \ + (var); \ + (var) = LIST_NEXT((var), field)) + +#define LIST_INIT(head) do { \ + LIST_FIRST((head)) = NULL; \ +} while (0) + +#define LIST_INSERT_AFTER(listelm, elm, field) do { \ + if ((LIST_NEXT((elm), field) = LIST_NEXT((listelm), field)) != NULL)\ + LIST_NEXT((listelm), field)->field.le_prev = \ + &LIST_NEXT((elm), field); \ + LIST_NEXT((listelm), field) = (elm); \ + (elm)->field.le_prev = &LIST_NEXT((listelm), field); \ +} while (0) + +#define LIST_INSERT_BEFORE(listelm, elm, field) do { \ + (elm)->field.le_prev = (listelm)->field.le_prev; \ + LIST_NEXT((elm), field) = (listelm); \ + *(listelm)->field.le_prev = (elm); \ + (listelm)->field.le_prev = &LIST_NEXT((elm), field); \ +} while (0) + +#define LIST_INSERT_HEAD(head, elm, field) do { \ + if ((LIST_NEXT((elm), field) = LIST_FIRST((head))) != NULL) \ + LIST_FIRST((head))->field.le_prev = &LIST_NEXT((elm), field);\ + LIST_FIRST((head)) = (elm); \ + (elm)->field.le_prev = &LIST_FIRST((head)); \ +} while (0) + +#define LIST_NEXT(elm, field) ((elm)->field.le_next) + +#define LIST_REMOVE(elm, field) do { \ + if (LIST_NEXT((elm), field) != NULL) \ + LIST_NEXT((elm), field)->field.le_prev = \ + (elm)->field.le_prev; \ + *(elm)->field.le_prev = LIST_NEXT((elm), field); \ +} while (0) + +/* + * Tail queue declarations. + */ +#define TAILQ_HEAD(name, type) \ +struct name { \ + struct type *tqh_first; /* first element */ \ + struct type **tqh_last; /* addr of last next element */ \ + TRACEBUF \ +} + +#define TAILQ_HEAD_INITIALIZER(head) \ + { NULL, &(head).tqh_first } + +#define TAILQ_ENTRY(type) \ +struct { \ + struct type *tqe_next; /* next element */ \ + struct type **tqe_prev; /* address of previous next element */ \ + TRACEBUF \ +} + +/* + * Tail queue functions. + */ +#define TAILQ_CONCAT(head1, head2, field) do { \ + if (!TAILQ_EMPTY(head2)) { \ + *(head1)->tqh_last = (head2)->tqh_first; \ + (head2)->tqh_first->field.tqe_prev = (head1)->tqh_last; \ + (head1)->tqh_last = (head2)->tqh_last; \ + TAILQ_INIT((head2)); \ + QMD_TRACE_HEAD(head); \ + QMD_TRACE_HEAD(head2); \ + } \ +} while (0) + +#define TAILQ_EMPTY(head) ((head)->tqh_first == NULL) + +#define TAILQ_FIRST(head) ((head)->tqh_first) + +#define TAILQ_FOREACH(var, head, field) \ + for ((var) = TAILQ_FIRST((head)); \ + (var); \ + (var) = TAILQ_NEXT((var), field)) + +#define TAILQ_FOREACH_REVERSE(var, head, headname, field) \ + for ((var) = TAILQ_LAST((head), headname); \ + (var); \ + (var) = TAILQ_PREV((var), headname, field)) + +#define TAILQ_INIT(head) do { \ + TAILQ_FIRST((head)) = NULL; \ + (head)->tqh_last = &TAILQ_FIRST((head)); \ + QMD_TRACE_HEAD(head); \ +} while (0) + +#define TAILQ_INSERT_AFTER(head, listelm, elm, field) do { \ + if ((TAILQ_NEXT((elm), field) = TAILQ_NEXT((listelm), field)) != NULL)\ + TAILQ_NEXT((elm), field)->field.tqe_prev = \ + &TAILQ_NEXT((elm), field); \ + else { \ + (head)->tqh_last = &TAILQ_NEXT((elm), field); \ + QMD_TRACE_HEAD(head); \ + } \ + TAILQ_NEXT((listelm), field) = (elm); \ + (elm)->field.tqe_prev = &TAILQ_NEXT((listelm), field); \ + QMD_TRACE_ELEM(&(elm)->field); \ + QMD_TRACE_ELEM(&listelm->field); \ +} while (0) + +#define TAILQ_INSERT_BEFORE(listelm, elm, field) do { \ + (elm)->field.tqe_prev = (listelm)->field.tqe_prev; \ + TAILQ_NEXT((elm), field) = (listelm); \ + *(listelm)->field.tqe_prev = (elm); \ + (listelm)->field.tqe_prev = &TAILQ_NEXT((elm), field); \ + QMD_TRACE_ELEM(&(elm)->field); \ + QMD_TRACE_ELEM(&listelm->field); \ +} while (0) + +#define TAILQ_INSERT_HEAD(head, elm, field) do { \ + if ((TAILQ_NEXT((elm), field) = TAILQ_FIRST((head))) != NULL) \ + TAILQ_FIRST((head))->field.tqe_prev = \ + &TAILQ_NEXT((elm), field); \ + else \ + (head)->tqh_last = &TAILQ_NEXT((elm), field); \ + TAILQ_FIRST((head)) = (elm); \ + (elm)->field.tqe_prev = &TAILQ_FIRST((head)); \ + QMD_TRACE_HEAD(head); \ + QMD_TRACE_ELEM(&(elm)->field); \ +} while (0) + +#define TAILQ_INSERT_TAIL(head, elm, field) do { \ + TAILQ_NEXT((elm), field) = NULL; \ + (elm)->field.tqe_prev = (head)->tqh_last; \ + *(head)->tqh_last = (elm); \ + (head)->tqh_last = &TAILQ_NEXT((elm), field); \ + QMD_TRACE_HEAD(head); \ + QMD_TRACE_ELEM(&(elm)->field); \ +} while (0) + +#define TAILQ_LAST(head, headname) \ + (*(((struct headname *)((head)->tqh_last))->tqh_last)) + +#define TAILQ_NEXT(elm, field) ((elm)->field.tqe_next) + +#define TAILQ_PREV(elm, headname, field) \ + (*(((struct headname *)((elm)->field.tqe_prev))->tqh_last)) + +#define TAILQ_REMOVE(head, elm, field) do { \ + if ((TAILQ_NEXT((elm), field)) != NULL) \ + TAILQ_NEXT((elm), field)->field.tqe_prev = \ + (elm)->field.tqe_prev; \ + else { \ + (head)->tqh_last = (elm)->field.tqe_prev; \ + QMD_TRACE_HEAD(head); \ + } \ + *(elm)->field.tqe_prev = TAILQ_NEXT((elm), field); \ + TRASHIT((elm)->field.tqe_next); \ + TRASHIT((elm)->field.tqe_prev); \ + QMD_TRACE_ELEM(&(elm)->field); \ +} while (0) + +#if defined(__cplusplus) +} +#endif +#endif /* !_DB_QUEUE_H_ */ diff -r 000000000000 -r a1985f14b030 src/dbinc/region.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/dbinc/region.h Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,351 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 1998, 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + * $Id$ + */ + +#ifndef _DB_REGION_H_ +#define _DB_REGION_H_ + +/* + * The DB environment consists of some number of "regions", which are described + * by the following four structures: + * + * REGENV -- shared information about the environment + * REGENV_REF -- file describing system memory version of REGENV + * REGION -- shared information about a single region + * REGINFO -- per-process information about a REGION + * + * There are three types of memory that hold regions: + * per-process heap (malloc) + * file mapped into memory (mmap, MapViewOfFile) + * system memory (shmget, CreateFileMapping) + * + * By default, regions are created in filesystem-backed shared memory. They + * can also be created in system shared memory (DB_SYSTEM_MEM), or, if private + * to a process, in heap memory (DB_PRIVATE). + * + * Regions in the filesystem are named "__db.001", "__db.002" and so on. If + * we're not using a private environment allocated in heap, "__db.001" will + * always exist, as we use it to synchronize on the regions, whether they are + * in filesystem-backed memory or system memory. + * + * The file "__db.001" contains a REGENV structure pointing to an + * array of REGION structures. Each REGION structures describes an + * underlying chunk of shared memory. + * + * __db.001 + * +---------+ + * |REGENV | + * +---------+ + * | + * \/ + * +---------+ +----------+ + * |REGION |-> | __db.001 | + * | | +----------+ + * +---------+ +----------+ + * |REGION |-> | __db.002 | + * | | +----------+ + * +---------+ +----------+ + * |REGION |-> | __db.003 | + * | | +----------+ + * +---------+ +----------+ + * |REGION |-> | __db.004 | + * | | +----------+ + * +---------+ + * + * The tricky part about manipulating the regions is creating or joining the + * database environment. We have to be sure only a single thread of control + * creates and/or recovers a database environment. All other threads should + * then join without seeing inconsistent data. + * + * We do this in two parts: first, we use the underlying O_EXCL flag to the + * open system call to serialize creation of the __db.001 file. The thread + * of control creating that file then proceeds to create the remaining + * regions in the environment, including the mutex region. Once the mutex + * region has been created, the creating thread of control fills in the + * __db.001 file's magic number. Other threads of control (the ones that + * didn't create the __db.001 file), wait on the initialization of the + * __db.001 file's magic number. After it has been initialized, all threads + * of control can proceed, using normal shared mutex locking procedures for + * exclusion. + * + * REGIONs are not moved or removed during the life of the environment, and + * so processes can have long-lived references to them. + * + * One of the REGION structures describes the environment region itself. + * + * The REGION array is not locked in any way. It's an array so we don't have + * to manipulate data structures after a crash -- on some systems, we have to + * join and clean up the mutex region after application failure. Using an + * array means we don't have to worry about broken links or other nastiness + * after the failure. + * + * All requests to create or join a region return a REGINFO structure, which + * is held by the caller and used to open and subsequently close the reference + * to the region. The REGINFO structure contains the per-process information + * that we need to access the region. + * + * The one remaining complication. If the regions (including the environment + * region) live in system memory, and the system memory isn't "named" somehow + * in the filesystem name space, we need some way of finding it. Do this by + * by writing the REGENV_REF structure into the "__db.001" file. When we find + * a __db.001 file that is too small to be a real, on-disk environment, we use + * the information it contains to redirect to the real "__db.001" file/memory. + * This currently only happens when the REGENV file is in shared system memory. + * + * Although DB does not currently grow regions when they run out of memory, it + * would be possible to do so. To grow a region, allocate a new region of the + * appropriate size, then copy the old region over it and insert the additional + * memory into the already existing shalloc arena. Region users must reset + * their base addresses and any local pointers into the memory, of course. + * This failed in historic versions of DB because the region mutexes lived in + * the mapped memory, and when it was unmapped and remapped (or copied), + * threads could lose track of it. Also, some systems didn't support mutex + * copying, e.g., from OSF1 V4.0: + * + * The address of an msemaphore structure may be significant. If the + * msemaphore structure contains any value copied from an msemaphore + * structure at a different address, the result is undefined. + * + * All mutexes are now maintained in a separate region which is never unmapped, + * so growing regions should be possible. + */ + +#if defined(__cplusplus) +extern "C" { +#endif + +#define DB_REGION_PREFIX "__db" /* DB file name prefix. */ +#define DB_REGION_FMT "__db.%03d" /* Region file name format. */ +#define DB_REGION_ENV "__db.001" /* Primary environment name. */ +#define IS_DB_FILE(name) (strncmp(name, DB_REGION_PREFIX, \ + sizeof(DB_REGION_PREFIX) - 1) == 0) + +#define INVALID_REGION_ID 0 /* Out-of-band region ID. */ +#define REGION_ID_ENV 1 /* Primary environment ID. */ + +typedef enum { + INVALID_REGION_TYPE=0, /* Region type. */ + REGION_TYPE_ENV, + REGION_TYPE_LOCK, + REGION_TYPE_LOG, + REGION_TYPE_MPOOL, + REGION_TYPE_MUTEX, + REGION_TYPE_TXN } reg_type_t; + +#define INVALID_REGION_SEGID -1 /* Segment IDs are either shmget(2) or + * Win16 segment identifiers. They are + * both stored in a "long", and we need + * an out-of-band value. + */ +/* + * Nothing can live at region offset 0, because, in all cases, that's where + * we store *something*. Lots of code needs an out-of-band value for region + * offsets, so we use 0. + */ +#define INVALID_ROFF 0 + +/* Reference describing system memory version of REGENV. */ +typedef struct __db_reg_env_ref { + roff_t size; /* Region size. */ + roff_t max; /* Region max in bytes. */ + long segid; /* UNIX shmget ID, VxWorks ID. */ +} REGENV_REF; + +/* Per-environment region information. */ +typedef struct __db_reg_env { /* SHARED */ + /* + * !!! + * The magic, panic, version, envid and signature fields of the region + * are fixed in size, the timestamp field is the first field which is + * variable length. These fields must never change in order, to + * guarantee we can always read them, no matter what release we have. + * + * !!! + * The magic and panic fields are NOT protected by any mutex, and for + * this reason cannot be anything more complicated than zero/non-zero. + */ + u_int32_t magic; /* Valid region magic number. */ + u_int32_t panic; /* Environment is dead. */ + + u_int32_t majver; /* Major DB version number. */ + u_int32_t minver; /* Minor DB version number. */ + u_int32_t patchver; /* Patch DB version number. */ + + u_int32_t envid; /* Unique environment ID. */ + + u_int32_t signature; /* Structure signatures. */ + + time_t timestamp; /* Creation time. */ + + /* + * Flags saved in the init_flags field of the environment, representing + * flags to DB_ENV->set_flags and DB_ENV->open that need to be set. + */ + u_int32_t init_flags; +#define DB_INITENV_CDB 0x0001 /* DB_INIT_CDB */ +#define DB_INITENV_CDB_ALLDB 0x0002 /* DB_INIT_CDB_ALLDB */ +#define DB_INITENV_LOCK 0x0004 /* DB_INIT_LOCK */ +#define DB_INITENV_LOG 0x0008 /* DB_INIT_LOG */ +#define DB_INITENV_MPOOL 0x0010 /* DB_INIT_MPOOL */ +#define DB_INITENV_REP 0x0020 /* DB_INIT_REP */ +#define DB_INITENV_TXN 0x0040 /* DB_INIT_TXN */ + + + /* + * The mtx_regenv mutex protects the environment reference count and + * memory allocation from the primary shared region (the crypto, thread + * control block and replication implementations allocate memory from + * the primary shared region). + * + * The rest of the fields are initialized at creation time, and don't + * need mutex protection. The flags, op_timestamp and rep_timestamp + * fields are used by replication only and are protected by the + * replication mutex. The rep_timestamp is is not protected when it + * is used in recovery as that is already single threaded. + */ + db_mutex_t mtx_regenv; /* Refcnt, region allocation mutex. */ + u_int32_t refcnt; /* References to the environment. */ + + u_int32_t region_cnt; /* Number of REGIONs. */ + roff_t region_off; /* Offset of region array */ + roff_t lt_primary; /* Lock primary. */ + roff_t lg_primary; /* Log primary. */ + roff_t tx_primary; /* Txn primary. */ + + roff_t cipher_off; /* Offset of cipher area */ + + roff_t thread_off; /* Offset of the thread area. */ + + roff_t rep_off; /* Offset of the replication area. */ +#define DB_REGENV_REPLOCKED 0x0001 /* Env locked for rep backup. */ + u_int32_t flags; /* Shared environment flags. */ +#define DB_REGENV_TIMEOUT 30 /* Backup timeout. */ + time_t op_timestamp; /* Timestamp for operations. */ + time_t rep_timestamp; /* Timestamp for rep db handles. */ + u_int32_t reg_panic; /* DB_REGISTER triggered panic */ + uintmax_t unused; /* The ALLOC_LAYOUT structure follows + * the REGENV structure in memory and + * contains uintmax_t fields. Force + * proper alignment of that structure. + */ +} REGENV; + +/* Per-region shared region information. */ +typedef struct __db_region { /* SHARED */ + roff_t size; /* Region size in bytes. */ + roff_t max; /* Region max in bytes. */ + long segid; /* UNIX shmget(2), Win16 segment ID. */ + + u_int32_t id; /* Region id. */ + reg_type_t type; /* Region type. */ + + roff_t primary; /* Primary data structure offset. */ + roff_t alloc; /* Region allocation size in bytes. */ +} REGION; + +/* + * Per-process/per-attachment information about a single region. + */ + +/* + * Structure used for tracking allocations in DB_PRIVATE regions. + */ +struct __db_region_mem_t; typedef struct __db_region_mem_t REGION_MEM; +struct __db_region_mem_t { + REGION_MEM *next; +}; + +struct __db_reginfo_t { /* __env_region_attach IN parameters. */ + ENV *env; /* Enclosing environment. */ + reg_type_t type; /* Region type. */ + u_int32_t id; /* Region id. */ + + /* env_region_attach OUT parameters. */ + REGION *rp; /* Shared region. */ + + char *name; /* Region file name. */ + DB_FH *fhp; /* Region file handle */ + + void *addr; /* Region address. */ + void *head; /* Head of the allocation struct. */ + void *primary; /* Primary data structure address. */ + + /* Private Memory Tracking. */ + size_t max_alloc; /* Maximum bytes allocated. */ + size_t allocated; /* Bytes allocated. */ + REGION_MEM *mem; /* List of memory to free */ + + db_mutex_t mtx_alloc; /* number of mutex for allocation. */ + +#ifdef DB_WIN32 + HANDLE wnt_handle; /* Win/NT HANDLE. */ +#endif + +#define REGION_CREATE 0x01 /* Caller created region. */ +#define REGION_CREATE_OK 0x02 /* Caller willing to create region. */ +#define REGION_JOIN_OK 0x04 /* Caller is looking for a match. */ +#define REGION_SHARED 0x08 /* Region is shared. */ +#define REGION_TRACKED 0x10 /* Region private memory is tracked. */ + u_int32_t flags; +}; + +/* + * R_ADDR Return a per-process address for a shared region offset. + * R_OFFSET Return a shared region offset for a per-process address. + */ +#define R_ADDR(reginfop, offset) \ + (F_ISSET((reginfop)->env, ENV_PRIVATE) ? \ + ROFF_TO_P(offset) : \ + (void *)((u_int8_t *)((reginfop)->addr) + (offset))) +#define R_OFFSET(reginfop, p) \ + (F_ISSET((reginfop)->env, ENV_PRIVATE) ? \ + P_TO_ROFF(p) : \ + (roff_t)((u_int8_t *)(p) - (u_int8_t *)(reginfop)->addr)) + +/* + * PANIC_ISSET, PANIC_CHECK: + * Check to see if the DB environment is dead. + */ +#define PANIC_ISSET(env) \ + ((env) != NULL && (env)->reginfo != NULL && \ + ((REGENV *)(env)->reginfo->primary)->panic != 0 && \ + !F_ISSET((env)->dbenv, DB_ENV_NOPANIC)) + +#define PANIC_CHECK(env) \ + if (PANIC_ISSET(env)) \ + return (__env_panic_msg(env)); + +#define PANIC_CHECK_RET(env, ret) \ + if (PANIC_ISSET(env)) \ + ret = (__env_panic_msg(env)); + +#if defined(__cplusplus) +} +#endif +#endif /* !_DB_REGION_H_ */ diff -r 000000000000 -r a1985f14b030 src/dbinc/rep.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/dbinc/rep.h Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,1126 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 2001, 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + * $Id$ + */ + +#ifndef _DB_REP_H_ +#define _DB_REP_H_ + +#include "dbinc_auto/rep_automsg.h" + +#if defined(__cplusplus) +extern "C" { +#endif + +/* + * Names of client temp databases. + */ +#define REPFILEPREFIX "__db.rep" +#define REPDBNAME "__db.rep.db" +#define REPPAGENAME "__db.reppg.db" + +/* + * Name of replicated system database file, and LSN history subdatabase within + * it. If the INMEM config flag is set, we create the database in memory, with + * the REPLSNHIST name (so that is why it also follows the __db naming + * convention). + */ +#define REPSYSDBNAME "__db.rep.system" +#define REPLSNHIST "__db.lsn.history" +#define REPMEMBERSHIP "__db.membership" +#define REPSYSDBPGSZ 1024 +#define IS_REP_FILE(name) (strcmp(name, REPSYSDBNAME) == 0) + + +/* Current version of commit token format, and LSN history database format. */ +#define REP_COMMIT_TOKEN_FMT_VERSION 1 +#define REP_LSN_HISTORY_FMT_VERSION 1 + +/* + * Message types + */ +#define REP_INVALID 0 /* Invalid message type. */ +#define REP_ALIVE 1 /* I am alive message. */ +#define REP_ALIVE_REQ 2 /* Request for alive messages. */ +#define REP_ALL_REQ 3 /* Request all log records greater than LSN. */ +#define REP_BULK_LOG 4 /* Bulk transfer of log records. */ +#define REP_BULK_PAGE 5 /* Bulk transfer of pages. */ +#define REP_DUPMASTER 6 /* Duplicate master detected; propagate. */ +#define REP_FILE 7 /* Page of a database file. NOTUSED */ +#define REP_FILE_FAIL 8 /* File requested does not exist. */ +#define REP_FILE_REQ 9 /* Request for a database file. NOTUSED */ +#define REP_LEASE_GRANT 10 /* Client grants a lease to a master. */ +#define REP_LOG 11 /* Log record. */ +#define REP_LOG_MORE 12 /* There are more log records to request. */ +#define REP_LOG_REQ 13 /* Request for a log record. */ +#define REP_MASTER_REQ 14 /* Who is the master */ +#define REP_NEWCLIENT 15 /* Announces the presence of a new client. */ +#define REP_NEWFILE 16 /* Announce a log file change. */ +#define REP_NEWMASTER 17 /* Announces who the master is. */ +#define REP_NEWSITE 18 /* Announces that a site has heard from a new + * site; like NEWCLIENT, but indirect. A + * NEWCLIENT message comes directly from the new + * client while a NEWSITE comes indirectly from + * someone who heard about a NEWSITE. + */ +#define REP_PAGE 19 /* Database page. */ +#define REP_PAGE_FAIL 20 /* Requested page does not exist. */ +#define REP_PAGE_MORE 21 /* There are more pages to request. */ +#define REP_PAGE_REQ 22 /* Request for a database page. */ +#define REP_REREQUEST 23 /* Force rerequest. */ +#define REP_START_SYNC 24 /* Tell client to begin syncing a ckp.*/ +#define REP_UPDATE 25 /* Environment hotcopy information. */ +#define REP_UPDATE_REQ 26 /* Request for hotcopy information. */ +#define REP_VERIFY 27 /* A log record for verification. */ +#define REP_VERIFY_FAIL 28 /* The client is outdated. */ +#define REP_VERIFY_REQ 29 /* Request for a log record to verify. */ +#define REP_VOTE1 30 /* Send out your information for an election. */ +#define REP_VOTE2 31 /* Send a "you are master" vote. */ +/* + * Maximum message number for conversion tables. Update this + * value as the largest message number above increases. + * It might make processing messages more straightforward if + * the *_MORE and BULK* messages were flags within the regular + * message type instead of separate message types themselves. + * + * !!! + * NOTE: When changing messages above, the two tables for upgrade support + * need adjusting. They are in rep_util.c. + */ +#define REP_MAX_MSG 31 + +/* + * This is the list of client-to-client requests messages. + * We use this to decide if we're doing client-to-client and + * might need to send a rerequest. + */ +#define REP_MSG_REQ(rectype) \ + (rectype == REP_ALL_REQ || \ + rectype == REP_LOG_REQ || \ + rectype == REP_PAGE_REQ || \ + rectype == REP_VERIFY_REQ) + +/* + * Note that the version information should be at the beginning of the + * structure, so that we can rearrange the rest of it while letting the + * version checks continue to work. DB_REPVERSION should be revved any time + * the rest of the structure changes or when the message numbers change. + * + * Define also, the corresponding log versions that are tied to the + * replication/release versions. These are only needed in replication + * and that is why they're defined here. db_printlog takes notice as well. + */ +#define DB_LOGVERSION_42 8 +#define DB_LOGVERSION_43 10 +#define DB_LOGVERSION_44 11 +#define DB_LOGVERSION_45 12 +#define DB_LOGVERSION_46 13 +#define DB_LOGVERSION_47 14 +#define DB_LOGVERSION_48 15 +#define DB_LOGVERSION_48p2 16 +#define DB_LOGVERSION_50 17 +#define DB_LOGVERSION_51 17 +#define DB_LOGVERSION_52 18 +#define DB_LOGVERSION_53 19 +#define DB_LOGVERSION_60 20 +#define DB_LOGVERSION_MIN DB_LOGVERSION_44 +#define DB_REPVERSION_INVALID 0 +#define DB_REPVERSION_44 3 +#define DB_REPVERSION_45 3 +#define DB_REPVERSION_46 4 +#define DB_REPVERSION_47 5 +#define DB_REPVERSION_48 5 +#define DB_REPVERSION_50 5 +#define DB_REPVERSION_51 5 +#define DB_REPVERSION_52 6 +#define DB_REPVERSION_53 7 +#define DB_REPVERSION_60 7 +#define DB_REPVERSION DB_REPVERSION_60 +#define DB_REPVERSION_MIN DB_REPVERSION_44 + +/* + * RPRINT - Replication diagnostic output + * VPRINT - Replication verbose output (superset of RPRINT). + * REP_PRINT_MESSAGE + * Macros for verbose replication messages. + * + * Everything using RPRINT will go to the system diag file (if it + * is configured) and also to the user's verbose output if + * they have that verbose level configured. + * Messages using VPRINT do not ever go to the system diag file, + * but will go to the user's verbose output if configured. + * + * Use VPRINT for anything that might be printed on a standard, + * successful transaction. Use RPRINT for error paths, rep + * state changes, elections, etc. + */ +#define REP_DIAGNAME "__db.rep.diag%02d" +#define REP_DIAGSIZE MEGABYTE +#define RPRINT(env, x) do { \ + if ((env)->dbenv->verbose != 0) \ + (void)__rep_print_system x; \ +} while (0) +#define VPRINT(env, x) do { \ + if ((env)->dbenv->verbose != 0) \ + (void)__rep_print x; \ +} while (0) +#define REP_PRINT_MESSAGE(env, eid, rp, str, fl) do { \ + if ((env)->dbenv->verbose != 0) \ + __rep_print_message(env, eid, rp, str, fl); \ +} while (0) + +/* + * Election gen file name + * The file contains an egen number for an election this client has NOT + * participated in. I.e. it is the number of a future election. We + * create it when we create the rep region, if it doesn't already exist + * and initialize egen to 1. If it does exist, we read it when we create + * the rep region. We write it immediately before sending our VOTE1 in + * an election. That way, if a client has ever sent a vote for any + * election, the file is already going to be updated to reflect a future + * election, should it crash. + */ +#define REP_EGENNAME "__db.rep.egen" +#define REP_GENNAME "__db.rep.gen" + +/* + * Internal init flag file name: + * The existence of this file serves as an indication that the client is in the + * process of Internal Initialization, in case it crashes before completing. + * During internal init the client's partially reconstructed database pages and + * logs may be in an inconsistent state, so much so that running recovery must + * be avoided. Furthermore, there is no other way to reliably recognize this + * condition. Therefore, when we open an environment, and we're just about to + * run recovery, we check for this file first. If it exists we must discard all + * logs and databases. This avoids the recovery problems, and leads to a fresh + * attempt at internal init if the environment becomes a replication client and + * finds a master. The list of databases which may need to be removed is stored + * in this file. + */ +#define REP_INITNAME "__db.rep.init" +#define REP_INITVERSION_46 1 +#define REP_INITVERSION_47 2 +#define REP_INITVERSION 3 + +/* + * Database types for __rep_client_dbinit + */ +typedef enum { + REP_DB, /* Log record database. */ + REP_PG /* Pg database. */ +} repdb_t; + +/* Macros to lock/unlock the replication region as a whole. */ +#define REP_SYSTEM_LOCK(env) \ + MUTEX_LOCK(env, (env)->rep_handle->region->mtx_region) +#define REP_SYSTEM_UNLOCK(env) \ + MUTEX_UNLOCK(env, (env)->rep_handle->region->mtx_region) + +/* + * Macros for manipulating the event synchronization. We use a separate mutex + * so that an application's call-back function can be invoked without locking + * the whole region. + */ +#define REP_EVENT_LOCK(env) \ + MUTEX_LOCK(env, (env)->rep_handle->region->mtx_event) +#define REP_EVENT_UNLOCK(env) \ + MUTEX_UNLOCK(env, (env)->rep_handle->region->mtx_event) + +/* + * Synchronization states + * Please change __rep_syncstate_to_string (rep_stat.c) to track any changes + * made to these states. + * + * The states are in alphabetical order (except for OFF). The usual + * order of progression for a full internal init is: + * VERIFY, UPDATE, PAGE, LOG (then back to OFF when we're done). + */ +typedef enum { + SYNC_OFF, /* No recovery. */ + SYNC_LOG, /* Recovery - log. */ + SYNC_PAGE, /* Recovery - pages. */ + SYNC_UPDATE, /* Recovery - update. */ + SYNC_VERIFY /* Recovery - verify. */ +} repsync_t; + +/* + * A record of the contents of the VOTE1 msg we sent out at current egen, in + * case we need to send out a duplicate VOTE1 to a late-joining client in a full + * election. The nsites, nvotes, and priority fields of the REP struct can't be + * used, because those could change. It's only safe to send out a dup if we + * send out the exact same info. + */ +typedef struct { + DB_LSN lsn; + u_int32_t nsites; + u_int32_t nvotes; + u_int32_t priority; + u_int32_t tiebreaker; + u_int32_t ctlflags; + u_int32_t data_gen; +} VOTE1_CONTENT; + +/* + * REP -- + * Shared replication structure. + */ +typedef struct __rep { /* SHARED */ + db_mutex_t mtx_region; /* Region mutex. */ + db_mutex_t mtx_clientdb; /* Client database mutex. */ + db_mutex_t mtx_ckp; /* Checkpoint mutex. */ + db_mutex_t mtx_diag; /* Diagnostic message mutex. */ + db_mutex_t mtx_repstart; /* Role change mutex. */ + int diag_index; /* Diagnostic file index. */ + off_t diag_off; /* Diagnostic message offset. */ + roff_t lease_off; /* Offset of the lease table. */ + roff_t tally_off; /* Offset of the tally region. */ + roff_t v2tally_off; /* Offset of the vote2 tally region. */ + int eid; /* Environment id. */ + int master_id; /* ID of the master site. */ + u_int32_t version; /* Current replication version. */ + u_int32_t egen; /* Replication election generation. */ + u_int32_t spent_egen; /* Egen satisfied by rep_elect call. */ + u_int32_t gen; /* Replication generation number. */ + u_int32_t mgen; /* Master gen seen by client. */ + u_int32_t asites; /* Space allocated for sites. */ + u_int32_t nsites; /* Number of sites in group. */ + u_int32_t nvotes; /* Number of votes needed. */ + u_int32_t priority; /* My priority in an election. */ + u_int32_t config_nsites; + + db_timeout_t elect_timeout; /* Normal/full election timeouts. */ + db_timeout_t full_elect_timeout; + + db_timeout_t chkpt_delay; /* Master checkpoint delay. */ + +#define REP_DEFAULT_THROTTLE (10 * MEGABYTE) /* Default value is < 1Gig. */ + u_int32_t gbytes; /* Limit on data sent in single... */ + u_int32_t bytes; /* __rep_process_message call. */ +#define DB_REP_REQUEST_GAP 40000 /* 40 msecs */ +#define DB_REP_MAX_GAP 1280000 /* 1.28 seconds */ + db_timespec request_gap; /* Minimum time to wait before we + * request a missing log record. */ + db_timespec max_gap; /* Maximum time to wait before + * requesting a missing log record. */ + /* Status change information */ + u_int32_t apply_th; /* Number of callers in rep_apply. */ + u_int32_t arch_th; /* Number of callers in log_archive. */ + u_int32_t elect_th; /* Elect threads in lock-out. */ + u_int32_t msg_th; /* Number of callers in rep_proc_msg.*/ + u_int32_t handle_cnt; /* Count of handles in library. */ + u_int32_t op_cnt; /* Multi-step operation count.*/ + DB_LSN ckp_lsn; /* LSN for syncing a checkpoint. */ + DB_LSN max_prep_lsn; /* Max LSN of txn_prepare record. */ + + /* + * Event notification synchronization: the mtx_event and associate + * fields which it protects govern event notification to the + * application. They form a guarantee that no matter how crazy the + * thread scheduling gets, the application sees a sensible, orderly + * progression of events. + */ + db_mutex_t mtx_event; /* Serializes event notification. */ + /* + * Latest generation whose NEWMASTER event the application has been + * notified of. Also serves to force STARTUPDONE to occur after + * NEWMASTER. + */ + u_int32_t newmaster_event_gen; + /* + * Latest local victory of an election that the application has been + * notified of, expressed as the election generation number. This + * ensures we notify the application exactly once when it wins an + * election. + */ + u_int32_t notified_egen; + + /* Internal init information. */ + u_int32_t nfiles; /* Number of files we have info on. */ + u_int32_t curfile; /* Cur file we're getting (0-based). */ + roff_t originfo_off; /* Offset of original file info. */ + u_int32_t infolen; /* Remaining length file info buffer. */ + u_int32_t originfolen; /* Original length file info buffer. */ + u_int32_t infoversion; /* Original file info version. */ + DB_LSN first_lsn; /* Earliest LSN we need. */ + u_int32_t first_vers; /* Log version of first log file. */ + DB_LSN last_lsn; /* Latest LSN we need. */ + /* These are protected by mtx_clientdb. */ + db_timespec last_pg_ts; /* Last page stored timestamp. */ + db_pgno_t ready_pg; /* Next pg expected. */ + db_pgno_t waiting_pg; /* First pg after gap. */ + db_pgno_t max_wait_pg; /* Maximum pg requested. */ + u_int32_t npages; /* Num of pages rcvd for this file. */ + roff_t curinfo_off; /* Offset of current file info. */ + /* Always access with GET_CURINFO(). */ + + /* Vote tallying information. */ + u_int32_t sites; /* Sites heard from. */ + int winner; /* Current winner EID. */ + u_int32_t w_priority; /* Winner priority. */ + u_int32_t w_gen; /* Winner generation. */ + u_int32_t w_datagen; /* Winner data generation. */ + DB_LSN w_lsn; /* Winner LSN. */ + u_int32_t w_tiebreaker; /* Winner tiebreaking value. */ + u_int32_t votes; /* Number of votes for this site. */ + + VOTE1_CONTENT vote1; /* Valid until rep->egen changes. */ + + db_timespec etime; /* Election start timestamp. */ + int full_elect; /* Is current election a "full" one? */ + + /* Leases. */ + db_timeout_t lease_timeout; /* Lease timeout. */ + db_timespec lease_duration; /* Lease timeout with clock skew. */ + u_int32_t clock_skew; /* Clock skew. */ + u_int32_t clock_base; /* Clock scale factor base. */ + db_timespec grant_expire; /* Local grant expiration time. */ + + /* Cached LSN history, matching current gen. */ + DB_LSN gen_base_lsn; /* Base LSN of current generation. */ + u_int32_t master_envid; /* Current master's "unique" env ID. */ + + SH_TAILQ_HEAD(__wait) waiters; /* List of threads in txn_applied(). */ + SH_TAILQ_HEAD(__wfree) free_waiters;/* Free list of waiter structs. */ + +#ifdef HAVE_REPLICATION_THREADS + /* + * Replication Framework (repmgr) shared config information. + */ + db_mutex_t mtx_repmgr; /* Region mutex. */ + roff_t siteinfo_off; /* Offset of site array region. */ + u_int site_cnt; /* Array slots in use. */ + u_int site_max; /* Total array slots allocated. */ + int self_eid; /* Where to find the local site. */ + u_int siteinfo_seq; /* Number of updates to this info. */ + u_int32_t min_log_file; /* Earliest log needed by repgroup. */ + + pid_t listener; + + int perm_policy; + db_timeout_t ack_timeout; + db_timeout_t election_retry_wait; + db_timeout_t connection_retry_wait; + db_timeout_t heartbeat_frequency; /* Max period between msgs. */ + db_timeout_t heartbeat_monitor_timeout; +#endif /* HAVE_REPLICATION_THREADS */ + + /* Statistics. */ + DB_REP_STAT stat; +#if defined(HAVE_REPLICATION_THREADS) && defined(HAVE_STATISTICS) + DB_REPMGR_STAT mstat; +#endif + + /* + * Please change __rep_print_all (rep_stat.c) to track any changes made + * to all these flag families below. + */ + /* Configuration. */ +#define REP_C_2SITE_STRICT 0x00001 /* Don't cheat on elections. */ +#define REP_C_AUTOINIT 0x00002 /* Auto initialization. */ +#define REP_C_AUTOROLLBACK 0x00004 /* Discard client txns: sync. */ +#define REP_C_BULK 0x00008 /* Bulk transfer. */ +#define REP_C_DELAYCLIENT 0x00010 /* Delay client sync-up. */ +#define REP_C_ELECTIONS 0x00020 /* Repmgr to use elections. */ +#define REP_C_INMEM 0x00040 /* In-memory replication. */ +#define REP_C_LEASE 0x00080 /* Leases configured. */ +#define REP_C_NOWAIT 0x00100 /* Immediate error return. */ + u_int32_t config; /* Configuration flags. */ + + /* Election. */ +#define REP_E_PHASE0 0x00000001 /* In phase 0 of election. */ +#define REP_E_PHASE1 0x00000002 /* In phase 1 of election. */ +#define REP_E_PHASE2 0x00000004 /* In phase 2 of election. */ +#define REP_E_TALLY 0x00000008 /* Tallied vote before elect. */ + u_int32_t elect_flags; /* Election flags. */ + + /* Lockout. */ +#define REP_LOCKOUT_API 0x00000001 /* BDB API - handle_cnt. */ +#define REP_LOCKOUT_APPLY 0x00000002 /* apply msgs - apply_th. */ +#define REP_LOCKOUT_ARCHIVE 0x00000004 /* log_archive. */ +#define REP_LOCKOUT_MSG 0x00000008 /* Message process - msg_th. */ +#define REP_LOCKOUT_OP 0x00000010 /* BDB ops txn,curs - op_cnt. */ + u_int32_t lockout_flags; /* Lockout flags. */ + + /* See above for enumerated sync states. */ + repsync_t sync_state; /* Recovery/synchronization flags. */ + + /* + * When adding a new flag value, consider whether it should be + * cleared in rep_start() when starting as a master or a client. + */ +#define REP_F_ABBREVIATED 0x00000001 /* Recover NIMDB pages only. */ +#define REP_F_APP_BASEAPI 0x00000002 /* Base API application. */ +#define REP_F_APP_REPMGR 0x00000004 /* repmgr application. */ +#define REP_F_CLIENT 0x00000008 /* Client replica. */ +#define REP_F_DELAY 0x00000010 /* Delaying client sync-up. */ +#define REP_F_GROUP_ESTD 0x00000020 /* Rep group is established. */ +#define REP_F_INUPDREQ 0x00000040 /* Thread in rep_update_req. */ +#define REP_F_LEASE_EXPIRED 0x00000080 /* Leases guaranteed expired. */ +#define REP_F_MASTER 0x00000100 /* Master replica. */ +#define REP_F_MASTERELECT 0x00000200 /* Master elect. */ +#define REP_F_NEWFILE 0x00000400 /* Newfile in progress. */ +#define REP_F_NIMDBS_LOADED 0x00000800 /* NIMDBs are materialized. */ +#define REP_F_SKIPPED_APPLY 0x00001000 /* Skipped applying a record. */ +#define REP_F_START_CALLED 0x00002000 /* Rep_start called. */ +#define REP_F_SYS_DB_OP 0x00004000 /* Operation in progress. */ + u_int32_t flags; +} REP; + +/* Information about a thread waiting in txn_applied(). */ +typedef enum { + AWAIT_GEN, /* Client's gen is behind token gen. */ + AWAIT_HISTORY, /* Haven't received master's LSN db update. */ + AWAIT_LSN, /* Awaiting replication of user txn. */ + AWAIT_NIMDB, /* LSN db missing: maybe it's INMEM. */ + LOCKOUT /* Thread awoken due to pending lockout. */ +} rep_waitreason_t; + +struct rep_waitgoal { + rep_waitreason_t why; + union { + DB_LSN lsn; /* For AWAIT_LSN and AWAIT_HISTORY. */ + u_int32_t gen; /* AWAIT_GEN */ + } u; +}; + +struct __rep_waiter { + db_mutex_t mtx_repwait; /* Self-blocking mutex. */ + struct rep_waitgoal goal; + SH_TAILQ_ENTRY links; /* On either free or waiting list. */ + +#define REP_F_PENDING_LOCKOUT 0x00000001 +#define REP_F_WOKEN 0x00000002 + u_int32_t flags; +}; + +/* + * Macros to check and clear the BDB lockouts. Currently they are + * locked out/set individually because they pertain to different pieces of + * the BDB API, they are otherwise always checked and cleared together. + */ +#define ISSET_LOCKOUT_BDB(R) \ + (FLD_ISSET((R)->lockout_flags, (REP_LOCKOUT_API | REP_LOCKOUT_OP))) + +#define CLR_LOCKOUT_BDB(R) \ + (FLD_CLR((R)->lockout_flags, (REP_LOCKOUT_API | REP_LOCKOUT_OP))) + +/* + * Recovery flag mask to easily check any/all recovery bits. That is + * REP_LOCKOUT_{API|OP} and most REP_S_*. This must change if the values + * of the flags change. NOTE: We do not include REP_LOCKOUT_MSG in + * this mask because it is used frequently in non-recovery related + * areas and we want to manipulate it separately (see especially + * in __rep_new_master). + */ +#define CLR_RECOVERY_SETTINGS(R) \ +do { \ + (R)->sync_state = SYNC_OFF; \ + CLR_LOCKOUT_BDB(R); \ +} while (0) + +#define IS_REP_RECOVERING(R) \ + ((R)->sync_state != SYNC_OFF || ISSET_LOCKOUT_BDB(R)) + +/* + * REP_F_EPHASE0 is not a *real* election phase. It is used for + * master leases and allowing the client to find the master or + * expire its lease. + */ +#define IN_ELECTION(R) \ + FLD_ISSET((R)->elect_flags, REP_E_PHASE1 | REP_E_PHASE2) +#define IN_ELECTION_TALLY(R) \ + FLD_ISSET((R)->elect_flags, REP_E_PHASE1 | REP_E_PHASE2 | REP_E_TALLY) +#define ELECTION_MAJORITY(n) (((n) / 2) + 1) + +#define IN_INTERNAL_INIT(R) \ + ((R)->sync_state == SYNC_LOG || (R)->sync_state == SYNC_PAGE) + +#define IS_REP_MASTER(env) \ + (REP_ON(env) && \ + F_ISSET(((env)->rep_handle->region), REP_F_MASTER)) + +#define IS_REP_CLIENT(env) \ + (REP_ON(env) && \ + F_ISSET(((env)->rep_handle->region), REP_F_CLIENT)) + +#define IS_REP_STARTED(env) \ + (REP_ON(env) && \ + F_ISSET(((env)->rep_handle->region), REP_F_START_CALLED)) + +#define IS_USING_LEASES(env) \ + (REP_ON(env) && \ + FLD_ISSET(((env)->rep_handle->region)->config, REP_C_LEASE)) + +#define IS_CLIENT_PGRECOVER(env) \ + (IS_REP_CLIENT(env) && \ + (((env)->rep_handle->region)->sync_state == SYNC_PAGE)) + +/* + * Macros to figure out if we need to do replication pre/post-amble processing. + * Skip for specific DB handles owned by the replication layer, either because + * replication is running recovery or because it's a handle entirely owned by + * the replication code (replication opens its own databases to track state). + */ +#define REP_FLAGS_SET(env) \ + ((env)->rep_handle->region->flags != 0 || \ + (env)->rep_handle->region->elect_flags != 0 || \ + (env)->rep_handle->region->lockout_flags != 0) + +#define IS_ENV_REPLICATED(env) \ + (REP_ON(env) && REP_FLAGS_SET(env)) + +/* + * Update the temporary log archive block timer. + */ +#define MASTER_UPDATE(env, renv) do { \ + REP_SYSTEM_LOCK(env); \ + F_SET((renv), DB_REGENV_REPLOCKED); \ + (void)time(&(renv)->op_timestamp); \ + REP_SYSTEM_UNLOCK(env); \ +} while (0) + +/* + * Macro to set a new generation number. Cached values from the LSN history + * database are associated with the current gen, so when the gen changes we must + * invalidate the cache. Use this macro for all gen changes, to avoid + * forgetting to do so. This macro should be used while holding the rep system + * mutex (unless we know we're single-threaded for some other reason, like at + * region create time). + */ +#define SET_GEN(g) do { \ + rep->gen = (g); \ + ZERO_LSN(rep->gen_base_lsn); \ +} while (0) + + +/* + * Gap processing flags. These provide control over the basic + * gap processing algorithm for some special cases. + */ +#define REP_GAP_FORCE 0x001 /* Force a request for a gap. */ +#define REP_GAP_REREQUEST 0x002 /* Gap request is a forced rerequest. */ + /* REREQUEST is a superset of FORCE. */ + +/* + * Flags indicating what kind of record we want to back up to, in the log. + */ +#define REP_REC_COMMIT 0x001 /* Most recent commit record. */ +#define REP_REC_PERM 0x002 /* Most recent perm record. */ + /* PERM is a superset of COMMIT. */ + +/* + * Basic pre/post-amble processing. + */ +#define REPLICATION_WRAP(env, func_call, checklock, ret) do { \ + int __rep_check, __t_ret; \ + __rep_check = IS_ENV_REPLICATED(env) ? 1 : 0; \ + (ret) = __rep_check ? __env_rep_enter(env, checklock) : 0; \ + if ((ret) == 0) { \ + (ret) = func_call; \ + if (__rep_check && (__t_ret = \ + __env_db_rep_exit(env)) != 0 && (ret) == 0) \ + (ret) = __t_ret; \ + } \ +} while (0) + +/* + * Macro to safely access curinfo and its internal DBT pointers from + * any process. This should always be used to access curinfo. If + * the internal DBT pointers are to be used, mtx_clientdb must be held + * between the time of this call and the use of the pointers. + * + * The current file information (curinfo) is stored in shared region + * memory and accessed via an offset. It contains DBTs that themselves + * point to allocated data. __rep_nextfile() manages this information in a + * single chunk of shared memory. + * + * If different processes access curinfo, they may have different shared + * region addresses. This means that curinfo and its pointers to DBT data + * must be recalculated for each process starting with the offset. + */ +#define GET_CURINFO(rep, infop, curinfo) \ +do { \ + curinfo = R_ADDR(infop, rep->curinfo_off); \ + if ((curinfo)->uid.size > 0) \ + (curinfo)->uid.data = R_ADDR(infop, \ + rep->curinfo_off + sizeof(__rep_fileinfo_args)); \ + else \ + (curinfo)->uid.data = NULL; \ + if ((curinfo)->info.size > 0) \ + (curinfo)->info.data = R_ADDR(infop, rep->curinfo_off + \ + sizeof(__rep_fileinfo_args) + (curinfo)->uid.size); \ + else \ + (curinfo)->info.data = NULL; \ + if ((curinfo)->dir.size > 0) \ + (curinfo)->dir.data = R_ADDR(infop, rep->curinfo_off + \ + sizeof(__rep_fileinfo_args) + (curinfo)->uid.size + \ + (curinfo)->info.size); \ + else \ + (curinfo)->dir.data = NULL; \ +} while (0) + +/* + * Per-process replication structure. + * + * There are 2 mutexes used in the Base replication API. (See LOCK_MUTEX in + * repmgr.h for a discussion of repmgr.) + * 1. mtx_region - This protects the fields of the rep region above. + * 2. mtx_clientdb - This protects the per-process flags, and bookkeeping + * database and all of the components that maintain it. Those + * components include the following fields in the log region (see log.h): + * a. ready_lsn + * b. waiting_lsn + * c. verify_lsn + * d. wait_recs + * e. rcvd_recs + * f. max_wait_lsn + * These fields in the log region are NOT protected by the log region lock at + * all. + * + * Note that the per-process flags should truly be protected by a special + * per-process thread mutex, but it is currently set in so isolated a manner + * that it didn't make sense to do so and in most case we're already holding + * the mtx_clientdb anyway. + * + * The lock ordering protocol is that mtx_clientdb must be acquired first and + * then either REP->mtx_region, or the LOG->mtx_region mutex may be acquired if + * necessary. + * + * Note that the appropriate mutex is needed any time one or more related + * values are read or written that could possibly use more than one atomic + * machine instruction. A single 32-bit integer value is safe without a + * mutex, but most other types of value should use a mutex. + * + * Any use of a mutex must be inside a matched pair of ENV_ENTER() and + * ENV_LEAVE() macros. This ensures that if a thread dies while holding + * a lock (i.e. a mutex), recovery can clean it up so that it does not + * indefinitely block other threads. + */ +struct __db_rep { + /* + * Shared configuration information -- copied to and maintained in the + * shared region as soon as the shared region is created. + */ + int eid; /* Environment ID. */ + + u_int32_t gbytes; /* Limit on data sent in single... */ + u_int32_t bytes; /* __rep_process_message call. */ + + db_timespec request_gap; /* Minimum time to wait before we + * request a missing log record. */ + db_timespec max_gap; /* Maximum time to wait before + * requesting a missing log record. */ + + u_int32_t clock_skew; /* Clock skew factor. */ + u_int32_t clock_base; /* Clock skew base. */ + u_int32_t config; /* Configuration flags. */ + u_int32_t config_nsites; + + db_timeout_t elect_timeout; /* Normal/full election timeouts. */ + db_timeout_t full_elect_timeout; + + db_timeout_t chkpt_delay; /* Master checkpoint delay. */ + + u_int32_t my_priority; + db_timeout_t lease_timeout; /* Master leases. */ + /* + * End of shared configuration information. + */ + int (*send) /* Send function. */ + __P((DB_ENV *, const DBT *, const DBT *, + const DB_LSN *, int, u_int32_t)); + + DB *rep_db; /* Bookkeeping database. */ + DB *lsn_db; /* (Replicated) LSN history database. */ + + REP *region; /* In memory structure. */ + u_int8_t *bulk; /* Shared memory bulk area. */ + +#define DBREP_DIAG_FILES 2 + DB_FH *diagfile[DBREP_DIAG_FILES]; /* Diag files fhp. */ + off_t diag_off; /* Current diag file offset. */ + + /* These are protected by mtx_clientdb. */ + DB_MPOOLFILE *file_mpf; /* Mpoolfile for current database. */ + DB *file_dbp; /* This file's page info. */ + DBC *queue_dbc; /* Dbc for a queue file. */ + + /* + * Please change __rep_print_all (rep_stat.c) to track any changes made + * to these flags. + */ +#define DBREP_APP_BASEAPI 0x0001 /* Base API application. */ +#define DBREP_APP_REPMGR 0x0002 /* repmgr application. */ +#define DBREP_OPENFILES 0x0004 /* This handle has opened files. */ + u_int32_t flags; /* per-process flags. */ + +#ifdef HAVE_REPLICATION_THREADS + /* + * Replication Framework (repmgr) per-process information. + */ + u_int nthreads; /* Msg processing threads. */ + u_int athreads; /* Space allocated for msg threads. */ + u_int non_rep_th; /* Threads in GMDB or channel msgs. */ + u_int aelect_threads; /* Space allocated for elect threads. */ + u_int32_t init_policy; + int perm_policy; + DB_LSN perm_lsn; /* Last perm LSN we've announced. */ + db_timeout_t ack_timeout; + db_timeout_t election_retry_wait; + db_timeout_t connection_retry_wait; + db_timeout_t heartbeat_frequency; /* Max period between msgs. */ + db_timeout_t heartbeat_monitor_timeout; + + /* Thread synchronization. */ + REPMGR_RUNNABLE *selector, **messengers, **elect_threads; + REPMGR_RUNNABLE *preferred_elect_thr; + db_timespec repstart_time; + mgr_mutex_t *mutex; + cond_var_t check_election, gmdb_idle, msg_avail; + waiter_t ack_waiters; /* For threads awaiting PERM acks. */ +#ifdef DB_WIN32 + HANDLE signaler; +#else + int read_pipe, write_pipe; +#endif + + /* Operational stuff. */ + REPMGR_SITE *sites; /* Array of known sites. */ + u_int site_cnt; /* Array slots in use. */ + u_int site_max; /* Total array slots allocated. */ + int self_eid; /* Where to find the local site. */ + u_int siteinfo_seq; /* Last known update to this list. */ + + /* + * The connections list contains only those connections not actively + * associated with a known site (see repmgr.h). + */ + CONNECTION_LIST connections; + RETRY_Q_HEADER retries; /* Sites needing connection retry. */ + struct { + int size; + STAILQ_HEAD(__repmgr_q_header, __repmgr_message) header; + } input_queue; + + socket_t listen_fd; + db_timespec last_bcast; /* Time of last broadcast msg. */ + + /* + * Status of repmgr. It is ready when repmgr is not yet started. It + * is running after repmgr is (re)started. It is stopped if the env + * of the running repmgr is closed, or the site is removed. + */ + enum { ready, running, stopped } repmgr_status; + int new_connection; /* Since last master seek attempt. */ + int takeover_pending; /* We've been elected master. */ + int gmdb_busy; + int client_intent; /* Will relinquish master role. */ + int gmdb_dirty; + int have_gmdb; + int seen_repmsg; + + /* + * Flag to show what kind of transaction is currently in progress. + * Primary means we're doing the first (critical) phase of a membership + * DB update, where we care about perm failures. In the secondary phase + * we don't care. Usually the value is "none", when normal user + * transactions are happening. We need to use this global flag because + * we don't have a more proper direct channel to communicate information + * between the originator of a transaction and the replication send() + * function that has to wait for acks and decide what to do about them. + */ + enum { none, gmdb_primary, gmdb_secondary } active_gmdb_update; + int limbo_resolution_needed; + + /* + * GMDB update sequence count. On creation we write version 1; so, once + * repmgr has started and tried to read, a 0 here can be taken to mean + * that the DB doesn't exist yet. + */ + u_int32_t membership_version; + u_int32_t member_version_gen; + + /* LSN of GMDB txn that got a perm failure. */ + DB_LSN limbo_failure; + /* EID whose membership status is therefore unresolved */ + int limbo_victim; + /* LSN of a later txn that achieves perm success. */ + DB_LSN durable_lsn; + DB *gmdb; /* Membership database handle. */ + /* + * Membership list restored from init file after crash during internal init. + */ + u_int8_t *restored_list; + size_t restored_list_length; + + /* Application's message dispatch call-back function. */ + void (*msg_dispatch) __P((DB_ENV *, DB_CHANNEL *, + DBT *, u_int32_t, u_int32_t)); +#endif /* HAVE_REPLICATION_THREADS */ +}; + +/* + * Determine whether application is repmgr or base replication API. If + * repmgr was configured, base the test on internal replication flags for + * APP_REPMGR and APP_BASEAPI. These flags get set by the appropriate parts + * of the various replication APIs. + */ +#ifdef HAVE_REPLICATION_THREADS +/* + * Application type is set to be repmgr when: + * 1. A local site is defined. + * 2. A remote site is defined. + * 3. An acknowledgement policy is configured. + * 4. A repmgr flag is configured. + * 5. A timeout value is configured for one of the repmgr timeouts. + */ +#define APP_IS_REPMGR(env) \ + (REP_ON(env) ? \ + F_ISSET((env)->rep_handle->region, REP_F_APP_REPMGR) : \ + F_ISSET((env)->rep_handle, DBREP_APP_REPMGR)) + +/* + * Application type is set to be base replication API when: + * 1. Transport send function is defined and is not the repmgr send + * function. + */ +#define APP_IS_BASEAPI(env) \ + (REP_ON(env) ? \ + F_ISSET((env)->rep_handle->region, REP_F_APP_BASEAPI) : \ + F_ISSET((env)->rep_handle, DBREP_APP_BASEAPI)) + +/* + * Set application type. These macros do extra checking to guarantee that + * only one application type is ever set. + */ +#define APP_SET_REPMGR(env) do { \ + if (REP_ON(env)) { \ + ENV_ENTER(env, ip); \ + REP_SYSTEM_LOCK(env); \ + if (!F_ISSET((env)->rep_handle->region, \ + REP_F_APP_BASEAPI)) \ + F_SET((env)->rep_handle->region, \ + REP_F_APP_REPMGR); \ + REP_SYSTEM_UNLOCK(env); \ + ENV_LEAVE(env, ip); \ + } else if (!F_ISSET((env)->rep_handle, DBREP_APP_BASEAPI)) \ + F_SET((env)->rep_handle, DBREP_APP_REPMGR); \ +} while (0) +#define APP_SET_BASEAPI(env) do { \ + if (REP_ON(env)) { \ + ENV_ENTER(env, ip); \ + REP_SYSTEM_LOCK(env); \ + if (!F_ISSET((env)->rep_handle->region, \ + REP_F_APP_REPMGR)) \ + F_SET((env)->rep_handle->region, \ + REP_F_APP_BASEAPI); \ + REP_SYSTEM_UNLOCK(env); \ + ENV_LEAVE(env, ip); \ + } else if (!F_ISSET((env)->rep_handle, DBREP_APP_REPMGR)) \ + F_SET((env)->rep_handle, DBREP_APP_BASEAPI); \ +} while (0) + +#else +/* + * We did not configure repmgr, application must be base replication API. + * The APP_SET_* macros are noops in this case, but they must be defined + * with a null body to avoid compiler warnings on some platforms. + */ +#define APP_IS_REPMGR(env) 0 +#define APP_SET_REPMGR(env) do { \ + ; \ +} while (0) +#define APP_IS_BASEAPI(env) 1 +#define APP_SET_BASEAPI(env) do { \ + ; \ +} while (0) +#endif /* HAVE_REPLICATION_THREADS */ + +/* + * Control structure flags for replication communication infrastructure. + */ +/* + * Define old DB_LOG_ values that we must support here. For reasons of + * compatibility with old versions, these values must be reserved explicitly in + * the list of flag values (below) + */ +#define DB_LOG_PERM_42_44 0x20 +#define DB_LOG_RESEND_42_44 0x40 +#define REPCTL_INIT_45 0x02 /* Back compatible flag value. */ + +#define REPCTL_ELECTABLE 0x01 /* Upgraded client is electable. */ +#define REPCTL_FLUSH 0x02 /* Record should be flushed. */ +#define REPCTL_GROUP_ESTD 0x04 /* Message from site in a group. */ +#define REPCTL_INIT 0x08 /* Internal init message. */ +#define REPCTL_LEASE 0x10 /* Lease related message.. */ + /* + * Skip over reserved values 0x20 + * and 0x40, as explained above. + */ +#define REPCTL_LOG_END 0x80 /* Approximate end of group-wide log. */ +#define REPCTL_PERM DB_LOG_PERM_42_44 +#define REPCTL_RESEND DB_LOG_RESEND_42_44 + +/* + * File info flags for internal init. The per-database (i.e., file) flag + * represents the on-disk format of the file, and is conveyed from the master to + * the initializing client in the UPDATE message, so that the client can know + * how to create the file. The per-page flag is conveyed along with each PAGE + * message, describing the format of the page image being transmitted; it is of + * course set by the site serving the PAGE_REQ. The serving site gets the page + * image from its own mpool, and thus the page is in the native format of the + * serving site. This format may be different (i.e., opposite) from the on-disk + * format, and in fact can vary per-page, since with client-to-client sync it is + * possible for various different sites to serve the various PAGE_REQ requests. + */ +#define REPINFO_DB_LITTLEENDIAN 0x0001 /* File is little-endian lorder. */ +#define REPINFO_PG_LITTLEENDIAN 0x0002 /* Page is little-endian lorder. */ + +/* + * Control message format for 4.6 release. The db_timespec_t is + * not a portable structure. Therefore, in 4.6, replication among + * mixed OSs such as Linux and Windows, which have different time_t + * sizes, does not work. + */ +typedef struct { + u_int32_t rep_version; /* Replication version number. */ + u_int32_t log_version; /* Log version number. */ + + DB_LSN lsn; /* Log sequence number. */ + u_int32_t rectype; /* Message type. */ + u_int32_t gen; /* Generation number. */ + db_timespec msg_time; /* Timestamp seconds for leases. */ + u_int32_t flags; /* log_put flag value. */ +} REP_46_CONTROL; + +/* + * Control message format for 4.5 release and earlier. + */ +typedef struct { + u_int32_t rep_version; /* Replication version number. */ + u_int32_t log_version; /* Log version number. */ + + DB_LSN lsn; /* Log sequence number. */ + u_int32_t rectype; /* Message type. */ + u_int32_t gen; /* Generation number. */ + u_int32_t flags; /* log_put flag value. */ +} REP_OLD_CONTROL; + +#define LEASE_REFRESH_MIN 30 /* Minimum number of refresh retries. */ +#define LEASE_REFRESH_USEC 50000 /* Microseconds between refresh tries. */ + +/* Master granted lease information. */ +typedef struct __rep_lease_entry { + int eid; /* EID of client grantor. */ + db_timespec start_time; /* Start time clients echo back. */ + db_timespec end_time; /* Master lease expiration time. */ + DB_LSN lease_lsn; /* Durable LSN lease applies to. */ +} REP_LEASE_ENTRY; + +/* + * Old vote info where some fields were not fixed size. + */ +typedef struct { + u_int32_t egen; /* Election generation. */ + int nsites; /* Number of sites I've been in + * communication with. */ + int nvotes; /* Number of votes needed to win. */ + int priority; /* My site's priority. */ + u_int32_t tiebreaker; /* Tie-breaking quasi-random value. */ +} REP_OLD_VOTE_INFO; + +typedef struct { + u_int32_t egen; /* Voter's election generation. */ + int eid; /* Voter's ID. */ +} REP_VTALLY; + +/* + * The REP_THROTTLE_ONLY flag is used to do throttle processing only. + * If set, it will only allow sending the REP_*_MORE message, but not + * the normal, non-throttled message. It is used to support throttling + * with bulk transfer. + */ +/* Flags for __rep_send_throttle. */ +#define REP_THROTTLE_ONLY 0x0001 /* Send _MORE message only. */ + +/* Throttled message processing information. */ +typedef struct { + DB_LSN lsn; /* LSN of this record. */ + DBT *data_dbt; /* DBT of this record. */ + u_int32_t gbytes; /* This call's max gbytes sent. */ + u_int32_t bytes; /* This call's max bytes sent. */ + u_int32_t type; /* Record type. */ +} REP_THROTTLE; + +/* Bulk processing information. */ +/* + * !!! + * We use a roff_t for the offset. We'd really like to use a ptrdiff_t + * since that really is what it is. But ptrdiff_t is not portable and + * doesn't exist everywhere. + */ +typedef struct { + u_int8_t *addr; /* Address of bulk buffer. */ + roff_t *offp; /* Ptr to current offset into buffer. */ + u_int32_t len; /* Bulk buffer length. */ + u_int32_t type; /* Item type in buffer (log, page). */ + DB_LSN lsn; /* First LSN in buffer. */ + int eid; /* ID of potential recipients. */ +#define BULK_XMIT 0x001 /* Buffer in transit. */ + u_int32_t *flagsp; /* Buffer flags. */ +} REP_BULK; + +/* + * This structure takes care of representing a transaction. + * It holds all the records, sorted by page number so that + * we can obtain locks and apply updates in a deadlock free + * order. + */ +typedef struct { + u_int nlsns; + u_int nalloc; + DB_LSN *array; +} LSN_COLLECTION; + +/* + * This is used by the page-prep routines to do the lock_vec call to + * apply the updates for a single transaction or a collection of + * transactions. + */ +typedef struct { + int n; + DB_LOCKREQ *reqs; + DBT *objs; +} linfo_t; + +#if defined(__cplusplus) +} +#endif + +#include "dbinc_auto/rep_ext.h" +#endif /* !_DB_REP_H_ */ diff -r 000000000000 -r a1985f14b030 src/dbinc/repmgr.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/dbinc/repmgr.h Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,865 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 2006, 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + * $Id$ + */ + +#ifndef _DB_REPMGR_H_ +#define _DB_REPMGR_H_ + +#include "dbinc_auto/repmgr_automsg.h" + +#if defined(__cplusplus) +extern "C" { +#endif + +/* + * Replication Manager message format types. These few format codes identify + * enough information to describe, at the lowest level, how a message should be + * read from the wire, including how much memory should be allocated to hold the + * result. (Often we want to allocate more than just enough to hold the + * received bytes, if we know that we will need more during processing.) + * + * These values are transmitted between sites, even sites running differing BDB + * versions. Therefore, once assigned, the values are permanently "frozen". + * + * For example, in repmgr wire protocol version 1 the highest assigned message + * type value was 3, for REPMGR_REP_MESSAGE. Wire protocol version 2 added the + * HEARTBEAT message type (4). + * + * New message types added in later versions always get new (higher) values. We + * still list them in alphabetical order, for ease of reference. But this + * generally does not correspond to numerical order. + */ +#define REPMGR_APP_MESSAGE 5 /* Msg sent from app. on DB_CHANNEL. */ +#define REPMGR_APP_RESPONSE 6 /* Response to a channel request. */ +#define REPMGR_OWN_MSG 8 /* Repmgr's own messages, to peers. */ +#define REPMGR_HANDSHAKE 2 /* Connection establishment sequence. */ +#define REPMGR_HEARTBEAT 4 /* Monitor connection health. */ +#define REPMGR_PERMLSN 1 /* My perm LSN. */ +#define REPMGR_REP_MESSAGE 3 /* Normal replication message. */ +#define REPMGR_RESP_ERROR 7 /* Sys-gen'd error resp to request. */ + +/* + * Largest known message type code known in each protocol version we support. + * In protocol version one there were only three message types: 1, 2, and 3; so + * 3 was the max. In protocol version 2 we introduced heartbeats, type 4. + * (Protocol version 3 did not introduce any new message types.) In version 4 + * we introduced a few more new message types, the largest of which had value 7. + */ +#define REPMGR_MAX_V1_MSG_TYPE 3 +#define REPMGR_MAX_V2_MSG_TYPE 4 +#define REPMGR_MAX_V3_MSG_TYPE 4 +#define REPMGR_MAX_V4_MSG_TYPE 8 +#define HEARTBEAT_MIN_VERSION 2 +#define CHANNEL_MIN_VERSION 4 +#define CONN_COLLISION_VERSION 4 +#define GM_MIN_VERSION 4 +#define OWN_MIN_VERSION 4 + +/* The range of protocol versions we're willing to support. */ +#define DB_REPMGR_VERSION 4 +#define DB_REPMGR_MIN_VERSION 1 + +/* + * For messages with the "REPMGR_OWN_MSG" format code, a message type (see + * REPMGR_OWN_MSG_TYPE, below) is included in the header. While at the lowest + * level, the format codes identify only enough to read and allocate memory, at + * the next higher level the following message type codes identify the content + * of the message: how to unmarshal and dispatch it. + * + * Like the message format types, these message type values should be + * permanently frozen. + */ +#define REPMGR_CONNECT_REJECT 1 +#define REPMGR_GM_FAILURE 2 +#define REPMGR_GM_FORWARD 3 +#define REPMGR_JOIN_REQUEST 4 +#define REPMGR_JOIN_SUCCESS 5 +#define REPMGR_PARM_REFRESH 6 +#define REPMGR_REJOIN 7 +#define REPMGR_REMOVE_REQUEST 8 +#define REPMGR_REMOVE_SUCCESS 9 +#define REPMGR_RESOLVE_LIMBO 10 +#define REPMGR_SHARING 11 + + +struct __repmgr_connection; + typedef struct __repmgr_connection REPMGR_CONNECTION; +struct __repmgr_queue; typedef struct __repmgr_queue REPMGR_QUEUE; +struct __queued_output; typedef struct __queued_output QUEUED_OUTPUT; +struct __repmgr_response; typedef struct __repmgr_response REPMGR_RESPONSE; +struct __repmgr_retry; typedef struct __repmgr_retry REPMGR_RETRY; +struct __repmgr_runnable; typedef struct __repmgr_runnable REPMGR_RUNNABLE; +struct __repmgr_site; typedef struct __repmgr_site REPMGR_SITE; +struct __cond_waiters_table; + typedef struct __cond_waiters_table COND_WAITERS_TABLE; + +/* Current Group Membership DB format ID. */ +#define REPMGR_GMDB_FMT_VERSION 1 + +#ifdef DB_WIN32 +typedef SOCKET socket_t; +typedef HANDLE thread_id_t; +typedef HANDLE mgr_mutex_t; +typedef HANDLE cond_var_t; + +typedef COND_WAITERS_TABLE *waiter_t; +typedef WSABUF db_iovec_t; +#else +typedef int socket_t; +typedef pthread_t thread_id_t; +typedef pthread_mutex_t mgr_mutex_t; +typedef pthread_cond_t cond_var_t; +typedef pthread_cond_t waiter_t; +typedef struct iovec db_iovec_t; +#endif + +/* + * The (arbitrary) maximum number of outgoing messages we're willing to hold, on + * a queue per connection, waiting for TCP buffer space to become available in + * the kernel. Rather than exceeding this limit, we simply discard additional + * messages (since this is always allowed by the replication protocol). + * As a special dispensation, if a message is destined for a specific remote + * site (i.e., it's not a broadcast), then we first try blocking the sending + * thread, waiting for space to become available (though we only wait a limited + * time). This is so as to be able to handle the immediate flood of (a + * potentially large number of) outgoing messages that replication generates, in + * a tight loop, when handling PAGE_REQ, LOG_REQ and ALL_REQ requests. + */ +#define OUT_QUEUE_LIMIT 10 + +/* + * The system value is available from sysconf(_SC_HOST_NAME_MAX). + * Historically, the maximum host name was 256. + */ +#ifndef MAXHOSTNAMELEN +#define MAXHOSTNAMELEN 256 +#endif + +/* A buffer big enough for the string "site host.domain.com:65535". */ +#define MAX_SITE_LOC_STRING (MAXHOSTNAMELEN+20) +typedef char SITE_STRING_BUFFER[MAX_SITE_LOC_STRING+1]; + +#define MAX_MSG_BUF (__REPMGR_MAXMSG_SIZE + MAXHOSTNAMELEN + 1) + +/* Default timeout values, in seconds. */ +#define DB_REPMGR_DEFAULT_ACK_TIMEOUT (1 * US_PER_SEC) +#define DB_REPMGR_DEFAULT_CONNECTION_RETRY (30 * US_PER_SEC) +#define DB_REPMGR_DEFAULT_ELECTION_RETRY (10 * US_PER_SEC) +#define DB_REPMGR_DEFAULT_CHANNEL_TIMEOUT (5 * US_PER_SEC) + +typedef TAILQ_HEAD(__repmgr_conn_list, __repmgr_connection) CONNECTION_LIST; +typedef STAILQ_HEAD(__repmgr_out_q_head, __queued_output) OUT_Q_HEADER; +typedef TAILQ_HEAD(__repmgr_retry_q, __repmgr_retry) RETRY_Q_HEADER; + +/* Information about threads managed by Replication Framework. */ +struct __repmgr_runnable { + ENV *env; + thread_id_t thread_id; + void *(*run) __P((void *)); + int finished; /* Boolean: thread is exiting, may be joined. */ + int quit_requested; /* Boolean: thread has been asked to quit. */ +#ifdef DB_WIN32 + HANDLE quit_event; +#endif + union { + +/* + * Options governing requested behavior of election thread. + */ +#define ELECT_F_EVENT_NOTIFY 0x01 /* Notify application of master failure. */ +#define ELECT_F_FAST 0x02 /* First election "fast" (n-1 trick). */ +#define ELECT_F_IMMED 0x04 /* Start with immediate election. */ +#define ELECT_F_INVITEE 0x08 /* Honor (remote) inviter's nsites. */ +#define ELECT_F_STARTUP 0x10 /* Observe repmgr_start() policy. */ + u_int32_t flags; + + int eid; /* For Connector thread. */ + + /* + * Args for other thread types can be added here in the future + * as needed. + */ + } args; +}; + +/* + * Information about pending connection establishment retry operations. + * + * We keep these in order by time. This works, under the assumption that the + * DB_REP_CONNECTION_RETRY never changes once we get going (though that + * assumption is of course wrong, so this needs to be fixed). + * + * Usually, we put things onto the tail end of the list. But when we add a new + * site while threads are running, we trigger its first connection attempt by + * scheduling a retry for "0" microseconds from now, putting its retry element + * at the head of the list instead. + * + * TODO: I think this can be fixed by defining "time" to be the time the element + * was added (with some convention like "0" meaning immediate), rather than the + * deadline time. + */ +struct __repmgr_retry { + TAILQ_ENTRY(__repmgr_retry) entries; + int eid; + db_timespec time; +}; + +/* + * We use scatter/gather I/O for both reading and writing. Repmgr messages + * (including rep messages) use 3 segments: envelope, control and rec. + * Application messages can have any number of segments (the number they + * specify, plus 1 for our envelope). REPMGR_IOVECS_ALLOC_SZ should (only) be + * used when n > 3. + */ +#define REPMGR_IOVECS_ALLOC_SZ(n) \ + (sizeof(REPMGR_IOVECS) + ((n) - MIN_IOVEC) * sizeof(db_iovec_t)) +typedef struct { + /* + * Index of the first iovec to be used. Initially of course this is + * zero. But as we progress through partial I/O transfers, it ends up + * pointing to the first iovec to be used on the next operation. + */ + int offset; + + /* + * Total number of pieces defined for this message; equal to the number + * of times add_buffer and/or add_dbt were called to populate it. We do + * *NOT* revise this as we go along. So subsequent I/O operations must + * use count-offset to get the number of active vector pieces still + * remaining. + */ + int count; + + /* + * Total number of bytes accounted for in all the pieces of this + * message. We do *NOT* revise this as we go along. + */ + size_t total_bytes; + +#define MIN_IOVEC 3 + db_iovec_t vectors[MIN_IOVEC]; /* Variable length array. */ +} REPMGR_IOVECS; + +typedef struct { + size_t length; /* number of bytes in data */ + int ref_count; /* # of sites' send queues pointing to us */ + u_int8_t data[1]; /* variable size data area */ +} REPMGR_FLAT; + +struct __queued_output { + STAILQ_ENTRY(__queued_output) entries; + REPMGR_FLAT *msg; + size_t offset; +}; + +/* + * The following is for input. Once we know the sizes of the pieces of an + * incoming message, we can create this struct (and also the data areas for the + * pieces themselves, in the same memory allocation). This is also the struct + * in which the message lives while it's waiting to be processed by message + * threads. + */ +typedef struct __repmgr_message { + STAILQ_ENTRY(__repmgr_message) entries; + __repmgr_msg_hdr_args msg_hdr; + union { + struct { + int originating_eid; + DBT control, rec; + } repmsg; + struct { + REPMGR_CONNECTION *conn; + DBT request; + } gmdb_msg; + struct { + /* + * Connection from which the message arrived; NULL if + * generated on the local site. + */ + REPMGR_CONNECTION *conn; + + DBT buf; /* for reading */ + DBT segments[1]; /* expanded in msg th. before callbk */ + } appmsg; + } v; /* Variants */ +} REPMGR_MESSAGE; + +typedef enum { + SIZES_PHASE, + DATA_PHASE +} phase_t; + +typedef enum { + APP_CONNECTION, + REP_CONNECTION, + UNKNOWN_CONN_TYPE +} conn_type_t; + +struct __repmgr_connection { + TAILQ_ENTRY(__repmgr_connection) entries; + + socket_t fd; +#ifdef DB_WIN32 + WSAEVENT event_object; +#endif + + /* + * Number of other structures referring to this conn struct. This + * ref_count must be reduced to zero before this conn struct can be + * destroyed. Referents include: + * + * - the select() loop, which owns the right to do all reading, as well + * as the exclusive right to eventually close the socket + * + * - a "channel" that owns this APP_CONNECTION (on the originating side) + * + * - a message received on this APP_CONNECTION, queued for processing + * + * - any writer blocked on waiting for the outbound queue to drain + */ + u_int32_t ref_count; + + conn_type_t type; + u_int32_t version; /* Wire protocol version on this connection. */ + /* (0 means not yet determined.) */ + +/* + * When we make an outgoing connection, it starts in CONNECTED state. When we + * get the response to our version negotiation, we move to READY. + * For incoming connections that we accept, we start in NEGOTIATE, then to + * PARAMETERS, and then to READY. + * CONGESTED is a hierarchical substate of READY: it's just like READY, with + * the additional wrinkle that we don't bother waiting for the outgoing queue to + * drain in certain circumstances. + */ +#define CONN_CONGESTED 1 /* Long-lived full outgoing queue. */ +#define CONN_CONNECTED 2 /* Awaiting reply to our version negotiation. */ +#define CONN_DEFUNCT 3 /* Basically dead, awaiting clean-up. */ +#define CONN_NEGOTIATE 4 /* Awaiting version proposal. */ +#define CONN_PARAMETERS 5 /* Awaiting parameters handshake. */ +#define CONN_READY 6 /* Everything's fine. */ + int state; + + /* + * Input: while we're reading a message, we keep track of what phase + * we're in. In both phases, we use a REPMGR_IOVECS to keep track of + * our progress within the phase. Depending upon the message type, we + * end up with either a rep_message (which is a wrapper for the control + * and rec DBTs), or a single generic DBT. + * Any time we're in DATA_PHASE, it means we have already received + * the message header (consisting of msg_type and 2 sizes), and + * therefore we have allocated buffer space to read the data. (This is + * important for resource clean-up.) + */ + phase_t reading_phase; + REPMGR_IOVECS iovecs; + + u_int8_t msg_type; + u_int8_t msg_hdr_buf[__REPMGR_MSG_HDR_SIZE]; + + union { + REPMGR_MESSAGE *rep_message; + struct { + DBT cntrl, rec; + } repmgr_msg; + } input; + + /* + * Output: usually we just simply write messages right in line, in the + * send() function's thread. But if TCP doesn't have enough network + * buffer space for us when we first try it, we instead allocate some + * memory, and copy the message, and then send it as space becomes + * available in our main select() thread. In some cases, if the queue + * gets too long we wait until it's drained, and then append to it. + * This condition variable's associated mutex is the normal per-repmgr + * db_rep->mutex, because that mutex is always held anyway whenever the + * output queue is consulted. + */ + OUT_Q_HEADER outbound_queue; + int out_queue_length; + cond_var_t drained; + + /* =-=-=-=-= app-channel stuff =-=-=-=-= */ + waiter_t response_waiters; + + /* + * Array of info about pending responses to requests. This info is here + * (rather than on the stack of the thread calling send_request()) + * because it provides an easy way to allocate available numbers for + * message tags, and also so that we can easily find the right info when + * we get the tag back in the msg header of the response. + */ + REPMGR_RESPONSE *responses; + u_int32_t aresp; /* Array size. */ + u_int32_t cur_resp; /* Index of response currently reading. */ + + /* =-=-=-=-= for normal repmgr connections =-=-=-=-= */ + /* + * Generally on a REP_CONNECTION type, we have an associated EID (which + * is an index into the sites array, by the way). When we initiate the + * connection ("outgoing"), we know from the start what the EID is; the + * connection struct is linked from the site struct. On the other hand, + * when we receive an incoming connection, we don't know at first what + * site it may be associated with (or even whether it's an + * APP_CONNECTION or REP_CONNECTION, for that matter). During that + * initial uncertain time, the eid is -1. Also, when a connection + * becomes defunct, but the conn struct hasn't yet been destroyed, the + * eid also becomes -1. + * + * The eid should be -1 if and only if the connection is on the orphans + * list. + */ + int eid; + +}; + +#define IS_READY_STATE(s) ((s) == CONN_READY || (s) == CONN_CONGESTED) + +#ifdef HAVE_GETADDRINFO +typedef struct addrinfo ADDRINFO; +typedef struct sockaddr_storage ACCEPT_ADDR; +#else +typedef struct sockaddr_in ACCEPT_ADDR; +/* + * Some windows platforms have getaddrinfo (Windows XP), some don't. We don't + * support conditional compilation in our Windows build, so we always use our + * own getaddrinfo implementation. Rename everything so that we don't collide + * with the system libraries. + */ +#undef AI_PASSIVE +#define AI_PASSIVE 0x01 +#undef AI_CANONNAME +#define AI_CANONNAME 0x02 +#undef AI_NUMERICHOST +#define AI_NUMERICHOST 0x04 + +typedef struct __addrinfo { + int ai_flags; /* AI_PASSIVE, AI_CANONNAME, AI_NUMERICHOST */ + int ai_family; /* PF_xxx */ + int ai_socktype; /* SOCK_xxx */ + int ai_protocol; /* 0 or IPPROTO_xxx for IPv4 and IPv6 */ + size_t ai_addrlen; /* length of ai_addr */ + char *ai_canonname; /* canonical name for nodename */ + struct sockaddr *ai_addr; /* binary address */ + struct __addrinfo *ai_next; /* next structure in linked list */ +} ADDRINFO; +#endif /* HAVE_GETADDRINFO */ + +/* + * Unprocessed network address configuration. + */ +typedef struct { + roff_t host; /* Separately allocated copy of string. */ + u_int16_t port; /* Stored in plain old host-byte-order. */ +} SITEADDR; + +/* + * Site information, as stored in shared region. + */ +typedef struct { + SITEADDR addr; /* Unprocessed network address of site. */ + u_int32_t config; /* Configuration flags: peer, helper, etc. */ + u_int32_t status; /* Group membership status. */ +} SITEINFO; + +/* + * A site address, as stored locally. + */ +typedef struct { + char *host; /* Separately allocated copy of string. */ + u_int16_t port; /* Stored in plain old host-byte-order. */ +} repmgr_netaddr_t; + +/* + * We store site structs in a dynamically allocated, growable array, indexed by + * EID. We allocate EID numbers for all sites simply according to their + * index within this array. + */ +#define SITE_FROM_EID(eid) (&db_rep->sites[eid]) +#define EID_FROM_SITE(s) ((int)((s) - (&db_rep->sites[0]))) +#define IS_VALID_EID(e) ((e) >= 0) +#define IS_KNOWN_REMOTE_SITE(e) ((e) >= 0 && ((e) != db_rep->self_eid) && \ + (((u_int)(e)) < db_rep->site_cnt)) +#define FOR_EACH_REMOTE_SITE_INDEX(i) \ + for ((i) = (db_rep->self_eid == 0 ? 1 : 0); \ + ((u_int)i) < db_rep->site_cnt; \ + (int)(++(i)) == db_rep->self_eid ? ++(i) : i) + +struct __repmgr_site { + repmgr_netaddr_t net_addr; + + /* + * Group membership status: a copy of the status from the membership + * database, or the out-of-band value 0, meaning that it doesn't exist. + * We keep track of a "non-existent" site because the associated + * host/port network address is promised to be associated with the + * locally known EID for the life of the environment. + */ + u_int32_t membership; /* Status flags from GMDB. */ + u_int32_t config; /* Flags from site->set_config() */ + + /* + * Everything below here is applicable only to remote sites. + */ + DB_LSN max_ack; /* Best ack we've heard from this site. */ + int ack_policy; /* Or 0 if unknown. */ + u_int16_t alignment; /* Requirements for app channel msgs. */ + db_timespec last_rcvd_timestamp; + + /* Contents depends on state. */ + struct { + struct { /* when CONNECTED */ + /* + * The only time we ever have two connections is in case + * of a "collision" on the "server" side. In that case, + * the incoming connection either will be closed + * promptly by the remote "client", or it is a half-open + * connection due to the remote client system having + * crashed and rebooted, in which case KEEPALIVE will + * eventually clear it. + */ + REPMGR_CONNECTION *in; /* incoming connection */ + REPMGR_CONNECTION *out; /* outgoing connection */ + } conn; + REPMGR_RETRY *retry; /* when PAUSING */ + /* Unused when CONNECTING. */ + } ref; + + /* + * Subordinate connections (connections from subordinate processes at a + * multi-process site). Note that the SITE_CONNECTED state, and all the + * ref.retry stuff above is irrelevant to subordinate connections. If a + * connection is on this list, it exists; and we never bother trying to + * reconnect lost connections (indeed we can't, for these are always + * incoming-only). + */ + CONNECTION_LIST sub_conns; + REPMGR_RUNNABLE *connector; /* Thread to open a connection. */ + +#define SITE_CONNECTED 1 /* We have a (main) connection. */ +#define SITE_CONNECTING 2 /* Trying to establish (main) connection. */ +#define SITE_IDLE 3 /* Doing nothing. */ +#define SITE_PAUSING 4 /* Waiting til time to retry connecting. */ + int state; + +#define SITE_HAS_PRIO 0x01 /* Set if "electable" flag bit is valid. */ +#define SITE_ELECTABLE 0x02 +#define SITE_TOUCHED 0x04 /* Seen GMDB record during present scan. */ + u_int32_t flags; +}; + +/* + * Flag values for the public DB_SITE handle. + */ +#define DB_SITE_PREOPEN 0x01 /* Provisional EID; may change at env open. */ + +struct __repmgr_response { + DBT dbt; + int ret; + +#define RESP_COMPLETE 0x01 +#define RESP_DUMMY_BUF 0x02 +#define RESP_IN_USE 0x04 +#define RESP_READING 0x08 +#define RESP_THREAD_WAITING 0x10 + u_int32_t flags; +}; + +/* + * Private structure for managing comms "channels." This is separate from + * DB_CHANNEL so as to avoid dragging in other private structures (e.g., + * REPMGR_CONNECTION) into db.h, similar to the relationship between DB_ENV and + * ENV. + */ +struct __channel { + DB_CHANNEL *db_channel; + ENV *env; + + union { + /* For simple, specific-EID channels. */ + REPMGR_CONNECTION *conn; + + /* For EID_MASTER or EID_BROADCAST channels. */ + struct { + mgr_mutex_t *mutex; /* For connection establishment. */ + REPMGR_CONNECTION **array; + u_int32_t cnt; + } conns; + } c; + REPMGR_MESSAGE *msg; /* Incoming channel only; NULL otherwise. */ + int responded; /* Boolean flag. */ + __repmgr_msg_metadata_args *meta; + + /* Used only in send-to-self request case. */ + struct __repmgr_response response; +}; + +/* + * Repmgr keeps track of references to connection information (instances + * of struct __repmgr_connection). There are three kinds of places + * connections may be found: (1) SITE->ref.conn, (2) SITE->sub_conns, and + * (3) db_rep->connections. + * + * 1. SITE->ref.conn points to our connection with the main process running + * at the given site, if such a connection exists. We may have initiated + * the connection to the site ourselves, or we may have received it as an + * incoming connection. Once it is established there is very little + * difference between those two cases. + * + * 2. SITE->sub_conns is a list of connections we have with subordinate + * processes running at the given site. There can be any number of these + * connections, one per subordinate process. Note that these connections + * are always incoming: there's no way for us to initiate this kind of + * connection because subordinate processes do not "listen". + * + * 3. The db_rep->connections list contains the references to any + * connections that are not actively associated with any site (we + * sometimes call these "orphans"). There are two times when this can + * be: + * + * a) When we accept an incoming connection, we don't know what site it + * comes from until we read the initial handshake message. + * + * b) When an error occurs on a connection, we first mark it as DEFUNCT + * and stop using it. Then, at a later, well-defined time, we close + * the connection's file descriptor and get rid of the connection + * struct. + * + * In light of the above, we can see that the following describes the + * rules for how connections may be moved among these three kinds of + * "places": + * + * - when we initiate an outgoing connection, we of course know what site + * it's going to be going to, and so we immediately put the pointer to + * the connection struct into SITE->ref.conn + * + * - when we accept an incoming connection, we don't immediately know + * whom it's from, so we have to put it on the orphans list + * (db_rep->connections). + * + * - (incoming, cont.) But as soon as we complete the initial "handshake" + * message exchange, we will know which site it's from and whether it's + * a subordinate or main connection. At that point we remove it from + * db_rep->connections and either point to it by SITE->ref.conn, or add + * it to the SITE->sub_conns list. + * + * - (for any active connection) when an error occurs, we move the + * connection to the orphans list until we have a chance to close it. + */ + +/* + * Repmgr message formats. + * + * Declarative definitions of current message formats appear in repmgr.msg. + * (The s_message/gen_msg.awk utility generates C code.) In general, we send + * the buffers marshaled from those structure formats in the "control" portion + * of a message. + * + * Each message is prefaced by a 9-byte message header (as described in + * repmgr_net.c). Different message types use the two available 32-bit integers + * in different ways, as codified here: + */ +#define REPMGR_HDR1(hdr) ((hdr).word1) +#define REPMGR_HDR2(hdr) ((hdr).word2) + +/* REPMGR_APP_MESSAGE */ +#define APP_MSG_BUFFER_SIZE REPMGR_HDR1 +#define APP_MSG_SEGMENT_COUNT REPMGR_HDR2 + +/* REPMGR_REP_MESSAGE and the other traditional repmgr message types. */ +#define REP_MSG_CONTROL_SIZE REPMGR_HDR1 +#define REP_MSG_REC_SIZE REPMGR_HDR2 + +/* REPMGR_APP_RESPONSE */ +#define APP_RESP_BUFFER_SIZE REPMGR_HDR1 +#define APP_RESP_TAG REPMGR_HDR2 + +/* REPMGR_RESP_ERROR. Note that a zero-length message body is implied. */ +#define RESP_ERROR_CODE REPMGR_HDR1 +#define RESP_ERROR_TAG REPMGR_HDR2 + +/* REPMGR_OWN_MSG */ +#define REPMGR_OWN_BUF_SIZE REPMGR_HDR1 +#define REPMGR_OWN_MSG_TYPE REPMGR_HDR2 + +/* + * Flags for the handshake message. As with repmgr message types, these values + * are transmitted between sites, and must therefore be "frozen" permanently. + * Names are alphabetized here for easy reference, but values reflect historical + * usage. + */ +#define APP_CHANNEL_CONNECTION 0x02 /* Connection used for app channel. */ +#define ELECTABLE_SITE 0x04 +#define REPMGR_SUBORDINATE 0x01 /* This is a subordinate connection. */ + +/* + * Flags for application-message meta-data. + */ +#define REPMGR_MULTI_RESP 0x01 +#define REPMGR_REQUEST_MSG_TYPE 0x02 +#define REPMGR_RESPONSE_LIMIT 0x04 + +/* + * Legacy V1 handshake message format. For compatibility, we send this as part + * of version negotiation upon connection establishment. + */ +typedef struct { + u_int32_t version; + u_int16_t port; + u_int32_t priority; +} DB_REPMGR_V1_HANDSHAKE; + +/* + * Storage formats. + * + * As with message formats, stored formats are defined in repmgr.msg. + */ +/* + * Flags for the Group Membership data portion of a record. Like message type + * codes, these values are frozen across releases, in order to avoid pointless + * churn. + */ +#define SITE_ADDING 0x01 +#define SITE_DELETING 0x02 +#define SITE_PRESENT 0x04 + +/* + * Message types whose processing could take a long time. We're careful to + * avoid using up all our message processing threads on these message types, so + * that we don't starve out the more important rep messages. + */ +#define IS_DEFERRABLE(t) ((t) == REPMGR_OWN_MSG || (t) == REPMGR_APP_MESSAGE) +/* + * When using leases there are times when a thread processing a message + * must block, waiting for leases to be refreshed. But refreshing the + * leases requires another thread to accept the lease grant messages. + */ +#define RESERVED_MSG_TH(env) (IS_USING_LEASES(env) ? 2 : 1) + +#define IS_SUBORDINATE(db_rep) (db_rep->listen_fd == INVALID_SOCKET) + +#define IS_PEER_POLICY(p) ((p) == DB_REPMGR_ACKS_ALL_PEERS || \ + (p) == DB_REPMGR_ACKS_QUORUM || \ + (p) == DB_REPMGR_ACKS_ONE_PEER) + +/* + * Most of the code in repmgr runs while holding repmgr's main mutex, which + * resides in db_rep->mutex. This mutex is owned by a single repmgr process, + * and serializes access to the (large) critical sections among threads in the + * process. Unlike many other mutexes in DB, it is specifically coded as either + * a POSIX threads mutex or a Win32 mutex. Note that although it's a large + * fraction of the code, it's a tiny fraction of the time: repmgr spends most of + * its time in a call to select(), and as well a bit in calls into the Base + * replication API. All of those release the mutex. + * Access to repmgr's shared list of site addresses is protected by + * another mutex: mtx_repmgr. And, when changing space allocation for that site + * list we conform to the convention of acquiring renv->mtx_regenv. These are + * less frequent of course. + * When it's necessary to acquire more than one of these mutexes, the + * ordering priority (or "lock ordering protocol") is: + * db_rep->mutex (first) + * mtx_repmgr (briefly) + * mtx_regenv (last, and most briefly) + * + * There are also mutexes for app message "channels". Each channel has a mutex, + * which is used to serialize any connection re-establishment that may become + * necessary during its lifetime (such as when a master changes). This never + * happens on a simple, specific-EID channel, but in other cases multiple app + * threads could be making send_xxx() calls concurrently, and it would not do to + * have two of them try to re-connect concurrently. + * When re-establishing a connection, the channel lock is held while + * grabbing first the mtx_repmgr, and then the db_rep mutex (but not both + * together). I.e., we have: + * channel->mutex (first) + * [mtx_repmgr (very briefly)] and then [db_rep->mutex (very briefly)] + */ + +#define LOCK_MUTEX(m) do { \ + if (__repmgr_lock_mutex(m) != 0) \ + return (DB_RUNRECOVERY); \ +} while (0) + +#define UNLOCK_MUTEX(m) do { \ + if (__repmgr_unlock_mutex(m) != 0) \ + return (DB_RUNRECOVERY); \ +} while (0) + +/* POSIX/Win32 socket (and other) portability. */ +#ifdef DB_WIN32 +#define WOULDBLOCK WSAEWOULDBLOCK +#undef DB_REPMGR_EAGAIN + +#define net_errno WSAGetLastError() +typedef int socklen_t; +typedef char * sockopt_t; +#define sendsocket(s, buf, len, flags) send((s), (buf), (int)(len), (flags)) + +#define iov_len len +#define iov_base buf + +typedef DWORD threadsync_timeout_t; + +#define REPMGR_INITED(db_rep) (db_rep->signaler != NULL) +#else + +#define INVALID_SOCKET -1 +#define SOCKET_ERROR -1 +#define WOULDBLOCK EWOULDBLOCK +#define DB_REPMGR_EAGAIN EAGAIN + +#define net_errno errno +typedef void * sockopt_t; + +#define sendsocket(s, buf, len, flags) send((s), (buf), (len), (flags)) +#define closesocket(fd) close(fd) + +typedef struct timespec threadsync_timeout_t; + +#define REPMGR_INITED(db_rep) (db_rep->read_pipe >= 0) +#endif + +#define SELECTOR_RUNNING(db_rep) ((db_rep)->selector != NULL) + +/* + * Generic definition of some action to be performed on each connection, in the + * form of a call-back function. + */ +typedef int (*CONNECTION_ACTION) __P((ENV *, REPMGR_CONNECTION *, void *)); + +/* + * Generic predicate to test a condition that a thread is waiting for. + */ +typedef int (*PREDICATE) __P((ENV *, void *)); + +#include "dbinc_auto/repmgr_ext.h" + +#if defined(__cplusplus) +} +#endif +#endif /* !_DB_REPMGR_H_ */ diff -r 000000000000 -r a1985f14b030 src/dbinc/shqueue.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/dbinc/shqueue.h Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,432 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 1996, 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + * $Id$ + */ + +#ifndef _DB_SHQUEUE_H_ +#define _DB_SHQUEUE_H_ + +/* + * This file defines three types of data structures: chains, lists and + * tail queues similarly to the include file . + * + * The difference is that this set of macros can be used for structures that + * reside in shared memory that may be mapped at different addresses in each + * process. In most cases, the macros for shared structures exactly mirror + * the normal macros, although the macro calls require an additional type + * parameter, only used by the HEAD and ENTRY macros of the standard macros. + * + * Since we use relative offsets of type ssize_t rather than pointers, 0 + * (aka NULL) is a valid offset and cannot be used to indicate the end + * of a list. Therefore, we use -1 to indicate end of list. + * + * The macros ending in "P" return pointers without checking for end or + * beginning of lists, the others check for end of list and evaluate to + * either a pointer or NULL. + * + * For details on the use of these macros, see the queue(3) manual page. + */ + +#if defined(__cplusplus) +extern "C" { +#endif + +#define SH_PTR_TO_OFF(src, dest) \ + ((db_ssize_t)(((u_int8_t *)(dest)) - ((u_int8_t *)(src)))) + +#define SH_OFF_TO_PTR(base, off, type) \ + ((type *) (((u_int8_t *)(base)) + (db_ssize_t) (off))) + + +/* + * Shared memory chain definitions. + */ +#define SH_CHAIN_ENTRY \ +struct { \ + db_ssize_t sce_next; /* relative offset to next element */ \ + db_ssize_t sce_prev; /* relative offset of prev element */ \ +} + +#define SH_CHAIN_INIT(elm, field) \ + (elm)->field.sce_next = (elm)->field.sce_prev = -1 + +#define SH_CHAIN_HASNEXT(elm, field) ((elm)->field.sce_next != -1) +#define SH_CHAIN_NEXTP(elm, field, type) \ + ((struct type *)((u_int8_t *)(elm) + (elm)->field.sce_next)) +#define SH_CHAIN_NEXT(elm, field, type) (SH_CHAIN_HASNEXT(elm, field) ? \ + SH_CHAIN_NEXTP(elm, field, type) : (struct type *)NULL) + +#define SH_CHAIN_HASPREV(elm, field) ((elm)->field.sce_prev != -1) +#define SH_CHAIN_PREVP(elm, field, type) \ + ((struct type *)((u_int8_t *)(elm) + (elm)->field.sce_prev)) +#define SH_CHAIN_PREV(elm, field, type) (SH_CHAIN_HASPREV(elm, field) ? \ + SH_CHAIN_PREVP(elm, field, type) : (struct type *)NULL) + +#define SH_CHAIN_SINGLETON(elm, field) \ + (!(SH_CHAIN_HASNEXT(elm, field) || SH_CHAIN_HASPREV(elm, field))) + +#define SH_CHAIN_INSERT_AFTER(listelm, elm, field, type) do { \ + struct type *__next = SH_CHAIN_NEXT(listelm, field, type); \ + if (__next != NULL) { \ + (elm)->field.sce_next = SH_PTR_TO_OFF(elm, __next); \ + __next->field.sce_prev = SH_PTR_TO_OFF(__next, elm); \ + } else \ + (elm)->field.sce_next = -1; \ + (elm)->field.sce_prev = SH_PTR_TO_OFF(elm, listelm); \ + (listelm)->field.sce_next = SH_PTR_TO_OFF(listelm, elm); \ +} while (0) + +#define SH_CHAIN_INSERT_BEFORE(listelm, elm, field, type) do { \ + struct type *__prev = SH_CHAIN_PREV(listelm, field, type); \ + if (__prev != NULL) { \ + (elm)->field.sce_prev = SH_PTR_TO_OFF(elm, __prev); \ + __prev->field.sce_next = SH_PTR_TO_OFF(__prev, elm); \ + } else \ + (elm)->field.sce_prev = -1; \ + (elm)->field.sce_next = SH_PTR_TO_OFF(elm, listelm); \ + (listelm)->field.sce_prev = SH_PTR_TO_OFF(listelm, elm); \ +} while (0) + +#define SH_CHAIN_REMOVE(elm, field, type) do { \ + struct type *__prev = SH_CHAIN_PREV(elm, field, type); \ + struct type *__next = SH_CHAIN_NEXT(elm, field, type); \ + if (__next != NULL) \ + __next->field.sce_prev = (__prev == NULL) ? -1 : \ + SH_PTR_TO_OFF(__next, __prev); \ + if (__prev != NULL) \ + __prev->field.sce_next = (__next == NULL) ? -1 : \ + SH_PTR_TO_OFF(__prev, __next); \ + SH_CHAIN_INIT(elm, field); \ +} while (0) + +/* + * Shared memory list definitions. + */ +#define SH_LIST_HEAD(name) \ +struct name { \ + db_ssize_t slh_first; /* first element */ \ +} + +#define SH_LIST_HEAD_INITIALIZER(head) \ + { -1 } + +#define SH_LIST_ENTRY \ +struct { \ + db_ssize_t sle_next; /* relative offset to next element */ \ + db_ssize_t sle_prev; /* relative offset of prev element */ \ +} + +/* + * Shared memory list functions. + */ +#define SH_LIST_EMPTY(head) \ + ((head)->slh_first == -1) + +#define SH_LIST_FIRSTP(head, type) \ + ((struct type *)(((u_int8_t *)(head)) + (head)->slh_first)) + +#define SH_LIST_FIRST(head, type) \ + (SH_LIST_EMPTY(head) ? NULL : \ + ((struct type *)(((u_int8_t *)(head)) + (head)->slh_first))) + +#define SH_LIST_NEXTP(elm, field, type) \ + ((struct type *)(((u_int8_t *)(elm)) + (elm)->field.sle_next)) + +#define SH_LIST_NEXT(elm, field, type) \ + ((elm)->field.sle_next == -1 ? NULL : \ + ((struct type *)(((u_int8_t *)(elm)) + (elm)->field.sle_next))) + + /* + *__SH_LIST_PREV_OFF is private API. It calculates the address of + * the elm->field.sle_next member of a SH_LIST structure. All offsets + * between elements are relative to that point in SH_LIST structures. + */ +#define __SH_LIST_PREV_OFF(elm, field) \ + ((db_ssize_t *)(((u_int8_t *)(elm)) + (elm)->field.sle_prev)) + +#define SH_LIST_PREV(elm, field, type) \ + (struct type *)((db_ssize_t)(elm) - (*__SH_LIST_PREV_OFF(elm, field))) + +#define SH_LIST_FOREACH(var, head, field, type) \ + for ((var) = SH_LIST_FIRST((head), type); \ + (var) != NULL; \ + (var) = SH_LIST_NEXT((var), field, type)) + +/* + * Given correct A.next: B.prev = SH_LIST_NEXT_TO_PREV(A) + * in a list [A, B] + * The prev value is always the offset from an element to its preceding + * element's next location, not the beginning of the structure. To get + * to the beginning of an element structure in memory given an element + * do the following: + * A = B - (B.prev + (&B.next - B)) + * Take the element's next pointer and calculate what the corresponding + * Prev pointer should be -- basically it is the negation plus the offset + * of the next field in the structure. + */ +#define SH_LIST_NEXT_TO_PREV(elm, field) \ + (((elm)->field.sle_next == -1 ? 0 : -(elm)->field.sle_next) + \ + SH_PTR_TO_OFF(elm, &(elm)->field.sle_next)) + +#define SH_LIST_INIT(head) (head)->slh_first = -1 + +#define SH_LIST_INSERT_BEFORE(head, listelm, elm, field, type) do { \ + if (listelm == SH_LIST_FIRST(head, type)) { \ + SH_LIST_INSERT_HEAD(head, elm, field, type); \ + } else { \ + (elm)->field.sle_next = SH_PTR_TO_OFF(elm, listelm); \ + (elm)->field.sle_prev = SH_LIST_NEXT_TO_PREV( \ + SH_LIST_PREV((listelm), field, type), field) + \ + (elm)->field.sle_next; \ + (SH_LIST_PREV(listelm, field, type))->field.sle_next = \ + (SH_PTR_TO_OFF((SH_LIST_PREV(listelm, field, \ + type)), elm)); \ + (listelm)->field.sle_prev = SH_LIST_NEXT_TO_PREV(elm, field); \ + } \ +} while (0) + +#define SH_LIST_INSERT_AFTER(listelm, elm, field, type) do { \ + if ((listelm)->field.sle_next != -1) { \ + (elm)->field.sle_next = SH_PTR_TO_OFF(elm, \ + SH_LIST_NEXTP(listelm, field, type)); \ + SH_LIST_NEXTP(listelm, field, type)->field.sle_prev = \ + SH_LIST_NEXT_TO_PREV(elm, field); \ + } else \ + (elm)->field.sle_next = -1; \ + (listelm)->field.sle_next = SH_PTR_TO_OFF(listelm, elm); \ + (elm)->field.sle_prev = SH_LIST_NEXT_TO_PREV(listelm, field); \ +} while (0) + +#define SH_LIST_INSERT_HEAD(head, elm, field, type) do { \ + if ((head)->slh_first != -1) { \ + (elm)->field.sle_next = \ + (head)->slh_first - SH_PTR_TO_OFF(head, elm); \ + SH_LIST_FIRSTP(head, type)->field.sle_prev = \ + SH_LIST_NEXT_TO_PREV(elm, field); \ + } else \ + (elm)->field.sle_next = -1; \ + (head)->slh_first = SH_PTR_TO_OFF(head, elm); \ + (elm)->field.sle_prev = SH_PTR_TO_OFF(elm, &(head)->slh_first); \ +} while (0) + +#define SH_LIST_REMOVE(elm, field, type) do { \ + if ((elm)->field.sle_next != -1) { \ + SH_LIST_NEXTP(elm, field, type)->field.sle_prev = \ + (elm)->field.sle_prev - (elm)->field.sle_next; \ + *__SH_LIST_PREV_OFF(elm, field) += (elm)->field.sle_next;\ + } else \ + *__SH_LIST_PREV_OFF(elm, field) = -1; \ +} while (0) + +#define SH_LIST_REMOVE_HEAD(head, field, type) do { \ + if (!SH_LIST_EMPTY(head)) { \ + SH_LIST_REMOVE(SH_LIST_FIRSTP(head, type), field, type);\ + } \ +} while (0) + +/* + * Shared memory tail queue definitions. + */ +#define SH_TAILQ_HEAD(name) \ +struct name { \ + db_ssize_t stqh_first; /* relative offset of first element */ \ + db_ssize_t stqh_last; /* relative offset of last's next */ \ +} + +#define SH_TAILQ_HEAD_INITIALIZER(head) \ + { -1, 0 } + +#define SH_TAILQ_ENTRY \ +struct { \ + db_ssize_t stqe_next; /* relative offset of next element */ \ + db_ssize_t stqe_prev; /* relative offset of prev's next */ \ +} + +/* + * Shared memory tail queue functions. + */ + +#define SH_TAILQ_EMPTY(head) \ + ((head)->stqh_first == -1) + +#define SH_TAILQ_FIRSTP(head, type) \ + ((struct type *)((u_int8_t *)(head) + (head)->stqh_first)) + +#define SH_TAILQ_FIRST(head, type) \ + (SH_TAILQ_EMPTY(head) ? NULL : SH_TAILQ_FIRSTP(head, type)) + +#define SH_TAILQ_NEXTP(elm, field, type) \ + ((struct type *)((u_int8_t *)(elm) + (elm)->field.stqe_next)) + +#define SH_TAILQ_NEXT(elm, field, type) \ + ((elm)->field.stqe_next == -1 ? NULL : \ + ((struct type *)((u_int8_t *)(elm) + (elm)->field.stqe_next))) + + /* + * __SH_TAILQ_PREV_OFF is private API. It calculates the address of + * the elm->field.stqe_next member of a SH_TAILQ structure. All + * offsets between elements are relative to that point in SH_TAILQ + * structures. + */ +#define __SH_TAILQ_PREV_OFF(elm, field) \ + ((db_ssize_t *)(((u_int8_t *)(elm)) + (elm)->field.stqe_prev)) + +#define SH_TAILQ_PREVP(elm, field, type) \ + (struct type *)((db_ssize_t)elm - (*__SH_TAILQ_PREV_OFF(elm, field))) + +#define SH_TAILQ_PREV(head, elm, field, type) \ + (((elm) == SH_TAILQ_FIRST(head, type)) ? NULL : \ + (struct type *)((db_ssize_t)elm - (*__SH_TAILQ_PREV_OFF(elm, field)))) + + /* + * __SH_TAILQ_LAST_OFF is private API. It calculates the address of + * the stqe_next member of a SH_TAILQ structure in the last element + * of this list. All offsets between elements are relative to that + * point in SH_TAILQ structures. + */ +#define __SH_TAILQ_LAST_OFF(head) \ + ((db_ssize_t *)(((u_int8_t *)(head)) + (head)->stqh_last)) + +#define SH_TAILQ_LASTP(head, field, type) \ + ((struct type *)((db_ssize_t)(head) + \ + ((db_ssize_t)((head)->stqh_last) - \ + ((db_ssize_t)SH_PTR_TO_OFF(SH_TAILQ_FIRST(head, type), \ + &(SH_TAILQ_FIRSTP(head, type)->field.stqe_next)))))) + +#define SH_TAILQ_LAST(head, field, type) \ + (SH_TAILQ_EMPTY(head) ? NULL : SH_TAILQ_LASTP(head, field, type)) + +/* + * Given correct A.next: B.prev = SH_TAILQ_NEXT_TO_PREV(A) + * in a list [A, B] + * The prev value is always the offset from an element to its preceding + * element's next location, not the beginning of the structure. To get + * to the beginning of an element structure in memory given an element + * do the following: + * A = B - (B.prev + (&B.next - B)) + */ +#define SH_TAILQ_NEXT_TO_PREV(elm, field) \ + (((elm)->field.stqe_next == -1 ? 0 : \ + (-(elm)->field.stqe_next) + \ + SH_PTR_TO_OFF(elm, &(elm)->field.stqe_next))) + +#define SH_TAILQ_FOREACH(var, head, field, type) \ + for ((var) = SH_TAILQ_FIRST((head), type); \ + (var) != NULL; \ + (var) = SH_TAILQ_NEXT((var), field, type)) + +#define SH_TAILQ_FOREACH_REVERSE(var, head, field, type) \ + for ((var) = SH_TAILQ_LAST((head), field, type); \ + (var) != NULL; \ + (var) = SH_TAILQ_PREV((head), (var), field, type)) + +#define SH_TAILQ_INIT(head) { \ + (head)->stqh_first = -1; \ + (head)->stqh_last = SH_PTR_TO_OFF(head, &(head)->stqh_first); \ +} + +#define SH_TAILQ_INSERT_HEAD(head, elm, field, type) do { \ + if ((head)->stqh_first != -1) { \ + (elm)->field.stqe_next = \ + (head)->stqh_first - SH_PTR_TO_OFF(head, elm); \ + SH_TAILQ_FIRSTP(head, type)->field.stqe_prev = \ + SH_TAILQ_NEXT_TO_PREV(elm, field); \ + } else { \ + (head)->stqh_last = \ + SH_PTR_TO_OFF(head, &(elm)->field.stqe_next); \ + (elm)->field.stqe_next = -1; \ + } \ + (head)->stqh_first = SH_PTR_TO_OFF(head, elm); \ + (elm)->field.stqe_prev = \ + SH_PTR_TO_OFF(elm, &(head)->stqh_first); \ +} while (0) + +#define SH_TAILQ_INSERT_TAIL(head, elm, field) do { \ + (elm)->field.stqe_next = -1; \ + (elm)->field.stqe_prev = \ + -SH_PTR_TO_OFF(head, elm) + (head)->stqh_last; \ + if ((head)->stqh_last == \ + SH_PTR_TO_OFF((head), &(head)->stqh_first)) \ + (head)->stqh_first = SH_PTR_TO_OFF(head, elm); \ + else \ + *__SH_TAILQ_LAST_OFF(head) = -(head)->stqh_last + \ + SH_PTR_TO_OFF((elm), &(elm)->field.stqe_next) + \ + SH_PTR_TO_OFF(head, elm); \ + (head)->stqh_last = \ + SH_PTR_TO_OFF(head, &((elm)->field.stqe_next)); \ +} while (0) + +#define SH_TAILQ_INSERT_BEFORE(head, listelm, elm, field, type) do { \ + if (listelm == SH_TAILQ_FIRST(head, type)) { \ + SH_TAILQ_INSERT_HEAD(head, elm, field, type); \ + } else { \ + (elm)->field.stqe_next = SH_PTR_TO_OFF(elm, listelm); \ + (elm)->field.stqe_prev = SH_TAILQ_NEXT_TO_PREV( \ + SH_TAILQ_PREVP((listelm), field, type), field) + \ + (elm)->field.stqe_next; \ + (SH_TAILQ_PREVP(listelm, field, type))->field.stqe_next =\ + (SH_PTR_TO_OFF((SH_TAILQ_PREVP(listelm, field, type)), \ + elm)); \ + (listelm)->field.stqe_prev = \ + SH_TAILQ_NEXT_TO_PREV(elm, field); \ + } \ +} while (0) + +#define SH_TAILQ_INSERT_AFTER(head, listelm, elm, field, type) do { \ + if ((listelm)->field.stqe_next != -1) { \ + (elm)->field.stqe_next = (listelm)->field.stqe_next - \ + SH_PTR_TO_OFF(listelm, elm); \ + SH_TAILQ_NEXTP(listelm, field, type)->field.stqe_prev = \ + SH_TAILQ_NEXT_TO_PREV(elm, field); \ + } else { \ + (elm)->field.stqe_next = -1; \ + (head)->stqh_last = \ + SH_PTR_TO_OFF(head, &(elm)->field.stqe_next); \ + } \ + (listelm)->field.stqe_next = SH_PTR_TO_OFF(listelm, elm); \ + (elm)->field.stqe_prev = SH_TAILQ_NEXT_TO_PREV(listelm, field); \ +} while (0) + +#define SH_TAILQ_REMOVE(head, elm, field, type) do { \ + if ((elm)->field.stqe_next != -1) { \ + SH_TAILQ_NEXTP(elm, field, type)->field.stqe_prev = \ + (elm)->field.stqe_prev + \ + SH_PTR_TO_OFF(SH_TAILQ_NEXTP(elm, \ + field, type), elm); \ + *__SH_TAILQ_PREV_OFF(elm, field) += (elm)->field.stqe_next;\ + } else { \ + (head)->stqh_last = (elm)->field.stqe_prev + \ + SH_PTR_TO_OFF(head, elm); \ + *__SH_TAILQ_PREV_OFF(elm, field) = -1; \ + } \ +} while (0) + +#if defined(__cplusplus) +} +#endif +#endif /* !_DB_SHQUEUE_H_ */ diff -r 000000000000 -r a1985f14b030 src/dbinc/tcl_db.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/dbinc/tcl_db.h Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,338 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 1999, 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + * $Id$ + */ + +#ifndef _DB_TCL_DB_H_ +#define _DB_TCL_DB_H_ + +#if defined(__cplusplus) +extern "C" { +#endif + +#define MSG_SIZE 100 /* Message size */ + +enum INFOTYPE { + I_AUX, I_DB, I_DBC, I_ENV, I_LOCK, I_LOGC, I_MP, I_NDBM, I_PG, I_SEQ, I_TXN}; + +#define MAX_ID 8 /* Maximum number of sub-id's we need */ +#define DBTCL_PREP 64 /* Size of txn_recover preplist */ + +#define DBTCL_DBM 1 +#define DBTCL_NDBM 2 + +#define DBTCL_GETCLOCK 0 +#define DBTCL_GETLIMIT 1 +#define DBTCL_GETREQ 2 + +#define DBTCL_MUT_ALIGN 0 +#define DBTCL_MUT_INCR 1 +#define DBTCL_MUT_INIT 2 +#define DBTCL_MUT_MAX 3 +#define DBTCL_MUT_TAS 4 + +/* + * Data structure to record information about events that have occurred. Tcl + * command "env event_info" can retrieve the information. For now, we record + * only one occurrence per event type; "env event_info -clear" can be used to + * reset the info. + * + * Besides the bit flag that records the fact that an event type occurred, some + * event types have associated "info" and we record that here too. When new + * event types are invented that have associated info, we should add a field + * here to record that info as well, so that it can be returned to the script + * with the "env event_info" results. + */ +typedef struct dbtcl_event_info { + u_int32_t events; /* Bit flag on for each event fired. */ + int panic_error; + int newmaster_eid; + int added_eid; + int removed_eid; + pid_t attached_process; + int connected_eid; + DB_REPMGR_CONN_ERR conn_broken_info; + DB_REPMGR_CONN_ERR conn_failed_try_info; + DB_LSN sync_point; +} DBTCL_EVENT_INFO; + +/* + * Why use a home grown package over the Tcl_Hash functions? + * + * We could have implemented the stuff below without maintaining our + * own list manipulation, efficiently hashing it with the available + * Tcl functions (Tcl_CreateHashEntry, Tcl_GetHashValue, etc). I chose + * not to do so for these reasons: + * + * We still need the information below. Using the hashing only removes + * us from needing the next/prev pointers. We still need the structure + * itself because we need more than one value associated with a widget. + * We need to keep track of parent pointers for sub-widgets (like cursors) + * so we can correctly close. We need to keep track of individual widget's + * id counters for any sub-widgets they may have. We need to be able to + * associate the name/client data outside the scope of the widget. + * + * So, is it better to use the hashing rather than + * the linear list we have now? I decided against it for the simple reason + * that to access the structure would require two calls. The first is + * Tcl_FindHashEntry(table, key) and then, once we have the entry, we'd + * have to do Tcl_GetHashValue(entry) to get the pointer of the structure. + * + * I believe the number of simultaneous DB widgets in existence at one time + * is not going to be that large (more than several dozen) such that + * linearly searching the list is not going to impact performance in a + * noticeable way. Should performance be impacted due to the size of the + * info list, then perhaps it is time to revisit this decision. + */ +typedef struct dbtcl_info { + LIST_ENTRY(dbtcl_info) entries; + Tcl_Interp *i_interp; + char *i_name; + enum INFOTYPE i_type; + union infop { + DB *dbp; + DBC *dbcp; + DB_ENV *envp; + DB_LOCK *lock; + DB_LOGC *logc; + DB_MPOOLFILE *mp; + DB_TXN *txnp; + void *anyp; + } un; + union data { + int anydata; + db_pgno_t pgno; /* For I_MP. */ + u_int32_t lockid; /* For I_LOCK. */ + DBTCL_EVENT_INFO *event_info; /* For I_ENV. */ + DB_TXN_TOKEN *commit_token; /* For I_TXN. */ + } und; + union data2 { + int anydata; + int pagesz; /* For I_MP. */ + DB_COMPACT *c_data; /* For I_DB. */ + db_mutex_t mutex; /* Protects event_info (I_ENV). */ + } und2; + DBT i_lockobj; + FILE *i_err; + char *i_errpfx; + FILE *i_msg; + + /* Callbacks--Tcl_Objs containing proc names */ + Tcl_Obj *i_compare; + Tcl_Obj *i_dupcompare; + Tcl_Obj *i_foreign_call; + Tcl_Obj *i_hashproc; + Tcl_Obj *i_isalive; + Tcl_Obj *i_part_callback; + Tcl_Obj *i_rep_send; + Tcl_Obj *i_second_call; + + /* Environment ID for the i_rep_send callback. */ + Tcl_Obj *i_rep_eid; + + struct dbtcl_info *i_parent; + int i_otherid[MAX_ID]; + + /* Heap dbs have an associated recno db, and secondary db. */ + DB *hrdbp; + DB *hsdbp; +} DBTCL_INFO; + +#define i_anyp un.anyp +#define i_dbp un.dbp +#define i_dbcp un.dbcp +#define i_envp un.envp +#define i_lock un.lock +#define i_logc un.logc +#define i_mp un.mp +#define i_pagep un.anyp +#define i_txnp un.txnp + +#define i_data und.anydata +#define i_pgno und.pgno +#define i_locker und.lockid +#define i_event_info und.event_info +#define i_commit_token und.commit_token +#define i_data2 und2.anydata +#define i_pgsz und2.pagesz +#define i_cdata und2.c_data +#define i_mutex und2.mutex + +#define i_envtxnid i_otherid[0] +#define i_envmpid i_otherid[1] +#define i_envlockid i_otherid[2] +#define i_envlogcid i_otherid[3] + +#define i_mppgid i_otherid[0] + +#define i_dbdbcid i_otherid[0] + +extern int __debug_on, __debug_print, __debug_stop, __debug_test; + +typedef struct dbtcl_global { + LIST_HEAD(infohead, dbtcl_info) g_infohead; +} DBTCL_GLOBAL; +#define __db_infohead __dbtcl_global.g_infohead + +extern DBTCL_GLOBAL __dbtcl_global; + +/* + * Tcl_NewStringObj takes an "int" length argument, when the typical use is to + * call it with a size_t length (for example, returned by strlen). Tcl is in + * the wrong, but that doesn't help us much -- cast the argument. + */ +#define NewStringObj(a, b) \ + Tcl_NewStringObj((a), (int)(b)) + +#define NAME_TO_DB(name) (DB *)_NameToPtr((name)) +#define NAME_TO_DBC(name) (DBC *)_NameToPtr((name)) +#define NAME_TO_ENV(name) (DB_ENV *)_NameToPtr((name)) +#define NAME_TO_LOCK(name) (DB_LOCK *)_NameToPtr((name)) +#define NAME_TO_MP(name) (DB_MPOOLFILE *)_NameToPtr((name)) +#define NAME_TO_TXN(name) (DB_TXN *)_NameToPtr((name)) +#define NAME_TO_SEQUENCE(name) (DB_SEQUENCE *)_NameToPtr((name)) + +/* + * MAKE_STAT_LIST appends a {name value} pair to a result list that MUST be + * called 'res' that is a Tcl_Obj * in the local function. This macro also + * assumes a label "error" to go to in the event of a Tcl error. For stat + * functions this will typically go before the "free" function to free the + * stat structure returned by DB. + */ +#define MAKE_STAT_LIST(s, v) do { \ + result = _SetListElemInt(interp, res, (s), (long)(v)); \ + if (result != TCL_OK) \ + goto error; \ +} while (0) + +#define MAKE_WSTAT_LIST(s, v) do { \ + result = _SetListElemWideInt(interp, res, (s), (int64_t)(v)); \ + if (result != TCL_OK) \ + goto error; \ +} while (0) + +/* + * MAKE_STAT_LSN appends a {name {LSNfile LSNoffset}} pair to a result list + * that MUST be called 'res' that is a Tcl_Obj * in the local + * function. This macro also assumes a label "error" to go to + * in the even of a Tcl error. For stat functions this will + * typically go before the "free" function to free the stat structure + * returned by DB. + */ +#define MAKE_STAT_LSN(s, lsn) do { \ + myobjc = 2; \ + myobjv[0] = Tcl_NewLongObj((long)(lsn)->file); \ + myobjv[1] = Tcl_NewLongObj((long)(lsn)->offset); \ + lsnlist = Tcl_NewListObj(myobjc, myobjv); \ + myobjc = 2; \ + myobjv[0] = Tcl_NewStringObj((s), (int)strlen(s)); \ + myobjv[1] = lsnlist; \ + thislist = Tcl_NewListObj(myobjc, myobjv); \ + result = Tcl_ListObjAppendElement(interp, res, thislist); \ + if (result != TCL_OK) \ + goto error; \ +} while (0) + +/* + * MAKE_STAT_STRLIST appends a {name string} pair to a result list + * that MUST be called 'res' that is a Tcl_Obj * in the local + * function. This macro also assumes a label "error" to go to + * in the even of a Tcl error. For stat functions this will + * typically go before the "free" function to free the stat structure + * returned by DB. + */ +#define MAKE_STAT_STRLIST(s,s1) do { \ + result = _SetListElem(interp, res, (s), (u_int32_t)strlen(s), \ + (s1), (u_int32_t)strlen(s1)); \ + if (result != TCL_OK) \ + goto error; \ +} while (0) + +/* + * MAKE_SITE_LIST appends a {eid host port status} tuple to a result list + * that MUST be called 'res' that is a Tcl_Obj * in the local function. + * This macro also assumes a label "error" to go to in the event of a Tcl + * error. + */ +#define MAKE_SITE_LIST(e, h, p, s, pr) do { \ + myobjc = 5; \ + myobjv[0] = Tcl_NewIntObj(e); \ + myobjv[1] = Tcl_NewStringObj((h), (int)strlen(h)); \ + myobjv[2] = Tcl_NewIntObj((int)p); \ + myobjv[3] = Tcl_NewStringObj((s), (int)strlen(s)); \ + myobjv[4] = Tcl_NewStringObj((pr), (int)strlen(pr)); \ + thislist = Tcl_NewListObj(myobjc, myobjv); \ + result = Tcl_ListObjAppendElement(interp, res, thislist); \ + if (result != TCL_OK) \ + goto error; \ +} while (0) + +/* + * FLAG_CHECK checks that the given flag is not set yet. + * If it is, it sets up an error message. + */ +#define FLAG_CHECK(flag) do { \ + if ((flag) != 0) { \ + Tcl_SetResult(interp, \ + " Only 1 policy can be specified.\n", \ + TCL_STATIC); \ + result = TCL_ERROR; \ + break; \ + } \ +} while (0) + +/* + * FLAG_CHECK2 checks that the given flag is not set yet or is + * only set to the given allowed value. + * If it is, it sets up an error message. + */ +#define FLAG_CHECK2(flag, val) do { \ + if (((flag) & ~(val)) != 0) { \ + Tcl_SetResult(interp, \ + " Only 1 policy can be specified.\n", \ + TCL_STATIC); \ + result = TCL_ERROR; \ + break; \ + } \ +} while (0) + +/* + * IS_HELP checks whether the arg we bombed on is -?, which is a help option. + * If it is, we return TCL_OK (but leave the result set to whatever + * Tcl_GetIndexFromObj says, which lists all the valid options. Otherwise + * return TCL_ERROR. + */ +#define IS_HELP(s) \ + (strcmp(Tcl_GetStringFromObj(s,NULL), "-?") == 0) ? TCL_OK : TCL_ERROR + +#if defined(__cplusplus) +} +#endif + +#include "dbinc_auto/tcl_ext.h" +#endif /* !_DB_TCL_DB_H_ */ diff -r 000000000000 -r a1985f14b030 src/dbinc/txn.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/dbinc/txn.h Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,310 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 1996, 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + * $Id$ + */ + +#ifndef _DB_TXN_H_ +#define _DB_TXN_H_ + +#include "dbinc/xa.h" + +#if defined(__cplusplus) +extern "C" { +#endif + +/* Operation parameters to the delayed commit processing code. */ +typedef enum { + TXN_CLOSE, /* Close a DB handle whose close had failed. */ + TXN_REMOVE, /* Remove a file. */ + TXN_TRADE, /* Trade lockers. */ + TXN_TRADED, /* Already traded; downgrade lock. */ + TXN_XTRADE /* Trade lockers on exclusive db handle. */ +} TXN_EVENT_T; + +struct __db_txnregion; typedef struct __db_txnregion DB_TXNREGION; +struct __db_txn_stat_int; +typedef struct __db_txn_stat_int DB_TXN_STAT_INT; +struct __txn_logrec; typedef struct __txn_logrec DB_TXNLOGREC; + +/* + * !!! + * TXN_MINIMUM = (DB_LOCK_MAXID + 1) but this makes compilers complain. + */ +#define TXN_MINIMUM 0x80000000 +#define TXN_MAXIMUM 0xffffffff /* Maximum number of txn ids. */ +#define TXN_INVALID 0 /* Invalid transaction ID. */ + +#define DEF_MAX_TXNS 100 /* Default max transactions. */ +#define TXN_NSLOTS 4 /* Initial slots to hold DB refs */ + +#define TXN_PRIORITY_DEFAULT DB_LOCK_DEFPRIORITY + +/* + * This structure must contain the same fields as the __db_txn_stat struct + * except for any pointer fields that are filled in only when the struct is + * being populated for output through the API. + */ +DB_ALIGN8 struct __db_txn_stat_int { /* SHARED */ + u_int32_t st_nrestores; /* number of restored transactions + after recovery. */ +#ifndef __TEST_DB_NO_STATISTICS + DB_LSN st_last_ckp; /* lsn of the last checkpoint */ + time_t st_time_ckp; /* time of last checkpoint */ + u_int32_t st_last_txnid; /* last transaction id given out */ + u_int32_t st_inittxns; /* initial txns allocated */ + u_int32_t st_maxtxns; /* maximum txns possible */ + uintmax_t st_naborts; /* number of aborted transactions */ + uintmax_t st_nbegins; /* number of begun transactions */ + uintmax_t st_ncommits; /* number of committed transactions */ + u_int32_t st_nactive; /* number of active transactions */ + u_int32_t st_nsnapshot; /* number of snapshot transactions */ + u_int32_t st_maxnactive; /* maximum active transactions */ + u_int32_t st_maxnsnapshot; /* maximum snapshot transactions */ + uintmax_t st_region_wait; /* Region lock granted after wait. */ + uintmax_t st_region_nowait; /* Region lock granted without wait. */ + roff_t st_regsize; /* Region size. */ +#endif +}; + +/* + * Internal data maintained in shared memory for each transaction. + */ +typedef struct __txn_detail { + u_int32_t txnid; /* current transaction id + used to link free list also */ + pid_t pid; /* Process owning txn */ + db_threadid_t tid; /* Thread owning txn */ + + DB_LSN last_lsn; /* Last LSN written for this txn. */ + DB_LSN begin_lsn; /* LSN of begin record. */ + roff_t parent; /* Offset of transaction's parent. */ + roff_t name; /* Offset of txn name. */ + + u_int32_t nlog_dbs; /* Number of databases used. */ + u_int32_t nlog_slots; /* Number of allocated slots. */ + roff_t log_dbs; /* Databases used. */ + + DB_LSN read_lsn; /* Read LSN for MVCC. */ + DB_LSN visible_lsn; /* LSN at which this transaction's + changes are visible. */ + db_mutex_t mvcc_mtx; /* Version mutex. */ + u_int32_t mvcc_ref; /* Number of buffers created by this + transaction still in cache. */ + + u_int32_t priority; /* Deadlock resolution priority. */ + + SH_TAILQ_HEAD(__tdkids) kids; /* Linked list of child txn detail. */ + SH_TAILQ_ENTRY klinks; + + /* TXN_{ABORTED, COMMITTED PREPARED, RUNNING} */ + u_int32_t status; /* status of the transaction */ + +#define TXN_DTL_COLLECTED 0x01 /* collected during txn_recover */ +#define TXN_DTL_RESTORED 0x02 /* prepared txn restored */ +#define TXN_DTL_INMEMORY 0x04 /* uses in memory logs */ +#define TXN_DTL_SNAPSHOT 0x08 /* On the list of snapshot txns. */ +#define TXN_DTL_NOWAIT 0x10 /* Don't block on locks. */ + u_int32_t flags; + + SH_TAILQ_ENTRY links; /* active/free/snapshot list */ + + u_int32_t xa_ref; /* XA: reference count; number + of DB_TXNs reffing this struct */ + /* TXN_XA_{ACTIVE, DEADLOCKED, IDLE, PREPARED, ROLLEDBACK} */ + u_int32_t xa_br_status; /* status of XA branch */ + u_int8_t gid[DB_GID_SIZE]; /* global transaction id */ + u_int32_t bqual; /* bqual_length from XID */ + u_int32_t gtrid; /* gtrid_length from XID */ + int32_t format; /* XA format */ + roff_t slots[TXN_NSLOTS]; /* Initial DB slot allocation. */ +} TXN_DETAIL; + +/* + * DB_TXNMGR -- + * The transaction manager encapsulates the transaction system. + */ +struct __db_txnmgr { + /* + * These fields need to be protected for multi-threaded support. + * + * Lock list of active transactions (including the content of each + * TXN_DETAIL structure on the list). + */ + db_mutex_t mutex; + /* List of active transactions. */ + TAILQ_HEAD(_chain, __db_txn) txn_chain; + + u_int32_t n_discards; /* Number of txns discarded. */ + + /* These fields are never updated after creation, so not protected. */ + ENV *env; /* Environment. */ + REGINFO reginfo; /* Region information. */ +}; + +/* Macros to lock/unlock the transaction region as a whole. */ +#define TXN_SYSTEM_LOCK(env) \ + MUTEX_LOCK(env, ((DB_TXNREGION *) \ + (env)->tx_handle->reginfo.primary)->mtx_region) +#define TXN_SYSTEM_UNLOCK(env) \ + MUTEX_UNLOCK(env, ((DB_TXNREGION *) \ + (env)->tx_handle->reginfo.primary)->mtx_region) + +/* + * DB_TXNREGION -- + * The primary transaction data structure in the shared memory region. + */ +struct __db_txnregion { /* SHARED */ + db_mutex_t mtx_region; /* Region mutex. */ + + u_int32_t inittxns; /* initial number of active TXNs */ + u_int32_t curtxns; /* current number of active TXNs */ + u_int32_t maxtxns; /* maximum number of active TXNs */ + u_int32_t last_txnid; /* last transaction id given out */ + u_int32_t cur_maxid; /* current max unused id. */ + + db_mutex_t mtx_ckp; /* Single thread checkpoints. */ + DB_LSN last_ckp; /* lsn of the last checkpoint */ + time_t time_ckp; /* time of last checkpoint */ + + DB_TXN_STAT_INT stat; /* Statistics for txns. */ + + u_int32_t n_bulk_txn; /* Num. bulk txns in progress. */ + u_int32_t n_hotbackup; /* Num. of outstanding backup notices.*/ + +#define TXN_IN_RECOVERY 0x01 /* environment is being recovered */ + u_int32_t flags; + /* active TXN list */ + SH_TAILQ_HEAD(__active) active_txn; + SH_TAILQ_HEAD(__mvcc) mvcc_txn; +}; + +/* + * DB_COMMIT_INFO -- + * Meta-data uniquely describing a transaction commit across a replication + * group. + */ +struct __db_commit_info { + u_int32_t version; /* Stored format version. */ + u_int32_t gen; /* Replication master generation. */ + u_int32_t envid; /* Unique env ID of master. */ + DB_LSN lsn; /* LSN of commit log record. */ +}; + +/* + * DB_TXNLOGREC -- + * An in-memory, linked-list copy of a log record. + */ +struct __txn_logrec { + STAILQ_ENTRY(__txn_logrec) links;/* Linked list. */ + + u_int8_t data[1]; /* Log record. */ +}; + +/* + * Log record types. Note that these are *not* alphabetical. This is + * intentional so that we don't change the meaning of values between + * software upgrades. + * + * EXPECTED, UNEXPECTED, IGNORE, and OK are used in the txnlist functions. + * Here is an explanation of how the statuses are used. + * + * TXN_OK + * BEGIN records for transactions found on the txnlist during + * OPENFILES (BEGIN records are those with a prev_lsn of 0,0) + * + * TXN_COMMIT + * Transaction committed and should be rolled forward. + * + * TXN_ABORT + * This transaction's changes must be undone. Either there was + * never a prepare or commit record for this transaction OR there + * was a commit, but we are recovering to a timestamp or particular + * LSN and that point is before this transaction's commit. + * + * TXN_PREPARE + * Prepare record, but no commit record is in the log. + * + * TXN_IGNORE + * Generic meaning is that this transaction should not be + * processed during later recovery passes. We use it in a + * number of different manners: + * + * 1. We never saw its BEGIN record. Therefore, the logs have + * been reclaimed and we *know* that this transaction doesn't + * need to be aborted, because in order for it to be + * reclaimed, there must have been a subsequent checkpoint + * (and any dirty pages for this transaction made it to + * disk). + * + * 2. This is a child transaction that created a database. + * For some reason, we don't want to recreate that database + * (i.e., it already exists or some other database created + * after it exists). + * + * 3. During recovery open of subdatabases, if the master check fails, + * we use a TXN_IGNORE on the create of the subdb in the nested + * transaction. + * + * 4. During a remove, the file with the name being removed isn't + * the file for which we are recovering a remove. + * + * TXN_EXPECTED + * After a successful open during recovery, we update the + * transaction's status to TXN_EXPECTED. The open was done + * in the parent, but in the open log record, we record the + * child transaction's ID if we also did a create. When there + * is a valid ID in that field, we use it and mark the child's + * status as TXN_EXPECTED (indicating that we don't need to redo + * a create for this file). + * + * When recovering a remove, if we don't find or can't open + * the file, the child (which does the remove) gets marked + * EXPECTED (indicating that we don't need to redo the remove). + * + * TXN_UNEXPECTED + * During recovery, we attempted an open that should have succeeded + * and we got ENOENT, so like with the EXPECTED case, we indicate + * in the child that we got the UNEXPECTED return so that we do redo + * the creating/deleting operation. + * + */ +#define TXN_OK 0 +#define TXN_COMMIT 1 +#define TXN_PREPARE 2 +#define TXN_ABORT 3 +#define TXN_IGNORE 4 +#define TXN_EXPECTED 5 +#define TXN_UNEXPECTED 6 + +#if defined(__cplusplus) +} +#endif + +#include "dbinc_auto/txn_auto.h" +#include "dbinc_auto/txn_ext.h" +#endif /* !_DB_TXN_H_ */ diff -r 000000000000 -r a1985f14b030 src/dbinc/win_db.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/dbinc/win_db.h Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,170 @@ +/*- + * Copyright (c) 2010, 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + * The following provides the information necessary to build Berkeley + * DB on native Windows, and other Windows environments such as MinGW. + */ + +/* + * Berkeley DB requires at least Windows 2000, tell Visual Studio of the + * requirement. + */ +#ifndef _WIN32_WINNT +#define _WIN32_WINNT 0x0500 +#endif + +#ifndef DB_WINCE +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#endif /* DB_WINCE */ + +#include +#include +#include +#include +#include + +/* + * To build Tcl interface libraries, the include path must be configured to + * use the directory containing , usually the include directory in + * the Tcl distribution. + */ +#ifdef DB_TCL_SUPPORT +#include +#endif + +#define WIN32_LEAN_AND_MEAN +#include +#include +#ifndef DB_WINCE +#include +#endif + +#ifdef HAVE_GETADDRINFO +/* + * Need explicit includes for IPv6 support on Windows. Both are necessary to + * ensure that pre WinXP versions have an implementation of the getaddrinfo API. + */ +#include +#include +#endif + +/* + * Microsoft's C runtime library has fsync, getcwd, getpid, snprintf and + * vsnprintf, but under different names. + */ +#define fsync _commit + +#ifndef DB_WINCE +#define getcwd(buf, size) _getcwd(buf, size) +#endif +#define getpid GetCurrentProcessId +#define snprintf _snprintf +#define strcasecmp _stricmp +#define strncasecmp _strnicmp +#define vsnprintf _vsnprintf + +#define h_errno WSAGetLastError() + +/* + * Win32 does not have getopt. + * + * The externs are here, instead of using db_config.h and clib_port.h, because + * that approach changes function names to BDB specific names, and the example + * programs use getopt and can't use BDB specific names. + */ +#if defined(__cplusplus) +extern "C" { +#endif +extern int getopt(int, char * const *, const char *); +#if defined(__cplusplus) +} +#endif + +/* + * Microsoft's compiler _doesn't_ define __STDC__ unless you invoke it with + * arguments turning OFF all vendor extensions. Even more unfortunately, if + * we do that, it fails to parse windows.h!!!!! So, we define __STDC__ here, + * after windows.h comes in. Note: the compiler knows we've defined it, and + * starts enforcing strict ANSI compliance from this point on. + */ +#ifndef __STDC__ +#define __STDC__ 1 +#endif + +#ifdef _UNICODE +#define TO_TSTRING(dbenv, s, ts, ret) do { \ + int __len = (int)strlen(s) + 1; \ + ts = NULL; \ + if ((ret = __os_malloc((dbenv), \ + __len * sizeof(_TCHAR), &(ts))) == 0 && \ + MultiByteToWideChar(CP_UTF8, 0, \ + (s), -1, (ts), __len) == 0) \ + ret = __os_posix_err(__os_get_syserr()); \ + } while (0) + +#define FROM_TSTRING(dbenv, ts, s, ret) { \ + int __len = WideCharToMultiByte(CP_UTF8, 0, ts, -1, \ + NULL, 0, NULL, NULL); \ + s = NULL; \ + if ((ret = __os_malloc((dbenv), __len, &(s))) == 0 && \ + WideCharToMultiByte(CP_UTF8, 0, \ + (ts), -1, (s), __len, NULL, NULL) == 0) \ + ret = __os_posix_err(__os_get_syserr()); \ + } while (0) + +#define FREE_STRING(dbenv, s) do { \ + if ((s) != NULL) { \ + __os_free((dbenv), (s)); \ + (s) = NULL; \ + } \ + } while (0) + +#else +#define TO_TSTRING(dbenv, s, ts, ret) (ret) = 0, (ts) = (_TCHAR *)(s) +#define FROM_TSTRING(dbenv, ts, s, ret) (ret) = 0, (s) = (char *)(ts) +#define FREE_STRING(dbenv, ts) +#endif + +#ifndef INVALID_HANDLE_VALUE +#define INVALID_HANDLE_VALUE ((HANDLE)-1) +#endif + +#ifndef INVALID_FILE_ATTRIBUTES +#define INVALID_FILE_ATTRIBUTES ((DWORD)-1) +#endif + +#ifndef INVALID_SET_FILE_POINTER +#define INVALID_SET_FILE_POINTER ((DWORD)-1) +#endif diff -r 000000000000 -r a1985f14b030 src/dbinc/xa.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/dbinc/xa.h Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,205 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 1998, 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + * $Id$ + */ +/* + * Start of xa.h header + * + * Define a symbol to prevent multiple inclusions of this header file + */ +#ifndef _DB_XA_H_ +#define _DB_XA_H_ + +#if defined(__cplusplus) +extern "C" { +#endif + +/* + * Transaction branch identification: XID and NULLXID: + */ +#define XIDDATASIZE 128 /* size in bytes */ +#define MAXGTRIDSIZE 64 /* maximum size in bytes of gtrid */ +#define MAXBQUALSIZE 64 /* maximum size in bytes of bqual */ + +struct xid_t { + long formatID; /* format identifier */ + long gtrid_length; /* value from 1 through 64 */ + long bqual_length; /* value from 1 through 64 */ + char data[XIDDATASIZE]; +}; +typedef struct xid_t XID; +/* + * A value of -1 in formatID means that the XID is null. + */ + +/* + * Declarations of routines by which RMs call TMs: + */ +extern int ax_reg __P((int, XID *, long)); +extern int ax_unreg __P((int, long)); + +/* + * XA Switch Data Structure + */ +#define RMNAMESZ 32 /* length of resource manager name, */ + /* including the null terminator */ +#define MAXINFOSIZE 256 /* maximum size in bytes of xa_info */ + /* strings, including the null + terminator */ +struct xa_switch_t { + char name[RMNAMESZ]; /* name of resource manager */ + long flags; /* resource manager specific options */ + long version; /* must be 0 */ + int (*xa_open_entry) /* xa_open function pointer */ + __P((char *, int, long)); + int (*xa_close_entry) /* xa_close function pointer */ + __P((char *, int, long)); + int (*xa_start_entry) /* xa_start function pointer */ + __P((XID *, int, long)); + int (*xa_end_entry) /* xa_end function pointer */ + __P((XID *, int, long)); + int (*xa_rollback_entry) /* xa_rollback function pointer */ + __P((XID *, int, long)); + int (*xa_prepare_entry) /* xa_prepare function pointer */ + __P((XID *, int, long)); + int (*xa_commit_entry) /* xa_commit function pointer */ + __P((XID *, int, long)); + int (*xa_recover_entry) /* xa_recover function pointer */ + __P((XID *, long, int, long)); + int (*xa_forget_entry) /* xa_forget function pointer */ + __P((XID *, int, long)); + int (*xa_complete_entry) /* xa_complete function pointer */ + __P((int *, int *, int, long)); +}; + +/* + * Flag definitions for the RM switch + */ +#define TMNOFLAGS 0x00000000L /* no resource manager features + selected */ +#define TMREGISTER 0x00000001L /* resource manager dynamically + registers */ +#define TMNOMIGRATE 0x00000002L /* resource manager does not support + association migration */ +#define TMUSEASYNC 0x00000004L /* resource manager supports + asynchronous operations */ +/* + * Flag definitions for xa_ and ax_ routines + */ +/* use TMNOFLAGGS, defined above, when not specifying other flags */ +#define TMASYNC 0x80000000L /* perform routine asynchronously */ +#define TMONEPHASE 0x40000000L /* caller is using one-phase commit + optimisation */ +#define TMFAIL 0x20000000L /* dissociates caller and marks + transaction branch rollback-only */ +#define TMNOWAIT 0x10000000L /* return if blocking condition + exists */ +#define TMRESUME 0x08000000L /* caller is resuming association with + suspended transaction branch */ +#define TMSUCCESS 0x04000000L /* dissociate caller from transaction + branch */ +#define TMSUSPEND 0x02000000L /* caller is suspending, not ending, + association */ +#define TMSTARTRSCAN 0x01000000L /* start a recovery scan */ +#define TMENDRSCAN 0x00800000L /* end a recovery scan */ +#define TMMULTIPLE 0x00400000L /* wait for any asynchronous + operation */ +#define TMJOIN 0x00200000L /* caller is joining existing + transaction branch */ +#define TMMIGRATE 0x00100000L /* caller intends to perform + migration */ + +/* + * ax_() return codes (transaction manager reports to resource manager) + */ +#define TM_JOIN 2 /* caller is joining existing + transaction branch */ +#define TM_RESUME 1 /* caller is resuming association with + suspended transaction branch */ +#define TM_OK 0 /* normal execution */ +#define TMER_TMERR -1 /* an error occurred in the transaction + manager */ +#define TMER_INVAL -2 /* invalid arguments were given */ +#define TMER_PROTO -3 /* routine invoked in an improper + context */ + +/* + * xa_() return codes (resource manager reports to transaction manager) + */ +#define XA_RBBASE 100 /* The inclusive lower bound of the + rollback codes */ +#define XA_RBROLLBACK XA_RBBASE /* The rollback was caused by an + unspecified reason */ +#define XA_RBCOMMFAIL XA_RBBASE+1 /* The rollback was caused by a + communication failure */ +#define XA_RBDEADLOCK XA_RBBASE+2 /* A deadlock was detected */ +#define XA_RBINTEGRITY XA_RBBASE+3 /* A condition that violates the + integrity of the resources was + detected */ +#define XA_RBOTHER XA_RBBASE+4 /* The resource manager rolled back the + transaction branch for a reason not + on this list */ +#define XA_RBPROTO XA_RBBASE+5 /* A protocol error occurred in the + resource manager */ +#define XA_RBTIMEOUT XA_RBBASE+6 /* A transaction branch took too long */ +#define XA_RBTRANSIENT XA_RBBASE+7 /* May retry the transaction branch */ +#define XA_RBEND XA_RBTRANSIENT /* The inclusive upper bound of the + rollback codes */ +#define XA_NOMIGRATE 9 /* resumption must occur where + suspension occurred */ +#define XA_HEURHAZ 8 /* the transaction branch may have + been heuristically completed */ +#define XA_HEURCOM 7 /* the transaction branch has been + heuristically committed */ +#define XA_HEURRB 6 /* the transaction branch has been + heuristically rolled back */ +#define XA_HEURMIX 5 /* the transaction branch has been + heuristically committed and rolled + back */ +#define XA_RETRY 4 /* routine returned with no effect and + may be re-issued */ +#define XA_RDONLY 3 /* the transaction branch was read-only + and has been committed */ +#define XA_OK 0 /* normal execution */ +#define XAER_ASYNC -2 /* asynchronous operation already + outstanding */ +#define XAER_RMERR -3 /* a resource manager error occurred in + the transaction branch */ +#define XAER_NOTA -4 /* the XID is not valid */ +#define XAER_INVAL -5 /* invalid arguments were given */ +#define XAER_PROTO -6 /* routine invoked in an improper + context */ +#define XAER_RMFAIL -7 /* resource manager unavailable */ +#define XAER_DUPID -8 /* the XID already exists */ +#define XAER_OUTSIDE -9 /* resource manager doing work outside + transaction */ + +#if defined(__cplusplus) +} +#endif +#endif /* !_DB_XA_H_ */ diff -r 000000000000 -r a1985f14b030 src/dbinc_auto/api_flags.in --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/dbinc_auto/api_flags.in Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,254 @@ +/* DO NOT EDIT: automatically built by dist/s_include. + * + * Copyright (c) 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ +#define DB_AGGRESSIVE 0x00000001 +#define DB_ARCH_ABS 0x00000001 +#define DB_ARCH_DATA 0x00000002 +#define DB_ARCH_LOG 0x00000004 +#define DB_ARCH_REMOVE 0x00000008 +#define DB_AUTO_COMMIT 0x00000100 +#define DB_BACKUP_CLEAN 0x00000002 +#define DB_BACKUP_FILES 0x00000008 +#define DB_BACKUP_NO_LOGS 0x00000010 +#define DB_BACKUP_SINGLE_DIR 0x00000020 +#define DB_BACKUP_UPDATE 0x00000040 +#define DB_BOOTSTRAP_HELPER 0x00000001 +#define DB_CDB_ALLDB 0x00000040 +#define DB_CHKSUM 0x00000008 +#define DB_CKP_INTERNAL 0x00000002 +#define DB_CREATE 0x00000001 +#define DB_CURSOR_BULK 0x00000001 +#define DB_CURSOR_TRANSIENT 0x00000008 +#define DB_CXX_NO_EXCEPTIONS 0x00000002 +#define DB_DATABASE_LOCKING 0x00000080 +#define DB_DIRECT 0x00000020 +#define DB_DIRECT_DB 0x00000200 +#define DB_DSYNC_DB 0x00000400 +#define DB_DUP 0x00000010 +#define DB_DUPSORT 0x00000002 +#define DB_DURABLE_UNKNOWN 0x00000040 +#define DB_ENCRYPT 0x00000001 +#define DB_ENCRYPT_AES 0x00000001 +#define DB_EXCL 0x00000004 +#define DB_EXTENT 0x00000100 +#define DB_FAILCHK 0x00000010 +#define DB_FAILCHK_ISALIVE 0x00000040 +#define DB_FAST_STAT 0x00000001 +#define DB_FCNTL_LOCKING 0x00000800 +#define DB_FLUSH 0x00000002 +#define DB_FORCE 0x00000001 +#define DB_FORCESYNC 0x00000001 +#define DB_FOREIGN_ABORT 0x00000001 +#define DB_FOREIGN_CASCADE 0x00000002 +#define DB_FOREIGN_NULLIFY 0x00000004 +#define DB_FREELIST_ONLY 0x00000001 +#define DB_FREE_SPACE 0x00000002 +#define DB_GROUP_CREATOR 0x00000002 +#define DB_HOTBACKUP_IN_PROGRESS 0x00000800 +#define DB_IGNORE_LEASE 0x00001000 +#define DB_IMMUTABLE_KEY 0x00000002 +#define DB_INIT_CDB 0x00000080 +#define DB_INIT_LOCK 0x00000100 +#define DB_INIT_LOG 0x00000200 +#define DB_INIT_MPOOL 0x00000400 +#define DB_INIT_MUTEX 0x00000800 +#define DB_INIT_REP 0x00001000 +#define DB_INIT_TXN 0x00002000 +#define DB_INORDER 0x00000020 +#define DB_INTERNAL_PERSISTENT_DB 0x00001000 +#define DB_INTERNAL_TEMPORARY_DB 0x00002000 +#define DB_JOIN_NOSORT 0x00000001 +#define DB_LEGACY 0x00000004 +#define DB_LOCAL_SITE 0x00000008 +#define DB_LOCKDOWN 0x00004000 +#define DB_LOCK_CHECK 0x00000001 +#define DB_LOCK_IGNORE_REC 0x00000002 +#define DB_LOCK_NOWAIT 0x00000004 +#define DB_LOCK_RECORD 0x00000008 +#define DB_LOCK_SET_TIMEOUT 0x00000010 +#define DB_LOCK_SWITCH 0x00000020 +#define DB_LOCK_UPGRADE 0x00000040 +#define DB_LOG_AUTO_REMOVE 0x00000001 +#define DB_LOG_CHKPNT 0x00000001 +#define DB_LOG_COMMIT 0x00000004 +#define DB_LOG_DIRECT 0x00000002 +#define DB_LOG_DSYNC 0x00000004 +#define DB_LOG_IN_MEMORY 0x00000008 +#define DB_LOG_NOCOPY 0x00000008 +#define DB_LOG_NOT_DURABLE 0x00000010 +#define DB_LOG_NO_DATA 0x00000002 +#define DB_LOG_VERIFY_CAF 0x00000001 +#define DB_LOG_VERIFY_DBFILE 0x00000002 +#define DB_LOG_VERIFY_ERR 0x00000004 +#define DB_LOG_VERIFY_FORWARD 0x00000008 +#define DB_LOG_VERIFY_INTERR 0x00000010 +#define DB_LOG_VERIFY_PARTIAL 0x00000020 +#define DB_LOG_VERIFY_VERBOSE 0x00000040 +#define DB_LOG_VERIFY_WARNING 0x00000080 +#define DB_LOG_WRNOSYNC 0x00000020 +#define DB_LOG_ZERO 0x00000010 +#define DB_MPOOL_CREATE 0x00000001 +#define DB_MPOOL_DIRTY 0x00000002 +#define DB_MPOOL_DISCARD 0x00000001 +#define DB_MPOOL_EDIT 0x00000004 +#define DB_MPOOL_FREE 0x00000008 +#define DB_MPOOL_LAST 0x00000010 +#define DB_MPOOL_NEW 0x00000020 +#define DB_MPOOL_NOFILE 0x00000001 +#define DB_MPOOL_NOLOCK 0x00000004 +#define DB_MPOOL_TRY 0x00000040 +#define DB_MPOOL_UNLINK 0x00000002 +#define DB_MULTIPLE 0x00000800 +#define DB_MULTIPLE_KEY 0x00004000 +#define DB_MULTIVERSION 0x00000008 +#define DB_MUTEX_ALLOCATED 0x00000001 +#define DB_MUTEX_LOCKED 0x00000002 +#define DB_MUTEX_LOGICAL_LOCK 0x00000004 +#define DB_MUTEX_PROCESS_ONLY 0x00000008 +#define DB_MUTEX_SELF_BLOCK 0x00000010 +#define DB_MUTEX_SHARED 0x00000020 +#define DB_NOERROR 0x00004000 +#define DB_NOFLUSH 0x00001000 +#define DB_NOLOCKING 0x00002000 +#define DB_NOMMAP 0x00000010 +#define DB_NOORDERCHK 0x00000002 +#define DB_NOPANIC 0x00004000 +#define DB_NOSYNC 0x00000001 +#define DB_NO_AUTO_COMMIT 0x00008000 +#define DB_NO_CHECKPOINT 0x00008000 +#define DB_ODDFILESIZE 0x00000080 +#define DB_ORDERCHKONLY 0x00000004 +#define DB_OVERWRITE 0x00008000 +#define DB_PANIC_ENVIRONMENT 0x00010000 +#define DB_PRINTABLE 0x00000008 +#define DB_PRIVATE 0x00010000 +#define DB_PR_PAGE 0x00000010 +#define DB_PR_RECOVERYTEST 0x00000020 +#define DB_RDONLY 0x00000400 +#define DB_RDWRMASTER 0x00010000 +#define DB_READ_COMMITTED 0x00000400 +#define DB_READ_UNCOMMITTED 0x00000200 +#define DB_RECNUM 0x00000040 +#define DB_RECOVER 0x00000002 +#define DB_RECOVER_FATAL 0x00020000 +#define DB_REGION_INIT 0x00020000 +#define DB_REGISTER 0x00040000 +#define DB_RENUMBER 0x00000080 +#define DB_REPMGR_CONF_2SITE_STRICT 0x00000001 +#define DB_REPMGR_CONF_ELECTIONS 0x00000002 +#define DB_REPMGR_NEED_RESPONSE 0x00000001 +#define DB_REPMGR_PEER 0x00000010 +#define DB_REP_ANYWHERE 0x00000001 +#define DB_REP_CLIENT 0x00000001 +#define DB_REP_CONF_AUTOINIT 0x00000004 +#define DB_REP_CONF_AUTOROLLBACK 0x00000008 +#define DB_REP_CONF_BULK 0x00000010 +#define DB_REP_CONF_DELAYCLIENT 0x00000020 +#define DB_REP_CONF_INMEM 0x00000040 +#define DB_REP_CONF_LEASE 0x00000080 +#define DB_REP_CONF_NOWAIT 0x00000100 +#define DB_REP_ELECTION 0x00000004 +#define DB_REP_MASTER 0x00000002 +#define DB_REP_NOBUFFER 0x00000002 +#define DB_REP_PERMANENT 0x00000004 +#define DB_REP_REREQUEST 0x00000008 +#define DB_REVSPLITOFF 0x00000100 +#define DB_RMW 0x00002000 +#define DB_SALVAGE 0x00000040 +#define DB_SA_SKIPFIRSTKEY 0x00000080 +#define DB_SA_UNKNOWNKEY 0x00000100 +#define DB_SEQ_DEC 0x00000001 +#define DB_SEQ_INC 0x00000002 +#define DB_SEQ_RANGE_SET 0x00000004 +#define DB_SEQ_WRAP 0x00000008 +#define DB_SEQ_WRAPPED 0x00000010 +#define DB_SET_LOCK_TIMEOUT 0x00000001 +#define DB_SET_REG_TIMEOUT 0x00000004 +#define DB_SET_TXN_NOW 0x00000008 +#define DB_SET_TXN_TIMEOUT 0x00000002 +#define DB_SHALLOW_DUP 0x00000100 +#define DB_SNAPSHOT 0x00000200 +#define DB_STAT_ALL 0x00000004 +#define DB_STAT_ALLOC 0x00000008 +#define DB_STAT_CLEAR 0x00000001 +#define DB_STAT_LOCK_CONF 0x00000010 +#define DB_STAT_LOCK_LOCKERS 0x00000020 +#define DB_STAT_LOCK_OBJECTS 0x00000040 +#define DB_STAT_LOCK_PARAMS 0x00000080 +#define DB_STAT_MEMP_HASH 0x00000010 +#define DB_STAT_MEMP_NOERROR 0x00000020 +#define DB_STAT_SUBSYSTEM 0x00000002 +#define DB_STAT_SUMMARY 0x00000010 +#define DB_ST_DUPOK 0x00000200 +#define DB_ST_DUPSET 0x00000400 +#define DB_ST_DUPSORT 0x00000800 +#define DB_ST_IS_RECNO 0x00001000 +#define DB_ST_OVFL_LEAF 0x00002000 +#define DB_ST_RECNUM 0x00004000 +#define DB_ST_RELEN 0x00008000 +#define DB_ST_TOPLEVEL 0x00010000 +#define DB_SYSTEM_MEM 0x00080000 +#define DB_THREAD 0x00000020 +#define DB_TIME_NOTGRANTED 0x00040000 +#define DB_TRUNCATE 0x00020000 +#define DB_TXN_BULK 0x00000010 +#define DB_TXN_FAMILY 0x00000040 +#define DB_TXN_NOSYNC 0x00000001 +#define DB_TXN_NOT_DURABLE 0x00000004 +#define DB_TXN_NOWAIT 0x00000002 +#define DB_TXN_SNAPSHOT 0x00000004 +#define DB_TXN_SYNC 0x00000008 +#define DB_TXN_WAIT 0x00000080 +#define DB_TXN_WRITE_NOSYNC 0x00000020 +#define DB_UNREF 0x00020000 +#define DB_UPGRADE 0x00000001 +#define DB_USE_ENVIRON 0x00000004 +#define DB_USE_ENVIRON_ROOT 0x00000008 +#define DB_VERB_BACKUP 0x00000001 +#define DB_VERB_DEADLOCK 0x00000002 +#define DB_VERB_FILEOPS 0x00000004 +#define DB_VERB_FILEOPS_ALL 0x00000008 +#define DB_VERB_RECOVERY 0x00000010 +#define DB_VERB_REGISTER 0x00000020 +#define DB_VERB_REPLICATION 0x00000040 +#define DB_VERB_REPMGR_CONNFAIL 0x00000080 +#define DB_VERB_REPMGR_MISC 0x00000100 +#define DB_VERB_REP_ELECT 0x00000200 +#define DB_VERB_REP_LEASE 0x00000400 +#define DB_VERB_REP_MISC 0x00000800 +#define DB_VERB_REP_MSGS 0x00001000 +#define DB_VERB_REP_SYNC 0x00002000 +#define DB_VERB_REP_SYSTEM 0x00004000 +#define DB_VERB_REP_TEST 0x00008000 +#define DB_VERB_WAITSFOR 0x00010000 +#define DB_VERIFY 0x00000002 +#define DB_VERIFY_PARTITION 0x00040000 +#define DB_WRITECURSOR 0x00000010 +#define DB_WRITELOCK 0x00000020 +#define DB_WRITEOPEN 0x00040000 +#define DB_XA_CREATE 0x00000001 +#define DB_YIELDCPU 0x00080000 diff -r 000000000000 -r a1985f14b030 src/dbinc_auto/btree_auto.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/dbinc_auto/btree_auto.h Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,481 @@ +/* Do not edit: automatically built by gen_rec.awk. + * + * Copyright (c) 2012 Oracle and/or its affiliates. All rights reserved. * + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +#ifndef __bam_AUTO_H +#define __bam_AUTO_H +#include "dbinc/log.h" +#define DB___bam_split 62 +typedef struct ___bam_split_args { + u_int32_t type; + DB_TXN *txnp; + DB_LSN prev_lsn; + int32_t fileid; + u_int32_t opflags; + db_pgno_t left; + DB_LSN llsn; + db_pgno_t right; + DB_LSN rlsn; + u_int32_t indx; + db_pgno_t npgno; + DB_LSN nlsn; + db_pgno_t ppgno; + DB_LSN plsn; + u_int32_t pindx; + DBT pg; + DBT pentry; + DBT rentry; +} __bam_split_args; + +extern __DB_IMPORT DB_LOG_RECSPEC __bam_split_desc[]; +static inline int +__bam_split_log(DB *dbp, DB_TXN *txnp, DB_LSN *ret_lsnp, u_int32_t flags, u_int32_t opflags, db_pgno_t left, DB_LSN * llsn, db_pgno_t right, + DB_LSN * rlsn, u_int32_t indx, db_pgno_t npgno, DB_LSN * nlsn, db_pgno_t ppgno, + DB_LSN * plsn, u_int32_t pindx, const DBT *pg, const DBT *pentry, const DBT *rentry) +{ + return (__log_put_record((dbp)->env, dbp, txnp, ret_lsnp, + flags, DB___bam_split, 0, + sizeof(u_int32_t) + sizeof(u_int32_t) + sizeof(DB_LSN) + + sizeof(u_int32_t) + sizeof(u_int32_t) + sizeof(u_int32_t) + + sizeof(*llsn) + sizeof(u_int32_t) + sizeof(*rlsn) + + sizeof(u_int32_t) + sizeof(u_int32_t) + sizeof(*nlsn) + + sizeof(u_int32_t) + sizeof(*plsn) + sizeof(u_int32_t) + + LOG_DBT_SIZE(pg) + LOG_DBT_SIZE(pentry) + LOG_DBT_SIZE(rentry), + __bam_split_desc, opflags, left, llsn, right, rlsn, indx, npgno, + nlsn, ppgno, plsn, pindx, pg, pentry, rentry)); +} + +static inline int __bam_split_read(ENV *env, + DB **dbpp, void *td, void *data, __bam_split_args **arg) +{ + *arg = NULL; + return (__log_read_record(env, + dbpp, td, data, __bam_split_desc, sizeof(__bam_split_args), (void**)arg)); +} +#define DB___bam_split_48 62 +typedef struct ___bam_split_48_args { + u_int32_t type; + DB_TXN *txnp; + DB_LSN prev_lsn; + int32_t fileid; + db_pgno_t left; + DB_LSN llsn; + db_pgno_t right; + DB_LSN rlsn; + u_int32_t indx; + db_pgno_t npgno; + DB_LSN nlsn; + db_pgno_t ppgno; + DB_LSN plsn; + u_int32_t pindx; + DBT pg; + DBT pentry; + DBT rentry; + u_int32_t opflags; +} __bam_split_48_args; + +extern __DB_IMPORT DB_LOG_RECSPEC __bam_split_48_desc[]; +static inline int __bam_split_48_read(ENV *env, + DB **dbpp, void *td, void *data, __bam_split_48_args **arg) +{ + *arg = NULL; + return (__log_read_record(env, + dbpp, td, data, __bam_split_48_desc, sizeof(__bam_split_48_args), (void**)arg)); +} +#define DB___bam_split_42 62 +typedef struct ___bam_split_42_args { + u_int32_t type; + DB_TXN *txnp; + DB_LSN prev_lsn; + int32_t fileid; + db_pgno_t left; + DB_LSN llsn; + db_pgno_t right; + DB_LSN rlsn; + u_int32_t indx; + db_pgno_t npgno; + DB_LSN nlsn; + db_pgno_t root_pgno; + DBT pg; + u_int32_t opflags; +} __bam_split_42_args; + +extern __DB_IMPORT DB_LOG_RECSPEC __bam_split_42_desc[]; +static inline int __bam_split_42_read(ENV *env, + DB **dbpp, void *td, void *data, __bam_split_42_args **arg) +{ + *arg = NULL; + return (__log_read_record(env, + dbpp, td, data, __bam_split_42_desc, sizeof(__bam_split_42_args), (void**)arg)); +} +#define DB___bam_rsplit 63 +typedef struct ___bam_rsplit_args { + u_int32_t type; + DB_TXN *txnp; + DB_LSN prev_lsn; + int32_t fileid; + db_pgno_t pgno; + DBT pgdbt; + db_pgno_t root_pgno; + db_pgno_t nrec; + DBT rootent; + DB_LSN rootlsn; +} __bam_rsplit_args; + +extern __DB_IMPORT DB_LOG_RECSPEC __bam_rsplit_desc[]; +static inline int +__bam_rsplit_log(DB *dbp, DB_TXN *txnp, DB_LSN *ret_lsnp, u_int32_t flags, db_pgno_t pgno, const DBT *pgdbt, db_pgno_t root_pgno, db_pgno_t nrec, + const DBT *rootent, DB_LSN * rootlsn) +{ + return (__log_put_record((dbp)->env, dbp, txnp, ret_lsnp, + flags, DB___bam_rsplit, 0, + sizeof(u_int32_t) + sizeof(u_int32_t) + sizeof(DB_LSN) + + sizeof(u_int32_t) + sizeof(u_int32_t) + LOG_DBT_SIZE(pgdbt) + + sizeof(u_int32_t) + sizeof(u_int32_t) + LOG_DBT_SIZE(rootent) + + sizeof(*rootlsn), + __bam_rsplit_desc, pgno, pgdbt, root_pgno, nrec, rootent, rootlsn)); +} + +static inline int __bam_rsplit_read(ENV *env, + DB **dbpp, void *td, void *data, __bam_rsplit_args **arg) +{ + *arg = NULL; + return (__log_read_record(env, + dbpp, td, data, __bam_rsplit_desc, sizeof(__bam_rsplit_args), (void**)arg)); +} +#define DB___bam_adj 55 +typedef struct ___bam_adj_args { + u_int32_t type; + DB_TXN *txnp; + DB_LSN prev_lsn; + int32_t fileid; + db_pgno_t pgno; + DB_LSN lsn; + u_int32_t indx; + u_int32_t indx_copy; + u_int32_t is_insert; +} __bam_adj_args; + +extern __DB_IMPORT DB_LOG_RECSPEC __bam_adj_desc[]; +static inline int +__bam_adj_log(DB *dbp, DB_TXN *txnp, DB_LSN *ret_lsnp, u_int32_t flags, db_pgno_t pgno, DB_LSN * lsn, u_int32_t indx, u_int32_t indx_copy, + u_int32_t is_insert) +{ + return (__log_put_record((dbp)->env, dbp, txnp, ret_lsnp, + flags, DB___bam_adj, 0, + sizeof(u_int32_t) + sizeof(u_int32_t) + sizeof(DB_LSN) + + sizeof(u_int32_t) + sizeof(u_int32_t) + sizeof(*lsn) + + sizeof(u_int32_t) + sizeof(u_int32_t) + sizeof(u_int32_t), + __bam_adj_desc, pgno, lsn, indx, indx_copy, is_insert)); +} + +static inline int __bam_adj_read(ENV *env, + DB **dbpp, void *td, void *data, __bam_adj_args **arg) +{ + *arg = NULL; + return (__log_read_record(env, + dbpp, td, data, __bam_adj_desc, sizeof(__bam_adj_args), (void**)arg)); +} +#define DB___bam_cadjust 56 +typedef struct ___bam_cadjust_args { + u_int32_t type; + DB_TXN *txnp; + DB_LSN prev_lsn; + int32_t fileid; + db_pgno_t pgno; + DB_LSN lsn; + u_int32_t indx; + int32_t adjust; + u_int32_t opflags; +} __bam_cadjust_args; + +extern __DB_IMPORT DB_LOG_RECSPEC __bam_cadjust_desc[]; +static inline int +__bam_cadjust_log(DB *dbp, DB_TXN *txnp, DB_LSN *ret_lsnp, u_int32_t flags, db_pgno_t pgno, DB_LSN * lsn, u_int32_t indx, int32_t adjust, + u_int32_t opflags) +{ + return (__log_put_record((dbp)->env, dbp, txnp, ret_lsnp, + flags, DB___bam_cadjust, 0, + sizeof(u_int32_t) + sizeof(u_int32_t) + sizeof(DB_LSN) + + sizeof(u_int32_t) + sizeof(u_int32_t) + sizeof(*lsn) + + sizeof(u_int32_t) + sizeof(u_int32_t) + sizeof(u_int32_t), + __bam_cadjust_desc, pgno, lsn, indx, adjust, opflags)); +} + +static inline int __bam_cadjust_read(ENV *env, + DB **dbpp, void *td, void *data, __bam_cadjust_args **arg) +{ + *arg = NULL; + return (__log_read_record(env, + dbpp, td, data, __bam_cadjust_desc, sizeof(__bam_cadjust_args), (void**)arg)); +} +#define DB___bam_cdel 57 +typedef struct ___bam_cdel_args { + u_int32_t type; + DB_TXN *txnp; + DB_LSN prev_lsn; + int32_t fileid; + db_pgno_t pgno; + DB_LSN lsn; + u_int32_t indx; +} __bam_cdel_args; + +extern __DB_IMPORT DB_LOG_RECSPEC __bam_cdel_desc[]; +static inline int +__bam_cdel_log(DB *dbp, DB_TXN *txnp, DB_LSN *ret_lsnp, u_int32_t flags, db_pgno_t pgno, DB_LSN * lsn, u_int32_t indx) +{ + return (__log_put_record((dbp)->env, dbp, txnp, ret_lsnp, + flags, DB___bam_cdel, 0, + sizeof(u_int32_t) + sizeof(u_int32_t) + sizeof(DB_LSN) + + sizeof(u_int32_t) + sizeof(u_int32_t) + sizeof(*lsn) + + sizeof(u_int32_t), + __bam_cdel_desc, pgno, lsn, indx)); +} + +static inline int __bam_cdel_read(ENV *env, + DB **dbpp, void *td, void *data, __bam_cdel_args **arg) +{ + *arg = NULL; + return (__log_read_record(env, + dbpp, td, data, __bam_cdel_desc, sizeof(__bam_cdel_args), (void**)arg)); +} +#define DB___bam_repl 58 +typedef struct ___bam_repl_args { + u_int32_t type; + DB_TXN *txnp; + DB_LSN prev_lsn; + int32_t fileid; + db_pgno_t pgno; + DB_LSN lsn; + u_int32_t indx; + u_int32_t isdeleted; + DBT orig; + DBT repl; + u_int32_t prefix; + u_int32_t suffix; +} __bam_repl_args; + +extern __DB_IMPORT DB_LOG_RECSPEC __bam_repl_desc[]; +static inline int +__bam_repl_log(DB *dbp, DB_TXN *txnp, DB_LSN *ret_lsnp, u_int32_t flags, db_pgno_t pgno, DB_LSN * lsn, u_int32_t indx, u_int32_t isdeleted, + const DBT *orig, const DBT *repl, u_int32_t prefix, u_int32_t suffix) +{ + return (__log_put_record((dbp)->env, dbp, txnp, ret_lsnp, + flags, DB___bam_repl, 0, + sizeof(u_int32_t) + sizeof(u_int32_t) + sizeof(DB_LSN) + + sizeof(u_int32_t) + sizeof(u_int32_t) + sizeof(*lsn) + + sizeof(u_int32_t) + sizeof(u_int32_t) + LOG_DBT_SIZE(orig) + + LOG_DBT_SIZE(repl) + sizeof(u_int32_t) + sizeof(u_int32_t), + __bam_repl_desc, pgno, lsn, indx, isdeleted, orig, repl, prefix, + suffix)); +} + +static inline int __bam_repl_read(ENV *env, + DB **dbpp, void *td, void *data, __bam_repl_args **arg) +{ + *arg = NULL; + return (__log_read_record(env, + dbpp, td, data, __bam_repl_desc, sizeof(__bam_repl_args), (void**)arg)); +} +#define DB___bam_irep 67 +typedef struct ___bam_irep_args { + u_int32_t type; + DB_TXN *txnp; + DB_LSN prev_lsn; + int32_t fileid; + db_pgno_t pgno; + DB_LSN lsn; + u_int32_t indx; + u_int32_t ptype; + DBT hdr; + DBT data; + DBT old; +} __bam_irep_args; + +extern __DB_IMPORT DB_LOG_RECSPEC __bam_irep_desc[]; +static inline int +__bam_irep_log(DB *dbp, DB_TXN *txnp, DB_LSN *ret_lsnp, u_int32_t flags, db_pgno_t pgno, DB_LSN * lsn, u_int32_t indx, u_int32_t ptype, + const DBT *hdr, const DBT *data, const DBT *old) +{ + return (__log_put_record((dbp)->env, dbp, txnp, ret_lsnp, + flags, DB___bam_irep, 1, + sizeof(u_int32_t) + sizeof(u_int32_t) + sizeof(DB_LSN) + + sizeof(u_int32_t) + sizeof(u_int32_t) + sizeof(*lsn) + + sizeof(u_int32_t) + sizeof(u_int32_t) + LOG_DBT_SIZE(hdr) + + LOG_DBT_SIZE(data) + LOG_DBT_SIZE(old), + __bam_irep_desc, pgno, lsn, indx, ptype, hdr, data, old)); +} + +static inline int __bam_irep_read(ENV *env, + DB **dbpp, void *td, void *data, __bam_irep_args **arg) +{ + *arg = NULL; + return (__log_read_record(env, + dbpp, td, data, __bam_irep_desc, sizeof(__bam_irep_args), (void**)arg)); +} +#define DB___bam_root 59 +typedef struct ___bam_root_args { + u_int32_t type; + DB_TXN *txnp; + DB_LSN prev_lsn; + int32_t fileid; + db_pgno_t meta_pgno; + db_pgno_t root_pgno; + DB_LSN meta_lsn; +} __bam_root_args; + +extern __DB_IMPORT DB_LOG_RECSPEC __bam_root_desc[]; +static inline int +__bam_root_log(DB *dbp, DB_TXN *txnp, DB_LSN *ret_lsnp, u_int32_t flags, db_pgno_t meta_pgno, db_pgno_t root_pgno, DB_LSN * meta_lsn) +{ + return (__log_put_record((dbp)->env, dbp, txnp, ret_lsnp, + flags, DB___bam_root, 0, + sizeof(u_int32_t) + sizeof(u_int32_t) + sizeof(DB_LSN) + + sizeof(u_int32_t) + sizeof(u_int32_t) + sizeof(u_int32_t) + + sizeof(*meta_lsn), + __bam_root_desc, meta_pgno, root_pgno, meta_lsn)); +} + +static inline int __bam_root_read(ENV *env, + DB **dbpp, void *td, void *data, __bam_root_args **arg) +{ + *arg = NULL; + return (__log_read_record(env, + dbpp, td, data, __bam_root_desc, sizeof(__bam_root_args), (void**)arg)); +} +#define DB___bam_curadj 64 +typedef struct ___bam_curadj_args { + u_int32_t type; + DB_TXN *txnp; + DB_LSN prev_lsn; + int32_t fileid; + db_ca_mode mode; + db_pgno_t from_pgno; + db_pgno_t to_pgno; + db_pgno_t left_pgno; + u_int32_t first_indx; + u_int32_t from_indx; + u_int32_t to_indx; +} __bam_curadj_args; + +extern __DB_IMPORT DB_LOG_RECSPEC __bam_curadj_desc[]; +static inline int +__bam_curadj_log(DB *dbp, DB_TXN *txnp, DB_LSN *ret_lsnp, u_int32_t flags, db_ca_mode mode, db_pgno_t from_pgno, db_pgno_t to_pgno, db_pgno_t left_pgno, + u_int32_t first_indx, u_int32_t from_indx, u_int32_t to_indx) +{ + return (__log_put_record((dbp)->env, dbp, txnp, ret_lsnp, + flags, DB___bam_curadj, 0, + sizeof(u_int32_t) + sizeof(u_int32_t) + sizeof(DB_LSN) + + sizeof(u_int32_t) + sizeof(u_int32_t) + sizeof(u_int32_t) + + sizeof(u_int32_t) + sizeof(u_int32_t) + sizeof(u_int32_t) + + sizeof(u_int32_t) + sizeof(u_int32_t), + __bam_curadj_desc, mode, from_pgno, to_pgno, left_pgno, first_indx, from_indx, to_indx)); +} + +static inline int __bam_curadj_read(ENV *env, + DB **dbpp, void *td, void *data, __bam_curadj_args **arg) +{ + *arg = NULL; + return (__log_read_record(env, + dbpp, td, data, __bam_curadj_desc, sizeof(__bam_curadj_args), (void**)arg)); +} +#define DB___bam_rcuradj 65 +typedef struct ___bam_rcuradj_args { + u_int32_t type; + DB_TXN *txnp; + DB_LSN prev_lsn; + int32_t fileid; + ca_recno_arg mode; + db_pgno_t root; + db_recno_t recno; + u_int32_t order; +} __bam_rcuradj_args; + +extern __DB_IMPORT DB_LOG_RECSPEC __bam_rcuradj_desc[]; +static inline int +__bam_rcuradj_log(DB *dbp, DB_TXN *txnp, DB_LSN *ret_lsnp, u_int32_t flags, ca_recno_arg mode, db_pgno_t root, db_recno_t recno, u_int32_t order) +{ + return (__log_put_record((dbp)->env, dbp, txnp, ret_lsnp, + flags, DB___bam_rcuradj, 0, + sizeof(u_int32_t) + sizeof(u_int32_t) + sizeof(DB_LSN) + + sizeof(u_int32_t) + sizeof(u_int32_t) + sizeof(u_int32_t) + + sizeof(u_int32_t) + sizeof(u_int32_t), + __bam_rcuradj_desc, mode, root, recno, order)); +} + +static inline int __bam_rcuradj_read(ENV *env, + DB **dbpp, void *td, void *data, __bam_rcuradj_args **arg) +{ + *arg = NULL; + return (__log_read_record(env, + dbpp, td, data, __bam_rcuradj_desc, sizeof(__bam_rcuradj_args), (void**)arg)); +} +#define DB___bam_relink_43 147 +typedef struct ___bam_relink_43_args { + u_int32_t type; + DB_TXN *txnp; + DB_LSN prev_lsn; + int32_t fileid; + db_pgno_t pgno; + DB_LSN lsn; + db_pgno_t prev; + DB_LSN lsn_prev; + db_pgno_t next; + DB_LSN lsn_next; +} __bam_relink_43_args; + +extern __DB_IMPORT DB_LOG_RECSPEC __bam_relink_43_desc[]; +static inline int __bam_relink_43_read(ENV *env, + DB **dbpp, void *td, void *data, __bam_relink_43_args **arg) +{ + *arg = NULL; + return (__log_read_record(env, + dbpp, td, data, __bam_relink_43_desc, sizeof(__bam_relink_43_args), (void**)arg)); +} +#define DB___bam_merge_44 148 +typedef struct ___bam_merge_44_args { + u_int32_t type; + DB_TXN *txnp; + DB_LSN prev_lsn; + int32_t fileid; + db_pgno_t pgno; + DB_LSN lsn; + db_pgno_t npgno; + DB_LSN nlsn; + DBT hdr; + DBT data; + DBT ind; +} __bam_merge_44_args; + +extern __DB_IMPORT DB_LOG_RECSPEC __bam_merge_44_desc[]; +static inline int __bam_merge_44_read(ENV *env, + DB **dbpp, void *td, void *data, __bam_merge_44_args **arg) +{ + *arg = NULL; + return (__log_read_record(env, + dbpp, td, data, __bam_merge_44_desc, sizeof(__bam_merge_44_args), (void**)arg)); +} +#endif diff -r 000000000000 -r a1985f14b030 src/dbinc_auto/btree_ext.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/dbinc_auto/btree_ext.h Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,173 @@ +/* DO NOT EDIT: automatically built by dist/s_include. + * + * Copyright (c) 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ +#ifndef _btree_ext_h_ +#define _btree_ext_h_ + +#if defined(__cplusplus) +extern "C" { +#endif + +int __bam_compact_int __P((DBC *, DBT *, DBT *, u_int32_t, int *, DB_COMPACT *, int *)); +int __bam_compact_opd __P((DBC *, db_pgno_t, PAGE **, u_int32_t, DB_COMPACT *, int *)); +int __bam_truncate_ipages __P((DB *, DB_THREAD_INFO *, DB_TXN *, DB_COMPACT *)); +int __bam_cmp __P((DBC *, const DBT *, PAGE *, u_int32_t, int (*)(DB *, const DBT *, const DBT *), int *)); +int __bam_defcmp __P((DB *, const DBT *, const DBT *)); +size_t __bam_defpfx __P((DB *, const DBT *, const DBT *)); +int __bam_compress_dupcmp __P((DB *, const DBT *, const DBT *)); +int __bam_defcompress __P((DB *, const DBT *, const DBT *, const DBT *, const DBT *, DBT *)); +int __bam_defdecompress __P((DB *, const DBT *, const DBT *, DBT *, DBT *, DBT *)); +int __bamc_compress_get __P((DBC *, DBT *, DBT *, u_int32_t)); +int __bamc_compress_put __P((DBC *, DBT *, DBT *, u_int32_t)); +int __bamc_compress_del __P((DBC *, u_int32_t)); +int __bamc_compress_bulk_del __P((DBC *, DBT *, u_int32_t)); +int __bamc_compress_count __P((DBC *, db_recno_t *)); +int __bamc_compress_cmp __P((DBC *, DBC *, int *)); +int __bamc_compress_dup __P((DBC *, DBC *, u_int32_t)); +int __bam_compress_salvage __P((DB *, VRFY_DBINFO *, void *, int (*)(void *, const void *), DBT *, DBT *)); +int __bam_compress_count __P((DBC *, u_int32_t *, u_int32_t *)); +int __bam_pgin __P((DB *, db_pgno_t, void *, DBT *)); +int __bam_pgout __P((DB *, db_pgno_t, void *, DBT *)); +int __bam_mswap __P((ENV *, PAGE *)); +int __bam_ca_delete __P((DB *, db_pgno_t, u_int32_t, int, u_int32_t *)); +int __ram_ca_delete __P((DB *, db_pgno_t, u_int32_t *)); +int __bam_ca_di __P((DBC *, db_pgno_t, u_int32_t, int)); +int __bam_ca_dup __P((DBC *, u_int32_t, db_pgno_t, u_int32_t, db_pgno_t, u_int32_t)); +int __bam_ca_undodup __P((DB *, u_int32_t, db_pgno_t, u_int32_t, u_int32_t)); +int __bam_ca_rsplit __P((DBC *, db_pgno_t, db_pgno_t)); +int __bam_ca_split __P((DBC *, db_pgno_t, db_pgno_t, db_pgno_t, u_int32_t, int)); +int __bam_ca_undosplit __P((DB *, db_pgno_t, db_pgno_t, db_pgno_t, u_int32_t)); +int __bamc_init __P((DBC *, DBTYPE)); +int __bamc_refresh __P((DBC *)); +int __bamc_cmp __P((DBC *, DBC *, int *)); +int __bamc_count __P((DBC *, db_recno_t *)); +int __bamc_dup __P((DBC *, DBC *, u_int32_t)); +int __bam_bulk_overflow __P((DBC *, u_int32_t, db_pgno_t, u_int8_t *)); +int __bam_bulk_duplicates __P((DBC *, db_pgno_t, u_int8_t *, int32_t *, int32_t **, u_int8_t **, u_int32_t *, int)); +int __bamc_rget __P((DBC *, DBT *)); +int __bam_opd_exists __P((DBC *, db_pgno_t)); +int __bam_ditem __P((DBC *, PAGE *, u_int32_t)); +int __bam_adjindx __P((DBC *, PAGE *, u_int32_t, u_int32_t, int)); +int __bam_dpages __P((DBC *, int, int)); +int __bam_pupdate __P((DBC *, PAGE *)); +int __bam_db_create __P((DB *)); +int __bam_db_close __P((DB *)); +void __bam_map_flags __P((DB *, u_int32_t *, u_int32_t *)); +int __bam_set_flags __P((DB *, u_int32_t *flagsp)); +int __bam_set_bt_compare __P((DB *, int (*)(DB *, const DBT *, const DBT *))); +int __bam_set_bt_compress __P((DB *, int (*)(DB *, const DBT *, const DBT *, const DBT *, const DBT *, DBT *), int (*)(DB *, const DBT *, const DBT *, DBT *, DBT *, DBT *))); +int __bam_get_bt_minkey __P((DB *, u_int32_t *)); +void __bam_copy_config __P((DB *, DB*, u_int32_t)); +void __ram_map_flags __P((DB *, u_int32_t *, u_int32_t *)); +int __ram_set_flags __P((DB *, u_int32_t *flagsp)); +int __ram_get_re_len __P((DB *, u_int32_t *)); +int __ram_get_re_pad __P((DB *, int *)); +int __bam_open __P((DB *, DB_THREAD_INFO *, DB_TXN *, const char *, db_pgno_t, u_int32_t)); +int __bam_metachk __P((DB *, const char *, BTMETA *)); +int __bam_read_root __P((DB *, DB_THREAD_INFO *, DB_TXN *, db_pgno_t, u_int32_t)); +int __bam_new_file __P((DB *, DB_THREAD_INFO *, DB_TXN *, DB_FH *, const char *)); +int __bam_new_subdb __P((DB *, DB *, DB_THREAD_INFO *, DB_TXN *)); +int __bam_iitem __P((DBC *, DBT *, DBT *, u_int32_t, u_int32_t)); +int __bam_ritem __P((DBC *, PAGE *, u_int32_t, DBT *, u_int32_t)); +int __bam_ritem_nolog __P((DBC *, PAGE *, u_int32_t, DBT *, DBT *, u_int32_t)); +int __bam_irep __P((DBC *, PAGE *, u_int32_t, DBT *, DBT *)); +int __bam_split_recover __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __bam_split_48_recover __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __bam_split_42_recover __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __bam_rsplit_recover __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __bam_adj_recover __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __bam_cadjust_recover __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __bam_cdel_recover __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __bam_repl_recover __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __bam_irep_recover __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __bam_root_recover __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __bam_curadj_recover __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __bam_rcuradj_recover __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __bam_merge_44_recover __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __bam_relink_43_recover __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __bam_reclaim __P((DB *, DB_THREAD_INFO *, DB_TXN *, u_int32_t)); +int __bam_truncate __P((DBC *, u_int32_t *)); +int __ram_open __P((DB *, DB_THREAD_INFO *, DB_TXN *, const char *, db_pgno_t, u_int32_t)); +int __ram_append __P((DBC *, DBT *, DBT *)); +int __ramc_del __P((DBC *, u_int32_t)); +int __ramc_get __P((DBC *, DBT *, DBT *, u_int32_t, db_pgno_t *)); +int __ramc_put __P((DBC *, DBT *, DBT *, u_int32_t, db_pgno_t *)); +int __ram_ca __P((DBC *, ca_recno_arg, int *)); +int __ram_getno __P((DBC *, const DBT *, db_recno_t *, int)); +int __ram_writeback __P((DB *)); +int __bam_rsearch __P((DBC *, db_recno_t *, u_int32_t, int, int *)); +int __bam_adjust __P((DBC *, int32_t)); +int __bam_nrecs __P((DBC *, db_recno_t *)); +db_recno_t __bam_total __P((DB *, PAGE *)); +int __bam_get_root __P((DBC *, db_pgno_t, int, u_int32_t, int *)); +int __bam_search __P((DBC *, db_pgno_t, const DBT *, u_int32_t, int, db_recno_t *, int *)); +int __bam_stkrel __P((DBC *, u_int32_t)); +int __bam_stkgrow __P((ENV *, BTREE_CURSOR *)); +int __bam_split __P((DBC *, void *, db_pgno_t *)); +int __bam_broot __P((DBC *, PAGE *, u_int32_t, PAGE *, PAGE *)); +int __ram_root __P((DBC *, PAGE *, PAGE *, PAGE *)); +int __bam_pinsert __P((DBC *, EPG *, u_int32_t, PAGE *, PAGE *, int)); +int __bam_copy __P((DB *, PAGE *, PAGE *, u_int32_t, u_int32_t)); +int __bam_stat __P((DBC *, void *, u_int32_t)); +int __bam_stat_print __P((DBC *, u_int32_t)); +int __bam_stat_callback __P((DBC *, PAGE *, void *, int *)); +void __bam_print_cursor __P((DBC *)); +int __bam_key_range __P((DBC *, DBT *, DB_KEY_RANGE *, u_int32_t)); +int __bam_traverse __P((DBC *, db_lockmode_t, db_pgno_t, int (*)(DBC *, PAGE *, void *, int *), void *)); +int __bam_30_btreemeta __P((DB *, char *, u_int8_t *)); +int __bam_31_btreemeta __P((DB *, char *, u_int32_t, DB_FH *, PAGE *, int *)); +int __bam_31_lbtree __P((DB *, char *, u_int32_t, DB_FH *, PAGE *, int *)); +int __bam_vrfy_meta __P((DB *, VRFY_DBINFO *, BTMETA *, db_pgno_t, u_int32_t)); +int __ram_vrfy_leaf __P((DB *, VRFY_DBINFO *, PAGE *, db_pgno_t, u_int32_t)); +int __bam_vrfy __P((DB *, VRFY_DBINFO *, PAGE *, db_pgno_t, u_int32_t)); +int __bam_vrfy_itemorder __P((DB *, VRFY_DBINFO *, DB_THREAD_INFO *, PAGE *, db_pgno_t, u_int32_t, int, int, u_int32_t)); +int __bam_vrfy_structure __P((DB *, VRFY_DBINFO *, db_pgno_t, void *, void *, u_int32_t)); +int __bam_vrfy_subtree __P((DB *, VRFY_DBINFO *, db_pgno_t, void *, void *, u_int32_t, u_int32_t *, u_int32_t *, u_int32_t *)); +int __bam_salvage __P((DB *, VRFY_DBINFO *, db_pgno_t, u_int32_t, PAGE *, void *, int (*)(void *, const void *), DBT *, u_int32_t)); +int __bam_salvage_walkdupint __P((DB *, VRFY_DBINFO *, PAGE *, DBT *, void *, int (*)(void *, const void *), u_int32_t)); +int __bam_meta2pgset __P((DB *, VRFY_DBINFO *, BTMETA *, u_int32_t, DB *)); +int __bam_init_recover __P((ENV *, DB_DISTAB *)); +int __bam_split_print __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __bam_split_48_print __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __bam_split_42_print __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __bam_rsplit_print __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __bam_adj_print __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __bam_cadjust_print __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __bam_cdel_print __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __bam_repl_print __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __bam_irep_print __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __bam_root_print __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __bam_curadj_print __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __bam_rcuradj_print __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __bam_relink_43_print __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __bam_merge_44_print __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __bam_init_print __P((ENV *, DB_DISTAB *)); + +#if defined(__cplusplus) +} +#endif +#endif /* !_btree_ext_h_ */ diff -r 000000000000 -r a1985f14b030 src/dbinc_auto/clib_ext.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/dbinc_auto/clib_ext.h Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,139 @@ +/* DO NOT EDIT: automatically built by dist/s_include. + * + * Copyright (c) 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ +#ifndef _clib_ext_h_ +#define _clib_ext_h_ + +#if defined(__cplusplus) +extern "C" { +#endif + +#ifndef HAVE_ATOI +int atoi __P((const char *)); +#endif +#ifndef HAVE_ATOL +long atol __P((const char *)); +#endif +#ifndef HAVE_BSEARCH +void *bsearch __P((const void *, const void *, size_t, size_t, int (*)(const void *, const void *))); +#endif +#ifndef HAVE_GETCWD +char *getcwd __P((char *, size_t)); +#endif +#ifndef HAVE_GETOPT +int getopt __P((int, char * const *, const char *)); +#endif +#ifndef HAVE_ISALPHA +int isalpha __P((int)); +#endif +#ifndef HAVE_ISDIGIT +int isdigit __P((int)); +#endif +#ifndef HAVE_ISPRINT +int isprint __P((int)); +#endif +#ifndef HAVE_ISSPACE +int isspace __P((int)); +#endif +#ifndef HAVE_MEMCMP +int memcmp __P((const void *, const void *, size_t)); +#endif +#ifndef HAVE_MEMCPY +void *memcpy __P((void *, const void *, size_t)); +#endif +#ifndef HAVE_MEMMOVE +void *memmove __P((void *, const void *, size_t)); +#endif +#ifndef HAVE_PRINTF +int printf __P((const char *, ...)); +#endif +#ifndef HAVE_PRINTF +int fprintf __P((FILE *, const char *, ...)); +#endif +#ifndef HAVE_PRINTF +int vfprintf __P((FILE *, const char *, va_list)); +#endif +#ifndef HAVE_QSORT +void qsort __P((void *, size_t, size_t, int(*)(const void *, const void *))); +#endif +#ifndef HAVE_RAISE +int raise __P((int)); +#endif +#ifndef HAVE_RAND +int rand __P((void)); +void srand __P((unsigned int)); +#endif +#ifndef HAVE_SNPRINTF +int snprintf __P((char *, size_t, const char *, ...)); +#endif +#ifndef HAVE_VSNPRINTF +int vsnprintf __P((char *, size_t, const char *, va_list)); +#endif +#ifndef HAVE_STRCASECMP +int strcasecmp __P((const char *, const char *)); +#endif +#ifndef HAVE_STRCASECMP +int strncasecmp __P((const char *, const char *, size_t)); +#endif +#ifndef HAVE_STRCAT +char *strcat __P((char *, const char *)); +#endif +#ifndef HAVE_STRCHR +char *strchr __P((const char *, int)); +#endif +#ifndef HAVE_STRDUP +char *strdup __P((const char *)); +#endif +#ifndef HAVE_STRERROR +char *strerror __P((int)); +#endif +#ifndef HAVE_STRNCAT +char *strncat __P((char *, const char *, size_t)); +#endif +#ifndef HAVE_STRNCMP +int strncmp __P((const char *, const char *, size_t)); +#endif +#ifndef HAVE_STRRCHR +char *strrchr __P((const char *, int)); +#endif +#ifndef HAVE_STRSEP +char *strsep __P((char **, const char *)); +#endif +#ifndef HAVE_STRTOL +long strtol __P((const char *, char **, int)); +#endif +#ifndef HAVE_STRTOUL +unsigned long strtoul __P((const char *, char **, int)); +#endif +#ifndef HAVE_TIME +time_t time __P((time_t *)); +#endif + +#if defined(__cplusplus) +} +#endif +#endif /* !_clib_ext_h_ */ diff -r 000000000000 -r a1985f14b030 src/dbinc_auto/common_ext.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/dbinc_auto/common_ext.h Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,99 @@ +/* DO NOT EDIT: automatically built by dist/s_include. + * + * Copyright (c) 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ +#ifndef _common_ext_h_ +#define _common_ext_h_ + +#if defined(__cplusplus) +extern "C" { +#endif + +void __clock_set_expires __P((ENV *, db_timespec *, db_timeout_t)); +int __clock_expired __P((ENV *, db_timespec *, db_timespec *)); +int __crypto_region_init __P((ENV *)); +int __db_isbigendian __P((void)); +int __db_byteorder __P((ENV *, int)); +u_int32_t __db_compress_count_int __P((u_int64_t)); +int __db_compress_int __P((u_int8_t *, u_int64_t)); +u_int32_t __db_decompress_count_int __P((const u_int8_t *)); +int __db_decompress_int __P((const u_int8_t *, u_int64_t *)); +int __db_decompress_int32 __P((const u_int8_t *, u_int32_t *)); +int __db_fchk __P((ENV *, const char *, u_int32_t, u_int32_t)); +int __db_fcchk __P((ENV *, const char *, u_int32_t, u_int32_t, u_int32_t)); +int __db_ferr __P((const ENV *, const char *, int)); +int __db_fnl __P((const ENV *, const char *)); +int __db_pgerr __P((DB *, db_pgno_t, int)); +int __db_pgfmt __P((ENV *, db_pgno_t)); +#ifdef DIAGNOSTIC +void __db_assert __P((ENV *, const char *, const char *, int)); +#endif +int __env_panic_msg __P((ENV *)); +int __env_panic __P((ENV *, int)); +char *__db_unknown_error __P((int)); +void __db_syserr __P((const ENV *, int, const char *, ...)) __attribute__ ((__format__ (__printf__, 3, 4))); +void __db_err __P((const ENV *, int, const char *, ...)) __attribute__ ((__format__ (__printf__, 3, 4))); +void __db_errx __P((const ENV *, const char *, ...)) __attribute__ ((__format__ (__printf__, 2, 3))); +void __db_errcall __P((const DB_ENV *, int, db_error_set_t, const char *, va_list)); +void __db_errfile __P((const DB_ENV *, int, db_error_set_t, const char *, va_list)); +void __db_msgadd __P((ENV *, DB_MSGBUF *, const char *, ...)) __attribute__ ((__format__ (__printf__, 3, 4))); +void __db_msgadd_ap __P((ENV *, DB_MSGBUF *, const char *, va_list)); +void __db_msg __P((const ENV *, const char *, ...)) __attribute__ ((__format__ (__printf__, 2, 3))); +void __db_repmsg __P((const ENV *, const char *, ...)) __attribute__ ((__format__ (__printf__, 2, 3))); +int __db_unknown_flag __P((ENV *, char *, u_int32_t)); +int __db_unknown_type __P((ENV *, char *, DBTYPE)); +int __db_unknown_path __P((ENV *, char *)); +int __db_not_txn_env __P((ENV *)); +int __db_rec_toobig __P((ENV *, u_int32_t, u_int32_t)); +int __db_rec_repl __P((ENV *, u_int32_t, u_int32_t)); +int __dbc_logging __P((DBC *)); +int __db_check_lsn __P((ENV *, DB_LSN *, DB_LSN *)); +int __db_rdonly __P((const ENV *, const char *)); +int __db_space_err __P((const DB *)); +int __db_failed __P((const ENV *, const char *, pid_t, db_threadid_t)); +int __db_getlong __P((DB_ENV *, const char *, char *, long, long, long *)); +int __db_getulong __P((DB_ENV *, const char *, char *, u_long, u_long, u_long *)); +void __db_idspace __P((u_int32_t *, int, u_int32_t *, u_int32_t *)); +u_int32_t __db_log2 __P((u_int32_t)); +u_int32_t __db_tablesize __P((u_int32_t)); +void __db_hashinit __P((void *, u_int32_t)); +int __dbt_usercopy __P((ENV *, DBT *)); +void __dbt_userfree __P((ENV *, DBT *, DBT *, DBT *)); +int __db_mkpath __P((ENV *, const char *)); +u_int32_t __db_openflags __P((int)); +int __db_util_arg __P((char *, char *, int *, char ***)); +int __db_util_cache __P((DB *, u_int32_t *, int *)); +int __db_util_logset __P((const char *, char *)); +void __db_util_siginit __P((void)); +int __db_util_interrupted __P((void)); +void __db_util_sigresend __P((void)); +int __db_zero_fill __P((ENV *, DB_FH *)); +int __db_zero_extend __P((ENV *, DB_FH *, db_pgno_t, db_pgno_t, u_int32_t)); + +#if defined(__cplusplus) +} +#endif +#endif /* !_common_ext_h_ */ diff -r 000000000000 -r a1985f14b030 src/dbinc_auto/crdel_auto.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/dbinc_auto/crdel_auto.h Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,152 @@ +/* Do not edit: automatically built by gen_rec.awk. + * + * Copyright (c) 2012 Oracle and/or its affiliates. All rights reserved. * + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +#ifndef __crdel_AUTO_H +#define __crdel_AUTO_H +#include "dbinc/log.h" +#define DB___crdel_metasub 142 +typedef struct ___crdel_metasub_args { + u_int32_t type; + DB_TXN *txnp; + DB_LSN prev_lsn; + int32_t fileid; + db_pgno_t pgno; + DBT page; + DB_LSN lsn; +} __crdel_metasub_args; + +extern __DB_IMPORT DB_LOG_RECSPEC __crdel_metasub_desc[]; +static inline int +__crdel_metasub_log(DB *dbp, DB_TXN *txnp, DB_LSN *ret_lsnp, u_int32_t flags, db_pgno_t pgno, const DBT *page, DB_LSN * lsn) +{ + return (__log_put_record((dbp)->env, dbp, txnp, ret_lsnp, + flags, DB___crdel_metasub, 0, + sizeof(u_int32_t) + sizeof(u_int32_t) + sizeof(DB_LSN) + + sizeof(u_int32_t) + sizeof(u_int32_t) + LOG_DBT_SIZE(page) + + sizeof(*lsn), + __crdel_metasub_desc, pgno, page, lsn)); +} + +static inline int __crdel_metasub_read(ENV *env, + DB **dbpp, void *td, void *data, __crdel_metasub_args **arg) +{ + *arg = NULL; + return (__log_read_record(env, + dbpp, td, data, __crdel_metasub_desc, sizeof(__crdel_metasub_args), (void**)arg)); +} +#define DB___crdel_inmem_create 138 +typedef struct ___crdel_inmem_create_args { + u_int32_t type; + DB_TXN *txnp; + DB_LSN prev_lsn; + int32_t fileid; + DBT name; + DBT fid; + u_int32_t pgsize; +} __crdel_inmem_create_args; + +extern __DB_IMPORT DB_LOG_RECSPEC __crdel_inmem_create_desc[]; +static inline int +__crdel_inmem_create_log(ENV *env, DB_TXN *txnp, DB_LSN *ret_lsnp, u_int32_t flags, + int32_t fileid, const DBT *name, const DBT *fid, u_int32_t pgsize) +{ + return (__log_put_record(env, NULL, txnp, ret_lsnp, + flags, DB___crdel_inmem_create, 0, + sizeof(u_int32_t) + sizeof(u_int32_t) + sizeof(DB_LSN) + + sizeof(u_int32_t) + LOG_DBT_SIZE(name) + LOG_DBT_SIZE(fid) + + sizeof(u_int32_t), + __crdel_inmem_create_desc, + fileid, name, fid, pgsize)); +} + +static inline int __crdel_inmem_create_read(ENV *env, + void *data, __crdel_inmem_create_args **arg) +{ + *arg = NULL; + return (__log_read_record(env, + NULL, NULL, data, __crdel_inmem_create_desc, sizeof(__crdel_inmem_create_args), (void**)arg)); +} +#define DB___crdel_inmem_rename 139 +typedef struct ___crdel_inmem_rename_args { + u_int32_t type; + DB_TXN *txnp; + DB_LSN prev_lsn; + DBT oldname; + DBT newname; + DBT fid; +} __crdel_inmem_rename_args; + +extern __DB_IMPORT DB_LOG_RECSPEC __crdel_inmem_rename_desc[]; +static inline int +__crdel_inmem_rename_log(ENV *env, DB_TXN *txnp, DB_LSN *ret_lsnp, u_int32_t flags, + const DBT *oldname, const DBT *newname, const DBT *fid) +{ + return (__log_put_record(env, NULL, txnp, ret_lsnp, + flags, DB___crdel_inmem_rename, 0, + sizeof(u_int32_t) + sizeof(u_int32_t) + sizeof(DB_LSN) + + LOG_DBT_SIZE(oldname) + LOG_DBT_SIZE(newname) + LOG_DBT_SIZE(fid), + __crdel_inmem_rename_desc, + oldname, newname, fid)); +} + +static inline int __crdel_inmem_rename_read(ENV *env, + void *data, __crdel_inmem_rename_args **arg) +{ + *arg = NULL; + return (__log_read_record(env, + NULL, NULL, data, __crdel_inmem_rename_desc, sizeof(__crdel_inmem_rename_args), (void**)arg)); +} +#define DB___crdel_inmem_remove 140 +typedef struct ___crdel_inmem_remove_args { + u_int32_t type; + DB_TXN *txnp; + DB_LSN prev_lsn; + DBT name; + DBT fid; +} __crdel_inmem_remove_args; + +extern __DB_IMPORT DB_LOG_RECSPEC __crdel_inmem_remove_desc[]; +static inline int +__crdel_inmem_remove_log(ENV *env, DB_TXN *txnp, DB_LSN *ret_lsnp, u_int32_t flags, + const DBT *name, const DBT *fid) +{ + return (__log_put_record(env, NULL, txnp, ret_lsnp, + flags, DB___crdel_inmem_remove, 0, + sizeof(u_int32_t) + sizeof(u_int32_t) + sizeof(DB_LSN) + + LOG_DBT_SIZE(name) + LOG_DBT_SIZE(fid), + __crdel_inmem_remove_desc, + name, fid)); +} + +static inline int __crdel_inmem_remove_read(ENV *env, + void *data, __crdel_inmem_remove_args **arg) +{ + *arg = NULL; + return (__log_read_record(env, + NULL, NULL, data, __crdel_inmem_remove_desc, sizeof(__crdel_inmem_remove_args), (void**)arg)); +} +#endif diff -r 000000000000 -r a1985f14b030 src/dbinc_auto/crypto_ext.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/dbinc_auto/crypto_ext.h Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,64 @@ +/* DO NOT EDIT: automatically built by dist/s_include. + * + * Copyright (c) 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ +#ifndef _crypto_ext_h_ +#define _crypto_ext_h_ + +#if defined(__cplusplus) +extern "C" { +#endif + +int __aes_setup __P((ENV *, DB_CIPHER *)); +u_int __aes_adj_size __P((size_t)); +int __aes_close __P((ENV *, void *)); +int __aes_decrypt __P((ENV *, void *, void *, u_int8_t *, size_t)); +int __aes_encrypt __P((ENV *, void *, void *, u_int8_t *, size_t)); +int __aes_init __P((ENV *, DB_CIPHER *)); +int __crypto_env_close __P((ENV *)); +int __crypto_env_refresh __P((ENV *)); +int __crypto_algsetup __P((ENV *, DB_CIPHER *, u_int32_t, int)); +int __crypto_decrypt_meta __P((ENV *, DB *, u_int8_t *, int)); +int __crypto_set_passwd __P((ENV *, ENV *)); +int __db_generate_iv __P((ENV *, u_int32_t *)); +int __db_rijndaelKeySetupEnc __P((u32 *, const u8 *, int)); +int __db_rijndaelKeySetupDec __P((u32 *, const u8 *, int)); +void __db_rijndaelEncrypt __P((u32 *, int, const u8 *, u8 *)); +void __db_rijndaelDecrypt __P((u32 *, int, const u8 *, u8 *)); +void __db_rijndaelEncryptRound __P((const u32 *, int, u8 *, int)); +void __db_rijndaelDecryptRound __P((const u32 *, int, u8 *, int)); +int __db_makeKey __P((keyInstance *, int, int, char *)); +int __db_cipherInit __P((cipherInstance *, int, char *)); +int __db_blockEncrypt __P((cipherInstance *, keyInstance *, u_int8_t *, size_t, u_int8_t *)); +int __db_padEncrypt __P((cipherInstance *, keyInstance *, u_int8_t *, int, u_int8_t *)); +int __db_blockDecrypt __P((cipherInstance *, keyInstance *, u_int8_t *, size_t, u_int8_t *)); +int __db_padDecrypt __P((cipherInstance *, keyInstance *, u_int8_t *, int, u_int8_t *)); +int __db_cipherUpdateRounds __P((cipherInstance *, keyInstance *, u_int8_t *, int, u_int8_t *, int)); + +#if defined(__cplusplus) +} +#endif +#endif /* !_crypto_ext_h_ */ diff -r 000000000000 -r a1985f14b030 src/dbinc_auto/db_auto.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/dbinc_auto/db_auto.h Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,691 @@ +/* Do not edit: automatically built by gen_rec.awk. + * + * Copyright (c) 2012 Oracle and/or its affiliates. All rights reserved. * + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +#ifndef __db_AUTO_H +#define __db_AUTO_H +#include "dbinc/log.h" +#define DB___db_addrem 41 +typedef struct ___db_addrem_args { + u_int32_t type; + DB_TXN *txnp; + DB_LSN prev_lsn; + u_int32_t opcode; + int32_t fileid; + db_pgno_t pgno; + u_int32_t indx; + u_int32_t nbytes; + DBT hdr; + DBT dbt; + DB_LSN pagelsn; +} __db_addrem_args; + +extern __DB_IMPORT DB_LOG_RECSPEC __db_addrem_desc[]; +static inline int +__db_addrem_log(DB *dbp, DB_TXN *txnp, DB_LSN *ret_lsnp, u_int32_t flags, + u_int32_t opcode, db_pgno_t pgno, u_int32_t indx, u_int32_t nbytes, + const DBT *hdr, const DBT *dbt, DB_LSN * pagelsn) +{ + return (__log_put_record((dbp)->env, dbp, txnp, ret_lsnp, + flags, DB___db_addrem, 0, + sizeof(u_int32_t) + sizeof(u_int32_t) + sizeof(DB_LSN) + + sizeof(u_int32_t) + sizeof(u_int32_t) + sizeof(u_int32_t) + + sizeof(u_int32_t) + sizeof(u_int32_t) + LOG_DBT_SIZE(hdr) + + LOG_DBT_SIZE(dbt) + sizeof(*pagelsn), + __db_addrem_desc, + opcode, pgno, indx, nbytes, hdr, dbt, pagelsn)); +} + +static inline int __db_addrem_read(ENV *env, + DB **dbpp, void *td, void *data, __db_addrem_args **arg) +{ + *arg = NULL; + return (__log_read_record(env, + dbpp, td, data, __db_addrem_desc, sizeof(__db_addrem_args), (void**)arg)); +} +#define DB___db_addrem_42 41 +typedef struct ___db_addrem_42_args { + u_int32_t type; + DB_TXN *txnp; + DB_LSN prev_lsn; + u_int32_t opcode; + int32_t fileid; + db_pgno_t pgno; + u_int32_t indx; + u_int32_t nbytes; + DBT hdr; + DBT dbt; + DB_LSN pagelsn; +} __db_addrem_42_args; + +extern __DB_IMPORT DB_LOG_RECSPEC __db_addrem_42_desc[]; +static inline int __db_addrem_42_read(ENV *env, + DB **dbpp, void *td, void *data, __db_addrem_42_args **arg) +{ + *arg = NULL; + return (__log_read_record(env, + dbpp, td, data, __db_addrem_42_desc, sizeof(__db_addrem_42_args), (void**)arg)); +} +#define DB___db_big 43 +typedef struct ___db_big_args { + u_int32_t type; + DB_TXN *txnp; + DB_LSN prev_lsn; + u_int32_t opcode; + int32_t fileid; + db_pgno_t pgno; + db_pgno_t prev_pgno; + db_pgno_t next_pgno; + DBT dbt; + DB_LSN pagelsn; + DB_LSN prevlsn; + DB_LSN nextlsn; +} __db_big_args; + +extern __DB_IMPORT DB_LOG_RECSPEC __db_big_desc[]; +static inline int +__db_big_log(DB *dbp, DB_TXN *txnp, DB_LSN *ret_lsnp, u_int32_t flags, + u_int32_t opcode, db_pgno_t pgno, db_pgno_t prev_pgno, db_pgno_t next_pgno, + const DBT *dbt, DB_LSN * pagelsn, DB_LSN * prevlsn, DB_LSN * nextlsn) +{ + return (__log_put_record((dbp)->env, dbp, txnp, ret_lsnp, + flags, DB___db_big, 0, + sizeof(u_int32_t) + sizeof(u_int32_t) + sizeof(DB_LSN) + + sizeof(u_int32_t) + sizeof(u_int32_t) + sizeof(u_int32_t) + + sizeof(u_int32_t) + sizeof(u_int32_t) + LOG_DBT_SIZE(dbt) + + sizeof(*pagelsn) + sizeof(*prevlsn) + sizeof(*nextlsn), + __db_big_desc, + opcode, pgno, prev_pgno, next_pgno, dbt, pagelsn, prevlsn, + nextlsn)); +} + +static inline int __db_big_read(ENV *env, + DB **dbpp, void *td, void *data, __db_big_args **arg) +{ + *arg = NULL; + return (__log_read_record(env, + dbpp, td, data, __db_big_desc, sizeof(__db_big_args), (void**)arg)); +} +#define DB___db_big_42 43 +typedef struct ___db_big_42_args { + u_int32_t type; + DB_TXN *txnp; + DB_LSN prev_lsn; + u_int32_t opcode; + int32_t fileid; + db_pgno_t pgno; + db_pgno_t prev_pgno; + db_pgno_t next_pgno; + DBT dbt; + DB_LSN pagelsn; + DB_LSN prevlsn; + DB_LSN nextlsn; +} __db_big_42_args; + +extern __DB_IMPORT DB_LOG_RECSPEC __db_big_42_desc[]; +static inline int __db_big_42_read(ENV *env, + DB **dbpp, void *td, void *data, __db_big_42_args **arg) +{ + *arg = NULL; + return (__log_read_record(env, + dbpp, td, data, __db_big_42_desc, sizeof(__db_big_42_args), (void**)arg)); +} +#define DB___db_ovref 44 +typedef struct ___db_ovref_args { + u_int32_t type; + DB_TXN *txnp; + DB_LSN prev_lsn; + int32_t fileid; + db_pgno_t pgno; + int32_t adjust; + DB_LSN lsn; +} __db_ovref_args; + +extern __DB_IMPORT DB_LOG_RECSPEC __db_ovref_desc[]; +static inline int +__db_ovref_log(DB *dbp, DB_TXN *txnp, DB_LSN *ret_lsnp, u_int32_t flags, db_pgno_t pgno, int32_t adjust, DB_LSN * lsn) +{ + return (__log_put_record((dbp)->env, dbp, txnp, ret_lsnp, + flags, DB___db_ovref, 0, + sizeof(u_int32_t) + sizeof(u_int32_t) + sizeof(DB_LSN) + + sizeof(u_int32_t) + sizeof(u_int32_t) + sizeof(u_int32_t) + + sizeof(*lsn), + __db_ovref_desc, pgno, adjust, lsn)); +} + +static inline int __db_ovref_read(ENV *env, + DB **dbpp, void *td, void *data, __db_ovref_args **arg) +{ + *arg = NULL; + return (__log_read_record(env, + dbpp, td, data, __db_ovref_desc, sizeof(__db_ovref_args), (void**)arg)); +} +#define DB___db_relink_42 45 +typedef struct ___db_relink_42_args { + u_int32_t type; + DB_TXN *txnp; + DB_LSN prev_lsn; + u_int32_t opcode; + int32_t fileid; + db_pgno_t pgno; + DB_LSN lsn; + db_pgno_t prev; + DB_LSN lsn_prev; + db_pgno_t next; + DB_LSN lsn_next; +} __db_relink_42_args; + +extern __DB_IMPORT DB_LOG_RECSPEC __db_relink_42_desc[]; +static inline int __db_relink_42_read(ENV *env, + DB **dbpp, void *td, void *data, __db_relink_42_args **arg) +{ + *arg = NULL; + return (__log_read_record(env, + dbpp, td, data, __db_relink_42_desc, sizeof(__db_relink_42_args), (void**)arg)); +} +#define DB___db_debug 47 +typedef struct ___db_debug_args { + u_int32_t type; + DB_TXN *txnp; + DB_LSN prev_lsn; + DBT op; + int32_t fileid; + DBT key; + DBT data; + u_int32_t arg_flags; +} __db_debug_args; + +extern __DB_IMPORT DB_LOG_RECSPEC __db_debug_desc[]; +static inline int +__db_debug_log(ENV *env, DB_TXN *txnp, DB_LSN *ret_lsnp, u_int32_t flags, + const DBT *op, int32_t fileid, const DBT *key, const DBT *data, u_int32_t arg_flags) +{ + return (__log_put_record(env, NULL, txnp, ret_lsnp, + flags, DB___db_debug, 0, + sizeof(u_int32_t) + sizeof(u_int32_t) + sizeof(DB_LSN) + + LOG_DBT_SIZE(op) + sizeof(u_int32_t) + LOG_DBT_SIZE(key) + + LOG_DBT_SIZE(data) + sizeof(u_int32_t), + __db_debug_desc, + op, fileid, key, data, arg_flags)); +} + +static inline int __db_debug_read(ENV *env, + void *data, __db_debug_args **arg) +{ + *arg = NULL; + return (__log_read_record(env, + NULL, NULL, data, __db_debug_desc, sizeof(__db_debug_args), (void**)arg)); +} +#define DB___db_noop 48 +typedef struct ___db_noop_args { + u_int32_t type; + DB_TXN *txnp; + DB_LSN prev_lsn; + int32_t fileid; + db_pgno_t pgno; + DB_LSN prevlsn; +} __db_noop_args; + +extern __DB_IMPORT DB_LOG_RECSPEC __db_noop_desc[]; +static inline int +__db_noop_log(DB *dbp, DB_TXN *txnp, DB_LSN *ret_lsnp, u_int32_t flags, db_pgno_t pgno, DB_LSN * prevlsn) +{ + return (__log_put_record((dbp)->env, dbp, txnp, ret_lsnp, + flags, DB___db_noop, 0, + sizeof(u_int32_t) + sizeof(u_int32_t) + sizeof(DB_LSN) + + sizeof(u_int32_t) + sizeof(u_int32_t) + sizeof(*prevlsn), + __db_noop_desc, pgno, prevlsn)); +} + +static inline int __db_noop_read(ENV *env, + DB **dbpp, void *td, void *data, __db_noop_args **arg) +{ + *arg = NULL; + return (__log_read_record(env, + dbpp, td, data, __db_noop_desc, sizeof(__db_noop_args), (void**)arg)); +} +#define DB___db_pg_alloc_42 49 +typedef struct ___db_pg_alloc_42_args { + u_int32_t type; + DB_TXN *txnp; + DB_LSN prev_lsn; + int32_t fileid; + DB_LSN meta_lsn; + db_pgno_t meta_pgno; + DB_LSN page_lsn; + db_pgno_t pgno; + u_int32_t ptype; + db_pgno_t next; +} __db_pg_alloc_42_args; + +extern __DB_IMPORT DB_LOG_RECSPEC __db_pg_alloc_42_desc[]; +static inline int __db_pg_alloc_42_read(ENV *env, + DB **dbpp, void *td, void *data, __db_pg_alloc_42_args **arg) +{ + *arg = NULL; + return (__log_read_record(env, + dbpp, td, data, __db_pg_alloc_42_desc, sizeof(__db_pg_alloc_42_args), (void**)arg)); +} +#define DB___db_pg_alloc 49 +typedef struct ___db_pg_alloc_args { + u_int32_t type; + DB_TXN *txnp; + DB_LSN prev_lsn; + int32_t fileid; + DB_LSN meta_lsn; + db_pgno_t meta_pgno; + DB_LSN page_lsn; + db_pgno_t pgno; + u_int32_t ptype; + db_pgno_t next; + db_pgno_t last_pgno; +} __db_pg_alloc_args; + +extern __DB_IMPORT DB_LOG_RECSPEC __db_pg_alloc_desc[]; +static inline int +__db_pg_alloc_log(DB *dbp, DB_TXN *txnp, DB_LSN *ret_lsnp, u_int32_t flags, DB_LSN * meta_lsn, db_pgno_t meta_pgno, DB_LSN * page_lsn, db_pgno_t pgno, + u_int32_t ptype, db_pgno_t next, db_pgno_t last_pgno) +{ + return (__log_put_record((dbp)->env, dbp, txnp, ret_lsnp, + flags, DB___db_pg_alloc, 0, + sizeof(u_int32_t) + sizeof(u_int32_t) + sizeof(DB_LSN) + + sizeof(u_int32_t) + sizeof(*meta_lsn) + sizeof(u_int32_t) + + sizeof(*page_lsn) + sizeof(u_int32_t) + sizeof(u_int32_t) + + sizeof(u_int32_t) + sizeof(u_int32_t), + __db_pg_alloc_desc, meta_lsn, meta_pgno, page_lsn, pgno, ptype, next, last_pgno)); +} + +static inline int __db_pg_alloc_read(ENV *env, + DB **dbpp, void *td, void *data, __db_pg_alloc_args **arg) +{ + *arg = NULL; + return (__log_read_record(env, + dbpp, td, data, __db_pg_alloc_desc, sizeof(__db_pg_alloc_args), (void**)arg)); +} +#define DB___db_pg_free_42 50 +typedef struct ___db_pg_free_42_args { + u_int32_t type; + DB_TXN *txnp; + DB_LSN prev_lsn; + int32_t fileid; + db_pgno_t pgno; + DB_LSN meta_lsn; + db_pgno_t meta_pgno; + DBT header; + db_pgno_t next; +} __db_pg_free_42_args; + +extern __DB_IMPORT DB_LOG_RECSPEC __db_pg_free_42_desc[]; +static inline int __db_pg_free_42_read(ENV *env, + DB **dbpp, void *td, void *data, __db_pg_free_42_args **arg) +{ + *arg = NULL; + return (__log_read_record(env, + dbpp, td, data, __db_pg_free_42_desc, sizeof(__db_pg_free_42_args), (void**)arg)); +} +#define DB___db_pg_free 50 +typedef struct ___db_pg_free_args { + u_int32_t type; + DB_TXN *txnp; + DB_LSN prev_lsn; + int32_t fileid; + db_pgno_t pgno; + DB_LSN meta_lsn; + db_pgno_t meta_pgno; + DBT header; + db_pgno_t next; + db_pgno_t last_pgno; +} __db_pg_free_args; + +extern __DB_IMPORT DB_LOG_RECSPEC __db_pg_free_desc[]; +static inline int +__db_pg_free_log(DB *dbp, DB_TXN *txnp, DB_LSN *ret_lsnp, u_int32_t flags, db_pgno_t pgno, DB_LSN * meta_lsn, db_pgno_t meta_pgno, const DBT *header, + db_pgno_t next, db_pgno_t last_pgno) +{ + return (__log_put_record((dbp)->env, dbp, txnp, ret_lsnp, + flags, DB___db_pg_free, 0, + sizeof(u_int32_t) + sizeof(u_int32_t) + sizeof(DB_LSN) + + sizeof(u_int32_t) + sizeof(u_int32_t) + sizeof(*meta_lsn) + + sizeof(u_int32_t) + LOG_DBT_SIZE(header) + sizeof(u_int32_t) + + sizeof(u_int32_t), + __db_pg_free_desc, pgno, meta_lsn, meta_pgno, header, next, last_pgno)); +} + +static inline int __db_pg_free_read(ENV *env, + DB **dbpp, void *td, void *data, __db_pg_free_args **arg) +{ + *arg = NULL; + return (__log_read_record(env, + dbpp, td, data, __db_pg_free_desc, sizeof(__db_pg_free_args), (void**)arg)); +} +#define DB___db_cksum 51 +typedef struct ___db_cksum_args { + u_int32_t type; + DB_TXN *txnp; + DB_LSN prev_lsn; +} __db_cksum_args; + +extern __DB_IMPORT DB_LOG_RECSPEC __db_cksum_desc[]; +static inline int +__db_cksum_log(ENV *env, DB_TXN *txnp, DB_LSN *ret_lsnp, u_int32_t flags) +{ + return (__log_put_record(env, NULL, txnp, ret_lsnp, + flags, DB___db_cksum, 0, + sizeof(u_int32_t) + sizeof(u_int32_t) + sizeof(DB_LSN), + __db_cksum_desc)); +} + +static inline int __db_cksum_read(ENV *env, + void *data, __db_cksum_args **arg) +{ + *arg = NULL; + return (__log_read_record(env, + NULL, NULL, data, __db_cksum_desc, sizeof(__db_cksum_args), (void**)arg)); +} +#define DB___db_pg_freedata_42 52 +typedef struct ___db_pg_freedata_42_args { + u_int32_t type; + DB_TXN *txnp; + DB_LSN prev_lsn; + int32_t fileid; + db_pgno_t pgno; + DB_LSN meta_lsn; + db_pgno_t meta_pgno; + DBT header; + db_pgno_t next; + DBT data; +} __db_pg_freedata_42_args; + +extern __DB_IMPORT DB_LOG_RECSPEC __db_pg_freedata_42_desc[]; +static inline int __db_pg_freedata_42_read(ENV *env, + DB **dbpp, void *td, void *data, __db_pg_freedata_42_args **arg) +{ + *arg = NULL; + return (__log_read_record(env, + dbpp, td, data, __db_pg_freedata_42_desc, sizeof(__db_pg_freedata_42_args), (void**)arg)); +} +#define DB___db_pg_freedata 52 +typedef struct ___db_pg_freedata_args { + u_int32_t type; + DB_TXN *txnp; + DB_LSN prev_lsn; + int32_t fileid; + db_pgno_t pgno; + DB_LSN meta_lsn; + db_pgno_t meta_pgno; + DBT header; + db_pgno_t next; + db_pgno_t last_pgno; + DBT data; +} __db_pg_freedata_args; + +extern __DB_IMPORT DB_LOG_RECSPEC __db_pg_freedata_desc[]; +static inline int +__db_pg_freedata_log(DB *dbp, DB_TXN *txnp, DB_LSN *ret_lsnp, u_int32_t flags, db_pgno_t pgno, DB_LSN * meta_lsn, db_pgno_t meta_pgno, const DBT *header, + db_pgno_t next, db_pgno_t last_pgno, const DBT *data) +{ + return (__log_put_record((dbp)->env, dbp, txnp, ret_lsnp, + flags, DB___db_pg_freedata, 1, + sizeof(u_int32_t) + sizeof(u_int32_t) + sizeof(DB_LSN) + + sizeof(u_int32_t) + sizeof(u_int32_t) + sizeof(*meta_lsn) + + sizeof(u_int32_t) + LOG_DBT_SIZE(header) + sizeof(u_int32_t) + + sizeof(u_int32_t) + LOG_DBT_SIZE(data), + __db_pg_freedata_desc, pgno, meta_lsn, meta_pgno, header, next, last_pgno, data)); +} + +static inline int __db_pg_freedata_read(ENV *env, + DB **dbpp, void *td, void *data, __db_pg_freedata_args **arg) +{ + *arg = NULL; + return (__log_read_record(env, + dbpp, td, data, __db_pg_freedata_desc, sizeof(__db_pg_freedata_args), (void**)arg)); +} +#define DB___db_pg_init 60 +typedef struct ___db_pg_init_args { + u_int32_t type; + DB_TXN *txnp; + DB_LSN prev_lsn; + int32_t fileid; + db_pgno_t pgno; + DBT header; + DBT data; +} __db_pg_init_args; + +extern __DB_IMPORT DB_LOG_RECSPEC __db_pg_init_desc[]; +static inline int +__db_pg_init_log(DB *dbp, DB_TXN *txnp, DB_LSN *ret_lsnp, u_int32_t flags, db_pgno_t pgno, const DBT *header, const DBT *data) +{ + return (__log_put_record((dbp)->env, dbp, txnp, ret_lsnp, + flags, DB___db_pg_init, 1, + sizeof(u_int32_t) + sizeof(u_int32_t) + sizeof(DB_LSN) + + sizeof(u_int32_t) + sizeof(u_int32_t) + LOG_DBT_SIZE(header) + + LOG_DBT_SIZE(data), + __db_pg_init_desc, pgno, header, data)); +} + +static inline int __db_pg_init_read(ENV *env, + DB **dbpp, void *td, void *data, __db_pg_init_args **arg) +{ + *arg = NULL; + return (__log_read_record(env, + dbpp, td, data, __db_pg_init_desc, sizeof(__db_pg_init_args), (void**)arg)); +} +#define DB___db_pg_sort_44 61 +typedef struct ___db_pg_sort_44_args { + u_int32_t type; + DB_TXN *txnp; + DB_LSN prev_lsn; + int32_t fileid; + db_pgno_t meta; + DB_LSN meta_lsn; + db_pgno_t last_free; + DB_LSN last_lsn; + db_pgno_t last_pgno; + DBT list; +} __db_pg_sort_44_args; + +extern __DB_IMPORT DB_LOG_RECSPEC __db_pg_sort_44_desc[]; +static inline int __db_pg_sort_44_read(ENV *env, + DB **dbpp, void *td, void *data, __db_pg_sort_44_args **arg) +{ + *arg = NULL; + return (__log_read_record(env, + dbpp, td, data, __db_pg_sort_44_desc, sizeof(__db_pg_sort_44_args), (void**)arg)); +} +#define DB___db_pg_trunc 66 +typedef struct ___db_pg_trunc_args { + u_int32_t type; + DB_TXN *txnp; + DB_LSN prev_lsn; + int32_t fileid; + db_pgno_t meta; + DB_LSN meta_lsn; + db_pgno_t last_free; + DB_LSN last_lsn; + db_pgno_t next_free; + db_pgno_t last_pgno; + DBT list; +} __db_pg_trunc_args; + +extern __DB_IMPORT DB_LOG_RECSPEC __db_pg_trunc_desc[]; +static inline int +__db_pg_trunc_log(DB *dbp, DB_TXN *txnp, DB_LSN *ret_lsnp, u_int32_t flags, db_pgno_t meta, DB_LSN * meta_lsn, db_pgno_t last_free, DB_LSN * last_lsn, + db_pgno_t next_free, db_pgno_t last_pgno, const DBT *list) +{ + return (__log_put_record((dbp)->env, dbp, txnp, ret_lsnp, + flags, DB___db_pg_trunc, 0, + sizeof(u_int32_t) + sizeof(u_int32_t) + sizeof(DB_LSN) + + sizeof(u_int32_t) + sizeof(u_int32_t) + sizeof(*meta_lsn) + + sizeof(u_int32_t) + sizeof(*last_lsn) + sizeof(u_int32_t) + + sizeof(u_int32_t) + LOG_DBT_SIZE(list), + __db_pg_trunc_desc, meta, meta_lsn, last_free, last_lsn, next_free, last_pgno, list)); +} + +static inline int __db_pg_trunc_read(ENV *env, + DB **dbpp, void *td, void *data, __db_pg_trunc_args **arg) +{ + *arg = NULL; + return (__log_read_record(env, + dbpp, td, data, __db_pg_trunc_desc, sizeof(__db_pg_trunc_args), (void**)arg)); +} +#define DB___db_realloc 36 +typedef struct ___db_realloc_args { + u_int32_t type; + DB_TXN *txnp; + DB_LSN prev_lsn; + int32_t fileid; + db_pgno_t prev_pgno; + DB_LSN page_lsn; + db_pgno_t next_free; + u_int32_t ptype; + DBT list; +} __db_realloc_args; + +extern __DB_IMPORT DB_LOG_RECSPEC __db_realloc_desc[]; +static inline int +__db_realloc_log(DB *dbp, DB_TXN *txnp, DB_LSN *ret_lsnp, u_int32_t flags, db_pgno_t prev_pgno, DB_LSN * page_lsn, db_pgno_t next_free, u_int32_t ptype, + const DBT *list) +{ + return (__log_put_record((dbp)->env, dbp, txnp, ret_lsnp, + flags, DB___db_realloc, 0, + sizeof(u_int32_t) + sizeof(u_int32_t) + sizeof(DB_LSN) + + sizeof(u_int32_t) + sizeof(u_int32_t) + sizeof(*page_lsn) + + sizeof(u_int32_t) + sizeof(u_int32_t) + LOG_DBT_SIZE(list), + __db_realloc_desc, prev_pgno, page_lsn, next_free, ptype, list)); +} + +static inline int __db_realloc_read(ENV *env, + DB **dbpp, void *td, void *data, __db_realloc_args **arg) +{ + *arg = NULL; + return (__log_read_record(env, + dbpp, td, data, __db_realloc_desc, sizeof(__db_realloc_args), (void**)arg)); +} +#define DB___db_relink 147 +typedef struct ___db_relink_args { + u_int32_t type; + DB_TXN *txnp; + DB_LSN prev_lsn; + int32_t fileid; + db_pgno_t pgno; + db_pgno_t new_pgno; + db_pgno_t prev_pgno; + DB_LSN lsn_prev; + db_pgno_t next_pgno; + DB_LSN lsn_next; +} __db_relink_args; + +extern __DB_IMPORT DB_LOG_RECSPEC __db_relink_desc[]; +static inline int +__db_relink_log(DB *dbp, DB_TXN *txnp, DB_LSN *ret_lsnp, u_int32_t flags, db_pgno_t pgno, db_pgno_t new_pgno, db_pgno_t prev_pgno, DB_LSN * lsn_prev, + db_pgno_t next_pgno, DB_LSN * lsn_next) +{ + return (__log_put_record((dbp)->env, dbp, txnp, ret_lsnp, + flags, DB___db_relink, 0, + sizeof(u_int32_t) + sizeof(u_int32_t) + sizeof(DB_LSN) + + sizeof(u_int32_t) + sizeof(u_int32_t) + sizeof(u_int32_t) + + sizeof(u_int32_t) + sizeof(*lsn_prev) + sizeof(u_int32_t) + + sizeof(*lsn_next), + __db_relink_desc, pgno, new_pgno, prev_pgno, lsn_prev, next_pgno, lsn_next)); +} + +static inline int __db_relink_read(ENV *env, + DB **dbpp, void *td, void *data, __db_relink_args **arg) +{ + *arg = NULL; + return (__log_read_record(env, + dbpp, td, data, __db_relink_desc, sizeof(__db_relink_args), (void**)arg)); +} +#define DB___db_merge 148 +typedef struct ___db_merge_args { + u_int32_t type; + DB_TXN *txnp; + DB_LSN prev_lsn; + int32_t fileid; + db_pgno_t pgno; + DB_LSN lsn; + db_pgno_t npgno; + DB_LSN nlsn; + DBT hdr; + DBT data; + int32_t pg_copy; +} __db_merge_args; + +extern __DB_IMPORT DB_LOG_RECSPEC __db_merge_desc[]; +static inline int +__db_merge_log(DB *dbp, DB_TXN *txnp, DB_LSN *ret_lsnp, u_int32_t flags, db_pgno_t pgno, DB_LSN * lsn, db_pgno_t npgno, DB_LSN * nlsn, + const DBT *hdr, const DBT *data, int32_t pg_copy) +{ + return (__log_put_record((dbp)->env, dbp, txnp, ret_lsnp, + flags, DB___db_merge, 1, + sizeof(u_int32_t) + sizeof(u_int32_t) + sizeof(DB_LSN) + + sizeof(u_int32_t) + sizeof(u_int32_t) + sizeof(*lsn) + + sizeof(u_int32_t) + sizeof(*nlsn) + LOG_DBT_SIZE(hdr) + + LOG_DBT_SIZE(data) + sizeof(u_int32_t), + __db_merge_desc, pgno, lsn, npgno, nlsn, hdr, data, pg_copy)); +} + +static inline int __db_merge_read(ENV *env, + DB **dbpp, void *td, void *data, __db_merge_args **arg) +{ + *arg = NULL; + return (__log_read_record(env, + dbpp, td, data, __db_merge_desc, sizeof(__db_merge_args), (void**)arg)); +} +#define DB___db_pgno 149 +typedef struct ___db_pgno_args { + u_int32_t type; + DB_TXN *txnp; + DB_LSN prev_lsn; + int32_t fileid; + db_pgno_t pgno; + DB_LSN lsn; + u_int32_t indx; + db_pgno_t opgno; + db_pgno_t npgno; +} __db_pgno_args; + +extern __DB_IMPORT DB_LOG_RECSPEC __db_pgno_desc[]; +static inline int +__db_pgno_log(DB *dbp, DB_TXN *txnp, DB_LSN *ret_lsnp, u_int32_t flags, db_pgno_t pgno, DB_LSN * lsn, u_int32_t indx, db_pgno_t opgno, + db_pgno_t npgno) +{ + return (__log_put_record((dbp)->env, dbp, txnp, ret_lsnp, + flags, DB___db_pgno, 0, + sizeof(u_int32_t) + sizeof(u_int32_t) + sizeof(DB_LSN) + + sizeof(u_int32_t) + sizeof(u_int32_t) + sizeof(*lsn) + + sizeof(u_int32_t) + sizeof(u_int32_t) + sizeof(u_int32_t), + __db_pgno_desc, pgno, lsn, indx, opgno, npgno)); +} + +static inline int __db_pgno_read(ENV *env, + DB **dbpp, void *td, void *data, __db_pgno_args **arg) +{ + *arg = NULL; + return (__log_read_record(env, + dbpp, td, data, __db_pgno_desc, sizeof(__db_pgno_args), (void**)arg)); +} +#endif diff -r 000000000000 -r a1985f14b030 src/dbinc_auto/db_ext.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/dbinc_auto/db_ext.h Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,367 @@ +/* DO NOT EDIT: automatically built by dist/s_include. + * + * Copyright (c) 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ +#ifndef _db_ext_h_ +#define _db_ext_h_ + +#if defined(__cplusplus) +extern "C" { +#endif + +int __crdel_init_recover __P((ENV *, DB_DISTAB *)); +int __crdel_metasub_print __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __crdel_inmem_create_print __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __crdel_inmem_rename_print __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __crdel_inmem_remove_print __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __crdel_init_print __P((ENV *, DB_DISTAB *)); +int __crdel_metasub_recover __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __crdel_inmem_create_recover __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __crdel_inmem_rename_recover __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __crdel_inmem_remove_recover __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __db_master_open __P((DB *, DB_THREAD_INFO *, DB_TXN *, const char *, u_int32_t, int, DB **)); +int __db_master_update __P((DB *, DB *, DB_THREAD_INFO *, DB_TXN *, const char *, DBTYPE, mu_action, const char *, u_int32_t)); +int __env_dbreg_setup __P((DB *, DB_TXN *, const char *, const char *, u_int32_t)); +int __env_setup __P((DB *, DB_TXN *, const char *, const char *, u_int32_t, u_int32_t)); +int __env_mpool __P((DB *, const char *, u_int32_t)); +int __db_close __P((DB *, DB_TXN *, u_int32_t)); +int __db_refresh __P((DB *, DB_TXN *, u_int32_t, int *, int)); +int __db_log_page __P((DB *, DB_TXN *, DB_LSN *, db_pgno_t, PAGE *)); +int __db_walk_cursors __P((DB *, DBC *, int (*) __P((DBC *, DBC *, u_int32_t *, db_pgno_t, u_int32_t, void *)), u_int32_t *, db_pgno_t, u_int32_t, void *)); +int __db_backup_name __P((ENV *, const char *, DB_TXN *, char **)); +#ifdef CONFIG_TEST +int __db_testcopy __P((ENV *, DB *, const char *)); +#endif +int __db_testdocopy __P((ENV *, const char *)); +int __db_cursor_int __P((DB *, DB_THREAD_INFO *, DB_TXN *, DBTYPE, db_pgno_t, int, DB_LOCKER *, DBC **)); +int __db_put __P((DB *, DB_THREAD_INFO *, DB_TXN *, DBT *, DBT *, u_int32_t)); +int __db_del __P((DB *, DB_THREAD_INFO *, DB_TXN *, DBT *, u_int32_t)); +int __db_sync __P((DB *)); +int __db_associate __P((DB *, DB_THREAD_INFO *, DB_TXN *, DB *, int (*)(DB *, const DBT *, const DBT *, DBT *), u_int32_t)); +int __db_secondary_close __P((DB *, u_int32_t)); +int __db_associate_foreign __P((DB *, DB *, int (*)(DB *, const DBT *, DBT *, const DBT *, int *), u_int32_t)); +int __db_init_recover __P((ENV *, DB_DISTAB *)); +int __db_addrem_print __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __db_addrem_42_print __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __db_big_print __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __db_big_42_print __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __db_ovref_print __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __db_relink_42_print __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __db_debug_print __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __db_noop_print __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __db_pg_alloc_42_print __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __db_pg_alloc_print __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __db_pg_free_42_print __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __db_pg_free_print __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __db_cksum_print __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __db_pg_freedata_42_print __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __db_pg_freedata_print __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __db_pg_init_print __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __db_pg_sort_44_print __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __db_pg_trunc_print __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __db_realloc_print __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __db_relink_print __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __db_merge_print __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __db_pgno_print __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __db_init_print __P((ENV *, DB_DISTAB *)); +int __db_dbbackup_pp __P((DB_ENV *, const char *, const char *, u_int32_t)); +int __db_dbbackup __P((DB_ENV *, DB_THREAD_INFO *, const char *, const char *, u_int32_t)); +int __db_backup __P((DB_ENV *, const char *, u_int32_t)); +int __dbc_close __P((DBC *)); +int __dbc_destroy __P((DBC *)); +int __dbc_cmp __P((DBC *, DBC *, int *)); +int __dbc_count __P((DBC *, db_recno_t *)); +int __dbc_del __P((DBC *, u_int32_t)); +int __dbc_idel __P((DBC *, u_int32_t)); +#ifdef HAVE_COMPRESSION +int __dbc_bulk_del __P((DBC *, DBT *, u_int32_t)); +#endif +int __dbc_dup __P((DBC *, DBC **, u_int32_t)); +int __dbc_idup __P((DBC *, DBC **, u_int32_t)); +int __dbc_newopd __P((DBC *, db_pgno_t, DBC *, DBC **)); +int __dbc_get __P((DBC *, DBT *, DBT *, u_int32_t)); +int __dbc_iget __P((DBC *, DBT *, DBT *, u_int32_t)); +int __dbc_put __P((DBC *, DBT *, DBT *, u_int32_t)); +int __dbc_iput __P((DBC *, DBT *, DBT *, u_int32_t)); +int __db_duperr __P((DB *, u_int32_t)); +int __dbc_cleanup __P((DBC *, DBC *, int)); +int __dbc_secondary_get_pp __P((DBC *, DBT *, DBT *, u_int32_t)); +int __dbc_pget __P((DBC *, DBT *, DBT *, DBT *, u_int32_t)); +int __dbc_del_primary __P((DBC *)); +int __db_s_first __P((DB *, DB **)); +int __db_s_next __P((DB **, DB_TXN *)); +int __db_s_done __P((DB *, DB_TXN *)); +int __db_buildpartial __P((DB *, DBT *, DBT *, DBT *)); +u_int32_t __db_partsize __P((u_int32_t, DBT *)); +int __db_secondary_corrupt __P((DB *)); +#ifdef DIAGNOSTIC +void __db_check_skeyset __P((DB *, DBT *)); +#endif +int __cdsgroup_begin __P((ENV *, DB_TXN **)); +int __cdsgroup_begin_pp __P((DB_ENV *, DB_TXN **)); +int __db_compact_pp __P((DB *, DB_TXN *, DBT *, DBT *, DB_COMPACT *, u_int32_t, DBT *)); +int __db_associate_foreign_pp __P((DB *, DB *, int (*)(DB *, const DBT *, DBT *, const DBT *, int *), u_int32_t)); +int __db_compact_int __P((DB *, DB_THREAD_INFO *, DB_TXN *, DBT *, DBT *, DB_COMPACT *, u_int32_t, DBT *)); +int __db_exchange_page __P((DBC *, PAGE **, PAGE *, db_pgno_t, int)); +int __db_truncate_overflow __P((DBC *, db_pgno_t, PAGE **, DB_COMPACT *)); +int __db_truncate_root __P((DBC *, PAGE *, u_int32_t, db_pgno_t *, u_int32_t)); +int __db_find_free __P((DBC *, u_int32_t, u_int32_t, db_pgno_t, db_pgno_t *)); +int __db_move_metadata __P((DBC *, DBMETA **, DB_COMPACT *)); +int __db_pgin __P((DB_ENV *, db_pgno_t, void *, DBT *)); +int __db_pgout __P((DB_ENV *, db_pgno_t, void *, DBT *)); +int __db_decrypt_pg __P((ENV *, DB *, PAGE *)); +int __db_encrypt_and_checksum_pg __P((ENV *, DB *, PAGE *)); +void __db_metaswap __P((PAGE *)); +int __db_byteswap __P((DB *, db_pgno_t, PAGE *, size_t, int)); +int __db_pageswap __P((ENV *, DB *, void *, size_t, DBT *, int)); +void __db_recordswap __P((u_int32_t, u_int32_t, void *, void *, u_int32_t)); +int __db_dispatch __P((ENV *, DB_DISTAB *, DBT *, DB_LSN *, db_recops, void *)); +int __db_add_recovery __P((DB_ENV *, DB_DISTAB *, int (*)(DB_ENV *, DBT *, DB_LSN *, db_recops), u_int32_t)); +int __db_add_recovery_int __P((ENV *, DB_DISTAB *, int (*)(ENV *, DBT *, DB_LSN *, db_recops, void *), u_int32_t)); +int __db_txnlist_init __P((ENV *, DB_THREAD_INFO *, u_int32_t, u_int32_t, DB_LSN *, DB_TXNHEAD **)); +int __db_txnlist_add __P((ENV *, DB_TXNHEAD *, u_int32_t, u_int32_t, DB_LSN *)); +int __db_txnlist_remove __P((ENV *, DB_TXNHEAD *, u_int32_t)); +void __db_txnlist_ckp __P((ENV *, DB_TXNHEAD *, DB_LSN *)); +void __db_txnlist_end __P((ENV *, DB_TXNHEAD *)); +int __db_txnlist_find __P((ENV *, DB_TXNHEAD *, u_int32_t, u_int32_t *)); +int __db_txnlist_update __P((ENV *, DB_TXNHEAD *, u_int32_t, u_int32_t, DB_LSN *, u_int32_t *, int)); +int __db_txnlist_gen __P((ENV *, DB_TXNHEAD *, int, u_int32_t, u_int32_t)); +int __db_txnlist_lsnadd __P((ENV *, DB_TXNHEAD *, DB_LSN *)); +int __db_txnlist_lsnget __P((ENV *, DB_TXNHEAD *, DB_LSN *, u_int32_t)); +int __db_txnlist_lsninit __P((ENV *, DB_TXNHEAD *, DB_LSN *)); +void __db_txnlist_print __P((DB_TXNHEAD *)); +int __db_ditem_nolog __P((DBC *, PAGE *, u_int32_t, u_int32_t)); +int __db_ditem __P((DBC *, PAGE *, u_int32_t, u_int32_t)); +int __db_pitem_nolog __P((DBC *, PAGE *, u_int32_t, u_int32_t, DBT *, DBT *)); +int __db_pitem __P((DBC *, PAGE *, u_int32_t, u_int32_t, DBT *, DBT *)); +int __db_associate_pp __P((DB *, DB_TXN *, DB *, int (*)(DB *, const DBT *, const DBT *, DBT *), u_int32_t)); +int __db_close_pp __P((DB *, u_int32_t)); +int __db_cursor_pp __P((DB *, DB_TXN *, DBC **, u_int32_t)); +int __db_cursor __P((DB *, DB_THREAD_INFO *, DB_TXN *, DBC **, u_int32_t)); +int __db_del_pp __P((DB *, DB_TXN *, DBT *, u_int32_t)); +int __db_exists __P((DB *, DB_TXN *, DBT *, u_int32_t)); +int __db_fd_pp __P((DB *, int *)); +int __db_get_pp __P((DB *, DB_TXN *, DBT *, DBT *, u_int32_t)); +int __db_get __P((DB *, DB_THREAD_INFO *, DB_TXN *, DBT *, DBT *, u_int32_t)); +int __db_key_range_pp __P((DB *, DB_TXN *, DBT *, DB_KEY_RANGE *, u_int32_t)); +int __db_open_pp __P((DB *, DB_TXN *, const char *, const char *, DBTYPE, u_int32_t, int)); +int __db_pget_pp __P((DB *, DB_TXN *, DBT *, DBT *, DBT *, u_int32_t)); +int __db_pget __P((DB *, DB_THREAD_INFO *, DB_TXN *, DBT *, DBT *, DBT *, u_int32_t)); +int __db_put_pp __P((DB *, DB_TXN *, DBT *, DBT *, u_int32_t)); +int __db_sync_pp __P((DB *, u_int32_t)); +int __dbc_close_pp __P((DBC *)); +int __dbc_cmp_pp __P((DBC *, DBC *, int*, u_int32_t)); +int __dbc_count_pp __P((DBC *, db_recno_t *, u_int32_t)); +int __dbc_del_pp __P((DBC *, u_int32_t)); +int __dbc_dup_pp __P((DBC *, DBC **, u_int32_t)); +int __dbc_get_pp __P((DBC *, DBT *, DBT *, u_int32_t)); +int __dbc_get_arg __P((DBC *, DBT *, DBT *, u_int32_t)); +int __db_secondary_close_pp __P((DB *, u_int32_t)); +int __dbc_pget_pp __P((DBC *, DBT *, DBT *, DBT *, u_int32_t)); +int __dbc_put_pp __P((DBC *, DBT *, DBT *, u_int32_t)); +int __db_txn_auto_init __P((ENV *, DB_THREAD_INFO *, DB_TXN **)); +int __db_txn_auto_resolve __P((ENV *, DB_TXN *, int, int)); +int __db_join_pp __P((DB *, DBC **, DBC **, u_int32_t)); +int __db_join __P((DB *, DBC **, DBC **, u_int32_t)); +int __db_join_close __P((DBC *)); +int __db_new __P((DBC *, u_int32_t, DB_LOCK *, PAGE **)); +int __db_free __P((DBC *, PAGE *, u_int32_t)); +#ifdef HAVE_FTRUNCATE +void __db_freelist_pos __P((db_pgno_t, db_pgno_t *, u_int32_t, u_int32_t *)); +#endif +void __db_freelist_sort __P((db_pglist_t *, u_int32_t)); +#ifdef HAVE_FTRUNCATE +int __db_pg_truncate __P((DBC *, DB_TXN *, db_pglist_t *, DB_COMPACT *, u_int32_t *, db_pgno_t , db_pgno_t *, DB_LSN *, int)); +#endif +#ifdef HAVE_FTRUNCATE +int __db_free_truncate __P((DB *, DB_THREAD_INFO *, DB_TXN *, u_int32_t, DB_COMPACT *, db_pglist_t **, u_int32_t *, db_pgno_t *)); +#endif +int __db_create_internal __P((DB **, ENV *, u_int32_t)); +int __dbh_am_chk __P((DB *, u_int32_t)); +int __db_get_flags __P((DB *, u_int32_t *)); +int __db_set_flags __P((DB *, u_int32_t)); +int __db_get_lorder __P((DB *, int *)); +int __db_set_lorder __P((DB *, int)); +int __db_set_pagesize __P((DB *, u_int32_t)); +int __db_relink __P((DBC *, PAGE *, PAGE *, db_pgno_t)); +#ifdef DIAGNOSTIC +int __db_haslock __P((ENV *, DB_LOCKER *, DB_MPOOLFILE *, db_pgno_t, db_lockmode_t, u_int32_t)); +#endif +#ifdef DIAGNOSTIC +int __db_has_pagelock __P((ENV *, DB_LOCKER *, DB_MPOOLFILE *, PAGE *, db_lockmode_t)); +#endif +int __db_open __P((DB *, DB_THREAD_INFO *, DB_TXN *, const char *, const char *, DBTYPE, u_int32_t, int, db_pgno_t)); +int __db_get_open_flags __P((DB *, u_int32_t *)); +int __db_new_file __P((DB *, DB_THREAD_INFO *, DB_TXN *, DB_FH *, const char *)); +int __db_init_subdb __P((DB *, DB *, const char *, DB_THREAD_INFO *, DB_TXN *)); +int __db_chk_meta __P((ENV *, DB *, DBMETA *, u_int32_t)); +int __db_meta_setup __P((ENV *, DB *, const char *, DBMETA *, u_int32_t, u_int32_t)); +int __db_reopen __P((DBC *)); +int __db_goff __P((DBC *, DBT *, u_int32_t, db_pgno_t, void **, u_int32_t *)); +int __db_poff __P((DBC *, const DBT *, db_pgno_t *)); +int __db_ovref __P((DBC *, db_pgno_t)); +int __db_doff __P((DBC *, db_pgno_t)); +int __db_moff __P((DBC *, const DBT *, db_pgno_t, u_int32_t, int (*)(DB *, const DBT *, const DBT *), int *)); +int __db_coff __P((DBC *, const DBT *, const DBT *, int (*)(DB *, const DBT *, const DBT *), int *)); +int __db_vrfy_overflow __P((DB *, VRFY_DBINFO *, PAGE *, db_pgno_t, u_int32_t)); +int __db_vrfy_ovfl_structure __P((DB *, VRFY_DBINFO *, db_pgno_t, u_int32_t, u_int32_t)); +int __db_safe_goff __P((DB *, VRFY_DBINFO *, db_pgno_t, DBT *, void *, u_int32_t *, u_int32_t)); +void __db_loadme __P((void)); +int __db_dumptree __P((DB *, DB_TXN *, char *, char *, db_pgno_t, db_pgno_t)); +const FN * __db_get_flags_fn __P((void)); +int __db_prnpage __P((DB *, DB_TXN *, db_pgno_t)); +int __db_prpage __P((DB *, PAGE *, u_int32_t)); +const char * __db_lockmode_to_string __P((db_lockmode_t)); +int __db_dumptree __P((DB *, DB_TXN *, char *, char *, db_pgno_t, db_pgno_t)); +const FN * __db_get_flags_fn __P((void)); +int __db_prpage_int __P((ENV *, DB_MSGBUF *, DB *, char *, PAGE *, u_int32_t, u_int8_t *, u_int32_t)); +void __db_prbytes __P((ENV *, DB_MSGBUF *, u_int8_t *, u_int32_t)); +void __db_prflags __P((ENV *, DB_MSGBUF *, u_int32_t, const FN *, const char *, const char *)); +int __db_name_to_val __P((FN const *, char *)); +const char *__db_pagetype_to_string __P((u_int32_t)); +int __db_dump_pp __P((DB *, const char *, int (*)(void *, const void *), void *, int, int)); +int __db_dump __P((DB *, const char *, int (*)(void *, const void *), void *, int, int)); +int __db_prdbt __P((DBT *, int, const char *, void *, int (*)(void *, const void *), int, int)); +int __db_prheader __P((DB *, const char *, int, int, void *, int (*)(void *, const void *), VRFY_DBINFO *, db_pgno_t)); +int __db_prfooter __P((void *, int (*)(void *, const void *))); +int __db_pr_callback __P((void *, const void *)); +const char * __db_dbtype_to_string __P((DBTYPE)); +int __db_addrem_recover __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __db_addrem_42_recover __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __db_big_recover __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __db_big_42_recover __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __db_ovref_recover __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __db_debug_recover __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __db_noop_recover __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __db_pg_alloc_recover __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __db_pg_free_recover __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __db_pg_freedata_recover __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __db_cksum_recover __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __db_pg_init_recover __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __db_pg_trunc_recover __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __db_realloc_recover __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __db_pg_sort_44_recover __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __db_pg_alloc_42_recover __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __db_pg_free_42_recover __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __db_pg_freedata_42_recover __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __db_relink_42_recover __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __db_relink_recover __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __db_merge_recover __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __db_pgno_recover __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +void __db_pglist_swap __P((u_int32_t, void *)); +void __db_pglist_print __P((ENV *, DB_MSGBUF *, DBT *)); +int __db_traverse_big __P((DBC *, db_pgno_t, int (*)(DBC *, PAGE *, void *, int *), void *)); +int __db_reclaim_callback __P((DBC *, PAGE *, void *, int *)); +int __db_truncate_callback __P((DBC *, PAGE *, void *, int *)); +int __env_dbremove_pp __P((DB_ENV *, DB_TXN *, const char *, const char *, u_int32_t)); +int __db_remove_pp __P((DB *, const char *, const char *, u_int32_t)); +int __db_remove __P((DB *, DB_THREAD_INFO *, DB_TXN *, const char *, const char *, u_int32_t)); +int __db_remove_int __P((DB *, DB_THREAD_INFO *, DB_TXN *, const char *, const char *, u_int32_t)); +int __db_inmem_remove __P((DB *, DB_TXN *, const char *)); +int __env_dbrename_pp __P((DB_ENV *, DB_TXN *, const char *, const char *, const char *, u_int32_t)); +int __db_rename_pp __P((DB *, const char *, const char *, const char *, u_int32_t)); +int __db_rename_int __P((DB *, DB_THREAD_INFO *, DB_TXN *, const char *, const char *, const char *, u_int32_t)); +int __db_ret __P((DBC *, PAGE *, u_int32_t, DBT *, void **, u_int32_t *)); +int __db_retcopy __P((ENV *, DBT *, void *, u_int32_t, void **, u_int32_t *)); +int __db_dbt_clone __P((ENV *, DBT *, const DBT *)); +int __db_dbt_clone_free __P((ENV *, DBT *)); +int __env_fileid_reset_pp __P((DB_ENV *, const char *, u_int32_t)); +int __env_fileid_reset __P((ENV *, DB_THREAD_INFO *, const char *, int)); +int __env_lsn_reset_pp __P((DB_ENV *, const char *, u_int32_t)); +int __db_lsn_reset __P((DB_MPOOLFILE *, DB_THREAD_INFO *)); +int __db_compare_both __P((DB *, const DBT *, const DBT *, const DBT *, const DBT *)); +int __db_sort_multiple __P((DB *, DBT *, DBT *, u_int32_t)); +int __db_stat_pp __P((DB *, DB_TXN *, void *, u_int32_t)); +int __db_stat_print_pp __P((DB *, u_int32_t)); +int __db_stat_print __P((DB *, DB_THREAD_INFO *, u_int32_t)); +int __db_truncate_pp __P((DB *, DB_TXN *, u_int32_t *, u_int32_t)); +int __db_truncate __P((DB *, DB_THREAD_INFO *, DB_TXN *, u_int32_t *)); +int __db_upgrade_pp __P((DB *, const char *, u_int32_t)); +int __db_upgrade __P((DB *, const char *, u_int32_t)); +int __db_lastpgno __P((DB *, char *, DB_FH *, db_pgno_t *)); +int __db_31_offdup __P((DB *, char *, DB_FH *, int, db_pgno_t *)); +int __db_verify_pp __P((DB *, const char *, const char *, FILE *, u_int32_t)); +int __db_verify_internal __P((DB *, const char *, const char *, void *, int (*)(void *, const void *), u_int32_t)); +int __db_verify __P((DB *, DB_THREAD_INFO *, const char *, const char *, void *, int (*)(void *, const void *), void *, void *, u_int32_t)); +int __db_vrfy_common __P((DB *, VRFY_DBINFO *, PAGE *, db_pgno_t, u_int32_t)); +int __db_vrfy_datapage __P((DB *, VRFY_DBINFO *, PAGE *, db_pgno_t, u_int32_t)); +int __db_vrfy_meta __P((DB *, VRFY_DBINFO *, DBMETA *, db_pgno_t, u_int32_t)); +void __db_vrfy_struct_feedback __P((DB *, VRFY_DBINFO *)); +int __db_salvage_pg __P((DB *, VRFY_DBINFO *, db_pgno_t, PAGE *, void *, int (*)(void *, const void *), u_int32_t)); +int __db_salvage_leaf __P((DB *, VRFY_DBINFO *, db_pgno_t, PAGE *, void *, int (*)(void *, const void *), u_int32_t)); +int __db_vrfy_inpitem __P((DB *, PAGE *, db_pgno_t, u_int32_t, int, u_int32_t, u_int32_t *, u_int32_t *)); +int __db_vrfy_duptype __P((DB *, VRFY_DBINFO *, db_pgno_t, u_int32_t)); +int __db_salvage_duptree __P((DB *, VRFY_DBINFO *, db_pgno_t, DBT *, void *, int (*)(void *, const void *), u_int32_t)); +int __db_vrfy_dbinfo_create __P((ENV *, DB_THREAD_INFO *, u_int32_t, VRFY_DBINFO **)); +int __db_vrfy_dbinfo_destroy __P((ENV *, VRFY_DBINFO *)); +int __db_vrfy_getpageinfo __P((VRFY_DBINFO *, db_pgno_t, VRFY_PAGEINFO **)); +int __db_vrfy_putpageinfo __P((ENV *, VRFY_DBINFO *, VRFY_PAGEINFO *)); +int __db_vrfy_pgset __P((ENV *, DB_THREAD_INFO *, u_int32_t, DB **)); +int __db_vrfy_pgset_get __P((DB *, DB_THREAD_INFO *, DB_TXN *, db_pgno_t, int *)); +int __db_vrfy_pgset_inc __P((DB *, DB_THREAD_INFO *, DB_TXN *, db_pgno_t)); +int __db_vrfy_pgset_next __P((DBC *, db_pgno_t *)); +int __db_vrfy_childcursor __P((VRFY_DBINFO *, DBC **)); +int __db_vrfy_childput __P((VRFY_DBINFO *, db_pgno_t, VRFY_CHILDINFO *)); +int __db_vrfy_ccset __P((DBC *, db_pgno_t, VRFY_CHILDINFO **)); +int __db_vrfy_ccnext __P((DBC *, VRFY_CHILDINFO **)); +int __db_vrfy_ccclose __P((DBC *)); +int __db_salvage_init __P((VRFY_DBINFO *)); +int __db_salvage_destroy __P((VRFY_DBINFO *)); +int __db_salvage_getnext __P((VRFY_DBINFO *, DBC **, db_pgno_t *, u_int32_t *, int)); +int __db_salvage_isdone __P((VRFY_DBINFO *, db_pgno_t)); +int __db_salvage_markdone __P((VRFY_DBINFO *, db_pgno_t)); +int __db_salvage_markneeded __P((VRFY_DBINFO *, db_pgno_t, u_int32_t)); +int __db_vrfy_prdbt __P((DBT *, int, const char *, void *, int (*)(void *, const void *), int, int, VRFY_DBINFO *)); +int __db_lget __P((DBC *, int, db_pgno_t, db_lockmode_t, u_int32_t, DB_LOCK *)); +int __db_lput __P((DBC *, DB_LOCK *)); +int __db_lprint __P((DBC *)); +int __partition_init __P((DB *, u_int32_t)); +int __partition_set __P((DB *, u_int32_t, DBT *, u_int32_t (*callback)(DB *, DBT *key))); +int __partition_set_dirs __P((DB *, const char **)); +int __partition_open __P((DB *, DB_THREAD_INFO *, DB_TXN *, const char *, DBTYPE, u_int32_t, int, int)); +int __partition_get_callback __P((DB *, u_int32_t *, u_int32_t (**callback)(DB *, DBT *key))); +int __partition_get_keys __P((DB *, u_int32_t *, DBT **)); +int __partition_get_dirs __P((DB *, const char ***)); +int __partc_init __P((DBC *)); +int __partc_get __P((DBC*, DBT *, DBT *, u_int32_t)); +int __partition_close __P((DB *, DB_TXN *, u_int32_t)); +int __partition_sync __P((DB *)); +int __partition_stat __P((DBC *, void *, u_int32_t)); +int __part_truncate __P((DBC *, u_int32_t *)); +int __part_compact __P((DB *, DB_THREAD_INFO *, DB_TXN *, DBT *, DBT *, DB_COMPACT *, u_int32_t, DBT *)); +int __part_lsn_reset __P((DB *, DB_THREAD_INFO *)); +int __part_fileid_reset __P((ENV *, DB_THREAD_INFO *, const char *, u_int32_t, int)); +int __part_key_range __P((DBC *, DBT *, DB_KEY_RANGE *, u_int32_t)); +int __part_remove __P((DB *, DB_THREAD_INFO *, DB_TXN *, const char *, const char *, u_int32_t)); +int __part_rename __P((DB *, DB_THREAD_INFO *, DB_TXN *, const char *, const char *, const char *)); +int __part_verify __P((DB *, VRFY_DBINFO *, const char *, void *, int (*)(void *, const void *), u_int32_t)); +int __part_testdocopy __P((DB *, const char *)); +int __db_no_partition __P((ENV *)); + +#if defined(__cplusplus) +} +#endif +#endif /* !_db_ext_h_ */ diff -r 000000000000 -r a1985f14b030 src/dbinc_auto/dbreg_auto.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/dbinc_auto/dbreg_auto.h Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,68 @@ +/* Do not edit: automatically built by gen_rec.awk. + * + * Copyright (c) 2012 Oracle and/or its affiliates. All rights reserved. * + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +#ifndef __dbreg_AUTO_H +#define __dbreg_AUTO_H +#include "dbinc/log.h" +#define DB___dbreg_register 2 +typedef struct ___dbreg_register_args { + u_int32_t type; + DB_TXN *txnp; + DB_LSN prev_lsn; + u_int32_t opcode; + DBT name; + DBT uid; + int32_t fileid; + DBTYPE ftype; + db_pgno_t meta_pgno; + u_int32_t id; +} __dbreg_register_args; + +extern __DB_IMPORT DB_LOG_RECSPEC __dbreg_register_desc[]; +static inline int +__dbreg_register_log(ENV *env, DB_TXN *txnp, DB_LSN *ret_lsnp, u_int32_t flags, + u_int32_t opcode, const DBT *name, const DBT *uid, int32_t fileid, DBTYPE ftype, + db_pgno_t meta_pgno, u_int32_t id) +{ + return (__log_put_record(env, NULL, txnp, ret_lsnp, + flags, DB___dbreg_register, 0, + sizeof(u_int32_t) + sizeof(u_int32_t) + sizeof(DB_LSN) + + sizeof(u_int32_t) + LOG_DBT_SIZE(name) + LOG_DBT_SIZE(uid) + + sizeof(u_int32_t) + sizeof(u_int32_t) + sizeof(u_int32_t) + + sizeof(u_int32_t), + __dbreg_register_desc, + opcode, name, uid, fileid, ftype, meta_pgno, id)); +} + +static inline int __dbreg_register_read(ENV *env, + void *data, __dbreg_register_args **arg) +{ + *arg = NULL; + return (__log_read_record(env, + NULL, NULL, data, __dbreg_register_desc, sizeof(__dbreg_register_args), (void**)arg)); +} +#endif diff -r 000000000000 -r a1985f14b030 src/dbinc_auto/dbreg_ext.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/dbinc_auto/dbreg_ext.h Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,72 @@ +/* DO NOT EDIT: automatically built by dist/s_include. + * + * Copyright (c) 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ +#ifndef _dbreg_ext_h_ +#define _dbreg_ext_h_ + +#if defined(__cplusplus) +extern "C" { +#endif + +int __dbreg_setup __P((DB *, const char *, const char *, u_int32_t)); +int __dbreg_teardown __P((DB *)); +int __dbreg_teardown_int __P((ENV *, FNAME *)); +int __dbreg_new_id __P((DB *, DB_TXN *)); +int __dbreg_get_id __P((DB *, DB_TXN *, int32_t *)); +int __dbreg_assign_id __P((DB *, int32_t, int)); +int __dbreg_revoke_id __P((DB *, int, int32_t)); +int __dbreg_revoke_id_int __P((ENV *, FNAME *, int, int, int32_t)); +int __dbreg_close_id __P((DB *, DB_TXN *, u_int32_t)); +int __dbreg_close_id_int __P((ENV *, FNAME *, u_int32_t, int)); +int __dbreg_failchk __P((ENV *)); +int __dbreg_log_close __P((ENV *, FNAME *, DB_TXN *, u_int32_t)); +int __dbreg_log_id __P((DB *, DB_TXN *, int32_t, int)); +int __dbreg_init_recover __P((ENV *, DB_DISTAB *)); +int __dbreg_register_print __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __dbreg_init_print __P((ENV *, DB_DISTAB *)); +int __dbreg_register_recover __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __dbreg_stat_print __P((ENV *, u_int32_t)); +void __dbreg_print_fname __P((ENV *, FNAME *)); +int __dbreg_add_dbentry __P((ENV *, DB_LOG *, DB *, int32_t)); +int __dbreg_rem_dbentry __P((DB_LOG *, int32_t)); +int __dbreg_log_files __P((ENV *, u_int32_t)); +int __dbreg_log_nofiles __P((ENV *)); +int __dbreg_close_files __P((ENV *, int)); +int __dbreg_close_file __P((ENV *, FNAME *)); +int __dbreg_mark_restored __P((ENV *)); +int __dbreg_invalidate_files __P((ENV *, int)); +int __dbreg_id_to_db __P((ENV *, DB_TXN *, DB **, int32_t, int)); +int __dbreg_id_to_fname __P((DB_LOG *, int32_t, int, FNAME **)); +int __dbreg_fid_to_fname __P((DB_LOG *, u_int8_t *, int, FNAME **)); +int __dbreg_get_name __P((ENV *, u_int8_t *, char **, char **)); +int __dbreg_do_open __P((ENV *, DB_TXN *, DB_LOG *, u_int8_t *, char *, DBTYPE, int32_t, db_pgno_t, void *, u_int32_t, u_int32_t)); +int __dbreg_lazy_id __P((DB *)); + +#if defined(__cplusplus) +} +#endif +#endif /* !_dbreg_ext_h_ */ diff -r 000000000000 -r a1985f14b030 src/dbinc_auto/env_ext.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/dbinc_auto/env_ext.h Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,184 @@ +/* DO NOT EDIT: automatically built by dist/s_include. + * + * Copyright (c) 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ +#ifndef _env_ext_h_ +#define _env_ext_h_ + +#if defined(__cplusplus) +extern "C" { +#endif + +void __env_alloc_init __P((REGINFO *, size_t)); +size_t __env_alloc_overhead __P((void)); +size_t __env_alloc_size __P((size_t)); +int __env_alloc __P((REGINFO *, size_t, void *)); +void __env_alloc_free __P((REGINFO *, void *)); +int __env_alloc_extend __P((REGINFO *, void *, size_t *)); +int __env_region_extend __P((ENV *, REGINFO *)); +uintmax_t __env_elem_size __P((ENV *, void *)); +void * __env_get_chunk __P((REGINFO *, void **, uintmax_t *)); +void __env_alloc_print __P((REGINFO *, u_int32_t)); +int __env_get_backup_config __P((DB_ENV *, DB_BACKUP_CONFIG, u_int32_t*)); +int __env_set_backup_config __P((DB_ENV *, DB_BACKUP_CONFIG, u_int32_t)); +int __env_get_backup_callbacks __P((DB_ENV *, int (**)(DB_ENV *, const char *, const char *, void **), int (**)(DB_ENV *, u_int32_t, u_int32_t, u_int32_t, u_int8_t *, void *), int (**)(DB_ENV *, const char *, void *))); +int __env_set_backup_callbacks __P((DB_ENV *, int (*)(DB_ENV *, const char *, const char *, void **), int (*)(DB_ENV *, u_int32_t, u_int32_t, u_int32_t, u_int8_t *, void *), int (*)(DB_ENV *, const char *, void *))); +int __env_read_db_config __P((ENV *)); +int __env_failchk_pp __P((DB_ENV *, u_int32_t)); +int __env_failchk_int __P((DB_ENV *)); +size_t __env_thread_size __P((ENV *, size_t)); +size_t __env_thread_max __P((ENV *)); +int __env_thread_init __P((ENV *, int)); +void __env_thread_destroy __P((ENV *)); +int __env_set_state __P((ENV *, DB_THREAD_INFO **, DB_THREAD_STATE)); +int __db_file_extend __P((ENV *, DB_FH *, size_t)); +int __db_file_multi_write __P((ENV *, const char *)); +int __db_file_write __P((ENV *, DB_FH *, u_int32_t, u_int32_t, int)); +void __db_env_destroy __P((DB_ENV *)); +int __env_get_alloc __P((DB_ENV *, void *(**)(size_t), void *(**)(void *, size_t), void (**)(void *))); +int __env_set_alloc __P((DB_ENV *, void *(*)(size_t), void *(*)(void *, size_t), void (*)(void *))); +int __env_get_memory_init __P((DB_ENV *, DB_MEM_CONFIG, u_int32_t *)); +int __env_set_memory_init __P((DB_ENV *, DB_MEM_CONFIG, u_int32_t)); +int __env_get_memory_max __P((DB_ENV *, u_int32_t *, u_int32_t *)); +int __env_set_memory_max __P((DB_ENV *, u_int32_t, u_int32_t)); +int __env_get_encrypt_flags __P((DB_ENV *, u_int32_t *)); +int __env_set_encrypt __P((DB_ENV *, const char *, u_int32_t)); +void __env_map_flags __P((const FLAG_MAP *, u_int, u_int32_t *, u_int32_t *)); +void __env_fetch_flags __P((const FLAG_MAP *, u_int, u_int32_t *, u_int32_t *)); +int __env_set_flags __P((DB_ENV *, u_int32_t, int)); +int __env_set_backup __P((ENV *, int)); +int __env_set_data_dir __P((DB_ENV *, const char *)); +int __env_add_data_dir __P((DB_ENV *, const char *)); +int __env_set_create_dir __P((DB_ENV *, const char *)); +int __env_set_metadata_dir __P((DB_ENV *, const char *)); +int __env_set_data_len __P((DB_ENV *, u_int32_t)); +int __env_set_intermediate_dir_mode __P((DB_ENV *, const char *)); +void __env_get_errcall __P((DB_ENV *, void (**)(const DB_ENV *, const char *, const char *))); +void __env_set_errcall __P((DB_ENV *, void (*)(const DB_ENV *, const char *, const char *))); +void __env_get_errfile __P((DB_ENV *, FILE **)); +void __env_set_errfile __P((DB_ENV *, FILE *)); +void __env_get_errpfx __P((DB_ENV *, const char **)); +void __env_set_errpfx __P((DB_ENV *, const char *)); +int __env_set_thread_count __P((DB_ENV *, u_int32_t)); +void __env_get_msgcall __P((DB_ENV *, void (**)(const DB_ENV *, const char *))); +void __env_set_msgcall __P((DB_ENV *, void (*)(const DB_ENV *, const char *))); +void __env_get_msgfile __P((DB_ENV *, FILE **)); +void __env_set_msgfile __P((DB_ENV *, FILE *)); +int __env_set_paniccall __P((DB_ENV *, void (*)(DB_ENV *, int))); +int __env_set_shm_key __P((DB_ENV *, long)); +int __env_set_tmp_dir __P((DB_ENV *, const char *)); +int __env_set_verbose __P((DB_ENV *, u_int32_t, int)); +int __db_mi_env __P((ENV *, const char *)); +int __db_mi_open __P((ENV *, const char *, int)); +int __env_not_config __P((ENV *, char *, u_int32_t)); +int __env_set_timeout __P((DB_ENV *, db_timeout_t, u_int32_t)); +char *__env_thread_id_string __P((DB_ENV *, pid_t, db_threadid_t, char *)); +int __db_appname __P((ENV *, APPNAME, const char *, const char **, char **)); +int __db_tmp_open __P((ENV *, u_int32_t, DB_FH **)); +int __env_open_pp __P((DB_ENV *, const char *, u_int32_t, int)); +int __env_open __P((DB_ENV *, const char *, u_int32_t, int)); +int __env_remove __P((DB_ENV *, const char *, u_int32_t)); +int __env_config __P((DB_ENV *, const char *, u_int32_t *, int)); +int __env_close_pp __P((DB_ENV *, u_int32_t)); +int __env_close __P((DB_ENV *, u_int32_t)); +int __env_refresh __P((DB_ENV *, u_int32_t, int)); +int __env_get_open_flags __P((DB_ENV *, u_int32_t *)); +int __env_attach_regions __P((DB_ENV *, u_int32_t, u_int32_t, int)); +int __db_apprec __P((ENV *, DB_THREAD_INFO *, DB_LSN *, DB_LSN *, int, u_int32_t)); +int __env_openfiles __P((ENV *, DB_LOGC *, void *, DBT *, DB_LSN *, DB_LSN *, double, int)); +int __env_init_rec __P((ENV *, u_int32_t)); +int __env_attach __P((ENV *, u_int32_t *, int, int)); +int __env_turn_on __P((ENV *)); +int __env_turn_off __P((ENV *, u_int32_t)); +void __env_panic_set __P((ENV *, int)); +int __env_ref_increment __P((ENV *)); +int __env_ref_decrement __P((ENV *)); +int __env_ref_get __P((DB_ENV *, u_int32_t *)); +int __env_detach __P((ENV *, int)); +int __env_remove_env __P((ENV *)); +int __env_region_attach __P((ENV *, REGINFO *, size_t, size_t)); +int __env_region_share __P((ENV *, REGINFO *)); +int __env_region_detach __P((ENV *, REGINFO *, int)); +int __envreg_register __P((ENV *, int *, u_int32_t)); +int __envreg_unregister __P((ENV *, int)); +int __envreg_xunlock __P((ENV *)); +int __envreg_isalive __P((DB_ENV *, pid_t, db_threadid_t, u_int32_t)); +u_int32_t __env_struct_sig __P((void)); +int __env_stat_print_pp __P((DB_ENV *, u_int32_t)); +void __db_print_fh __P((ENV *, const char *, DB_FH *, u_int32_t)); +void __db_print_fileid __P((ENV *, u_int8_t *, const char *)); +void __db_dl __P((ENV *, const char *, u_long)); +void __db_dl_pct __P((ENV *, const char *, u_long, int, const char *)); +void __db_dlbytes __P((ENV *, const char *, u_long, u_long, u_long)); +void __db_print_reginfo __P((ENV *, REGINFO *, const char *, u_int32_t)); +int __db_stat_not_built __P((ENV *)); +#ifndef HAVE_REPLICATION_THREADS +int __repmgr_close __P((ENV *)); +#endif +#ifndef HAVE_REPLICATION_THREADS +int __repmgr_get_ack_policy __P((DB_ENV *, int *)); +#endif +#ifndef HAVE_REPLICATION_THREADS +int __repmgr_set_ack_policy __P((DB_ENV *, int)); +#endif +#ifndef HAVE_REPLICATION_THREADS +int __repmgr_site __P((DB_ENV *, const char *, u_int, DB_SITE **, u_int32_t)); +#endif +#ifndef HAVE_REPLICATION_THREADS +int __repmgr_site_by_eid __P((DB_ENV *, int, DB_SITE **)); +#endif +#ifndef HAVE_REPLICATION_THREADS +int __repmgr_local_site __P((DB_ENV *, DB_SITE **)); +#endif +#ifndef HAVE_REPLICATION_THREADS +int __repmgr_site_list __P((DB_ENV *, u_int *, DB_REPMGR_SITE **)); +#endif +#ifndef HAVE_REPLICATION_THREADS +int __repmgr_start __P((DB_ENV *, int, u_int32_t)); +#endif +#ifndef HAVE_REPLICATION_THREADS +int __repmgr_stat_pp __P((DB_ENV *, DB_REPMGR_STAT **, u_int32_t)); +#endif +#ifndef HAVE_REPLICATION_THREADS +int __repmgr_stat_print_pp __P((DB_ENV *, u_int32_t)); +#endif +#ifndef HAVE_REPLICATION_THREADS +int __repmgr_handle_event __P((ENV *, u_int32_t, void *)); +#endif +#ifndef HAVE_REPLICATION_THREADS +int __repmgr_channel __P((DB_ENV *, int, DB_CHANNEL **, u_int32_t)); +#endif +#ifndef HAVE_REPLICATION_THREADS +int __repmgr_set_msg_dispatch __P((DB_ENV *, void (*)(DB_ENV *, DB_CHANNEL *, DBT *, u_int32_t, u_int32_t), u_int32_t)); +#endif +#ifndef HAVE_REPLICATION_THREADS +int __repmgr_init_recover __P((ENV *, DB_DISTAB *)); +#endif + +#if defined(__cplusplus) +} +#endif +#endif /* !_env_ext_h_ */ diff -r 000000000000 -r a1985f14b030 src/dbinc_auto/ext_185_def.in --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/dbinc_auto/ext_185_def.in Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,38 @@ + +/* DO NOT EDIT: automatically built by dist/s_include. + * + * Copyright (c) 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ +#ifndef _DB_EXT_185_DEF_IN_ +#define _DB_EXT_185_DEF_IN_ + +#ifdef _DB185_INT_H_ +#define __db185_open __db185_open@DB_VERSION_UNIQUE_NAME@ +#else +#define __db185_open __db185_open@DB_VERSION_UNIQUE_NAME@ +#endif + +#endif /* !_DB_EXT_185_DEF_IN_ */ diff -r 000000000000 -r a1985f14b030 src/dbinc_auto/ext_185_prot.in --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/dbinc_auto/ext_185_prot.in Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,45 @@ + +/* DO NOT EDIT: automatically built by dist/s_include. + * + * Copyright (c) 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ +#ifndef _DB_EXT_185_PROT_IN_ +#define _DB_EXT_185_PROT_IN_ + +#if defined(__cplusplus) +extern "C" { +#endif + +#ifdef _DB185_INT_H_ +DB185 *__db185_open __P((const char *, int, int, DBTYPE, const void *)); +#else +DB *__db185_open __P((const char *, int, int, DBTYPE, const void *)); +#endif + +#if defined(__cplusplus) +} +#endif +#endif /* !_DB_EXT_185_PROT_IN_ */ diff -r 000000000000 -r a1985f14b030 src/dbinc_auto/ext_def.in --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/dbinc_auto/ext_def.in Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,92 @@ + +/* DO NOT EDIT: automatically built by dist/s_include. + * + * Copyright (c) 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ +#ifndef _DB_EXT_DEF_IN_ +#define _DB_EXT_DEF_IN_ + +#define db_copy db_copy@DB_VERSION_UNIQUE_NAME@ +#define db_create db_create@DB_VERSION_UNIQUE_NAME@ +#define db_strerror db_strerror@DB_VERSION_UNIQUE_NAME@ +#define db_env_set_func_assert db_env_set_func_assert@DB_VERSION_UNIQUE_NAME@ +#define db_env_set_func_close db_env_set_func_close@DB_VERSION_UNIQUE_NAME@ +#define db_env_set_func_dirfree db_env_set_func_dirfree@DB_VERSION_UNIQUE_NAME@ +#define db_env_set_func_dirlist db_env_set_func_dirlist@DB_VERSION_UNIQUE_NAME@ +#define db_env_set_func_exists db_env_set_func_exists@DB_VERSION_UNIQUE_NAME@ +#define db_env_set_func_free db_env_set_func_free@DB_VERSION_UNIQUE_NAME@ +#define db_env_set_func_fsync db_env_set_func_fsync@DB_VERSION_UNIQUE_NAME@ +#define db_env_set_func_ftruncate db_env_set_func_ftruncate@DB_VERSION_UNIQUE_NAME@ +#define db_env_set_func_ioinfo db_env_set_func_ioinfo@DB_VERSION_UNIQUE_NAME@ +#define db_env_set_func_malloc db_env_set_func_malloc@DB_VERSION_UNIQUE_NAME@ +#define db_env_set_func_file_map db_env_set_func_file_map@DB_VERSION_UNIQUE_NAME@ +#define db_env_set_func_region_map db_env_set_func_region_map@DB_VERSION_UNIQUE_NAME@ +#define db_env_set_func_pread db_env_set_func_pread@DB_VERSION_UNIQUE_NAME@ +#define db_env_set_func_pwrite db_env_set_func_pwrite@DB_VERSION_UNIQUE_NAME@ +#define db_env_set_func_open db_env_set_func_open@DB_VERSION_UNIQUE_NAME@ +#define db_env_set_func_read db_env_set_func_read@DB_VERSION_UNIQUE_NAME@ +#define db_env_set_func_realloc db_env_set_func_realloc@DB_VERSION_UNIQUE_NAME@ +#define db_env_set_func_rename db_env_set_func_rename@DB_VERSION_UNIQUE_NAME@ +#define db_env_set_func_seek db_env_set_func_seek@DB_VERSION_UNIQUE_NAME@ +#define db_env_set_func_unlink db_env_set_func_unlink@DB_VERSION_UNIQUE_NAME@ +#define db_env_set_func_write db_env_set_func_write@DB_VERSION_UNIQUE_NAME@ +#define db_env_set_func_yield db_env_set_func_yield@DB_VERSION_UNIQUE_NAME@ +#define db_env_create db_env_create@DB_VERSION_UNIQUE_NAME@ +#define db_version db_version@DB_VERSION_UNIQUE_NAME@ +#define db_full_version db_full_version@DB_VERSION_UNIQUE_NAME@ +#define log_compare log_compare@DB_VERSION_UNIQUE_NAME@ +#if defined(DB_WIN32) && !defined(DB_WINCE) +#define db_env_set_win_security db_env_set_win_security@DB_VERSION_UNIQUE_NAME@ +#endif +#define db_sequence_create db_sequence_create@DB_VERSION_UNIQUE_NAME@ +#if DB_DBM_HSEARCH != 0 +#define __db_ndbm_clearerr __db_ndbm_clearerr@DB_VERSION_UNIQUE_NAME@ +#define __db_ndbm_close __db_ndbm_close@DB_VERSION_UNIQUE_NAME@ +#define __db_ndbm_delete __db_ndbm_delete@DB_VERSION_UNIQUE_NAME@ +#define __db_ndbm_dirfno __db_ndbm_dirfno@DB_VERSION_UNIQUE_NAME@ +#define __db_ndbm_error __db_ndbm_error@DB_VERSION_UNIQUE_NAME@ +#define __db_ndbm_fetch __db_ndbm_fetch@DB_VERSION_UNIQUE_NAME@ +#define __db_ndbm_firstkey __db_ndbm_firstkey@DB_VERSION_UNIQUE_NAME@ +#define __db_ndbm_nextkey __db_ndbm_nextkey@DB_VERSION_UNIQUE_NAME@ +#define __db_ndbm_open __db_ndbm_open@DB_VERSION_UNIQUE_NAME@ +#define __db_ndbm_pagfno __db_ndbm_pagfno@DB_VERSION_UNIQUE_NAME@ +#define __db_ndbm_rdonly __db_ndbm_rdonly@DB_VERSION_UNIQUE_NAME@ +#define __db_ndbm_store __db_ndbm_store@DB_VERSION_UNIQUE_NAME@ +#define __db_dbm_close __db_dbm_close@DB_VERSION_UNIQUE_NAME@ +#define __db_dbm_delete __db_dbm_delete@DB_VERSION_UNIQUE_NAME@ +#define __db_dbm_fetch __db_dbm_fetch@DB_VERSION_UNIQUE_NAME@ +#define __db_dbm_firstkey __db_dbm_firstkey@DB_VERSION_UNIQUE_NAME@ +#define __db_dbm_init __db_dbm_init@DB_VERSION_UNIQUE_NAME@ +#define __db_dbm_nextkey __db_dbm_nextkey@DB_VERSION_UNIQUE_NAME@ +#define __db_dbm_store __db_dbm_store@DB_VERSION_UNIQUE_NAME@ +#endif +#if DB_DBM_HSEARCH != 0 +#define __db_hcreate __db_hcreate@DB_VERSION_UNIQUE_NAME@ +#define __db_hsearch __db_hsearch@DB_VERSION_UNIQUE_NAME@ +#define __db_hdestroy __db_hdestroy@DB_VERSION_UNIQUE_NAME@ +#endif + +#endif /* !_DB_EXT_DEF_IN_ */ diff -r 000000000000 -r a1985f14b030 src/dbinc_auto/ext_prot.in --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/dbinc_auto/ext_prot.in Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,99 @@ + +/* DO NOT EDIT: automatically built by dist/s_include. + * + * Copyright (c) 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ +#ifndef _DB_EXT_PROT_IN_ +#define _DB_EXT_PROT_IN_ + +#if defined(__cplusplus) +extern "C" { +#endif + +int db_copy __P((DB_ENV *, const char *, const char *, const char *)); +int db_create __P((DB **, DB_ENV *, u_int32_t)); +char *db_strerror __P((int)); +int db_env_set_func_assert __P((void (*)(const char *, const char *, int))); +int db_env_set_func_close __P((int (*)(int))); +int db_env_set_func_dirfree __P((void (*)(char **, int))); +int db_env_set_func_dirlist __P((int (*)(const char *, char ***, int *))); +int db_env_set_func_exists __P((int (*)(const char *, int *))); +int db_env_set_func_free __P((void (*)(void *))); +int db_env_set_func_fsync __P((int (*)(int))); +int db_env_set_func_ftruncate __P((int (*)(int, off_t))); +int db_env_set_func_ioinfo __P((int (*)(const char *, int, u_int32_t *, u_int32_t *, u_int32_t *))); +int db_env_set_func_malloc __P((void *(*)(size_t))); +int db_env_set_func_file_map __P((int (*)(DB_ENV *, char *, size_t, int, void **), int (*)(DB_ENV *, void *))); +int db_env_set_func_region_map __P((int (*)(DB_ENV *, char *, size_t, int *, void **), int (*)(DB_ENV *, void *))); +int db_env_set_func_pread __P((ssize_t (*)(int, void *, size_t, off_t))); +int db_env_set_func_pwrite __P((ssize_t (*)(int, const void *, size_t, off_t))); +int db_env_set_func_open __P((int (*)(const char *, int, ...))); +int db_env_set_func_read __P((ssize_t (*)(int, void *, size_t))); +int db_env_set_func_realloc __P((void *(*)(void *, size_t))); +int db_env_set_func_rename __P((int (*)(const char *, const char *))); +int db_env_set_func_seek __P((int (*)(int, off_t, int))); +int db_env_set_func_unlink __P((int (*)(const char *))); +int db_env_set_func_write __P((ssize_t (*)(int, const void *, size_t))); +int db_env_set_func_yield __P((int (*)(u_long, u_long))); +int db_env_create __P((DB_ENV **, u_int32_t)); +char *db_version __P((int *, int *, int *)); +char *db_full_version __P((int *, int *, int *, int *, int *)); +int log_compare __P((const DB_LSN *, const DB_LSN *)); +#if defined(DB_WIN32) && !defined(DB_WINCE) +int db_env_set_win_security __P((SECURITY_ATTRIBUTES *sa)); +#endif +int db_sequence_create __P((DB_SEQUENCE **, DB *, u_int32_t)); +#if DB_DBM_HSEARCH != 0 +int __db_ndbm_clearerr __P((DBM *)); +void __db_ndbm_close __P((DBM *)); +int __db_ndbm_delete __P((DBM *, datum)); +int __db_ndbm_dirfno __P((DBM *)); +int __db_ndbm_error __P((DBM *)); +datum __db_ndbm_fetch __P((DBM *, datum)); +datum __db_ndbm_firstkey __P((DBM *)); +datum __db_ndbm_nextkey __P((DBM *)); +DBM *__db_ndbm_open __P((const char *, int, int)); +int __db_ndbm_pagfno __P((DBM *)); +int __db_ndbm_rdonly __P((DBM *)); +int __db_ndbm_store __P((DBM *, datum, datum, int)); +int __db_dbm_close __P((void)); +int __db_dbm_delete __P((datum)); +datum __db_dbm_fetch __P((datum)); +datum __db_dbm_firstkey __P((void)); +int __db_dbm_init __P((char *)); +datum __db_dbm_nextkey __P((datum)); +int __db_dbm_store __P((datum, datum)); +#endif +#if DB_DBM_HSEARCH != 0 +int __db_hcreate __P((size_t)); +ENTRY *__db_hsearch __P((ENTRY, ACTION)); +void __db_hdestroy __P((void)); +#endif + +#if defined(__cplusplus) +} +#endif +#endif /* !_DB_EXT_PROT_IN_ */ diff -r 000000000000 -r a1985f14b030 src/dbinc_auto/fileops_auto.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/dbinc_auto/fileops_auto.h Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,287 @@ +/* Do not edit: automatically built by gen_rec.awk. + * + * Copyright (c) 2012 Oracle and/or its affiliates. All rights reserved. * + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +#ifndef __fop_AUTO_H +#define __fop_AUTO_H +#include "dbinc/log.h" +#define DB___fop_create_42 143 +typedef struct ___fop_create_42_args { + u_int32_t type; + DB_TXN *txnp; + DB_LSN prev_lsn; + DBT name; + u_int32_t appname; + u_int32_t mode; +} __fop_create_42_args; + +extern __DB_IMPORT DB_LOG_RECSPEC __fop_create_42_desc[]; +static inline int __fop_create_42_read(ENV *env, + void *data, __fop_create_42_args **arg) +{ + *arg = NULL; + return (__log_read_record(env, + NULL, NULL, data, __fop_create_42_desc, sizeof(__fop_create_42_args), (void**)arg)); +} +#define DB___fop_create 143 +typedef struct ___fop_create_args { + u_int32_t type; + DB_TXN *txnp; + DB_LSN prev_lsn; + DBT name; + DBT dirname; + u_int32_t appname; + u_int32_t mode; +} __fop_create_args; + +extern __DB_IMPORT DB_LOG_RECSPEC __fop_create_desc[]; +static inline int +__fop_create_log(ENV *env, DB_TXN *txnp, DB_LSN *ret_lsnp, u_int32_t flags, + const DBT *name, const DBT *dirname, u_int32_t appname, u_int32_t mode) +{ + return (__log_put_record(env, NULL, txnp, ret_lsnp, + flags, DB___fop_create, 0, + sizeof(u_int32_t) + sizeof(u_int32_t) + sizeof(DB_LSN) + + LOG_DBT_SIZE(name) + LOG_DBT_SIZE(dirname) + sizeof(u_int32_t) + + sizeof(u_int32_t), + __fop_create_desc, + name, dirname, appname, mode)); +} + +static inline int __fop_create_read(ENV *env, + void *data, __fop_create_args **arg) +{ + *arg = NULL; + return (__log_read_record(env, + NULL, NULL, data, __fop_create_desc, sizeof(__fop_create_args), (void**)arg)); +} +#define DB___fop_remove 144 +typedef struct ___fop_remove_args { + u_int32_t type; + DB_TXN *txnp; + DB_LSN prev_lsn; + DBT name; + DBT fid; + u_int32_t appname; +} __fop_remove_args; + +extern __DB_IMPORT DB_LOG_RECSPEC __fop_remove_desc[]; +static inline int +__fop_remove_log(ENV *env, DB_TXN *txnp, DB_LSN *ret_lsnp, u_int32_t flags, + const DBT *name, const DBT *fid, u_int32_t appname) +{ + return (__log_put_record(env, NULL, txnp, ret_lsnp, + flags, DB___fop_remove, 0, + sizeof(u_int32_t) + sizeof(u_int32_t) + sizeof(DB_LSN) + + LOG_DBT_SIZE(name) + LOG_DBT_SIZE(fid) + sizeof(u_int32_t), + __fop_remove_desc, + name, fid, appname)); +} + +static inline int __fop_remove_read(ENV *env, + void *data, __fop_remove_args **arg) +{ + *arg = NULL; + return (__log_read_record(env, + NULL, NULL, data, __fop_remove_desc, sizeof(__fop_remove_args), (void**)arg)); +} +#define DB___fop_write_42 145 +typedef struct ___fop_write_42_args { + u_int32_t type; + DB_TXN *txnp; + DB_LSN prev_lsn; + DBT name; + u_int32_t appname; + u_int32_t pgsize; + db_pgno_t pageno; + u_int32_t offset; + DBT page; + u_int32_t flag; +} __fop_write_42_args; + +extern __DB_IMPORT DB_LOG_RECSPEC __fop_write_42_desc[]; +static inline int __fop_write_42_read(ENV *env, + void *data, __fop_write_42_args **arg) +{ + *arg = NULL; + return (__log_read_record(env, + NULL, NULL, data, __fop_write_42_desc, sizeof(__fop_write_42_args), (void**)arg)); +} +#define DB___fop_write 145 +typedef struct ___fop_write_args { + u_int32_t type; + DB_TXN *txnp; + DB_LSN prev_lsn; + DBT name; + DBT dirname; + u_int32_t appname; + u_int32_t pgsize; + db_pgno_t pageno; + u_int32_t offset; + DBT page; + u_int32_t flag; +} __fop_write_args; + +extern __DB_IMPORT DB_LOG_RECSPEC __fop_write_desc[]; +static inline int +__fop_write_log(ENV *env, DB_TXN *txnp, DB_LSN *ret_lsnp, u_int32_t flags, + const DBT *name, const DBT *dirname, u_int32_t appname, u_int32_t pgsize, db_pgno_t pageno, + u_int32_t offset, const DBT *page, u_int32_t flag) +{ + return (__log_put_record(env, NULL, txnp, ret_lsnp, + flags, DB___fop_write, 0, + sizeof(u_int32_t) + sizeof(u_int32_t) + sizeof(DB_LSN) + + LOG_DBT_SIZE(name) + LOG_DBT_SIZE(dirname) + sizeof(u_int32_t) + + sizeof(u_int32_t) + sizeof(u_int32_t) + sizeof(u_int32_t) + + LOG_DBT_SIZE(page) + sizeof(u_int32_t), + __fop_write_desc, + name, dirname, appname, pgsize, pageno, offset, page, flag)); +} + +static inline int __fop_write_read(ENV *env, + void *data, __fop_write_args **arg) +{ + *arg = NULL; + return (__log_read_record(env, + NULL, NULL, data, __fop_write_desc, sizeof(__fop_write_args), (void**)arg)); +} +#define DB___fop_rename_42 146 +#define DB___fop_rename_noundo_46 150 +typedef struct ___fop_rename_42_args { + u_int32_t type; + DB_TXN *txnp; + DB_LSN prev_lsn; + DBT oldname; + DBT newname; + DBT fileid; + u_int32_t appname; +} __fop_rename_42_args; + +extern __DB_IMPORT DB_LOG_RECSPEC __fop_rename_42_desc[]; +static inline int __fop_rename_42_read(ENV *env, + void *data, __fop_rename_42_args **arg) +{ + *arg = NULL; + return (__log_read_record(env, + NULL, NULL, data, __fop_rename_42_desc, sizeof(__fop_rename_42_args), (void**)arg)); +} +extern __DB_IMPORT DB_LOG_RECSPEC __fop_rename_noundo_46_desc[]; +static inline int __fop_rename_noundo_46_read(ENV *env, + void *data, __fop_rename_42_args **arg) +{ + *arg = NULL; + return (__log_read_record(env, + NULL, NULL, data, __fop_rename_noundo_46_desc, sizeof(__fop_rename_42_args), (void**)arg)); +} +#define DB___fop_rename 146 +#define DB___fop_rename_noundo 150 +typedef struct ___fop_rename_args { + u_int32_t type; + DB_TXN *txnp; + DB_LSN prev_lsn; + DBT oldname; + DBT newname; + DBT dirname; + DBT fileid; + u_int32_t appname; +} __fop_rename_args; + +extern __DB_IMPORT DB_LOG_RECSPEC __fop_rename_desc[]; +static inline int +__fop_rename_log(ENV *env, DB_TXN *txnp, DB_LSN *ret_lsnp, u_int32_t flags, + const DBT *oldname, const DBT *newname, const DBT *dirname, const DBT *fileid, u_int32_t appname) +{ + return (__log_put_record(env, NULL, txnp, ret_lsnp, + flags, DB___fop_rename, 0, + sizeof(u_int32_t) + sizeof(u_int32_t) + sizeof(DB_LSN) + + LOG_DBT_SIZE(oldname) + LOG_DBT_SIZE(newname) + LOG_DBT_SIZE(dirname) + + LOG_DBT_SIZE(fileid) + sizeof(u_int32_t), + __fop_rename_desc, + oldname, newname, dirname, fileid, appname)); +} + +static inline int __fop_rename_read(ENV *env, + void *data, __fop_rename_args **arg) +{ + *arg = NULL; + return (__log_read_record(env, + NULL, NULL, data, __fop_rename_desc, sizeof(__fop_rename_args), (void**)arg)); +} +extern __DB_IMPORT DB_LOG_RECSPEC __fop_rename_noundo_desc[]; +static inline int +__fop_rename_noundo_log(ENV *env, DB_TXN *txnp, DB_LSN *ret_lsnp, u_int32_t flags, + const DBT *oldname, const DBT *newname, const DBT *dirname, const DBT *fileid, u_int32_t appname) +{ + return (__log_put_record(env, NULL, txnp, ret_lsnp, + flags, DB___fop_rename_noundo, 0, + sizeof(u_int32_t) + sizeof(u_int32_t) + sizeof(DB_LSN) + + LOG_DBT_SIZE(oldname) + LOG_DBT_SIZE(newname) + LOG_DBT_SIZE(dirname) + + LOG_DBT_SIZE(fileid) + sizeof(u_int32_t), + __fop_rename_noundo_desc, + oldname, newname, dirname, fileid, appname)); +} + +static inline int __fop_rename_noundo_read(ENV *env, + void *data, __fop_rename_args **arg) +{ + *arg = NULL; + return (__log_read_record(env, + NULL, NULL, data, __fop_rename_noundo_desc, sizeof(__fop_rename_args), (void**)arg)); +} +#define DB___fop_file_remove 141 +typedef struct ___fop_file_remove_args { + u_int32_t type; + DB_TXN *txnp; + DB_LSN prev_lsn; + DBT real_fid; + DBT tmp_fid; + DBT name; + u_int32_t appname; + u_int32_t child; +} __fop_file_remove_args; + +extern __DB_IMPORT DB_LOG_RECSPEC __fop_file_remove_desc[]; +static inline int +__fop_file_remove_log(ENV *env, DB_TXN *txnp, DB_LSN *ret_lsnp, u_int32_t flags, + const DBT *real_fid, const DBT *tmp_fid, const DBT *name, u_int32_t appname, u_int32_t child) +{ + return (__log_put_record(env, NULL, txnp, ret_lsnp, + flags, DB___fop_file_remove, 0, + sizeof(u_int32_t) + sizeof(u_int32_t) + sizeof(DB_LSN) + + LOG_DBT_SIZE(real_fid) + LOG_DBT_SIZE(tmp_fid) + LOG_DBT_SIZE(name) + + sizeof(u_int32_t) + sizeof(u_int32_t), + __fop_file_remove_desc, + real_fid, tmp_fid, name, appname, child)); +} + +static inline int __fop_file_remove_read(ENV *env, + void *data, __fop_file_remove_args **arg) +{ + *arg = NULL; + return (__log_read_record(env, + NULL, NULL, data, __fop_file_remove_desc, sizeof(__fop_file_remove_args), (void**)arg)); +} +#endif diff -r 000000000000 -r a1985f14b030 src/dbinc_auto/fileops_ext.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/dbinc_auto/fileops_ext.h Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,70 @@ +/* DO NOT EDIT: automatically built by dist/s_include. + * + * Copyright (c) 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ +#ifndef _fileops_ext_h_ +#define _fileops_ext_h_ + +#if defined(__cplusplus) +extern "C" { +#endif + +int __fop_init_recover __P((ENV *, DB_DISTAB *)); +int __fop_create_42_print __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __fop_create_print __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __fop_remove_print __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __fop_write_42_print __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __fop_write_print __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __fop_rename_42_print __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __fop_rename_print __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __fop_file_remove_print __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __fop_init_print __P((ENV *, DB_DISTAB *)); +int __fop_create __P((ENV *, DB_TXN *, DB_FH **, const char *, const char **, APPNAME, int, u_int32_t)); +int __fop_remove __P((ENV *, DB_TXN *, u_int8_t *, const char *, const char **, APPNAME, u_int32_t)); +int __fop_write __P((ENV *, DB_TXN *, const char *, const char *, APPNAME, DB_FH *, u_int32_t, db_pgno_t, u_int32_t, void *, u_int32_t, u_int32_t, u_int32_t)); +int __fop_rename __P((ENV *, DB_TXN *, const char *, const char *, const char **, u_int8_t *, APPNAME, int, u_int32_t)); +int __fop_create_recover __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __fop_create_42_recover __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __fop_remove_recover __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __fop_write_recover __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __fop_write_42_recover __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __fop_rename_recover __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __fop_rename_noundo_recover __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __fop_rename_42_recover __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __fop_rename_noundo_46_recover __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __fop_file_remove_recover __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __fop_lock_handle __P((ENV *, DB *, DB_LOCKER *, db_lockmode_t, DB_LOCK *, u_int32_t)); +int __fop_file_setup __P((DB *, DB_THREAD_INFO *ip, DB_TXN *, const char *, int, u_int32_t, u_int32_t *)); +int __fop_subdb_setup __P((DB *, DB_THREAD_INFO *, DB_TXN *, const char *, const char *, int, u_int32_t)); +int __fop_remove_setup __P((DB *, DB_TXN *, const char *, u_int32_t)); +int __fop_read_meta __P((ENV *, const char *, u_int8_t *, size_t, DB_FH *, int, size_t *)); +int __fop_dummy __P((DB *, DB_TXN *, const char *, const char *)); +int __fop_dbrename __P((DB *, const char *, const char *)); + +#if defined(__cplusplus) +} +#endif +#endif /* !_fileops_ext_h_ */ diff -r 000000000000 -r a1985f14b030 src/dbinc_auto/hash_auto.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/dbinc_auto/hash_auto.h Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,509 @@ +/* Do not edit: automatically built by gen_rec.awk. + * + * Copyright (c) 2012 Oracle and/or its affiliates. All rights reserved. * + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +#ifndef __ham_AUTO_H +#define __ham_AUTO_H +#ifdef HAVE_HASH +#include "dbinc/log.h" +#define DB___ham_insdel 21 +typedef struct ___ham_insdel_args { + u_int32_t type; + DB_TXN *txnp; + DB_LSN prev_lsn; + u_int32_t opcode; + int32_t fileid; + db_pgno_t pgno; + u_int32_t ndx; + DB_LSN pagelsn; + u_int32_t keytype; + DBT key; + u_int32_t datatype; + DBT data; +} __ham_insdel_args; + +extern __DB_IMPORT DB_LOG_RECSPEC __ham_insdel_desc[]; +static inline int +__ham_insdel_log(DB *dbp, DB_TXN *txnp, DB_LSN *ret_lsnp, u_int32_t flags, + u_int32_t opcode, db_pgno_t pgno, u_int32_t ndx, DB_LSN * pagelsn, + u_int32_t keytype, const DBT *key, u_int32_t datatype, const DBT *data) +{ + return (__log_put_record((dbp)->env, dbp, txnp, ret_lsnp, + flags, DB___ham_insdel, 0, + sizeof(u_int32_t) + sizeof(u_int32_t) + sizeof(DB_LSN) + + sizeof(u_int32_t) + sizeof(u_int32_t) + sizeof(u_int32_t) + + sizeof(u_int32_t) + sizeof(*pagelsn) + sizeof(u_int32_t) + + LOG_DBT_SIZE(key) + sizeof(u_int32_t) + LOG_DBT_SIZE(data), + __ham_insdel_desc, + opcode, pgno, ndx, pagelsn, keytype, key, datatype, + data)); +} + +static inline int __ham_insdel_read(ENV *env, + DB **dbpp, void *td, void *data, __ham_insdel_args **arg) +{ + *arg = NULL; + return (__log_read_record(env, + dbpp, td, data, __ham_insdel_desc, sizeof(__ham_insdel_args), (void**)arg)); +} +#define DB___ham_insdel_42 21 +typedef struct ___ham_insdel_42_args { + u_int32_t type; + DB_TXN *txnp; + DB_LSN prev_lsn; + u_int32_t opcode; + int32_t fileid; + db_pgno_t pgno; + u_int32_t ndx; + DB_LSN pagelsn; + DBT key; + DBT data; +} __ham_insdel_42_args; + +extern __DB_IMPORT DB_LOG_RECSPEC __ham_insdel_42_desc[]; +static inline int __ham_insdel_42_read(ENV *env, + DB **dbpp, void *td, void *data, __ham_insdel_42_args **arg) +{ + *arg = NULL; + return (__log_read_record(env, + dbpp, td, data, __ham_insdel_42_desc, sizeof(__ham_insdel_42_args), (void**)arg)); +} +#define DB___ham_newpage 22 +typedef struct ___ham_newpage_args { + u_int32_t type; + DB_TXN *txnp; + DB_LSN prev_lsn; + u_int32_t opcode; + int32_t fileid; + db_pgno_t prev_pgno; + DB_LSN prevlsn; + db_pgno_t new_pgno; + DB_LSN pagelsn; + db_pgno_t next_pgno; + DB_LSN nextlsn; +} __ham_newpage_args; + +extern __DB_IMPORT DB_LOG_RECSPEC __ham_newpage_desc[]; +static inline int +__ham_newpage_log(DB *dbp, DB_TXN *txnp, DB_LSN *ret_lsnp, u_int32_t flags, + u_int32_t opcode, db_pgno_t prev_pgno, DB_LSN * prevlsn, db_pgno_t new_pgno, + DB_LSN * pagelsn, db_pgno_t next_pgno, DB_LSN * nextlsn) +{ + return (__log_put_record((dbp)->env, dbp, txnp, ret_lsnp, + flags, DB___ham_newpage, 0, + sizeof(u_int32_t) + sizeof(u_int32_t) + sizeof(DB_LSN) + + sizeof(u_int32_t) + sizeof(u_int32_t) + sizeof(u_int32_t) + + sizeof(*prevlsn) + sizeof(u_int32_t) + sizeof(*pagelsn) + + sizeof(u_int32_t) + sizeof(*nextlsn), + __ham_newpage_desc, + opcode, prev_pgno, prevlsn, new_pgno, pagelsn, next_pgno, nextlsn)); +} + +static inline int __ham_newpage_read(ENV *env, + DB **dbpp, void *td, void *data, __ham_newpage_args **arg) +{ + *arg = NULL; + return (__log_read_record(env, + dbpp, td, data, __ham_newpage_desc, sizeof(__ham_newpage_args), (void**)arg)); +} +#define DB___ham_splitdata 24 +typedef struct ___ham_splitdata_args { + u_int32_t type; + DB_TXN *txnp; + DB_LSN prev_lsn; + int32_t fileid; + u_int32_t opcode; + db_pgno_t pgno; + DBT pageimage; + DB_LSN pagelsn; +} __ham_splitdata_args; + +extern __DB_IMPORT DB_LOG_RECSPEC __ham_splitdata_desc[]; +static inline int +__ham_splitdata_log(DB *dbp, DB_TXN *txnp, DB_LSN *ret_lsnp, u_int32_t flags, u_int32_t opcode, db_pgno_t pgno, const DBT *pageimage, DB_LSN * pagelsn) +{ + return (__log_put_record((dbp)->env, dbp, txnp, ret_lsnp, + flags, DB___ham_splitdata, 0, + sizeof(u_int32_t) + sizeof(u_int32_t) + sizeof(DB_LSN) + + sizeof(u_int32_t) + sizeof(u_int32_t) + sizeof(u_int32_t) + + LOG_DBT_SIZE(pageimage) + sizeof(*pagelsn), + __ham_splitdata_desc, opcode, pgno, pageimage, pagelsn)); +} + +static inline int __ham_splitdata_read(ENV *env, + DB **dbpp, void *td, void *data, __ham_splitdata_args **arg) +{ + *arg = NULL; + return (__log_read_record(env, + dbpp, td, data, __ham_splitdata_desc, sizeof(__ham_splitdata_args), (void**)arg)); +} +#define DB___ham_replace 25 +typedef struct ___ham_replace_args { + u_int32_t type; + DB_TXN *txnp; + DB_LSN prev_lsn; + int32_t fileid; + db_pgno_t pgno; + u_int32_t ndx; + DB_LSN pagelsn; + int32_t off; + u_int32_t oldtype; + DBT olditem; + u_int32_t newtype; + DBT newitem; +} __ham_replace_args; + +extern __DB_IMPORT DB_LOG_RECSPEC __ham_replace_desc[]; +static inline int +__ham_replace_log(DB *dbp, DB_TXN *txnp, DB_LSN *ret_lsnp, u_int32_t flags, db_pgno_t pgno, u_int32_t ndx, DB_LSN * pagelsn, int32_t off, + u_int32_t oldtype, const DBT *olditem, u_int32_t newtype, const DBT *newitem) +{ + return (__log_put_record((dbp)->env, dbp, txnp, ret_lsnp, + flags, DB___ham_replace, 0, + sizeof(u_int32_t) + sizeof(u_int32_t) + sizeof(DB_LSN) + + sizeof(u_int32_t) + sizeof(u_int32_t) + sizeof(u_int32_t) + + sizeof(*pagelsn) + sizeof(u_int32_t) + sizeof(u_int32_t) + + LOG_DBT_SIZE(olditem) + sizeof(u_int32_t) + LOG_DBT_SIZE(newitem), + __ham_replace_desc, pgno, ndx, pagelsn, off, oldtype, olditem, newtype, + newitem)); +} + +static inline int __ham_replace_read(ENV *env, + DB **dbpp, void *td, void *data, __ham_replace_args **arg) +{ + *arg = NULL; + return (__log_read_record(env, + dbpp, td, data, __ham_replace_desc, sizeof(__ham_replace_args), (void**)arg)); +} +#define DB___ham_replace_42 25 +typedef struct ___ham_replace_42_args { + u_int32_t type; + DB_TXN *txnp; + DB_LSN prev_lsn; + int32_t fileid; + db_pgno_t pgno; + u_int32_t ndx; + DB_LSN pagelsn; + int32_t off; + DBT olditem; + DBT newitem; + u_int32_t makedup; +} __ham_replace_42_args; + +extern __DB_IMPORT DB_LOG_RECSPEC __ham_replace_42_desc[]; +static inline int __ham_replace_42_read(ENV *env, + DB **dbpp, void *td, void *data, __ham_replace_42_args **arg) +{ + *arg = NULL; + return (__log_read_record(env, + dbpp, td, data, __ham_replace_42_desc, sizeof(__ham_replace_42_args), (void**)arg)); +} +#define DB___ham_copypage 28 +typedef struct ___ham_copypage_args { + u_int32_t type; + DB_TXN *txnp; + DB_LSN prev_lsn; + int32_t fileid; + db_pgno_t pgno; + DB_LSN pagelsn; + db_pgno_t next_pgno; + DB_LSN nextlsn; + db_pgno_t nnext_pgno; + DB_LSN nnextlsn; + DBT page; +} __ham_copypage_args; + +extern __DB_IMPORT DB_LOG_RECSPEC __ham_copypage_desc[]; +static inline int +__ham_copypage_log(DB *dbp, DB_TXN *txnp, DB_LSN *ret_lsnp, u_int32_t flags, db_pgno_t pgno, DB_LSN * pagelsn, db_pgno_t next_pgno, DB_LSN * nextlsn, + db_pgno_t nnext_pgno, DB_LSN * nnextlsn, const DBT *page) +{ + return (__log_put_record((dbp)->env, dbp, txnp, ret_lsnp, + flags, DB___ham_copypage, 0, + sizeof(u_int32_t) + sizeof(u_int32_t) + sizeof(DB_LSN) + + sizeof(u_int32_t) + sizeof(u_int32_t) + sizeof(*pagelsn) + + sizeof(u_int32_t) + sizeof(*nextlsn) + sizeof(u_int32_t) + + sizeof(*nnextlsn) + LOG_DBT_SIZE(page), + __ham_copypage_desc, pgno, pagelsn, next_pgno, nextlsn, nnext_pgno, nnextlsn, page)); +} + +static inline int __ham_copypage_read(ENV *env, + DB **dbpp, void *td, void *data, __ham_copypage_args **arg) +{ + *arg = NULL; + return (__log_read_record(env, + dbpp, td, data, __ham_copypage_desc, sizeof(__ham_copypage_args), (void**)arg)); +} +#define DB___ham_metagroup_42 29 +typedef struct ___ham_metagroup_42_args { + u_int32_t type; + DB_TXN *txnp; + DB_LSN prev_lsn; + int32_t fileid; + u_int32_t bucket; + db_pgno_t mmpgno; + DB_LSN mmetalsn; + db_pgno_t mpgno; + DB_LSN metalsn; + db_pgno_t pgno; + DB_LSN pagelsn; + u_int32_t newalloc; +} __ham_metagroup_42_args; + +extern __DB_IMPORT DB_LOG_RECSPEC __ham_metagroup_42_desc[]; +static inline int __ham_metagroup_42_read(ENV *env, + DB **dbpp, void *td, void *data, __ham_metagroup_42_args **arg) +{ + *arg = NULL; + return (__log_read_record(env, + dbpp, td, data, __ham_metagroup_42_desc, sizeof(__ham_metagroup_42_args), (void**)arg)); +} +#define DB___ham_metagroup 29 +typedef struct ___ham_metagroup_args { + u_int32_t type; + DB_TXN *txnp; + DB_LSN prev_lsn; + int32_t fileid; + u_int32_t bucket; + db_pgno_t mmpgno; + DB_LSN mmetalsn; + db_pgno_t mpgno; + DB_LSN metalsn; + db_pgno_t pgno; + DB_LSN pagelsn; + u_int32_t newalloc; + db_pgno_t last_pgno; +} __ham_metagroup_args; + +extern __DB_IMPORT DB_LOG_RECSPEC __ham_metagroup_desc[]; +static inline int +__ham_metagroup_log(DB *dbp, DB_TXN *txnp, DB_LSN *ret_lsnp, u_int32_t flags, u_int32_t bucket, db_pgno_t mmpgno, DB_LSN * mmetalsn, db_pgno_t mpgno, + DB_LSN * metalsn, db_pgno_t pgno, DB_LSN * pagelsn, u_int32_t newalloc, db_pgno_t last_pgno) +{ + return (__log_put_record((dbp)->env, dbp, txnp, ret_lsnp, + flags, DB___ham_metagroup, 0, + sizeof(u_int32_t) + sizeof(u_int32_t) + sizeof(DB_LSN) + + sizeof(u_int32_t) + sizeof(u_int32_t) + sizeof(u_int32_t) + + sizeof(*mmetalsn) + sizeof(u_int32_t) + sizeof(*metalsn) + + sizeof(u_int32_t) + sizeof(*pagelsn) + sizeof(u_int32_t) + + sizeof(u_int32_t), + __ham_metagroup_desc, bucket, mmpgno, mmetalsn, mpgno, metalsn, pgno, pagelsn, + newalloc, last_pgno)); +} + +static inline int __ham_metagroup_read(ENV *env, + DB **dbpp, void *td, void *data, __ham_metagroup_args **arg) +{ + *arg = NULL; + return (__log_read_record(env, + dbpp, td, data, __ham_metagroup_desc, sizeof(__ham_metagroup_args), (void**)arg)); +} +#define DB___ham_groupalloc_42 32 +typedef struct ___ham_groupalloc_42_args { + u_int32_t type; + DB_TXN *txnp; + DB_LSN prev_lsn; + int32_t fileid; + DB_LSN meta_lsn; + db_pgno_t start_pgno; + u_int32_t num; + db_pgno_t free; +} __ham_groupalloc_42_args; + +extern __DB_IMPORT DB_LOG_RECSPEC __ham_groupalloc_42_desc[]; +static inline int __ham_groupalloc_42_read(ENV *env, + DB **dbpp, void *td, void *data, __ham_groupalloc_42_args **arg) +{ + *arg = NULL; + return (__log_read_record(env, + dbpp, td, data, __ham_groupalloc_42_desc, sizeof(__ham_groupalloc_42_args), (void**)arg)); +} +#define DB___ham_groupalloc 32 +typedef struct ___ham_groupalloc_args { + u_int32_t type; + DB_TXN *txnp; + DB_LSN prev_lsn; + int32_t fileid; + DB_LSN meta_lsn; + db_pgno_t start_pgno; + u_int32_t num; + db_pgno_t unused; + db_pgno_t last_pgno; +} __ham_groupalloc_args; + +extern __DB_IMPORT DB_LOG_RECSPEC __ham_groupalloc_desc[]; +static inline int +__ham_groupalloc_log(DB *dbp, DB_TXN *txnp, DB_LSN *ret_lsnp, u_int32_t flags, DB_LSN * meta_lsn, db_pgno_t start_pgno, u_int32_t num, db_pgno_t unused, + db_pgno_t last_pgno) +{ + return (__log_put_record((dbp)->env, dbp, txnp, ret_lsnp, + flags, DB___ham_groupalloc, 0, + sizeof(u_int32_t) + sizeof(u_int32_t) + sizeof(DB_LSN) + + sizeof(u_int32_t) + sizeof(*meta_lsn) + sizeof(u_int32_t) + + sizeof(u_int32_t) + sizeof(u_int32_t) + sizeof(u_int32_t), + __ham_groupalloc_desc, meta_lsn, start_pgno, num, unused, last_pgno)); +} + +static inline int __ham_groupalloc_read(ENV *env, + DB **dbpp, void *td, void *data, __ham_groupalloc_args **arg) +{ + *arg = NULL; + return (__log_read_record(env, + dbpp, td, data, __ham_groupalloc_desc, sizeof(__ham_groupalloc_args), (void**)arg)); +} +#define DB___ham_changeslot 35 +typedef struct ___ham_changeslot_args { + u_int32_t type; + DB_TXN *txnp; + DB_LSN prev_lsn; + int32_t fileid; + DB_LSN meta_lsn; + u_int32_t slot; + db_pgno_t old; + db_pgno_t new; +} __ham_changeslot_args; + +extern __DB_IMPORT DB_LOG_RECSPEC __ham_changeslot_desc[]; +static inline int +__ham_changeslot_log(DB *dbp, DB_TXN *txnp, DB_LSN *ret_lsnp, u_int32_t flags, DB_LSN * meta_lsn, u_int32_t slot, db_pgno_t old, db_pgno_t new) +{ + return (__log_put_record((dbp)->env, dbp, txnp, ret_lsnp, + flags, DB___ham_changeslot, 0, + sizeof(u_int32_t) + sizeof(u_int32_t) + sizeof(DB_LSN) + + sizeof(u_int32_t) + sizeof(*meta_lsn) + sizeof(u_int32_t) + + sizeof(u_int32_t) + sizeof(u_int32_t), + __ham_changeslot_desc, meta_lsn, slot, old, new)); +} + +static inline int __ham_changeslot_read(ENV *env, + DB **dbpp, void *td, void *data, __ham_changeslot_args **arg) +{ + *arg = NULL; + return (__log_read_record(env, + dbpp, td, data, __ham_changeslot_desc, sizeof(__ham_changeslot_args), (void**)arg)); +} +#define DB___ham_contract 37 +typedef struct ___ham_contract_args { + u_int32_t type; + DB_TXN *txnp; + DB_LSN prev_lsn; + int32_t fileid; + db_pgno_t meta; + DB_LSN meta_lsn; + u_int32_t bucket; + db_pgno_t pgno; +} __ham_contract_args; + +extern __DB_IMPORT DB_LOG_RECSPEC __ham_contract_desc[]; +static inline int +__ham_contract_log(DB *dbp, DB_TXN *txnp, DB_LSN *ret_lsnp, u_int32_t flags, db_pgno_t meta, DB_LSN * meta_lsn, u_int32_t bucket, db_pgno_t pgno) +{ + return (__log_put_record((dbp)->env, dbp, txnp, ret_lsnp, + flags, DB___ham_contract, 0, + sizeof(u_int32_t) + sizeof(u_int32_t) + sizeof(DB_LSN) + + sizeof(u_int32_t) + sizeof(u_int32_t) + sizeof(*meta_lsn) + + sizeof(u_int32_t) + sizeof(u_int32_t), + __ham_contract_desc, meta, meta_lsn, bucket, pgno)); +} + +static inline int __ham_contract_read(ENV *env, + DB **dbpp, void *td, void *data, __ham_contract_args **arg) +{ + *arg = NULL; + return (__log_read_record(env, + dbpp, td, data, __ham_contract_desc, sizeof(__ham_contract_args), (void**)arg)); +} +#define DB___ham_curadj 33 +typedef struct ___ham_curadj_args { + u_int32_t type; + DB_TXN *txnp; + DB_LSN prev_lsn; + int32_t fileid; + db_pgno_t pgno; + u_int32_t indx; + u_int32_t len; + u_int32_t dup_off; + int add; + int is_dup; + u_int32_t order; +} __ham_curadj_args; + +extern __DB_IMPORT DB_LOG_RECSPEC __ham_curadj_desc[]; +static inline int +__ham_curadj_log(DB *dbp, DB_TXN *txnp, DB_LSN *ret_lsnp, u_int32_t flags, db_pgno_t pgno, u_int32_t indx, u_int32_t len, u_int32_t dup_off, + int add, int is_dup, u_int32_t order) +{ + return (__log_put_record((dbp)->env, dbp, txnp, ret_lsnp, + flags, DB___ham_curadj, 0, + sizeof(u_int32_t) + sizeof(u_int32_t) + sizeof(DB_LSN) + + sizeof(u_int32_t) + sizeof(u_int32_t) + sizeof(u_int32_t) + + sizeof(u_int32_t) + sizeof(u_int32_t) + sizeof(u_int32_t) + + sizeof(u_int32_t) + sizeof(u_int32_t), + __ham_curadj_desc, pgno, indx, len, dup_off, add, is_dup, order)); +} + +static inline int __ham_curadj_read(ENV *env, + DB **dbpp, void *td, void *data, __ham_curadj_args **arg) +{ + *arg = NULL; + return (__log_read_record(env, + dbpp, td, data, __ham_curadj_desc, sizeof(__ham_curadj_args), (void**)arg)); +} +#define DB___ham_chgpg 34 +typedef struct ___ham_chgpg_args { + u_int32_t type; + DB_TXN *txnp; + DB_LSN prev_lsn; + int32_t fileid; + db_ham_mode mode; + db_pgno_t old_pgno; + db_pgno_t new_pgno; + u_int32_t old_indx; + u_int32_t new_indx; +} __ham_chgpg_args; + +extern __DB_IMPORT DB_LOG_RECSPEC __ham_chgpg_desc[]; +static inline int +__ham_chgpg_log(DB *dbp, DB_TXN *txnp, DB_LSN *ret_lsnp, u_int32_t flags, db_ham_mode mode, db_pgno_t old_pgno, db_pgno_t new_pgno, u_int32_t old_indx, + u_int32_t new_indx) +{ + return (__log_put_record((dbp)->env, dbp, txnp, ret_lsnp, + flags, DB___ham_chgpg, 0, + sizeof(u_int32_t) + sizeof(u_int32_t) + sizeof(DB_LSN) + + sizeof(u_int32_t) + sizeof(u_int32_t) + sizeof(u_int32_t) + + sizeof(u_int32_t) + sizeof(u_int32_t) + sizeof(u_int32_t), + __ham_chgpg_desc, mode, old_pgno, new_pgno, old_indx, new_indx)); +} + +static inline int __ham_chgpg_read(ENV *env, + DB **dbpp, void *td, void *data, __ham_chgpg_args **arg) +{ + *arg = NULL; + return (__log_read_record(env, + dbpp, td, data, __ham_chgpg_desc, sizeof(__ham_chgpg_args), (void**)arg)); +} +#endif /* HAVE_HASH */ +#endif diff -r 000000000000 -r a1985f14b030 src/dbinc_auto/hash_ext.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/dbinc_auto/hash_ext.h Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,155 @@ +/* DO NOT EDIT: automatically built by dist/s_include. + * + * Copyright (c) 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ +#ifndef _hash_ext_h_ +#define _hash_ext_h_ + +#if defined(__cplusplus) +extern "C" { +#endif + +int __ham_quick_delete __P((DBC *)); +int __hamc_init __P((DBC *)); +int __hamc_count __P((DBC *, db_recno_t *)); +int __hamc_cmp __P((DBC *, DBC *, int *)); +int __hamc_dup __P((DBC *, DBC *)); +int __ham_contract_table __P((DBC *, DB_COMPACT *)); +u_int32_t __ham_call_hash __P((DBC *, u_int8_t *, u_int32_t)); +int __ham_overwrite __P((DBC *, DBT *, u_int32_t)); +int __ham_lookup __P((DBC *, const DBT *, u_int32_t, db_lockmode_t, db_pgno_t *)); +int __ham_init_dbt __P((ENV *, DBT *, u_int32_t, void **, u_int32_t *)); +int __hamc_update __P((DBC *, u_int32_t, db_ham_curadj, int)); +int __ham_get_clist __P((DB *, db_pgno_t, u_int32_t, DBC ***)); +int __ham_init_recover __P((ENV *, DB_DISTAB *)); +int __ham_insdel_print __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __ham_insdel_42_print __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __ham_newpage_print __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __ham_splitdata_print __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __ham_replace_print __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __ham_replace_42_print __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __ham_copypage_print __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __ham_metagroup_42_print __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __ham_metagroup_print __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __ham_groupalloc_42_print __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __ham_groupalloc_print __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __ham_changeslot_print __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __ham_contract_print __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __ham_curadj_print __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __ham_chgpg_print __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __ham_init_print __P((ENV *, DB_DISTAB *)); +int __ham_compact_int __P((DBC *, DBT *, DBT *, u_int32_t, DB_COMPACT *, int *, u_int32_t)); +int __ham_compact_bucket __P((DBC *, DB_COMPACT *, int *)); +int __ham_compact_hash __P((DB *, DB_THREAD_INFO *, DB_TXN *, DB_COMPACT *)); +int __ham_pgin __P((DB *, db_pgno_t, void *, DBT *)); +int __ham_pgout __P((DB *, db_pgno_t, void *, DBT *)); +int __ham_mswap __P((ENV *, void *)); +int __ham_add_dup __P((DBC *, DBT *, u_int32_t, db_pgno_t *)); +int __ham_dup_convert __P((DBC *)); +int __ham_make_dup __P((ENV *, const DBT *, DBT *d, void **, u_int32_t *)); +void __ham_dsearch __P((DBC *, DBT *, u_int32_t *, int *, u_int32_t)); +u_int32_t __ham_func2 __P((DB *, const void *, u_int32_t)); +u_int32_t __ham_func3 __P((DB *, const void *, u_int32_t)); +u_int32_t __ham_func4 __P((DB *, const void *, u_int32_t)); +u_int32_t __ham_func5 __P((DB *, const void *, u_int32_t)); +u_int32_t __ham_test __P((DB *, const void *, u_int32_t)); +int __ham_get_meta __P((DBC *)); +int __ham_release_meta __P((DBC *)); +int __ham_dirty_meta __P((DBC *, u_int32_t)); +int __ham_return_meta __P((DBC *, u_int32_t, DBMETA **)); +int __ham_db_create __P((DB *)); +int __ham_db_close __P((DB *)); +int __ham_get_h_ffactor __P((DB *, u_int32_t *)); +int __ham_set_h_compare __P((DB *, int (*)(DB *, const DBT *, const DBT *))); +int __ham_get_h_nelem __P((DB *, u_int32_t *)); +void __ham_copy_config __P((DB *, DB*, u_int32_t)); +int __ham_open __P((DB *, DB_THREAD_INFO *, DB_TXN *, const char * name, db_pgno_t, u_int32_t)); +int __ham_metachk __P((DB *, const char *, HMETA *)); +int __ham_new_file __P((DB *, DB_THREAD_INFO *, DB_TXN *, DB_FH *, const char *)); +int __ham_new_subdb __P((DB *, DB *, DB_THREAD_INFO *, DB_TXN *)); +int __ham_item __P((DBC *, db_lockmode_t, db_pgno_t *)); +int __ham_item_reset __P((DBC *)); +int __ham_item_init __P((DBC *)); +int __ham_item_last __P((DBC *, db_lockmode_t, db_pgno_t *)); +int __ham_item_first __P((DBC *, db_lockmode_t, db_pgno_t *)); +int __ham_item_prev __P((DBC *, db_lockmode_t, db_pgno_t *)); +int __ham_item_next __P((DBC *, db_lockmode_t, db_pgno_t *)); +int __ham_insertpair __P((DBC *, PAGE *p, db_indx_t *indxp, const DBT *, const DBT *, u_int32_t, u_int32_t)); +int __ham_getindex __P((DBC *, PAGE *, const DBT *, u_int32_t, int *, db_indx_t *)); +int __ham_verify_sorted_page __P((DBC *, PAGE *)); +int __ham_sort_page_cursor __P((DBC *, PAGE *)); +int __ham_sort_page __P((DBC *, PAGE **, PAGE *)); +int __ham_del_pair __P((DBC *, int, PAGE *)); +int __ham_replpair __P((DBC *, DBT *, u_int32_t)); +void __ham_onpage_replace __P((DB *, PAGE *, u_int32_t, int32_t, u_int32_t, int, DBT *)); +int __ham_merge_pages __P((DBC *, u_int32_t, u_int32_t, DB_COMPACT *)); +int __ham_split_page __P((DBC *, u_int32_t, u_int32_t)); +int __ham_add_el __P((DBC *, const DBT *, const DBT *, u_int32_t)); +int __ham_copypair __P((DBC *, PAGE *, u_int32_t, PAGE *, db_indx_t *, int)); +int __ham_add_ovflpage __P((DBC *, PAGE **)); +int __ham_get_cpage __P((DBC *, db_lockmode_t)); +int __ham_next_cpage __P((DBC *, db_pgno_t)); +int __ham_lock_bucket __P((DBC *, db_lockmode_t)); +void __ham_dpair __P((DB *, PAGE *, u_int32_t)); +int __ham_insdel_recover __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __ham_insdel_42_recover __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __ham_newpage_recover __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __ham_replace_recover __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __ham_replace_42_recover __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __ham_splitdata_recover __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __ham_copypage_recover __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __ham_metagroup_recover __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __ham_contract_recover __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __ham_groupalloc_recover __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __ham_changeslot_recover __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __ham_curadj_recover __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __ham_chgpg_recover __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __ham_metagroup_42_recover __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __ham_groupalloc_42_recover __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __ham_reclaim __P((DB *, DB_THREAD_INFO *, DB_TXN *txn, u_int32_t)); +int __ham_truncate __P((DBC *, u_int32_t *)); +int __ham_stat __P((DBC *, void *, u_int32_t)); +int __ham_stat_print __P((DBC *, u_int32_t)); +void __ham_print_cursor __P((DBC *)); +int __ham_traverse __P((DBC *, db_lockmode_t, int (*)(DBC *, PAGE *, void *, int *), void *, int)); +int __db_no_hash_am __P((ENV *)); +int __ham_30_hashmeta __P((DB *, char *, u_int8_t *)); +int __ham_30_sizefix __P((DB *, DB_FH *, char *, u_int8_t *)); +int __ham_31_hashmeta __P((DB *, char *, u_int32_t, DB_FH *, PAGE *, int *)); +int __ham_31_hash __P((DB *, char *, u_int32_t, DB_FH *, PAGE *, int *)); +int __ham_46_hashmeta __P((DB *, char *, u_int32_t, DB_FH *, PAGE *, int *)); +int __ham_46_hash __P((DB *, char *, u_int32_t, DB_FH *, PAGE *, int *)); +int __ham_vrfy_meta __P((DB *, VRFY_DBINFO *, HMETA *, db_pgno_t, u_int32_t)); +int __ham_vrfy __P((DB *, VRFY_DBINFO *, PAGE *, db_pgno_t, u_int32_t)); +int __ham_vrfy_structure __P((DB *, VRFY_DBINFO *, db_pgno_t, u_int32_t)); +int __ham_vrfy_hashing __P((DBC *, u_int32_t, HMETA *, u_int32_t, db_pgno_t, u_int32_t, u_int32_t (*) __P((DB *, const void *, u_int32_t)))); +int __ham_salvage __P((DB *, VRFY_DBINFO *, db_pgno_t, PAGE *, void *, int (*)(void *, const void *), u_int32_t)); +int __ham_meta2pgset __P((DB *, VRFY_DBINFO *, HMETA *, u_int32_t, DB *)); + +#if defined(__cplusplus) +} +#endif +#endif /* !_hash_ext_h_ */ diff -r 000000000000 -r a1985f14b030 src/dbinc_auto/heap_auto.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/dbinc_auto/heap_auto.h Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,194 @@ +/* Do not edit: automatically built by gen_rec.awk. + * + * Copyright (c) 2012 Oracle and/or its affiliates. All rights reserved. * + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +#ifndef __heap_AUTO_H +#define __heap_AUTO_H +#ifdef HAVE_HEAP +#include "dbinc/log.h" +#define DB___heap_addrem 151 +typedef struct ___heap_addrem_args { + u_int32_t type; + DB_TXN *txnp; + DB_LSN prev_lsn; + u_int32_t opcode; + int32_t fileid; + db_pgno_t pgno; + u_int32_t indx; + u_int32_t nbytes; + DBT hdr; + DBT dbt; + DB_LSN pagelsn; +} __heap_addrem_args; + +extern __DB_IMPORT DB_LOG_RECSPEC __heap_addrem_desc[]; +static inline int +__heap_addrem_log(DB *dbp, DB_TXN *txnp, DB_LSN *ret_lsnp, u_int32_t flags, + u_int32_t opcode, db_pgno_t pgno, u_int32_t indx, u_int32_t nbytes, + const DBT *hdr, const DBT *dbt, DB_LSN * pagelsn) +{ + return (__log_put_record((dbp)->env, dbp, txnp, ret_lsnp, + flags, DB___heap_addrem, 0, + sizeof(u_int32_t) + sizeof(u_int32_t) + sizeof(DB_LSN) + + sizeof(u_int32_t) + sizeof(u_int32_t) + sizeof(u_int32_t) + + sizeof(u_int32_t) + sizeof(u_int32_t) + LOG_DBT_SIZE(hdr) + + LOG_DBT_SIZE(dbt) + sizeof(*pagelsn), + __heap_addrem_desc, + opcode, pgno, indx, nbytes, hdr, dbt, pagelsn)); +} + +static inline int __heap_addrem_read(ENV *env, + DB **dbpp, void *td, void *data, __heap_addrem_args **arg) +{ + *arg = NULL; + return (__log_read_record(env, + dbpp, td, data, __heap_addrem_desc, sizeof(__heap_addrem_args), (void**)arg)); +} +#define DB___heap_addrem_50 151 +typedef struct ___heap_addrem_50_args { + u_int32_t type; + DB_TXN *txnp; + DB_LSN prev_lsn; + u_int32_t opcode; + int32_t fileid; + db_pgno_t pgno; + u_int32_t indx; + u_int32_t nbytes; + DBT hdr; + DBT dbt; + DB_LSN pagelsn; +} __heap_addrem_50_args; + +extern __DB_IMPORT DB_LOG_RECSPEC __heap_addrem_50_desc[]; +static inline int __heap_addrem_50_read(ENV *env, + DB **dbpp, void *td, void *data, __heap_addrem_50_args **arg) +{ + *arg = NULL; + return (__log_read_record(env, + dbpp, td, data, __heap_addrem_50_desc, sizeof(__heap_addrem_50_args), (void**)arg)); +} +#define DB___heap_pg_alloc 152 +typedef struct ___heap_pg_alloc_args { + u_int32_t type; + DB_TXN *txnp; + DB_LSN prev_lsn; + int32_t fileid; + DB_LSN meta_lsn; + db_pgno_t meta_pgno; + db_pgno_t pgno; + u_int32_t ptype; + db_pgno_t last_pgno; +} __heap_pg_alloc_args; + +extern __DB_IMPORT DB_LOG_RECSPEC __heap_pg_alloc_desc[]; +static inline int +__heap_pg_alloc_log(DB *dbp, DB_TXN *txnp, DB_LSN *ret_lsnp, u_int32_t flags, DB_LSN * meta_lsn, db_pgno_t meta_pgno, db_pgno_t pgno, u_int32_t ptype, + db_pgno_t last_pgno) +{ + return (__log_put_record((dbp)->env, dbp, txnp, ret_lsnp, + flags, DB___heap_pg_alloc, 0, + sizeof(u_int32_t) + sizeof(u_int32_t) + sizeof(DB_LSN) + + sizeof(u_int32_t) + sizeof(*meta_lsn) + sizeof(u_int32_t) + + sizeof(u_int32_t) + sizeof(u_int32_t) + sizeof(u_int32_t), + __heap_pg_alloc_desc, meta_lsn, meta_pgno, pgno, ptype, last_pgno)); +} + +static inline int __heap_pg_alloc_read(ENV *env, + DB **dbpp, void *td, void *data, __heap_pg_alloc_args **arg) +{ + *arg = NULL; + return (__log_read_record(env, + dbpp, td, data, __heap_pg_alloc_desc, sizeof(__heap_pg_alloc_args), (void**)arg)); +} +#define DB___heap_trunc_meta 153 +typedef struct ___heap_trunc_meta_args { + u_int32_t type; + DB_TXN *txnp; + DB_LSN prev_lsn; + int32_t fileid; + db_pgno_t pgno; + u_int32_t last_pgno; + u_int32_t key_count; + u_int32_t record_count; + u_int32_t curregion; + u_int32_t nregions; + DB_LSN pagelsn; +} __heap_trunc_meta_args; + +extern __DB_IMPORT DB_LOG_RECSPEC __heap_trunc_meta_desc[]; +static inline int +__heap_trunc_meta_log(DB *dbp, DB_TXN *txnp, DB_LSN *ret_lsnp, u_int32_t flags, db_pgno_t pgno, u_int32_t last_pgno, u_int32_t key_count, u_int32_t record_count, + u_int32_t curregion, u_int32_t nregions, DB_LSN * pagelsn) +{ + return (__log_put_record((dbp)->env, dbp, txnp, ret_lsnp, + flags, DB___heap_trunc_meta, 0, + sizeof(u_int32_t) + sizeof(u_int32_t) + sizeof(DB_LSN) + + sizeof(u_int32_t) + sizeof(u_int32_t) + sizeof(u_int32_t) + + sizeof(u_int32_t) + sizeof(u_int32_t) + sizeof(u_int32_t) + + sizeof(u_int32_t) + sizeof(*pagelsn), + __heap_trunc_meta_desc, pgno, last_pgno, key_count, record_count, curregion, nregions, pagelsn)); +} + +static inline int __heap_trunc_meta_read(ENV *env, + DB **dbpp, void *td, void *data, __heap_trunc_meta_args **arg) +{ + *arg = NULL; + return (__log_read_record(env, + dbpp, td, data, __heap_trunc_meta_desc, sizeof(__heap_trunc_meta_args), (void**)arg)); +} +#define DB___heap_trunc_page 154 +typedef struct ___heap_trunc_page_args { + u_int32_t type; + DB_TXN *txnp; + DB_LSN prev_lsn; + int32_t fileid; + db_pgno_t pgno; + DBT old_data; + u_int32_t is_region; + DB_LSN pagelsn; +} __heap_trunc_page_args; + +extern __DB_IMPORT DB_LOG_RECSPEC __heap_trunc_page_desc[]; +static inline int +__heap_trunc_page_log(DB *dbp, DB_TXN *txnp, DB_LSN *ret_lsnp, u_int32_t flags, db_pgno_t pgno, const DBT *old_data, u_int32_t is_region, DB_LSN * pagelsn) +{ + return (__log_put_record((dbp)->env, dbp, txnp, ret_lsnp, + flags, DB___heap_trunc_page, 0, + sizeof(u_int32_t) + sizeof(u_int32_t) + sizeof(DB_LSN) + + sizeof(u_int32_t) + sizeof(u_int32_t) + LOG_DBT_SIZE(old_data) + + sizeof(u_int32_t) + sizeof(*pagelsn), + __heap_trunc_page_desc, pgno, old_data, is_region, pagelsn)); +} + +static inline int __heap_trunc_page_read(ENV *env, + DB **dbpp, void *td, void *data, __heap_trunc_page_args **arg) +{ + *arg = NULL; + return (__log_read_record(env, + dbpp, td, data, __heap_trunc_page_desc, sizeof(__heap_trunc_page_args), (void**)arg)); +} +#endif /* HAVE_HEAP */ +#endif diff -r 000000000000 -r a1985f14b030 src/dbinc_auto/heap_ext.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/dbinc_auto/heap_ext.h Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,86 @@ +/* DO NOT EDIT: automatically built by dist/s_include. + * + * Copyright (c) 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ +#ifndef _heap_ext_h_ +#define _heap_ext_h_ + +#if defined(__cplusplus) +extern "C" { +#endif + +int __heapc_init __P((DBC *)); +int __heap_ditem __P((DBC *, PAGE *, u_int32_t, u_int32_t)); +int __heap_append __P((DBC *, DBT *, DBT *)); +int __heap_pitem __P((DBC *, PAGE *, u_int32_t, u_int32_t, DBT *, DBT *)); +int __heapc_dup __P((DBC *, DBC *)); +int __heapc_gsplit __P((DBC *, DBT *, void **, u_int32_t *)); +int __heapc_refresh __P((DBC *)); +int __heap_init_recover __P((ENV *, DB_DISTAB *)); +int __heap_addrem_print __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __heap_addrem_50_print __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __heap_pg_alloc_print __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __heap_trunc_meta_print __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __heap_trunc_page_print __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __heap_init_print __P((ENV *, DB_DISTAB *)); +int __heap_backup __P((DB_ENV *, DB *, DB_THREAD_INFO *, DB_FH *, void *, u_int32_t)); +int __heap_pgin __P((DB *, db_pgno_t, void *, DBT *)); +int __heap_pgout __P((DB *, db_pgno_t, void *, DBT *)); +int __heap_mswap __P((ENV *, PAGE *)); +int __heap_db_create __P((DB *)); +int __heap_db_close __P((DB *)); +int __heap_get_heapsize __P((DB *, u_int32_t *, u_int32_t *)); +int __heap_get_heap_regionsize __P((DB *, u_int32_t *)); +int __heap_set_heapsize __P((DB *, u_int32_t, u_int32_t, u_int32_t)); +int __heap_set_heap_regionsize __P((DB *, u_int32_t)); +int __heap_exist __P((void)); +int __heap_open __P((DB *, DB_THREAD_INFO *, DB_TXN *, const char *, db_pgno_t, u_int32_t)); +int __heap_metachk __P((DB *, const char *, HEAPMETA *)); +int __heap_read_meta __P((DB *, DB_THREAD_INFO *, DB_TXN *, db_pgno_t, u_int32_t)); +int __heap_new_file __P((DB *, DB_THREAD_INFO *, DB_TXN *, DB_FH *, const char *)); +int __heap_create_region __P((DBC *, db_pgno_t)); +int __heap_addrem_recover __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __heap_pg_alloc_recover __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __heap_trunc_meta_recover __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __heap_trunc_page_recover __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __heap_addrem_50_recover __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __heap_truncate __P((DBC *, u_int32_t *)); +int __heap_stat __P((DBC *, void *, u_int32_t)); +int __heap_stat_print __P((DBC *, u_int32_t)); +void __heap_print_cursor __P((DBC *)); +int __heap_stat_callback __P((DBC *, PAGE *, void *, int *)); +int __heap_traverse __P((DBC *, int (*)(DBC *, PAGE *, void *, int *), void *)); +int __db_no_heap_am __P((ENV *)); +int __heap_vrfy_meta __P((DB *, VRFY_DBINFO *, HEAPMETA *, db_pgno_t, u_int32_t)); +int __heap_vrfy __P((DB *, VRFY_DBINFO *, PAGE *, db_pgno_t, u_int32_t)); +int __heap_vrfy_structure __P((DB *, VRFY_DBINFO *, u_int32_t)); +int __heap_salvage __P((DB *, VRFY_DBINFO *, db_pgno_t, PAGE *, void *, int (*)(void *, const void *), u_int32_t)); +int __heap_meta2pgset __P((DB *, VRFY_DBINFO *, HEAPMETA *, DB *)); + +#if defined(__cplusplus) +} +#endif +#endif /* !_heap_ext_h_ */ diff -r 000000000000 -r a1985f14b030 src/dbinc_auto/hmac_ext.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/dbinc_auto/hmac_ext.h Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,46 @@ +/* DO NOT EDIT: automatically built by dist/s_include. + * + * Copyright (c) 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ +#ifndef _hmac_ext_h_ +#define _hmac_ext_h_ + +#if defined(__cplusplus) +extern "C" { +#endif + +void __db_chksum __P((void *, u_int8_t *, size_t, u_int8_t *, u_int8_t *)); +void __db_derive_mac __P((u_int8_t *, size_t, u_int8_t *)); +int __db_check_chksum __P((ENV *, void *, DB_CIPHER *, u_int8_t *, void *, size_t, int)); +void __db_SHA1Transform __P((u_int32_t *, unsigned char *)); +void __db_SHA1Init __P((SHA1_CTX *)); +void __db_SHA1Update __P((SHA1_CTX *, unsigned char *, size_t)); +void __db_SHA1Final __P((unsigned char *, SHA1_CTX *)); + +#if defined(__cplusplus) +} +#endif +#endif /* !_hmac_ext_h_ */ diff -r 000000000000 -r a1985f14b030 src/dbinc_auto/int_def.in --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/dbinc_auto/int_def.in Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,2378 @@ +/* DO NOT EDIT: automatically built by dist/s_include. + * + * Copyright (c) 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ +#ifndef _DB_INT_DEF_IN_ +#define _DB_INT_DEF_IN_ + +#define __crdel_metasub_desc __crdel_metasub_desc@DB_VERSION_UNIQUE_NAME@ +#define __crdel_inmem_create_desc __crdel_inmem_create_desc@DB_VERSION_UNIQUE_NAME@ +#define __crdel_inmem_rename_desc __crdel_inmem_rename_desc@DB_VERSION_UNIQUE_NAME@ +#define __crdel_inmem_remove_desc __crdel_inmem_remove_desc@DB_VERSION_UNIQUE_NAME@ +#define __crdel_init_recover __crdel_init_recover@DB_VERSION_UNIQUE_NAME@ +#define __crdel_metasub_print __crdel_metasub_print@DB_VERSION_UNIQUE_NAME@ +#define __crdel_inmem_create_print __crdel_inmem_create_print@DB_VERSION_UNIQUE_NAME@ +#define __crdel_inmem_rename_print __crdel_inmem_rename_print@DB_VERSION_UNIQUE_NAME@ +#define __crdel_inmem_remove_print __crdel_inmem_remove_print@DB_VERSION_UNIQUE_NAME@ +#define __crdel_init_print __crdel_init_print@DB_VERSION_UNIQUE_NAME@ +#define __crdel_metasub_recover __crdel_metasub_recover@DB_VERSION_UNIQUE_NAME@ +#define __crdel_inmem_create_recover __crdel_inmem_create_recover@DB_VERSION_UNIQUE_NAME@ +#define __crdel_inmem_rename_recover __crdel_inmem_rename_recover@DB_VERSION_UNIQUE_NAME@ +#define __crdel_inmem_remove_recover __crdel_inmem_remove_recover@DB_VERSION_UNIQUE_NAME@ +#define __db_master_open __db_master_open@DB_VERSION_UNIQUE_NAME@ +#define __db_master_update __db_master_update@DB_VERSION_UNIQUE_NAME@ +#define __env_dbreg_setup __env_dbreg_setup@DB_VERSION_UNIQUE_NAME@ +#define __env_setup __env_setup@DB_VERSION_UNIQUE_NAME@ +#define __env_mpool __env_mpool@DB_VERSION_UNIQUE_NAME@ +#define __db_close __db_close@DB_VERSION_UNIQUE_NAME@ +#define __db_refresh __db_refresh@DB_VERSION_UNIQUE_NAME@ +#define __db_log_page __db_log_page@DB_VERSION_UNIQUE_NAME@ +#define __db_walk_cursors __db_walk_cursors@DB_VERSION_UNIQUE_NAME@ +#define __db_backup_name __db_backup_name@DB_VERSION_UNIQUE_NAME@ +#ifdef CONFIG_TEST +#define __db_testcopy __db_testcopy@DB_VERSION_UNIQUE_NAME@ +#endif +#define __db_testdocopy __db_testdocopy@DB_VERSION_UNIQUE_NAME@ +#define __db_cursor_int __db_cursor_int@DB_VERSION_UNIQUE_NAME@ +#define __db_put __db_put@DB_VERSION_UNIQUE_NAME@ +#define __db_del __db_del@DB_VERSION_UNIQUE_NAME@ +#define __db_sync __db_sync@DB_VERSION_UNIQUE_NAME@ +#define __db_associate __db_associate@DB_VERSION_UNIQUE_NAME@ +#define __db_secondary_close __db_secondary_close@DB_VERSION_UNIQUE_NAME@ +#define __db_associate_foreign __db_associate_foreign@DB_VERSION_UNIQUE_NAME@ +#define __db_addrem_desc __db_addrem_desc@DB_VERSION_UNIQUE_NAME@ +#define __db_addrem_42_desc __db_addrem_42_desc@DB_VERSION_UNIQUE_NAME@ +#define __db_big_desc __db_big_desc@DB_VERSION_UNIQUE_NAME@ +#define __db_big_42_desc __db_big_42_desc@DB_VERSION_UNIQUE_NAME@ +#define __db_ovref_desc __db_ovref_desc@DB_VERSION_UNIQUE_NAME@ +#define __db_relink_42_desc __db_relink_42_desc@DB_VERSION_UNIQUE_NAME@ +#define __db_debug_desc __db_debug_desc@DB_VERSION_UNIQUE_NAME@ +#define __db_noop_desc __db_noop_desc@DB_VERSION_UNIQUE_NAME@ +#define __db_pg_alloc_42_desc __db_pg_alloc_42_desc@DB_VERSION_UNIQUE_NAME@ +#define __db_pg_alloc_desc __db_pg_alloc_desc@DB_VERSION_UNIQUE_NAME@ +#define __db_pg_free_42_desc __db_pg_free_42_desc@DB_VERSION_UNIQUE_NAME@ +#define __db_pg_free_desc __db_pg_free_desc@DB_VERSION_UNIQUE_NAME@ +#define __db_cksum_desc __db_cksum_desc@DB_VERSION_UNIQUE_NAME@ +#define __db_pg_freedata_42_desc __db_pg_freedata_42_desc@DB_VERSION_UNIQUE_NAME@ +#define __db_pg_freedata_desc __db_pg_freedata_desc@DB_VERSION_UNIQUE_NAME@ +#define __db_pg_init_desc __db_pg_init_desc@DB_VERSION_UNIQUE_NAME@ +#define __db_pg_sort_44_desc __db_pg_sort_44_desc@DB_VERSION_UNIQUE_NAME@ +#define __db_pg_trunc_desc __db_pg_trunc_desc@DB_VERSION_UNIQUE_NAME@ +#define __db_realloc_desc __db_realloc_desc@DB_VERSION_UNIQUE_NAME@ +#define __db_relink_desc __db_relink_desc@DB_VERSION_UNIQUE_NAME@ +#define __db_merge_desc __db_merge_desc@DB_VERSION_UNIQUE_NAME@ +#define __db_pgno_desc __db_pgno_desc@DB_VERSION_UNIQUE_NAME@ +#define __db_init_recover __db_init_recover@DB_VERSION_UNIQUE_NAME@ +#define __db_addrem_print __db_addrem_print@DB_VERSION_UNIQUE_NAME@ +#define __db_addrem_42_print __db_addrem_42_print@DB_VERSION_UNIQUE_NAME@ +#define __db_big_print __db_big_print@DB_VERSION_UNIQUE_NAME@ +#define __db_big_42_print __db_big_42_print@DB_VERSION_UNIQUE_NAME@ +#define __db_ovref_print __db_ovref_print@DB_VERSION_UNIQUE_NAME@ +#define __db_relink_42_print __db_relink_42_print@DB_VERSION_UNIQUE_NAME@ +#define __db_debug_print __db_debug_print@DB_VERSION_UNIQUE_NAME@ +#define __db_noop_print __db_noop_print@DB_VERSION_UNIQUE_NAME@ +#define __db_pg_alloc_42_print __db_pg_alloc_42_print@DB_VERSION_UNIQUE_NAME@ +#define __db_pg_alloc_print __db_pg_alloc_print@DB_VERSION_UNIQUE_NAME@ +#define __db_pg_free_42_print __db_pg_free_42_print@DB_VERSION_UNIQUE_NAME@ +#define __db_pg_free_print __db_pg_free_print@DB_VERSION_UNIQUE_NAME@ +#define __db_cksum_print __db_cksum_print@DB_VERSION_UNIQUE_NAME@ +#define __db_pg_freedata_42_print __db_pg_freedata_42_print@DB_VERSION_UNIQUE_NAME@ +#define __db_pg_freedata_print __db_pg_freedata_print@DB_VERSION_UNIQUE_NAME@ +#define __db_pg_init_print __db_pg_init_print@DB_VERSION_UNIQUE_NAME@ +#define __db_pg_sort_44_print __db_pg_sort_44_print@DB_VERSION_UNIQUE_NAME@ +#define __db_pg_trunc_print __db_pg_trunc_print@DB_VERSION_UNIQUE_NAME@ +#define __db_realloc_print __db_realloc_print@DB_VERSION_UNIQUE_NAME@ +#define __db_relink_print __db_relink_print@DB_VERSION_UNIQUE_NAME@ +#define __db_merge_print __db_merge_print@DB_VERSION_UNIQUE_NAME@ +#define __db_pgno_print __db_pgno_print@DB_VERSION_UNIQUE_NAME@ +#define __db_init_print __db_init_print@DB_VERSION_UNIQUE_NAME@ +#define __db_dbbackup_pp __db_dbbackup_pp@DB_VERSION_UNIQUE_NAME@ +#define __db_dbbackup __db_dbbackup@DB_VERSION_UNIQUE_NAME@ +#define __db_backup __db_backup@DB_VERSION_UNIQUE_NAME@ +#define __dbc_close __dbc_close@DB_VERSION_UNIQUE_NAME@ +#define __dbc_destroy __dbc_destroy@DB_VERSION_UNIQUE_NAME@ +#define __dbc_cmp __dbc_cmp@DB_VERSION_UNIQUE_NAME@ +#define __dbc_count __dbc_count@DB_VERSION_UNIQUE_NAME@ +#define __dbc_del __dbc_del@DB_VERSION_UNIQUE_NAME@ +#define __dbc_idel __dbc_idel@DB_VERSION_UNIQUE_NAME@ +#ifdef HAVE_COMPRESSION +#define __dbc_bulk_del __dbc_bulk_del@DB_VERSION_UNIQUE_NAME@ +#endif +#define __dbc_dup __dbc_dup@DB_VERSION_UNIQUE_NAME@ +#define __dbc_idup __dbc_idup@DB_VERSION_UNIQUE_NAME@ +#define __dbc_newopd __dbc_newopd@DB_VERSION_UNIQUE_NAME@ +#define __dbc_get __dbc_get@DB_VERSION_UNIQUE_NAME@ +#define __dbc_iget __dbc_iget@DB_VERSION_UNIQUE_NAME@ +#define __dbc_put __dbc_put@DB_VERSION_UNIQUE_NAME@ +#define __dbc_iput __dbc_iput@DB_VERSION_UNIQUE_NAME@ +#define __db_duperr __db_duperr@DB_VERSION_UNIQUE_NAME@ +#define __dbc_cleanup __dbc_cleanup@DB_VERSION_UNIQUE_NAME@ +#define __dbc_secondary_get_pp __dbc_secondary_get_pp@DB_VERSION_UNIQUE_NAME@ +#define __dbc_pget __dbc_pget@DB_VERSION_UNIQUE_NAME@ +#define __dbc_del_primary __dbc_del_primary@DB_VERSION_UNIQUE_NAME@ +#define __db_s_first __db_s_first@DB_VERSION_UNIQUE_NAME@ +#define __db_s_next __db_s_next@DB_VERSION_UNIQUE_NAME@ +#define __db_s_done __db_s_done@DB_VERSION_UNIQUE_NAME@ +#define __db_buildpartial __db_buildpartial@DB_VERSION_UNIQUE_NAME@ +#define __db_partsize __db_partsize@DB_VERSION_UNIQUE_NAME@ +#define __db_secondary_corrupt __db_secondary_corrupt@DB_VERSION_UNIQUE_NAME@ +#ifdef DIAGNOSTIC +#define __db_check_skeyset __db_check_skeyset@DB_VERSION_UNIQUE_NAME@ +#endif +#define __cdsgroup_begin __cdsgroup_begin@DB_VERSION_UNIQUE_NAME@ +#define __cdsgroup_begin_pp __cdsgroup_begin_pp@DB_VERSION_UNIQUE_NAME@ +#define __db_compact_pp __db_compact_pp@DB_VERSION_UNIQUE_NAME@ +#define __db_associate_foreign_pp __db_associate_foreign_pp@DB_VERSION_UNIQUE_NAME@ +#define __db_compact_int __db_compact_int@DB_VERSION_UNIQUE_NAME@ +#define __db_exchange_page __db_exchange_page@DB_VERSION_UNIQUE_NAME@ +#define __db_truncate_overflow __db_truncate_overflow@DB_VERSION_UNIQUE_NAME@ +#define __db_truncate_root __db_truncate_root@DB_VERSION_UNIQUE_NAME@ +#define __db_find_free __db_find_free@DB_VERSION_UNIQUE_NAME@ +#define __db_move_metadata __db_move_metadata@DB_VERSION_UNIQUE_NAME@ +#define __db_pgin __db_pgin@DB_VERSION_UNIQUE_NAME@ +#define __db_pgout __db_pgout@DB_VERSION_UNIQUE_NAME@ +#define __db_decrypt_pg __db_decrypt_pg@DB_VERSION_UNIQUE_NAME@ +#define __db_encrypt_and_checksum_pg __db_encrypt_and_checksum_pg@DB_VERSION_UNIQUE_NAME@ +#define __db_metaswap __db_metaswap@DB_VERSION_UNIQUE_NAME@ +#define __db_byteswap __db_byteswap@DB_VERSION_UNIQUE_NAME@ +#define __db_pageswap __db_pageswap@DB_VERSION_UNIQUE_NAME@ +#define __db_recordswap __db_recordswap@DB_VERSION_UNIQUE_NAME@ +#define __db_dispatch __db_dispatch@DB_VERSION_UNIQUE_NAME@ +#define __db_add_recovery __db_add_recovery@DB_VERSION_UNIQUE_NAME@ +#define __db_add_recovery_int __db_add_recovery_int@DB_VERSION_UNIQUE_NAME@ +#define __db_txnlist_init __db_txnlist_init@DB_VERSION_UNIQUE_NAME@ +#define __db_txnlist_add __db_txnlist_add@DB_VERSION_UNIQUE_NAME@ +#define __db_txnlist_remove __db_txnlist_remove@DB_VERSION_UNIQUE_NAME@ +#define __db_txnlist_ckp __db_txnlist_ckp@DB_VERSION_UNIQUE_NAME@ +#define __db_txnlist_end __db_txnlist_end@DB_VERSION_UNIQUE_NAME@ +#define __db_txnlist_find __db_txnlist_find@DB_VERSION_UNIQUE_NAME@ +#define __db_txnlist_update __db_txnlist_update@DB_VERSION_UNIQUE_NAME@ +#define __db_txnlist_gen __db_txnlist_gen@DB_VERSION_UNIQUE_NAME@ +#define __db_txnlist_lsnadd __db_txnlist_lsnadd@DB_VERSION_UNIQUE_NAME@ +#define __db_txnlist_lsnget __db_txnlist_lsnget@DB_VERSION_UNIQUE_NAME@ +#define __db_txnlist_lsninit __db_txnlist_lsninit@DB_VERSION_UNIQUE_NAME@ +#define __db_txnlist_print __db_txnlist_print@DB_VERSION_UNIQUE_NAME@ +#define __db_ditem_nolog __db_ditem_nolog@DB_VERSION_UNIQUE_NAME@ +#define __db_ditem __db_ditem@DB_VERSION_UNIQUE_NAME@ +#define __db_pitem_nolog __db_pitem_nolog@DB_VERSION_UNIQUE_NAME@ +#define __db_pitem __db_pitem@DB_VERSION_UNIQUE_NAME@ +#define __db_associate_pp __db_associate_pp@DB_VERSION_UNIQUE_NAME@ +#define __db_close_pp __db_close_pp@DB_VERSION_UNIQUE_NAME@ +#define __db_cursor_pp __db_cursor_pp@DB_VERSION_UNIQUE_NAME@ +#define __db_cursor __db_cursor@DB_VERSION_UNIQUE_NAME@ +#define __db_del_pp __db_del_pp@DB_VERSION_UNIQUE_NAME@ +#define __db_exists __db_exists@DB_VERSION_UNIQUE_NAME@ +#define __db_fd_pp __db_fd_pp@DB_VERSION_UNIQUE_NAME@ +#define __db_get_pp __db_get_pp@DB_VERSION_UNIQUE_NAME@ +#define __db_get __db_get@DB_VERSION_UNIQUE_NAME@ +#define __db_key_range_pp __db_key_range_pp@DB_VERSION_UNIQUE_NAME@ +#define __db_open_pp __db_open_pp@DB_VERSION_UNIQUE_NAME@ +#define __db_pget_pp __db_pget_pp@DB_VERSION_UNIQUE_NAME@ +#define __db_pget __db_pget@DB_VERSION_UNIQUE_NAME@ +#define __db_put_pp __db_put_pp@DB_VERSION_UNIQUE_NAME@ +#define __db_sync_pp __db_sync_pp@DB_VERSION_UNIQUE_NAME@ +#define __dbc_close_pp __dbc_close_pp@DB_VERSION_UNIQUE_NAME@ +#define __dbc_cmp_pp __dbc_cmp_pp@DB_VERSION_UNIQUE_NAME@ +#define __dbc_count_pp __dbc_count_pp@DB_VERSION_UNIQUE_NAME@ +#define __dbc_del_pp __dbc_del_pp@DB_VERSION_UNIQUE_NAME@ +#define __dbc_dup_pp __dbc_dup_pp@DB_VERSION_UNIQUE_NAME@ +#define __dbc_get_pp __dbc_get_pp@DB_VERSION_UNIQUE_NAME@ +#define __dbc_get_arg __dbc_get_arg@DB_VERSION_UNIQUE_NAME@ +#define __db_secondary_close_pp __db_secondary_close_pp@DB_VERSION_UNIQUE_NAME@ +#define __dbc_pget_pp __dbc_pget_pp@DB_VERSION_UNIQUE_NAME@ +#define __dbc_put_pp __dbc_put_pp@DB_VERSION_UNIQUE_NAME@ +#define __db_txn_auto_init __db_txn_auto_init@DB_VERSION_UNIQUE_NAME@ +#define __db_txn_auto_resolve __db_txn_auto_resolve@DB_VERSION_UNIQUE_NAME@ +#define __db_join_pp __db_join_pp@DB_VERSION_UNIQUE_NAME@ +#define __db_join __db_join@DB_VERSION_UNIQUE_NAME@ +#define __db_join_close __db_join_close@DB_VERSION_UNIQUE_NAME@ +#define __db_new __db_new@DB_VERSION_UNIQUE_NAME@ +#define __db_free __db_free@DB_VERSION_UNIQUE_NAME@ +#ifdef HAVE_FTRUNCATE +#define __db_freelist_pos __db_freelist_pos@DB_VERSION_UNIQUE_NAME@ +#endif +#define __db_freelist_sort __db_freelist_sort@DB_VERSION_UNIQUE_NAME@ +#ifdef HAVE_FTRUNCATE +#define __db_pg_truncate __db_pg_truncate@DB_VERSION_UNIQUE_NAME@ +#endif +#ifdef HAVE_FTRUNCATE +#define __db_free_truncate __db_free_truncate@DB_VERSION_UNIQUE_NAME@ +#endif +#define __db_create_internal __db_create_internal@DB_VERSION_UNIQUE_NAME@ +#define __dbh_am_chk __dbh_am_chk@DB_VERSION_UNIQUE_NAME@ +#define __db_get_flags __db_get_flags@DB_VERSION_UNIQUE_NAME@ +#define __db_set_flags __db_set_flags@DB_VERSION_UNIQUE_NAME@ +#define __db_get_lorder __db_get_lorder@DB_VERSION_UNIQUE_NAME@ +#define __db_set_lorder __db_set_lorder@DB_VERSION_UNIQUE_NAME@ +#define __db_set_pagesize __db_set_pagesize@DB_VERSION_UNIQUE_NAME@ +#define __db_relink __db_relink@DB_VERSION_UNIQUE_NAME@ +#ifdef DIAGNOSTIC +#define __db_haslock __db_haslock@DB_VERSION_UNIQUE_NAME@ +#endif +#ifdef DIAGNOSTIC +#define __db_has_pagelock __db_has_pagelock@DB_VERSION_UNIQUE_NAME@ +#endif +#define __db_open __db_open@DB_VERSION_UNIQUE_NAME@ +#define __db_get_open_flags __db_get_open_flags@DB_VERSION_UNIQUE_NAME@ +#define __db_new_file __db_new_file@DB_VERSION_UNIQUE_NAME@ +#define __db_init_subdb __db_init_subdb@DB_VERSION_UNIQUE_NAME@ +#define __db_chk_meta __db_chk_meta@DB_VERSION_UNIQUE_NAME@ +#define __db_meta_setup __db_meta_setup@DB_VERSION_UNIQUE_NAME@ +#define __db_reopen __db_reopen@DB_VERSION_UNIQUE_NAME@ +#define __db_goff __db_goff@DB_VERSION_UNIQUE_NAME@ +#define __db_poff __db_poff@DB_VERSION_UNIQUE_NAME@ +#define __db_ovref __db_ovref@DB_VERSION_UNIQUE_NAME@ +#define __db_doff __db_doff@DB_VERSION_UNIQUE_NAME@ +#define __db_moff __db_moff@DB_VERSION_UNIQUE_NAME@ +#define __db_coff __db_coff@DB_VERSION_UNIQUE_NAME@ +#define __db_vrfy_overflow __db_vrfy_overflow@DB_VERSION_UNIQUE_NAME@ +#define __db_vrfy_ovfl_structure __db_vrfy_ovfl_structure@DB_VERSION_UNIQUE_NAME@ +#define __db_safe_goff __db_safe_goff@DB_VERSION_UNIQUE_NAME@ +#define __db_loadme __db_loadme@DB_VERSION_UNIQUE_NAME@ +#define __db_dumptree __db_dumptree@DB_VERSION_UNIQUE_NAME@ +#define __db_get_flags_fn __db_get_flags_fn@DB_VERSION_UNIQUE_NAME@ +#define __db_prnpage __db_prnpage@DB_VERSION_UNIQUE_NAME@ +#define __db_prpage __db_prpage@DB_VERSION_UNIQUE_NAME@ +#define __db_lockmode_to_string __db_lockmode_to_string@DB_VERSION_UNIQUE_NAME@ +#define __db_dumptree __db_dumptree@DB_VERSION_UNIQUE_NAME@ +#define __db_get_flags_fn __db_get_flags_fn@DB_VERSION_UNIQUE_NAME@ +#define __db_prpage_int __db_prpage_int@DB_VERSION_UNIQUE_NAME@ +#define __db_prbytes __db_prbytes@DB_VERSION_UNIQUE_NAME@ +#define __db_prflags __db_prflags@DB_VERSION_UNIQUE_NAME@ +#define __db_name_to_val __db_name_to_val@DB_VERSION_UNIQUE_NAME@ +#define __db_pagetype_to_string __db_pagetype_to_string@DB_VERSION_UNIQUE_NAME@ +#define __db_dump_pp __db_dump_pp@DB_VERSION_UNIQUE_NAME@ +#define __db_dump __db_dump@DB_VERSION_UNIQUE_NAME@ +#define __db_prdbt __db_prdbt@DB_VERSION_UNIQUE_NAME@ +#define __db_prheader __db_prheader@DB_VERSION_UNIQUE_NAME@ +#define __db_prfooter __db_prfooter@DB_VERSION_UNIQUE_NAME@ +#define __db_pr_callback __db_pr_callback@DB_VERSION_UNIQUE_NAME@ +#define __db_dbtype_to_string __db_dbtype_to_string@DB_VERSION_UNIQUE_NAME@ +#define __db_addrem_recover __db_addrem_recover@DB_VERSION_UNIQUE_NAME@ +#define __db_addrem_42_recover __db_addrem_42_recover@DB_VERSION_UNIQUE_NAME@ +#define __db_big_recover __db_big_recover@DB_VERSION_UNIQUE_NAME@ +#define __db_big_42_recover __db_big_42_recover@DB_VERSION_UNIQUE_NAME@ +#define __db_ovref_recover __db_ovref_recover@DB_VERSION_UNIQUE_NAME@ +#define __db_debug_recover __db_debug_recover@DB_VERSION_UNIQUE_NAME@ +#define __db_noop_recover __db_noop_recover@DB_VERSION_UNIQUE_NAME@ +#define __db_pg_alloc_recover __db_pg_alloc_recover@DB_VERSION_UNIQUE_NAME@ +#define __db_pg_free_recover __db_pg_free_recover@DB_VERSION_UNIQUE_NAME@ +#define __db_pg_freedata_recover __db_pg_freedata_recover@DB_VERSION_UNIQUE_NAME@ +#define __db_cksum_recover __db_cksum_recover@DB_VERSION_UNIQUE_NAME@ +#define __db_pg_init_recover __db_pg_init_recover@DB_VERSION_UNIQUE_NAME@ +#define __db_pg_trunc_recover __db_pg_trunc_recover@DB_VERSION_UNIQUE_NAME@ +#define __db_realloc_recover __db_realloc_recover@DB_VERSION_UNIQUE_NAME@ +#define __db_pg_sort_44_recover __db_pg_sort_44_recover@DB_VERSION_UNIQUE_NAME@ +#define __db_pg_alloc_42_recover __db_pg_alloc_42_recover@DB_VERSION_UNIQUE_NAME@ +#define __db_pg_free_42_recover __db_pg_free_42_recover@DB_VERSION_UNIQUE_NAME@ +#define __db_pg_freedata_42_recover __db_pg_freedata_42_recover@DB_VERSION_UNIQUE_NAME@ +#define __db_relink_42_recover __db_relink_42_recover@DB_VERSION_UNIQUE_NAME@ +#define __db_relink_recover __db_relink_recover@DB_VERSION_UNIQUE_NAME@ +#define __db_merge_recover __db_merge_recover@DB_VERSION_UNIQUE_NAME@ +#define __db_pgno_recover __db_pgno_recover@DB_VERSION_UNIQUE_NAME@ +#define __db_pglist_swap __db_pglist_swap@DB_VERSION_UNIQUE_NAME@ +#define __db_pglist_print __db_pglist_print@DB_VERSION_UNIQUE_NAME@ +#define __db_traverse_big __db_traverse_big@DB_VERSION_UNIQUE_NAME@ +#define __db_reclaim_callback __db_reclaim_callback@DB_VERSION_UNIQUE_NAME@ +#define __db_truncate_callback __db_truncate_callback@DB_VERSION_UNIQUE_NAME@ +#define __env_dbremove_pp __env_dbremove_pp@DB_VERSION_UNIQUE_NAME@ +#define __db_remove_pp __db_remove_pp@DB_VERSION_UNIQUE_NAME@ +#define __db_remove __db_remove@DB_VERSION_UNIQUE_NAME@ +#define __db_remove_int __db_remove_int@DB_VERSION_UNIQUE_NAME@ +#define __db_inmem_remove __db_inmem_remove@DB_VERSION_UNIQUE_NAME@ +#define __env_dbrename_pp __env_dbrename_pp@DB_VERSION_UNIQUE_NAME@ +#define __db_rename_pp __db_rename_pp@DB_VERSION_UNIQUE_NAME@ +#define __db_rename_int __db_rename_int@DB_VERSION_UNIQUE_NAME@ +#define __db_ret __db_ret@DB_VERSION_UNIQUE_NAME@ +#define __db_retcopy __db_retcopy@DB_VERSION_UNIQUE_NAME@ +#define __db_dbt_clone __db_dbt_clone@DB_VERSION_UNIQUE_NAME@ +#define __db_dbt_clone_free __db_dbt_clone_free@DB_VERSION_UNIQUE_NAME@ +#define __env_fileid_reset_pp __env_fileid_reset_pp@DB_VERSION_UNIQUE_NAME@ +#define __env_fileid_reset __env_fileid_reset@DB_VERSION_UNIQUE_NAME@ +#define __env_lsn_reset_pp __env_lsn_reset_pp@DB_VERSION_UNIQUE_NAME@ +#define __db_lsn_reset __db_lsn_reset@DB_VERSION_UNIQUE_NAME@ +#define __db_compare_both __db_compare_both@DB_VERSION_UNIQUE_NAME@ +#define __db_sort_multiple __db_sort_multiple@DB_VERSION_UNIQUE_NAME@ +#define __db_stat_pp __db_stat_pp@DB_VERSION_UNIQUE_NAME@ +#define __db_stat_print_pp __db_stat_print_pp@DB_VERSION_UNIQUE_NAME@ +#define __db_stat_print __db_stat_print@DB_VERSION_UNIQUE_NAME@ +#define __db_truncate_pp __db_truncate_pp@DB_VERSION_UNIQUE_NAME@ +#define __db_truncate __db_truncate@DB_VERSION_UNIQUE_NAME@ +#define __db_upgrade_pp __db_upgrade_pp@DB_VERSION_UNIQUE_NAME@ +#define __db_upgrade __db_upgrade@DB_VERSION_UNIQUE_NAME@ +#define __db_lastpgno __db_lastpgno@DB_VERSION_UNIQUE_NAME@ +#define __db_31_offdup __db_31_offdup@DB_VERSION_UNIQUE_NAME@ +#define __db_verify_pp __db_verify_pp@DB_VERSION_UNIQUE_NAME@ +#define __db_verify_internal __db_verify_internal@DB_VERSION_UNIQUE_NAME@ +#define __db_verify __db_verify@DB_VERSION_UNIQUE_NAME@ +#define __db_vrfy_common __db_vrfy_common@DB_VERSION_UNIQUE_NAME@ +#define __db_vrfy_datapage __db_vrfy_datapage@DB_VERSION_UNIQUE_NAME@ +#define __db_vrfy_meta __db_vrfy_meta@DB_VERSION_UNIQUE_NAME@ +#define __db_vrfy_struct_feedback __db_vrfy_struct_feedback@DB_VERSION_UNIQUE_NAME@ +#define __db_salvage_pg __db_salvage_pg@DB_VERSION_UNIQUE_NAME@ +#define __db_salvage_leaf __db_salvage_leaf@DB_VERSION_UNIQUE_NAME@ +#define __db_vrfy_inpitem __db_vrfy_inpitem@DB_VERSION_UNIQUE_NAME@ +#define __db_vrfy_duptype __db_vrfy_duptype@DB_VERSION_UNIQUE_NAME@ +#define __db_salvage_duptree __db_salvage_duptree@DB_VERSION_UNIQUE_NAME@ +#define __db_vrfy_dbinfo_create __db_vrfy_dbinfo_create@DB_VERSION_UNIQUE_NAME@ +#define __db_vrfy_dbinfo_destroy __db_vrfy_dbinfo_destroy@DB_VERSION_UNIQUE_NAME@ +#define __db_vrfy_getpageinfo __db_vrfy_getpageinfo@DB_VERSION_UNIQUE_NAME@ +#define __db_vrfy_putpageinfo __db_vrfy_putpageinfo@DB_VERSION_UNIQUE_NAME@ +#define __db_vrfy_pgset __db_vrfy_pgset@DB_VERSION_UNIQUE_NAME@ +#define __db_vrfy_pgset_get __db_vrfy_pgset_get@DB_VERSION_UNIQUE_NAME@ +#define __db_vrfy_pgset_inc __db_vrfy_pgset_inc@DB_VERSION_UNIQUE_NAME@ +#define __db_vrfy_pgset_next __db_vrfy_pgset_next@DB_VERSION_UNIQUE_NAME@ +#define __db_vrfy_childcursor __db_vrfy_childcursor@DB_VERSION_UNIQUE_NAME@ +#define __db_vrfy_childput __db_vrfy_childput@DB_VERSION_UNIQUE_NAME@ +#define __db_vrfy_ccset __db_vrfy_ccset@DB_VERSION_UNIQUE_NAME@ +#define __db_vrfy_ccnext __db_vrfy_ccnext@DB_VERSION_UNIQUE_NAME@ +#define __db_vrfy_ccclose __db_vrfy_ccclose@DB_VERSION_UNIQUE_NAME@ +#define __db_salvage_init __db_salvage_init@DB_VERSION_UNIQUE_NAME@ +#define __db_salvage_destroy __db_salvage_destroy@DB_VERSION_UNIQUE_NAME@ +#define __db_salvage_getnext __db_salvage_getnext@DB_VERSION_UNIQUE_NAME@ +#define __db_salvage_isdone __db_salvage_isdone@DB_VERSION_UNIQUE_NAME@ +#define __db_salvage_markdone __db_salvage_markdone@DB_VERSION_UNIQUE_NAME@ +#define __db_salvage_markneeded __db_salvage_markneeded@DB_VERSION_UNIQUE_NAME@ +#define __db_vrfy_prdbt __db_vrfy_prdbt@DB_VERSION_UNIQUE_NAME@ +#define __db_lget __db_lget@DB_VERSION_UNIQUE_NAME@ +#define __db_lput __db_lput@DB_VERSION_UNIQUE_NAME@ +#define __db_lprint __db_lprint@DB_VERSION_UNIQUE_NAME@ +#define __partition_init __partition_init@DB_VERSION_UNIQUE_NAME@ +#define __partition_set __partition_set@DB_VERSION_UNIQUE_NAME@ +#define __partition_set_dirs __partition_set_dirs@DB_VERSION_UNIQUE_NAME@ +#define __partition_open __partition_open@DB_VERSION_UNIQUE_NAME@ +#define __partition_get_callback __partition_get_callback@DB_VERSION_UNIQUE_NAME@ +#define __partition_get_keys __partition_get_keys@DB_VERSION_UNIQUE_NAME@ +#define __partition_get_dirs __partition_get_dirs@DB_VERSION_UNIQUE_NAME@ +#define __partc_init __partc_init@DB_VERSION_UNIQUE_NAME@ +#define __partc_get __partc_get@DB_VERSION_UNIQUE_NAME@ +#define __partition_close __partition_close@DB_VERSION_UNIQUE_NAME@ +#define __partition_sync __partition_sync@DB_VERSION_UNIQUE_NAME@ +#define __partition_stat __partition_stat@DB_VERSION_UNIQUE_NAME@ +#define __part_truncate __part_truncate@DB_VERSION_UNIQUE_NAME@ +#define __part_compact __part_compact@DB_VERSION_UNIQUE_NAME@ +#define __part_lsn_reset __part_lsn_reset@DB_VERSION_UNIQUE_NAME@ +#define __part_fileid_reset __part_fileid_reset@DB_VERSION_UNIQUE_NAME@ +#define __part_key_range __part_key_range@DB_VERSION_UNIQUE_NAME@ +#define __part_remove __part_remove@DB_VERSION_UNIQUE_NAME@ +#define __part_rename __part_rename@DB_VERSION_UNIQUE_NAME@ +#define __part_verify __part_verify@DB_VERSION_UNIQUE_NAME@ +#define __part_testdocopy __part_testdocopy@DB_VERSION_UNIQUE_NAME@ +#define __db_no_partition __db_no_partition@DB_VERSION_UNIQUE_NAME@ +#define __bam_compact_int __bam_compact_int@DB_VERSION_UNIQUE_NAME@ +#define __bam_compact_opd __bam_compact_opd@DB_VERSION_UNIQUE_NAME@ +#define __bam_truncate_ipages __bam_truncate_ipages@DB_VERSION_UNIQUE_NAME@ +#define __bam_cmp __bam_cmp@DB_VERSION_UNIQUE_NAME@ +#define __bam_defcmp __bam_defcmp@DB_VERSION_UNIQUE_NAME@ +#define __bam_defpfx __bam_defpfx@DB_VERSION_UNIQUE_NAME@ +#define __bam_compress_dupcmp __bam_compress_dupcmp@DB_VERSION_UNIQUE_NAME@ +#define __bam_defcompress __bam_defcompress@DB_VERSION_UNIQUE_NAME@ +#define __bam_defdecompress __bam_defdecompress@DB_VERSION_UNIQUE_NAME@ +#define __bamc_compress_get __bamc_compress_get@DB_VERSION_UNIQUE_NAME@ +#define __bamc_compress_put __bamc_compress_put@DB_VERSION_UNIQUE_NAME@ +#define __bamc_compress_del __bamc_compress_del@DB_VERSION_UNIQUE_NAME@ +#define __bamc_compress_bulk_del __bamc_compress_bulk_del@DB_VERSION_UNIQUE_NAME@ +#define __bamc_compress_count __bamc_compress_count@DB_VERSION_UNIQUE_NAME@ +#define __bamc_compress_cmp __bamc_compress_cmp@DB_VERSION_UNIQUE_NAME@ +#define __bamc_compress_dup __bamc_compress_dup@DB_VERSION_UNIQUE_NAME@ +#define __bam_compress_salvage __bam_compress_salvage@DB_VERSION_UNIQUE_NAME@ +#define __bam_compress_count __bam_compress_count@DB_VERSION_UNIQUE_NAME@ +#define __bam_pgin __bam_pgin@DB_VERSION_UNIQUE_NAME@ +#define __bam_pgout __bam_pgout@DB_VERSION_UNIQUE_NAME@ +#define __bam_mswap __bam_mswap@DB_VERSION_UNIQUE_NAME@ +#define __bam_ca_delete __bam_ca_delete@DB_VERSION_UNIQUE_NAME@ +#define __ram_ca_delete __ram_ca_delete@DB_VERSION_UNIQUE_NAME@ +#define __bam_ca_di __bam_ca_di@DB_VERSION_UNIQUE_NAME@ +#define __bam_ca_dup __bam_ca_dup@DB_VERSION_UNIQUE_NAME@ +#define __bam_ca_undodup __bam_ca_undodup@DB_VERSION_UNIQUE_NAME@ +#define __bam_ca_rsplit __bam_ca_rsplit@DB_VERSION_UNIQUE_NAME@ +#define __bam_ca_split __bam_ca_split@DB_VERSION_UNIQUE_NAME@ +#define __bam_ca_undosplit __bam_ca_undosplit@DB_VERSION_UNIQUE_NAME@ +#define __bamc_init __bamc_init@DB_VERSION_UNIQUE_NAME@ +#define __bamc_refresh __bamc_refresh@DB_VERSION_UNIQUE_NAME@ +#define __bamc_cmp __bamc_cmp@DB_VERSION_UNIQUE_NAME@ +#define __bamc_count __bamc_count@DB_VERSION_UNIQUE_NAME@ +#define __bamc_dup __bamc_dup@DB_VERSION_UNIQUE_NAME@ +#define __bam_bulk_overflow __bam_bulk_overflow@DB_VERSION_UNIQUE_NAME@ +#define __bam_bulk_duplicates __bam_bulk_duplicates@DB_VERSION_UNIQUE_NAME@ +#define __bamc_rget __bamc_rget@DB_VERSION_UNIQUE_NAME@ +#define __bam_opd_exists __bam_opd_exists@DB_VERSION_UNIQUE_NAME@ +#define __bam_ditem __bam_ditem@DB_VERSION_UNIQUE_NAME@ +#define __bam_adjindx __bam_adjindx@DB_VERSION_UNIQUE_NAME@ +#define __bam_dpages __bam_dpages@DB_VERSION_UNIQUE_NAME@ +#define __bam_pupdate __bam_pupdate@DB_VERSION_UNIQUE_NAME@ +#define __bam_db_create __bam_db_create@DB_VERSION_UNIQUE_NAME@ +#define __bam_db_close __bam_db_close@DB_VERSION_UNIQUE_NAME@ +#define __bam_map_flags __bam_map_flags@DB_VERSION_UNIQUE_NAME@ +#define __bam_set_flags __bam_set_flags@DB_VERSION_UNIQUE_NAME@ +#define __bam_set_bt_compare __bam_set_bt_compare@DB_VERSION_UNIQUE_NAME@ +#define __bam_set_bt_compress __bam_set_bt_compress@DB_VERSION_UNIQUE_NAME@ +#define __bam_get_bt_minkey __bam_get_bt_minkey@DB_VERSION_UNIQUE_NAME@ +#define __bam_copy_config __bam_copy_config@DB_VERSION_UNIQUE_NAME@ +#define __ram_map_flags __ram_map_flags@DB_VERSION_UNIQUE_NAME@ +#define __ram_set_flags __ram_set_flags@DB_VERSION_UNIQUE_NAME@ +#define __ram_get_re_len __ram_get_re_len@DB_VERSION_UNIQUE_NAME@ +#define __ram_get_re_pad __ram_get_re_pad@DB_VERSION_UNIQUE_NAME@ +#define __bam_open __bam_open@DB_VERSION_UNIQUE_NAME@ +#define __bam_metachk __bam_metachk@DB_VERSION_UNIQUE_NAME@ +#define __bam_read_root __bam_read_root@DB_VERSION_UNIQUE_NAME@ +#define __bam_new_file __bam_new_file@DB_VERSION_UNIQUE_NAME@ +#define __bam_new_subdb __bam_new_subdb@DB_VERSION_UNIQUE_NAME@ +#define __bam_iitem __bam_iitem@DB_VERSION_UNIQUE_NAME@ +#define __bam_ritem __bam_ritem@DB_VERSION_UNIQUE_NAME@ +#define __bam_ritem_nolog __bam_ritem_nolog@DB_VERSION_UNIQUE_NAME@ +#define __bam_irep __bam_irep@DB_VERSION_UNIQUE_NAME@ +#define __bam_split_recover __bam_split_recover@DB_VERSION_UNIQUE_NAME@ +#define __bam_split_48_recover __bam_split_48_recover@DB_VERSION_UNIQUE_NAME@ +#define __bam_split_42_recover __bam_split_42_recover@DB_VERSION_UNIQUE_NAME@ +#define __bam_rsplit_recover __bam_rsplit_recover@DB_VERSION_UNIQUE_NAME@ +#define __bam_adj_recover __bam_adj_recover@DB_VERSION_UNIQUE_NAME@ +#define __bam_cadjust_recover __bam_cadjust_recover@DB_VERSION_UNIQUE_NAME@ +#define __bam_cdel_recover __bam_cdel_recover@DB_VERSION_UNIQUE_NAME@ +#define __bam_repl_recover __bam_repl_recover@DB_VERSION_UNIQUE_NAME@ +#define __bam_irep_recover __bam_irep_recover@DB_VERSION_UNIQUE_NAME@ +#define __bam_root_recover __bam_root_recover@DB_VERSION_UNIQUE_NAME@ +#define __bam_curadj_recover __bam_curadj_recover@DB_VERSION_UNIQUE_NAME@ +#define __bam_rcuradj_recover __bam_rcuradj_recover@DB_VERSION_UNIQUE_NAME@ +#define __bam_merge_44_recover __bam_merge_44_recover@DB_VERSION_UNIQUE_NAME@ +#define __bam_relink_43_recover __bam_relink_43_recover@DB_VERSION_UNIQUE_NAME@ +#define __bam_reclaim __bam_reclaim@DB_VERSION_UNIQUE_NAME@ +#define __bam_truncate __bam_truncate@DB_VERSION_UNIQUE_NAME@ +#define __ram_open __ram_open@DB_VERSION_UNIQUE_NAME@ +#define __ram_append __ram_append@DB_VERSION_UNIQUE_NAME@ +#define __ramc_del __ramc_del@DB_VERSION_UNIQUE_NAME@ +#define __ramc_get __ramc_get@DB_VERSION_UNIQUE_NAME@ +#define __ramc_put __ramc_put@DB_VERSION_UNIQUE_NAME@ +#define __ram_ca __ram_ca@DB_VERSION_UNIQUE_NAME@ +#define __ram_getno __ram_getno@DB_VERSION_UNIQUE_NAME@ +#define __ram_writeback __ram_writeback@DB_VERSION_UNIQUE_NAME@ +#define __bam_rsearch __bam_rsearch@DB_VERSION_UNIQUE_NAME@ +#define __bam_adjust __bam_adjust@DB_VERSION_UNIQUE_NAME@ +#define __bam_nrecs __bam_nrecs@DB_VERSION_UNIQUE_NAME@ +#define __bam_total __bam_total@DB_VERSION_UNIQUE_NAME@ +#define __bam_get_root __bam_get_root@DB_VERSION_UNIQUE_NAME@ +#define __bam_search __bam_search@DB_VERSION_UNIQUE_NAME@ +#define __bam_stkrel __bam_stkrel@DB_VERSION_UNIQUE_NAME@ +#define __bam_stkgrow __bam_stkgrow@DB_VERSION_UNIQUE_NAME@ +#define __bam_split __bam_split@DB_VERSION_UNIQUE_NAME@ +#define __bam_broot __bam_broot@DB_VERSION_UNIQUE_NAME@ +#define __ram_root __ram_root@DB_VERSION_UNIQUE_NAME@ +#define __bam_pinsert __bam_pinsert@DB_VERSION_UNIQUE_NAME@ +#define __bam_copy __bam_copy@DB_VERSION_UNIQUE_NAME@ +#define __bam_stat __bam_stat@DB_VERSION_UNIQUE_NAME@ +#define __bam_stat_print __bam_stat_print@DB_VERSION_UNIQUE_NAME@ +#define __bam_stat_callback __bam_stat_callback@DB_VERSION_UNIQUE_NAME@ +#define __bam_print_cursor __bam_print_cursor@DB_VERSION_UNIQUE_NAME@ +#define __bam_key_range __bam_key_range@DB_VERSION_UNIQUE_NAME@ +#define __bam_traverse __bam_traverse@DB_VERSION_UNIQUE_NAME@ +#define __bam_30_btreemeta __bam_30_btreemeta@DB_VERSION_UNIQUE_NAME@ +#define __bam_31_btreemeta __bam_31_btreemeta@DB_VERSION_UNIQUE_NAME@ +#define __bam_31_lbtree __bam_31_lbtree@DB_VERSION_UNIQUE_NAME@ +#define __bam_vrfy_meta __bam_vrfy_meta@DB_VERSION_UNIQUE_NAME@ +#define __ram_vrfy_leaf __ram_vrfy_leaf@DB_VERSION_UNIQUE_NAME@ +#define __bam_vrfy __bam_vrfy@DB_VERSION_UNIQUE_NAME@ +#define __bam_vrfy_itemorder __bam_vrfy_itemorder@DB_VERSION_UNIQUE_NAME@ +#define __bam_vrfy_structure __bam_vrfy_structure@DB_VERSION_UNIQUE_NAME@ +#define __bam_vrfy_subtree __bam_vrfy_subtree@DB_VERSION_UNIQUE_NAME@ +#define __bam_salvage __bam_salvage@DB_VERSION_UNIQUE_NAME@ +#define __bam_salvage_walkdupint __bam_salvage_walkdupint@DB_VERSION_UNIQUE_NAME@ +#define __bam_meta2pgset __bam_meta2pgset@DB_VERSION_UNIQUE_NAME@ +#define __bam_split_desc __bam_split_desc@DB_VERSION_UNIQUE_NAME@ +#define __bam_split_48_desc __bam_split_48_desc@DB_VERSION_UNIQUE_NAME@ +#define __bam_split_42_desc __bam_split_42_desc@DB_VERSION_UNIQUE_NAME@ +#define __bam_rsplit_desc __bam_rsplit_desc@DB_VERSION_UNIQUE_NAME@ +#define __bam_adj_desc __bam_adj_desc@DB_VERSION_UNIQUE_NAME@ +#define __bam_cadjust_desc __bam_cadjust_desc@DB_VERSION_UNIQUE_NAME@ +#define __bam_cdel_desc __bam_cdel_desc@DB_VERSION_UNIQUE_NAME@ +#define __bam_repl_desc __bam_repl_desc@DB_VERSION_UNIQUE_NAME@ +#define __bam_irep_desc __bam_irep_desc@DB_VERSION_UNIQUE_NAME@ +#define __bam_root_desc __bam_root_desc@DB_VERSION_UNIQUE_NAME@ +#define __bam_curadj_desc __bam_curadj_desc@DB_VERSION_UNIQUE_NAME@ +#define __bam_rcuradj_desc __bam_rcuradj_desc@DB_VERSION_UNIQUE_NAME@ +#define __bam_relink_43_desc __bam_relink_43_desc@DB_VERSION_UNIQUE_NAME@ +#define __bam_merge_44_desc __bam_merge_44_desc@DB_VERSION_UNIQUE_NAME@ +#define __bam_init_recover __bam_init_recover@DB_VERSION_UNIQUE_NAME@ +#define __bam_split_print __bam_split_print@DB_VERSION_UNIQUE_NAME@ +#define __bam_split_48_print __bam_split_48_print@DB_VERSION_UNIQUE_NAME@ +#define __bam_split_42_print __bam_split_42_print@DB_VERSION_UNIQUE_NAME@ +#define __bam_rsplit_print __bam_rsplit_print@DB_VERSION_UNIQUE_NAME@ +#define __bam_adj_print __bam_adj_print@DB_VERSION_UNIQUE_NAME@ +#define __bam_cadjust_print __bam_cadjust_print@DB_VERSION_UNIQUE_NAME@ +#define __bam_cdel_print __bam_cdel_print@DB_VERSION_UNIQUE_NAME@ +#define __bam_repl_print __bam_repl_print@DB_VERSION_UNIQUE_NAME@ +#define __bam_irep_print __bam_irep_print@DB_VERSION_UNIQUE_NAME@ +#define __bam_root_print __bam_root_print@DB_VERSION_UNIQUE_NAME@ +#define __bam_curadj_print __bam_curadj_print@DB_VERSION_UNIQUE_NAME@ +#define __bam_rcuradj_print __bam_rcuradj_print@DB_VERSION_UNIQUE_NAME@ +#define __bam_relink_43_print __bam_relink_43_print@DB_VERSION_UNIQUE_NAME@ +#define __bam_merge_44_print __bam_merge_44_print@DB_VERSION_UNIQUE_NAME@ +#define __bam_init_print __bam_init_print@DB_VERSION_UNIQUE_NAME@ +#ifndef HAVE_ATOI +#define atoi atoi@DB_VERSION_UNIQUE_NAME@ +#endif +#ifndef HAVE_ATOL +#define atol atol@DB_VERSION_UNIQUE_NAME@ +#endif +#ifndef HAVE_BSEARCH +#define bsearch bsearch@DB_VERSION_UNIQUE_NAME@ +#endif +#ifndef HAVE_GETCWD +#define getcwd getcwd@DB_VERSION_UNIQUE_NAME@ +#endif +#ifndef HAVE_GETOPT +#define getopt getopt@DB_VERSION_UNIQUE_NAME@ +#endif +#ifndef HAVE_ISALPHA +#define isalpha isalpha@DB_VERSION_UNIQUE_NAME@ +#endif +#ifndef HAVE_ISDIGIT +#define isdigit isdigit@DB_VERSION_UNIQUE_NAME@ +#endif +#ifndef HAVE_ISPRINT +#define isprint isprint@DB_VERSION_UNIQUE_NAME@ +#endif +#ifndef HAVE_ISSPACE +#define isspace isspace@DB_VERSION_UNIQUE_NAME@ +#endif +#ifndef HAVE_MEMCMP +#define memcmp memcmp@DB_VERSION_UNIQUE_NAME@ +#endif +#ifndef HAVE_MEMCPY +#define memcpy memcpy@DB_VERSION_UNIQUE_NAME@ +#endif +#ifndef HAVE_MEMMOVE +#define memmove memmove@DB_VERSION_UNIQUE_NAME@ +#endif +#ifndef HAVE_PRINTF +#define printf printf@DB_VERSION_UNIQUE_NAME@ +#endif +#ifndef HAVE_PRINTF +#define fprintf fprintf@DB_VERSION_UNIQUE_NAME@ +#endif +#ifndef HAVE_PRINTF +#define vfprintf vfprintf@DB_VERSION_UNIQUE_NAME@ +#endif +#ifndef HAVE_QSORT +#define qsort qsort@DB_VERSION_UNIQUE_NAME@ +#endif +#ifndef HAVE_RAISE +#define raise raise@DB_VERSION_UNIQUE_NAME@ +#endif +#ifndef HAVE_RAND +#define rand rand@DB_VERSION_UNIQUE_NAME@ +#define srand srand@DB_VERSION_UNIQUE_NAME@ +#endif +#ifndef HAVE_SNPRINTF +#define snprintf snprintf@DB_VERSION_UNIQUE_NAME@ +#endif +#ifndef HAVE_VSNPRINTF +#define vsnprintf vsnprintf@DB_VERSION_UNIQUE_NAME@ +#endif +#ifndef HAVE_STRCASECMP +#define strcasecmp strcasecmp@DB_VERSION_UNIQUE_NAME@ +#endif +#ifndef HAVE_STRCASECMP +#define strncasecmp strncasecmp@DB_VERSION_UNIQUE_NAME@ +#endif +#ifndef HAVE_STRCAT +#define strcat strcat@DB_VERSION_UNIQUE_NAME@ +#endif +#ifndef HAVE_STRCHR +#define strchr strchr@DB_VERSION_UNIQUE_NAME@ +#endif +#ifndef HAVE_STRDUP +#define strdup strdup@DB_VERSION_UNIQUE_NAME@ +#endif +#ifndef HAVE_STRERROR +#define strerror strerror@DB_VERSION_UNIQUE_NAME@ +#endif +#ifndef HAVE_STRNCAT +#define strncat strncat@DB_VERSION_UNIQUE_NAME@ +#endif +#ifndef HAVE_STRNCMP +#define strncmp strncmp@DB_VERSION_UNIQUE_NAME@ +#endif +#ifndef HAVE_STRRCHR +#define strrchr strrchr@DB_VERSION_UNIQUE_NAME@ +#endif +#ifndef HAVE_STRSEP +#define strsep strsep@DB_VERSION_UNIQUE_NAME@ +#endif +#ifndef HAVE_STRTOL +#define strtol strtol@DB_VERSION_UNIQUE_NAME@ +#endif +#ifndef HAVE_STRTOUL +#define strtoul strtoul@DB_VERSION_UNIQUE_NAME@ +#endif +#ifndef HAVE_TIME +#define time time@DB_VERSION_UNIQUE_NAME@ +#endif +#define __clock_set_expires __clock_set_expires@DB_VERSION_UNIQUE_NAME@ +#define __clock_expired __clock_expired@DB_VERSION_UNIQUE_NAME@ +#define __crypto_region_init __crypto_region_init@DB_VERSION_UNIQUE_NAME@ +#define __db_isbigendian __db_isbigendian@DB_VERSION_UNIQUE_NAME@ +#define __db_byteorder __db_byteorder@DB_VERSION_UNIQUE_NAME@ +#define __db_compress_count_int __db_compress_count_int@DB_VERSION_UNIQUE_NAME@ +#define __db_compress_int __db_compress_int@DB_VERSION_UNIQUE_NAME@ +#define __db_decompress_count_int __db_decompress_count_int@DB_VERSION_UNIQUE_NAME@ +#define __db_decompress_int __db_decompress_int@DB_VERSION_UNIQUE_NAME@ +#define __db_decompress_int32 __db_decompress_int32@DB_VERSION_UNIQUE_NAME@ +#define __db_fchk __db_fchk@DB_VERSION_UNIQUE_NAME@ +#define __db_fcchk __db_fcchk@DB_VERSION_UNIQUE_NAME@ +#define __db_ferr __db_ferr@DB_VERSION_UNIQUE_NAME@ +#define __db_fnl __db_fnl@DB_VERSION_UNIQUE_NAME@ +#define __db_pgerr __db_pgerr@DB_VERSION_UNIQUE_NAME@ +#define __db_pgfmt __db_pgfmt@DB_VERSION_UNIQUE_NAME@ +#ifdef DIAGNOSTIC +#define __db_assert __db_assert@DB_VERSION_UNIQUE_NAME@ +#endif +#define __env_panic_msg __env_panic_msg@DB_VERSION_UNIQUE_NAME@ +#define __env_panic __env_panic@DB_VERSION_UNIQUE_NAME@ +#define __db_unknown_error __db_unknown_error@DB_VERSION_UNIQUE_NAME@ +#define __db_syserr __db_syserr@DB_VERSION_UNIQUE_NAME@ +#define __db_err __db_err@DB_VERSION_UNIQUE_NAME@ +#define __db_errx __db_errx@DB_VERSION_UNIQUE_NAME@ +#define __db_errcall __db_errcall@DB_VERSION_UNIQUE_NAME@ +#define __db_errfile __db_errfile@DB_VERSION_UNIQUE_NAME@ +#define __db_msgadd __db_msgadd@DB_VERSION_UNIQUE_NAME@ +#define __db_msgadd_ap __db_msgadd_ap@DB_VERSION_UNIQUE_NAME@ +#define __db_msg __db_msg@DB_VERSION_UNIQUE_NAME@ +#define __db_repmsg __db_repmsg@DB_VERSION_UNIQUE_NAME@ +#define __db_unknown_flag __db_unknown_flag@DB_VERSION_UNIQUE_NAME@ +#define __db_unknown_type __db_unknown_type@DB_VERSION_UNIQUE_NAME@ +#define __db_unknown_path __db_unknown_path@DB_VERSION_UNIQUE_NAME@ +#define __db_not_txn_env __db_not_txn_env@DB_VERSION_UNIQUE_NAME@ +#define __db_rec_toobig __db_rec_toobig@DB_VERSION_UNIQUE_NAME@ +#define __db_rec_repl __db_rec_repl@DB_VERSION_UNIQUE_NAME@ +#define __dbc_logging __dbc_logging@DB_VERSION_UNIQUE_NAME@ +#define __db_check_lsn __db_check_lsn@DB_VERSION_UNIQUE_NAME@ +#define __db_rdonly __db_rdonly@DB_VERSION_UNIQUE_NAME@ +#define __db_space_err __db_space_err@DB_VERSION_UNIQUE_NAME@ +#define __db_failed __db_failed@DB_VERSION_UNIQUE_NAME@ +#define __db_getlong __db_getlong@DB_VERSION_UNIQUE_NAME@ +#define __db_getulong __db_getulong@DB_VERSION_UNIQUE_NAME@ +#define __db_idspace __db_idspace@DB_VERSION_UNIQUE_NAME@ +#define __db_log2 __db_log2@DB_VERSION_UNIQUE_NAME@ +#define __db_tablesize __db_tablesize@DB_VERSION_UNIQUE_NAME@ +#define __db_hashinit __db_hashinit@DB_VERSION_UNIQUE_NAME@ +#define __dbt_usercopy __dbt_usercopy@DB_VERSION_UNIQUE_NAME@ +#define __dbt_userfree __dbt_userfree@DB_VERSION_UNIQUE_NAME@ +#define __db_mkpath __db_mkpath@DB_VERSION_UNIQUE_NAME@ +#define __db_openflags __db_openflags@DB_VERSION_UNIQUE_NAME@ +#define __bam_split_desc __bam_split_desc@DB_VERSION_UNIQUE_NAME@ +#define __bam_split_48_desc __bam_split_48_desc@DB_VERSION_UNIQUE_NAME@ +#define __bam_split_42_desc __bam_split_42_desc@DB_VERSION_UNIQUE_NAME@ +#define __bam_rsplit_desc __bam_rsplit_desc@DB_VERSION_UNIQUE_NAME@ +#define __bam_adj_desc __bam_adj_desc@DB_VERSION_UNIQUE_NAME@ +#define __bam_cadjust_desc __bam_cadjust_desc@DB_VERSION_UNIQUE_NAME@ +#define __bam_cdel_desc __bam_cdel_desc@DB_VERSION_UNIQUE_NAME@ +#define __bam_repl_desc __bam_repl_desc@DB_VERSION_UNIQUE_NAME@ +#define __bam_irep_desc __bam_irep_desc@DB_VERSION_UNIQUE_NAME@ +#define __bam_root_desc __bam_root_desc@DB_VERSION_UNIQUE_NAME@ +#define __bam_curadj_desc __bam_curadj_desc@DB_VERSION_UNIQUE_NAME@ +#define __bam_rcuradj_desc __bam_rcuradj_desc@DB_VERSION_UNIQUE_NAME@ +#define __bam_relink_43_desc __bam_relink_43_desc@DB_VERSION_UNIQUE_NAME@ +#define __bam_merge_44_desc __bam_merge_44_desc@DB_VERSION_UNIQUE_NAME@ +#define __crdel_metasub_desc __crdel_metasub_desc@DB_VERSION_UNIQUE_NAME@ +#define __crdel_inmem_create_desc __crdel_inmem_create_desc@DB_VERSION_UNIQUE_NAME@ +#define __crdel_inmem_rename_desc __crdel_inmem_rename_desc@DB_VERSION_UNIQUE_NAME@ +#define __crdel_inmem_remove_desc __crdel_inmem_remove_desc@DB_VERSION_UNIQUE_NAME@ +#define __db_addrem_desc __db_addrem_desc@DB_VERSION_UNIQUE_NAME@ +#define __db_addrem_42_desc __db_addrem_42_desc@DB_VERSION_UNIQUE_NAME@ +#define __db_big_desc __db_big_desc@DB_VERSION_UNIQUE_NAME@ +#define __db_big_42_desc __db_big_42_desc@DB_VERSION_UNIQUE_NAME@ +#define __db_ovref_desc __db_ovref_desc@DB_VERSION_UNIQUE_NAME@ +#define __db_relink_42_desc __db_relink_42_desc@DB_VERSION_UNIQUE_NAME@ +#define __db_debug_desc __db_debug_desc@DB_VERSION_UNIQUE_NAME@ +#define __db_noop_desc __db_noop_desc@DB_VERSION_UNIQUE_NAME@ +#define __db_pg_alloc_42_desc __db_pg_alloc_42_desc@DB_VERSION_UNIQUE_NAME@ +#define __db_pg_alloc_desc __db_pg_alloc_desc@DB_VERSION_UNIQUE_NAME@ +#define __db_pg_free_42_desc __db_pg_free_42_desc@DB_VERSION_UNIQUE_NAME@ +#define __db_pg_free_desc __db_pg_free_desc@DB_VERSION_UNIQUE_NAME@ +#define __db_cksum_desc __db_cksum_desc@DB_VERSION_UNIQUE_NAME@ +#define __db_pg_freedata_42_desc __db_pg_freedata_42_desc@DB_VERSION_UNIQUE_NAME@ +#define __db_pg_freedata_desc __db_pg_freedata_desc@DB_VERSION_UNIQUE_NAME@ +#define __db_pg_init_desc __db_pg_init_desc@DB_VERSION_UNIQUE_NAME@ +#define __db_pg_sort_44_desc __db_pg_sort_44_desc@DB_VERSION_UNIQUE_NAME@ +#define __db_pg_trunc_desc __db_pg_trunc_desc@DB_VERSION_UNIQUE_NAME@ +#define __db_realloc_desc __db_realloc_desc@DB_VERSION_UNIQUE_NAME@ +#define __db_relink_desc __db_relink_desc@DB_VERSION_UNIQUE_NAME@ +#define __db_merge_desc __db_merge_desc@DB_VERSION_UNIQUE_NAME@ +#define __db_pgno_desc __db_pgno_desc@DB_VERSION_UNIQUE_NAME@ +#define __dbreg_register_desc __dbreg_register_desc@DB_VERSION_UNIQUE_NAME@ +#define __fop_create_42_desc __fop_create_42_desc@DB_VERSION_UNIQUE_NAME@ +#define __fop_create_desc __fop_create_desc@DB_VERSION_UNIQUE_NAME@ +#define __fop_remove_desc __fop_remove_desc@DB_VERSION_UNIQUE_NAME@ +#define __fop_write_42_desc __fop_write_42_desc@DB_VERSION_UNIQUE_NAME@ +#define __fop_write_desc __fop_write_desc@DB_VERSION_UNIQUE_NAME@ +#define __fop_rename_42_desc __fop_rename_42_desc@DB_VERSION_UNIQUE_NAME@ +#define __fop_rename_noundo_46_desc __fop_rename_noundo_46_desc@DB_VERSION_UNIQUE_NAME@ +#define __fop_rename_desc __fop_rename_desc@DB_VERSION_UNIQUE_NAME@ +#define __fop_rename_noundo_desc __fop_rename_noundo_desc@DB_VERSION_UNIQUE_NAME@ +#define __fop_file_remove_desc __fop_file_remove_desc@DB_VERSION_UNIQUE_NAME@ +#define __ham_insdel_desc __ham_insdel_desc@DB_VERSION_UNIQUE_NAME@ +#define __ham_insdel_42_desc __ham_insdel_42_desc@DB_VERSION_UNIQUE_NAME@ +#define __ham_newpage_desc __ham_newpage_desc@DB_VERSION_UNIQUE_NAME@ +#define __ham_splitdata_desc __ham_splitdata_desc@DB_VERSION_UNIQUE_NAME@ +#define __ham_replace_desc __ham_replace_desc@DB_VERSION_UNIQUE_NAME@ +#define __ham_replace_42_desc __ham_replace_42_desc@DB_VERSION_UNIQUE_NAME@ +#define __ham_copypage_desc __ham_copypage_desc@DB_VERSION_UNIQUE_NAME@ +#define __ham_metagroup_42_desc __ham_metagroup_42_desc@DB_VERSION_UNIQUE_NAME@ +#define __ham_metagroup_desc __ham_metagroup_desc@DB_VERSION_UNIQUE_NAME@ +#define __ham_groupalloc_42_desc __ham_groupalloc_42_desc@DB_VERSION_UNIQUE_NAME@ +#define __ham_groupalloc_desc __ham_groupalloc_desc@DB_VERSION_UNIQUE_NAME@ +#define __ham_changeslot_desc __ham_changeslot_desc@DB_VERSION_UNIQUE_NAME@ +#define __ham_contract_desc __ham_contract_desc@DB_VERSION_UNIQUE_NAME@ +#define __ham_curadj_desc __ham_curadj_desc@DB_VERSION_UNIQUE_NAME@ +#define __ham_chgpg_desc __ham_chgpg_desc@DB_VERSION_UNIQUE_NAME@ +#define __heap_addrem_desc __heap_addrem_desc@DB_VERSION_UNIQUE_NAME@ +#define __heap_addrem_50_desc __heap_addrem_50_desc@DB_VERSION_UNIQUE_NAME@ +#define __heap_pg_alloc_desc __heap_pg_alloc_desc@DB_VERSION_UNIQUE_NAME@ +#define __heap_trunc_meta_desc __heap_trunc_meta_desc@DB_VERSION_UNIQUE_NAME@ +#define __heap_trunc_page_desc __heap_trunc_page_desc@DB_VERSION_UNIQUE_NAME@ +#define __qam_incfirst_desc __qam_incfirst_desc@DB_VERSION_UNIQUE_NAME@ +#define __qam_mvptr_desc __qam_mvptr_desc@DB_VERSION_UNIQUE_NAME@ +#define __qam_del_desc __qam_del_desc@DB_VERSION_UNIQUE_NAME@ +#define __qam_add_desc __qam_add_desc@DB_VERSION_UNIQUE_NAME@ +#define __qam_delext_desc __qam_delext_desc@DB_VERSION_UNIQUE_NAME@ +#define __repmgr_member_desc __repmgr_member_desc@DB_VERSION_UNIQUE_NAME@ +#define __txn_regop_42_desc __txn_regop_42_desc@DB_VERSION_UNIQUE_NAME@ +#define __txn_regop_desc __txn_regop_desc@DB_VERSION_UNIQUE_NAME@ +#define __txn_ckp_42_desc __txn_ckp_42_desc@DB_VERSION_UNIQUE_NAME@ +#define __txn_ckp_desc __txn_ckp_desc@DB_VERSION_UNIQUE_NAME@ +#define __txn_child_desc __txn_child_desc@DB_VERSION_UNIQUE_NAME@ +#define __txn_xa_regop_42_desc __txn_xa_regop_42_desc@DB_VERSION_UNIQUE_NAME@ +#define __txn_prepare_desc __txn_prepare_desc@DB_VERSION_UNIQUE_NAME@ +#define __txn_recycle_desc __txn_recycle_desc@DB_VERSION_UNIQUE_NAME@ +#define __db_util_arg __db_util_arg@DB_VERSION_UNIQUE_NAME@ +#define __db_util_cache __db_util_cache@DB_VERSION_UNIQUE_NAME@ +#define __db_util_logset __db_util_logset@DB_VERSION_UNIQUE_NAME@ +#define __db_util_siginit __db_util_siginit@DB_VERSION_UNIQUE_NAME@ +#define __db_util_interrupted __db_util_interrupted@DB_VERSION_UNIQUE_NAME@ +#define __db_util_sigresend __db_util_sigresend@DB_VERSION_UNIQUE_NAME@ +#define __db_zero_fill __db_zero_fill@DB_VERSION_UNIQUE_NAME@ +#define __db_zero_extend __db_zero_extend@DB_VERSION_UNIQUE_NAME@ +#define __aes_setup __aes_setup@DB_VERSION_UNIQUE_NAME@ +#define __aes_adj_size __aes_adj_size@DB_VERSION_UNIQUE_NAME@ +#define __aes_close __aes_close@DB_VERSION_UNIQUE_NAME@ +#define __aes_decrypt __aes_decrypt@DB_VERSION_UNIQUE_NAME@ +#define __aes_encrypt __aes_encrypt@DB_VERSION_UNIQUE_NAME@ +#define __aes_init __aes_init@DB_VERSION_UNIQUE_NAME@ +#define __crypto_env_close __crypto_env_close@DB_VERSION_UNIQUE_NAME@ +#define __crypto_env_refresh __crypto_env_refresh@DB_VERSION_UNIQUE_NAME@ +#define __crypto_algsetup __crypto_algsetup@DB_VERSION_UNIQUE_NAME@ +#define __crypto_decrypt_meta __crypto_decrypt_meta@DB_VERSION_UNIQUE_NAME@ +#define __crypto_set_passwd __crypto_set_passwd@DB_VERSION_UNIQUE_NAME@ +#define __db_generate_iv __db_generate_iv@DB_VERSION_UNIQUE_NAME@ +#define __db_rijndaelKeySetupEnc __db_rijndaelKeySetupEnc@DB_VERSION_UNIQUE_NAME@ +#define __db_rijndaelKeySetupDec __db_rijndaelKeySetupDec@DB_VERSION_UNIQUE_NAME@ +#define __db_rijndaelEncrypt __db_rijndaelEncrypt@DB_VERSION_UNIQUE_NAME@ +#define __db_rijndaelDecrypt __db_rijndaelDecrypt@DB_VERSION_UNIQUE_NAME@ +#define __db_rijndaelEncryptRound __db_rijndaelEncryptRound@DB_VERSION_UNIQUE_NAME@ +#define __db_rijndaelDecryptRound __db_rijndaelDecryptRound@DB_VERSION_UNIQUE_NAME@ +#define __db_makeKey __db_makeKey@DB_VERSION_UNIQUE_NAME@ +#define __db_cipherInit __db_cipherInit@DB_VERSION_UNIQUE_NAME@ +#define __db_blockEncrypt __db_blockEncrypt@DB_VERSION_UNIQUE_NAME@ +#define __db_padEncrypt __db_padEncrypt@DB_VERSION_UNIQUE_NAME@ +#define __db_blockDecrypt __db_blockDecrypt@DB_VERSION_UNIQUE_NAME@ +#define __db_padDecrypt __db_padDecrypt@DB_VERSION_UNIQUE_NAME@ +#define __db_cipherUpdateRounds __db_cipherUpdateRounds@DB_VERSION_UNIQUE_NAME@ +#define __dbreg_setup __dbreg_setup@DB_VERSION_UNIQUE_NAME@ +#define __dbreg_teardown __dbreg_teardown@DB_VERSION_UNIQUE_NAME@ +#define __dbreg_teardown_int __dbreg_teardown_int@DB_VERSION_UNIQUE_NAME@ +#define __dbreg_new_id __dbreg_new_id@DB_VERSION_UNIQUE_NAME@ +#define __dbreg_get_id __dbreg_get_id@DB_VERSION_UNIQUE_NAME@ +#define __dbreg_assign_id __dbreg_assign_id@DB_VERSION_UNIQUE_NAME@ +#define __dbreg_revoke_id __dbreg_revoke_id@DB_VERSION_UNIQUE_NAME@ +#define __dbreg_revoke_id_int __dbreg_revoke_id_int@DB_VERSION_UNIQUE_NAME@ +#define __dbreg_close_id __dbreg_close_id@DB_VERSION_UNIQUE_NAME@ +#define __dbreg_close_id_int __dbreg_close_id_int@DB_VERSION_UNIQUE_NAME@ +#define __dbreg_failchk __dbreg_failchk@DB_VERSION_UNIQUE_NAME@ +#define __dbreg_log_close __dbreg_log_close@DB_VERSION_UNIQUE_NAME@ +#define __dbreg_log_id __dbreg_log_id@DB_VERSION_UNIQUE_NAME@ +#define __dbreg_register_desc __dbreg_register_desc@DB_VERSION_UNIQUE_NAME@ +#define __dbreg_init_recover __dbreg_init_recover@DB_VERSION_UNIQUE_NAME@ +#define __dbreg_register_print __dbreg_register_print@DB_VERSION_UNIQUE_NAME@ +#define __dbreg_init_print __dbreg_init_print@DB_VERSION_UNIQUE_NAME@ +#define __dbreg_register_recover __dbreg_register_recover@DB_VERSION_UNIQUE_NAME@ +#define __dbreg_stat_print __dbreg_stat_print@DB_VERSION_UNIQUE_NAME@ +#define __dbreg_print_fname __dbreg_print_fname@DB_VERSION_UNIQUE_NAME@ +#define __dbreg_add_dbentry __dbreg_add_dbentry@DB_VERSION_UNIQUE_NAME@ +#define __dbreg_rem_dbentry __dbreg_rem_dbentry@DB_VERSION_UNIQUE_NAME@ +#define __dbreg_log_files __dbreg_log_files@DB_VERSION_UNIQUE_NAME@ +#define __dbreg_log_nofiles __dbreg_log_nofiles@DB_VERSION_UNIQUE_NAME@ +#define __dbreg_close_files __dbreg_close_files@DB_VERSION_UNIQUE_NAME@ +#define __dbreg_close_file __dbreg_close_file@DB_VERSION_UNIQUE_NAME@ +#define __dbreg_mark_restored __dbreg_mark_restored@DB_VERSION_UNIQUE_NAME@ +#define __dbreg_invalidate_files __dbreg_invalidate_files@DB_VERSION_UNIQUE_NAME@ +#define __dbreg_id_to_db __dbreg_id_to_db@DB_VERSION_UNIQUE_NAME@ +#define __dbreg_id_to_fname __dbreg_id_to_fname@DB_VERSION_UNIQUE_NAME@ +#define __dbreg_fid_to_fname __dbreg_fid_to_fname@DB_VERSION_UNIQUE_NAME@ +#define __dbreg_get_name __dbreg_get_name@DB_VERSION_UNIQUE_NAME@ +#define __dbreg_do_open __dbreg_do_open@DB_VERSION_UNIQUE_NAME@ +#define __dbreg_lazy_id __dbreg_lazy_id@DB_VERSION_UNIQUE_NAME@ +#define __env_alloc_init __env_alloc_init@DB_VERSION_UNIQUE_NAME@ +#define __env_alloc_overhead __env_alloc_overhead@DB_VERSION_UNIQUE_NAME@ +#define __env_alloc_size __env_alloc_size@DB_VERSION_UNIQUE_NAME@ +#define __env_alloc __env_alloc@DB_VERSION_UNIQUE_NAME@ +#define __env_alloc_free __env_alloc_free@DB_VERSION_UNIQUE_NAME@ +#define __env_alloc_extend __env_alloc_extend@DB_VERSION_UNIQUE_NAME@ +#define __env_region_extend __env_region_extend@DB_VERSION_UNIQUE_NAME@ +#define __env_elem_size __env_elem_size@DB_VERSION_UNIQUE_NAME@ +#define __env_get_chunk __env_get_chunk@DB_VERSION_UNIQUE_NAME@ +#define __env_alloc_print __env_alloc_print@DB_VERSION_UNIQUE_NAME@ +#define __env_get_backup_config __env_get_backup_config@DB_VERSION_UNIQUE_NAME@ +#define __env_set_backup_config __env_set_backup_config@DB_VERSION_UNIQUE_NAME@ +#define __env_get_backup_callbacks __env_get_backup_callbacks@DB_VERSION_UNIQUE_NAME@ +#define __env_set_backup_callbacks __env_set_backup_callbacks@DB_VERSION_UNIQUE_NAME@ +#define __env_read_db_config __env_read_db_config@DB_VERSION_UNIQUE_NAME@ +#define __env_failchk_pp __env_failchk_pp@DB_VERSION_UNIQUE_NAME@ +#define __env_failchk_int __env_failchk_int@DB_VERSION_UNIQUE_NAME@ +#define __env_thread_size __env_thread_size@DB_VERSION_UNIQUE_NAME@ +#define __env_thread_max __env_thread_max@DB_VERSION_UNIQUE_NAME@ +#define __env_thread_init __env_thread_init@DB_VERSION_UNIQUE_NAME@ +#define __env_thread_destroy __env_thread_destroy@DB_VERSION_UNIQUE_NAME@ +#define __env_set_state __env_set_state@DB_VERSION_UNIQUE_NAME@ +#define __db_file_extend __db_file_extend@DB_VERSION_UNIQUE_NAME@ +#define __db_file_multi_write __db_file_multi_write@DB_VERSION_UNIQUE_NAME@ +#define __db_file_write __db_file_write@DB_VERSION_UNIQUE_NAME@ +#define __db_env_destroy __db_env_destroy@DB_VERSION_UNIQUE_NAME@ +#define __env_get_alloc __env_get_alloc@DB_VERSION_UNIQUE_NAME@ +#define __env_set_alloc __env_set_alloc@DB_VERSION_UNIQUE_NAME@ +#define __env_get_memory_init __env_get_memory_init@DB_VERSION_UNIQUE_NAME@ +#define __env_set_memory_init __env_set_memory_init@DB_VERSION_UNIQUE_NAME@ +#define __env_get_memory_max __env_get_memory_max@DB_VERSION_UNIQUE_NAME@ +#define __env_set_memory_max __env_set_memory_max@DB_VERSION_UNIQUE_NAME@ +#define __env_get_encrypt_flags __env_get_encrypt_flags@DB_VERSION_UNIQUE_NAME@ +#define __env_set_encrypt __env_set_encrypt@DB_VERSION_UNIQUE_NAME@ +#define __env_map_flags __env_map_flags@DB_VERSION_UNIQUE_NAME@ +#define __env_fetch_flags __env_fetch_flags@DB_VERSION_UNIQUE_NAME@ +#define __env_set_flags __env_set_flags@DB_VERSION_UNIQUE_NAME@ +#define __env_set_backup __env_set_backup@DB_VERSION_UNIQUE_NAME@ +#define __env_set_data_dir __env_set_data_dir@DB_VERSION_UNIQUE_NAME@ +#define __env_add_data_dir __env_add_data_dir@DB_VERSION_UNIQUE_NAME@ +#define __env_set_create_dir __env_set_create_dir@DB_VERSION_UNIQUE_NAME@ +#define __env_set_metadata_dir __env_set_metadata_dir@DB_VERSION_UNIQUE_NAME@ +#define __env_set_data_len __env_set_data_len@DB_VERSION_UNIQUE_NAME@ +#define __env_set_intermediate_dir_mode __env_set_intermediate_dir_mode@DB_VERSION_UNIQUE_NAME@ +#define __env_get_errcall __env_get_errcall@DB_VERSION_UNIQUE_NAME@ +#define __env_set_errcall __env_set_errcall@DB_VERSION_UNIQUE_NAME@ +#define __env_get_errfile __env_get_errfile@DB_VERSION_UNIQUE_NAME@ +#define __env_set_errfile __env_set_errfile@DB_VERSION_UNIQUE_NAME@ +#define __env_get_errpfx __env_get_errpfx@DB_VERSION_UNIQUE_NAME@ +#define __env_set_errpfx __env_set_errpfx@DB_VERSION_UNIQUE_NAME@ +#define __env_set_thread_count __env_set_thread_count@DB_VERSION_UNIQUE_NAME@ +#define __env_get_msgcall __env_get_msgcall@DB_VERSION_UNIQUE_NAME@ +#define __env_set_msgcall __env_set_msgcall@DB_VERSION_UNIQUE_NAME@ +#define __env_get_msgfile __env_get_msgfile@DB_VERSION_UNIQUE_NAME@ +#define __env_set_msgfile __env_set_msgfile@DB_VERSION_UNIQUE_NAME@ +#define __env_set_paniccall __env_set_paniccall@DB_VERSION_UNIQUE_NAME@ +#define __env_set_shm_key __env_set_shm_key@DB_VERSION_UNIQUE_NAME@ +#define __env_set_tmp_dir __env_set_tmp_dir@DB_VERSION_UNIQUE_NAME@ +#define __env_set_verbose __env_set_verbose@DB_VERSION_UNIQUE_NAME@ +#define __db_mi_env __db_mi_env@DB_VERSION_UNIQUE_NAME@ +#define __db_mi_open __db_mi_open@DB_VERSION_UNIQUE_NAME@ +#define __env_not_config __env_not_config@DB_VERSION_UNIQUE_NAME@ +#define __env_set_timeout __env_set_timeout@DB_VERSION_UNIQUE_NAME@ +#define __env_thread_id_string __env_thread_id_string@DB_VERSION_UNIQUE_NAME@ +#define __db_appname __db_appname@DB_VERSION_UNIQUE_NAME@ +#define __db_tmp_open __db_tmp_open@DB_VERSION_UNIQUE_NAME@ +#define __env_open_pp __env_open_pp@DB_VERSION_UNIQUE_NAME@ +#define __env_open __env_open@DB_VERSION_UNIQUE_NAME@ +#define __env_remove __env_remove@DB_VERSION_UNIQUE_NAME@ +#define __env_config __env_config@DB_VERSION_UNIQUE_NAME@ +#define __env_close_pp __env_close_pp@DB_VERSION_UNIQUE_NAME@ +#define __env_close __env_close@DB_VERSION_UNIQUE_NAME@ +#define __env_refresh __env_refresh@DB_VERSION_UNIQUE_NAME@ +#define __env_get_open_flags __env_get_open_flags@DB_VERSION_UNIQUE_NAME@ +#define __env_attach_regions __env_attach_regions@DB_VERSION_UNIQUE_NAME@ +#define __db_apprec __db_apprec@DB_VERSION_UNIQUE_NAME@ +#define __env_openfiles __env_openfiles@DB_VERSION_UNIQUE_NAME@ +#define __env_init_rec __env_init_rec@DB_VERSION_UNIQUE_NAME@ +#define __env_attach __env_attach@DB_VERSION_UNIQUE_NAME@ +#define __env_turn_on __env_turn_on@DB_VERSION_UNIQUE_NAME@ +#define __env_turn_off __env_turn_off@DB_VERSION_UNIQUE_NAME@ +#define __env_panic_set __env_panic_set@DB_VERSION_UNIQUE_NAME@ +#define __env_ref_increment __env_ref_increment@DB_VERSION_UNIQUE_NAME@ +#define __env_ref_decrement __env_ref_decrement@DB_VERSION_UNIQUE_NAME@ +#define __env_ref_get __env_ref_get@DB_VERSION_UNIQUE_NAME@ +#define __env_detach __env_detach@DB_VERSION_UNIQUE_NAME@ +#define __env_remove_env __env_remove_env@DB_VERSION_UNIQUE_NAME@ +#define __env_region_attach __env_region_attach@DB_VERSION_UNIQUE_NAME@ +#define __env_region_share __env_region_share@DB_VERSION_UNIQUE_NAME@ +#define __env_region_detach __env_region_detach@DB_VERSION_UNIQUE_NAME@ +#define __envreg_register __envreg_register@DB_VERSION_UNIQUE_NAME@ +#define __envreg_unregister __envreg_unregister@DB_VERSION_UNIQUE_NAME@ +#define __envreg_xunlock __envreg_xunlock@DB_VERSION_UNIQUE_NAME@ +#define __envreg_isalive __envreg_isalive@DB_VERSION_UNIQUE_NAME@ +#define __env_struct_sig __env_struct_sig@DB_VERSION_UNIQUE_NAME@ +#define __env_stat_print_pp __env_stat_print_pp@DB_VERSION_UNIQUE_NAME@ +#define __db_print_fh __db_print_fh@DB_VERSION_UNIQUE_NAME@ +#define __db_print_fileid __db_print_fileid@DB_VERSION_UNIQUE_NAME@ +#define __db_dl __db_dl@DB_VERSION_UNIQUE_NAME@ +#define __db_dl_pct __db_dl_pct@DB_VERSION_UNIQUE_NAME@ +#define __db_dlbytes __db_dlbytes@DB_VERSION_UNIQUE_NAME@ +#define __db_print_reginfo __db_print_reginfo@DB_VERSION_UNIQUE_NAME@ +#define __db_stat_not_built __db_stat_not_built@DB_VERSION_UNIQUE_NAME@ +#ifndef HAVE_REPLICATION_THREADS +#define __repmgr_close __repmgr_close@DB_VERSION_UNIQUE_NAME@ +#endif +#ifndef HAVE_REPLICATION_THREADS +#define __repmgr_get_ack_policy __repmgr_get_ack_policy@DB_VERSION_UNIQUE_NAME@ +#endif +#ifndef HAVE_REPLICATION_THREADS +#define __repmgr_set_ack_policy __repmgr_set_ack_policy@DB_VERSION_UNIQUE_NAME@ +#endif +#ifndef HAVE_REPLICATION_THREADS +#define __repmgr_site __repmgr_site@DB_VERSION_UNIQUE_NAME@ +#endif +#ifndef HAVE_REPLICATION_THREADS +#define __repmgr_site_by_eid __repmgr_site_by_eid@DB_VERSION_UNIQUE_NAME@ +#endif +#ifndef HAVE_REPLICATION_THREADS +#define __repmgr_local_site __repmgr_local_site@DB_VERSION_UNIQUE_NAME@ +#endif +#ifndef HAVE_REPLICATION_THREADS +#define __repmgr_site_list __repmgr_site_list@DB_VERSION_UNIQUE_NAME@ +#endif +#ifndef HAVE_REPLICATION_THREADS +#define __repmgr_start __repmgr_start@DB_VERSION_UNIQUE_NAME@ +#endif +#ifndef HAVE_REPLICATION_THREADS +#define __repmgr_stat_pp __repmgr_stat_pp@DB_VERSION_UNIQUE_NAME@ +#endif +#ifndef HAVE_REPLICATION_THREADS +#define __repmgr_stat_print_pp __repmgr_stat_print_pp@DB_VERSION_UNIQUE_NAME@ +#endif +#ifndef HAVE_REPLICATION_THREADS +#define __repmgr_handle_event __repmgr_handle_event@DB_VERSION_UNIQUE_NAME@ +#endif +#ifndef HAVE_REPLICATION_THREADS +#define __repmgr_channel __repmgr_channel@DB_VERSION_UNIQUE_NAME@ +#endif +#ifndef HAVE_REPLICATION_THREADS +#define __repmgr_set_msg_dispatch __repmgr_set_msg_dispatch@DB_VERSION_UNIQUE_NAME@ +#endif +#ifndef HAVE_REPLICATION_THREADS +#define __repmgr_init_recover __repmgr_init_recover@DB_VERSION_UNIQUE_NAME@ +#endif +#define __fop_create_42_desc __fop_create_42_desc@DB_VERSION_UNIQUE_NAME@ +#define __fop_create_desc __fop_create_desc@DB_VERSION_UNIQUE_NAME@ +#define __fop_remove_desc __fop_remove_desc@DB_VERSION_UNIQUE_NAME@ +#define __fop_write_42_desc __fop_write_42_desc@DB_VERSION_UNIQUE_NAME@ +#define __fop_write_desc __fop_write_desc@DB_VERSION_UNIQUE_NAME@ +#define __fop_rename_42_desc __fop_rename_42_desc@DB_VERSION_UNIQUE_NAME@ +#define __fop_rename_noundo_46_desc __fop_rename_noundo_46_desc@DB_VERSION_UNIQUE_NAME@ +#define __fop_rename_desc __fop_rename_desc@DB_VERSION_UNIQUE_NAME@ +#define __fop_rename_noundo_desc __fop_rename_noundo_desc@DB_VERSION_UNIQUE_NAME@ +#define __fop_file_remove_desc __fop_file_remove_desc@DB_VERSION_UNIQUE_NAME@ +#define __fop_init_recover __fop_init_recover@DB_VERSION_UNIQUE_NAME@ +#define __fop_create_42_print __fop_create_42_print@DB_VERSION_UNIQUE_NAME@ +#define __fop_create_print __fop_create_print@DB_VERSION_UNIQUE_NAME@ +#define __fop_remove_print __fop_remove_print@DB_VERSION_UNIQUE_NAME@ +#define __fop_write_42_print __fop_write_42_print@DB_VERSION_UNIQUE_NAME@ +#define __fop_write_print __fop_write_print@DB_VERSION_UNIQUE_NAME@ +#define __fop_rename_42_print __fop_rename_42_print@DB_VERSION_UNIQUE_NAME@ +#define __fop_rename_print __fop_rename_print@DB_VERSION_UNIQUE_NAME@ +#define __fop_file_remove_print __fop_file_remove_print@DB_VERSION_UNIQUE_NAME@ +#define __fop_init_print __fop_init_print@DB_VERSION_UNIQUE_NAME@ +#define __fop_create __fop_create@DB_VERSION_UNIQUE_NAME@ +#define __fop_remove __fop_remove@DB_VERSION_UNIQUE_NAME@ +#define __fop_write __fop_write@DB_VERSION_UNIQUE_NAME@ +#define __fop_rename __fop_rename@DB_VERSION_UNIQUE_NAME@ +#define __fop_create_recover __fop_create_recover@DB_VERSION_UNIQUE_NAME@ +#define __fop_create_42_recover __fop_create_42_recover@DB_VERSION_UNIQUE_NAME@ +#define __fop_remove_recover __fop_remove_recover@DB_VERSION_UNIQUE_NAME@ +#define __fop_write_recover __fop_write_recover@DB_VERSION_UNIQUE_NAME@ +#define __fop_write_42_recover __fop_write_42_recover@DB_VERSION_UNIQUE_NAME@ +#define __fop_rename_recover __fop_rename_recover@DB_VERSION_UNIQUE_NAME@ +#define __fop_rename_noundo_recover __fop_rename_noundo_recover@DB_VERSION_UNIQUE_NAME@ +#define __fop_rename_42_recover __fop_rename_42_recover@DB_VERSION_UNIQUE_NAME@ +#define __fop_rename_noundo_46_recover __fop_rename_noundo_46_recover@DB_VERSION_UNIQUE_NAME@ +#define __fop_file_remove_recover __fop_file_remove_recover@DB_VERSION_UNIQUE_NAME@ +#define __fop_lock_handle __fop_lock_handle@DB_VERSION_UNIQUE_NAME@ +#define __fop_file_setup __fop_file_setup@DB_VERSION_UNIQUE_NAME@ +#define __fop_subdb_setup __fop_subdb_setup@DB_VERSION_UNIQUE_NAME@ +#define __fop_remove_setup __fop_remove_setup@DB_VERSION_UNIQUE_NAME@ +#define __fop_read_meta __fop_read_meta@DB_VERSION_UNIQUE_NAME@ +#define __fop_dummy __fop_dummy@DB_VERSION_UNIQUE_NAME@ +#define __fop_dbrename __fop_dbrename@DB_VERSION_UNIQUE_NAME@ +#define __ham_quick_delete __ham_quick_delete@DB_VERSION_UNIQUE_NAME@ +#define __hamc_init __hamc_init@DB_VERSION_UNIQUE_NAME@ +#define __hamc_count __hamc_count@DB_VERSION_UNIQUE_NAME@ +#define __hamc_cmp __hamc_cmp@DB_VERSION_UNIQUE_NAME@ +#define __hamc_dup __hamc_dup@DB_VERSION_UNIQUE_NAME@ +#define __ham_contract_table __ham_contract_table@DB_VERSION_UNIQUE_NAME@ +#define __ham_call_hash __ham_call_hash@DB_VERSION_UNIQUE_NAME@ +#define __ham_overwrite __ham_overwrite@DB_VERSION_UNIQUE_NAME@ +#define __ham_lookup __ham_lookup@DB_VERSION_UNIQUE_NAME@ +#define __ham_init_dbt __ham_init_dbt@DB_VERSION_UNIQUE_NAME@ +#define __hamc_update __hamc_update@DB_VERSION_UNIQUE_NAME@ +#define __ham_get_clist __ham_get_clist@DB_VERSION_UNIQUE_NAME@ +#define __ham_insdel_desc __ham_insdel_desc@DB_VERSION_UNIQUE_NAME@ +#define __ham_insdel_42_desc __ham_insdel_42_desc@DB_VERSION_UNIQUE_NAME@ +#define __ham_newpage_desc __ham_newpage_desc@DB_VERSION_UNIQUE_NAME@ +#define __ham_splitdata_desc __ham_splitdata_desc@DB_VERSION_UNIQUE_NAME@ +#define __ham_replace_desc __ham_replace_desc@DB_VERSION_UNIQUE_NAME@ +#define __ham_replace_42_desc __ham_replace_42_desc@DB_VERSION_UNIQUE_NAME@ +#define __ham_copypage_desc __ham_copypage_desc@DB_VERSION_UNIQUE_NAME@ +#define __ham_metagroup_42_desc __ham_metagroup_42_desc@DB_VERSION_UNIQUE_NAME@ +#define __ham_metagroup_desc __ham_metagroup_desc@DB_VERSION_UNIQUE_NAME@ +#define __ham_groupalloc_42_desc __ham_groupalloc_42_desc@DB_VERSION_UNIQUE_NAME@ +#define __ham_groupalloc_desc __ham_groupalloc_desc@DB_VERSION_UNIQUE_NAME@ +#define __ham_changeslot_desc __ham_changeslot_desc@DB_VERSION_UNIQUE_NAME@ +#define __ham_contract_desc __ham_contract_desc@DB_VERSION_UNIQUE_NAME@ +#define __ham_curadj_desc __ham_curadj_desc@DB_VERSION_UNIQUE_NAME@ +#define __ham_chgpg_desc __ham_chgpg_desc@DB_VERSION_UNIQUE_NAME@ +#define __ham_init_recover __ham_init_recover@DB_VERSION_UNIQUE_NAME@ +#define __ham_insdel_print __ham_insdel_print@DB_VERSION_UNIQUE_NAME@ +#define __ham_insdel_42_print __ham_insdel_42_print@DB_VERSION_UNIQUE_NAME@ +#define __ham_newpage_print __ham_newpage_print@DB_VERSION_UNIQUE_NAME@ +#define __ham_splitdata_print __ham_splitdata_print@DB_VERSION_UNIQUE_NAME@ +#define __ham_replace_print __ham_replace_print@DB_VERSION_UNIQUE_NAME@ +#define __ham_replace_42_print __ham_replace_42_print@DB_VERSION_UNIQUE_NAME@ +#define __ham_copypage_print __ham_copypage_print@DB_VERSION_UNIQUE_NAME@ +#define __ham_metagroup_42_print __ham_metagroup_42_print@DB_VERSION_UNIQUE_NAME@ +#define __ham_metagroup_print __ham_metagroup_print@DB_VERSION_UNIQUE_NAME@ +#define __ham_groupalloc_42_print __ham_groupalloc_42_print@DB_VERSION_UNIQUE_NAME@ +#define __ham_groupalloc_print __ham_groupalloc_print@DB_VERSION_UNIQUE_NAME@ +#define __ham_changeslot_print __ham_changeslot_print@DB_VERSION_UNIQUE_NAME@ +#define __ham_contract_print __ham_contract_print@DB_VERSION_UNIQUE_NAME@ +#define __ham_curadj_print __ham_curadj_print@DB_VERSION_UNIQUE_NAME@ +#define __ham_chgpg_print __ham_chgpg_print@DB_VERSION_UNIQUE_NAME@ +#define __ham_init_print __ham_init_print@DB_VERSION_UNIQUE_NAME@ +#define __ham_compact_int __ham_compact_int@DB_VERSION_UNIQUE_NAME@ +#define __ham_compact_bucket __ham_compact_bucket@DB_VERSION_UNIQUE_NAME@ +#define __ham_compact_hash __ham_compact_hash@DB_VERSION_UNIQUE_NAME@ +#define __ham_pgin __ham_pgin@DB_VERSION_UNIQUE_NAME@ +#define __ham_pgout __ham_pgout@DB_VERSION_UNIQUE_NAME@ +#define __ham_mswap __ham_mswap@DB_VERSION_UNIQUE_NAME@ +#define __ham_add_dup __ham_add_dup@DB_VERSION_UNIQUE_NAME@ +#define __ham_dup_convert __ham_dup_convert@DB_VERSION_UNIQUE_NAME@ +#define __ham_make_dup __ham_make_dup@DB_VERSION_UNIQUE_NAME@ +#define __ham_dsearch __ham_dsearch@DB_VERSION_UNIQUE_NAME@ +#define __ham_func2 __ham_func2@DB_VERSION_UNIQUE_NAME@ +#define __ham_func3 __ham_func3@DB_VERSION_UNIQUE_NAME@ +#define __ham_func4 __ham_func4@DB_VERSION_UNIQUE_NAME@ +#define __ham_func5 __ham_func5@DB_VERSION_UNIQUE_NAME@ +#define __ham_test __ham_test@DB_VERSION_UNIQUE_NAME@ +#define __ham_get_meta __ham_get_meta@DB_VERSION_UNIQUE_NAME@ +#define __ham_release_meta __ham_release_meta@DB_VERSION_UNIQUE_NAME@ +#define __ham_dirty_meta __ham_dirty_meta@DB_VERSION_UNIQUE_NAME@ +#define __ham_return_meta __ham_return_meta@DB_VERSION_UNIQUE_NAME@ +#define __ham_db_create __ham_db_create@DB_VERSION_UNIQUE_NAME@ +#define __ham_db_close __ham_db_close@DB_VERSION_UNIQUE_NAME@ +#define __ham_get_h_ffactor __ham_get_h_ffactor@DB_VERSION_UNIQUE_NAME@ +#define __ham_set_h_compare __ham_set_h_compare@DB_VERSION_UNIQUE_NAME@ +#define __ham_get_h_nelem __ham_get_h_nelem@DB_VERSION_UNIQUE_NAME@ +#define __ham_copy_config __ham_copy_config@DB_VERSION_UNIQUE_NAME@ +#define __ham_open __ham_open@DB_VERSION_UNIQUE_NAME@ +#define __ham_metachk __ham_metachk@DB_VERSION_UNIQUE_NAME@ +#define __ham_new_file __ham_new_file@DB_VERSION_UNIQUE_NAME@ +#define __ham_new_subdb __ham_new_subdb@DB_VERSION_UNIQUE_NAME@ +#define __ham_item __ham_item@DB_VERSION_UNIQUE_NAME@ +#define __ham_item_reset __ham_item_reset@DB_VERSION_UNIQUE_NAME@ +#define __ham_item_init __ham_item_init@DB_VERSION_UNIQUE_NAME@ +#define __ham_item_last __ham_item_last@DB_VERSION_UNIQUE_NAME@ +#define __ham_item_first __ham_item_first@DB_VERSION_UNIQUE_NAME@ +#define __ham_item_prev __ham_item_prev@DB_VERSION_UNIQUE_NAME@ +#define __ham_item_next __ham_item_next@DB_VERSION_UNIQUE_NAME@ +#define __ham_insertpair __ham_insertpair@DB_VERSION_UNIQUE_NAME@ +#define __ham_getindex __ham_getindex@DB_VERSION_UNIQUE_NAME@ +#define __ham_verify_sorted_page __ham_verify_sorted_page@DB_VERSION_UNIQUE_NAME@ +#define __ham_sort_page_cursor __ham_sort_page_cursor@DB_VERSION_UNIQUE_NAME@ +#define __ham_sort_page __ham_sort_page@DB_VERSION_UNIQUE_NAME@ +#define __ham_del_pair __ham_del_pair@DB_VERSION_UNIQUE_NAME@ +#define __ham_replpair __ham_replpair@DB_VERSION_UNIQUE_NAME@ +#define __ham_onpage_replace __ham_onpage_replace@DB_VERSION_UNIQUE_NAME@ +#define __ham_merge_pages __ham_merge_pages@DB_VERSION_UNIQUE_NAME@ +#define __ham_split_page __ham_split_page@DB_VERSION_UNIQUE_NAME@ +#define __ham_add_el __ham_add_el@DB_VERSION_UNIQUE_NAME@ +#define __ham_copypair __ham_copypair@DB_VERSION_UNIQUE_NAME@ +#define __ham_add_ovflpage __ham_add_ovflpage@DB_VERSION_UNIQUE_NAME@ +#define __ham_get_cpage __ham_get_cpage@DB_VERSION_UNIQUE_NAME@ +#define __ham_next_cpage __ham_next_cpage@DB_VERSION_UNIQUE_NAME@ +#define __ham_lock_bucket __ham_lock_bucket@DB_VERSION_UNIQUE_NAME@ +#define __ham_dpair __ham_dpair@DB_VERSION_UNIQUE_NAME@ +#define __ham_insdel_recover __ham_insdel_recover@DB_VERSION_UNIQUE_NAME@ +#define __ham_insdel_42_recover __ham_insdel_42_recover@DB_VERSION_UNIQUE_NAME@ +#define __ham_newpage_recover __ham_newpage_recover@DB_VERSION_UNIQUE_NAME@ +#define __ham_replace_recover __ham_replace_recover@DB_VERSION_UNIQUE_NAME@ +#define __ham_replace_42_recover __ham_replace_42_recover@DB_VERSION_UNIQUE_NAME@ +#define __ham_splitdata_recover __ham_splitdata_recover@DB_VERSION_UNIQUE_NAME@ +#define __ham_copypage_recover __ham_copypage_recover@DB_VERSION_UNIQUE_NAME@ +#define __ham_metagroup_recover __ham_metagroup_recover@DB_VERSION_UNIQUE_NAME@ +#define __ham_contract_recover __ham_contract_recover@DB_VERSION_UNIQUE_NAME@ +#define __ham_groupalloc_recover __ham_groupalloc_recover@DB_VERSION_UNIQUE_NAME@ +#define __ham_changeslot_recover __ham_changeslot_recover@DB_VERSION_UNIQUE_NAME@ +#define __ham_curadj_recover __ham_curadj_recover@DB_VERSION_UNIQUE_NAME@ +#define __ham_chgpg_recover __ham_chgpg_recover@DB_VERSION_UNIQUE_NAME@ +#define __ham_metagroup_42_recover __ham_metagroup_42_recover@DB_VERSION_UNIQUE_NAME@ +#define __ham_groupalloc_42_recover __ham_groupalloc_42_recover@DB_VERSION_UNIQUE_NAME@ +#define __ham_reclaim __ham_reclaim@DB_VERSION_UNIQUE_NAME@ +#define __ham_truncate __ham_truncate@DB_VERSION_UNIQUE_NAME@ +#define __ham_stat __ham_stat@DB_VERSION_UNIQUE_NAME@ +#define __ham_stat_print __ham_stat_print@DB_VERSION_UNIQUE_NAME@ +#define __ham_print_cursor __ham_print_cursor@DB_VERSION_UNIQUE_NAME@ +#define __ham_traverse __ham_traverse@DB_VERSION_UNIQUE_NAME@ +#define __db_no_hash_am __db_no_hash_am@DB_VERSION_UNIQUE_NAME@ +#define __ham_30_hashmeta __ham_30_hashmeta@DB_VERSION_UNIQUE_NAME@ +#define __ham_30_sizefix __ham_30_sizefix@DB_VERSION_UNIQUE_NAME@ +#define __ham_31_hashmeta __ham_31_hashmeta@DB_VERSION_UNIQUE_NAME@ +#define __ham_31_hash __ham_31_hash@DB_VERSION_UNIQUE_NAME@ +#define __ham_46_hashmeta __ham_46_hashmeta@DB_VERSION_UNIQUE_NAME@ +#define __ham_46_hash __ham_46_hash@DB_VERSION_UNIQUE_NAME@ +#define __ham_vrfy_meta __ham_vrfy_meta@DB_VERSION_UNIQUE_NAME@ +#define __ham_vrfy __ham_vrfy@DB_VERSION_UNIQUE_NAME@ +#define __ham_vrfy_structure __ham_vrfy_structure@DB_VERSION_UNIQUE_NAME@ +#define __ham_vrfy_hashing __ham_vrfy_hashing@DB_VERSION_UNIQUE_NAME@ +#define __ham_salvage __ham_salvage@DB_VERSION_UNIQUE_NAME@ +#define __ham_meta2pgset __ham_meta2pgset@DB_VERSION_UNIQUE_NAME@ +#define __heapc_init __heapc_init@DB_VERSION_UNIQUE_NAME@ +#define __heap_ditem __heap_ditem@DB_VERSION_UNIQUE_NAME@ +#define __heap_append __heap_append@DB_VERSION_UNIQUE_NAME@ +#define __heap_pitem __heap_pitem@DB_VERSION_UNIQUE_NAME@ +#define __heapc_dup __heapc_dup@DB_VERSION_UNIQUE_NAME@ +#define __heapc_gsplit __heapc_gsplit@DB_VERSION_UNIQUE_NAME@ +#define __heapc_refresh __heapc_refresh@DB_VERSION_UNIQUE_NAME@ +#define __heap_addrem_desc __heap_addrem_desc@DB_VERSION_UNIQUE_NAME@ +#define __heap_addrem_50_desc __heap_addrem_50_desc@DB_VERSION_UNIQUE_NAME@ +#define __heap_pg_alloc_desc __heap_pg_alloc_desc@DB_VERSION_UNIQUE_NAME@ +#define __heap_trunc_meta_desc __heap_trunc_meta_desc@DB_VERSION_UNIQUE_NAME@ +#define __heap_trunc_page_desc __heap_trunc_page_desc@DB_VERSION_UNIQUE_NAME@ +#define __heap_init_recover __heap_init_recover@DB_VERSION_UNIQUE_NAME@ +#define __heap_addrem_print __heap_addrem_print@DB_VERSION_UNIQUE_NAME@ +#define __heap_addrem_50_print __heap_addrem_50_print@DB_VERSION_UNIQUE_NAME@ +#define __heap_pg_alloc_print __heap_pg_alloc_print@DB_VERSION_UNIQUE_NAME@ +#define __heap_trunc_meta_print __heap_trunc_meta_print@DB_VERSION_UNIQUE_NAME@ +#define __heap_trunc_page_print __heap_trunc_page_print@DB_VERSION_UNIQUE_NAME@ +#define __heap_init_print __heap_init_print@DB_VERSION_UNIQUE_NAME@ +#define __heap_backup __heap_backup@DB_VERSION_UNIQUE_NAME@ +#define __heap_pgin __heap_pgin@DB_VERSION_UNIQUE_NAME@ +#define __heap_pgout __heap_pgout@DB_VERSION_UNIQUE_NAME@ +#define __heap_mswap __heap_mswap@DB_VERSION_UNIQUE_NAME@ +#define __heap_db_create __heap_db_create@DB_VERSION_UNIQUE_NAME@ +#define __heap_db_close __heap_db_close@DB_VERSION_UNIQUE_NAME@ +#define __heap_get_heapsize __heap_get_heapsize@DB_VERSION_UNIQUE_NAME@ +#define __heap_get_heap_regionsize __heap_get_heap_regionsize@DB_VERSION_UNIQUE_NAME@ +#define __heap_set_heapsize __heap_set_heapsize@DB_VERSION_UNIQUE_NAME@ +#define __heap_set_heap_regionsize __heap_set_heap_regionsize@DB_VERSION_UNIQUE_NAME@ +#define __heap_exist __heap_exist@DB_VERSION_UNIQUE_NAME@ +#define __heap_open __heap_open@DB_VERSION_UNIQUE_NAME@ +#define __heap_metachk __heap_metachk@DB_VERSION_UNIQUE_NAME@ +#define __heap_read_meta __heap_read_meta@DB_VERSION_UNIQUE_NAME@ +#define __heap_new_file __heap_new_file@DB_VERSION_UNIQUE_NAME@ +#define __heap_create_region __heap_create_region@DB_VERSION_UNIQUE_NAME@ +#define __heap_addrem_recover __heap_addrem_recover@DB_VERSION_UNIQUE_NAME@ +#define __heap_pg_alloc_recover __heap_pg_alloc_recover@DB_VERSION_UNIQUE_NAME@ +#define __heap_trunc_meta_recover __heap_trunc_meta_recover@DB_VERSION_UNIQUE_NAME@ +#define __heap_trunc_page_recover __heap_trunc_page_recover@DB_VERSION_UNIQUE_NAME@ +#define __heap_addrem_50_recover __heap_addrem_50_recover@DB_VERSION_UNIQUE_NAME@ +#define __heap_truncate __heap_truncate@DB_VERSION_UNIQUE_NAME@ +#define __heap_stat __heap_stat@DB_VERSION_UNIQUE_NAME@ +#define __heap_stat_print __heap_stat_print@DB_VERSION_UNIQUE_NAME@ +#define __heap_print_cursor __heap_print_cursor@DB_VERSION_UNIQUE_NAME@ +#define __heap_stat_callback __heap_stat_callback@DB_VERSION_UNIQUE_NAME@ +#define __heap_traverse __heap_traverse@DB_VERSION_UNIQUE_NAME@ +#define __db_no_heap_am __db_no_heap_am@DB_VERSION_UNIQUE_NAME@ +#define __heap_vrfy_meta __heap_vrfy_meta@DB_VERSION_UNIQUE_NAME@ +#define __heap_vrfy __heap_vrfy@DB_VERSION_UNIQUE_NAME@ +#define __heap_vrfy_structure __heap_vrfy_structure@DB_VERSION_UNIQUE_NAME@ +#define __heap_salvage __heap_salvage@DB_VERSION_UNIQUE_NAME@ +#define __heap_meta2pgset __heap_meta2pgset@DB_VERSION_UNIQUE_NAME@ +#define __db_chksum __db_chksum@DB_VERSION_UNIQUE_NAME@ +#define __db_derive_mac __db_derive_mac@DB_VERSION_UNIQUE_NAME@ +#define __db_check_chksum __db_check_chksum@DB_VERSION_UNIQUE_NAME@ +#define __db_SHA1Transform __db_SHA1Transform@DB_VERSION_UNIQUE_NAME@ +#define __db_SHA1Init __db_SHA1Init@DB_VERSION_UNIQUE_NAME@ +#define __db_SHA1Update __db_SHA1Update@DB_VERSION_UNIQUE_NAME@ +#define __db_SHA1Final __db_SHA1Final@DB_VERSION_UNIQUE_NAME@ +#define __db_lget __db_lget@DB_VERSION_UNIQUE_NAME@ +#define __db_lput __db_lput@DB_VERSION_UNIQUE_NAME@ +#define __db_lprint __db_lprint@DB_VERSION_UNIQUE_NAME@ +#define __lock_vec_pp __lock_vec_pp@DB_VERSION_UNIQUE_NAME@ +#define __lock_vec __lock_vec@DB_VERSION_UNIQUE_NAME@ +#define __lock_get_pp __lock_get_pp@DB_VERSION_UNIQUE_NAME@ +#define __lock_get __lock_get@DB_VERSION_UNIQUE_NAME@ +#define __lock_get_internal __lock_get_internal@DB_VERSION_UNIQUE_NAME@ +#define __lock_put_pp __lock_put_pp@DB_VERSION_UNIQUE_NAME@ +#define __lock_put __lock_put@DB_VERSION_UNIQUE_NAME@ +#define __lock_downgrade __lock_downgrade@DB_VERSION_UNIQUE_NAME@ +#define __lock_locker_same_family __lock_locker_same_family@DB_VERSION_UNIQUE_NAME@ +#define __lock_wakeup __lock_wakeup@DB_VERSION_UNIQUE_NAME@ +#define __lock_promote __lock_promote@DB_VERSION_UNIQUE_NAME@ +#define __lock_change __lock_change@DB_VERSION_UNIQUE_NAME@ +#define __lock_detect_pp __lock_detect_pp@DB_VERSION_UNIQUE_NAME@ +#define __lock_detect __lock_detect@DB_VERSION_UNIQUE_NAME@ +#define __lock_failchk __lock_failchk@DB_VERSION_UNIQUE_NAME@ +#define __lock_id_pp __lock_id_pp@DB_VERSION_UNIQUE_NAME@ +#define __lock_id __lock_id@DB_VERSION_UNIQUE_NAME@ +#define __lock_set_thread_id __lock_set_thread_id@DB_VERSION_UNIQUE_NAME@ +#define __lock_id_free_pp __lock_id_free_pp@DB_VERSION_UNIQUE_NAME@ +#define __lock_id_free __lock_id_free@DB_VERSION_UNIQUE_NAME@ +#define __lock_id_set __lock_id_set@DB_VERSION_UNIQUE_NAME@ +#define __lock_getlocker __lock_getlocker@DB_VERSION_UNIQUE_NAME@ +#define __lock_getlocker_int __lock_getlocker_int@DB_VERSION_UNIQUE_NAME@ +#define __lock_addfamilylocker __lock_addfamilylocker@DB_VERSION_UNIQUE_NAME@ +#define __lock_freelocker __lock_freelocker@DB_VERSION_UNIQUE_NAME@ +#define __lock_familyremove __lock_familyremove@DB_VERSION_UNIQUE_NAME@ +#define __lock_fix_list __lock_fix_list@DB_VERSION_UNIQUE_NAME@ +#define __lock_get_list __lock_get_list@DB_VERSION_UNIQUE_NAME@ +#define __lock_list_print __lock_list_print@DB_VERSION_UNIQUE_NAME@ +#define __lock_env_create __lock_env_create@DB_VERSION_UNIQUE_NAME@ +#define __lock_env_destroy __lock_env_destroy@DB_VERSION_UNIQUE_NAME@ +#define __lock_get_lk_conflicts __lock_get_lk_conflicts@DB_VERSION_UNIQUE_NAME@ +#define __lock_set_lk_conflicts __lock_set_lk_conflicts@DB_VERSION_UNIQUE_NAME@ +#define __lock_get_lk_detect __lock_get_lk_detect@DB_VERSION_UNIQUE_NAME@ +#define __lock_set_lk_detect __lock_set_lk_detect@DB_VERSION_UNIQUE_NAME@ +#define __lock_get_lk_max_locks __lock_get_lk_max_locks@DB_VERSION_UNIQUE_NAME@ +#define __lock_set_lk_max_locks __lock_set_lk_max_locks@DB_VERSION_UNIQUE_NAME@ +#define __lock_get_lk_max_lockers __lock_get_lk_max_lockers@DB_VERSION_UNIQUE_NAME@ +#define __lock_set_lk_max_lockers __lock_set_lk_max_lockers@DB_VERSION_UNIQUE_NAME@ +#define __lock_get_lk_max_objects __lock_get_lk_max_objects@DB_VERSION_UNIQUE_NAME@ +#define __lock_set_lk_max_objects __lock_set_lk_max_objects@DB_VERSION_UNIQUE_NAME@ +#define __lock_get_lk_partitions __lock_get_lk_partitions@DB_VERSION_UNIQUE_NAME@ +#define __lock_set_lk_partitions __lock_set_lk_partitions@DB_VERSION_UNIQUE_NAME@ +#define __lock_get_lk_tablesize __lock_get_lk_tablesize@DB_VERSION_UNIQUE_NAME@ +#define __lock_set_lk_tablesize __lock_set_lk_tablesize@DB_VERSION_UNIQUE_NAME@ +#define __lock_set_lk_priority __lock_set_lk_priority@DB_VERSION_UNIQUE_NAME@ +#define __lock_get_lk_priority __lock_get_lk_priority@DB_VERSION_UNIQUE_NAME@ +#define __lock_get_env_timeout __lock_get_env_timeout@DB_VERSION_UNIQUE_NAME@ +#define __lock_set_env_timeout __lock_set_env_timeout@DB_VERSION_UNIQUE_NAME@ +#define __lock_open __lock_open@DB_VERSION_UNIQUE_NAME@ +#define __lock_env_refresh __lock_env_refresh@DB_VERSION_UNIQUE_NAME@ +#define __lock_region_mutex_count __lock_region_mutex_count@DB_VERSION_UNIQUE_NAME@ +#define __lock_region_mutex_max __lock_region_mutex_max@DB_VERSION_UNIQUE_NAME@ +#define __lock_region_max __lock_region_max@DB_VERSION_UNIQUE_NAME@ +#define __lock_region_size __lock_region_size@DB_VERSION_UNIQUE_NAME@ +#define __lock_stat_pp __lock_stat_pp@DB_VERSION_UNIQUE_NAME@ +#define __lock_stat_print_pp __lock_stat_print_pp@DB_VERSION_UNIQUE_NAME@ +#define __lock_stat_print __lock_stat_print@DB_VERSION_UNIQUE_NAME@ +#define __lock_printlock __lock_printlock@DB_VERSION_UNIQUE_NAME@ +#define __lock_set_timeout __lock_set_timeout@DB_VERSION_UNIQUE_NAME@ +#define __lock_set_timeout_internal __lock_set_timeout_internal@DB_VERSION_UNIQUE_NAME@ +#define __lock_inherit_timeout __lock_inherit_timeout@DB_VERSION_UNIQUE_NAME@ +#define __lock_ohash __lock_ohash@DB_VERSION_UNIQUE_NAME@ +#define __lock_lhash __lock_lhash@DB_VERSION_UNIQUE_NAME@ +#define __lock_nomem __lock_nomem@DB_VERSION_UNIQUE_NAME@ +#define __log_open __log_open@DB_VERSION_UNIQUE_NAME@ +#define __log_find __log_find@DB_VERSION_UNIQUE_NAME@ +#define __log_valid __log_valid@DB_VERSION_UNIQUE_NAME@ +#define __log_env_refresh __log_env_refresh@DB_VERSION_UNIQUE_NAME@ +#define __log_get_cached_ckp_lsn __log_get_cached_ckp_lsn@DB_VERSION_UNIQUE_NAME@ +#define __log_region_mutex_count __log_region_mutex_count@DB_VERSION_UNIQUE_NAME@ +#define __log_region_mutex_max __log_region_mutex_max@DB_VERSION_UNIQUE_NAME@ +#define __log_region_size __log_region_size@DB_VERSION_UNIQUE_NAME@ +#define __log_region_max __log_region_max@DB_VERSION_UNIQUE_NAME@ +#define __log_vtruncate __log_vtruncate@DB_VERSION_UNIQUE_NAME@ +#define __log_is_outdated __log_is_outdated@DB_VERSION_UNIQUE_NAME@ +#define __log_zero __log_zero@DB_VERSION_UNIQUE_NAME@ +#define __log_inmem_lsnoff __log_inmem_lsnoff@DB_VERSION_UNIQUE_NAME@ +#define __log_inmem_newfile __log_inmem_newfile@DB_VERSION_UNIQUE_NAME@ +#define __log_inmem_chkspace __log_inmem_chkspace@DB_VERSION_UNIQUE_NAME@ +#define __log_inmem_copyout __log_inmem_copyout@DB_VERSION_UNIQUE_NAME@ +#define __log_inmem_copyin __log_inmem_copyin@DB_VERSION_UNIQUE_NAME@ +#define __log_set_version __log_set_version@DB_VERSION_UNIQUE_NAME@ +#define __log_get_oldversion __log_get_oldversion@DB_VERSION_UNIQUE_NAME@ +#define __log_archive_pp __log_archive_pp@DB_VERSION_UNIQUE_NAME@ +#define __log_archive __log_archive@DB_VERSION_UNIQUE_NAME@ +#define __log_get_stable_lsn __log_get_stable_lsn@DB_VERSION_UNIQUE_NAME@ +#define __log_autoremove __log_autoremove@DB_VERSION_UNIQUE_NAME@ +#define __log_check_page_lsn __log_check_page_lsn@DB_VERSION_UNIQUE_NAME@ +#define __log_printf_capi __log_printf_capi@DB_VERSION_UNIQUE_NAME@ +#define __log_printf_pp __log_printf_pp@DB_VERSION_UNIQUE_NAME@ +#define __log_printf __log_printf@DB_VERSION_UNIQUE_NAME@ +#define __log_cursor_pp __log_cursor_pp@DB_VERSION_UNIQUE_NAME@ +#define __log_cursor __log_cursor@DB_VERSION_UNIQUE_NAME@ +#define __logc_close __logc_close@DB_VERSION_UNIQUE_NAME@ +#define __logc_version __logc_version@DB_VERSION_UNIQUE_NAME@ +#define __logc_get __logc_get@DB_VERSION_UNIQUE_NAME@ +#define __log_hdrswap __log_hdrswap@DB_VERSION_UNIQUE_NAME@ +#define __log_persistswap __log_persistswap@DB_VERSION_UNIQUE_NAME@ +#define __log_read_record_pp __log_read_record_pp@DB_VERSION_UNIQUE_NAME@ +#define __log_read_record __log_read_record@DB_VERSION_UNIQUE_NAME@ +#define __log_env_create __log_env_create@DB_VERSION_UNIQUE_NAME@ +#define __log_env_destroy __log_env_destroy@DB_VERSION_UNIQUE_NAME@ +#define __log_get_lg_bsize __log_get_lg_bsize@DB_VERSION_UNIQUE_NAME@ +#define __log_set_lg_bsize __log_set_lg_bsize@DB_VERSION_UNIQUE_NAME@ +#define __log_get_lg_filemode __log_get_lg_filemode@DB_VERSION_UNIQUE_NAME@ +#define __log_set_lg_filemode __log_set_lg_filemode@DB_VERSION_UNIQUE_NAME@ +#define __log_get_lg_max __log_get_lg_max@DB_VERSION_UNIQUE_NAME@ +#define __log_set_lg_max __log_set_lg_max@DB_VERSION_UNIQUE_NAME@ +#define __log_get_lg_regionmax __log_get_lg_regionmax@DB_VERSION_UNIQUE_NAME@ +#define __log_set_lg_regionmax __log_set_lg_regionmax@DB_VERSION_UNIQUE_NAME@ +#define __log_get_lg_dir __log_get_lg_dir@DB_VERSION_UNIQUE_NAME@ +#define __log_set_lg_dir __log_set_lg_dir@DB_VERSION_UNIQUE_NAME@ +#define __log_get_flags __log_get_flags@DB_VERSION_UNIQUE_NAME@ +#define __log_set_flags __log_set_flags@DB_VERSION_UNIQUE_NAME@ +#define __log_get_config __log_get_config@DB_VERSION_UNIQUE_NAME@ +#define __log_set_config __log_set_config@DB_VERSION_UNIQUE_NAME@ +#define __log_set_config_int __log_set_config_int@DB_VERSION_UNIQUE_NAME@ +#define __log_check_sizes __log_check_sizes@DB_VERSION_UNIQUE_NAME@ +#define __log_print_record __log_print_record@DB_VERSION_UNIQUE_NAME@ +#define __log_put_pp __log_put_pp@DB_VERSION_UNIQUE_NAME@ +#define __log_put __log_put@DB_VERSION_UNIQUE_NAME@ +#define __log_current_lsn_int __log_current_lsn_int@DB_VERSION_UNIQUE_NAME@ +#define __log_current_lsn __log_current_lsn@DB_VERSION_UNIQUE_NAME@ +#define __log_newfile __log_newfile@DB_VERSION_UNIQUE_NAME@ +#define __log_flush_pp __log_flush_pp@DB_VERSION_UNIQUE_NAME@ +#define __log_flush __log_flush@DB_VERSION_UNIQUE_NAME@ +#define __log_flush_int __log_flush_int@DB_VERSION_UNIQUE_NAME@ +#define __log_file_pp __log_file_pp@DB_VERSION_UNIQUE_NAME@ +#define __log_name __log_name@DB_VERSION_UNIQUE_NAME@ +#define __log_rep_put __log_rep_put@DB_VERSION_UNIQUE_NAME@ +#define __log_put_record_pp __log_put_record_pp@DB_VERSION_UNIQUE_NAME@ +#define __log_put_record __log_put_record@DB_VERSION_UNIQUE_NAME@ +#define __log_stat_pp __log_stat_pp@DB_VERSION_UNIQUE_NAME@ +#define __log_stat_print_pp __log_stat_print_pp@DB_VERSION_UNIQUE_NAME@ +#define __log_stat_print __log_stat_print@DB_VERSION_UNIQUE_NAME@ +#define __log_verify_pp __log_verify_pp@DB_VERSION_UNIQUE_NAME@ +#define __log_verify __log_verify@DB_VERSION_UNIQUE_NAME@ +#define __log_verify_wrap __log_verify_wrap@DB_VERSION_UNIQUE_NAME@ +#define __crdel_init_verify __crdel_init_verify@DB_VERSION_UNIQUE_NAME@ +#define __db_init_verify __db_init_verify@DB_VERSION_UNIQUE_NAME@ +#define __dbreg_init_verify __dbreg_init_verify@DB_VERSION_UNIQUE_NAME@ +#define __bam_init_verify __bam_init_verify@DB_VERSION_UNIQUE_NAME@ +#define __fop_init_verify __fop_init_verify@DB_VERSION_UNIQUE_NAME@ +#define __ham_init_verify __ham_init_verify@DB_VERSION_UNIQUE_NAME@ +#define __heap_init_verify __heap_init_verify@DB_VERSION_UNIQUE_NAME@ +#define __qam_init_verify __qam_init_verify@DB_VERSION_UNIQUE_NAME@ +#define __txn_init_verify __txn_init_verify@DB_VERSION_UNIQUE_NAME@ +#define __db_log_verify_global_report __db_log_verify_global_report@DB_VERSION_UNIQUE_NAME@ +#define __crdel_metasub_verify __crdel_metasub_verify@DB_VERSION_UNIQUE_NAME@ +#define __crdel_inmem_create_verify __crdel_inmem_create_verify@DB_VERSION_UNIQUE_NAME@ +#define __crdel_inmem_rename_verify __crdel_inmem_rename_verify@DB_VERSION_UNIQUE_NAME@ +#define __crdel_inmem_remove_verify __crdel_inmem_remove_verify@DB_VERSION_UNIQUE_NAME@ +#define __db_addrem_verify __db_addrem_verify@DB_VERSION_UNIQUE_NAME@ +#define __db_big_verify __db_big_verify@DB_VERSION_UNIQUE_NAME@ +#define __db_ovref_verify __db_ovref_verify@DB_VERSION_UNIQUE_NAME@ +#define __db_relink_42_verify __db_relink_42_verify@DB_VERSION_UNIQUE_NAME@ +#define __db_debug_verify __db_debug_verify@DB_VERSION_UNIQUE_NAME@ +#define __db_noop_verify __db_noop_verify@DB_VERSION_UNIQUE_NAME@ +#define __db_pg_alloc_42_verify __db_pg_alloc_42_verify@DB_VERSION_UNIQUE_NAME@ +#define __db_pg_alloc_verify __db_pg_alloc_verify@DB_VERSION_UNIQUE_NAME@ +#define __db_pg_free_42_verify __db_pg_free_42_verify@DB_VERSION_UNIQUE_NAME@ +#define __db_pg_free_verify __db_pg_free_verify@DB_VERSION_UNIQUE_NAME@ +#define __db_cksum_verify __db_cksum_verify@DB_VERSION_UNIQUE_NAME@ +#define __db_pg_freedata_42_verify __db_pg_freedata_42_verify@DB_VERSION_UNIQUE_NAME@ +#define __db_pg_freedata_verify __db_pg_freedata_verify@DB_VERSION_UNIQUE_NAME@ +#define __db_pg_init_verify __db_pg_init_verify@DB_VERSION_UNIQUE_NAME@ +#define __db_pg_sort_44_verify __db_pg_sort_44_verify@DB_VERSION_UNIQUE_NAME@ +#define __db_pg_trunc_verify __db_pg_trunc_verify@DB_VERSION_UNIQUE_NAME@ +#define __db_realloc_verify __db_realloc_verify@DB_VERSION_UNIQUE_NAME@ +#define __db_relink_verify __db_relink_verify@DB_VERSION_UNIQUE_NAME@ +#define __db_merge_verify __db_merge_verify@DB_VERSION_UNIQUE_NAME@ +#define __db_pgno_verify __db_pgno_verify@DB_VERSION_UNIQUE_NAME@ +#define __dbreg_register_verify __dbreg_register_verify@DB_VERSION_UNIQUE_NAME@ +#define __bam_split_verify __bam_split_verify@DB_VERSION_UNIQUE_NAME@ +#define __bam_split_42_verify __bam_split_42_verify@DB_VERSION_UNIQUE_NAME@ +#define __bam_rsplit_verify __bam_rsplit_verify@DB_VERSION_UNIQUE_NAME@ +#define __bam_adj_verify __bam_adj_verify@DB_VERSION_UNIQUE_NAME@ +#define __bam_irep_verify __bam_irep_verify@DB_VERSION_UNIQUE_NAME@ +#define __bam_cadjust_verify __bam_cadjust_verify@DB_VERSION_UNIQUE_NAME@ +#define __bam_cdel_verify __bam_cdel_verify@DB_VERSION_UNIQUE_NAME@ +#define __bam_repl_verify __bam_repl_verify@DB_VERSION_UNIQUE_NAME@ +#define __bam_root_verify __bam_root_verify@DB_VERSION_UNIQUE_NAME@ +#define __bam_curadj_verify __bam_curadj_verify@DB_VERSION_UNIQUE_NAME@ +#define __bam_rcuradj_verify __bam_rcuradj_verify@DB_VERSION_UNIQUE_NAME@ +#define __bam_relink_43_verify __bam_relink_43_verify@DB_VERSION_UNIQUE_NAME@ +#define __bam_merge_44_verify __bam_merge_44_verify@DB_VERSION_UNIQUE_NAME@ +#define __fop_create_42_verify __fop_create_42_verify@DB_VERSION_UNIQUE_NAME@ +#define __fop_create_verify __fop_create_verify@DB_VERSION_UNIQUE_NAME@ +#define __fop_remove_verify __fop_remove_verify@DB_VERSION_UNIQUE_NAME@ +#define __fop_write_42_verify __fop_write_42_verify@DB_VERSION_UNIQUE_NAME@ +#define __fop_write_verify __fop_write_verify@DB_VERSION_UNIQUE_NAME@ +#define __fop_rename_42_verify __fop_rename_42_verify@DB_VERSION_UNIQUE_NAME@ +#define __fop_rename_verify __fop_rename_verify@DB_VERSION_UNIQUE_NAME@ +#define __fop_file_remove_verify __fop_file_remove_verify@DB_VERSION_UNIQUE_NAME@ +#define __ham_insdel_verify __ham_insdel_verify@DB_VERSION_UNIQUE_NAME@ +#define __ham_newpage_verify __ham_newpage_verify@DB_VERSION_UNIQUE_NAME@ +#define __ham_splitdata_verify __ham_splitdata_verify@DB_VERSION_UNIQUE_NAME@ +#define __ham_replace_verify __ham_replace_verify@DB_VERSION_UNIQUE_NAME@ +#define __ham_copypage_verify __ham_copypage_verify@DB_VERSION_UNIQUE_NAME@ +#define __ham_metagroup_42_verify __ham_metagroup_42_verify@DB_VERSION_UNIQUE_NAME@ +#define __ham_metagroup_verify __ham_metagroup_verify@DB_VERSION_UNIQUE_NAME@ +#define __ham_groupalloc_42_verify __ham_groupalloc_42_verify@DB_VERSION_UNIQUE_NAME@ +#define __ham_groupalloc_verify __ham_groupalloc_verify@DB_VERSION_UNIQUE_NAME@ +#define __ham_changeslot_verify __ham_changeslot_verify@DB_VERSION_UNIQUE_NAME@ +#define __ham_contract_verify __ham_contract_verify@DB_VERSION_UNIQUE_NAME@ +#define __ham_curadj_verify __ham_curadj_verify@DB_VERSION_UNIQUE_NAME@ +#define __ham_chgpg_verify __ham_chgpg_verify@DB_VERSION_UNIQUE_NAME@ +#define __heap_addrem_verify __heap_addrem_verify@DB_VERSION_UNIQUE_NAME@ +#define __heap_pg_alloc_verify __heap_pg_alloc_verify@DB_VERSION_UNIQUE_NAME@ +#define __heap_trunc_meta_verify __heap_trunc_meta_verify@DB_VERSION_UNIQUE_NAME@ +#define __heap_trunc_page_verify __heap_trunc_page_verify@DB_VERSION_UNIQUE_NAME@ +#define __qam_incfirst_verify __qam_incfirst_verify@DB_VERSION_UNIQUE_NAME@ +#define __qam_mvptr_verify __qam_mvptr_verify@DB_VERSION_UNIQUE_NAME@ +#define __qam_del_verify __qam_del_verify@DB_VERSION_UNIQUE_NAME@ +#define __qam_add_verify __qam_add_verify@DB_VERSION_UNIQUE_NAME@ +#define __qam_delext_verify __qam_delext_verify@DB_VERSION_UNIQUE_NAME@ +#define __txn_regop_42_verify __txn_regop_42_verify@DB_VERSION_UNIQUE_NAME@ +#define __txn_regop_verify __txn_regop_verify@DB_VERSION_UNIQUE_NAME@ +#define __txn_ckp_42_verify __txn_ckp_42_verify@DB_VERSION_UNIQUE_NAME@ +#define __txn_ckp_verify __txn_ckp_verify@DB_VERSION_UNIQUE_NAME@ +#define __txn_child_verify __txn_child_verify@DB_VERSION_UNIQUE_NAME@ +#define __txn_xa_regop_42_verify __txn_xa_regop_42_verify@DB_VERSION_UNIQUE_NAME@ +#define __txn_prepare_verify __txn_prepare_verify@DB_VERSION_UNIQUE_NAME@ +#define __txn_recycle_verify __txn_recycle_verify@DB_VERSION_UNIQUE_NAME@ +#define __create_log_vrfy_info __create_log_vrfy_info@DB_VERSION_UNIQUE_NAME@ +#define __destroy_log_vrfy_info __destroy_log_vrfy_info@DB_VERSION_UNIQUE_NAME@ +#define __put_txn_vrfy_info __put_txn_vrfy_info@DB_VERSION_UNIQUE_NAME@ +#define __get_txn_vrfy_info __get_txn_vrfy_info@DB_VERSION_UNIQUE_NAME@ +#define __add_recycle_lsn_range __add_recycle_lsn_range@DB_VERSION_UNIQUE_NAME@ +#define __iterate_txninfo __iterate_txninfo@DB_VERSION_UNIQUE_NAME@ +#define __rem_last_recycle_lsn __rem_last_recycle_lsn@DB_VERSION_UNIQUE_NAME@ +#define __add_file_updated __add_file_updated@DB_VERSION_UNIQUE_NAME@ +#define __del_file_updated __del_file_updated@DB_VERSION_UNIQUE_NAME@ +#define __clear_fileups __clear_fileups@DB_VERSION_UNIQUE_NAME@ +#define __free_txninfo_stack __free_txninfo_stack@DB_VERSION_UNIQUE_NAME@ +#define __free_txninfo __free_txninfo@DB_VERSION_UNIQUE_NAME@ +#define __put_filereg_info __put_filereg_info@DB_VERSION_UNIQUE_NAME@ +#define __del_filelife __del_filelife@DB_VERSION_UNIQUE_NAME@ +#define __put_filelife __put_filelife@DB_VERSION_UNIQUE_NAME@ +#define __get_filelife __get_filelife@DB_VERSION_UNIQUE_NAME@ +#define __get_filereg_by_dbregid __get_filereg_by_dbregid@DB_VERSION_UNIQUE_NAME@ +#define __add_dbregid __add_dbregid@DB_VERSION_UNIQUE_NAME@ +#define __get_filereg_info __get_filereg_info@DB_VERSION_UNIQUE_NAME@ +#define __free_filereg_info __free_filereg_info@DB_VERSION_UNIQUE_NAME@ +#define __get_ckp_info __get_ckp_info@DB_VERSION_UNIQUE_NAME@ +#define __get_last_ckp_info __get_last_ckp_info@DB_VERSION_UNIQUE_NAME@ +#define __put_ckp_info __put_ckp_info@DB_VERSION_UNIQUE_NAME@ +#define __get_timestamp_info __get_timestamp_info@DB_VERSION_UNIQUE_NAME@ +#define __get_latest_timestamp_info __get_latest_timestamp_info@DB_VERSION_UNIQUE_NAME@ +#define __put_timestamp_info __put_timestamp_info@DB_VERSION_UNIQUE_NAME@ +#define __find_lsnrg_by_timerg __find_lsnrg_by_timerg@DB_VERSION_UNIQUE_NAME@ +#define __add_txnrange __add_txnrange@DB_VERSION_UNIQUE_NAME@ +#define __get_aborttxn __get_aborttxn@DB_VERSION_UNIQUE_NAME@ +#define __txn_started __txn_started@DB_VERSION_UNIQUE_NAME@ +#define __set_logvrfy_dbfuid __set_logvrfy_dbfuid@DB_VERSION_UNIQUE_NAME@ +#define __add_page_to_txn __add_page_to_txn@DB_VERSION_UNIQUE_NAME@ +#define __del_txn_pages __del_txn_pages@DB_VERSION_UNIQUE_NAME@ +#define __is_ancestor_txn __is_ancestor_txn@DB_VERSION_UNIQUE_NAME@ +#define __return_txn_pages __return_txn_pages@DB_VERSION_UNIQUE_NAME@ +#define __memp_alloc __memp_alloc@DB_VERSION_UNIQUE_NAME@ +#define __memp_free __memp_free@DB_VERSION_UNIQUE_NAME@ +#define __memp_backup_open __memp_backup_open@DB_VERSION_UNIQUE_NAME@ +#define __memp_backup_mpf __memp_backup_mpf@DB_VERSION_UNIQUE_NAME@ +#define __memp_backup_close __memp_backup_close@DB_VERSION_UNIQUE_NAME@ +#define __memp_failchk __memp_failchk@DB_VERSION_UNIQUE_NAME@ +#define __memp_bhwrite __memp_bhwrite@DB_VERSION_UNIQUE_NAME@ +#define __memp_pgread __memp_pgread@DB_VERSION_UNIQUE_NAME@ +#define __memp_pg __memp_pg@DB_VERSION_UNIQUE_NAME@ +#define __memp_bhfree __memp_bhfree@DB_VERSION_UNIQUE_NAME@ +#define __memp_fget_pp __memp_fget_pp@DB_VERSION_UNIQUE_NAME@ +#define __memp_fget __memp_fget@DB_VERSION_UNIQUE_NAME@ +#define __memp_fcreate_pp __memp_fcreate_pp@DB_VERSION_UNIQUE_NAME@ +#define __memp_fcreate __memp_fcreate@DB_VERSION_UNIQUE_NAME@ +#define __memp_set_clear_len __memp_set_clear_len@DB_VERSION_UNIQUE_NAME@ +#define __memp_get_fileid __memp_get_fileid@DB_VERSION_UNIQUE_NAME@ +#define __memp_set_fileid __memp_set_fileid@DB_VERSION_UNIQUE_NAME@ +#define __memp_get_flags __memp_get_flags@DB_VERSION_UNIQUE_NAME@ +#define __memp_set_flags __memp_set_flags@DB_VERSION_UNIQUE_NAME@ +#define __memp_get_ftype __memp_get_ftype@DB_VERSION_UNIQUE_NAME@ +#define __memp_set_ftype __memp_set_ftype@DB_VERSION_UNIQUE_NAME@ +#define __memp_set_lsn_offset __memp_set_lsn_offset@DB_VERSION_UNIQUE_NAME@ +#define __memp_get_pgcookie __memp_get_pgcookie@DB_VERSION_UNIQUE_NAME@ +#define __memp_set_pgcookie __memp_set_pgcookie@DB_VERSION_UNIQUE_NAME@ +#define __memp_get_priority __memp_get_priority@DB_VERSION_UNIQUE_NAME@ +#define __memp_get_last_pgno __memp_get_last_pgno@DB_VERSION_UNIQUE_NAME@ +#define __memp_fn __memp_fn@DB_VERSION_UNIQUE_NAME@ +#define __memp_fns __memp_fns@DB_VERSION_UNIQUE_NAME@ +#define __memp_fopen_pp __memp_fopen_pp@DB_VERSION_UNIQUE_NAME@ +#define __memp_fopen __memp_fopen@DB_VERSION_UNIQUE_NAME@ +#define __memp_fclose_pp __memp_fclose_pp@DB_VERSION_UNIQUE_NAME@ +#define __memp_fclose __memp_fclose@DB_VERSION_UNIQUE_NAME@ +#define __memp_mf_discard __memp_mf_discard@DB_VERSION_UNIQUE_NAME@ +#define __memp_inmemlist __memp_inmemlist@DB_VERSION_UNIQUE_NAME@ +#define __memp_fput_pp __memp_fput_pp@DB_VERSION_UNIQUE_NAME@ +#define __memp_fput __memp_fput@DB_VERSION_UNIQUE_NAME@ +#define __memp_unpin_buffers __memp_unpin_buffers@DB_VERSION_UNIQUE_NAME@ +#define __memp_dirty __memp_dirty@DB_VERSION_UNIQUE_NAME@ +#define __memp_shared __memp_shared@DB_VERSION_UNIQUE_NAME@ +#define __memp_env_create __memp_env_create@DB_VERSION_UNIQUE_NAME@ +#define __memp_env_destroy __memp_env_destroy@DB_VERSION_UNIQUE_NAME@ +#define __memp_get_cachesize __memp_get_cachesize@DB_VERSION_UNIQUE_NAME@ +#define __memp_set_cachesize __memp_set_cachesize@DB_VERSION_UNIQUE_NAME@ +#define __memp_set_config __memp_set_config@DB_VERSION_UNIQUE_NAME@ +#define __memp_get_config __memp_get_config@DB_VERSION_UNIQUE_NAME@ +#define __memp_get_mp_max_openfd __memp_get_mp_max_openfd@DB_VERSION_UNIQUE_NAME@ +#define __memp_set_mp_max_openfd __memp_set_mp_max_openfd@DB_VERSION_UNIQUE_NAME@ +#define __memp_get_mp_max_write __memp_get_mp_max_write@DB_VERSION_UNIQUE_NAME@ +#define __memp_set_mp_max_write __memp_set_mp_max_write@DB_VERSION_UNIQUE_NAME@ +#define __memp_get_mp_mmapsize __memp_get_mp_mmapsize@DB_VERSION_UNIQUE_NAME@ +#define __memp_set_mp_mmapsize __memp_set_mp_mmapsize@DB_VERSION_UNIQUE_NAME@ +#define __memp_get_mp_pagesize __memp_get_mp_pagesize@DB_VERSION_UNIQUE_NAME@ +#define __memp_set_mp_pagesize __memp_set_mp_pagesize@DB_VERSION_UNIQUE_NAME@ +#define __memp_get_mp_tablesize __memp_get_mp_tablesize@DB_VERSION_UNIQUE_NAME@ +#define __memp_set_mp_tablesize __memp_set_mp_tablesize@DB_VERSION_UNIQUE_NAME@ +#define __memp_get_mp_mtxcount __memp_get_mp_mtxcount@DB_VERSION_UNIQUE_NAME@ +#define __memp_set_mp_mtxcount __memp_set_mp_mtxcount@DB_VERSION_UNIQUE_NAME@ +#define __memp_nameop __memp_nameop@DB_VERSION_UNIQUE_NAME@ +#define __memp_ftruncate __memp_ftruncate@DB_VERSION_UNIQUE_NAME@ +#define __memp_alloc_freelist __memp_alloc_freelist@DB_VERSION_UNIQUE_NAME@ +#define __memp_free_freelist __memp_free_freelist@DB_VERSION_UNIQUE_NAME@ +#define __memp_get_freelist __memp_get_freelist@DB_VERSION_UNIQUE_NAME@ +#define __memp_extend_freelist __memp_extend_freelist@DB_VERSION_UNIQUE_NAME@ +#define __memp_set_last_pgno __memp_set_last_pgno@DB_VERSION_UNIQUE_NAME@ +#define __memp_bh_settxn __memp_bh_settxn@DB_VERSION_UNIQUE_NAME@ +#define __memp_skip_curadj __memp_skip_curadj@DB_VERSION_UNIQUE_NAME@ +#define __memp_bh_freeze __memp_bh_freeze@DB_VERSION_UNIQUE_NAME@ +#define __memp_bh_thaw __memp_bh_thaw@DB_VERSION_UNIQUE_NAME@ +#define __memp_open __memp_open@DB_VERSION_UNIQUE_NAME@ +#define __memp_init __memp_init@DB_VERSION_UNIQUE_NAME@ +#define __memp_max_regions __memp_max_regions@DB_VERSION_UNIQUE_NAME@ +#define __memp_region_mutex_count __memp_region_mutex_count@DB_VERSION_UNIQUE_NAME@ +#define __memp_env_refresh __memp_env_refresh@DB_VERSION_UNIQUE_NAME@ +#define __memp_register_pp __memp_register_pp@DB_VERSION_UNIQUE_NAME@ +#define __memp_register __memp_register@DB_VERSION_UNIQUE_NAME@ +#define __memp_get_bucket __memp_get_bucket@DB_VERSION_UNIQUE_NAME@ +#define __memp_resize __memp_resize@DB_VERSION_UNIQUE_NAME@ +#define __memp_get_cache_max __memp_get_cache_max@DB_VERSION_UNIQUE_NAME@ +#define __memp_set_cache_max __memp_set_cache_max@DB_VERSION_UNIQUE_NAME@ +#define __memp_stat_pp __memp_stat_pp@DB_VERSION_UNIQUE_NAME@ +#define __memp_stat_print_pp __memp_stat_print_pp@DB_VERSION_UNIQUE_NAME@ +#define __memp_stat_print __memp_stat_print@DB_VERSION_UNIQUE_NAME@ +#define __memp_stat_hash __memp_stat_hash@DB_VERSION_UNIQUE_NAME@ +#define __memp_walk_files __memp_walk_files@DB_VERSION_UNIQUE_NAME@ +#define __memp_discard_all_mpfs __memp_discard_all_mpfs@DB_VERSION_UNIQUE_NAME@ +#define __memp_sync_pp __memp_sync_pp@DB_VERSION_UNIQUE_NAME@ +#define __memp_sync __memp_sync@DB_VERSION_UNIQUE_NAME@ +#define __memp_fsync_pp __memp_fsync_pp@DB_VERSION_UNIQUE_NAME@ +#define __memp_fsync __memp_fsync@DB_VERSION_UNIQUE_NAME@ +#define __mp_xxx_fh __mp_xxx_fh@DB_VERSION_UNIQUE_NAME@ +#define __memp_sync_int __memp_sync_int@DB_VERSION_UNIQUE_NAME@ +#define __memp_mf_sync __memp_mf_sync@DB_VERSION_UNIQUE_NAME@ +#define __memp_trickle_pp __memp_trickle_pp@DB_VERSION_UNIQUE_NAME@ +#define __mutex_alloc __mutex_alloc@DB_VERSION_UNIQUE_NAME@ +#define __mutex_alloc_int __mutex_alloc_int@DB_VERSION_UNIQUE_NAME@ +#define __mutex_free __mutex_free@DB_VERSION_UNIQUE_NAME@ +#define __mutex_free_int __mutex_free_int@DB_VERSION_UNIQUE_NAME@ +#define __mutex_refresh __mutex_refresh@DB_VERSION_UNIQUE_NAME@ +#define __mut_failchk __mut_failchk@DB_VERSION_UNIQUE_NAME@ +#define __db_fcntl_mutex_init __db_fcntl_mutex_init@DB_VERSION_UNIQUE_NAME@ +#define __db_fcntl_mutex_lock __db_fcntl_mutex_lock@DB_VERSION_UNIQUE_NAME@ +#define __db_fcntl_mutex_trylock __db_fcntl_mutex_trylock@DB_VERSION_UNIQUE_NAME@ +#define __db_fcntl_mutex_unlock __db_fcntl_mutex_unlock@DB_VERSION_UNIQUE_NAME@ +#define __db_fcntl_mutex_destroy __db_fcntl_mutex_destroy@DB_VERSION_UNIQUE_NAME@ +#define __mutex_alloc_pp __mutex_alloc_pp@DB_VERSION_UNIQUE_NAME@ +#define __mutex_free_pp __mutex_free_pp@DB_VERSION_UNIQUE_NAME@ +#define __mutex_lock_pp __mutex_lock_pp@DB_VERSION_UNIQUE_NAME@ +#define __mutex_unlock_pp __mutex_unlock_pp@DB_VERSION_UNIQUE_NAME@ +#define __mutex_get_align __mutex_get_align@DB_VERSION_UNIQUE_NAME@ +#define __mutex_set_align __mutex_set_align@DB_VERSION_UNIQUE_NAME@ +#define __mutex_get_increment __mutex_get_increment@DB_VERSION_UNIQUE_NAME@ +#define __mutex_set_increment __mutex_set_increment@DB_VERSION_UNIQUE_NAME@ +#define __mutex_get_init __mutex_get_init@DB_VERSION_UNIQUE_NAME@ +#define __mutex_set_init __mutex_set_init@DB_VERSION_UNIQUE_NAME@ +#define __mutex_get_max __mutex_get_max@DB_VERSION_UNIQUE_NAME@ +#define __mutex_set_max __mutex_set_max@DB_VERSION_UNIQUE_NAME@ +#define __mutex_get_tas_spins __mutex_get_tas_spins@DB_VERSION_UNIQUE_NAME@ +#define __mutex_set_tas_spins __mutex_set_tas_spins@DB_VERSION_UNIQUE_NAME@ +#if !defined(HAVE_ATOMIC_SUPPORT) && defined(HAVE_MUTEX_SUPPORT) +#define __atomic_inc __atomic_inc@DB_VERSION_UNIQUE_NAME@ +#endif +#if !defined(HAVE_ATOMIC_SUPPORT) && defined(HAVE_MUTEX_SUPPORT) +#define __atomic_dec __atomic_dec@DB_VERSION_UNIQUE_NAME@ +#endif +#if !defined(HAVE_ATOMIC_SUPPORT) && defined(HAVE_MUTEX_SUPPORT) +#define atomic_compare_exchange atomic_compare_exchange@DB_VERSION_UNIQUE_NAME@ +#endif +#define __db_pthread_mutex_init __db_pthread_mutex_init@DB_VERSION_UNIQUE_NAME@ +#ifndef HAVE_MUTEX_HYBRID +#define __db_pthread_mutex_lock __db_pthread_mutex_lock@DB_VERSION_UNIQUE_NAME@ +#endif +#if defined(HAVE_SHARED_LATCHES) +#define __db_pthread_mutex_readlock __db_pthread_mutex_readlock@DB_VERSION_UNIQUE_NAME@ +#endif +#ifdef HAVE_MUTEX_HYBRID +#define __db_hybrid_mutex_suspend __db_hybrid_mutex_suspend@DB_VERSION_UNIQUE_NAME@ +#endif +#define __db_pthread_mutex_unlock __db_pthread_mutex_unlock@DB_VERSION_UNIQUE_NAME@ +#define __db_pthread_mutex_destroy __db_pthread_mutex_destroy@DB_VERSION_UNIQUE_NAME@ +#define __mutex_open __mutex_open@DB_VERSION_UNIQUE_NAME@ +#define __mutex_env_refresh __mutex_env_refresh@DB_VERSION_UNIQUE_NAME@ +#define __mutex_resource_return __mutex_resource_return@DB_VERSION_UNIQUE_NAME@ +#define __mutex_stat_pp __mutex_stat_pp@DB_VERSION_UNIQUE_NAME@ +#define __mutex_stat_print_pp __mutex_stat_print_pp@DB_VERSION_UNIQUE_NAME@ +#define __mutex_stat_print __mutex_stat_print@DB_VERSION_UNIQUE_NAME@ +#define __mutex_print_debug_single __mutex_print_debug_single@DB_VERSION_UNIQUE_NAME@ +#define __mutex_print_debug_stats __mutex_print_debug_stats@DB_VERSION_UNIQUE_NAME@ +#define __mutex_set_wait_info __mutex_set_wait_info@DB_VERSION_UNIQUE_NAME@ +#define __mutex_clear __mutex_clear@DB_VERSION_UNIQUE_NAME@ +#define __db_tas_mutex_init __db_tas_mutex_init@DB_VERSION_UNIQUE_NAME@ +#define __db_tas_mutex_lock __db_tas_mutex_lock@DB_VERSION_UNIQUE_NAME@ +#define __db_tas_mutex_trylock __db_tas_mutex_trylock@DB_VERSION_UNIQUE_NAME@ +#if defined(HAVE_SHARED_LATCHES) +#define __db_tas_mutex_readlock __db_tas_mutex_readlock@DB_VERSION_UNIQUE_NAME@ +#endif +#if defined(HAVE_SHARED_LATCHES) +#define __db_tas_mutex_tryreadlock __db_tas_mutex_tryreadlock@DB_VERSION_UNIQUE_NAME@ +#endif +#define __db_tas_mutex_unlock __db_tas_mutex_unlock@DB_VERSION_UNIQUE_NAME@ +#define __db_tas_mutex_destroy __db_tas_mutex_destroy@DB_VERSION_UNIQUE_NAME@ +#define __db_win32_mutex_init __db_win32_mutex_init@DB_VERSION_UNIQUE_NAME@ +#define __db_win32_mutex_lock __db_win32_mutex_lock@DB_VERSION_UNIQUE_NAME@ +#define __db_win32_mutex_trylock __db_win32_mutex_trylock@DB_VERSION_UNIQUE_NAME@ +#if defined(HAVE_SHARED_LATCHES) +#define __db_win32_mutex_readlock __db_win32_mutex_readlock@DB_VERSION_UNIQUE_NAME@ +#endif +#if defined(HAVE_SHARED_LATCHES) +#define __db_win32_mutex_tryreadlock __db_win32_mutex_tryreadlock@DB_VERSION_UNIQUE_NAME@ +#endif +#define __db_win32_mutex_unlock __db_win32_mutex_unlock@DB_VERSION_UNIQUE_NAME@ +#define __db_win32_mutex_destroy __db_win32_mutex_destroy@DB_VERSION_UNIQUE_NAME@ +#define __os_abort __os_abort@DB_VERSION_UNIQUE_NAME@ +#define __os_abspath __os_abspath@DB_VERSION_UNIQUE_NAME@ +#if defined(HAVE_REPLICATION_THREADS) +#define __os_getaddrinfo __os_getaddrinfo@DB_VERSION_UNIQUE_NAME@ +#endif +#if defined(HAVE_REPLICATION_THREADS) +#define __os_freeaddrinfo __os_freeaddrinfo@DB_VERSION_UNIQUE_NAME@ +#endif +#define __os_umalloc __os_umalloc@DB_VERSION_UNIQUE_NAME@ +#define __os_urealloc __os_urealloc@DB_VERSION_UNIQUE_NAME@ +#define __os_ufree __os_ufree@DB_VERSION_UNIQUE_NAME@ +#define __os_strdup __os_strdup@DB_VERSION_UNIQUE_NAME@ +#define __os_calloc __os_calloc@DB_VERSION_UNIQUE_NAME@ +#define __os_malloc __os_malloc@DB_VERSION_UNIQUE_NAME@ +#define __os_realloc __os_realloc@DB_VERSION_UNIQUE_NAME@ +#define __os_free __os_free@DB_VERSION_UNIQUE_NAME@ +#define __ua_memcpy __ua_memcpy@DB_VERSION_UNIQUE_NAME@ +#define __os_gettime __os_gettime@DB_VERSION_UNIQUE_NAME@ +#define __os_fs_notzero __os_fs_notzero@DB_VERSION_UNIQUE_NAME@ +#define __os_support_direct_io __os_support_direct_io@DB_VERSION_UNIQUE_NAME@ +#define __os_support_db_register __os_support_db_register@DB_VERSION_UNIQUE_NAME@ +#define __os_support_replication __os_support_replication@DB_VERSION_UNIQUE_NAME@ +#define __os_cpu_count __os_cpu_count@DB_VERSION_UNIQUE_NAME@ +#define __os_ctime __os_ctime@DB_VERSION_UNIQUE_NAME@ +#define __os_dirlist __os_dirlist@DB_VERSION_UNIQUE_NAME@ +#define __os_dirfree __os_dirfree@DB_VERSION_UNIQUE_NAME@ +#define __os_get_errno_ret_zero __os_get_errno_ret_zero@DB_VERSION_UNIQUE_NAME@ +#define __os_get_errno __os_get_errno@DB_VERSION_UNIQUE_NAME@ +#define __os_get_neterr __os_get_neterr@DB_VERSION_UNIQUE_NAME@ +#define __os_get_syserr __os_get_syserr@DB_VERSION_UNIQUE_NAME@ +#define __os_set_errno __os_set_errno@DB_VERSION_UNIQUE_NAME@ +#define __os_strerror __os_strerror@DB_VERSION_UNIQUE_NAME@ +#define __os_posix_err __os_posix_err@DB_VERSION_UNIQUE_NAME@ +#define __os_fileid __os_fileid@DB_VERSION_UNIQUE_NAME@ +#define __os_fdlock __os_fdlock@DB_VERSION_UNIQUE_NAME@ +#define __os_fsync __os_fsync@DB_VERSION_UNIQUE_NAME@ +#define __os_getenv __os_getenv@DB_VERSION_UNIQUE_NAME@ +#define __os_openhandle __os_openhandle@DB_VERSION_UNIQUE_NAME@ +#define __os_closehandle __os_closehandle@DB_VERSION_UNIQUE_NAME@ +#define __os_attach __os_attach@DB_VERSION_UNIQUE_NAME@ +#define __os_detach __os_detach@DB_VERSION_UNIQUE_NAME@ +#define __os_mapfile __os_mapfile@DB_VERSION_UNIQUE_NAME@ +#define __os_unmapfile __os_unmapfile@DB_VERSION_UNIQUE_NAME@ +#define __os_mkdir __os_mkdir@DB_VERSION_UNIQUE_NAME@ +#define __os_open __os_open@DB_VERSION_UNIQUE_NAME@ +#define __os_concat_path __os_concat_path@DB_VERSION_UNIQUE_NAME@ +#define __os_id __os_id@DB_VERSION_UNIQUE_NAME@ +#define __os_rename __os_rename@DB_VERSION_UNIQUE_NAME@ +#define __os_isroot __os_isroot@DB_VERSION_UNIQUE_NAME@ +#define __db_rpath __db_rpath@DB_VERSION_UNIQUE_NAME@ +#define __os_io __os_io@DB_VERSION_UNIQUE_NAME@ +#define __os_read __os_read@DB_VERSION_UNIQUE_NAME@ +#define __os_write __os_write@DB_VERSION_UNIQUE_NAME@ +#define __os_physwrite __os_physwrite@DB_VERSION_UNIQUE_NAME@ +#define __os_seek __os_seek@DB_VERSION_UNIQUE_NAME@ +#define __os_stack __os_stack@DB_VERSION_UNIQUE_NAME@ +#define __os_exists __os_exists@DB_VERSION_UNIQUE_NAME@ +#define __os_ioinfo __os_ioinfo@DB_VERSION_UNIQUE_NAME@ +#define __os_tmpdir __os_tmpdir@DB_VERSION_UNIQUE_NAME@ +#define __os_truncate __os_truncate@DB_VERSION_UNIQUE_NAME@ +#define __os_unique_id __os_unique_id@DB_VERSION_UNIQUE_NAME@ +#define __os_unlink __os_unlink@DB_VERSION_UNIQUE_NAME@ +#define __os_yield __os_yield@DB_VERSION_UNIQUE_NAME@ +#ifdef HAVE_QNX +#define __os_qnx_region_open __os_qnx_region_open@DB_VERSION_UNIQUE_NAME@ +#endif +#define __os_is_winnt __os_is_winnt@DB_VERSION_UNIQUE_NAME@ +#define __os_cpu_count __os_cpu_count@DB_VERSION_UNIQUE_NAME@ +#ifdef HAVE_REPLICATION_THREADS +#define __os_get_neterr __os_get_neterr@DB_VERSION_UNIQUE_NAME@ +#endif +#define __qam_position __qam_position@DB_VERSION_UNIQUE_NAME@ +#define __qam_pitem __qam_pitem@DB_VERSION_UNIQUE_NAME@ +#define __qam_append __qam_append@DB_VERSION_UNIQUE_NAME@ +#define __qamc_dup __qamc_dup@DB_VERSION_UNIQUE_NAME@ +#define __qamc_init __qamc_init@DB_VERSION_UNIQUE_NAME@ +#define __qam_truncate __qam_truncate@DB_VERSION_UNIQUE_NAME@ +#define __qam_delete __qam_delete@DB_VERSION_UNIQUE_NAME@ +#define __qam_incfirst_desc __qam_incfirst_desc@DB_VERSION_UNIQUE_NAME@ +#define __qam_mvptr_desc __qam_mvptr_desc@DB_VERSION_UNIQUE_NAME@ +#define __qam_del_desc __qam_del_desc@DB_VERSION_UNIQUE_NAME@ +#define __qam_add_desc __qam_add_desc@DB_VERSION_UNIQUE_NAME@ +#define __qam_delext_desc __qam_delext_desc@DB_VERSION_UNIQUE_NAME@ +#define __qam_init_recover __qam_init_recover@DB_VERSION_UNIQUE_NAME@ +#define __qam_incfirst_print __qam_incfirst_print@DB_VERSION_UNIQUE_NAME@ +#define __qam_mvptr_print __qam_mvptr_print@DB_VERSION_UNIQUE_NAME@ +#define __qam_del_print __qam_del_print@DB_VERSION_UNIQUE_NAME@ +#define __qam_add_print __qam_add_print@DB_VERSION_UNIQUE_NAME@ +#define __qam_delext_print __qam_delext_print@DB_VERSION_UNIQUE_NAME@ +#define __qam_init_print __qam_init_print@DB_VERSION_UNIQUE_NAME@ +#define __qam_mswap __qam_mswap@DB_VERSION_UNIQUE_NAME@ +#define __qam_pgin_out __qam_pgin_out@DB_VERSION_UNIQUE_NAME@ +#define __qam_fprobe __qam_fprobe@DB_VERSION_UNIQUE_NAME@ +#define __qam_fclose __qam_fclose@DB_VERSION_UNIQUE_NAME@ +#define __qam_fremove __qam_fremove@DB_VERSION_UNIQUE_NAME@ +#define __qam_sync __qam_sync@DB_VERSION_UNIQUE_NAME@ +#define __qam_gen_filelist __qam_gen_filelist@DB_VERSION_UNIQUE_NAME@ +#define __qam_extent_names __qam_extent_names@DB_VERSION_UNIQUE_NAME@ +#define __qam_exid __qam_exid@DB_VERSION_UNIQUE_NAME@ +#define __qam_nameop __qam_nameop@DB_VERSION_UNIQUE_NAME@ +#define __qam_lsn_reset __qam_lsn_reset@DB_VERSION_UNIQUE_NAME@ +#define __qam_backup_extents __qam_backup_extents@DB_VERSION_UNIQUE_NAME@ +#define __qam_db_create __qam_db_create@DB_VERSION_UNIQUE_NAME@ +#define __qam_db_close __qam_db_close@DB_VERSION_UNIQUE_NAME@ +#define __qam_get_extentsize __qam_get_extentsize@DB_VERSION_UNIQUE_NAME@ +#define __queue_pageinfo __queue_pageinfo@DB_VERSION_UNIQUE_NAME@ +#define __db_prqueue __db_prqueue@DB_VERSION_UNIQUE_NAME@ +#define __qam_remove __qam_remove@DB_VERSION_UNIQUE_NAME@ +#define __qam_rename __qam_rename@DB_VERSION_UNIQUE_NAME@ +#define __qam_map_flags __qam_map_flags@DB_VERSION_UNIQUE_NAME@ +#define __qam_set_flags __qam_set_flags@DB_VERSION_UNIQUE_NAME@ +#define __qam_open __qam_open@DB_VERSION_UNIQUE_NAME@ +#define __qam_set_ext_data __qam_set_ext_data@DB_VERSION_UNIQUE_NAME@ +#define __qam_metachk __qam_metachk@DB_VERSION_UNIQUE_NAME@ +#define __qam_new_file __qam_new_file@DB_VERSION_UNIQUE_NAME@ +#define __qam_incfirst_recover __qam_incfirst_recover@DB_VERSION_UNIQUE_NAME@ +#define __qam_mvptr_recover __qam_mvptr_recover@DB_VERSION_UNIQUE_NAME@ +#define __qam_del_recover __qam_del_recover@DB_VERSION_UNIQUE_NAME@ +#define __qam_delext_recover __qam_delext_recover@DB_VERSION_UNIQUE_NAME@ +#define __qam_add_recover __qam_add_recover@DB_VERSION_UNIQUE_NAME@ +#define __qam_stat __qam_stat@DB_VERSION_UNIQUE_NAME@ +#define __qam_stat_print __qam_stat_print@DB_VERSION_UNIQUE_NAME@ +#define __db_no_queue_am __db_no_queue_am@DB_VERSION_UNIQUE_NAME@ +#define __qam_31_qammeta __qam_31_qammeta@DB_VERSION_UNIQUE_NAME@ +#define __qam_32_qammeta __qam_32_qammeta@DB_VERSION_UNIQUE_NAME@ +#define __qam_vrfy_meta __qam_vrfy_meta@DB_VERSION_UNIQUE_NAME@ +#define __qam_meta2pgset __qam_meta2pgset@DB_VERSION_UNIQUE_NAME@ +#define __qam_vrfy_data __qam_vrfy_data@DB_VERSION_UNIQUE_NAME@ +#define __qam_vrfy_structure __qam_vrfy_structure@DB_VERSION_UNIQUE_NAME@ +#define __qam_vrfy_walkqueue __qam_vrfy_walkqueue@DB_VERSION_UNIQUE_NAME@ +#define __qam_salvage __qam_salvage@DB_VERSION_UNIQUE_NAME@ +#define __rep_bulk_marshal __rep_bulk_marshal@DB_VERSION_UNIQUE_NAME@ +#define __rep_bulk_unmarshal __rep_bulk_unmarshal@DB_VERSION_UNIQUE_NAME@ +#define __rep_control_marshal __rep_control_marshal@DB_VERSION_UNIQUE_NAME@ +#define __rep_control_unmarshal __rep_control_unmarshal@DB_VERSION_UNIQUE_NAME@ +#define __rep_egen_marshal __rep_egen_marshal@DB_VERSION_UNIQUE_NAME@ +#define __rep_egen_unmarshal __rep_egen_unmarshal@DB_VERSION_UNIQUE_NAME@ +#define __rep_fileinfo_marshal __rep_fileinfo_marshal@DB_VERSION_UNIQUE_NAME@ +#define __rep_fileinfo_unmarshal __rep_fileinfo_unmarshal@DB_VERSION_UNIQUE_NAME@ +#define __rep_fileinfo_v6_marshal __rep_fileinfo_v6_marshal@DB_VERSION_UNIQUE_NAME@ +#define __rep_fileinfo_v6_unmarshal __rep_fileinfo_v6_unmarshal@DB_VERSION_UNIQUE_NAME@ +#define __rep_grant_info_marshal __rep_grant_info_marshal@DB_VERSION_UNIQUE_NAME@ +#define __rep_grant_info_unmarshal __rep_grant_info_unmarshal@DB_VERSION_UNIQUE_NAME@ +#define __rep_logreq_marshal __rep_logreq_marshal@DB_VERSION_UNIQUE_NAME@ +#define __rep_logreq_unmarshal __rep_logreq_unmarshal@DB_VERSION_UNIQUE_NAME@ +#define __rep_newfile_marshal __rep_newfile_marshal@DB_VERSION_UNIQUE_NAME@ +#define __rep_newfile_unmarshal __rep_newfile_unmarshal@DB_VERSION_UNIQUE_NAME@ +#define __rep_update_marshal __rep_update_marshal@DB_VERSION_UNIQUE_NAME@ +#define __rep_update_unmarshal __rep_update_unmarshal@DB_VERSION_UNIQUE_NAME@ +#define __rep_vote_info_marshal __rep_vote_info_marshal@DB_VERSION_UNIQUE_NAME@ +#define __rep_vote_info_unmarshal __rep_vote_info_unmarshal@DB_VERSION_UNIQUE_NAME@ +#define __rep_vote_info_v5_marshal __rep_vote_info_v5_marshal@DB_VERSION_UNIQUE_NAME@ +#define __rep_vote_info_v5_unmarshal __rep_vote_info_v5_unmarshal@DB_VERSION_UNIQUE_NAME@ +#define __rep_lsn_hist_key_marshal __rep_lsn_hist_key_marshal@DB_VERSION_UNIQUE_NAME@ +#define __rep_lsn_hist_key_unmarshal __rep_lsn_hist_key_unmarshal@DB_VERSION_UNIQUE_NAME@ +#define __rep_lsn_hist_data_marshal __rep_lsn_hist_data_marshal@DB_VERSION_UNIQUE_NAME@ +#define __rep_lsn_hist_data_unmarshal __rep_lsn_hist_data_unmarshal@DB_VERSION_UNIQUE_NAME@ +#define __rep_update_req __rep_update_req@DB_VERSION_UNIQUE_NAME@ +#define __rep_page_req __rep_page_req@DB_VERSION_UNIQUE_NAME@ +#define __rep_update_setup __rep_update_setup@DB_VERSION_UNIQUE_NAME@ +#define __rep_bulk_page __rep_bulk_page@DB_VERSION_UNIQUE_NAME@ +#define __rep_page __rep_page@DB_VERSION_UNIQUE_NAME@ +#define __rep_init_cleanup __rep_init_cleanup@DB_VERSION_UNIQUE_NAME@ +#define __rep_pggap_req __rep_pggap_req@DB_VERSION_UNIQUE_NAME@ +#define __rep_finfo_alloc __rep_finfo_alloc@DB_VERSION_UNIQUE_NAME@ +#define __rep_remove_init_file __rep_remove_init_file@DB_VERSION_UNIQUE_NAME@ +#define __rep_reset_init __rep_reset_init@DB_VERSION_UNIQUE_NAME@ +#define __rep_elect_pp __rep_elect_pp@DB_VERSION_UNIQUE_NAME@ +#define __rep_elect_int __rep_elect_int@DB_VERSION_UNIQUE_NAME@ +#define __rep_vote1 __rep_vote1@DB_VERSION_UNIQUE_NAME@ +#define __rep_vote2 __rep_vote2@DB_VERSION_UNIQUE_NAME@ +#define __rep_update_grant __rep_update_grant@DB_VERSION_UNIQUE_NAME@ +#define __rep_islease_granted __rep_islease_granted@DB_VERSION_UNIQUE_NAME@ +#define __rep_lease_table_alloc __rep_lease_table_alloc@DB_VERSION_UNIQUE_NAME@ +#define __rep_lease_grant __rep_lease_grant@DB_VERSION_UNIQUE_NAME@ +#define __rep_lease_check __rep_lease_check@DB_VERSION_UNIQUE_NAME@ +#define __rep_lease_refresh __rep_lease_refresh@DB_VERSION_UNIQUE_NAME@ +#define __rep_lease_expire __rep_lease_expire@DB_VERSION_UNIQUE_NAME@ +#define __rep_lease_waittime __rep_lease_waittime@DB_VERSION_UNIQUE_NAME@ +#define __rep_allreq __rep_allreq@DB_VERSION_UNIQUE_NAME@ +#define __rep_log __rep_log@DB_VERSION_UNIQUE_NAME@ +#define __rep_bulk_log __rep_bulk_log@DB_VERSION_UNIQUE_NAME@ +#define __rep_logreq __rep_logreq@DB_VERSION_UNIQUE_NAME@ +#define __rep_loggap_req __rep_loggap_req@DB_VERSION_UNIQUE_NAME@ +#define __rep_logready __rep_logready@DB_VERSION_UNIQUE_NAME@ +#define __rep_env_create __rep_env_create@DB_VERSION_UNIQUE_NAME@ +#define __rep_env_destroy __rep_env_destroy@DB_VERSION_UNIQUE_NAME@ +#define __rep_get_config __rep_get_config@DB_VERSION_UNIQUE_NAME@ +#define __rep_set_config __rep_set_config@DB_VERSION_UNIQUE_NAME@ +#define __rep_start_pp __rep_start_pp@DB_VERSION_UNIQUE_NAME@ +#define __rep_start_int __rep_start_int@DB_VERSION_UNIQUE_NAME@ +#define __rep_open_sysdb __rep_open_sysdb@DB_VERSION_UNIQUE_NAME@ +#define __rep_client_dbinit __rep_client_dbinit@DB_VERSION_UNIQUE_NAME@ +#define __rep_get_limit __rep_get_limit@DB_VERSION_UNIQUE_NAME@ +#define __rep_set_limit __rep_set_limit@DB_VERSION_UNIQUE_NAME@ +#define __rep_set_nsites_pp __rep_set_nsites_pp@DB_VERSION_UNIQUE_NAME@ +#define __rep_set_nsites_int __rep_set_nsites_int@DB_VERSION_UNIQUE_NAME@ +#define __rep_get_nsites __rep_get_nsites@DB_VERSION_UNIQUE_NAME@ +#define __rep_set_priority __rep_set_priority@DB_VERSION_UNIQUE_NAME@ +#define __rep_get_priority __rep_get_priority@DB_VERSION_UNIQUE_NAME@ +#define __rep_set_timeout __rep_set_timeout@DB_VERSION_UNIQUE_NAME@ +#define __rep_get_timeout __rep_get_timeout@DB_VERSION_UNIQUE_NAME@ +#define __rep_get_request __rep_get_request@DB_VERSION_UNIQUE_NAME@ +#define __rep_set_request __rep_set_request@DB_VERSION_UNIQUE_NAME@ +#define __rep_set_transport_pp __rep_set_transport_pp@DB_VERSION_UNIQUE_NAME@ +#define __rep_set_transport_int __rep_set_transport_int@DB_VERSION_UNIQUE_NAME@ +#define __rep_get_clockskew __rep_get_clockskew@DB_VERSION_UNIQUE_NAME@ +#define __rep_set_clockskew __rep_set_clockskew@DB_VERSION_UNIQUE_NAME@ +#define __rep_flush __rep_flush@DB_VERSION_UNIQUE_NAME@ +#define __rep_sync __rep_sync@DB_VERSION_UNIQUE_NAME@ +#define __rep_txn_applied __rep_txn_applied@DB_VERSION_UNIQUE_NAME@ +#define __rep_process_message_pp __rep_process_message_pp@DB_VERSION_UNIQUE_NAME@ +#define __rep_process_message_int __rep_process_message_int@DB_VERSION_UNIQUE_NAME@ +#define __rep_apply __rep_apply@DB_VERSION_UNIQUE_NAME@ +#define __rep_process_txn __rep_process_txn@DB_VERSION_UNIQUE_NAME@ +#define __rep_resend_req __rep_resend_req@DB_VERSION_UNIQUE_NAME@ +#define __rep_check_doreq __rep_check_doreq@DB_VERSION_UNIQUE_NAME@ +#define __rep_check_missing __rep_check_missing@DB_VERSION_UNIQUE_NAME@ +#define __rep_open __rep_open@DB_VERSION_UNIQUE_NAME@ +#define __rep_close_diagfiles __rep_close_diagfiles@DB_VERSION_UNIQUE_NAME@ +#define __rep_env_refresh __rep_env_refresh@DB_VERSION_UNIQUE_NAME@ +#define __rep_env_close __rep_env_close@DB_VERSION_UNIQUE_NAME@ +#define __rep_preclose __rep_preclose@DB_VERSION_UNIQUE_NAME@ +#define __rep_closefiles __rep_closefiles@DB_VERSION_UNIQUE_NAME@ +#define __rep_write_egen __rep_write_egen@DB_VERSION_UNIQUE_NAME@ +#define __rep_write_gen __rep_write_gen@DB_VERSION_UNIQUE_NAME@ +#define __rep_stat_pp __rep_stat_pp@DB_VERSION_UNIQUE_NAME@ +#define __rep_stat_print_pp __rep_stat_print_pp@DB_VERSION_UNIQUE_NAME@ +#define __rep_stat_print __rep_stat_print@DB_VERSION_UNIQUE_NAME@ +#define __rep_bulk_message __rep_bulk_message@DB_VERSION_UNIQUE_NAME@ +#define __rep_send_bulk __rep_send_bulk@DB_VERSION_UNIQUE_NAME@ +#define __rep_bulk_alloc __rep_bulk_alloc@DB_VERSION_UNIQUE_NAME@ +#define __rep_bulk_free __rep_bulk_free@DB_VERSION_UNIQUE_NAME@ +#define __rep_send_message __rep_send_message@DB_VERSION_UNIQUE_NAME@ +#define __rep_new_master __rep_new_master@DB_VERSION_UNIQUE_NAME@ +#define __rep_elect_done __rep_elect_done@DB_VERSION_UNIQUE_NAME@ +#define __env_rep_enter __env_rep_enter@DB_VERSION_UNIQUE_NAME@ +#define __env_db_rep_exit __env_db_rep_exit@DB_VERSION_UNIQUE_NAME@ +#define __db_rep_enter __db_rep_enter@DB_VERSION_UNIQUE_NAME@ +#define __op_handle_enter __op_handle_enter@DB_VERSION_UNIQUE_NAME@ +#define __op_rep_enter __op_rep_enter@DB_VERSION_UNIQUE_NAME@ +#define __op_rep_exit __op_rep_exit@DB_VERSION_UNIQUE_NAME@ +#define __archive_rep_enter __archive_rep_enter@DB_VERSION_UNIQUE_NAME@ +#define __archive_rep_exit __archive_rep_exit@DB_VERSION_UNIQUE_NAME@ +#define __rep_lockout_archive __rep_lockout_archive@DB_VERSION_UNIQUE_NAME@ +#define __rep_lockout_api __rep_lockout_api@DB_VERSION_UNIQUE_NAME@ +#define __rep_take_apilockout __rep_take_apilockout@DB_VERSION_UNIQUE_NAME@ +#define __rep_clear_apilockout __rep_clear_apilockout@DB_VERSION_UNIQUE_NAME@ +#define __rep_lockout_apply __rep_lockout_apply@DB_VERSION_UNIQUE_NAME@ +#define __rep_lockout_msg __rep_lockout_msg@DB_VERSION_UNIQUE_NAME@ +#define __rep_send_throttle __rep_send_throttle@DB_VERSION_UNIQUE_NAME@ +#define __rep_msg_to_old __rep_msg_to_old@DB_VERSION_UNIQUE_NAME@ +#define __rep_msg_from_old __rep_msg_from_old@DB_VERSION_UNIQUE_NAME@ +#define __rep_print_system __rep_print_system@DB_VERSION_UNIQUE_NAME@ +#define __rep_print __rep_print@DB_VERSION_UNIQUE_NAME@ +#define __rep_print_message __rep_print_message@DB_VERSION_UNIQUE_NAME@ +#define __rep_fire_event __rep_fire_event@DB_VERSION_UNIQUE_NAME@ +#define __rep_msg __rep_msg@DB_VERSION_UNIQUE_NAME@ +#define __rep_notify_threads __rep_notify_threads@DB_VERSION_UNIQUE_NAME@ +#define __rep_check_goal __rep_check_goal@DB_VERSION_UNIQUE_NAME@ +#define __rep_log_backup __rep_log_backup@DB_VERSION_UNIQUE_NAME@ +#define __rep_get_maxpermlsn __rep_get_maxpermlsn@DB_VERSION_UNIQUE_NAME@ +#define __rep_is_internal_rep_file __rep_is_internal_rep_file@DB_VERSION_UNIQUE_NAME@ +#define __rep_get_datagen __rep_get_datagen@DB_VERSION_UNIQUE_NAME@ +#define __rep_verify __rep_verify@DB_VERSION_UNIQUE_NAME@ +#define __rep_verify_fail __rep_verify_fail@DB_VERSION_UNIQUE_NAME@ +#define __rep_verify_req __rep_verify_req@DB_VERSION_UNIQUE_NAME@ +#define __rep_dorecovery __rep_dorecovery@DB_VERSION_UNIQUE_NAME@ +#define __rep_verify_match __rep_verify_match@DB_VERSION_UNIQUE_NAME@ +#define __repmgr_member_desc __repmgr_member_desc@DB_VERSION_UNIQUE_NAME@ +#define __repmgr_init_recover __repmgr_init_recover@DB_VERSION_UNIQUE_NAME@ +#define __repmgr_handshake_marshal __repmgr_handshake_marshal@DB_VERSION_UNIQUE_NAME@ +#define __repmgr_handshake_unmarshal __repmgr_handshake_unmarshal@DB_VERSION_UNIQUE_NAME@ +#define __repmgr_v3handshake_marshal __repmgr_v3handshake_marshal@DB_VERSION_UNIQUE_NAME@ +#define __repmgr_v3handshake_unmarshal __repmgr_v3handshake_unmarshal@DB_VERSION_UNIQUE_NAME@ +#define __repmgr_v2handshake_marshal __repmgr_v2handshake_marshal@DB_VERSION_UNIQUE_NAME@ +#define __repmgr_v2handshake_unmarshal __repmgr_v2handshake_unmarshal@DB_VERSION_UNIQUE_NAME@ +#define __repmgr_parm_refresh_marshal __repmgr_parm_refresh_marshal@DB_VERSION_UNIQUE_NAME@ +#define __repmgr_parm_refresh_unmarshal __repmgr_parm_refresh_unmarshal@DB_VERSION_UNIQUE_NAME@ +#define __repmgr_permlsn_marshal __repmgr_permlsn_marshal@DB_VERSION_UNIQUE_NAME@ +#define __repmgr_permlsn_unmarshal __repmgr_permlsn_unmarshal@DB_VERSION_UNIQUE_NAME@ +#define __repmgr_version_proposal_marshal __repmgr_version_proposal_marshal@DB_VERSION_UNIQUE_NAME@ +#define __repmgr_version_proposal_unmarshal __repmgr_version_proposal_unmarshal@DB_VERSION_UNIQUE_NAME@ +#define __repmgr_version_confirmation_marshal __repmgr_version_confirmation_marshal@DB_VERSION_UNIQUE_NAME@ +#define __repmgr_version_confirmation_unmarshal __repmgr_version_confirmation_unmarshal@DB_VERSION_UNIQUE_NAME@ +#define __repmgr_msg_hdr_marshal __repmgr_msg_hdr_marshal@DB_VERSION_UNIQUE_NAME@ +#define __repmgr_msg_hdr_unmarshal __repmgr_msg_hdr_unmarshal@DB_VERSION_UNIQUE_NAME@ +#define __repmgr_msg_metadata_marshal __repmgr_msg_metadata_marshal@DB_VERSION_UNIQUE_NAME@ +#define __repmgr_msg_metadata_unmarshal __repmgr_msg_metadata_unmarshal@DB_VERSION_UNIQUE_NAME@ +#define __repmgr_membership_key_marshal __repmgr_membership_key_marshal@DB_VERSION_UNIQUE_NAME@ +#define __repmgr_membership_key_unmarshal __repmgr_membership_key_unmarshal@DB_VERSION_UNIQUE_NAME@ +#define __repmgr_membership_data_marshal __repmgr_membership_data_marshal@DB_VERSION_UNIQUE_NAME@ +#define __repmgr_membership_data_unmarshal __repmgr_membership_data_unmarshal@DB_VERSION_UNIQUE_NAME@ +#define __repmgr_member_metadata_marshal __repmgr_member_metadata_marshal@DB_VERSION_UNIQUE_NAME@ +#define __repmgr_member_metadata_unmarshal __repmgr_member_metadata_unmarshal@DB_VERSION_UNIQUE_NAME@ +#define __repmgr_gm_fwd_marshal __repmgr_gm_fwd_marshal@DB_VERSION_UNIQUE_NAME@ +#define __repmgr_gm_fwd_unmarshal __repmgr_gm_fwd_unmarshal@DB_VERSION_UNIQUE_NAME@ +#define __repmgr_membr_vers_marshal __repmgr_membr_vers_marshal@DB_VERSION_UNIQUE_NAME@ +#define __repmgr_membr_vers_unmarshal __repmgr_membr_vers_unmarshal@DB_VERSION_UNIQUE_NAME@ +#define __repmgr_site_info_marshal __repmgr_site_info_marshal@DB_VERSION_UNIQUE_NAME@ +#define __repmgr_site_info_unmarshal __repmgr_site_info_unmarshal@DB_VERSION_UNIQUE_NAME@ +#define __repmgr_connect_reject_marshal __repmgr_connect_reject_marshal@DB_VERSION_UNIQUE_NAME@ +#define __repmgr_connect_reject_unmarshal __repmgr_connect_reject_unmarshal@DB_VERSION_UNIQUE_NAME@ +#define __repmgr_member_print __repmgr_member_print@DB_VERSION_UNIQUE_NAME@ +#define __repmgr_init_print __repmgr_init_print@DB_VERSION_UNIQUE_NAME@ +#define __repmgr_init_election __repmgr_init_election@DB_VERSION_UNIQUE_NAME@ +#define __repmgr_claim_victory __repmgr_claim_victory@DB_VERSION_UNIQUE_NAME@ +#define __repmgr_turn_on_elections __repmgr_turn_on_elections@DB_VERSION_UNIQUE_NAME@ +#define __repmgr_start __repmgr_start@DB_VERSION_UNIQUE_NAME@ +#define __repmgr_valid_config __repmgr_valid_config@DB_VERSION_UNIQUE_NAME@ +#define __repmgr_autostart __repmgr_autostart@DB_VERSION_UNIQUE_NAME@ +#define __repmgr_start_selector __repmgr_start_selector@DB_VERSION_UNIQUE_NAME@ +#define __repmgr_close __repmgr_close@DB_VERSION_UNIQUE_NAME@ +#define __repmgr_stop __repmgr_stop@DB_VERSION_UNIQUE_NAME@ +#define __repmgr_set_ack_policy __repmgr_set_ack_policy@DB_VERSION_UNIQUE_NAME@ +#define __repmgr_get_ack_policy __repmgr_get_ack_policy@DB_VERSION_UNIQUE_NAME@ +#define __repmgr_env_create __repmgr_env_create@DB_VERSION_UNIQUE_NAME@ +#define __repmgr_env_destroy __repmgr_env_destroy@DB_VERSION_UNIQUE_NAME@ +#define __repmgr_stop_threads __repmgr_stop_threads@DB_VERSION_UNIQUE_NAME@ +#define __repmgr_local_site __repmgr_local_site@DB_VERSION_UNIQUE_NAME@ +#define __repmgr_channel __repmgr_channel@DB_VERSION_UNIQUE_NAME@ +#define __repmgr_set_msg_dispatch __repmgr_set_msg_dispatch@DB_VERSION_UNIQUE_NAME@ +#define __repmgr_send_msg __repmgr_send_msg@DB_VERSION_UNIQUE_NAME@ +#define __repmgr_send_request __repmgr_send_request@DB_VERSION_UNIQUE_NAME@ +#define __repmgr_send_response __repmgr_send_response@DB_VERSION_UNIQUE_NAME@ +#define __repmgr_channel_close __repmgr_channel_close@DB_VERSION_UNIQUE_NAME@ +#define __repmgr_channel_timeout __repmgr_channel_timeout@DB_VERSION_UNIQUE_NAME@ +#define __repmgr_send_request_inval __repmgr_send_request_inval@DB_VERSION_UNIQUE_NAME@ +#define __repmgr_channel_close_inval __repmgr_channel_close_inval@DB_VERSION_UNIQUE_NAME@ +#define __repmgr_channel_timeout_inval __repmgr_channel_timeout_inval@DB_VERSION_UNIQUE_NAME@ +#define __repmgr_join_group __repmgr_join_group@DB_VERSION_UNIQUE_NAME@ +#define __repmgr_site __repmgr_site@DB_VERSION_UNIQUE_NAME@ +#define __repmgr_site_by_eid __repmgr_site_by_eid@DB_VERSION_UNIQUE_NAME@ +#define __repmgr_get_site_address __repmgr_get_site_address@DB_VERSION_UNIQUE_NAME@ +#define __repmgr_get_eid __repmgr_get_eid@DB_VERSION_UNIQUE_NAME@ +#define __repmgr_get_config __repmgr_get_config@DB_VERSION_UNIQUE_NAME@ +#define __repmgr_site_config __repmgr_site_config@DB_VERSION_UNIQUE_NAME@ +#define __repmgr_site_close __repmgr_site_close@DB_VERSION_UNIQUE_NAME@ +#define __repmgr_msg_thread __repmgr_msg_thread@DB_VERSION_UNIQUE_NAME@ +#define __repmgr_send_err_resp __repmgr_send_err_resp@DB_VERSION_UNIQUE_NAME@ +#define __repmgr_handle_event __repmgr_handle_event@DB_VERSION_UNIQUE_NAME@ +#define __repmgr_update_membership __repmgr_update_membership@DB_VERSION_UNIQUE_NAME@ +#define __repmgr_set_gm_version __repmgr_set_gm_version@DB_VERSION_UNIQUE_NAME@ +#define __repmgr_setup_gmdb_op __repmgr_setup_gmdb_op@DB_VERSION_UNIQUE_NAME@ +#define __repmgr_cleanup_gmdb_op __repmgr_cleanup_gmdb_op@DB_VERSION_UNIQUE_NAME@ +#define __repmgr_hold_master_role __repmgr_hold_master_role@DB_VERSION_UNIQUE_NAME@ +#define __repmgr_rlse_master_role __repmgr_rlse_master_role@DB_VERSION_UNIQUE_NAME@ +#define __repmgr_set_sites __repmgr_set_sites@DB_VERSION_UNIQUE_NAME@ +#define __repmgr_connect __repmgr_connect@DB_VERSION_UNIQUE_NAME@ +#define __repmgr_send __repmgr_send@DB_VERSION_UNIQUE_NAME@ +#define __repmgr_sync_siteaddr __repmgr_sync_siteaddr@DB_VERSION_UNIQUE_NAME@ +#define __repmgr_send_broadcast __repmgr_send_broadcast@DB_VERSION_UNIQUE_NAME@ +#define __repmgr_send_one __repmgr_send_one@DB_VERSION_UNIQUE_NAME@ +#define __repmgr_send_many __repmgr_send_many@DB_VERSION_UNIQUE_NAME@ +#define __repmgr_send_own_msg __repmgr_send_own_msg@DB_VERSION_UNIQUE_NAME@ +#define __repmgr_write_iovecs __repmgr_write_iovecs@DB_VERSION_UNIQUE_NAME@ +#define __repmgr_bust_connection __repmgr_bust_connection@DB_VERSION_UNIQUE_NAME@ +#define __repmgr_disable_connection __repmgr_disable_connection@DB_VERSION_UNIQUE_NAME@ +#define __repmgr_cleanup_defunct __repmgr_cleanup_defunct@DB_VERSION_UNIQUE_NAME@ +#define __repmgr_close_connection __repmgr_close_connection@DB_VERSION_UNIQUE_NAME@ +#define __repmgr_decr_conn_ref __repmgr_decr_conn_ref@DB_VERSION_UNIQUE_NAME@ +#define __repmgr_destroy_conn __repmgr_destroy_conn@DB_VERSION_UNIQUE_NAME@ +#define __repmgr_pack_netaddr __repmgr_pack_netaddr@DB_VERSION_UNIQUE_NAME@ +#define __repmgr_getaddr __repmgr_getaddr@DB_VERSION_UNIQUE_NAME@ +#define __repmgr_listen __repmgr_listen@DB_VERSION_UNIQUE_NAME@ +#define __repmgr_net_close __repmgr_net_close@DB_VERSION_UNIQUE_NAME@ +#define __repmgr_net_destroy __repmgr_net_destroy@DB_VERSION_UNIQUE_NAME@ +#define __repmgr_thread_start __repmgr_thread_start@DB_VERSION_UNIQUE_NAME@ +#define __repmgr_thread_join __repmgr_thread_join@DB_VERSION_UNIQUE_NAME@ +#define __repmgr_set_nonblock_conn __repmgr_set_nonblock_conn@DB_VERSION_UNIQUE_NAME@ +#define __repmgr_set_nonblocking __repmgr_set_nonblocking@DB_VERSION_UNIQUE_NAME@ +#define __repmgr_wake_waiters __repmgr_wake_waiters@DB_VERSION_UNIQUE_NAME@ +#define __repmgr_await_cond __repmgr_await_cond@DB_VERSION_UNIQUE_NAME@ +#define __repmgr_await_gmdbop __repmgr_await_gmdbop@DB_VERSION_UNIQUE_NAME@ +#define __repmgr_compute_wait_deadline __repmgr_compute_wait_deadline@DB_VERSION_UNIQUE_NAME@ +#define __repmgr_await_drain __repmgr_await_drain@DB_VERSION_UNIQUE_NAME@ +#define __repmgr_alloc_cond __repmgr_alloc_cond@DB_VERSION_UNIQUE_NAME@ +#define __repmgr_free_cond __repmgr_free_cond@DB_VERSION_UNIQUE_NAME@ +#define __repmgr_env_create_pf __repmgr_env_create_pf@DB_VERSION_UNIQUE_NAME@ +#define __repmgr_create_mutex_pf __repmgr_create_mutex_pf@DB_VERSION_UNIQUE_NAME@ +#define __repmgr_destroy_mutex_pf __repmgr_destroy_mutex_pf@DB_VERSION_UNIQUE_NAME@ +#define __repmgr_init __repmgr_init@DB_VERSION_UNIQUE_NAME@ +#define __repmgr_deinit __repmgr_deinit@DB_VERSION_UNIQUE_NAME@ +#define __repmgr_init_waiters __repmgr_init_waiters@DB_VERSION_UNIQUE_NAME@ +#define __repmgr_destroy_waiters __repmgr_destroy_waiters@DB_VERSION_UNIQUE_NAME@ +#define __repmgr_lock_mutex __repmgr_lock_mutex@DB_VERSION_UNIQUE_NAME@ +#define __repmgr_unlock_mutex __repmgr_unlock_mutex@DB_VERSION_UNIQUE_NAME@ +#define __repmgr_signal __repmgr_signal@DB_VERSION_UNIQUE_NAME@ +#define __repmgr_wake_msngers __repmgr_wake_msngers@DB_VERSION_UNIQUE_NAME@ +#define __repmgr_wake_main_thread __repmgr_wake_main_thread@DB_VERSION_UNIQUE_NAME@ +#define __repmgr_writev __repmgr_writev@DB_VERSION_UNIQUE_NAME@ +#define __repmgr_readv __repmgr_readv@DB_VERSION_UNIQUE_NAME@ +#define __repmgr_select_loop __repmgr_select_loop@DB_VERSION_UNIQUE_NAME@ +#define __repmgr_queue_destroy __repmgr_queue_destroy@DB_VERSION_UNIQUE_NAME@ +#define __repmgr_queue_get __repmgr_queue_get@DB_VERSION_UNIQUE_NAME@ +#define __repmgr_queue_put __repmgr_queue_put@DB_VERSION_UNIQUE_NAME@ +#define __repmgr_queue_size __repmgr_queue_size@DB_VERSION_UNIQUE_NAME@ +#define __repmgr_member_recover __repmgr_member_recover@DB_VERSION_UNIQUE_NAME@ +#define __repmgr_select_thread __repmgr_select_thread@DB_VERSION_UNIQUE_NAME@ +#define __repmgr_bow_out __repmgr_bow_out@DB_VERSION_UNIQUE_NAME@ +#define __repmgr_accept __repmgr_accept@DB_VERSION_UNIQUE_NAME@ +#define __repmgr_compute_timeout __repmgr_compute_timeout@DB_VERSION_UNIQUE_NAME@ +#define __repmgr_connected_master __repmgr_connected_master@DB_VERSION_UNIQUE_NAME@ +#define __repmgr_check_timeouts __repmgr_check_timeouts@DB_VERSION_UNIQUE_NAME@ +#define __repmgr_first_try_connections __repmgr_first_try_connections@DB_VERSION_UNIQUE_NAME@ +#define __repmgr_send_v1_handshake __repmgr_send_v1_handshake@DB_VERSION_UNIQUE_NAME@ +#define __repmgr_read_from_site __repmgr_read_from_site@DB_VERSION_UNIQUE_NAME@ +#define __repmgr_read_conn __repmgr_read_conn@DB_VERSION_UNIQUE_NAME@ +#define __repmgr_prepare_simple_input __repmgr_prepare_simple_input@DB_VERSION_UNIQUE_NAME@ +#define __repmgr_send_handshake __repmgr_send_handshake@DB_VERSION_UNIQUE_NAME@ +#define __repmgr_find_version_info __repmgr_find_version_info@DB_VERSION_UNIQUE_NAME@ +#define __repmgr_write_some __repmgr_write_some@DB_VERSION_UNIQUE_NAME@ +#define __repmgr_stat_pp __repmgr_stat_pp@DB_VERSION_UNIQUE_NAME@ +#define __repmgr_stat_print_pp __repmgr_stat_print_pp@DB_VERSION_UNIQUE_NAME@ +#define __repmgr_stat_print __repmgr_stat_print@DB_VERSION_UNIQUE_NAME@ +#define __repmgr_site_list __repmgr_site_list@DB_VERSION_UNIQUE_NAME@ +#ifndef HAVE_REPLICATION_THREADS +#define __repmgr_close __repmgr_close@DB_VERSION_UNIQUE_NAME@ +#endif +#ifndef HAVE_REPLICATION_THREADS +#define __repmgr_get_ack_policy __repmgr_get_ack_policy@DB_VERSION_UNIQUE_NAME@ +#endif +#ifndef HAVE_REPLICATION_THREADS +#define __repmgr_set_ack_policy __repmgr_set_ack_policy@DB_VERSION_UNIQUE_NAME@ +#endif +#ifndef HAVE_REPLICATION_THREADS +#define __repmgr_site __repmgr_site@DB_VERSION_UNIQUE_NAME@ +#endif +#ifndef HAVE_REPLICATION_THREADS +#define __repmgr_site_by_eid __repmgr_site_by_eid@DB_VERSION_UNIQUE_NAME@ +#endif +#ifndef HAVE_REPLICATION_THREADS +#define __repmgr_local_site __repmgr_local_site@DB_VERSION_UNIQUE_NAME@ +#endif +#ifndef HAVE_REPLICATION_THREADS +#define __repmgr_site_list __repmgr_site_list@DB_VERSION_UNIQUE_NAME@ +#endif +#ifndef HAVE_REPLICATION_THREADS +#define __repmgr_start __repmgr_start@DB_VERSION_UNIQUE_NAME@ +#endif +#ifndef HAVE_REPLICATION_THREADS +#define __repmgr_stat_pp __repmgr_stat_pp@DB_VERSION_UNIQUE_NAME@ +#endif +#ifndef HAVE_REPLICATION_THREADS +#define __repmgr_stat_print_pp __repmgr_stat_print_pp@DB_VERSION_UNIQUE_NAME@ +#endif +#ifndef HAVE_REPLICATION_THREADS +#define __repmgr_handle_event __repmgr_handle_event@DB_VERSION_UNIQUE_NAME@ +#endif +#ifndef HAVE_REPLICATION_THREADS +#define __repmgr_channel __repmgr_channel@DB_VERSION_UNIQUE_NAME@ +#endif +#ifndef HAVE_REPLICATION_THREADS +#define __repmgr_set_msg_dispatch __repmgr_set_msg_dispatch@DB_VERSION_UNIQUE_NAME@ +#endif +#ifndef HAVE_REPLICATION_THREADS +#define __repmgr_init_recover __repmgr_init_recover@DB_VERSION_UNIQUE_NAME@ +#endif +#define __repmgr_schedule_connection_attempt __repmgr_schedule_connection_attempt@DB_VERSION_UNIQUE_NAME@ +#define __repmgr_is_server __repmgr_is_server@DB_VERSION_UNIQUE_NAME@ +#define __repmgr_reset_for_reading __repmgr_reset_for_reading@DB_VERSION_UNIQUE_NAME@ +#define __repmgr_new_connection __repmgr_new_connection@DB_VERSION_UNIQUE_NAME@ +#define __repmgr_set_keepalive __repmgr_set_keepalive@DB_VERSION_UNIQUE_NAME@ +#define __repmgr_new_site __repmgr_new_site@DB_VERSION_UNIQUE_NAME@ +#define __repmgr_create_mutex __repmgr_create_mutex@DB_VERSION_UNIQUE_NAME@ +#define __repmgr_destroy_mutex __repmgr_destroy_mutex@DB_VERSION_UNIQUE_NAME@ +#define __repmgr_cleanup_netaddr __repmgr_cleanup_netaddr@DB_VERSION_UNIQUE_NAME@ +#define __repmgr_iovec_init __repmgr_iovec_init@DB_VERSION_UNIQUE_NAME@ +#define __repmgr_add_buffer __repmgr_add_buffer@DB_VERSION_UNIQUE_NAME@ +#define __repmgr_add_dbt __repmgr_add_dbt@DB_VERSION_UNIQUE_NAME@ +#define __repmgr_update_consumed __repmgr_update_consumed@DB_VERSION_UNIQUE_NAME@ +#define __repmgr_prepare_my_addr __repmgr_prepare_my_addr@DB_VERSION_UNIQUE_NAME@ +#define __repmgr_get_nsites __repmgr_get_nsites@DB_VERSION_UNIQUE_NAME@ +#define __repmgr_thread_failure __repmgr_thread_failure@DB_VERSION_UNIQUE_NAME@ +#define __repmgr_format_eid_loc __repmgr_format_eid_loc@DB_VERSION_UNIQUE_NAME@ +#define __repmgr_format_site_loc __repmgr_format_site_loc@DB_VERSION_UNIQUE_NAME@ +#define __repmgr_format_addr_loc __repmgr_format_addr_loc@DB_VERSION_UNIQUE_NAME@ +#define __repmgr_repstart __repmgr_repstart@DB_VERSION_UNIQUE_NAME@ +#define __repmgr_become_master __repmgr_become_master@DB_VERSION_UNIQUE_NAME@ +#define __repmgr_each_connection __repmgr_each_connection@DB_VERSION_UNIQUE_NAME@ +#define __repmgr_open __repmgr_open@DB_VERSION_UNIQUE_NAME@ +#define __repmgr_join __repmgr_join@DB_VERSION_UNIQUE_NAME@ +#define __repmgr_env_refresh __repmgr_env_refresh@DB_VERSION_UNIQUE_NAME@ +#define __repmgr_share_netaddrs __repmgr_share_netaddrs@DB_VERSION_UNIQUE_NAME@ +#define __repmgr_copy_in_added_sites __repmgr_copy_in_added_sites@DB_VERSION_UNIQUE_NAME@ +#define __repmgr_init_new_sites __repmgr_init_new_sites@DB_VERSION_UNIQUE_NAME@ +#define __repmgr_failchk __repmgr_failchk@DB_VERSION_UNIQUE_NAME@ +#define __repmgr_master_is_known __repmgr_master_is_known@DB_VERSION_UNIQUE_NAME@ +#define __repmgr_stable_lsn __repmgr_stable_lsn@DB_VERSION_UNIQUE_NAME@ +#define __repmgr_send_sync_msg __repmgr_send_sync_msg@DB_VERSION_UNIQUE_NAME@ +#define __repmgr_marshal_member_list __repmgr_marshal_member_list@DB_VERSION_UNIQUE_NAME@ +#define __repmgr_refresh_membership __repmgr_refresh_membership@DB_VERSION_UNIQUE_NAME@ +#define __repmgr_reload_gmdb __repmgr_reload_gmdb@DB_VERSION_UNIQUE_NAME@ +#define __repmgr_gmdb_version_cmp __repmgr_gmdb_version_cmp@DB_VERSION_UNIQUE_NAME@ +#define __repmgr_init_save __repmgr_init_save@DB_VERSION_UNIQUE_NAME@ +#define __repmgr_init_restore __repmgr_init_restore@DB_VERSION_UNIQUE_NAME@ +#define __repmgr_defer_op __repmgr_defer_op@DB_VERSION_UNIQUE_NAME@ +#define __repmgr_fire_conn_err_event __repmgr_fire_conn_err_event@DB_VERSION_UNIQUE_NAME@ +#define __repmgr_print_conn_err __repmgr_print_conn_err@DB_VERSION_UNIQUE_NAME@ +#define __repmgr_become_client __repmgr_become_client@DB_VERSION_UNIQUE_NAME@ +#define __repmgr_lookup_site __repmgr_lookup_site@DB_VERSION_UNIQUE_NAME@ +#define __repmgr_find_site __repmgr_find_site@DB_VERSION_UNIQUE_NAME@ +#define __repmgr_set_membership __repmgr_set_membership@DB_VERSION_UNIQUE_NAME@ +#define __repmgr_bcast_parm_refresh __repmgr_bcast_parm_refresh@DB_VERSION_UNIQUE_NAME@ +#define __repmgr_chg_prio __repmgr_chg_prio@DB_VERSION_UNIQUE_NAME@ +#define __repmgr_bcast_own_msg __repmgr_bcast_own_msg@DB_VERSION_UNIQUE_NAME@ +#define __seq_stat __seq_stat@DB_VERSION_UNIQUE_NAME@ +#define __seq_stat_print __seq_stat_print@DB_VERSION_UNIQUE_NAME@ +#define __db_get_seq_flags_fn __db_get_seq_flags_fn@DB_VERSION_UNIQUE_NAME@ +#define __db_get_seq_flags_fn __db_get_seq_flags_fn@DB_VERSION_UNIQUE_NAME@ +#define bdb_HCommand bdb_HCommand@DB_VERSION_UNIQUE_NAME@ +#if DB_DBM_HSEARCH != 0 +#define bdb_NdbmOpen bdb_NdbmOpen@DB_VERSION_UNIQUE_NAME@ +#endif +#if DB_DBM_HSEARCH != 0 +#define bdb_DbmCommand bdb_DbmCommand@DB_VERSION_UNIQUE_NAME@ +#endif +#define ndbm_Cmd ndbm_Cmd@DB_VERSION_UNIQUE_NAME@ +#define _DbInfoDelete _DbInfoDelete@DB_VERSION_UNIQUE_NAME@ +#define db_Cmd db_Cmd@DB_VERSION_UNIQUE_NAME@ +#define tcl_CompactStat tcl_CompactStat@DB_VERSION_UNIQUE_NAME@ +#define tcl_rep_send tcl_rep_send@DB_VERSION_UNIQUE_NAME@ +#define dbc_Cmd dbc_Cmd@DB_VERSION_UNIQUE_NAME@ +#define env_Cmd env_Cmd@DB_VERSION_UNIQUE_NAME@ +#define tcl_EnvRemove tcl_EnvRemove@DB_VERSION_UNIQUE_NAME@ +#define tcl_EnvClose tcl_EnvClose@DB_VERSION_UNIQUE_NAME@ +#define tcl_EnvAttr tcl_EnvAttr@DB_VERSION_UNIQUE_NAME@ +#define tcl_EnvIdReset tcl_EnvIdReset@DB_VERSION_UNIQUE_NAME@ +#define tcl_EnvLsnReset tcl_EnvLsnReset@DB_VERSION_UNIQUE_NAME@ +#define tcl_EnvVerbose tcl_EnvVerbose@DB_VERSION_UNIQUE_NAME@ +#define tcl_EnvSetFlags tcl_EnvSetFlags@DB_VERSION_UNIQUE_NAME@ +#define tcl_EnvTest tcl_EnvTest@DB_VERSION_UNIQUE_NAME@ +#define tcl_EnvGetEncryptFlags tcl_EnvGetEncryptFlags@DB_VERSION_UNIQUE_NAME@ +#define tcl_EnvSetErrfile tcl_EnvSetErrfile@DB_VERSION_UNIQUE_NAME@ +#define tcl_EnvSetMsgfile tcl_EnvSetMsgfile@DB_VERSION_UNIQUE_NAME@ +#define tcl_EnvSetErrpfx tcl_EnvSetErrpfx@DB_VERSION_UNIQUE_NAME@ +#define tcl_EnvStatPrint tcl_EnvStatPrint@DB_VERSION_UNIQUE_NAME@ +#define _NewInfo _NewInfo@DB_VERSION_UNIQUE_NAME@ +#define _NameToPtr _NameToPtr@DB_VERSION_UNIQUE_NAME@ +#define _PtrToInfo _PtrToInfo@DB_VERSION_UNIQUE_NAME@ +#define _NameToInfo _NameToInfo@DB_VERSION_UNIQUE_NAME@ +#define _SetInfoData _SetInfoData@DB_VERSION_UNIQUE_NAME@ +#define _DeleteInfo _DeleteInfo@DB_VERSION_UNIQUE_NAME@ +#define _SetListElem _SetListElem@DB_VERSION_UNIQUE_NAME@ +#define _SetListElemInt _SetListElemInt@DB_VERSION_UNIQUE_NAME@ +#define _SetListElemWideInt _SetListElemWideInt@DB_VERSION_UNIQUE_NAME@ +#define _SetListRecnoElem _SetListRecnoElem@DB_VERSION_UNIQUE_NAME@ +#define _SetListHeapElem _SetListHeapElem@DB_VERSION_UNIQUE_NAME@ +#define _Set3DBTList _Set3DBTList@DB_VERSION_UNIQUE_NAME@ +#define _SetMultiList _SetMultiList@DB_VERSION_UNIQUE_NAME@ +#define _GetGlobPrefix _GetGlobPrefix@DB_VERSION_UNIQUE_NAME@ +#define _ReturnSetup _ReturnSetup@DB_VERSION_UNIQUE_NAME@ +#define _ErrorSetup _ErrorSetup@DB_VERSION_UNIQUE_NAME@ +#define _ErrorFunc _ErrorFunc@DB_VERSION_UNIQUE_NAME@ +#ifdef CONFIG_TEST +#define _EventFunc _EventFunc@DB_VERSION_UNIQUE_NAME@ +#endif +#define _GetLsn _GetLsn@DB_VERSION_UNIQUE_NAME@ +#define _GetRid _GetRid@DB_VERSION_UNIQUE_NAME@ +#define _GetUInt32 _GetUInt32@DB_VERSION_UNIQUE_NAME@ +#define _GetFlagsList _GetFlagsList@DB_VERSION_UNIQUE_NAME@ +#define _debug_check _debug_check@DB_VERSION_UNIQUE_NAME@ +#define _CopyObjBytes _CopyObjBytes@DB_VERSION_UNIQUE_NAME@ +#define tcl_LockDetect tcl_LockDetect@DB_VERSION_UNIQUE_NAME@ +#define tcl_LockGet tcl_LockGet@DB_VERSION_UNIQUE_NAME@ +#define tcl_LockStat tcl_LockStat@DB_VERSION_UNIQUE_NAME@ +#define tcl_LockStatPrint tcl_LockStatPrint@DB_VERSION_UNIQUE_NAME@ +#define tcl_LockTimeout tcl_LockTimeout@DB_VERSION_UNIQUE_NAME@ +#define tcl_LockVec tcl_LockVec@DB_VERSION_UNIQUE_NAME@ +#define tcl_LogArchive tcl_LogArchive@DB_VERSION_UNIQUE_NAME@ +#define tcl_LogCompare tcl_LogCompare@DB_VERSION_UNIQUE_NAME@ +#define tcl_LogFile tcl_LogFile@DB_VERSION_UNIQUE_NAME@ +#define tcl_LogFlush tcl_LogFlush@DB_VERSION_UNIQUE_NAME@ +#define tcl_LogGet tcl_LogGet@DB_VERSION_UNIQUE_NAME@ +#define tcl_LogPut tcl_LogPut@DB_VERSION_UNIQUE_NAME@ +#define tcl_LogStat tcl_LogStat@DB_VERSION_UNIQUE_NAME@ +#define tcl_LogStatPrint tcl_LogStatPrint@DB_VERSION_UNIQUE_NAME@ +#define logc_Cmd logc_Cmd@DB_VERSION_UNIQUE_NAME@ +#define tcl_LogConfig tcl_LogConfig@DB_VERSION_UNIQUE_NAME@ +#define tcl_LogGetConfig tcl_LogGetConfig@DB_VERSION_UNIQUE_NAME@ +#define _MpInfoDelete _MpInfoDelete@DB_VERSION_UNIQUE_NAME@ +#define tcl_MpSync tcl_MpSync@DB_VERSION_UNIQUE_NAME@ +#define tcl_MpTrickle tcl_MpTrickle@DB_VERSION_UNIQUE_NAME@ +#define tcl_Mp tcl_Mp@DB_VERSION_UNIQUE_NAME@ +#define tcl_MpStat tcl_MpStat@DB_VERSION_UNIQUE_NAME@ +#define tcl_MpStatPrint tcl_MpStatPrint@DB_VERSION_UNIQUE_NAME@ +#define tcl_Mutex tcl_Mutex@DB_VERSION_UNIQUE_NAME@ +#define tcl_MutFree tcl_MutFree@DB_VERSION_UNIQUE_NAME@ +#define tcl_MutGet tcl_MutGet@DB_VERSION_UNIQUE_NAME@ +#define tcl_MutLock tcl_MutLock@DB_VERSION_UNIQUE_NAME@ +#define tcl_MutSet tcl_MutSet@DB_VERSION_UNIQUE_NAME@ +#define tcl_MutStat tcl_MutStat@DB_VERSION_UNIQUE_NAME@ +#define tcl_MutStatPrint tcl_MutStatPrint@DB_VERSION_UNIQUE_NAME@ +#define tcl_MutUnlock tcl_MutUnlock@DB_VERSION_UNIQUE_NAME@ +#define tcl_RepConfig tcl_RepConfig@DB_VERSION_UNIQUE_NAME@ +#define tcl_RepGetTwo tcl_RepGetTwo@DB_VERSION_UNIQUE_NAME@ +#define tcl_RepGetConfig tcl_RepGetConfig@DB_VERSION_UNIQUE_NAME@ +#define tcl_RepGetTimeout tcl_RepGetTimeout@DB_VERSION_UNIQUE_NAME@ +#define tcl_RepGetAckPolicy tcl_RepGetAckPolicy@DB_VERSION_UNIQUE_NAME@ +#define tcl_RepGetLocalSite tcl_RepGetLocalSite@DB_VERSION_UNIQUE_NAME@ +#define tcl_RepElect tcl_RepElect@DB_VERSION_UNIQUE_NAME@ +#define tcl_RepFlush tcl_RepFlush@DB_VERSION_UNIQUE_NAME@ +#define tcl_RepSync tcl_RepSync@DB_VERSION_UNIQUE_NAME@ +#define tcl_RepLease tcl_RepLease@DB_VERSION_UNIQUE_NAME@ +#define tcl_RepInmemFiles tcl_RepInmemFiles@DB_VERSION_UNIQUE_NAME@ +#define tcl_RepLimit tcl_RepLimit@DB_VERSION_UNIQUE_NAME@ +#define tcl_RepNSites tcl_RepNSites@DB_VERSION_UNIQUE_NAME@ +#define tcl_RepRequest tcl_RepRequest@DB_VERSION_UNIQUE_NAME@ +#define tcl_RepNoarchiveTimeout tcl_RepNoarchiveTimeout@DB_VERSION_UNIQUE_NAME@ +#define tcl_RepTransport tcl_RepTransport@DB_VERSION_UNIQUE_NAME@ +#define tcl_RepStart tcl_RepStart@DB_VERSION_UNIQUE_NAME@ +#define tcl_RepProcessMessage tcl_RepProcessMessage@DB_VERSION_UNIQUE_NAME@ +#define tcl_RepStat tcl_RepStat@DB_VERSION_UNIQUE_NAME@ +#define tcl_RepStatPrint tcl_RepStatPrint@DB_VERSION_UNIQUE_NAME@ +#define tcl_RepMgr tcl_RepMgr@DB_VERSION_UNIQUE_NAME@ +#define tcl_RepMgrSiteList tcl_RepMgrSiteList@DB_VERSION_UNIQUE_NAME@ +#define tcl_RepMgrStat tcl_RepMgrStat@DB_VERSION_UNIQUE_NAME@ +#define tcl_RepMgrStatPrint tcl_RepMgrStatPrint@DB_VERSION_UNIQUE_NAME@ +#define tcl_RepApplied tcl_RepApplied@DB_VERSION_UNIQUE_NAME@ +#define seq_Cmd seq_Cmd@DB_VERSION_UNIQUE_NAME@ +#define _TxnInfoDelete _TxnInfoDelete@DB_VERSION_UNIQUE_NAME@ +#define tcl_TxnCheckpoint tcl_TxnCheckpoint@DB_VERSION_UNIQUE_NAME@ +#define tcl_Txn tcl_Txn@DB_VERSION_UNIQUE_NAME@ +#define tcl_CDSGroup tcl_CDSGroup@DB_VERSION_UNIQUE_NAME@ +#define tcl_TxnStat tcl_TxnStat@DB_VERSION_UNIQUE_NAME@ +#define tcl_TxnStatPrint tcl_TxnStatPrint@DB_VERSION_UNIQUE_NAME@ +#define tcl_TxnTimeout tcl_TxnTimeout@DB_VERSION_UNIQUE_NAME@ +#define tcl_TxnRecover tcl_TxnRecover@DB_VERSION_UNIQUE_NAME@ +#define bdb_RandCommand bdb_RandCommand@DB_VERSION_UNIQUE_NAME@ +#define tcl_LockMutex tcl_LockMutex@DB_VERSION_UNIQUE_NAME@ +#define tcl_UnlockMutex tcl_UnlockMutex@DB_VERSION_UNIQUE_NAME@ +#define __txn_begin_pp __txn_begin_pp@DB_VERSION_UNIQUE_NAME@ +#define __txn_begin __txn_begin@DB_VERSION_UNIQUE_NAME@ +#define __txn_recycle_id __txn_recycle_id@DB_VERSION_UNIQUE_NAME@ +#define __txn_continue __txn_continue@DB_VERSION_UNIQUE_NAME@ +#define __txn_commit __txn_commit@DB_VERSION_UNIQUE_NAME@ +#define __txn_abort __txn_abort@DB_VERSION_UNIQUE_NAME@ +#define __txn_discard_int __txn_discard_int@DB_VERSION_UNIQUE_NAME@ +#define __txn_prepare __txn_prepare@DB_VERSION_UNIQUE_NAME@ +#define __txn_id __txn_id@DB_VERSION_UNIQUE_NAME@ +#define __txn_get_name __txn_get_name@DB_VERSION_UNIQUE_NAME@ +#define __txn_set_name __txn_set_name@DB_VERSION_UNIQUE_NAME@ +#define __txn_get_priority __txn_get_priority@DB_VERSION_UNIQUE_NAME@ +#define __txn_set_priority __txn_set_priority@DB_VERSION_UNIQUE_NAME@ +#define __txn_set_timeout __txn_set_timeout@DB_VERSION_UNIQUE_NAME@ +#define __txn_activekids __txn_activekids@DB_VERSION_UNIQUE_NAME@ +#define __txn_force_abort __txn_force_abort@DB_VERSION_UNIQUE_NAME@ +#define __txn_preclose __txn_preclose@DB_VERSION_UNIQUE_NAME@ +#define __txn_reset __txn_reset@DB_VERSION_UNIQUE_NAME@ +#define __txn_applied_pp __txn_applied_pp@DB_VERSION_UNIQUE_NAME@ +#define __txn_regop_42_desc __txn_regop_42_desc@DB_VERSION_UNIQUE_NAME@ +#define __txn_regop_desc __txn_regop_desc@DB_VERSION_UNIQUE_NAME@ +#define __txn_ckp_42_desc __txn_ckp_42_desc@DB_VERSION_UNIQUE_NAME@ +#define __txn_ckp_desc __txn_ckp_desc@DB_VERSION_UNIQUE_NAME@ +#define __txn_child_desc __txn_child_desc@DB_VERSION_UNIQUE_NAME@ +#define __txn_xa_regop_42_desc __txn_xa_regop_42_desc@DB_VERSION_UNIQUE_NAME@ +#define __txn_prepare_desc __txn_prepare_desc@DB_VERSION_UNIQUE_NAME@ +#define __txn_recycle_desc __txn_recycle_desc@DB_VERSION_UNIQUE_NAME@ +#define __txn_init_recover __txn_init_recover@DB_VERSION_UNIQUE_NAME@ +#define __txn_regop_42_print __txn_regop_42_print@DB_VERSION_UNIQUE_NAME@ +#define __txn_regop_print __txn_regop_print@DB_VERSION_UNIQUE_NAME@ +#define __txn_ckp_42_print __txn_ckp_42_print@DB_VERSION_UNIQUE_NAME@ +#define __txn_ckp_print __txn_ckp_print@DB_VERSION_UNIQUE_NAME@ +#define __txn_child_print __txn_child_print@DB_VERSION_UNIQUE_NAME@ +#define __txn_xa_regop_42_print __txn_xa_regop_42_print@DB_VERSION_UNIQUE_NAME@ +#define __txn_prepare_print __txn_prepare_print@DB_VERSION_UNIQUE_NAME@ +#define __txn_recycle_print __txn_recycle_print@DB_VERSION_UNIQUE_NAME@ +#define __txn_init_print __txn_init_print@DB_VERSION_UNIQUE_NAME@ +#define __txn_checkpoint_pp __txn_checkpoint_pp@DB_VERSION_UNIQUE_NAME@ +#define __txn_checkpoint __txn_checkpoint@DB_VERSION_UNIQUE_NAME@ +#define __txn_getactive __txn_getactive@DB_VERSION_UNIQUE_NAME@ +#define __txn_getckp __txn_getckp@DB_VERSION_UNIQUE_NAME@ +#define __txn_updateckp __txn_updateckp@DB_VERSION_UNIQUE_NAME@ +#define __txn_failchk __txn_failchk@DB_VERSION_UNIQUE_NAME@ +#define __txn_env_create __txn_env_create@DB_VERSION_UNIQUE_NAME@ +#define __txn_env_destroy __txn_env_destroy@DB_VERSION_UNIQUE_NAME@ +#define __txn_get_tx_max __txn_get_tx_max@DB_VERSION_UNIQUE_NAME@ +#define __txn_set_tx_max __txn_set_tx_max@DB_VERSION_UNIQUE_NAME@ +#define __txn_get_tx_timestamp __txn_get_tx_timestamp@DB_VERSION_UNIQUE_NAME@ +#define __txn_set_tx_timestamp __txn_set_tx_timestamp@DB_VERSION_UNIQUE_NAME@ +#define __db_check_txn __db_check_txn@DB_VERSION_UNIQUE_NAME@ +#define __db_txn_deadlock_err __db_txn_deadlock_err@DB_VERSION_UNIQUE_NAME@ +#define __db_dbtxn_remove __db_dbtxn_remove@DB_VERSION_UNIQUE_NAME@ +#define __txn_regop_recover __txn_regop_recover@DB_VERSION_UNIQUE_NAME@ +#define __txn_prepare_recover __txn_prepare_recover@DB_VERSION_UNIQUE_NAME@ +#define __txn_ckp_recover __txn_ckp_recover@DB_VERSION_UNIQUE_NAME@ +#define __txn_child_recover __txn_child_recover@DB_VERSION_UNIQUE_NAME@ +#define __txn_restore_txn __txn_restore_txn@DB_VERSION_UNIQUE_NAME@ +#define __txn_recycle_recover __txn_recycle_recover@DB_VERSION_UNIQUE_NAME@ +#define __txn_regop_42_recover __txn_regop_42_recover@DB_VERSION_UNIQUE_NAME@ +#define __txn_ckp_42_recover __txn_ckp_42_recover@DB_VERSION_UNIQUE_NAME@ +#define __txn_recover_pp __txn_recover_pp@DB_VERSION_UNIQUE_NAME@ +#define __txn_recover __txn_recover@DB_VERSION_UNIQUE_NAME@ +#define __txn_get_prepared __txn_get_prepared@DB_VERSION_UNIQUE_NAME@ +#define __txn_openfiles __txn_openfiles@DB_VERSION_UNIQUE_NAME@ +#define __txn_open __txn_open@DB_VERSION_UNIQUE_NAME@ +#define __txn_findlastckp __txn_findlastckp@DB_VERSION_UNIQUE_NAME@ +#define __txn_env_refresh __txn_env_refresh@DB_VERSION_UNIQUE_NAME@ +#define __txn_region_mutex_count __txn_region_mutex_count@DB_VERSION_UNIQUE_NAME@ +#define __txn_region_mutex_max __txn_region_mutex_max@DB_VERSION_UNIQUE_NAME@ +#define __txn_region_size __txn_region_size@DB_VERSION_UNIQUE_NAME@ +#define __txn_region_max __txn_region_max@DB_VERSION_UNIQUE_NAME@ +#define __txn_id_set __txn_id_set@DB_VERSION_UNIQUE_NAME@ +#define __txn_oldest_reader __txn_oldest_reader@DB_VERSION_UNIQUE_NAME@ +#define __txn_add_buffer __txn_add_buffer@DB_VERSION_UNIQUE_NAME@ +#define __txn_remove_buffer __txn_remove_buffer@DB_VERSION_UNIQUE_NAME@ +#define __txn_stat_pp __txn_stat_pp@DB_VERSION_UNIQUE_NAME@ +#define __txn_stat_print_pp __txn_stat_print_pp@DB_VERSION_UNIQUE_NAME@ +#define __txn_stat_print __txn_stat_print@DB_VERSION_UNIQUE_NAME@ +#define __txn_closeevent __txn_closeevent@DB_VERSION_UNIQUE_NAME@ +#define __txn_remevent __txn_remevent@DB_VERSION_UNIQUE_NAME@ +#define __txn_remrem __txn_remrem@DB_VERSION_UNIQUE_NAME@ +#define __txn_lockevent __txn_lockevent@DB_VERSION_UNIQUE_NAME@ +#define __txn_remlock __txn_remlock@DB_VERSION_UNIQUE_NAME@ +#define __txn_doevents __txn_doevents@DB_VERSION_UNIQUE_NAME@ +#define __txn_record_fname __txn_record_fname@DB_VERSION_UNIQUE_NAME@ +#define __txn_dref_fname __txn_dref_fname@DB_VERSION_UNIQUE_NAME@ +#define __txn_reset_fe_watermarks __txn_reset_fe_watermarks@DB_VERSION_UNIQUE_NAME@ +#define __txn_remove_fe_watermark __txn_remove_fe_watermark@DB_VERSION_UNIQUE_NAME@ +#define __txn_add_fe_watermark __txn_add_fe_watermark@DB_VERSION_UNIQUE_NAME@ +#define __txn_flush_fe_files __txn_flush_fe_files@DB_VERSION_UNIQUE_NAME@ +#define __txn_pg_above_fe_watermark __txn_pg_above_fe_watermark@DB_VERSION_UNIQUE_NAME@ +#define __db_rmid_to_env __db_rmid_to_env@DB_VERSION_UNIQUE_NAME@ +#define __db_xid_to_txn __db_xid_to_txn@DB_VERSION_UNIQUE_NAME@ +#define __db_map_rmid __db_map_rmid@DB_VERSION_UNIQUE_NAME@ +#define __db_unmap_rmid __db_unmap_rmid@DB_VERSION_UNIQUE_NAME@ +#define __db_unmap_xid __db_unmap_xid@DB_VERSION_UNIQUE_NAME@ +#define __db_global_values __db_global_values@DB_VERSION_UNIQUE_NAME@ +#define __repmgr_guesstimated_max __repmgr_guesstimated_max@DB_VERSION_UNIQUE_NAME@ +#define db_xa_switch db_xa_switch@DB_VERSION_UNIQUE_NAME@ + +#endif /* !_DB_INT_DEF_IN_ */ diff -r 000000000000 -r a1985f14b030 src/dbinc_auto/lock_ext.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/dbinc_auto/lock_ext.h Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,107 @@ +/* DO NOT EDIT: automatically built by dist/s_include. + * + * Copyright (c) 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ +#ifndef _lock_ext_h_ +#define _lock_ext_h_ + +#if defined(__cplusplus) +extern "C" { +#endif + +int __db_lget __P((DBC *, int, db_pgno_t, db_lockmode_t, u_int32_t, DB_LOCK *)); +int __db_lput __P((DBC *, DB_LOCK *)); +int __db_lprint __P((DBC *)); +int __lock_vec_pp __P((DB_ENV *, u_int32_t, u_int32_t, DB_LOCKREQ *, int, DB_LOCKREQ **)); +int __lock_vec __P((ENV *, DB_LOCKER *, u_int32_t, DB_LOCKREQ *, int, DB_LOCKREQ **)); +int __lock_get_pp __P((DB_ENV *, u_int32_t, u_int32_t, DBT *, db_lockmode_t, DB_LOCK *)); +int __lock_get __P((ENV *, DB_LOCKER *, u_int32_t, const DBT *, db_lockmode_t, DB_LOCK *)); +int __lock_get_internal __P((DB_LOCKTAB *, DB_LOCKER *, u_int32_t, const DBT *, db_lockmode_t, db_timeout_t, DB_LOCK *)); +int __lock_put_pp __P((DB_ENV *, DB_LOCK *)); +int __lock_put __P((ENV *, DB_LOCK *)); +int __lock_downgrade __P((ENV *, DB_LOCK *, db_lockmode_t, u_int32_t)); +int __lock_locker_same_family __P((ENV *, DB_LOCKER *, DB_LOCKER *, int *)); +int __lock_wakeup __P((ENV *, const DBT *)); +int __lock_promote __P((DB_LOCKTAB *, DB_LOCKOBJ *, int *, u_int32_t)); +int __lock_change __P((ENV *, DB_LOCK *, DB_LOCK *)); +int __lock_detect_pp __P((DB_ENV *, u_int32_t, u_int32_t, int *)); +int __lock_detect __P((ENV *, u_int32_t, int *)); +int __lock_failchk __P((ENV *)); +int __lock_id_pp __P((DB_ENV *, u_int32_t *)); +int __lock_id __P((ENV *, u_int32_t *, DB_LOCKER **)); +void __lock_set_thread_id __P((void *, pid_t, db_threadid_t)); +int __lock_id_free_pp __P((DB_ENV *, u_int32_t)); +int __lock_id_free __P((ENV *, DB_LOCKER *)); +int __lock_id_set __P((ENV *, u_int32_t, u_int32_t)); +int __lock_getlocker __P((DB_LOCKTAB *, u_int32_t, int, DB_LOCKER **)); +int __lock_getlocker_int __P((DB_LOCKTAB *, u_int32_t, int, DB_LOCKER **)); +int __lock_addfamilylocker __P((ENV *, u_int32_t, u_int32_t, u_int32_t)); +int __lock_freelocker __P((DB_LOCKTAB *, DB_LOCKER *)); +int __lock_familyremove __P((DB_LOCKTAB *, DB_LOCKER *)); +int __lock_fix_list __P((ENV *, DBT *, u_int32_t)); +int __lock_get_list __P((ENV *, DB_LOCKER *, u_int32_t, db_lockmode_t, DBT *)); +void __lock_list_print __P((ENV *, DB_MSGBUF *, DBT *)); +int __lock_env_create __P((DB_ENV *)); +void __lock_env_destroy __P((DB_ENV *)); +int __lock_get_lk_conflicts __P((DB_ENV *, const u_int8_t **, int *)); +int __lock_set_lk_conflicts __P((DB_ENV *, u_int8_t *, int)); +int __lock_get_lk_detect __P((DB_ENV *, u_int32_t *)); +int __lock_set_lk_detect __P((DB_ENV *, u_int32_t)); +int __lock_get_lk_max_locks __P((DB_ENV *, u_int32_t *)); +int __lock_set_lk_max_locks __P((DB_ENV *, u_int32_t)); +int __lock_get_lk_max_lockers __P((DB_ENV *, u_int32_t *)); +int __lock_set_lk_max_lockers __P((DB_ENV *, u_int32_t)); +int __lock_get_lk_max_objects __P((DB_ENV *, u_int32_t *)); +int __lock_set_lk_max_objects __P((DB_ENV *, u_int32_t)); +int __lock_get_lk_partitions __P((DB_ENV *, u_int32_t *)); +int __lock_set_lk_partitions __P((DB_ENV *, u_int32_t)); +int __lock_get_lk_tablesize __P((DB_ENV *, u_int32_t *)); +int __lock_set_lk_tablesize __P((DB_ENV *, u_int32_t)); +int __lock_set_lk_priority __P((DB_ENV *, u_int32_t, u_int32_t)); +int __lock_get_lk_priority __P((DB_ENV *, u_int32_t, u_int32_t *)); +int __lock_get_env_timeout __P((DB_ENV *, db_timeout_t *, u_int32_t)); +int __lock_set_env_timeout __P((DB_ENV *, db_timeout_t, u_int32_t)); +int __lock_open __P((ENV *)); +int __lock_env_refresh __P((ENV *)); +u_int32_t __lock_region_mutex_count __P((ENV *)); +u_int32_t __lock_region_mutex_max __P((ENV *)); +size_t __lock_region_max __P((ENV *)); +size_t __lock_region_size __P((ENV *, size_t)); +int __lock_stat_pp __P((DB_ENV *, DB_LOCK_STAT **, u_int32_t)); +int __lock_stat_print_pp __P((DB_ENV *, u_int32_t)); +int __lock_stat_print __P((ENV *, u_int32_t)); +void __lock_printlock __P((DB_LOCKTAB *, DB_MSGBUF *mbp, struct __db_lock *, int)); +int __lock_set_timeout __P((ENV *, DB_LOCKER *, db_timeout_t, u_int32_t)); +int __lock_set_timeout_internal __P((ENV *, DB_LOCKER *, db_timeout_t, u_int32_t)); +int __lock_inherit_timeout __P((ENV *, DB_LOCKER *, DB_LOCKER *)); +u_int32_t __lock_ohash __P((const DBT *)); +u_int32_t __lock_lhash __P((DB_LOCKOBJ *)); +int __lock_nomem __P((ENV *, const char *)); + +#if defined(__cplusplus) +} +#endif +#endif /* !_lock_ext_h_ */ diff -r 000000000000 -r a1985f14b030 src/dbinc_auto/log_ext.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/dbinc_auto/log_ext.h Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,234 @@ +/* DO NOT EDIT: automatically built by dist/s_include. + * + * Copyright (c) 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ +#ifndef _log_ext_h_ +#define _log_ext_h_ + +#if defined(__cplusplus) +extern "C" { +#endif + +int __log_open __P((ENV *)); +int __log_find __P((DB_LOG *, int, u_int32_t *, logfile_validity *)); +int __log_valid __P((DB_LOG *, u_int32_t, int, DB_FH **, u_int32_t, logfile_validity *, u_int32_t *)); +int __log_env_refresh __P((ENV *)); +int __log_get_cached_ckp_lsn __P((ENV *, DB_LSN *)); +u_int32_t __log_region_mutex_count __P((ENV *)); +u_int32_t __log_region_mutex_max __P((ENV *)); +size_t __log_region_size __P((ENV *)); +size_t __log_region_max __P((ENV *)); +int __log_vtruncate __P((ENV *, DB_LSN *, DB_LSN *, DB_LSN *)); +int __log_is_outdated __P((ENV *, u_int32_t, int *)); +int __log_zero __P((ENV *, DB_LSN *)); +int __log_inmem_lsnoff __P((DB_LOG *, DB_LSN *, size_t *)); +int __log_inmem_newfile __P((DB_LOG *, u_int32_t)); +int __log_inmem_chkspace __P((DB_LOG *, size_t)); +void __log_inmem_copyout __P((DB_LOG *, size_t, void *, size_t)); +void __log_inmem_copyin __P((DB_LOG *, size_t, void *, size_t)); +void __log_set_version __P((ENV *, u_int32_t)); +int __log_get_oldversion __P((ENV *, u_int32_t *)); +int __log_archive_pp __P((DB_ENV *, char **[], u_int32_t)); +int __log_archive __P((ENV *, char **[], u_int32_t)); +int __log_get_stable_lsn __P((ENV *, DB_LSN *, int)); +void __log_autoremove __P((ENV *)); +int __log_check_page_lsn __P((ENV *, DB *, DB_LSN *)); +int __log_printf_capi __P((DB_ENV *, DB_TXN *, const char *, ...)) __attribute__ ((__format__ (__printf__, 3, 4))); +int __log_printf_pp __P((DB_ENV *, DB_TXN *, const char *, va_list)); +int __log_printf __P((ENV *, DB_TXN *, const char *, ...)) __attribute__ ((__format__ (__printf__, 3, 4))); +int __log_cursor_pp __P((DB_ENV *, DB_LOGC **, u_int32_t)); +int __log_cursor __P((ENV *, DB_LOGC **)); +int __logc_close __P((DB_LOGC *)); +int __logc_version __P((DB_LOGC *, u_int32_t *)); +int __logc_get __P((DB_LOGC *, DB_LSN *, DBT *, u_int32_t)); +void __log_hdrswap __P((HDR *, int)); +void __log_persistswap __P((LOGP *)); +int __log_read_record_pp __P((DB_ENV *, DB **, void *, void *, DB_LOG_RECSPEC *, u_int32_t, void **)); +int __log_read_record __P((ENV *, DB **, void *, void *, DB_LOG_RECSPEC *, u_int32_t, void **)); +int __log_env_create __P((DB_ENV *)); +void __log_env_destroy __P((DB_ENV *)); +int __log_get_lg_bsize __P((DB_ENV *, u_int32_t *)); +int __log_set_lg_bsize __P((DB_ENV *, u_int32_t)); +int __log_get_lg_filemode __P((DB_ENV *, int *)); +int __log_set_lg_filemode __P((DB_ENV *, int)); +int __log_get_lg_max __P((DB_ENV *, u_int32_t *)); +int __log_set_lg_max __P((DB_ENV *, u_int32_t)); +int __log_get_lg_regionmax __P((DB_ENV *, u_int32_t *)); +int __log_set_lg_regionmax __P((DB_ENV *, u_int32_t)); +int __log_get_lg_dir __P((DB_ENV *, const char **)); +int __log_set_lg_dir __P((DB_ENV *, const char *)); +void __log_get_flags __P((DB_ENV *, u_int32_t *)); +void __log_set_flags __P((ENV *, u_int32_t, int)); +int __log_get_config __P((DB_ENV *, u_int32_t, int *)); +int __log_set_config __P((DB_ENV *, u_int32_t, int)); +int __log_set_config_int __P((DB_ENV *, u_int32_t, int, int)); +int __log_check_sizes __P((ENV *, u_int32_t, u_int32_t)); +int __log_print_record __P((ENV *, DBT *, DB_LSN *, char *, DB_LOG_RECSPEC *, void *)); +int __log_put_pp __P((DB_ENV *, DB_LSN *, const DBT *, u_int32_t)); +int __log_put __P((ENV *, DB_LSN *, const DBT *, u_int32_t)); +int __log_current_lsn_int __P((ENV *, DB_LSN *, u_int32_t *, u_int32_t *)); +int __log_current_lsn __P((ENV *, DB_LSN *, u_int32_t *, u_int32_t *)); +int __log_newfile __P((DB_LOG *, DB_LSN *, u_int32_t, u_int32_t)); +int __log_flush_pp __P((DB_ENV *, const DB_LSN *)); +int __log_flush __P((ENV *, const DB_LSN *)); +int __log_flush_int __P((DB_LOG *, const DB_LSN *, int)); +int __log_file_pp __P((DB_ENV *, const DB_LSN *, char *, size_t)); +int __log_name __P((DB_LOG *, u_int32_t, char **, DB_FH **, u_int32_t)); +int __log_rep_put __P((ENV *, DB_LSN *, const DBT *, u_int32_t)); +int __log_put_record_pp __P((DB_ENV *, DB *, DB_TXN *, DB_LSN *, u_int32_t, u_int32_t, u_int32_t, u_int32_t, DB_LOG_RECSPEC *, ...)); +int __log_put_record __P((ENV *, DB *, DB_TXN *, DB_LSN *, u_int32_t, u_int32_t, u_int32_t, u_int32_t, DB_LOG_RECSPEC *, ...)); +int __log_stat_pp __P((DB_ENV *, DB_LOG_STAT **, u_int32_t)); +int __log_stat_print_pp __P((DB_ENV *, u_int32_t)); +int __log_stat_print __P((ENV *, u_int32_t)); +int __log_verify_pp __P((DB_ENV *, const DB_LOG_VERIFY_CONFIG *)); +int __log_verify __P((DB_ENV *, const DB_LOG_VERIFY_CONFIG *, DB_THREAD_INFO *)); +int __log_verify_wrap __P((ENV *, const char *, u_int32_t, const char *, const char *, time_t, time_t, u_int32_t, u_int32_t, u_int32_t, u_int32_t, int, int)); +int __crdel_init_verify __P((ENV *, DB_DISTAB *)); +int __db_init_verify __P((ENV *, DB_DISTAB *)); +int __dbreg_init_verify __P((ENV *, DB_DISTAB *)); +int __bam_init_verify __P((ENV *, DB_DISTAB *)); +int __fop_init_verify __P((ENV *, DB_DISTAB *)); +int __ham_init_verify __P((ENV *, DB_DISTAB *)); +int __heap_init_verify __P((ENV *, DB_DISTAB *)); +int __qam_init_verify __P((ENV *, DB_DISTAB *)); +int __txn_init_verify __P((ENV *, DB_DISTAB *)); +void __db_log_verify_global_report __P((const DB_LOG_VRFY_INFO *)); +int __crdel_metasub_verify __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __crdel_inmem_create_verify __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __crdel_inmem_rename_verify __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __crdel_inmem_remove_verify __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __db_addrem_verify __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __db_big_verify __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __db_ovref_verify __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __db_relink_42_verify __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __db_debug_verify __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __db_noop_verify __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __db_pg_alloc_42_verify __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __db_pg_alloc_verify __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __db_pg_free_42_verify __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __db_pg_free_verify __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __db_cksum_verify __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __db_pg_freedata_42_verify __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __db_pg_freedata_verify __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __db_pg_init_verify __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __db_pg_sort_44_verify __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __db_pg_trunc_verify __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __db_realloc_verify __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __db_relink_verify __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __db_merge_verify __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __db_pgno_verify __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __dbreg_register_verify __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __bam_split_verify __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __bam_split_42_verify __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __bam_rsplit_verify __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __bam_adj_verify __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __bam_irep_verify __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __bam_cadjust_verify __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __bam_cdel_verify __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __bam_repl_verify __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __bam_root_verify __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __bam_curadj_verify __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __bam_rcuradj_verify __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __bam_relink_43_verify __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __bam_merge_44_verify __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __fop_create_42_verify __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __fop_create_verify __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __fop_remove_verify __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __fop_write_42_verify __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __fop_write_verify __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __fop_rename_42_verify __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __fop_rename_verify __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __fop_file_remove_verify __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __ham_insdel_verify __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __ham_newpage_verify __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __ham_splitdata_verify __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __ham_replace_verify __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __ham_copypage_verify __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __ham_metagroup_42_verify __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __ham_metagroup_verify __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __ham_groupalloc_42_verify __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __ham_groupalloc_verify __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __ham_changeslot_verify __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __ham_contract_verify __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __ham_curadj_verify __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __ham_chgpg_verify __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __heap_addrem_verify __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __heap_pg_alloc_verify __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __heap_trunc_meta_verify __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __heap_trunc_page_verify __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __qam_incfirst_verify __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __qam_mvptr_verify __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __qam_del_verify __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __qam_add_verify __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __qam_delext_verify __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __txn_regop_42_verify __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __txn_regop_verify __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __txn_ckp_42_verify __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __txn_ckp_verify __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __txn_child_verify __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __txn_xa_regop_42_verify __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __txn_prepare_verify __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __txn_recycle_verify __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __create_log_vrfy_info __P((const DB_LOG_VERIFY_CONFIG *, DB_LOG_VRFY_INFO **, DB_THREAD_INFO *)); +int __destroy_log_vrfy_info __P((DB_LOG_VRFY_INFO *)); +int __put_txn_vrfy_info __P((const DB_LOG_VRFY_INFO *, const VRFY_TXN_INFO *)); +int __get_txn_vrfy_info __P((const DB_LOG_VRFY_INFO *, u_int32_t, VRFY_TXN_INFO **)); +int __add_recycle_lsn_range __P((DB_LOG_VRFY_INFO *, const DB_LSN *, u_int32_t, u_int32_t)); +int __iterate_txninfo __P((DB_LOG_VRFY_INFO *, u_int32_t, u_int32_t, TXNINFO_HANDLER, void *)); +int __rem_last_recycle_lsn __P((VRFY_TXN_INFO *)); +int __add_file_updated __P((VRFY_TXN_INFO *, const DBT *, int32_t)); +int __del_file_updated __P((VRFY_TXN_INFO *, const DBT *)); +int __clear_fileups __P((VRFY_TXN_INFO *)); +int __free_txninfo_stack __P((VRFY_TXN_INFO *)); +int __free_txninfo __P((VRFY_TXN_INFO *)); +int __put_filereg_info __P((const DB_LOG_VRFY_INFO *, const VRFY_FILEREG_INFO *)); +int __del_filelife __P((const DB_LOG_VRFY_INFO *, int32_t)); +int __put_filelife __P((const DB_LOG_VRFY_INFO *, VRFY_FILELIFE *)); +int __get_filelife __P((const DB_LOG_VRFY_INFO *, int32_t, VRFY_FILELIFE **)); +int __get_filereg_by_dbregid __P((const DB_LOG_VRFY_INFO *, int32_t, VRFY_FILEREG_INFO **)); +int __add_dbregid __P((DB_LOG_VRFY_INFO *, VRFY_FILEREG_INFO *, int32_t, u_int32_t, DB_LSN, DBTYPE, db_pgno_t, int *)); +int __get_filereg_info __P((const DB_LOG_VRFY_INFO *, const DBT *, VRFY_FILEREG_INFO **)); +int __free_filereg_info __P((VRFY_FILEREG_INFO *)); +int __get_ckp_info __P((const DB_LOG_VRFY_INFO *, DB_LSN, VRFY_CKP_INFO **)); +int __get_last_ckp_info __P((const DB_LOG_VRFY_INFO *, VRFY_CKP_INFO **)); +int __put_ckp_info __P((const DB_LOG_VRFY_INFO *, const VRFY_CKP_INFO *)); +int __get_timestamp_info __P((const DB_LOG_VRFY_INFO *, DB_LSN, VRFY_TIMESTAMP_INFO **)); +int __get_latest_timestamp_info __P((const DB_LOG_VRFY_INFO *, DB_LSN, VRFY_TIMESTAMP_INFO **)); +int __put_timestamp_info __P((const DB_LOG_VRFY_INFO *, const VRFY_TIMESTAMP_INFO *)); +int __find_lsnrg_by_timerg __P((DB_LOG_VRFY_INFO *, time_t, time_t, DB_LSN *, DB_LSN *)); +int __add_txnrange __P((DB_LOG_VRFY_INFO *, u_int32_t, DB_LSN, int32_t, int)); +int __get_aborttxn __P((DB_LOG_VRFY_INFO *, DB_LSN)); +int __txn_started __P((DB_LOG_VRFY_INFO *, DB_LSN, u_int32_t, int *)); +int __set_logvrfy_dbfuid __P((DB_LOG_VRFY_INFO *)); +int __add_page_to_txn __P((DB_LOG_VRFY_INFO *, int32_t, db_pgno_t, u_int32_t, u_int32_t *, int *)); +int __del_txn_pages __P((DB_LOG_VRFY_INFO *, u_int32_t)); +int __is_ancestor_txn __P((DB_LOG_VRFY_INFO *, u_int32_t, u_int32_t, DB_LSN, int *)); +int __return_txn_pages __P((DB_LOG_VRFY_INFO *, u_int32_t, u_int32_t)); + +#if defined(__cplusplus) +} +#endif +#endif /* !_log_ext_h_ */ diff -r 000000000000 -r a1985f14b030 src/dbinc_auto/mp_ext.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/dbinc_auto/mp_ext.h Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,132 @@ +/* DO NOT EDIT: automatically built by dist/s_include. + * + * Copyright (c) 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ +#ifndef _mp_ext_h_ +#define _mp_ext_h_ + +#if defined(__cplusplus) +extern "C" { +#endif + +int __memp_alloc __P((DB_MPOOL *, REGINFO *, MPOOLFILE *, size_t, roff_t *, void *)); +void __memp_free __P((REGINFO *, void *)); +int __memp_backup_open __P((ENV *, DB_MPOOLFILE *, const char *, const char *, u_int32_t, DB_FH **, void**)); +int __memp_backup_mpf __P((ENV *, DB_MPOOLFILE *, DB_THREAD_INFO *, db_pgno_t, db_pgno_t, DB_FH *, void *, u_int32_t)); +int __memp_backup_close __P((ENV *, DB_MPOOLFILE *, const char *, DB_FH *, void *HANDLE)); +int __memp_failchk __P((ENV *)); +int __memp_bhwrite __P((DB_MPOOL *, DB_MPOOL_HASH *, MPOOLFILE *, BH *, int)); +int __memp_pgread __P((DB_MPOOLFILE *, BH *, int)); +int __memp_pg __P((DB_MPOOLFILE *, db_pgno_t, void *, int)); +int __memp_bhfree __P((DB_MPOOL *, REGINFO *, MPOOLFILE *, DB_MPOOL_HASH *, BH *, u_int32_t)); +int __memp_fget_pp __P((DB_MPOOLFILE *, db_pgno_t *, DB_TXN *, u_int32_t, void *)); +int __memp_fget __P((DB_MPOOLFILE *, db_pgno_t *, DB_THREAD_INFO *, DB_TXN *, u_int32_t, void *)); +int __memp_fcreate_pp __P((DB_ENV *, DB_MPOOLFILE **, u_int32_t)); +int __memp_fcreate __P((ENV *, DB_MPOOLFILE **)); +int __memp_set_clear_len __P((DB_MPOOLFILE *, u_int32_t)); +int __memp_get_fileid __P((DB_MPOOLFILE *, u_int8_t *)); +int __memp_set_fileid __P((DB_MPOOLFILE *, u_int8_t *)); +int __memp_get_flags __P((DB_MPOOLFILE *, u_int32_t *)); +int __memp_set_flags __P((DB_MPOOLFILE *, u_int32_t, int)); +int __memp_get_ftype __P((DB_MPOOLFILE *, int *)); +int __memp_set_ftype __P((DB_MPOOLFILE *, int)); +int __memp_set_lsn_offset __P((DB_MPOOLFILE *, int32_t)); +int __memp_get_pgcookie __P((DB_MPOOLFILE *, DBT *)); +int __memp_set_pgcookie __P((DB_MPOOLFILE *, DBT *)); +int __memp_get_priority __P((DB_MPOOLFILE *, DB_CACHE_PRIORITY *)); +int __memp_get_last_pgno __P((DB_MPOOLFILE *, db_pgno_t *)); +char * __memp_fn __P((DB_MPOOLFILE *)); +char * __memp_fns __P((DB_MPOOL *, MPOOLFILE *)); +int __memp_fopen_pp __P((DB_MPOOLFILE *, const char *, u_int32_t, int, size_t)); +int __memp_fopen __P((DB_MPOOLFILE *, MPOOLFILE *, const char *, const char **, u_int32_t, int, size_t)); +int __memp_fclose_pp __P((DB_MPOOLFILE *, u_int32_t)); +int __memp_fclose __P((DB_MPOOLFILE *, u_int32_t)); +int __memp_mf_discard __P((DB_MPOOL *, MPOOLFILE *, int)); +int __memp_inmemlist __P((ENV *, char ***, int *)); +int __memp_fput_pp __P((DB_MPOOLFILE *, void *, DB_CACHE_PRIORITY, u_int32_t)); +int __memp_fput __P((DB_MPOOLFILE *, DB_THREAD_INFO *, void *, DB_CACHE_PRIORITY)); +int __memp_unpin_buffers __P((ENV *, DB_THREAD_INFO *)); +int __memp_dirty __P((DB_MPOOLFILE *, void *, DB_THREAD_INFO *, DB_TXN *, DB_CACHE_PRIORITY, u_int32_t)); +int __memp_shared __P((DB_MPOOLFILE *, void *)); +int __memp_env_create __P((DB_ENV *)); +void __memp_env_destroy __P((DB_ENV *)); +int __memp_get_cachesize __P((DB_ENV *, u_int32_t *, u_int32_t *, int *)); +int __memp_set_cachesize __P((DB_ENV *, u_int32_t, u_int32_t, int)); +int __memp_set_config __P((DB_ENV *, u_int32_t, int)); +int __memp_get_config __P((DB_ENV *, u_int32_t, int *)); +int __memp_get_mp_max_openfd __P((DB_ENV *, int *)); +int __memp_set_mp_max_openfd __P((DB_ENV *, int)); +int __memp_get_mp_max_write __P((DB_ENV *, int *, db_timeout_t *)); +int __memp_set_mp_max_write __P((DB_ENV *, int, db_timeout_t)); +int __memp_get_mp_mmapsize __P((DB_ENV *, size_t *)); +int __memp_set_mp_mmapsize __P((DB_ENV *, size_t)); +int __memp_get_mp_pagesize __P((DB_ENV *, u_int32_t *)); +int __memp_set_mp_pagesize __P((DB_ENV *, u_int32_t)); +int __memp_get_mp_tablesize __P((DB_ENV *, u_int32_t *)); +int __memp_set_mp_tablesize __P((DB_ENV *, u_int32_t)); +int __memp_get_mp_mtxcount __P((DB_ENV *, u_int32_t *)); +int __memp_set_mp_mtxcount __P((DB_ENV *, u_int32_t)); +int __memp_nameop __P((ENV *, u_int8_t *, const char *, const char *, const char *, int)); +int __memp_ftruncate __P((DB_MPOOLFILE *, DB_TXN *, DB_THREAD_INFO *, db_pgno_t, u_int32_t)); +int __memp_alloc_freelist __P((DB_MPOOLFILE *, u_int32_t, db_pgno_t **)); +int __memp_free_freelist __P((DB_MPOOLFILE *)); +int __memp_get_freelist __P(( DB_MPOOLFILE *, u_int32_t *, db_pgno_t **)); +int __memp_extend_freelist __P(( DB_MPOOLFILE *, u_int32_t , db_pgno_t **)); +int __memp_set_last_pgno __P((DB_MPOOLFILE *, db_pgno_t)); +int __memp_bh_settxn __P((DB_MPOOL *, MPOOLFILE *mfp, BH *, void *)); +int __memp_skip_curadj __P((DBC *, db_pgno_t)); +int __memp_bh_freeze __P((DB_MPOOL *, REGINFO *, DB_MPOOL_HASH *, BH *, int *)); +int __memp_bh_thaw __P((DB_MPOOL *, REGINFO *, DB_MPOOL_HASH *, BH *, BH *)); +int __memp_open __P((ENV *, int)); +int __memp_init __P((ENV *, DB_MPOOL *, u_int, u_int32_t, u_int)); +u_int32_t __memp_max_regions __P((ENV *)); +u_int32_t __memp_region_mutex_count __P((ENV *)); +int __memp_env_refresh __P((ENV *)); +int __memp_register_pp __P((DB_ENV *, int, int (*)(DB_ENV *, db_pgno_t, void *, DBT *), int (*)(DB_ENV *, db_pgno_t, void *, DBT *))); +int __memp_register __P((ENV *, int, int (*)(DB_ENV *, db_pgno_t, void *, DBT *), int (*)(DB_ENV *, db_pgno_t, void *, DBT *))); +int __memp_get_bucket __P((ENV *, MPOOLFILE *, db_pgno_t, REGINFO **, DB_MPOOL_HASH **, u_int32_t *)); +int __memp_resize __P((DB_MPOOL *, u_int32_t, u_int32_t)); +int __memp_get_cache_max __P((DB_ENV *, u_int32_t *, u_int32_t *)); +int __memp_set_cache_max __P((DB_ENV *, u_int32_t, u_int32_t)); +int __memp_stat_pp __P((DB_ENV *, DB_MPOOL_STAT **, DB_MPOOL_FSTAT ***, u_int32_t)); +int __memp_stat_print_pp __P((DB_ENV *, u_int32_t)); +int __memp_stat_print __P((ENV *, u_int32_t)); +void __memp_stat_hash __P((REGINFO *, MPOOL *, u_int32_t *)); +int __memp_walk_files __P((ENV *, MPOOL *, int (*) __P((ENV *, MPOOLFILE *, void *, u_int32_t *, u_int32_t)), void *, u_int32_t *, u_int32_t)); +int __memp_discard_all_mpfs __P((ENV *, MPOOL *)); +int __memp_sync_pp __P((DB_ENV *, DB_LSN *)); +int __memp_sync __P((ENV *, u_int32_t, DB_LSN *)); +int __memp_fsync_pp __P((DB_MPOOLFILE *)); +int __memp_fsync __P((DB_MPOOLFILE *)); +int __mp_xxx_fh __P((DB_MPOOLFILE *, DB_FH **)); +int __memp_sync_int __P((ENV *, DB_MPOOLFILE *, u_int32_t, u_int32_t, u_int32_t *, int *)); +int __memp_mf_sync __P((DB_MPOOL *, MPOOLFILE *, int)); +int __memp_trickle_pp __P((DB_ENV *, int, int *)); + +#if defined(__cplusplus) +} +#endif +#endif /* !_mp_ext_h_ */ diff -r 000000000000 -r a1985f14b030 src/dbinc_auto/mutex_ext.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/dbinc_auto/mutex_ext.h Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,117 @@ +/* DO NOT EDIT: automatically built by dist/s_include. + * + * Copyright (c) 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ +#ifndef _mutex_ext_h_ +#define _mutex_ext_h_ + +#if defined(__cplusplus) +extern "C" { +#endif + +int __mutex_alloc __P((ENV *, int, u_int32_t, db_mutex_t *)); +int __mutex_alloc_int __P((ENV *, int, int, u_int32_t, db_mutex_t *)); +int __mutex_free __P((ENV *, db_mutex_t *)); +int __mutex_free_int __P((ENV *, int, db_mutex_t *)); +int __mutex_refresh __P((ENV *, db_mutex_t)); +int __mut_failchk __P((ENV *)); +int __db_fcntl_mutex_init __P((ENV *, db_mutex_t, u_int32_t)); +int __db_fcntl_mutex_lock __P((ENV *, db_mutex_t, db_timeout_t)); +int __db_fcntl_mutex_trylock __P((ENV *, db_mutex_t)); +int __db_fcntl_mutex_unlock __P((ENV *, db_mutex_t)); +int __db_fcntl_mutex_destroy __P((ENV *, db_mutex_t)); +int __mutex_alloc_pp __P((DB_ENV *, u_int32_t, db_mutex_t *)); +int __mutex_free_pp __P((DB_ENV *, db_mutex_t)); +int __mutex_lock_pp __P((DB_ENV *, db_mutex_t)); +int __mutex_unlock_pp __P((DB_ENV *, db_mutex_t)); +int __mutex_get_align __P((DB_ENV *, u_int32_t *)); +int __mutex_set_align __P((DB_ENV *, u_int32_t)); +int __mutex_get_increment __P((DB_ENV *, u_int32_t *)); +int __mutex_set_increment __P((DB_ENV *, u_int32_t)); +int __mutex_get_init __P((DB_ENV *, u_int32_t *)); +int __mutex_set_init __P((DB_ENV *, u_int32_t)); +int __mutex_get_max __P((DB_ENV *, u_int32_t *)); +int __mutex_set_max __P((DB_ENV *, u_int32_t)); +int __mutex_get_tas_spins __P((DB_ENV *, u_int32_t *)); +int __mutex_set_tas_spins __P((DB_ENV *, u_int32_t)); +#if !defined(HAVE_ATOMIC_SUPPORT) && defined(HAVE_MUTEX_SUPPORT) +atomic_value_t __atomic_inc __P((ENV *, db_atomic_t *)); +#endif +#if !defined(HAVE_ATOMIC_SUPPORT) && defined(HAVE_MUTEX_SUPPORT) +atomic_value_t __atomic_dec __P((ENV *, db_atomic_t *)); +#endif +#if !defined(HAVE_ATOMIC_SUPPORT) && defined(HAVE_MUTEX_SUPPORT) +int atomic_compare_exchange __P((ENV *, db_atomic_t *, atomic_value_t, atomic_value_t)); +#endif +int __db_pthread_mutex_init __P((ENV *, db_mutex_t, u_int32_t)); +#ifndef HAVE_MUTEX_HYBRID +int __db_pthread_mutex_lock __P((ENV *, db_mutex_t, db_timeout_t)); +#endif +#if defined(HAVE_SHARED_LATCHES) +int __db_pthread_mutex_readlock __P((ENV *, db_mutex_t)); +#endif +#ifdef HAVE_MUTEX_HYBRID +int __db_hybrid_mutex_suspend __P((ENV *, db_mutex_t, db_timespec *, int)); +#endif +int __db_pthread_mutex_unlock __P((ENV *, db_mutex_t)); +int __db_pthread_mutex_destroy __P((ENV *, db_mutex_t)); +int __mutex_open __P((ENV *, int)); +int __mutex_env_refresh __P((ENV *)); +void __mutex_resource_return __P((ENV *, REGINFO *)); +int __mutex_stat_pp __P((DB_ENV *, DB_MUTEX_STAT **, u_int32_t)); +int __mutex_stat_print_pp __P((DB_ENV *, u_int32_t)); +int __mutex_stat_print __P((ENV *, u_int32_t)); +void __mutex_print_debug_single __P((ENV *, const char *, db_mutex_t, u_int32_t)); +void __mutex_print_debug_stats __P((ENV *, DB_MSGBUF *, db_mutex_t, u_int32_t)); +void __mutex_set_wait_info __P((ENV *, db_mutex_t, uintmax_t *, uintmax_t *)); +void __mutex_clear __P((ENV *, db_mutex_t)); +int __db_tas_mutex_init __P((ENV *, db_mutex_t, u_int32_t)); +int __db_tas_mutex_lock __P((ENV *, db_mutex_t, db_timeout_t)); +int __db_tas_mutex_trylock __P((ENV *, db_mutex_t)); +#if defined(HAVE_SHARED_LATCHES) +int __db_tas_mutex_readlock __P((ENV *, db_mutex_t)); +#endif +#if defined(HAVE_SHARED_LATCHES) +int __db_tas_mutex_tryreadlock __P((ENV *, db_mutex_t)); +#endif +int __db_tas_mutex_unlock __P((ENV *, db_mutex_t)); +int __db_tas_mutex_destroy __P((ENV *, db_mutex_t)); +int __db_win32_mutex_init __P((ENV *, db_mutex_t, u_int32_t)); +int __db_win32_mutex_lock __P((ENV *, db_mutex_t, db_timeout_t)); +int __db_win32_mutex_trylock __P((ENV *, db_mutex_t)); +#if defined(HAVE_SHARED_LATCHES) +int __db_win32_mutex_readlock __P((ENV *, db_mutex_t)); +#endif +#if defined(HAVE_SHARED_LATCHES) +int __db_win32_mutex_tryreadlock __P((ENV *, db_mutex_t)); +#endif +int __db_win32_mutex_unlock __P((ENV *, db_mutex_t)); +int __db_win32_mutex_destroy __P((ENV *, db_mutex_t)); + +#if defined(__cplusplus) +} +#endif +#endif /* !_mutex_ext_h_ */ diff -r 000000000000 -r a1985f14b030 src/dbinc_auto/os_ext.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/dbinc_auto/os_ext.h Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,110 @@ +/* DO NOT EDIT: automatically built by dist/s_include. + * + * Copyright (c) 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ +#ifndef _os_ext_h_ +#define _os_ext_h_ + +#if defined(__cplusplus) +extern "C" { +#endif + +void __os_abort __P((ENV *)); +int __os_abspath __P((const char *)); +#if defined(HAVE_REPLICATION_THREADS) +int __os_getaddrinfo __P((ENV *, const char *, u_int, const char *, const ADDRINFO *, ADDRINFO **)); +#endif +#if defined(HAVE_REPLICATION_THREADS) +void __os_freeaddrinfo __P((ENV *, ADDRINFO *)); +#endif +int __os_umalloc __P((ENV *, size_t, void *)); +int __os_urealloc __P((ENV *, size_t, void *)); +void __os_ufree __P((ENV *, void *)); +int __os_strdup __P((ENV *, const char *, void *)); +int __os_calloc __P((ENV *, size_t, size_t, void *)); +int __os_malloc __P((ENV *, size_t, void *)); +int __os_realloc __P((ENV *, size_t, void *)); +void __os_free __P((ENV *, void *)); +void *__ua_memcpy __P((void *, const void *, size_t)); +void __os_gettime __P((ENV *, db_timespec *, int)); +int __os_fs_notzero __P((void)); +int __os_support_direct_io __P((void)); +int __os_support_db_register __P((void)); +int __os_support_replication __P((void)); +u_int32_t __os_cpu_count __P((void)); +char *__os_ctime __P((const time_t *, char *)); +int __os_dirlist __P((ENV *, const char *, int, char ***, int *)); +void __os_dirfree __P((ENV *, char **, int)); +int __os_get_errno_ret_zero __P((void)); +int __os_get_errno __P((void)); +int __os_get_neterr __P((void)); +int __os_get_syserr __P((void)); +void __os_set_errno __P((int)); +char *__os_strerror __P((int, char *, size_t)); +int __os_posix_err __P((int)); +int __os_fileid __P((ENV *, const char *, int, u_int8_t *)); +int __os_fdlock __P((ENV *, DB_FH *, off_t, int, int)); +int __os_fsync __P((ENV *, DB_FH *)); +int __os_getenv __P((ENV *, const char *, char **, size_t)); +int __os_openhandle __P((ENV *, const char *, int, int, DB_FH **)); +int __os_closehandle __P((ENV *, DB_FH *)); +int __os_attach __P((ENV *, REGINFO *, REGION *)); +int __os_detach __P((ENV *, REGINFO *, int)); +int __os_mapfile __P((ENV *, char *, DB_FH *, size_t, int, void **)); +int __os_unmapfile __P((ENV *, void *, size_t)); +int __os_mkdir __P((ENV *, const char *, int)); +int __os_open __P((ENV *, const char *, u_int32_t, u_int32_t, int, DB_FH **)); +int __os_concat_path __P((char *, size_t, const char *, const char *)); +void __os_id __P((DB_ENV *, pid_t *, db_threadid_t*)); +int __os_rename __P((ENV *, const char *, const char *, u_int32_t)); +int __os_isroot __P((void)); +char *__db_rpath __P((const char *)); +int __os_io __P((ENV *, int, DB_FH *, db_pgno_t, u_int32_t, u_int32_t, u_int32_t, u_int8_t *, size_t *)); +int __os_read __P((ENV *, DB_FH *, void *, size_t, size_t *)); +int __os_write __P((ENV *, DB_FH *, void *, size_t, size_t *)); +int __os_physwrite __P((ENV *, DB_FH *, void *, size_t, size_t *)); +int __os_seek __P((ENV *, DB_FH *, db_pgno_t, u_int32_t, off_t)); +void __os_stack __P((ENV *)); +int __os_exists __P((ENV *, const char *, int *)); +int __os_ioinfo __P((ENV *, const char *, DB_FH *, u_int32_t *, u_int32_t *, u_int32_t *)); +int __os_tmpdir __P((ENV *, u_int32_t)); +int __os_truncate __P((ENV *, DB_FH *, db_pgno_t, u_int32_t)); +void __os_unique_id __P((ENV *, u_int32_t *)); +int __os_unlink __P((ENV *, const char *, int)); +void __os_yield __P((ENV *, u_long, u_long)); +#ifdef HAVE_QNX +int __os_qnx_region_open __P((ENV *, const char *, int, int, DB_FH **)); +#endif +int __os_is_winnt __P((void)); +u_int32_t __os_cpu_count __P((void)); +#ifdef HAVE_REPLICATION_THREADS +int __os_get_neterr __P((void)); +#endif + +#if defined(__cplusplus) +} +#endif +#endif /* !_os_ext_h_ */ diff -r 000000000000 -r a1985f14b030 src/dbinc_auto/qam_auto.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/dbinc_auto/qam_auto.h Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,199 @@ +/* Do not edit: automatically built by gen_rec.awk. + * + * Copyright (c) 2012 Oracle and/or its affiliates. All rights reserved. * + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +#ifndef __qam_AUTO_H +#define __qam_AUTO_H +#ifdef HAVE_QUEUE +#include "dbinc/log.h" +#define DB___qam_incfirst 84 +typedef struct ___qam_incfirst_args { + u_int32_t type; + DB_TXN *txnp; + DB_LSN prev_lsn; + int32_t fileid; + db_recno_t recno; + db_pgno_t meta_pgno; +} __qam_incfirst_args; + +extern __DB_IMPORT DB_LOG_RECSPEC __qam_incfirst_desc[]; +static inline int +__qam_incfirst_log(DB *dbp, DB_TXN *txnp, DB_LSN *ret_lsnp, u_int32_t flags, db_recno_t recno, db_pgno_t meta_pgno) +{ + return (__log_put_record((dbp)->env, dbp, txnp, ret_lsnp, + flags, DB___qam_incfirst, 0, + sizeof(u_int32_t) + sizeof(u_int32_t) + sizeof(DB_LSN) + + sizeof(u_int32_t) + sizeof(u_int32_t) + sizeof(u_int32_t), + __qam_incfirst_desc, recno, meta_pgno)); +} + +static inline int __qam_incfirst_read(ENV *env, + DB **dbpp, void *td, void *data, __qam_incfirst_args **arg) +{ + *arg = NULL; + return (__log_read_record(env, + dbpp, td, data, __qam_incfirst_desc, sizeof(__qam_incfirst_args), (void**)arg)); +} +#define DB___qam_mvptr 85 +typedef struct ___qam_mvptr_args { + u_int32_t type; + DB_TXN *txnp; + DB_LSN prev_lsn; + u_int32_t opcode; + int32_t fileid; + db_recno_t old_first; + db_recno_t new_first; + db_recno_t old_cur; + db_recno_t new_cur; + DB_LSN metalsn; + db_pgno_t meta_pgno; +} __qam_mvptr_args; + +extern __DB_IMPORT DB_LOG_RECSPEC __qam_mvptr_desc[]; +static inline int +__qam_mvptr_log(DB *dbp, DB_TXN *txnp, DB_LSN *ret_lsnp, u_int32_t flags, + u_int32_t opcode, db_recno_t old_first, db_recno_t new_first, db_recno_t old_cur, + db_recno_t new_cur, DB_LSN * metalsn, db_pgno_t meta_pgno) +{ + return (__log_put_record((dbp)->env, dbp, txnp, ret_lsnp, + flags, DB___qam_mvptr, 0, + sizeof(u_int32_t) + sizeof(u_int32_t) + sizeof(DB_LSN) + + sizeof(u_int32_t) + sizeof(u_int32_t) + sizeof(u_int32_t) + + sizeof(u_int32_t) + sizeof(u_int32_t) + sizeof(u_int32_t) + + sizeof(*metalsn) + sizeof(u_int32_t), + __qam_mvptr_desc, + opcode, old_first, new_first, old_cur, new_cur, metalsn, meta_pgno)); +} + +static inline int __qam_mvptr_read(ENV *env, + DB **dbpp, void *td, void *data, __qam_mvptr_args **arg) +{ + *arg = NULL; + return (__log_read_record(env, + dbpp, td, data, __qam_mvptr_desc, sizeof(__qam_mvptr_args), (void**)arg)); +} +#define DB___qam_del 79 +typedef struct ___qam_del_args { + u_int32_t type; + DB_TXN *txnp; + DB_LSN prev_lsn; + int32_t fileid; + DB_LSN lsn; + db_pgno_t pgno; + u_int32_t indx; + db_recno_t recno; +} __qam_del_args; + +extern __DB_IMPORT DB_LOG_RECSPEC __qam_del_desc[]; +static inline int +__qam_del_log(DB *dbp, DB_TXN *txnp, DB_LSN *ret_lsnp, u_int32_t flags, DB_LSN * lsn, db_pgno_t pgno, u_int32_t indx, db_recno_t recno) +{ + return (__log_put_record((dbp)->env, dbp, txnp, ret_lsnp, + flags, DB___qam_del, 0, + sizeof(u_int32_t) + sizeof(u_int32_t) + sizeof(DB_LSN) + + sizeof(u_int32_t) + sizeof(*lsn) + sizeof(u_int32_t) + + sizeof(u_int32_t) + sizeof(u_int32_t), + __qam_del_desc, lsn, pgno, indx, recno)); +} + +static inline int __qam_del_read(ENV *env, + DB **dbpp, void *td, void *data, __qam_del_args **arg) +{ + *arg = NULL; + return (__log_read_record(env, + dbpp, td, data, __qam_del_desc, sizeof(__qam_del_args), (void**)arg)); +} +#define DB___qam_add 80 +typedef struct ___qam_add_args { + u_int32_t type; + DB_TXN *txnp; + DB_LSN prev_lsn; + int32_t fileid; + DB_LSN lsn; + db_pgno_t pgno; + u_int32_t indx; + db_recno_t recno; + DBT data; + u_int32_t vflag; + DBT olddata; +} __qam_add_args; + +extern __DB_IMPORT DB_LOG_RECSPEC __qam_add_desc[]; +static inline int +__qam_add_log(DB *dbp, DB_TXN *txnp, DB_LSN *ret_lsnp, u_int32_t flags, DB_LSN * lsn, db_pgno_t pgno, u_int32_t indx, db_recno_t recno, + const DBT *data, u_int32_t vflag, const DBT *olddata) +{ + return (__log_put_record((dbp)->env, dbp, txnp, ret_lsnp, + flags, DB___qam_add, 0, + sizeof(u_int32_t) + sizeof(u_int32_t) + sizeof(DB_LSN) + + sizeof(u_int32_t) + sizeof(*lsn) + sizeof(u_int32_t) + + sizeof(u_int32_t) + sizeof(u_int32_t) + LOG_DBT_SIZE(data) + + sizeof(u_int32_t) + LOG_DBT_SIZE(olddata), + __qam_add_desc, lsn, pgno, indx, recno, data, vflag, olddata)); +} + +static inline int __qam_add_read(ENV *env, + DB **dbpp, void *td, void *data, __qam_add_args **arg) +{ + *arg = NULL; + return (__log_read_record(env, + dbpp, td, data, __qam_add_desc, sizeof(__qam_add_args), (void**)arg)); +} +#define DB___qam_delext 83 +typedef struct ___qam_delext_args { + u_int32_t type; + DB_TXN *txnp; + DB_LSN prev_lsn; + int32_t fileid; + DB_LSN lsn; + db_pgno_t pgno; + u_int32_t indx; + db_recno_t recno; + DBT data; +} __qam_delext_args; + +extern __DB_IMPORT DB_LOG_RECSPEC __qam_delext_desc[]; +static inline int +__qam_delext_log(DB *dbp, DB_TXN *txnp, DB_LSN *ret_lsnp, u_int32_t flags, DB_LSN * lsn, db_pgno_t pgno, u_int32_t indx, db_recno_t recno, + const DBT *data) +{ + return (__log_put_record((dbp)->env, dbp, txnp, ret_lsnp, + flags, DB___qam_delext, 0, + sizeof(u_int32_t) + sizeof(u_int32_t) + sizeof(DB_LSN) + + sizeof(u_int32_t) + sizeof(*lsn) + sizeof(u_int32_t) + + sizeof(u_int32_t) + sizeof(u_int32_t) + LOG_DBT_SIZE(data), + __qam_delext_desc, lsn, pgno, indx, recno, data)); +} + +static inline int __qam_delext_read(ENV *env, + DB **dbpp, void *td, void *data, __qam_delext_args **arg) +{ + *arg = NULL; + return (__log_read_record(env, + dbpp, td, data, __qam_delext_desc, sizeof(__qam_delext_args), (void**)arg)); +} +#endif /* HAVE_QUEUE */ +#endif diff -r 000000000000 -r a1985f14b030 src/dbinc_auto/qam_ext.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/dbinc_auto/qam_ext.h Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,94 @@ +/* DO NOT EDIT: automatically built by dist/s_include. + * + * Copyright (c) 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ +#ifndef _qam_ext_h_ +#define _qam_ext_h_ + +#if defined(__cplusplus) +extern "C" { +#endif + +int __qam_position __P((DBC *, db_recno_t *, u_int32_t, int *)); +int __qam_pitem __P((DBC *, QPAGE *, u_int32_t, db_recno_t, DBT *)); +int __qam_append __P((DBC *, DBT *, DBT *)); +int __qamc_dup __P((DBC *, DBC *)); +int __qamc_init __P((DBC *)); +int __qam_truncate __P((DBC *, u_int32_t *)); +int __qam_delete __P((DBC *, DBT *, u_int32_t)); +int __qam_init_recover __P((ENV *, DB_DISTAB *)); +int __qam_incfirst_print __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __qam_mvptr_print __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __qam_del_print __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __qam_add_print __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __qam_delext_print __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __qam_init_print __P((ENV *, DB_DISTAB *)); +int __qam_mswap __P((ENV *, PAGE *)); +int __qam_pgin_out __P((ENV *, db_pgno_t, void *, DBT *)); +int __qam_fprobe __P((DBC *, db_pgno_t, void *, qam_probe_mode, DB_CACHE_PRIORITY, u_int32_t)); +int __qam_fclose __P((DB *, db_pgno_t)); +int __qam_fremove __P((DB *, db_pgno_t)); +int __qam_sync __P((DB *)); +int __qam_gen_filelist __P((DB *, DB_THREAD_INFO *, QUEUE_FILELIST **)); +int __qam_extent_names __P((ENV *, char *, char ***)); +void __qam_exid __P((DB *, u_int8_t *, u_int32_t)); +int __qam_nameop __P((DB *, DB_TXN *, const char *, qam_name_op)); +int __qam_lsn_reset __P((DB *, DB_THREAD_INFO *)); +int __qam_backup_extents __P((DB *, DB_THREAD_INFO *, const char *, u_int32_t)); +int __qam_db_create __P((DB *)); +int __qam_db_close __P((DB *, u_int32_t)); +int __qam_get_extentsize __P((DB *, u_int32_t *)); +int __queue_pageinfo __P((DB *, db_pgno_t *, db_pgno_t *, int *, int, u_int32_t)); +int __db_prqueue __P((DB *, u_int32_t)); +int __qam_remove __P((DB *, DB_THREAD_INFO *, DB_TXN *, const char *, const char *, u_int32_t)); +int __qam_rename __P((DB *, DB_THREAD_INFO *, DB_TXN *, const char *, const char *, const char *)); +void __qam_map_flags __P((DB *, u_int32_t *, u_int32_t *)); +int __qam_set_flags __P((DB *, u_int32_t *flagsp)); +int __qam_open __P((DB *, DB_THREAD_INFO *, DB_TXN *, const char *, db_pgno_t, int, u_int32_t)); +int __qam_set_ext_data __P((DB*, const char *)); +int __qam_metachk __P((DB *, const char *, QMETA *)); +int __qam_new_file __P((DB *, DB_THREAD_INFO *, DB_TXN *, DB_FH *, const char *)); +int __qam_incfirst_recover __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __qam_mvptr_recover __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __qam_del_recover __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __qam_delext_recover __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __qam_add_recover __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __qam_stat __P((DBC *, void *, u_int32_t)); +int __qam_stat_print __P((DBC *, u_int32_t)); +int __db_no_queue_am __P((ENV *)); +int __qam_31_qammeta __P((DB *, char *, u_int8_t *)); +int __qam_32_qammeta __P((DB *, char *, u_int8_t *)); +int __qam_vrfy_meta __P((DB *, VRFY_DBINFO *, QMETA *, db_pgno_t, u_int32_t)); +int __qam_meta2pgset __P((DB *, VRFY_DBINFO *, DB *)); +int __qam_vrfy_data __P((DB *, VRFY_DBINFO *, QPAGE *, db_pgno_t, u_int32_t)); +int __qam_vrfy_structure __P((DB *, VRFY_DBINFO *, u_int32_t)); +int __qam_vrfy_walkqueue __P((DB *, VRFY_DBINFO *, void *, int (*)(void *, const void *), u_int32_t)); +int __qam_salvage __P((DB *, VRFY_DBINFO *, db_pgno_t, PAGE *, void *, int (*)(void *, const void *), u_int32_t)); + +#if defined(__cplusplus) +} +#endif +#endif /* !_qam_ext_h_ */ diff -r 000000000000 -r a1985f14b030 src/dbinc_auto/rep_automsg.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/dbinc_auto/rep_automsg.h Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,145 @@ +/* Do not edit: automatically built by gen_msg.awk. + * + * Copyright (c) 2012 Oracle and/or its affiliates. All rights reserved. * + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +#ifndef __rep_AUTOMSG_H +#define __rep_AUTOMSG_H + +/* + * Message sizes are simply the sum of field sizes (not + * counting variable size parts, when DBTs are present), + * and may be different from struct sizes due to padding. + */ +#define __REP_BULK_SIZE 16 +typedef struct ___rep_bulk_args { + u_int32_t len; + DB_LSN lsn; + DBT bulkdata; +} __rep_bulk_args; + +#define __REP_CONTROL_SIZE 36 +typedef struct ___rep_control_args { + u_int32_t rep_version; + u_int32_t log_version; + DB_LSN lsn; + u_int32_t rectype; + u_int32_t gen; + u_int32_t msg_sec; + u_int32_t msg_nsec; + u_int32_t flags; +} __rep_control_args; + +#define __REP_EGEN_SIZE 4 +typedef struct ___rep_egen_args { + u_int32_t egen; +} __rep_egen_args; + +#define __REP_FILEINFO_SIZE 40 +typedef struct ___rep_fileinfo_args { + u_int32_t pgsize; + db_pgno_t pgno; + db_pgno_t max_pgno; + u_int32_t filenum; + u_int32_t finfo_flags; + u_int32_t type; + u_int32_t db_flags; + DBT uid; + DBT info; + DBT dir; +} __rep_fileinfo_args; + +#define __REP_FILEINFO_V6_SIZE 36 +typedef struct ___rep_fileinfo_v6_args { + u_int32_t pgsize; + db_pgno_t pgno; + db_pgno_t max_pgno; + u_int32_t filenum; + u_int32_t finfo_flags; + u_int32_t type; + u_int32_t db_flags; + DBT uid; + DBT info; +} __rep_fileinfo_v6_args; + +#define __REP_GRANT_INFO_SIZE 8 +typedef struct ___rep_grant_info_args { + u_int32_t msg_sec; + u_int32_t msg_nsec; +} __rep_grant_info_args; + +#define __REP_LOGREQ_SIZE 8 +typedef struct ___rep_logreq_args { + DB_LSN endlsn; +} __rep_logreq_args; + +#define __REP_NEWFILE_SIZE 4 +typedef struct ___rep_newfile_args { + u_int32_t version; +} __rep_newfile_args; + +#define __REP_UPDATE_SIZE 16 +typedef struct ___rep_update_args { + DB_LSN first_lsn; + u_int32_t first_vers; + u_int32_t num_files; +} __rep_update_args; + +#define __REP_VOTE_INFO_SIZE 28 +typedef struct ___rep_vote_info_args { + u_int32_t egen; + u_int32_t nsites; + u_int32_t nvotes; + u_int32_t priority; + u_int32_t spare_pri; + u_int32_t tiebreaker; + u_int32_t data_gen; +} __rep_vote_info_args; + +#define __REP_VOTE_INFO_V5_SIZE 20 +typedef struct ___rep_vote_info_v5_args { + u_int32_t egen; + u_int32_t nsites; + u_int32_t nvotes; + u_int32_t priority; + u_int32_t tiebreaker; +} __rep_vote_info_v5_args; + +#define __REP_LSN_HIST_KEY_SIZE 8 +typedef struct ___rep_lsn_hist_key_args { + u_int32_t version; + u_int32_t gen; +} __rep_lsn_hist_key_args; + +#define __REP_LSN_HIST_DATA_SIZE 20 +typedef struct ___rep_lsn_hist_data_args { + u_int32_t envid; + DB_LSN lsn; + u_int32_t hist_sec; + u_int32_t hist_nsec; +} __rep_lsn_hist_data_args; + +#define __REP_MAXMSG_SIZE 40 +#endif diff -r 000000000000 -r a1985f14b030 src/dbinc_auto/rep_ext.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/dbinc_auto/rep_ext.h Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,177 @@ +/* DO NOT EDIT: automatically built by dist/s_include. + * + * Copyright (c) 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ +#ifndef _rep_ext_h_ +#define _rep_ext_h_ + +#if defined(__cplusplus) +extern "C" { +#endif + +int __rep_bulk_marshal __P((ENV *, __rep_bulk_args *, u_int8_t *, size_t, size_t *)); +int __rep_bulk_unmarshal __P((ENV *, __rep_bulk_args *, u_int8_t *, size_t, u_int8_t **)); +int __rep_control_marshal __P((ENV *, __rep_control_args *, u_int8_t *, size_t, size_t *)); +int __rep_control_unmarshal __P((ENV *, __rep_control_args *, u_int8_t *, size_t, u_int8_t **)); +int __rep_egen_marshal __P((ENV *, __rep_egen_args *, u_int8_t *, size_t, size_t *)); +int __rep_egen_unmarshal __P((ENV *, __rep_egen_args *, u_int8_t *, size_t, u_int8_t **)); +int __rep_fileinfo_marshal __P((ENV *, u_int32_t, __rep_fileinfo_args *, u_int8_t *, size_t, size_t *)); +int __rep_fileinfo_unmarshal __P((ENV *, u_int32_t, __rep_fileinfo_args **, u_int8_t *, size_t, u_int8_t **)); +int __rep_fileinfo_v6_marshal __P((ENV *, u_int32_t, __rep_fileinfo_v6_args *, u_int8_t *, size_t, size_t *)); +int __rep_fileinfo_v6_unmarshal __P((ENV *, u_int32_t, __rep_fileinfo_v6_args **, u_int8_t *, size_t, u_int8_t **)); +int __rep_grant_info_marshal __P((ENV *, __rep_grant_info_args *, u_int8_t *, size_t, size_t *)); +int __rep_grant_info_unmarshal __P((ENV *, __rep_grant_info_args *, u_int8_t *, size_t, u_int8_t **)); +int __rep_logreq_marshal __P((ENV *, __rep_logreq_args *, u_int8_t *, size_t, size_t *)); +int __rep_logreq_unmarshal __P((ENV *, __rep_logreq_args *, u_int8_t *, size_t, u_int8_t **)); +int __rep_newfile_marshal __P((ENV *, __rep_newfile_args *, u_int8_t *, size_t, size_t *)); +int __rep_newfile_unmarshal __P((ENV *, __rep_newfile_args *, u_int8_t *, size_t, u_int8_t **)); +int __rep_update_marshal __P((ENV *, u_int32_t, __rep_update_args *, u_int8_t *, size_t, size_t *)); +int __rep_update_unmarshal __P((ENV *, u_int32_t, __rep_update_args **, u_int8_t *, size_t, u_int8_t **)); +int __rep_vote_info_marshal __P((ENV *, __rep_vote_info_args *, u_int8_t *, size_t, size_t *)); +int __rep_vote_info_unmarshal __P((ENV *, __rep_vote_info_args *, u_int8_t *, size_t, u_int8_t **)); +int __rep_vote_info_v5_marshal __P((ENV *, __rep_vote_info_v5_args *, u_int8_t *, size_t, size_t *)); +int __rep_vote_info_v5_unmarshal __P((ENV *, __rep_vote_info_v5_args *, u_int8_t *, size_t, u_int8_t **)); +void __rep_lsn_hist_key_marshal __P((ENV *, __rep_lsn_hist_key_args *, u_int8_t *)); +int __rep_lsn_hist_key_unmarshal __P((ENV *, __rep_lsn_hist_key_args *, u_int8_t *, size_t, u_int8_t **)); +void __rep_lsn_hist_data_marshal __P((ENV *, __rep_lsn_hist_data_args *, u_int8_t *)); +int __rep_lsn_hist_data_unmarshal __P((ENV *, __rep_lsn_hist_data_args *, u_int8_t *, size_t, u_int8_t **)); +int __rep_update_req __P((ENV *, __rep_control_args *)); +int __rep_page_req __P((ENV *, DB_THREAD_INFO *, int, __rep_control_args *, DBT *)); +int __rep_update_setup __P((ENV *, int, __rep_control_args *, DBT *, time_t, DB_LSN *)); +int __rep_bulk_page __P((ENV *, DB_THREAD_INFO *, int, __rep_control_args *, DBT *)); +int __rep_page __P((ENV *, DB_THREAD_INFO *, int, __rep_control_args *, DBT *)); +int __rep_init_cleanup __P((ENV *, REP *, int)); +int __rep_pggap_req __P((ENV *, REP *, __rep_fileinfo_args *, u_int32_t)); +int __rep_finfo_alloc __P((ENV *, __rep_fileinfo_args *, __rep_fileinfo_args **)); +int __rep_remove_init_file __P((ENV *)); +int __rep_reset_init __P((ENV *)); +int __rep_elect_pp __P((DB_ENV *, u_int32_t, u_int32_t, u_int32_t)); +int __rep_elect_int __P((ENV *, u_int32_t, u_int32_t, u_int32_t)); +int __rep_vote1 __P((ENV *, __rep_control_args *, DBT *, int)); +int __rep_vote2 __P((ENV *, __rep_control_args *, DBT *, int)); +int __rep_update_grant __P((ENV *, db_timespec *)); +int __rep_islease_granted __P((ENV *)); +int __rep_lease_table_alloc __P((ENV *, u_int32_t)); +int __rep_lease_grant __P((ENV *, __rep_control_args *, DBT *, int)); +int __rep_lease_check __P((ENV *, int)); +int __rep_lease_refresh __P((ENV *)); +int __rep_lease_expire __P((ENV *)); +db_timeout_t __rep_lease_waittime __P((ENV *)); +int __rep_allreq __P((ENV *, __rep_control_args *, int)); +int __rep_log __P((ENV *, DB_THREAD_INFO *, __rep_control_args *, DBT *, int, time_t, DB_LSN *)); +int __rep_bulk_log __P((ENV *, DB_THREAD_INFO *, __rep_control_args *, DBT *, time_t, DB_LSN *)); +int __rep_logreq __P((ENV *, __rep_control_args *, DBT *, int)); +int __rep_loggap_req __P((ENV *, REP *, DB_LSN *, u_int32_t)); +int __rep_logready __P((ENV *, REP *, time_t, DB_LSN *)); +int __rep_env_create __P((DB_ENV *)); +void __rep_env_destroy __P((DB_ENV *)); +int __rep_get_config __P((DB_ENV *, u_int32_t, int *)); +int __rep_set_config __P((DB_ENV *, u_int32_t, int)); +int __rep_start_pp __P((DB_ENV *, DBT *, u_int32_t)); +int __rep_start_int __P((ENV *, DBT *, u_int32_t)); +int __rep_open_sysdb __P((ENV *, DB_THREAD_INFO *, DB_TXN *, const char *, u_int32_t, DB **)); +int __rep_client_dbinit __P((ENV *, int, repdb_t)); +int __rep_get_limit __P((DB_ENV *, u_int32_t *, u_int32_t *)); +int __rep_set_limit __P((DB_ENV *, u_int32_t, u_int32_t)); +int __rep_set_nsites_pp __P((DB_ENV *, u_int32_t)); +int __rep_set_nsites_int __P((ENV *, u_int32_t)); +int __rep_get_nsites __P((DB_ENV *, u_int32_t *)); +int __rep_set_priority __P((DB_ENV *, u_int32_t)); +int __rep_get_priority __P((DB_ENV *, u_int32_t *)); +int __rep_set_timeout __P((DB_ENV *, int, db_timeout_t)); +int __rep_get_timeout __P((DB_ENV *, int, db_timeout_t *)); +int __rep_get_request __P((DB_ENV *, db_timeout_t *, db_timeout_t *)); +int __rep_set_request __P((DB_ENV *, db_timeout_t, db_timeout_t)); +int __rep_set_transport_pp __P((DB_ENV *, int, int (*)(DB_ENV *, const DBT *, const DBT *, const DB_LSN *, int, u_int32_t))); +int __rep_set_transport_int __P((ENV *, int, int (*)(DB_ENV *, const DBT *, const DBT *, const DB_LSN *, int, u_int32_t))); +int __rep_get_clockskew __P((DB_ENV *, u_int32_t *, u_int32_t *)); +int __rep_set_clockskew __P((DB_ENV *, u_int32_t, u_int32_t)); +int __rep_flush __P((DB_ENV *)); +int __rep_sync __P((DB_ENV *, u_int32_t)); +int __rep_txn_applied __P((ENV *, DB_THREAD_INFO *, DB_COMMIT_INFO *, db_timeout_t)); +int __rep_process_message_pp __P((DB_ENV *, DBT *, DBT *, int, DB_LSN *)); +int __rep_process_message_int __P((ENV *, DBT *, DBT *, int, DB_LSN *)); +int __rep_apply __P((ENV *, DB_THREAD_INFO *, __rep_control_args *, DBT *, DB_LSN *, int *, DB_LSN *)); +int __rep_process_txn __P((ENV *, DBT *)); +int __rep_resend_req __P((ENV *, int)); +int __rep_check_doreq __P((ENV *, REP *)); +int __rep_check_missing __P((ENV *, u_int32_t, DB_LSN *)); +int __rep_open __P((ENV *)); +int __rep_close_diagfiles __P((ENV *)); +int __rep_env_refresh __P((ENV *)); +int __rep_env_close __P((ENV *)); +int __rep_preclose __P((ENV *)); +int __rep_closefiles __P((ENV *)); +int __rep_write_egen __P((ENV *, REP *, u_int32_t)); +int __rep_write_gen __P((ENV *, REP *, u_int32_t)); +int __rep_stat_pp __P((DB_ENV *, DB_REP_STAT **, u_int32_t)); +int __rep_stat_print_pp __P((DB_ENV *, u_int32_t)); +int __rep_stat_print __P((ENV *, u_int32_t)); +int __rep_bulk_message __P((ENV *, REP_BULK *, REP_THROTTLE *, DB_LSN *, const DBT *, u_int32_t)); +int __rep_send_bulk __P((ENV *, REP_BULK *, u_int32_t)); +int __rep_bulk_alloc __P((ENV *, REP_BULK *, int, uintptr_t *, u_int32_t *, u_int32_t)); +int __rep_bulk_free __P((ENV *, REP_BULK *, u_int32_t)); +int __rep_send_message __P((ENV *, int, u_int32_t, DB_LSN *, const DBT *, u_int32_t, u_int32_t)); +int __rep_new_master __P((ENV *, __rep_control_args *, int)); +void __rep_elect_done __P((ENV *, REP *)); +int __env_rep_enter __P((ENV *, int)); +int __env_db_rep_exit __P((ENV *)); +int __db_rep_enter __P((DB *, int, int, int)); +int __op_handle_enter __P((ENV *)); +int __op_rep_enter __P((ENV *, int, int)); +int __op_rep_exit __P((ENV *)); +int __archive_rep_enter __P((ENV *)); +int __archive_rep_exit __P((ENV *)); +int __rep_lockout_archive __P((ENV *, REP *)); +int __rep_lockout_api __P((ENV *, REP *)); +int __rep_take_apilockout __P((ENV *)); +int __rep_clear_apilockout __P((ENV *)); +int __rep_lockout_apply __P((ENV *, REP *, u_int32_t)); +int __rep_lockout_msg __P((ENV *, REP *, u_int32_t)); +int __rep_send_throttle __P((ENV *, int, REP_THROTTLE *, u_int32_t, u_int32_t)); +u_int32_t __rep_msg_to_old __P((u_int32_t, u_int32_t)); +u_int32_t __rep_msg_from_old __P((u_int32_t, u_int32_t)); +int __rep_print_system __P((ENV *, u_int32_t, const char *, ...)) __attribute__ ((__format__ (__printf__, 3, 4))); +int __rep_print __P((ENV *, u_int32_t, const char *, ...)) __attribute__ ((__format__ (__printf__, 3, 4))); +void __rep_print_message __P((ENV *, int, __rep_control_args *, char *, u_int32_t)); +void __rep_fire_event __P((ENV *, u_int32_t, void *)); +void __rep_msg __P((const ENV *, const char *)); +int __rep_notify_threads __P((ENV *, rep_waitreason_t)); +int __rep_check_goal __P((ENV *, struct rep_waitgoal *)); +int __rep_log_backup __P((ENV *, DB_LOGC *, DB_LSN *, u_int32_t)); +int __rep_get_maxpermlsn __P((ENV *, DB_LSN *)); +int __rep_is_internal_rep_file __P((char *)); +int __rep_get_datagen __P((ENV *, u_int32_t *)); +int __rep_verify __P((ENV *, __rep_control_args *, DBT *, int, time_t)); +int __rep_verify_fail __P((ENV *, __rep_control_args *)); +int __rep_verify_req __P((ENV *, __rep_control_args *, int)); +int __rep_dorecovery __P((ENV *, DB_LSN *, DB_LSN *)); +int __rep_verify_match __P((ENV *, DB_LSN *, time_t)); + +#if defined(__cplusplus) +} +#endif +#endif /* !_rep_ext_h_ */ diff -r 000000000000 -r a1985f14b030 src/dbinc_auto/repmgr_auto.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/dbinc_auto/repmgr_auto.h Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,66 @@ +/* Do not edit: automatically built by gen_rec.awk. + * + * Copyright (c) 2012 Oracle and/or its affiliates. All rights reserved. * + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +#ifndef __repmgr_AUTO_H +#define __repmgr_AUTO_H +#ifdef HAVE_REPLICATION_THREADS +#include "dbinc/log.h" +#define DB___repmgr_member 200 +typedef struct ___repmgr_member_args { + u_int32_t type; + DB_TXN *txnp; + DB_LSN prev_lsn; + u_int32_t version; + u_int32_t prev_status; + u_int32_t status; + DBT host; + u_int32_t port; +} __repmgr_member_args; + +extern __DB_IMPORT DB_LOG_RECSPEC __repmgr_member_desc[]; +static inline int +__repmgr_member_log(ENV *env, DB_TXN *txnp, DB_LSN *ret_lsnp, u_int32_t flags, + u_int32_t version, u_int32_t prev_status, u_int32_t status, const DBT *host, u_int32_t port) +{ + return (__log_put_record(env, NULL, txnp, ret_lsnp, + flags, DB___repmgr_member, 0, + sizeof(u_int32_t) + sizeof(u_int32_t) + sizeof(DB_LSN) + + sizeof(u_int32_t) + sizeof(u_int32_t) + sizeof(u_int32_t) + + LOG_DBT_SIZE(host) + sizeof(u_int32_t), + __repmgr_member_desc, + version, prev_status, status, host, port)); +} + +static inline int __repmgr_member_read(ENV *env, + void *data, __repmgr_member_args **arg) +{ + *arg = NULL; + return (__log_read_record(env, + NULL, NULL, data, __repmgr_member_desc, sizeof(__repmgr_member_args), (void**)arg)); +} +#endif /* HAVE_REPLICATION_THREADS */ +#endif diff -r 000000000000 -r a1985f14b030 src/dbinc_auto/repmgr_automsg.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/dbinc_auto/repmgr_automsg.h Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,138 @@ +/* Do not edit: automatically built by gen_msg.awk. + * + * Copyright (c) 2012 Oracle and/or its affiliates. All rights reserved. * + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +#ifndef __repmgr_AUTOMSG_H +#define __repmgr_AUTOMSG_H + +/* + * Message sizes are simply the sum of field sizes (not + * counting variable size parts, when DBTs are present), + * and may be different from struct sizes due to padding. + */ +#define __REPMGR_HANDSHAKE_SIZE 12 +typedef struct ___repmgr_handshake_args { + u_int16_t port; + u_int16_t alignment; + u_int32_t ack_policy; + u_int32_t flags; +} __repmgr_handshake_args; + +#define __REPMGR_V3HANDSHAKE_SIZE 10 +typedef struct ___repmgr_v3handshake_args { + u_int16_t port; + u_int32_t priority; + u_int32_t flags; +} __repmgr_v3handshake_args; + +#define __REPMGR_V2HANDSHAKE_SIZE 6 +typedef struct ___repmgr_v2handshake_args { + u_int16_t port; + u_int32_t priority; +} __repmgr_v2handshake_args; + +#define __REPMGR_PARM_REFRESH_SIZE 8 +typedef struct ___repmgr_parm_refresh_args { + u_int32_t ack_policy; + u_int32_t flags; +} __repmgr_parm_refresh_args; + +#define __REPMGR_PERMLSN_SIZE 12 +typedef struct ___repmgr_permlsn_args { + u_int32_t generation; + DB_LSN lsn; +} __repmgr_permlsn_args; + +#define __REPMGR_VERSION_PROPOSAL_SIZE 8 +typedef struct ___repmgr_version_proposal_args { + u_int32_t min; + u_int32_t max; +} __repmgr_version_proposal_args; + +#define __REPMGR_VERSION_CONFIRMATION_SIZE 4 +typedef struct ___repmgr_version_confirmation_args { + u_int32_t version; +} __repmgr_version_confirmation_args; + +#define __REPMGR_MSG_HDR_SIZE 9 +typedef struct ___repmgr_msg_hdr_args { + u_int8_t type; + u_int32_t word1; + u_int32_t word2; +} __repmgr_msg_hdr_args; + +#define __REPMGR_MSG_METADATA_SIZE 12 +typedef struct ___repmgr_msg_metadata_args { + u_int32_t tag; + u_int32_t limit; + u_int32_t flags; +} __repmgr_msg_metadata_args; + +#define __REPMGR_MEMBERSHIP_KEY_SIZE 6 +typedef struct ___repmgr_membership_key_args { + DBT host; + u_int16_t port; +} __repmgr_membership_key_args; + +#define __REPMGR_MEMBERSHIP_DATA_SIZE 4 +typedef struct ___repmgr_membership_data_args { + u_int32_t flags; +} __repmgr_membership_data_args; + +#define __REPMGR_MEMBER_METADATA_SIZE 8 +typedef struct ___repmgr_member_metadata_args { + u_int32_t format; + u_int32_t version; +} __repmgr_member_metadata_args; + +#define __REPMGR_GM_FWD_SIZE 10 +typedef struct ___repmgr_gm_fwd_args { + DBT host; + u_int16_t port; + u_int32_t gen; +} __repmgr_gm_fwd_args; + +#define __REPMGR_MEMBR_VERS_SIZE 8 +typedef struct ___repmgr_membr_vers_args { + u_int32_t version; + u_int32_t gen; +} __repmgr_membr_vers_args; + +#define __REPMGR_SITE_INFO_SIZE 10 +typedef struct ___repmgr_site_info_args { + DBT host; + u_int16_t port; + u_int32_t flags; +} __repmgr_site_info_args; + +#define __REPMGR_CONNECT_REJECT_SIZE 8 +typedef struct ___repmgr_connect_reject_args { + u_int32_t version; + u_int32_t gen; +} __repmgr_connect_reject_args; + +#define __REPMGR_MAXMSG_SIZE 12 +#endif diff -r 000000000000 -r a1985f14b030 src/dbinc_auto/repmgr_ext.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/dbinc_auto/repmgr_ext.h Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,275 @@ +/* DO NOT EDIT: automatically built by dist/s_include. + * + * Copyright (c) 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ +#ifndef _repmgr_ext_h_ +#define _repmgr_ext_h_ + +#if defined(__cplusplus) +extern "C" { +#endif + +int __repmgr_init_recover __P((ENV *, DB_DISTAB *)); +void __repmgr_handshake_marshal __P((ENV *, __repmgr_handshake_args *, u_int8_t *)); +int __repmgr_handshake_unmarshal __P((ENV *, __repmgr_handshake_args *, u_int8_t *, size_t, u_int8_t **)); +void __repmgr_v3handshake_marshal __P((ENV *, __repmgr_v3handshake_args *, u_int8_t *)); +int __repmgr_v3handshake_unmarshal __P((ENV *, __repmgr_v3handshake_args *, u_int8_t *, size_t, u_int8_t **)); +void __repmgr_v2handshake_marshal __P((ENV *, __repmgr_v2handshake_args *, u_int8_t *)); +int __repmgr_v2handshake_unmarshal __P((ENV *, __repmgr_v2handshake_args *, u_int8_t *, size_t, u_int8_t **)); +void __repmgr_parm_refresh_marshal __P((ENV *, __repmgr_parm_refresh_args *, u_int8_t *)); +int __repmgr_parm_refresh_unmarshal __P((ENV *, __repmgr_parm_refresh_args *, u_int8_t *, size_t, u_int8_t **)); +void __repmgr_permlsn_marshal __P((ENV *, __repmgr_permlsn_args *, u_int8_t *)); +int __repmgr_permlsn_unmarshal __P((ENV *, __repmgr_permlsn_args *, u_int8_t *, size_t, u_int8_t **)); +void __repmgr_version_proposal_marshal __P((ENV *, __repmgr_version_proposal_args *, u_int8_t *)); +int __repmgr_version_proposal_unmarshal __P((ENV *, __repmgr_version_proposal_args *, u_int8_t *, size_t, u_int8_t **)); +void __repmgr_version_confirmation_marshal __P((ENV *, __repmgr_version_confirmation_args *, u_int8_t *)); +int __repmgr_version_confirmation_unmarshal __P((ENV *, __repmgr_version_confirmation_args *, u_int8_t *, size_t, u_int8_t **)); +void __repmgr_msg_hdr_marshal __P((ENV *, __repmgr_msg_hdr_args *, u_int8_t *)); +int __repmgr_msg_hdr_unmarshal __P((ENV *, __repmgr_msg_hdr_args *, u_int8_t *, size_t, u_int8_t **)); +void __repmgr_msg_metadata_marshal __P((ENV *, __repmgr_msg_metadata_args *, u_int8_t *)); +int __repmgr_msg_metadata_unmarshal __P((ENV *, __repmgr_msg_metadata_args *, u_int8_t *, size_t, u_int8_t **)); +int __repmgr_membership_key_marshal __P((ENV *, __repmgr_membership_key_args *, u_int8_t *, size_t, size_t *)); +int __repmgr_membership_key_unmarshal __P((ENV *, __repmgr_membership_key_args *, u_int8_t *, size_t, u_int8_t **)); +void __repmgr_membership_data_marshal __P((ENV *, __repmgr_membership_data_args *, u_int8_t *)); +int __repmgr_membership_data_unmarshal __P((ENV *, __repmgr_membership_data_args *, u_int8_t *, size_t, u_int8_t **)); +void __repmgr_member_metadata_marshal __P((ENV *, __repmgr_member_metadata_args *, u_int8_t *)); +int __repmgr_member_metadata_unmarshal __P((ENV *, __repmgr_member_metadata_args *, u_int8_t *, size_t, u_int8_t **)); +int __repmgr_gm_fwd_marshal __P((ENV *, __repmgr_gm_fwd_args *, u_int8_t *, size_t, size_t *)); +int __repmgr_gm_fwd_unmarshal __P((ENV *, __repmgr_gm_fwd_args *, u_int8_t *, size_t, u_int8_t **)); +void __repmgr_membr_vers_marshal __P((ENV *, __repmgr_membr_vers_args *, u_int8_t *)); +int __repmgr_membr_vers_unmarshal __P((ENV *, __repmgr_membr_vers_args *, u_int8_t *, size_t, u_int8_t **)); +int __repmgr_site_info_marshal __P((ENV *, __repmgr_site_info_args *, u_int8_t *, size_t, size_t *)); +int __repmgr_site_info_unmarshal __P((ENV *, __repmgr_site_info_args *, u_int8_t *, size_t, u_int8_t **)); +void __repmgr_connect_reject_marshal __P((ENV *, __repmgr_connect_reject_args *, u_int8_t *)); +int __repmgr_connect_reject_unmarshal __P((ENV *, __repmgr_connect_reject_args *, u_int8_t *, size_t, u_int8_t **)); +int __repmgr_member_print __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __repmgr_init_print __P((ENV *, DB_DISTAB *)); +int __repmgr_init_election __P((ENV *, u_int32_t)); +int __repmgr_claim_victory __P((ENV *)); +int __repmgr_turn_on_elections __P((ENV *)); +int __repmgr_start __P((DB_ENV *, int, u_int32_t)); +int __repmgr_valid_config __P((ENV *, u_int32_t)); +int __repmgr_autostart __P((ENV *)); +int __repmgr_start_selector __P((ENV *)); +int __repmgr_close __P((ENV *)); +int __repmgr_stop __P((ENV *)); +int __repmgr_set_ack_policy __P((DB_ENV *, int)); +int __repmgr_get_ack_policy __P((DB_ENV *, int *)); +int __repmgr_env_create __P((ENV *, DB_REP *)); +void __repmgr_env_destroy __P((ENV *, DB_REP *)); +int __repmgr_stop_threads __P((ENV *)); +int __repmgr_local_site __P((DB_ENV *, DB_SITE **)); +int __repmgr_channel __P((DB_ENV *, int, DB_CHANNEL **, u_int32_t)); +int __repmgr_set_msg_dispatch __P((DB_ENV *, void (*)(DB_ENV *, DB_CHANNEL *, DBT *, u_int32_t, u_int32_t), u_int32_t)); +int __repmgr_send_msg __P((DB_CHANNEL *, DBT *, u_int32_t, u_int32_t)); +int __repmgr_send_request __P((DB_CHANNEL *, DBT *, u_int32_t, DBT *, db_timeout_t, u_int32_t)); +int __repmgr_send_response __P((DB_CHANNEL *, DBT *, u_int32_t, u_int32_t)); +int __repmgr_channel_close __P((DB_CHANNEL *, u_int32_t)); +int __repmgr_channel_timeout __P((DB_CHANNEL *, db_timeout_t)); +int __repmgr_send_request_inval __P((DB_CHANNEL *, DBT *, u_int32_t, DBT *, db_timeout_t, u_int32_t)); +int __repmgr_channel_close_inval __P((DB_CHANNEL *, u_int32_t)); +int __repmgr_channel_timeout_inval __P((DB_CHANNEL *, db_timeout_t)); +int __repmgr_join_group __P((ENV *)); +int __repmgr_site __P((DB_ENV *, const char *, u_int, DB_SITE **, u_int32_t)); +int __repmgr_site_by_eid __P((DB_ENV *, int, DB_SITE **)); +int __repmgr_get_site_address __P((DB_SITE *, const char **, u_int *)); +int __repmgr_get_eid __P((DB_SITE *, int *)); +int __repmgr_get_config __P((DB_SITE *, u_int32_t, u_int32_t *)); +int __repmgr_site_config __P((DB_SITE *, u_int32_t, u_int32_t)); +int __repmgr_site_close __P((DB_SITE *)); +void *__repmgr_msg_thread __P((void *)); +int __repmgr_send_err_resp __P((ENV *, CHANNEL *, int)); +int __repmgr_handle_event __P((ENV *, u_int32_t, void *)); +int __repmgr_update_membership __P((ENV *, DB_THREAD_INFO *, int, u_int32_t)); +int __repmgr_set_gm_version __P((ENV *, DB_THREAD_INFO *, DB_TXN *, u_int32_t)); +int __repmgr_setup_gmdb_op __P((ENV *, DB_THREAD_INFO *, DB_TXN **, u_int32_t)); +int __repmgr_cleanup_gmdb_op __P((ENV *, int)); +int __repmgr_hold_master_role __P((ENV *, REPMGR_CONNECTION *)); +int __repmgr_rlse_master_role __P((ENV *)); +void __repmgr_set_sites __P((ENV *)); +int __repmgr_connect __P((ENV *, repmgr_netaddr_t *, REPMGR_CONNECTION **, int *)); +int __repmgr_send __P((DB_ENV *, const DBT *, const DBT *, const DB_LSN *, int, u_int32_t)); +int __repmgr_sync_siteaddr __P((ENV *)); +int __repmgr_send_broadcast __P((ENV *, u_int, const DBT *, const DBT *, u_int *, u_int *, int *)); +int __repmgr_send_one __P((ENV *, REPMGR_CONNECTION *, u_int, const DBT *, const DBT *, db_timeout_t)); +int __repmgr_send_many __P((ENV *, REPMGR_CONNECTION *, REPMGR_IOVECS *, db_timeout_t)); +int __repmgr_send_own_msg __P((ENV *, REPMGR_CONNECTION *, u_int32_t, u_int8_t *, u_int32_t)); +int __repmgr_write_iovecs __P((ENV *, REPMGR_CONNECTION *, REPMGR_IOVECS *, size_t *)); +int __repmgr_bust_connection __P((ENV *, REPMGR_CONNECTION *)); +int __repmgr_disable_connection __P((ENV *, REPMGR_CONNECTION *)); +int __repmgr_cleanup_defunct __P((ENV *, REPMGR_CONNECTION *)); +int __repmgr_close_connection __P((ENV *, REPMGR_CONNECTION *)); +int __repmgr_decr_conn_ref __P((ENV *, REPMGR_CONNECTION *)); +int __repmgr_destroy_conn __P((ENV *, REPMGR_CONNECTION *)); +int __repmgr_pack_netaddr __P((ENV *, const char *, u_int, repmgr_netaddr_t *)); +int __repmgr_getaddr __P((ENV *, const char *, u_int, int, ADDRINFO **)); +int __repmgr_listen __P((ENV *)); +int __repmgr_net_close __P((ENV *)); +void __repmgr_net_destroy __P((ENV *, DB_REP *)); +int __repmgr_thread_start __P((ENV *, REPMGR_RUNNABLE *)); +int __repmgr_thread_join __P((REPMGR_RUNNABLE *)); +int __repmgr_set_nonblock_conn __P((REPMGR_CONNECTION *)); +int __repmgr_set_nonblocking __P((socket_t)); +int __repmgr_wake_waiters __P((ENV *, waiter_t *)); +int __repmgr_await_cond __P((ENV *, PREDICATE, void *, db_timeout_t, waiter_t *)); +int __repmgr_await_gmdbop __P((ENV *)); +void __repmgr_compute_wait_deadline __P((ENV*, struct timespec *, db_timeout_t)); +int __repmgr_await_drain __P((ENV *, REPMGR_CONNECTION *, db_timeout_t)); +int __repmgr_alloc_cond __P((cond_var_t *)); +int __repmgr_free_cond __P((cond_var_t *)); +void __repmgr_env_create_pf __P((DB_REP *)); +int __repmgr_create_mutex_pf __P((mgr_mutex_t *)); +int __repmgr_destroy_mutex_pf __P((mgr_mutex_t *)); +int __repmgr_init __P((ENV *)); +int __repmgr_deinit __P((ENV *)); +int __repmgr_init_waiters __P((ENV *, waiter_t *)); +int __repmgr_destroy_waiters __P((ENV *, waiter_t *)); +int __repmgr_lock_mutex __P((mgr_mutex_t *)); +int __repmgr_unlock_mutex __P((mgr_mutex_t *)); +int __repmgr_signal __P((cond_var_t *)); +int __repmgr_wake_msngers __P((ENV*, u_int)); +int __repmgr_wake_main_thread __P((ENV*)); +int __repmgr_writev __P((socket_t, db_iovec_t *, int, size_t *)); +int __repmgr_readv __P((socket_t, db_iovec_t *, int, size_t *)); +int __repmgr_select_loop __P((ENV *)); +int __repmgr_queue_destroy __P((ENV *)); +int __repmgr_queue_get __P((ENV *, REPMGR_MESSAGE **, REPMGR_RUNNABLE *)); +int __repmgr_queue_put __P((ENV *, REPMGR_MESSAGE *)); +int __repmgr_queue_size __P((ENV *)); +int __repmgr_member_recover __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +void *__repmgr_select_thread __P((void *)); +int __repmgr_bow_out __P((ENV *)); +int __repmgr_accept __P((ENV *)); +int __repmgr_compute_timeout __P((ENV *, db_timespec *)); +REPMGR_SITE *__repmgr_connected_master __P((ENV *)); +int __repmgr_check_timeouts __P((ENV *)); +int __repmgr_first_try_connections __P((ENV *)); +int __repmgr_send_v1_handshake __P((ENV *, REPMGR_CONNECTION *, void *, size_t)); +int __repmgr_read_from_site __P((ENV *, REPMGR_CONNECTION *)); +int __repmgr_read_conn __P((REPMGR_CONNECTION *)); +int __repmgr_prepare_simple_input __P((ENV *, REPMGR_CONNECTION *, __repmgr_msg_hdr_args *)); +int __repmgr_send_handshake __P((ENV *, REPMGR_CONNECTION *, void *, size_t, u_int32_t)); +int __repmgr_find_version_info __P((ENV *, REPMGR_CONNECTION *, DBT *)); +int __repmgr_write_some __P((ENV *, REPMGR_CONNECTION *)); +int __repmgr_stat_pp __P((DB_ENV *, DB_REPMGR_STAT **, u_int32_t)); +int __repmgr_stat_print_pp __P((DB_ENV *, u_int32_t)); +int __repmgr_stat_print __P((ENV *, u_int32_t)); +int __repmgr_site_list __P((DB_ENV *, u_int *, DB_REPMGR_SITE **)); +#ifndef HAVE_REPLICATION_THREADS +int __repmgr_close __P((ENV *)); +#endif +#ifndef HAVE_REPLICATION_THREADS +int __repmgr_get_ack_policy __P((DB_ENV *, int *)); +#endif +#ifndef HAVE_REPLICATION_THREADS +int __repmgr_set_ack_policy __P((DB_ENV *, int)); +#endif +#ifndef HAVE_REPLICATION_THREADS +int __repmgr_site __P((DB_ENV *, const char *, u_int, DB_SITE **, u_int32_t)); +#endif +#ifndef HAVE_REPLICATION_THREADS +int __repmgr_site_by_eid __P((DB_ENV *, int, DB_SITE **)); +#endif +#ifndef HAVE_REPLICATION_THREADS +int __repmgr_local_site __P((DB_ENV *, DB_SITE **)); +#endif +#ifndef HAVE_REPLICATION_THREADS +int __repmgr_site_list __P((DB_ENV *, u_int *, DB_REPMGR_SITE **)); +#endif +#ifndef HAVE_REPLICATION_THREADS +int __repmgr_start __P((DB_ENV *, int, u_int32_t)); +#endif +#ifndef HAVE_REPLICATION_THREADS +int __repmgr_stat_pp __P((DB_ENV *, DB_REPMGR_STAT **, u_int32_t)); +#endif +#ifndef HAVE_REPLICATION_THREADS +int __repmgr_stat_print_pp __P((DB_ENV *, u_int32_t)); +#endif +#ifndef HAVE_REPLICATION_THREADS +int __repmgr_handle_event __P((ENV *, u_int32_t, void *)); +#endif +#ifndef HAVE_REPLICATION_THREADS +int __repmgr_channel __P((DB_ENV *, int, DB_CHANNEL **, u_int32_t)); +#endif +#ifndef HAVE_REPLICATION_THREADS +int __repmgr_set_msg_dispatch __P((DB_ENV *, void (*)(DB_ENV *, DB_CHANNEL *, DBT *, u_int32_t, u_int32_t), u_int32_t)); +#endif +#ifndef HAVE_REPLICATION_THREADS +int __repmgr_init_recover __P((ENV *, DB_DISTAB *)); +#endif +int __repmgr_schedule_connection_attempt __P((ENV *, int, int)); +int __repmgr_is_server __P((ENV *, REPMGR_SITE *)); +void __repmgr_reset_for_reading __P((REPMGR_CONNECTION *)); +int __repmgr_new_connection __P((ENV *, REPMGR_CONNECTION **, socket_t, int)); +int __repmgr_set_keepalive __P((ENV *, REPMGR_CONNECTION *)); +int __repmgr_new_site __P((ENV *, REPMGR_SITE**, const char *, u_int)); +int __repmgr_create_mutex __P((ENV *, mgr_mutex_t **)); +int __repmgr_destroy_mutex __P((ENV *, mgr_mutex_t *)); +void __repmgr_cleanup_netaddr __P((ENV *, repmgr_netaddr_t *)); +void __repmgr_iovec_init __P((REPMGR_IOVECS *)); +void __repmgr_add_buffer __P((REPMGR_IOVECS *, void *, size_t)); +void __repmgr_add_dbt __P((REPMGR_IOVECS *, const DBT *)); +int __repmgr_update_consumed __P((REPMGR_IOVECS *, size_t)); +int __repmgr_prepare_my_addr __P((ENV *, DBT *)); +int __repmgr_get_nsites __P((ENV *, u_int32_t *)); +int __repmgr_thread_failure __P((ENV *, int)); +char *__repmgr_format_eid_loc __P((DB_REP *, REPMGR_CONNECTION *, char *)); +char *__repmgr_format_site_loc __P((REPMGR_SITE *, char *)); +char *__repmgr_format_addr_loc __P((repmgr_netaddr_t *, char *)); +int __repmgr_repstart __P((ENV *, u_int32_t)); +int __repmgr_become_master __P((ENV *)); +int __repmgr_each_connection __P((ENV *, CONNECTION_ACTION, void *, int)); +int __repmgr_open __P((ENV *, void *)); +int __repmgr_join __P((ENV *, void *)); +int __repmgr_env_refresh __P((ENV *env)); +int __repmgr_share_netaddrs __P((ENV *, void *, u_int, u_int)); +int __repmgr_copy_in_added_sites __P((ENV *)); +int __repmgr_init_new_sites __P((ENV *, int, int)); +int __repmgr_failchk __P((ENV *)); +int __repmgr_master_is_known __P((ENV *)); +int __repmgr_stable_lsn __P((ENV *, DB_LSN *)); +int __repmgr_send_sync_msg __P((ENV *, REPMGR_CONNECTION *, u_int32_t, u_int8_t *, u_int32_t)); +int __repmgr_marshal_member_list __P((ENV *, u_int8_t **, size_t *)); +int __repmgr_refresh_membership __P((ENV *, u_int8_t *, size_t)); +int __repmgr_reload_gmdb __P((ENV *)); +int __repmgr_gmdb_version_cmp __P((ENV *, u_int32_t, u_int32_t)); +int __repmgr_init_save __P((ENV *, DBT *)); +int __repmgr_init_restore __P((ENV *, DBT *)); +int __repmgr_defer_op __P((ENV *, u_int32_t)); +void __repmgr_fire_conn_err_event __P((ENV *, REPMGR_CONNECTION *, int)); +void __repmgr_print_conn_err __P((ENV *, repmgr_netaddr_t *, int)); +int __repmgr_become_client __P((ENV *)); +REPMGR_SITE *__repmgr_lookup_site __P((ENV *, const char *, u_int)); +int __repmgr_find_site __P((ENV *, const char *, u_int, int *)); +int __repmgr_set_membership __P((ENV *, const char *, u_int, u_int32_t)); +int __repmgr_bcast_parm_refresh __P((ENV *)); +int __repmgr_chg_prio __P((ENV *, u_int32_t, u_int32_t)); +int __repmgr_bcast_own_msg __P((ENV *, u_int32_t, u_int8_t *, size_t)); + +#if defined(__cplusplus) +} +#endif +#endif /* !_repmgr_ext_h_ */ diff -r 000000000000 -r a1985f14b030 src/dbinc_auto/sequence_ext.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/dbinc_auto/sequence_ext.h Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,43 @@ +/* DO NOT EDIT: automatically built by dist/s_include. + * + * Copyright (c) 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ +#ifndef _sequence_ext_h_ +#define _sequence_ext_h_ + +#if defined(__cplusplus) +extern "C" { +#endif + +int __seq_stat __P((DB_SEQUENCE *, DB_SEQUENCE_STAT **, u_int32_t)); +int __seq_stat_print __P((DB_SEQUENCE *, u_int32_t)); +const FN * __db_get_seq_flags_fn __P((void)); +const FN * __db_get_seq_flags_fn __P((void)); + +#if defined(__cplusplus) +} +#endif +#endif /* !_sequence_ext_h_ */ diff -r 000000000000 -r a1985f14b030 src/dbinc_auto/tcl_ext.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/dbinc_auto/tcl_ext.h Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,160 @@ +/* DO NOT EDIT: automatically built by dist/s_include. + * + * Copyright (c) 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ +#ifndef _tcl_ext_h_ +#define _tcl_ext_h_ + +#if defined(__cplusplus) +extern "C" { +#endif + +int bdb_HCommand __P((Tcl_Interp *, int, Tcl_Obj * CONST*)); +#if DB_DBM_HSEARCH != 0 +int bdb_NdbmOpen __P((Tcl_Interp *, int, Tcl_Obj * CONST*, DBM **)); +#endif +#if DB_DBM_HSEARCH != 0 +int bdb_DbmCommand __P((Tcl_Interp *, int, Tcl_Obj * CONST*, int, DBM *)); +#endif +int ndbm_Cmd __P((ClientData, Tcl_Interp *, int, Tcl_Obj * CONST*)); +void _DbInfoDelete __P((Tcl_Interp *, DBTCL_INFO *)); +int db_Cmd __P((ClientData, Tcl_Interp *, int, Tcl_Obj * CONST*)); +int tcl_CompactStat __P((Tcl_Interp *, DBTCL_INFO *)); +int tcl_rep_send __P((DB_ENV *, const DBT *, const DBT *, const DB_LSN *, int, u_int32_t)); +int dbc_Cmd __P((ClientData, Tcl_Interp *, int, Tcl_Obj * CONST*)); +int env_Cmd __P((ClientData, Tcl_Interp *, int, Tcl_Obj * CONST*)); +int tcl_EnvRemove __P((Tcl_Interp *, int, Tcl_Obj * CONST*)); +int tcl_EnvClose __P((Tcl_Interp *, int, Tcl_Obj * CONST*, DB_ENV *, DBTCL_INFO *)); +int tcl_EnvAttr __P((Tcl_Interp *, int, Tcl_Obj * CONST*, DB_ENV *)); +int tcl_EnvIdReset __P((Tcl_Interp *, int, Tcl_Obj * CONST*, DB_ENV *)); +int tcl_EnvLsnReset __P((Tcl_Interp *, int, Tcl_Obj * CONST*, DB_ENV *)); +int tcl_EnvVerbose __P((Tcl_Interp *, DB_ENV *, Tcl_Obj *, Tcl_Obj *)); +int tcl_EnvSetFlags __P((Tcl_Interp *, DB_ENV *, Tcl_Obj *, Tcl_Obj *)); +int tcl_EnvTest __P((Tcl_Interp *, int, Tcl_Obj * CONST*, DB_ENV *)); +int tcl_EnvGetEncryptFlags __P((Tcl_Interp *, int, Tcl_Obj * CONST*, DB_ENV *)); +void tcl_EnvSetErrfile __P((Tcl_Interp *, DB_ENV *, DBTCL_INFO *, char *)); +void tcl_EnvSetMsgfile __P((Tcl_Interp *, DB_ENV *, DBTCL_INFO *, char *)); +int tcl_EnvSetErrpfx __P((Tcl_Interp *, DB_ENV *, DBTCL_INFO *, char *)); +int tcl_EnvStatPrint __P((Tcl_Interp *, int, Tcl_Obj * CONST*, DB_ENV *)); +DBTCL_INFO *_NewInfo __P((Tcl_Interp *, void *, char *, enum INFOTYPE)); +void *_NameToPtr __P((CONST char *)); +DBTCL_INFO *_PtrToInfo __P((CONST void *)); +DBTCL_INFO *_NameToInfo __P((CONST char *)); +void _SetInfoData __P((DBTCL_INFO *, void *)); +void _DeleteInfo __P((DBTCL_INFO *)); +int _SetListElem __P((Tcl_Interp *, Tcl_Obj *, void *, u_int32_t, void *, u_int32_t)); +int _SetListElemInt __P((Tcl_Interp *, Tcl_Obj *, void *, long)); +int _SetListElemWideInt __P((Tcl_Interp *, Tcl_Obj *, void *, int64_t)); +int _SetListRecnoElem __P((Tcl_Interp *, Tcl_Obj *, db_recno_t, u_char *, u_int32_t)); +int _SetListHeapElem __P((Tcl_Interp *, Tcl_Obj *, DB_HEAP_RID, u_char *, u_int32_t)); +int _Set3DBTList __P((Tcl_Interp *, Tcl_Obj *, DBT *, int, DBT *, int, DBT *)); +int _SetMultiList __P((Tcl_Interp *, Tcl_Obj *, DBT *, DBT*, DBTYPE, u_int32_t, DBC*)); +int _GetGlobPrefix __P((char *, char **)); +int _ReturnSetup __P((Tcl_Interp *, int, int, char *)); +int _ErrorSetup __P((Tcl_Interp *, int, char *)); +void _ErrorFunc __P((const DB_ENV *, CONST char *, const char *)); +#ifdef CONFIG_TEST +void _EventFunc __P((DB_ENV *, u_int32_t, void *)); +#endif +int _GetLsn __P((Tcl_Interp *, Tcl_Obj *, DB_LSN *)); +int _GetRid __P((Tcl_Interp *, Tcl_Obj *, DB_HEAP_RID *)); +int _GetUInt32 __P((Tcl_Interp *, Tcl_Obj *, u_int32_t *)); +Tcl_Obj *_GetFlagsList __P((Tcl_Interp *, u_int32_t, const FN *)); +void _debug_check __P((void)); +int _CopyObjBytes __P((Tcl_Interp *, Tcl_Obj *obj, void *, u_int32_t *, int *)); +int tcl_LockDetect __P((Tcl_Interp *, int, Tcl_Obj * CONST*, DB_ENV *)); +int tcl_LockGet __P((Tcl_Interp *, int, Tcl_Obj * CONST*, DB_ENV *)); +int tcl_LockStat __P((Tcl_Interp *, int, Tcl_Obj * CONST*, DB_ENV *)); +int tcl_LockStatPrint __P((Tcl_Interp *, int, Tcl_Obj * CONST*, DB_ENV *)); +int tcl_LockTimeout __P((Tcl_Interp *, int, Tcl_Obj * CONST*, DB_ENV *)); +int tcl_LockVec __P((Tcl_Interp *, int, Tcl_Obj * CONST*, DB_ENV *)); +int tcl_LogArchive __P((Tcl_Interp *, int, Tcl_Obj * CONST*, DB_ENV *)); +int tcl_LogCompare __P((Tcl_Interp *, int, Tcl_Obj * CONST*)); +int tcl_LogFile __P((Tcl_Interp *, int, Tcl_Obj * CONST*, DB_ENV *)); +int tcl_LogFlush __P((Tcl_Interp *, int, Tcl_Obj * CONST*, DB_ENV *)); +int tcl_LogGet __P((Tcl_Interp *, int, Tcl_Obj * CONST*, DB_ENV *)); +int tcl_LogPut __P((Tcl_Interp *, int, Tcl_Obj * CONST*, DB_ENV *)); +int tcl_LogStat __P((Tcl_Interp *, int, Tcl_Obj * CONST*, DB_ENV *)); +int tcl_LogStatPrint __P((Tcl_Interp *, int, Tcl_Obj * CONST*, DB_ENV *)); +int logc_Cmd __P((ClientData, Tcl_Interp *, int, Tcl_Obj * CONST*)); +int tcl_LogConfig __P((Tcl_Interp *, DB_ENV *, Tcl_Obj *, Tcl_Obj *)); +int tcl_LogGetConfig __P((Tcl_Interp *, DB_ENV *, Tcl_Obj *)); +void _MpInfoDelete __P((Tcl_Interp *, DBTCL_INFO *)); +int tcl_MpSync __P((Tcl_Interp *, int, Tcl_Obj * CONST*, DB_ENV *)); +int tcl_MpTrickle __P((Tcl_Interp *, int, Tcl_Obj * CONST*, DB_ENV *)); +int tcl_Mp __P((Tcl_Interp *, int, Tcl_Obj * CONST*, DB_ENV *, DBTCL_INFO *)); +int tcl_MpStat __P((Tcl_Interp *, int, Tcl_Obj * CONST*, DB_ENV *)); +int tcl_MpStatPrint __P((Tcl_Interp *, int, Tcl_Obj * CONST*, DB_ENV *)); +int tcl_Mutex __P((Tcl_Interp *, int, Tcl_Obj * CONST*, DB_ENV *)); +int tcl_MutFree __P((Tcl_Interp *, int, Tcl_Obj * CONST*, DB_ENV *)); +int tcl_MutGet __P((Tcl_Interp *, DB_ENV *, int)); +int tcl_MutLock __P((Tcl_Interp *, int, Tcl_Obj * CONST*, DB_ENV *)); +int tcl_MutSet __P((Tcl_Interp *, Tcl_Obj *, DB_ENV *, int)); +int tcl_MutStat __P((Tcl_Interp *, int, Tcl_Obj * CONST*, DB_ENV *)); +int tcl_MutStatPrint __P((Tcl_Interp *, int, Tcl_Obj * CONST*, DB_ENV *)); +int tcl_MutUnlock __P((Tcl_Interp *, int, Tcl_Obj * CONST*, DB_ENV *)); +int tcl_RepConfig __P((Tcl_Interp *, DB_ENV *, Tcl_Obj *)); +int tcl_RepGetTwo __P((Tcl_Interp *, DB_ENV *, int)); +int tcl_RepGetConfig __P((Tcl_Interp *, DB_ENV *, Tcl_Obj *)); +int tcl_RepGetTimeout __P((Tcl_Interp *, DB_ENV *, Tcl_Obj *)); +int tcl_RepGetAckPolicy __P((Tcl_Interp *, int, Tcl_Obj * CONST *, DB_ENV *)); +int tcl_RepGetLocalSite __P((Tcl_Interp *, int, Tcl_Obj * CONST *, DB_ENV *)); +int tcl_RepElect __P((Tcl_Interp *, int, Tcl_Obj * CONST *, DB_ENV *)); +int tcl_RepFlush __P((Tcl_Interp *, int, Tcl_Obj * CONST *, DB_ENV *)); +int tcl_RepSync __P((Tcl_Interp *, int, Tcl_Obj * CONST *, DB_ENV *)); +int tcl_RepLease __P((Tcl_Interp *, int, Tcl_Obj * CONST *, DB_ENV *)); +int tcl_RepInmemFiles __P((Tcl_Interp *, DB_ENV *)); +int tcl_RepLimit __P((Tcl_Interp *, int, Tcl_Obj * CONST *, DB_ENV *)); +int tcl_RepNSites __P((Tcl_Interp *, int, Tcl_Obj * CONST *, DB_ENV *)); +int tcl_RepRequest __P((Tcl_Interp *, int, Tcl_Obj * CONST *, DB_ENV *)); +int tcl_RepNoarchiveTimeout __P((Tcl_Interp *, DB_ENV *)); +int tcl_RepTransport __P((Tcl_Interp *, int, Tcl_Obj * CONST *, DB_ENV *, DBTCL_INFO *)); +int tcl_RepStart __P((Tcl_Interp *, int, Tcl_Obj * CONST *, DB_ENV *)); +int tcl_RepProcessMessage __P((Tcl_Interp *, int, Tcl_Obj * CONST *, DB_ENV *)); +int tcl_RepStat __P((Tcl_Interp *, int, Tcl_Obj * CONST *, DB_ENV *)); +int tcl_RepStatPrint __P((Tcl_Interp *, int, Tcl_Obj * CONST*, DB_ENV *)); +int tcl_RepMgr __P((Tcl_Interp *, int, Tcl_Obj * CONST *, DB_ENV *)); +int tcl_RepMgrSiteList __P((Tcl_Interp *, int, Tcl_Obj * CONST *, DB_ENV *)); +int tcl_RepMgrStat __P((Tcl_Interp *, int, Tcl_Obj * CONST *, DB_ENV *)); +int tcl_RepMgrStatPrint __P((Tcl_Interp *, int, Tcl_Obj * CONST*, DB_ENV *)); +int tcl_RepApplied __P((Tcl_Interp *, int, Tcl_Obj * CONST *, DB_ENV *)); +int seq_Cmd __P((ClientData, Tcl_Interp *, int, Tcl_Obj * CONST*)); +void _TxnInfoDelete __P((Tcl_Interp *, DBTCL_INFO *)); +int tcl_TxnCheckpoint __P((Tcl_Interp *, int, Tcl_Obj * CONST*, DB_ENV *)); +int tcl_Txn __P((Tcl_Interp *, int, Tcl_Obj * CONST*, DB_ENV *, DBTCL_INFO *)); +int tcl_CDSGroup __P((Tcl_Interp *, int, Tcl_Obj * CONST*, DB_ENV *, DBTCL_INFO *)); +int tcl_TxnStat __P((Tcl_Interp *, int, Tcl_Obj * CONST*, DB_ENV *)); +int tcl_TxnStatPrint __P((Tcl_Interp *, int, Tcl_Obj * CONST*, DB_ENV *)); +int tcl_TxnTimeout __P((Tcl_Interp *, int, Tcl_Obj * CONST*, DB_ENV *)); +int tcl_TxnRecover __P((Tcl_Interp *, int, Tcl_Obj * CONST*, DB_ENV *, DBTCL_INFO *)); +int bdb_RandCommand __P((Tcl_Interp *, int, Tcl_Obj * CONST*)); +int tcl_LockMutex __P((DB_ENV *, db_mutex_t)); +int tcl_UnlockMutex __P((DB_ENV *, db_mutex_t)); + +#if defined(__cplusplus) +} +#endif +#endif /* !_tcl_ext_h_ */ diff -r 000000000000 -r a1985f14b030 src/dbinc_auto/txn_auto.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/dbinc_auto/txn_auto.h Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,245 @@ +/* Do not edit: automatically built by gen_rec.awk. + * + * Copyright (c) 2012 Oracle and/or its affiliates. All rights reserved. * + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +#ifndef __txn_AUTO_H +#define __txn_AUTO_H +#include "dbinc/log.h" +#define DB___txn_regop_42 10 +typedef struct ___txn_regop_42_args { + u_int32_t type; + DB_TXN *txnp; + DB_LSN prev_lsn; + u_int32_t opcode; + int32_t timestamp; + DBT locks; +} __txn_regop_42_args; + +extern __DB_IMPORT DB_LOG_RECSPEC __txn_regop_42_desc[]; +static inline int __txn_regop_42_read(ENV *env, + void *data, __txn_regop_42_args **arg) +{ + *arg = NULL; + return (__log_read_record(env, + NULL, NULL, data, __txn_regop_42_desc, sizeof(__txn_regop_42_args), (void**)arg)); +} +#define DB___txn_regop 10 +typedef struct ___txn_regop_args { + u_int32_t type; + DB_TXN *txnp; + DB_LSN prev_lsn; + u_int32_t opcode; + int32_t timestamp; + u_int32_t envid; + DBT locks; +} __txn_regop_args; + +extern __DB_IMPORT DB_LOG_RECSPEC __txn_regop_desc[]; +static inline int +__txn_regop_log(ENV *env, DB_TXN *txnp, DB_LSN *ret_lsnp, u_int32_t flags, + u_int32_t opcode, int32_t timestamp, u_int32_t envid, const DBT *locks) +{ + return (__log_put_record(env, NULL, txnp, ret_lsnp, + flags, DB___txn_regop, 0, + sizeof(u_int32_t) + sizeof(u_int32_t) + sizeof(DB_LSN) + + sizeof(u_int32_t) + sizeof(u_int32_t) + sizeof(u_int32_t) + + LOG_DBT_SIZE(locks), + __txn_regop_desc, + opcode, timestamp, envid, locks)); +} + +static inline int __txn_regop_read(ENV *env, + void *data, __txn_regop_args **arg) +{ + *arg = NULL; + return (__log_read_record(env, + NULL, NULL, data, __txn_regop_desc, sizeof(__txn_regop_args), (void**)arg)); +} +#define DB___txn_ckp_42 11 +typedef struct ___txn_ckp_42_args { + u_int32_t type; + DB_TXN *txnp; + DB_LSN prev_lsn; + DB_LSN ckp_lsn; + DB_LSN last_ckp; + int32_t timestamp; + u_int32_t rep_gen; +} __txn_ckp_42_args; + +extern __DB_IMPORT DB_LOG_RECSPEC __txn_ckp_42_desc[]; +static inline int __txn_ckp_42_read(ENV *env, + void *data, __txn_ckp_42_args **arg) +{ + *arg = NULL; + return (__log_read_record(env, + NULL, NULL, data, __txn_ckp_42_desc, sizeof(__txn_ckp_42_args), (void**)arg)); +} +#define DB___txn_ckp 11 +typedef struct ___txn_ckp_args { + u_int32_t type; + DB_TXN *txnp; + DB_LSN prev_lsn; + DB_LSN ckp_lsn; + DB_LSN last_ckp; + int32_t timestamp; + u_int32_t envid; + u_int32_t spare; +} __txn_ckp_args; + +extern __DB_IMPORT DB_LOG_RECSPEC __txn_ckp_desc[]; +static inline int +__txn_ckp_log(ENV *env, DB_TXN *txnp, DB_LSN *ret_lsnp, u_int32_t flags, + DB_LSN * ckp_lsn, DB_LSN * last_ckp, int32_t timestamp, u_int32_t envid, u_int32_t spare) +{ + return (__log_put_record(env, NULL, txnp, ret_lsnp, + flags, DB___txn_ckp, 0, + sizeof(u_int32_t) + sizeof(u_int32_t) + sizeof(DB_LSN) + + sizeof(*ckp_lsn) + sizeof(*last_ckp) + sizeof(u_int32_t) + + sizeof(u_int32_t) + sizeof(u_int32_t), + __txn_ckp_desc, + ckp_lsn, last_ckp, timestamp, envid, spare)); +} + +static inline int __txn_ckp_read(ENV *env, + void *data, __txn_ckp_args **arg) +{ + *arg = NULL; + return (__log_read_record(env, + NULL, NULL, data, __txn_ckp_desc, sizeof(__txn_ckp_args), (void**)arg)); +} +#define DB___txn_child 12 +typedef struct ___txn_child_args { + u_int32_t type; + DB_TXN *txnp; + DB_LSN prev_lsn; + u_int32_t child; + DB_LSN c_lsn; +} __txn_child_args; + +extern __DB_IMPORT DB_LOG_RECSPEC __txn_child_desc[]; +static inline int +__txn_child_log(ENV *env, DB_TXN *txnp, DB_LSN *ret_lsnp, u_int32_t flags, + u_int32_t child, DB_LSN * c_lsn) +{ + return (__log_put_record(env, NULL, txnp, ret_lsnp, + flags, DB___txn_child, 0, + sizeof(u_int32_t) + sizeof(u_int32_t) + sizeof(DB_LSN) + + sizeof(u_int32_t) + sizeof(*c_lsn), + __txn_child_desc, + child, c_lsn)); +} + +static inline int __txn_child_read(ENV *env, + void *data, __txn_child_args **arg) +{ + *arg = NULL; + return (__log_read_record(env, + NULL, NULL, data, __txn_child_desc, sizeof(__txn_child_args), (void**)arg)); +} +#define DB___txn_xa_regop_42 13 +typedef struct ___txn_xa_regop_42_args { + u_int32_t type; + DB_TXN *txnp; + DB_LSN prev_lsn; + u_int32_t opcode; + DBT xid; + int32_t formatID; + u_int32_t gtrid; + u_int32_t bqual; + DB_LSN begin_lsn; + DBT locks; +} __txn_xa_regop_42_args; + +extern __DB_IMPORT DB_LOG_RECSPEC __txn_xa_regop_42_desc[]; +static inline int __txn_xa_regop_42_read(ENV *env, + void *data, __txn_xa_regop_42_args **arg) +{ + *arg = NULL; + return (__log_read_record(env, + NULL, NULL, data, __txn_xa_regop_42_desc, sizeof(__txn_xa_regop_42_args), (void**)arg)); +} +#define DB___txn_prepare 13 +typedef struct ___txn_prepare_args { + u_int32_t type; + DB_TXN *txnp; + DB_LSN prev_lsn; + u_int32_t opcode; + DBT gid; + DB_LSN begin_lsn; + DBT locks; +} __txn_prepare_args; + +extern __DB_IMPORT DB_LOG_RECSPEC __txn_prepare_desc[]; +static inline int +__txn_prepare_log(ENV *env, DB_TXN *txnp, DB_LSN *ret_lsnp, u_int32_t flags, + u_int32_t opcode, const DBT *gid, DB_LSN * begin_lsn, const DBT *locks) +{ + return (__log_put_record(env, NULL, txnp, ret_lsnp, + flags, DB___txn_prepare, 0, + sizeof(u_int32_t) + sizeof(u_int32_t) + sizeof(DB_LSN) + + sizeof(u_int32_t) + LOG_DBT_SIZE(gid) + sizeof(*begin_lsn) + + LOG_DBT_SIZE(locks), + __txn_prepare_desc, + opcode, gid, begin_lsn, locks)); +} + +static inline int __txn_prepare_read(ENV *env, + void *data, __txn_prepare_args **arg) +{ + *arg = NULL; + return (__log_read_record(env, + NULL, NULL, data, __txn_prepare_desc, sizeof(__txn_prepare_args), (void**)arg)); +} +#define DB___txn_recycle 14 +typedef struct ___txn_recycle_args { + u_int32_t type; + DB_TXN *txnp; + DB_LSN prev_lsn; + u_int32_t min; + u_int32_t max; +} __txn_recycle_args; + +extern __DB_IMPORT DB_LOG_RECSPEC __txn_recycle_desc[]; +static inline int +__txn_recycle_log(ENV *env, DB_TXN *txnp, DB_LSN *ret_lsnp, u_int32_t flags, + u_int32_t min, u_int32_t max) +{ + return (__log_put_record(env, NULL, txnp, ret_lsnp, + flags, DB___txn_recycle, 0, + sizeof(u_int32_t) + sizeof(u_int32_t) + sizeof(DB_LSN) + + sizeof(u_int32_t) + sizeof(u_int32_t), + __txn_recycle_desc, + min, max)); +} + +static inline int __txn_recycle_read(ENV *env, + void *data, __txn_recycle_args **arg) +{ + *arg = NULL; + return (__log_read_record(env, + NULL, NULL, data, __txn_recycle_desc, sizeof(__txn_recycle_args), (void**)arg)); +} +#endif diff -r 000000000000 -r a1985f14b030 src/dbinc_auto/txn_ext.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/dbinc_auto/txn_ext.h Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,122 @@ +/* DO NOT EDIT: automatically built by dist/s_include. + * + * Copyright (c) 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ +#ifndef _txn_ext_h_ +#define _txn_ext_h_ + +#if defined(__cplusplus) +extern "C" { +#endif + +int __txn_begin_pp __P((DB_ENV *, DB_TXN *, DB_TXN **, u_int32_t)); +int __txn_begin __P((ENV *, DB_THREAD_INFO *, DB_TXN *, DB_TXN **, u_int32_t)); +int __txn_recycle_id __P((ENV *, int)); +int __txn_continue __P((ENV *, DB_TXN *, TXN_DETAIL *, DB_THREAD_INFO *, int)); +int __txn_commit __P((DB_TXN *, u_int32_t)); +int __txn_abort __P((DB_TXN *)); +int __txn_discard_int __P((DB_TXN *, u_int32_t flags)); +int __txn_prepare __P((DB_TXN *, u_int8_t *)); +u_int32_t __txn_id __P((DB_TXN *)); +int __txn_get_name __P((DB_TXN *, const char **)); +int __txn_set_name __P((DB_TXN *, const char *)); +int __txn_get_priority __P((DB_TXN *, u_int32_t *)); +int __txn_set_priority __P((DB_TXN *, u_int32_t)); +int __txn_set_timeout __P((DB_TXN *, db_timeout_t, u_int32_t)); +int __txn_activekids __P((ENV *, u_int32_t, DB_TXN *)); +int __txn_force_abort __P((ENV *, u_int8_t *)); +int __txn_preclose __P((ENV *)); +int __txn_reset __P((ENV *)); +int __txn_applied_pp __P((DB_ENV *, DB_TXN_TOKEN *, db_timeout_t, u_int32_t)); +int __txn_init_recover __P((ENV *, DB_DISTAB *)); +int __txn_regop_42_print __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __txn_regop_print __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __txn_ckp_42_print __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __txn_ckp_print __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __txn_child_print __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __txn_xa_regop_42_print __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __txn_prepare_print __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __txn_recycle_print __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __txn_init_print __P((ENV *, DB_DISTAB *)); +int __txn_checkpoint_pp __P((DB_ENV *, u_int32_t, u_int32_t, u_int32_t)); +int __txn_checkpoint __P((ENV *, u_int32_t, u_int32_t, u_int32_t)); +int __txn_getactive __P((ENV *, DB_LSN *)); +int __txn_getckp __P((ENV *, DB_LSN *)); +int __txn_updateckp __P((ENV *, DB_LSN *)); +int __txn_failchk __P((ENV *)); +int __txn_env_create __P((DB_ENV *)); +void __txn_env_destroy __P((DB_ENV *)); +int __txn_get_tx_max __P((DB_ENV *, u_int32_t *)); +int __txn_set_tx_max __P((DB_ENV *, u_int32_t)); +int __txn_get_tx_timestamp __P((DB_ENV *, time_t *)); +int __txn_set_tx_timestamp __P((DB_ENV *, time_t *)); +int __db_check_txn __P((DB *, DB_TXN *, DB_LOCKER *, int)); +int __db_txn_deadlock_err __P((ENV *, DB_TXN *)); +int __db_dbtxn_remove __P((DB *, DB_THREAD_INFO *, DB_TXN *, const char *, const char *)); +int __txn_regop_recover __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __txn_prepare_recover __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __txn_ckp_recover __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __txn_child_recover __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __txn_restore_txn __P((ENV *, DB_LSN *, __txn_prepare_args *)); +int __txn_recycle_recover __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __txn_regop_42_recover __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __txn_ckp_42_recover __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); +int __txn_recover_pp __P((DB_ENV *, DB_PREPLIST *, long, long *, u_int32_t)); +int __txn_recover __P((ENV *, DB_PREPLIST *, long, long *, u_int32_t)); +int __txn_get_prepared __P((ENV *, XID *, DB_PREPLIST *, long, long *, u_int32_t)); +int __txn_openfiles __P((ENV *, DB_THREAD_INFO *, DB_LSN *, int)); +int __txn_open __P((ENV *)); +int __txn_findlastckp __P((ENV *, DB_LSN *, DB_LSN *)); +int __txn_env_refresh __P((ENV *)); +u_int32_t __txn_region_mutex_count __P((ENV *)); +u_int32_t __txn_region_mutex_max __P((ENV *)); +size_t __txn_region_size __P((ENV *)); +size_t __txn_region_max __P((ENV *)); +int __txn_id_set __P((ENV *, u_int32_t, u_int32_t)); +int __txn_oldest_reader __P((ENV *, DB_LSN *)); +int __txn_add_buffer __P((ENV *, TXN_DETAIL *)); +int __txn_remove_buffer __P((ENV *, TXN_DETAIL *, db_mutex_t)); +int __txn_stat_pp __P((DB_ENV *, DB_TXN_STAT **, u_int32_t)); +int __txn_stat_print_pp __P((DB_ENV *, u_int32_t)); +int __txn_stat_print __P((ENV *, u_int32_t)); +int __txn_closeevent __P((ENV *, DB_TXN *, DB *)); +int __txn_remevent __P((ENV *, DB_TXN *, const char *, u_int8_t *, int)); +void __txn_remrem __P((ENV *, DB_TXN *, const char *)); +int __txn_lockevent __P((ENV *, DB_TXN *, DB *, DB_LOCK *, DB_LOCKER *)); +void __txn_remlock __P((ENV *, DB_TXN *, DB_LOCK *, DB_LOCKER *)); +int __txn_doevents __P((ENV *, DB_TXN *, int, int)); +int __txn_record_fname __P((ENV *, DB_TXN *, FNAME *)); +int __txn_dref_fname __P((ENV *, DB_TXN *)); +void __txn_reset_fe_watermarks __P((DB_TXN *)); +void __txn_remove_fe_watermark __P((DB_TXN *,DB *)); +void __txn_add_fe_watermark __P((DB_TXN *, DB *, db_pgno_t)); +int __txn_flush_fe_files __P((DB_TXN *)); +int __txn_pg_above_fe_watermark __P((DB_TXN*, MPOOLFILE*, db_pgno_t)); + +#if defined(__cplusplus) +} +#endif +#endif /* !_txn_ext_h_ */ diff -r 000000000000 -r a1985f14b030 src/dbinc_auto/xa_ext.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/dbinc_auto/xa_ext.h Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,44 @@ +/* DO NOT EDIT: automatically built by dist/s_include. + * + * Copyright (c) 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ +#ifndef _xa_ext_h_ +#define _xa_ext_h_ + +#if defined(__cplusplus) +extern "C" { +#endif + +int __db_rmid_to_env __P((int, ENV **)); +int __db_xid_to_txn __P((ENV *, XID *, TXN_DETAIL **)); +void __db_map_rmid __P((int, ENV *)); +int __db_unmap_rmid __P((int)); +void __db_unmap_xid __P((ENV *, XID *, size_t)); + +#if defined(__cplusplus) +} +#endif +#endif /* !_xa_ext_h_ */ diff -r 000000000000 -r a1985f14b030 src/env/env_alloc.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/env/env_alloc.c Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,781 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 1996, 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + * $Id$ + */ + +#include "db_config.h" + +#include "db_int.h" + +/* + * Implement shared memory region allocation. The initial list is a single + * memory "chunk" which is carved up as memory is requested. Chunks are + * coalesced when free'd. We maintain two types of linked-lists: a list of + * all chunks sorted by address, and a set of lists with free chunks sorted + * by size. + * + * The ALLOC_LAYOUT structure is the governing structure for the allocator. + * + * The ALLOC_ELEMENT structure is the structure that describes any single + * chunk of memory, and is immediately followed by the user's memory. + * + * The internal memory chunks are always aligned to a uintmax_t boundary so + * we don't drop core accessing the fields of the ALLOC_ELEMENT structure. + * + * The memory chunks returned to the user are aligned to a uintmax_t boundary. + * This is enforced by terminating the ALLOC_ELEMENT structure with a uintmax_t + * field as that immediately precedes the user's memory. Any caller needing + * more than uintmax_t alignment is responsible for doing alignment themselves. + */ + +typedef SH_TAILQ_HEAD(__sizeq) SIZEQ_HEAD; + +typedef struct __alloc_layout { + SH_TAILQ_HEAD(__addrq) addrq; /* Sorted by address */ + + /* + * A perfect Berkeley DB application does little allocation because + * most things are allocated on startup and never free'd. This is + * true even for the cache, because we don't free and re-allocate + * the memory associated with a cache buffer when swapping a page + * in memory for a page on disk -- unless the page is changing size. + * The latter problem is why we have multiple size queues. If the + * application's working set fits in cache, it's not a problem. If + * the application's working set doesn't fit in cache, but all of + * the databases have the same size pages, it's still not a problem. + * If the application's working set doesn't fit in cache, and its + * databases have different page sizes, we can end up walking a lot + * of 512B chunk allocations looking for an available 64KB chunk. + * + * So, we keep a set of queues, where we expect to find a chunk of + * roughly the right size at the front of the list. The first queue + * is chunks <= 1024, the second is <= 2048, and so on. With 11 + * queues, we have separate queues for chunks up to 1MB. + */ +#define DB_SIZE_Q_COUNT 11 + SIZEQ_HEAD sizeq[DB_SIZE_Q_COUNT]; /* Sorted by size */ +#ifdef HAVE_STATISTICS + u_int32_t pow2_size[DB_SIZE_Q_COUNT]; +#endif + +#ifdef HAVE_STATISTICS + u_int32_t success; /* Successful allocations */ + u_int32_t failure; /* Failed allocations */ + u_int32_t freed; /* Free calls */ + u_int32_t longest; /* Longest chain walked */ +#endif + uintmax_t unused; /* Guarantee alignment */ +} ALLOC_LAYOUT; + +typedef struct __alloc_element { + SH_TAILQ_ENTRY addrq; /* List by address */ + SH_TAILQ_ENTRY sizeq; /* List by size */ + + /* + * The "len" field is the total length of the chunk, not the size + * available to the caller. Use a uintmax_t to guarantee that the + * size of this struct will be aligned correctly. + */ + uintmax_t len; /* Chunk length */ + + /* + * The "ulen" field is the length returned to the caller. + * + * Set to 0 if the chunk is not currently in use. + */ + uintmax_t ulen; /* User's length */ +} ALLOC_ELEMENT; + +/* + * If the chunk can be split into two pieces, with the fragment holding at + * least 64 bytes of memory, we divide the chunk into two parts. + */ +#define SHALLOC_FRAGMENT (sizeof(ALLOC_ELEMENT) + 64) + +/* Macro to find the appropriate queue for a specific size chunk. */ +#undef SET_QUEUE_FOR_SIZE +#define SET_QUEUE_FOR_SIZE(head, q, i, len) do { \ + for (i = 0; i < DB_SIZE_Q_COUNT; ++i) { \ + q = &(head)->sizeq[i]; \ + if ((len) <= (u_int64_t)1024 << i) \ + break; \ + } \ +} while (0) + +static void __env_size_insert __P((ALLOC_LAYOUT *, ALLOC_ELEMENT *)); + +/* + * __env_alloc_init -- + * Initialize the area as one large chunk. + * + * PUBLIC: void __env_alloc_init __P((REGINFO *, size_t)); + */ +void +__env_alloc_init(infop, size) + REGINFO *infop; + size_t size; +{ + ALLOC_ELEMENT *elp; + ALLOC_LAYOUT *head; + ENV *env; + u_int i; + + env = infop->env; + + /* No initialization needed for heap memory regions. */ + if (F_ISSET(env, ENV_PRIVATE)) + return; + + /* + * The first chunk of memory is the ALLOC_LAYOUT structure. + */ + head = infop->head; + memset(head, 0, sizeof(*head)); + SH_TAILQ_INIT(&head->addrq); + for (i = 0; i < DB_SIZE_Q_COUNT; ++i) + SH_TAILQ_INIT(&head->sizeq[i]); + COMPQUIET(head->unused, 0); + + /* + * The rest of the memory is the first available chunk. + */ + elp = (ALLOC_ELEMENT *)((u_int8_t *)head + sizeof(ALLOC_LAYOUT)); + elp->len = size - sizeof(ALLOC_LAYOUT); + elp->ulen = 0; + + SH_TAILQ_INSERT_HEAD(&head->addrq, elp, addrq, __alloc_element); + SH_TAILQ_INSERT_HEAD( + &head->sizeq[DB_SIZE_Q_COUNT - 1], elp, sizeq, __alloc_element); +} + +/* + * The length, the ALLOC_ELEMENT structure and an optional guard byte, + * rounded up to standard alignment. + */ +#ifdef DIAGNOSTIC +#define DB_ALLOC_SIZE(len) \ + (size_t)DB_ALIGN((len) + sizeof(ALLOC_ELEMENT) + 1, sizeof(uintmax_t)) +#else +#define DB_ALLOC_SIZE(len) \ + (size_t)DB_ALIGN((len) + sizeof(ALLOC_ELEMENT), sizeof(uintmax_t)) +#endif + +/* + * __env_alloc_overhead -- + * Return the overhead needed for an allocation. + * + * PUBLIC: size_t __env_alloc_overhead __P((void)); + */ +size_t +__env_alloc_overhead() +{ + return (sizeof(ALLOC_ELEMENT)); +} + +/* + * __env_alloc_size -- + * Return the space needed for an allocation, including alignment. + * + * PUBLIC: size_t __env_alloc_size __P((size_t)); + */ +size_t +__env_alloc_size(len) + size_t len; +{ + return (DB_ALLOC_SIZE(len)); +} + +/* + * __env_alloc -- + * Allocate space from the shared region. + * + * PUBLIC: int __env_alloc __P((REGINFO *, size_t, void *)); + */ +int +__env_alloc(infop, len, retp) + REGINFO *infop; + size_t len; + void *retp; +{ + SIZEQ_HEAD *q; + ALLOC_ELEMENT *elp, *frag, *elp_tmp; + ALLOC_LAYOUT *head; + ENV *env; + REGION_MEM *mem; + REGINFO *envinfop; + size_t total_len; + u_int8_t *p; + u_int i; + int ret; +#ifdef HAVE_STATISTICS + u_int32_t st_search; +#endif + env = infop->env; + *(void **)retp = NULL; +#ifdef HAVE_MUTEX_SUPPORT + MUTEX_REQUIRED(env, infop->mtx_alloc); +#endif + + PERFMON3(env, mpool, env_alloc, len, infop->id, infop->type); + /* + * In a heap-backed environment, we call malloc for additional space. + * (Malloc must return memory correctly aligned for our use.) + * + * In a heap-backed environment, memory is laid out as follows: + * + * { uintmax_t total-length } { user-memory } { guard-byte } + */ + if (F_ISSET(env, ENV_PRIVATE)) { + /* + * If we are shared then we must track the allocation + * in the main environment region. + */ + if (F_ISSET(infop, REGION_SHARED)) + envinfop = env->reginfo; + else + envinfop = infop; + /* + * We need an additional uintmax_t to hold the length (and + * keep the buffer aligned on 32-bit systems). + */ + len += sizeof(uintmax_t); + if (F_ISSET(infop, REGION_TRACKED)) + len += sizeof(REGION_MEM); + +#ifdef DIAGNOSTIC + /* Plus one byte for the guard byte. */ + ++len; +#endif + /* Check if we're over the limit. */ + if (envinfop->max_alloc != 0 && + envinfop->allocated + len > envinfop->max_alloc) + return (ENOMEM); + + /* Allocate the space. */ + if ((ret = __os_malloc(env, len, &p)) != 0) + return (ret); + infop->allocated += len; + if (infop != envinfop) + envinfop->allocated += len; + + *(uintmax_t *)p = len; +#ifdef DIAGNOSTIC + p[len - 1] = GUARD_BYTE; +#endif + if (F_ISSET(infop, REGION_TRACKED)) { + mem = (REGION_MEM *)(p + sizeof(uintmax_t)); + mem->next = infop->mem; + infop->mem = mem; + p += sizeof(mem); + } + *(void **)retp = p + sizeof(uintmax_t); + return (0); + } + + head = infop->head; + total_len = DB_ALLOC_SIZE(len); + + /* Find the first size queue that could satisfy the request. */ + COMPQUIET(q, NULL); +#ifdef HAVE_MMAP_EXTEND +retry: +#endif + SET_QUEUE_FOR_SIZE(head, q, i, total_len); + +#ifdef HAVE_STATISTICS + if (i >= DB_SIZE_Q_COUNT) + i = DB_SIZE_Q_COUNT - 1; + ++head->pow2_size[i]; /* Note the size of the request. */ +#endif + + /* + * Search this queue, and, if necessary, queues larger than this queue, + * looking for a chunk we can use. + */ + STAT(st_search = 0); + for (elp = NULL;; ++q) { + SH_TAILQ_FOREACH(elp_tmp, q, sizeq, __alloc_element) { + STAT(++st_search); + + /* + * Chunks are sorted from largest to smallest -- if + * this chunk is less than what we need, no chunk + * further down the list will be large enough. + */ + if (elp_tmp->len < total_len) + break; + + /* + * This chunk will do... maybe there's a better one, + * but this one will do. + */ + elp = elp_tmp; + + /* + * We might have many chunks of the same size. Stop + * looking if we won't fragment memory by picking the + * current one. + */ + if (elp_tmp->len - total_len <= SHALLOC_FRAGMENT) + break; + } + if (elp != NULL || ++i >= DB_SIZE_Q_COUNT) + break; + } + +#ifdef HAVE_STATISTICS + if (head->longest < st_search) { + head->longest = st_search; + STAT_PERFMON3(env, + mpool, longest_search, len, infop->id, st_search); + } +#endif + + /* + * If we don't find an element of the right size, try to extend + * the region, if not then we are done. + */ + if (elp == NULL) { + ret = ENOMEM; +#ifdef HAVE_MMAP_EXTEND + if (infop->rp->size < infop->rp->max && + (ret = __env_region_extend(env, infop)) == 0) + goto retry; +#endif + STAT_INC_VERB(env, mpool, fail, head->failure, len, infop->id); + return (ret); + } + STAT_INC_VERB(env, mpool, alloc, head->success, len, infop->id); + + /* Pull the chunk off of the size queue. */ + SH_TAILQ_REMOVE(q, elp, sizeq, __alloc_element); + + if (elp->len - total_len > SHALLOC_FRAGMENT) { + frag = (ALLOC_ELEMENT *)((u_int8_t *)elp + total_len); + frag->len = elp->len - total_len; + frag->ulen = 0; + + elp->len = total_len; + + /* The fragment follows the chunk on the address queue. */ + SH_TAILQ_INSERT_AFTER( + &head->addrq, elp, frag, addrq, __alloc_element); + + /* Insert the frag into the correct size queue. */ + __env_size_insert(head, frag); + } + + p = (u_int8_t *)elp + sizeof(ALLOC_ELEMENT); + elp->ulen = len; +#ifdef DIAGNOSTIC + p[len] = GUARD_BYTE; +#endif + *(void **)retp = p; + + return (0); +} + +/* + * __env_alloc_free -- + * Free space into the shared region. + * + * PUBLIC: void __env_alloc_free __P((REGINFO *, void *)); + */ +void +__env_alloc_free(infop, ptr) + REGINFO *infop; + void *ptr; +{ + ALLOC_ELEMENT *elp, *elp_tmp; + ALLOC_LAYOUT *head; + ENV *env; + SIZEQ_HEAD *q; + size_t len; + u_int8_t i, *p; + + env = infop->env; + + /* In a private region, we call free. */ + if (F_ISSET(env, ENV_PRIVATE)) { + /* Find the start of the memory chunk and its length. */ + p = (u_int8_t *)((uintmax_t *)ptr - 1); + len = (size_t)*(uintmax_t *)p; + + infop->allocated -= len; + if (F_ISSET(infop, REGION_SHARED)) + env->reginfo->allocated -= len; + +#ifdef DIAGNOSTIC + /* Check the guard byte. */ + DB_ASSERT(env, p[len - 1] == GUARD_BYTE); + + /* Trash the memory chunk. */ + memset(p, CLEAR_BYTE, len); +#endif + __os_free(env, p); + return; + } + +#ifdef HAVE_MUTEX_SUPPORT + MUTEX_REQUIRED(env, infop->mtx_alloc); +#endif + + head = infop->head; + + p = ptr; + elp = (ALLOC_ELEMENT *)(p - sizeof(ALLOC_ELEMENT)); + + STAT_INC_VERB(env, mpool, free, head->freed, elp->ulen, infop->id); + +#ifdef DIAGNOSTIC + /* Check the guard byte. */ + DB_ASSERT(env, p[elp->ulen] == GUARD_BYTE); + + /* Trash the memory chunk. */ + memset(p, CLEAR_BYTE, (size_t)elp->len - sizeof(ALLOC_ELEMENT)); +#endif + + /* Mark the memory as no longer in use. */ + elp->ulen = 0; + + /* + * Try and merge this chunk with chunks on either side of it. Two + * chunks can be merged if they're contiguous and not in use. + */ + if ((elp_tmp = + SH_TAILQ_PREV(&head->addrq, elp, addrq, __alloc_element)) != NULL && + elp_tmp->ulen == 0 && + (u_int8_t *)elp_tmp + elp_tmp->len == (u_int8_t *)elp) { + /* + * If we're merging the entry into a previous entry, remove the + * current entry from the addr queue and the previous entry from + * its size queue, and merge. + */ + SH_TAILQ_REMOVE(&head->addrq, elp, addrq, __alloc_element); + SET_QUEUE_FOR_SIZE(head, q, i, elp_tmp->len); + SH_TAILQ_REMOVE(q, elp_tmp, sizeq, __alloc_element); + + elp_tmp->len += elp->len; + elp = elp_tmp; + } + if ((elp_tmp = SH_TAILQ_NEXT(elp, addrq, __alloc_element)) != NULL && + elp_tmp->ulen == 0 && + (u_int8_t *)elp + elp->len == (u_int8_t *)elp_tmp) { + /* + * If we're merging the current entry into a subsequent entry, + * remove the subsequent entry from the addr and size queues + * and merge. + */ + SH_TAILQ_REMOVE(&head->addrq, elp_tmp, addrq, __alloc_element); + SET_QUEUE_FOR_SIZE(head, q, i, elp_tmp->len); + SH_TAILQ_REMOVE(q, elp_tmp, sizeq, __alloc_element); + + elp->len += elp_tmp->len; + } + + /* Insert in the correct place in the size queues. */ + __env_size_insert(head, elp); +} + +/* + * __env_alloc_extend -- + * Extend a previously allocated chunk at the end of a region. + * + * PUBLIC: int __env_alloc_extend __P((REGINFO *, void *, size_t *)); + */ +int +__env_alloc_extend(infop, ptr, lenp) + REGINFO *infop; + void *ptr; + size_t *lenp; +{ + ALLOC_ELEMENT *elp, *elp_tmp; + ALLOC_LAYOUT *head; + ENV *env; + SIZEQ_HEAD *q; + size_t len, tlen; + u_int8_t i, *p; + int ret; + + env = infop->env; + + DB_ASSERT(env, !F_ISSET(env, ENV_PRIVATE)); + +#ifdef HAVE_MUTEX_SUPPORT + MUTEX_REQUIRED(env, infop->mtx_alloc); +#endif + + head = infop->head; + + p = ptr; + len = *lenp; + elp = (ALLOC_ELEMENT *)(p - sizeof(ALLOC_ELEMENT)); +#ifdef DIAGNOSTIC + /* Check the guard byte. */ + DB_ASSERT(env, p[elp->ulen] == GUARD_BYTE); +#endif + + /* See if there is anything left in the region. */ +again: if ((elp_tmp = SH_TAILQ_NEXT(elp, addrq, __alloc_element)) != NULL && + elp_tmp->ulen == 0 && + (u_int8_t *)elp + elp->len == (u_int8_t *)elp_tmp) { + /* + * If we're merging the current entry into a subsequent entry, + * remove the subsequent entry from the addr and size queues + * and merge. + */ + SH_TAILQ_REMOVE(&head->addrq, elp_tmp, addrq, __alloc_element); + SET_QUEUE_FOR_SIZE(head, q, i, elp_tmp->len); + SH_TAILQ_REMOVE(q, elp_tmp, sizeq, __alloc_element); + if (elp_tmp->len < len + SHALLOC_FRAGMENT) { + elp->len += elp_tmp->len; + if (elp_tmp->len < len) + len -= (size_t)elp_tmp->len; + else + len = 0; + } else { + tlen = (size_t)elp_tmp->len; + elp_tmp = (ALLOC_ELEMENT *) ((u_int8_t *)elp_tmp + len); + elp_tmp->len = tlen - len; + elp_tmp->ulen = 0; + elp->len += len; + len = 0; + + /* The fragment follows the on the address queue. */ + SH_TAILQ_INSERT_AFTER( + &head->addrq, elp, elp_tmp, addrq, __alloc_element); + + /* Insert the frag into the correct size queue. */ + __env_size_insert(head, elp_tmp); + } + } else if (elp_tmp != NULL) { + __db_errx(env, DB_STR("1583", "block not at end of region")); + return (__env_panic(env, EINVAL)); + } + if (len == 0) + goto done; + + if ((ret = __env_region_extend(env, infop)) != 0) { + if (ret != ENOMEM) + return (ret); + goto done; + } + goto again; + +done: elp->ulen = elp->len - sizeof(ALLOC_ELEMENT); +#ifdef DIAGNOSTIC + elp->ulen -= sizeof(uintmax_t); + /* There was room for the guard byte in the chunk that came in. */ + p[elp->ulen] = GUARD_BYTE; +#endif + *lenp -= len; + infop->allocated += *lenp; + if (F_ISSET(infop, REGION_SHARED)) + env->reginfo->allocated += *lenp; + return (0); +} + +/* + * __env_size_insert -- + * Insert into the correct place in the size queues. + */ +static void +__env_size_insert(head, elp) + ALLOC_LAYOUT *head; + ALLOC_ELEMENT *elp; +{ + SIZEQ_HEAD *q; + ALLOC_ELEMENT *elp_tmp; + u_int i; + + /* Find the appropriate queue for the chunk. */ + SET_QUEUE_FOR_SIZE(head, q, i, elp->len); + + /* Find the correct slot in the size queue. */ + SH_TAILQ_FOREACH(elp_tmp, q, sizeq, __alloc_element) + if (elp->len >= elp_tmp->len) + break; + if (elp_tmp == NULL) + SH_TAILQ_INSERT_TAIL(q, elp, sizeq); + else + SH_TAILQ_INSERT_BEFORE(q, elp_tmp, elp, sizeq, __alloc_element); +} + +/* + * __env_region_extend -- + * Extend a region. + * + * PUBLIC: int __env_region_extend __P((ENV *, REGINFO *)); + */ +int +__env_region_extend(env, infop) + ENV *env; + REGINFO *infop; +{ + ALLOC_ELEMENT *elp; + REGION *rp; + int ret; + + DB_ASSERT(env, !F_ISSET(env, ENV_PRIVATE)); + + ret = 0; + rp = infop->rp; + if (rp->size >= rp->max) + return (ENOMEM); + elp = (ALLOC_ELEMENT *)((u_int8_t *)infop->addr + rp->size); + if (rp->size + rp->alloc > rp->max) + rp->alloc = rp->max - rp->size; + rp->size += rp->alloc; + rp->size = (size_t)ALIGNP_INC(rp->size, sizeof(size_t)); + if (rp->max - rp->size <= SHALLOC_FRAGMENT) + rp->size = rp->max; + if (infop->fhp && + (ret = __db_file_extend(env, infop->fhp, rp->size)) != 0) + return (ret); + elp->len = rp->alloc; + elp->ulen = 0; +#ifdef DIAGNOSTIC + *(u_int8_t *)(elp+1) = GUARD_BYTE; +#endif + + SH_TAILQ_INSERT_TAIL(&((ALLOC_LAYOUT *)infop->head)->addrq, elp, addrq); + __env_alloc_free(infop, elp + 1); + if (rp->alloc < MEGABYTE) + rp->alloc += rp->size; + if (rp->alloc > MEGABYTE) + rp->alloc = MEGABYTE; + return (ret); +} + +/* + * __env_elem_size -- + * Return the size of an allocated element. + * PUBLIC: uintmax_t __env_elem_size __P((ENV *, void *)); + */ +uintmax_t +__env_elem_size(env, p) + ENV *env; + void *p; +{ + ALLOC_ELEMENT *elp; + uintmax_t size; + + if (F_ISSET(env, ENV_PRIVATE)) { + size = *((uintmax_t *)p - 1); + size -= sizeof(uintmax_t); + } else { + elp = (ALLOC_ELEMENT *)((u_int8_t *)p - sizeof(ALLOC_ELEMENT)); + size = elp->ulen; + } + return (size); +} + +/* + * __env_get_chunk -- + * Return the next chunk allocated in a private region. + * PUBLIC: void * __env_get_chunk __P((REGINFO *, void **, uintmax_t *)); + */ +void * +__env_get_chunk(infop, nextp, sizep) + REGINFO *infop; + void **nextp; + uintmax_t *sizep; +{ + REGION_MEM *mem; + + if (infop->mem == NULL) + return (NULL); + if (*nextp == NULL) + *nextp = infop->mem; + mem = *(REGION_MEM **)nextp; + *nextp = mem->next; + + *sizep = __env_elem_size(infop->env, mem); + *sizep -= sizeof(*mem); + + return ((void *)(mem + 1)); +} + +#ifdef HAVE_STATISTICS +/* + * __env_alloc_print -- + * Display the lists of memory chunks. + * + * PUBLIC: void __env_alloc_print __P((REGINFO *, u_int32_t)); + */ +void +__env_alloc_print(infop, flags) + REGINFO *infop; + u_int32_t flags; +{ + ALLOC_ELEMENT *elp; + ALLOC_LAYOUT *head; + ENV *env; + u_int i; + + env = infop->env; + head = infop->head; + + if (F_ISSET(env, ENV_PRIVATE)) + return; + + __db_msg(env, + "Region allocations: %lu allocations, %lu failures, %lu frees, %lu longest", + (u_long)head->success, (u_long)head->failure, (u_long)head->freed, + (u_long)head->longest); + + if (!LF_ISSET(DB_STAT_ALL)) + return; + + __db_msg(env, "%s", "Allocations by power-of-two sizes:"); + for (i = 0; i < DB_SIZE_Q_COUNT; ++i) + __db_msg(env, "%3dKB\t%lu", + (1024 << i) / 1024, (u_long)head->pow2_size[i]); + + if (!LF_ISSET(DB_STAT_ALLOC)) + return; + /* + * We don't normally display the list of address/chunk pairs, a few + * thousand lines of output is too voluminous for even DB_STAT_ALL. + */ + __db_msg(env, + "Allocation list by address, offset: {chunk length, user length}"); + SH_TAILQ_FOREACH(elp, &head->addrq, addrq, __alloc_element) + __db_msg(env, "\t%#lx, %lu {%lu, %lu}", + P_TO_ULONG(elp), (u_long)R_OFFSET(infop, elp), + (u_long)elp->len, (u_long)elp->ulen); + + __db_msg(env, "Allocation free list by size: KB {chunk length}"); + for (i = 0; i < DB_SIZE_Q_COUNT; ++i) { + __db_msg(env, "%3dKB", (1024 << i) / 1024); + SH_TAILQ_FOREACH(elp, &head->sizeq[i], sizeq, __alloc_element) + __db_msg(env, + "\t%#lx {%lu}", P_TO_ULONG(elp), (u_long)elp->len); + } +} +#endif diff -r 000000000000 -r a1985f14b030 src/env/env_config.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/env/env_config.c Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,759 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 1996, 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + * $Id$ + */ + +#include "db_config.h" + +#include "db_int.h" +#include "dbinc/lock.h" +#include "dbinc/log.h" +#include "dbinc/mp.h" +#include "dbinc/txn.h" +#include "dbinc/db_page.h" +#include "dbinc_auto/db_ext.h" + +/* + * DB_CONFIG lines are processed primarily by interpreting the command + * description tables initialized below. + * + * Most DB_CONFIG commands consist of a single token name followed by one or two + * integer or string arguments. These commands are described by entries in the + * config_descs[] array. + * + * The remaining, usually more complex, DB_CONFIG commands are handled by small + * code blocks in __config_parse(). Many of those commands need to translate + * option names to the integer values needed by the API configuration functions. + * Below the __config_descs[] initialization there are many FN array + * initializations which provide the mapping between user-specifiable strings + * and internally-used integer values. Typically there is one of these mappings + * defined for each complex DB_CONFIG command. Use __db_name_to_val() + * to translate a string to its integer value. + */ +typedef enum { + CFG_INT, /* The argument is 1 signed integer. */ + CFG_LONG, /* The argument is 1 signed long int. */ + CFG_UINT, /* The argument is 1 unsigned integer. */ + CFG_2INT, /* The arguments are 2 signed integers. */ + CFG_2UINT, /* The arguments are 2 unsigned integers. */ + CFG_STRING /* The rest of the line is a string. */ +} __db_config_type; + +typedef struct __db_config_desc { + char *name; /* The name of a simple DB_CONFIG command. */ + __db_config_type type; /* The enum describing its argument type(s). */ + int (*func)(); /* The function to call with the argument(s). */ +} CFG_DESC; + +/* These typedefs help eliminate lint warnings where "func" above is used. */ +typedef int (*CFG_FUNC_STRING) __P((DB_ENV *, const char *)); +typedef int (*CFG_FUNC_INT) __P((DB_ENV *, int)); +typedef int (*CFG_FUNC_LONG) __P((DB_ENV *, long)); +typedef int (*CFG_FUNC_UINT) __P((DB_ENV *, u_int32_t)); +typedef int (*CFG_FUNC_2INT) __P((DB_ENV *, int, int)); +typedef int (*CFG_FUNC_2UINT) __P((DB_ENV *, u_int32_t, u_int32_t)); + +/* + * This table lists the simple DB_CONFIG configuration commands. It is sorted by + * the command name, so that __config_scan() can bsearch() it. After making an + * addition to this table, please be sure that it remains sorted. With vi or + * vim, the following command line will do it: + * :/^static const CFG_DESC config_descs/+1, /^}/-1 ! sort + * + * This table can contain aliases. Aliases have different names with identical + * types and functions. At this time there are four aliases: + * Outdated Name Current Name + * db_data_dir set_data_dir + * db_log_dir set_lg_dir + * db_tmp_dir set_tmp_dir + * set_tas_spins mutex_set_tas_spins + */ +static const CFG_DESC config_descs[] = { + { "add_data_dir", CFG_STRING, __env_add_data_dir }, + { "db_data_dir", CFG_STRING, __env_set_data_dir }, + { "db_log_dir", CFG_STRING, __log_set_lg_dir }, + { "db_tmp_dir", CFG_STRING, __env_set_tmp_dir }, + { "mutex_set_align", CFG_UINT, __mutex_set_align }, + { "mutex_set_increment", CFG_UINT, __mutex_set_increment }, + { "mutex_set_init", CFG_UINT, __mutex_set_init }, + { "mutex_set_max", CFG_UINT, __mutex_set_max }, + { "mutex_set_tas_spins", CFG_UINT, __mutex_set_tas_spins }, + { "rep_set_clockskew", CFG_2UINT, __rep_set_clockskew }, + { "rep_set_limit", CFG_2UINT, __rep_set_limit }, + { "rep_set_nsites", CFG_UINT, __rep_set_nsites_pp }, + { "rep_set_priority", CFG_UINT, __rep_set_priority }, + { "rep_set_request", CFG_2UINT, __rep_set_request }, + { "set_cache_max", CFG_2UINT, __memp_set_cache_max }, + { "set_create_dir", CFG_STRING, __env_set_create_dir }, + { "set_data_dir", CFG_STRING, __env_set_data_dir }, + { "set_data_len", CFG_UINT, __env_set_data_len }, + { "set_intermediate_dir_mode",CFG_STRING, __env_set_intermediate_dir_mode }, + { "set_lg_bsize", CFG_UINT, __log_set_lg_bsize }, + { "set_lg_dir", CFG_STRING, __log_set_lg_dir }, + { "set_lg_filemode", CFG_INT, __log_set_lg_filemode }, + { "set_lg_max", CFG_UINT, __log_set_lg_max }, + { "set_lg_regionmax", CFG_UINT, __log_set_lg_regionmax }, + { "set_lk_max_lockers", CFG_UINT, __lock_set_lk_max_lockers }, + { "set_lk_max_locks", CFG_UINT, __lock_set_lk_max_locks }, + { "set_lk_max_objects", CFG_UINT, __lock_set_lk_max_objects }, + { "set_lk_partitions", CFG_UINT, __lock_set_lk_partitions }, + { "set_lk_tablesize", CFG_UINT, __lock_set_lk_tablesize }, + { "set_memory_max", CFG_2UINT, __env_set_memory_max }, + { "set_metadata_dir", CFG_STRING, __env_set_metadata_dir }, + { "set_mp_max_openfd", CFG_INT, __memp_set_mp_max_openfd }, + { "set_mp_max_write", CFG_2INT, __memp_set_mp_max_write }, + { "set_mp_mmapsize", CFG_UINT, __memp_set_mp_mmapsize }, + { "set_mp_mtxcount", CFG_UINT, __memp_set_mp_mtxcount }, + { "set_mp_pagesize", CFG_UINT, __memp_set_mp_pagesize }, + { "set_shm_key", CFG_LONG, __env_set_shm_key }, + { "set_tas_spins", CFG_UINT, __mutex_set_tas_spins }, + { "set_thread_count", CFG_UINT, __env_set_thread_count }, + { "set_tmp_dir", CFG_STRING, __env_set_tmp_dir }, + { "set_tx_max", CFG_UINT, __txn_set_tx_max } +}; + +/* + * Here are the option-name to option-value mappings used by complex commands. + */ +static const FN config_mem_init[] = { + { (u_int32_t) DB_MEM_LOCK, "DB_MEM_LOCK" }, + { (u_int32_t) DB_MEM_LOCKER, "DB_MEM_LOCKER" }, + { (u_int32_t) DB_MEM_LOCKOBJECT, "DB_MEM_LOCKOBJECT" }, + { (u_int32_t) DB_MEM_TRANSACTION, "DB_MEM_TRANSACTION" }, + { (u_int32_t) DB_MEM_THREAD, "DB_MEM_THREAD" }, + { (u_int32_t) DB_MEM_LOGID, "DB_MEM_LOGID" }, + { 0, NULL } +}; + +static const FN config_rep_config[] = { + { DB_REP_CONF_AUTOINIT, "db_rep_conf_autoinit" }, + { DB_REP_CONF_AUTOROLLBACK, "db_rep_conf_autorollback" }, + { DB_REP_CONF_BULK, "db_rep_conf_bulk" }, + { DB_REP_CONF_DELAYCLIENT, "db_rep_conf_delayclient" }, + { DB_REP_CONF_INMEM, "db_rep_conf_inmem" }, + { DB_REP_CONF_LEASE, "db_rep_conf_lease" }, + { DB_REP_CONF_NOWAIT, "db_rep_conf_nowait" }, + { DB_REPMGR_CONF_2SITE_STRICT, "db_repmgr_conf_2site_strict" }, + { DB_REPMGR_CONF_ELECTIONS, "db_repmgr_conf_elections" }, + { 0, NULL } +}; + +static const FN config_rep_timeout[] = { + { DB_REP_ACK_TIMEOUT, "db_rep_ack_timeout" }, + { DB_REP_CHECKPOINT_DELAY, "db_rep_checkpoint_delay" }, + { DB_REP_CONNECTION_RETRY, "db_rep_connection_retry" }, + { DB_REP_ELECTION_TIMEOUT, "db_rep_election_timeout" }, + { DB_REP_ELECTION_RETRY, "db_rep_election_retry" }, + { DB_REP_FULL_ELECTION_TIMEOUT, "db_rep_full_election_timeout" }, + { DB_REP_HEARTBEAT_MONITOR, "db_rep_heartbeat_monitor" }, + { DB_REP_HEARTBEAT_SEND, "db_rep_heartbeat_send" }, + { DB_REP_LEASE_TIMEOUT, "db_rep_lease_timeout" }, + { 0, NULL } +}; + +static const FN config_repmgr_ack_policy[] = { + { DB_REPMGR_ACKS_ALL, "db_repmgr_acks_all" }, + { DB_REPMGR_ACKS_ALL_AVAILABLE, "db_repmgr_acks_all_available" }, + { DB_REPMGR_ACKS_ALL_PEERS, "db_repmgr_acks_all_peers" }, + { DB_REPMGR_ACKS_NONE, "db_repmgr_acks_none" }, + { DB_REPMGR_ACKS_ONE, "db_repmgr_acks_one" }, + { DB_REPMGR_ACKS_ONE_PEER, "db_repmgr_acks_one_peer" }, + { DB_REPMGR_ACKS_QUORUM, "db_repmgr_acks_quorum" }, + { 0, NULL } +}; + +static const FN config_repmgr_site[] = { + { DB_BOOTSTRAP_HELPER, "db_bootstrap_helper" }, + { DB_GROUP_CREATOR, "db_group_creator" }, + { DB_LEGACY, "db_legacy" }, + { DB_LOCAL_SITE, "db_local_site" }, + { DB_REPMGR_PEER, "db_repmgr_peer" }, + { 0, NULL } +}; + +static const FN config_set_flags[] = { + { DB_AUTO_COMMIT, "db_auto_commit" }, + { DB_CDB_ALLDB, "db_cdb_alldb" }, + { DB_DIRECT_DB, "db_direct_db" }, + { DB_DSYNC_DB, "db_dsync_db" }, + { DB_MULTIVERSION, "db_multiversion" }, + { DB_NOLOCKING, "db_nolocking" }, + { DB_NOMMAP, "db_nommap" }, + { DB_NOPANIC, "db_nopanic" }, + { DB_OVERWRITE, "db_overwrite" }, + { DB_REGION_INIT, "db_region_init" }, + { DB_TIME_NOTGRANTED, "db_time_notgranted" }, + { DB_TXN_NOSYNC, "db_txn_nosync" }, + { DB_TXN_NOWAIT, "db_txn_nowait" }, + { DB_TXN_SNAPSHOT, "db_txn_snapshot" }, + { DB_TXN_WRITE_NOSYNC, "db_txn_write_nosync" }, + { DB_YIELDCPU, "db_yieldcpu" }, + { 0, NULL } +}; + +static const FN config_set_flags_forlog[] = { + { DB_LOG_DIRECT, "db_direct_log" }, + { DB_LOG_DSYNC, "db_dsync_log" }, + { DB_LOG_AUTO_REMOVE, "db_log_autoremove" }, + { DB_LOG_IN_MEMORY, "db_log_inmemory" }, + { 0, NULL } +}; + +static const FN config_log_set_config[] = { + { DB_LOG_DIRECT, "db_log_direct" }, + { DB_LOG_DSYNC, "db_log_dsync" }, + { DB_LOG_AUTO_REMOVE, "db_log_auto_remove" }, + { DB_LOG_IN_MEMORY, "db_log_in_memory" }, + { DB_LOG_ZERO, "db_log_zero" }, + { 0, NULL } +}; + +static const FN config_set_lk_detect[] = { + { DB_LOCK_DEFAULT, "db_lock_default" }, + { DB_LOCK_EXPIRE, "db_lock_expire" }, + { DB_LOCK_MAXLOCKS, "db_lock_maxlocks" }, + { DB_LOCK_MAXWRITE, "db_lock_maxwrite" }, + { DB_LOCK_MINLOCKS, "db_lock_minlocks" }, + { DB_LOCK_MINWRITE, "db_lock_minwrite" }, + { DB_LOCK_OLDEST, "db_lock_oldest" }, + { DB_LOCK_RANDOM, "db_lock_random" }, + { DB_LOCK_YOUNGEST, "db_lock_youngest" }, + { 0, NULL } +}; + +static const FN config_set_open_flags[] = { + { DB_INIT_REP, "db_init_rep" }, + { DB_PRIVATE, "db_private" }, + { DB_REGISTER, "db_register" }, + { DB_THREAD, "db_thread" }, + { 0, NULL } +}; + +static const FN config_set_verbose[] = { + { DB_VERB_BACKUP, "db_verb_backup" }, + { DB_VERB_DEADLOCK, "db_verb_deadlock" }, + { DB_VERB_FILEOPS, "db_verb_fileops" }, + { DB_VERB_FILEOPS_ALL, "db_verb_fileops_all" }, + { DB_VERB_RECOVERY, "db_verb_recovery" }, + { DB_VERB_REGISTER, "db_verb_register" }, + { DB_VERB_REPLICATION, "db_verb_replication" }, + { DB_VERB_REP_ELECT, "db_verb_rep_elect" }, + { DB_VERB_REP_LEASE, "db_verb_rep_lease" }, + { DB_VERB_REP_MISC, "db_verb_rep_misc" }, + { DB_VERB_REP_MSGS, "db_verb_rep_msgs" }, + { DB_VERB_REP_SYNC, "db_verb_rep_sync" }, + { DB_VERB_REP_SYSTEM, "db_verb_rep_system" }, + { DB_VERB_REP_TEST, "db_verb_rep_test" }, + { DB_VERB_REPMGR_CONNFAIL, "db_verb_repmgr_connfail" }, + { DB_VERB_REPMGR_MISC, "db_verb_repmgr_misc" }, + { DB_VERB_WAITSFOR, "db_verb_waitsfor" }, + { 0, NULL} +}; + +static int __config_parse __P((ENV *, char *, int)); +static int __config_scan __P((char *, char **, const CFG_DESC **)); +static int cmp_cfg_name __P((const void *, const void *element)); + +/* + * __env_read_db_config -- + * Read the DB_CONFIG file. + * + * PUBLIC: int __env_read_db_config __P((ENV *)); + */ +int +__env_read_db_config(env) + ENV *env; +{ + FILE *fp; + int lc, ret; + char *p, buf[256]; + + /* Parse the config file. */ + p = NULL; + if ((ret = __db_appname(env, + DB_APP_NONE, "DB_CONFIG", NULL, &p)) != 0) + return (ret); + if (p == NULL) + fp = NULL; + else { + fp = fopen(p, "r"); + __os_free(env, p); + } + + if (fp == NULL) + return (0); + + for (lc = 1; fgets(buf, sizeof(buf), fp) != NULL; ++lc) { + if ((p = strchr(buf, '\n')) == NULL) + p = buf + strlen(buf); + if (p > buf && p[-1] == '\r') + --p; + *p = '\0'; + for (p = buf; *p != '\0' && isspace((int)*p); ++p) + ; + if (*p == '\0' || *p == '#') + continue; + + if ((ret = __config_parse(env, p, lc)) != 0) + break; + } + (void)fclose(fp); + + return (ret); +} + +#undef CFG_GET_INT +#define CFG_GET_INT(s, vp) do { \ + int __ret; \ + if ((__ret = \ + __db_getlong(env->dbenv, NULL, s, 0, INT_MAX, vp)) != 0) \ + return (__ret); \ +} while (0) +#undef CFG_GET_LONG +#define CFG_GET_LONG(s, vp) do { \ + int __ret; \ + if ((__ret = \ + __db_getlong(env->dbenv, NULL, s, 0, LONG_MAX, vp)) != 0) \ + return (__ret); \ +} while (0) +#undef CFG_GET_UINT +#define CFG_GET_UINT(s, vp) do { \ + int __ret; \ + if ((__ret = \ + __db_getulong(env->dbenv, NULL, s, 0, UINT_MAX, vp)) != 0) \ + return (__ret); \ +} while (0) +#undef CFG_GET_UINT32 +#define CFG_GET_UINT32(s, vp) do { \ + if (__db_getulong(env->dbenv, NULL, s, 0, UINT32_MAX, vp) != 0) \ + return (EINVAL); \ +} while (0) + +/* This is the maximum number of tokens in a DB_CONFIG line. */ +#undef CFG_SLOTS +#define CFG_SLOTS 10 + +/* + * __config_parse -- + * Parse a single NAME VALUE pair. + */ +static int +__config_parse(env, s, lc) + ENV *env; + char *s; + int lc; +{ + DB_ENV *dbenv; + DB_SITE *site; + u_long uv1, uv2; + long lv1, lv2; + u_int port; + int i, nf, onoff, bad, ret, t_ret; + char *argv[CFG_SLOTS]; + const CFG_DESC *desc; + + bad = 0; + dbenv = env->dbenv; + + /* + * Split the input line in 's' into its argv-like components, returning + * the number of fields. If the command is one of the "simple" ones in + * config_descs, also return its command descriptor. + */ + if ((nf = __config_scan(s, argv, &desc)) < 2) { +format: __db_errx(env, DB_STR_A("1584", + "line %d: %s: incorrect name-value pair", "%d %s"), + lc, argv[0]); + return (EINVAL); + } + + /* Handle simple configuration lines here. */ + if (desc != NULL) { + ret = 0; + switch (desc->type) { + case CFG_INT: /* */ + if (nf != 2) + goto format; + CFG_GET_INT(argv[1], &lv1); + ret = ((CFG_FUNC_INT)desc->func)(dbenv, (int) lv1); + break; + + case CFG_LONG: /* */ + if (nf != 2) + goto format; + CFG_GET_LONG(argv[1], &lv1); + ret = ((CFG_FUNC_LONG)desc->func)(dbenv, lv1); + break; + + case CFG_UINT: /* */ + if (nf != 2) + goto format; + CFG_GET_UINT(argv[1], &uv1); + ret = ((CFG_FUNC_UINT)desc->func) + (dbenv, (u_int32_t) uv1); + break; + + case CFG_2INT: /* */ + if (nf != 3) + goto format; + CFG_GET_INT(argv[1], &lv1); + CFG_GET_INT(argv[2], &lv2); + ret = ((CFG_FUNC_2INT)desc->func) + (dbenv, (int) lv1, (int) lv2); + break; + + case CFG_2UINT: /* */ + if (nf != 3) + goto format; + CFG_GET_UINT(argv[1], &uv1); + CFG_GET_UINT(argv[2], &uv2); + ret = ((CFG_FUNC_2UINT)desc->func) + (dbenv, (u_int32_t) uv1, (u_int32_t) uv2); + break; + + case CFG_STRING: /* */ + ret = ((CFG_FUNC_STRING) desc->func)(dbenv, argv[1]); + break; + } + return (ret); + } + + /* + * The commands not covered in config_descs are handled below, each + * with their own command-specific block of code. Most of them are + * fairly similar to each other, but not quite enough to warrant + * that they all be table-driven too. + */ + + /* set_memory_init db_mem_XXX */ + if (strcasecmp(argv[0], "set_memory_init") == 0) { + if (nf != 3) + goto format; + if ((lv1 = __db_name_to_val(config_mem_init, argv[1])) == -1) + goto format; + CFG_GET_UINT32(argv[2], &uv2); + return (__env_set_memory_init(dbenv, + (DB_MEM_CONFIG) lv1, (u_int32_t)uv2)); + } + + /* rep_set_config { db_rep_conf_XXX | db_repmgr_conf_XXX } [on|off] */ + if (strcasecmp(argv[0], "rep_set_config") == 0) { + if (nf != 2 && nf != 3) + goto format; + onoff = 1; + if (nf == 3) { + if (strcasecmp(argv[2], "off") == 0) + onoff = 0; + else if (strcasecmp(argv[2], "on") != 0) + goto format; + } + if ((lv1 = __db_name_to_val(config_rep_config, argv[1])) == -1) + goto format; + return (__rep_set_config(dbenv, (u_int32_t)lv1, onoff)); + } + + /* rep_set_timeout db_rep_XXX */ + if (strcasecmp(argv[0], "rep_set_timeout") == 0) { + if (nf != 3) + goto format; + if ((lv1 = __db_name_to_val(config_rep_timeout, argv[1])) == -1) + goto format; + CFG_GET_UINT32(argv[2], &uv2); + return (__rep_set_timeout(dbenv, lv1, (db_timeout_t)uv2)); + } + + /* repmgr_set_ack_policy db_repmgr_acks_XXX */ + if (strcasecmp(argv[0], "repmgr_set_ack_policy") == 0) { + if (nf != 2) + goto format; + if ((lv1 = + __db_name_to_val(config_repmgr_ack_policy, argv[1])) == -1) + goto format; + return (__repmgr_set_ack_policy(dbenv, lv1)); + } + + /* + * Configure name/value pairs of config information for a site (local or + * remote). + * + * repmgr_site host port [which value(on | off | unsigned)}] ... + */ + if (strcasecmp(argv[0], "repmgr_site") == 0) { + if (nf < 3 || (nf % 2) == 0) + goto format; + CFG_GET_UINT(argv[2], &uv2); + port = (u_int)uv2; + + if ((ret = __repmgr_site(dbenv, argv[1], port, &site, 0)) != 0) + return (ret); +#ifdef HAVE_REPLICATION_THREADS + for (i = 3; i < nf; i += 2) { + if ((lv1 = __db_name_to_val( + config_repmgr_site, argv[i])) == -1) { + bad = 1; + break; + } + + if (strcasecmp(argv[i + 1], "on") == 0) + uv2 = 1; + else if (strcasecmp(argv[i + 1], "off") == 0) + uv2 = 0; + else + CFG_GET_UINT32(argv[i + 1], &uv2); + if ((ret = __repmgr_site_config(site, + (u_int32_t)lv1, (u_int32_t)uv2)) != 0) + break; + } + if ((t_ret = __repmgr_site_close(site)) != 0 && ret == 0) + ret = t_ret; + if (bad) + goto format; +#else + /* If repmgr not built, __repmgr_site() returns DB_OPNOTSUP. */ + COMPQUIET(i, 0); + COMPQUIET(t_ret, 0); + DB_ASSERT(env, 0); +#endif + return (ret); + } + + /* set_cachesize */ + if (strcasecmp(argv[0], "set_cachesize") == 0) { + if (nf != 4) + goto format; + CFG_GET_UINT32(argv[1], &uv1); + CFG_GET_UINT32(argv[2], &uv2); + CFG_GET_INT(argv[3], &lv1); + return (__memp_set_cachesize( + dbenv, (u_int32_t)uv1, (u_int32_t)uv2, (int)lv1)); + } + + /* set_intermediate_dir */ + if (strcasecmp(argv[0], "set_intermediate_dir") == 0) { + if (nf != 2) + goto format; + CFG_GET_INT(argv[1], &lv1); + if (lv1 <= 0) + goto format; + env->dir_mode = (int)lv1; + return (0); + } + + /* set_flags [on | off] */ + if (strcasecmp(argv[0], "set_flags") == 0) { + if (nf != 2 && nf != 3) + goto format; + onoff = 1; + if (nf == 3) { + if (strcasecmp(argv[2], "off") == 0) + onoff = 0; + else if (strcasecmp(argv[2], "on") != 0) + goto format; + } + /* First see whether it is an env flag, then a log flag. */ + if ((lv1 = __db_name_to_val(config_set_flags, argv[1])) != -1) + return (__env_set_flags(dbenv, (u_int32_t)lv1, onoff)); + else if ((lv1 = + __db_name_to_val(config_set_flags_forlog, argv[1])) != -1) + return (__log_set_config(dbenv, (u_int32_t)lv1, onoff)); + goto format; + } + + /* log_set_config [on | off] */ + if (strcasecmp(argv[0], "log_set_config") == 0) { + if (nf != 2 && nf != 3) + goto format; + onoff = 1; + if (nf == 3) { + if (strcasecmp(argv[2], "off") == 0) + onoff = 0; + else if (strcasecmp(argv[2], "on") != 0) + goto format; + } + if ((lv1 = + __db_name_to_val(config_log_set_config, argv[1])) == -1) + goto format; + return (__log_set_config(dbenv, (u_int32_t)lv1, onoff)); + } + + /* set_lk_detect db_lock_xxx */ + if (strcasecmp(argv[0], "set_lk_detect") == 0) { + if (nf != 2) + goto format; + if ((lv1 = + __db_name_to_val(config_set_lk_detect, argv[1])) == -1) + goto format; + return (__lock_set_lk_detect(dbenv, (u_int32_t)lv1)); + } + + /* set_lock_timeout */ + if (strcasecmp(argv[0], "set_lock_timeout") == 0) { + if (nf != 2) + goto format; + CFG_GET_UINT32(argv[1], &uv1); + return (__lock_set_env_timeout( + dbenv, (u_int32_t)uv1, DB_SET_LOCK_TIMEOUT)); + } + + /* set_open_flags [on | off] */ + if (strcasecmp(argv[0], "set_open_flags") == 0) { + if (nf != 2 && nf != 3) + goto format; + onoff = 1; + if (nf == 3) { + if (strcasecmp(argv[2], "off") == 0) + onoff = 0; + else if (strcasecmp(argv[2], "on") != 0) + goto format; + } + if ((lv1 = + __db_name_to_val(config_set_open_flags, argv[1])) == -1) + goto format; + if (onoff == 1) + FLD_SET(env->open_flags, (u_int32_t)lv1); + else + FLD_CLR(env->open_flags, (u_int32_t)lv1); + return (0); + } + + /* set_region_init <0 or 1> */ + if (strcasecmp(argv[0], "set_region_init") == 0) { + if (nf != 2) + goto format; + CFG_GET_INT(argv[1], &lv1); + if (lv1 != 0 && lv1 != 1) + goto format; + return (__env_set_flags( + dbenv, DB_REGION_INIT, lv1 == 0 ? 0 : 1)); + } + + /* set_reg_timeout */ + if (strcasecmp(argv[0], "set_reg_timeout") == 0) { + if (nf != 2) + goto format; + CFG_GET_UINT32(argv[1], &uv1); + return (__env_set_timeout( + dbenv, (u_int32_t)uv1, DB_SET_REG_TIMEOUT)); + } + + /* set_txn_timeout */ + if (strcasecmp(argv[0], "set_txn_timeout") == 0) { + if (nf != 2) + goto format; + CFG_GET_UINT32(argv[1], &uv1); + return (__lock_set_env_timeout( + dbenv, (u_int32_t)uv1, DB_SET_TXN_TIMEOUT)); + } + + /* set_verbose db_verb_XXX [on | off] */ + if (strcasecmp(argv[0], "set_verbose") == 0) { + if (nf != 2 && nf != 3) + goto format; + onoff = 1; + if (nf == 3) { + if (strcasecmp(argv[2], "off") == 0) + onoff = 0; + else if (strcasecmp(argv[2], "on") != 0) + goto format; + } + if ((lv1 = __db_name_to_val(config_set_verbose, argv[1])) == -1) + goto format; + return (__env_set_verbose(dbenv, (u_int32_t)lv1, onoff)); + } + + __db_errx(env, + DB_STR_A("1585", "unrecognized name-value pair: %s", "%s"), s); + return (EINVAL); +} + +/* cmp_cfg_name -- + * Bsearch comparison function for CFG_DESC.name, for looking up + * the names of simple commmands. + */ +static int +cmp_cfg_name(sought, element) + const void *sought; + const void *element; +{ + return + (strcmp((const char *) sought, ((const CFG_DESC *) element)->name)); +} + +/* + * __config_scan -- + * Split DB_CONFIG lines into fields. Usually each whitespace separated + * field is scanned as a distinct argument. However, if the command is + * recognized as one needing a single string value, then the rest of the + * line is returned as the one argument. That supports strings which + * contain whitespaces, such as some directory paths. + * + * This returns the number of fields. It sets *descptr to the command + * descriptor (if it is recognized), or NULL. + */ +static int +__config_scan(input, argv, descptr) + char *input, *argv[CFG_SLOTS]; + const CFG_DESC **descptr; +{ + size_t tablecount; + int count; + char **ap; + + tablecount = sizeof(config_descs) / sizeof(config_descs[0]); + *descptr = NULL; + for (count = 0, ap = argv; (*ap = strsep(&input, " \t\n")) != NULL;) { + /* Empty tokens are adjacent whitespaces; skip them. */ + if (**ap == '\0') + continue; + /* Accept a non-empty token as the next field. */ + count++; + ap++; + /* + * If that was the first token, look it up in the simple command + * table. If it is there and takes a single string value, then + * return the remainder of the line (after skipping over any + * leading whitespaces) without splitting it further. + */ + if (count == 1) { + *descptr = bsearch(argv[0], config_descs, + tablecount, sizeof(config_descs[0]), cmp_cfg_name); + if (*descptr != NULL && + (*descptr)->type == CFG_STRING) { + count++; + while (isspace(*input)) + input++; + *ap++ = input; + break; + } + } + /* Stop scanning if the line has too many tokens. */ + if (count >= CFG_SLOTS) + break; + } + return (count); +} diff -r 000000000000 -r a1985f14b030 src/env/env_file.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/env/env_file.c Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,150 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 2002, 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + * $Id$ + */ + +#include "db_config.h" + +#include "db_int.h" + +/* + * __db_file_extend -- + * Initialize a regular file by writing the last page of the file. + * + * PUBLIC: int __db_file_extend __P((ENV *, DB_FH *, size_t)); + */ +int +__db_file_extend(env, fhp, size) + ENV *env; + DB_FH *fhp; + size_t size; +{ + db_pgno_t pages; + size_t nw; + u_int32_t relative; + int ret; + char buf; + + buf = '\0'; + /* + * Extend the file by writing the last page. If the region is >4Gb, + * increment may be larger than the maximum possible seek "relative" + * argument, as it's an unsigned 32-bit value. Break the offset into + * pages of 1MB each so we don't overflow -- (2^20 * 2^32 is bigger + * than any memory I expect to see for awhile). + */ + pages = (db_pgno_t)((size - sizeof(buf)) / MEGABYTE); + relative = (u_int32_t)((size - sizeof(buf)) % MEGABYTE); + if ((ret = __os_seek(env, fhp, pages, MEGABYTE, relative)) == 0) + ret = __os_write(env, fhp, &buf, sizeof(buf), &nw); + + return (ret); +} + +/* + * __db_file_multi_write -- + * Overwrite a file with multiple passes to corrupt the data. + * + * PUBLIC: int __db_file_multi_write __P((ENV *, const char *)); + */ +int +__db_file_multi_write(env, path) + ENV *env; + const char *path; +{ + DB_FH *fhp; + u_int32_t mbytes, bytes; + int ret; + + if ((ret = __os_open(env, path, 0, DB_OSO_REGION, 0, &fhp)) == 0 && + (ret = __os_ioinfo(env, path, fhp, &mbytes, &bytes, NULL)) == 0) { + /* + * !!! + * Overwrite a regular file with alternating 0xff, 0x00 and 0xff + * byte patterns. Implies a fixed-block filesystem, journaling + * or logging filesystems will require operating system support. + */ + if ((ret = + __db_file_write(env, fhp, mbytes, bytes, 255)) != 0) + goto err; + if ((ret = + __db_file_write(env, fhp, mbytes, bytes, 0)) != 0) + goto err; + if ((ret = + __db_file_write(env, fhp, mbytes, bytes, 255)) != 0) + goto err; + } else + __db_err(env, ret, "%s", path); + +err: if (fhp != NULL) + (void)__os_closehandle(env, fhp); + return (ret); +} + +/* + * __db_file_write -- + * A single pass over the file, writing the specified byte pattern. + * + * PUBLIC: int __db_file_write __P((ENV *, + * PUBLIC: DB_FH *, u_int32_t, u_int32_t, int)); + */ +int +__db_file_write(env, fhp, mbytes, bytes, pattern) + ENV *env; + DB_FH *fhp; + int pattern; + u_int32_t mbytes, bytes; +{ + size_t len, nw; + int i, ret; + char *buf; + +#undef FILE_WRITE_IO_SIZE +#define FILE_WRITE_IO_SIZE (64 * 1024) + if ((ret = __os_malloc(env, FILE_WRITE_IO_SIZE, &buf)) != 0) + return (ret); + memset(buf, pattern, FILE_WRITE_IO_SIZE); + + if ((ret = __os_seek(env, fhp, 0, 0, 0)) != 0) + goto err; + for (; mbytes > 0; --mbytes) + for (i = MEGABYTE / FILE_WRITE_IO_SIZE; i > 0; --i) + if ((ret = __os_write( + env, fhp, buf, FILE_WRITE_IO_SIZE, &nw)) != 0) + goto err; + for (; bytes > 0; bytes -= (u_int32_t)len) { + len = bytes < FILE_WRITE_IO_SIZE ? bytes : FILE_WRITE_IO_SIZE; + if ((ret = __os_write(env, fhp, buf, len, &nw)) != 0) + goto err; + } + + ret = __os_fsync(env, fhp); + +err: __os_free(env, buf); + return (ret); +} diff -r 000000000000 -r a1985f14b030 src/env/env_globals.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/env/env_globals.c Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,88 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 1999, 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + * $Id$ + */ + +#include "db_config.h" + +#include "db_int.h" + +/* + * A structure with static initialization values for all of the global fields + * used by Berkeley DB. + * See dbinc/globals.h for the structure definition. + */ +DB_GLOBALS __db_global_values = { +#ifdef HAVE_VXWORKS + 0, /* VxWorks: db_global_init */ + NULL, /* VxWorks: db_global_lock */ +#endif +#ifdef DB_WIN32 +#ifndef DB_WINCE + { 0 }, /* SECURITY_DESCRIPTOR win_default_sec_desc */ + { 0 }, /* SECURITY_ATTRIBUTES win_default_sec_attr */ +#endif + NULL, /* SECURITY_ATTRIBUTES *win_sec_attr */ +#endif + { NULL, NULL }, /* XA env list */ + + "=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=", /* db_line */ + { 0 }, /* error_buf */ + 0, /* uid_init */ + 0, /* rand_next */ + 0, /* fid_serial */ + 0, /* db_errno */ + 0, /* num_active_pids */ + 0, /* size_active_pids */ + NULL, /* active_pids */ + NULL, /* saved_errstr */ + NULL, /* j_assert */ + NULL, /* j_close */ + NULL, /* j_dirfree */ + NULL, /* j_dirlist */ + NULL, /* j_exists*/ + NULL, /* j_free */ + NULL, /* j_fsync */ + NULL, /* j_ftruncate */ + NULL, /* j_ioinfo */ + NULL, /* j_malloc */ + NULL, /* j_file_map */ + NULL, /* j_file_unmap */ + NULL, /* j_open */ + NULL, /* j_pread */ + NULL, /* j_pwrite */ + NULL, /* j_read */ + NULL, /* j_realloc */ + NULL, /* j_region_map */ + NULL, /* j_region_unmap */ + NULL, /* j_rename */ + NULL, /* j_seek */ + NULL, /* j_unlink */ + NULL, /* j_write */ + NULL /* j_yield */ +}; diff -r 000000000000 -r a1985f14b030 src/env/env_method.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/env/env_method.c Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,1782 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 1999, 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + * $Id: env_method.c,v dabaaeb7d839 2010/08/03 17:28:53 mike $ + */ + +#include "db_config.h" + +#include "db_int.h" +#include "dbinc/crypto.h" +#include "dbinc/hmac.h" +#include "dbinc/db_page.h" +#include "dbinc/db_am.h" +#include "dbinc/lock.h" +#include "dbinc/mp.h" +#include "dbinc/txn.h" + +static int __db_env_init __P((DB_ENV *)); +static void __env_err __P((const DB_ENV *, int, const char *, ...)); +static void __env_errx __P((const DB_ENV *, const char *, ...)); +static int __env_get_create_dir __P((DB_ENV *, const char **)); +static int __env_get_data_dirs __P((DB_ENV *, const char ***)); +static int __env_get_data_len __P((DB_ENV *, u_int32_t *)); +static int __env_get_flags __P((DB_ENV *, u_int32_t *)); +static int __env_get_home __P((DB_ENV *, const char **)); +static int __env_get_intermediate_dir_mode __P((DB_ENV *, const char **)); +static int __env_get_metadata_dir __P((DB_ENV *, const char **)); +static int __env_get_shm_key __P((DB_ENV *, long *)); +static int __env_get_thread_count __P((DB_ENV *, u_int32_t *)); +static int __env_get_thread_id_fn __P((DB_ENV *, + void (**)(DB_ENV *, pid_t *, db_threadid_t *))); +static int __env_get_thread_id_string_fn __P((DB_ENV *, + char * (**)(DB_ENV *, pid_t, db_threadid_t, char *))); +static int __env_get_timeout __P((DB_ENV *, db_timeout_t *, u_int32_t)); +static int __env_get_tmp_dir __P((DB_ENV *, const char **)); +static int __env_get_verbose __P((DB_ENV *, u_int32_t, int *)); +static int __env_set_event_notify + __P((DB_ENV *, void (*)(DB_ENV *, u_int32_t, void *))); +static int __env_get_feedback __P((DB_ENV *, void (**)(DB_ENV *, int, int))); +static int __env_set_feedback __P((DB_ENV *, void (*)(DB_ENV *, int, int))); +static int __env_set_thread_id __P((DB_ENV *, void (*)(DB_ENV *, + pid_t *, db_threadid_t *))); +static int __env_set_thread_id_string __P((DB_ENV *, + char * (*)(DB_ENV *, pid_t, db_threadid_t, char *))); + +/* + * db_env_create -- + * DB_ENV constructor. + * + * EXTERN: int db_env_create __P((DB_ENV **, u_int32_t)); + */ +int +db_env_create(dbenvpp, flags) + DB_ENV **dbenvpp; + u_int32_t flags; +{ + DB_ENV *dbenv; + ENV *env; + int ret; + + /* + * !!! + * Our caller has not yet had the opportunity to reset the panic + * state or turn off mutex locking, and so we can neither check + * the panic state or acquire a mutex in the DB_ENV create path. + * + * !!! + * We can't call the flags-checking routines, we don't have an + * environment yet. + */ + if (flags != 0) + return (EINVAL); + + /* Allocate the DB_ENV and ENV structures -- we always have both. */ + if ((ret = __os_calloc(NULL, 1, sizeof(DB_ENV), &dbenv)) != 0) + return (ret); + if ((ret = __os_calloc(NULL, 1, sizeof(ENV), &env)) != 0) + goto err; + dbenv->env = env; + env->dbenv = dbenv; + + if ((ret = __db_env_init(dbenv)) != 0 || + (ret = __lock_env_create(dbenv)) != 0 || + (ret = __log_env_create(dbenv)) != 0 || + (ret = __memp_env_create(dbenv)) != 0 || +#ifdef HAVE_REPLICATION + (ret = __rep_env_create(dbenv)) != 0 || +#endif + (ret = __txn_env_create(dbenv))) + goto err; + + *dbenvpp = dbenv; + return (0); + +err: __db_env_destroy(dbenv); + return (ret); +} + +/* + * __db_env_destroy -- + * DB_ENV destructor. + * + * PUBLIC: void __db_env_destroy __P((DB_ENV *)); + */ +void +__db_env_destroy(dbenv) + DB_ENV *dbenv; +{ + __lock_env_destroy(dbenv); + __log_env_destroy(dbenv); + __memp_env_destroy(dbenv); +#ifdef HAVE_REPLICATION + __rep_env_destroy(dbenv); +#endif + __txn_env_destroy(dbenv); + + /* + * Discard the underlying ENV structure. + * + * XXX + * This is wrong, but can't be fixed until we finish the work of + * splitting up the DB_ENV and ENV structures so that we don't + * touch anything in the ENV as part of the above calls to subsystem + * DB_ENV cleanup routines. + */ + memset(dbenv->env, CLEAR_BYTE, sizeof(ENV)); + __os_free(NULL, dbenv->env); + + memset(dbenv, CLEAR_BYTE, sizeof(DB_ENV)); + __os_free(NULL, dbenv); +} + +/* + * __db_env_init -- + * Initialize a DB_ENV structure. + */ +static int +__db_env_init(dbenv) + DB_ENV *dbenv; +{ + ENV *env; + /* + * !!! + * Our caller has not yet had the opportunity to reset the panic + * state or turn off mutex locking, and so we can neither check + * the panic state or acquire a mutex in the DB_ENV create path. + * + * Initialize the method handles. + */ + /* DB_ENV PUBLIC HANDLE LIST BEGIN */ + dbenv->add_data_dir = __env_add_data_dir; + dbenv->close = __env_close_pp; + dbenv->err = __env_err; + dbenv->errx = __env_errx; + dbenv->get_alloc = __env_get_alloc; + dbenv->get_cache_max = __memp_get_cache_max; + dbenv->get_cachesize = __memp_get_cachesize; + dbenv->get_create_dir = __env_get_create_dir; + dbenv->get_data_dirs = __env_get_data_dirs; + dbenv->get_data_len = __env_get_data_len; + dbenv->get_errcall = __env_get_errcall; + dbenv->get_errfile = __env_get_errfile; + dbenv->get_errpfx = __env_get_errpfx; + dbenv->get_feedback = __env_get_feedback; + dbenv->get_flags = __env_get_flags; + dbenv->get_home = __env_get_home; + dbenv->get_intermediate_dir_mode = __env_get_intermediate_dir_mode; + dbenv->get_memory_init = __env_get_memory_init; + dbenv->get_memory_max = __env_get_memory_max; + dbenv->get_metadata_dir = __env_get_metadata_dir; + dbenv->get_mp_max_openfd = __memp_get_mp_max_openfd; + dbenv->get_mp_max_write = __memp_get_mp_max_write; + dbenv->get_mp_mmapsize = __memp_get_mp_mmapsize; + dbenv->get_mp_mtxcount = __memp_get_mp_mtxcount; + dbenv->get_mp_pagesize = __memp_get_mp_pagesize; + dbenv->get_mp_tablesize = __memp_get_mp_tablesize; + dbenv->get_msgcall = __env_get_msgcall; + dbenv->get_msgfile = __env_get_msgfile; + dbenv->get_open_flags = __env_get_open_flags; + dbenv->get_shm_key = __env_get_shm_key; + dbenv->get_thread_count = __env_get_thread_count; + dbenv->get_thread_id_fn = __env_get_thread_id_fn; + dbenv->get_thread_id_string_fn = __env_get_thread_id_string_fn; + dbenv->get_timeout = __env_get_timeout; + dbenv->get_tmp_dir = __env_get_tmp_dir; + dbenv->get_verbose = __env_get_verbose; + dbenv->is_bigendian = __db_isbigendian; + dbenv->memp_fcreate = __memp_fcreate_pp; + dbenv->memp_register = __memp_register_pp; + dbenv->memp_stat = __memp_stat_pp; + dbenv->memp_stat_print = __memp_stat_print_pp; + dbenv->memp_sync = __memp_sync_pp; + dbenv->memp_trickle = __memp_trickle_pp; + dbenv->mutex_alloc = __mutex_alloc_pp; + dbenv->mutex_free = __mutex_free_pp; + dbenv->mutex_get_align = __mutex_get_align; + dbenv->mutex_get_increment = __mutex_get_increment; + dbenv->mutex_get_init = __mutex_get_init; + dbenv->mutex_get_max = __mutex_get_max; + dbenv->mutex_get_tas_spins = __mutex_get_tas_spins; + dbenv->mutex_lock = __mutex_lock_pp; + dbenv->mutex_set_align = __mutex_set_align; + dbenv->mutex_set_increment = __mutex_set_increment; + dbenv->mutex_set_init = __mutex_set_init; + dbenv->mutex_set_max = __mutex_set_max; + dbenv->mutex_set_tas_spins = __mutex_set_tas_spins; + dbenv->mutex_stat = __mutex_stat_pp; + dbenv->mutex_stat_print = __mutex_stat_print_pp; + dbenv->mutex_unlock = __mutex_unlock_pp; + dbenv->open = __env_open_pp; + dbenv->remove = __env_remove; + dbenv->set_alloc = __env_set_alloc; + dbenv->set_cache_max = __memp_set_cache_max; + dbenv->set_cachesize = __memp_set_cachesize; + dbenv->set_create_dir = __env_set_create_dir; + dbenv->set_data_dir = __env_set_data_dir; + dbenv->set_data_len = __env_set_data_len; + dbenv->set_encrypt = __env_set_encrypt; + dbenv->set_errcall = __env_set_errcall; + dbenv->set_errfile = __env_set_errfile; + dbenv->set_errpfx = __env_set_errpfx; + dbenv->set_event_notify = __env_set_event_notify; + dbenv->set_feedback = __env_set_feedback; + dbenv->set_flags = __env_set_flags; + dbenv->set_intermediate_dir_mode = __env_set_intermediate_dir_mode; + dbenv->set_memory_init = __env_set_memory_init; + dbenv->set_memory_max = __env_set_memory_max; + dbenv->set_metadata_dir = __env_set_metadata_dir; + dbenv->set_mp_max_openfd = __memp_set_mp_max_openfd; + dbenv->set_mp_max_write = __memp_set_mp_max_write; + dbenv->set_mp_mmapsize = __memp_set_mp_mmapsize; + dbenv->set_mp_mtxcount = __memp_set_mp_mtxcount; + dbenv->set_mp_pagesize = __memp_set_mp_pagesize; + dbenv->set_mp_tablesize = __memp_set_mp_tablesize; + dbenv->set_msgcall = __env_set_msgcall; + dbenv->set_msgfile = __env_set_msgfile; + dbenv->set_paniccall = __env_set_paniccall; + dbenv->set_shm_key = __env_set_shm_key; + dbenv->set_thread_count = __env_set_thread_count; + dbenv->set_thread_id = __env_set_thread_id; + dbenv->set_thread_id_string = __env_set_thread_id_string; + dbenv->set_timeout = __env_set_timeout; + dbenv->set_tmp_dir = __env_set_tmp_dir; + dbenv->set_verbose = __env_set_verbose; + dbenv->stat_print = __env_stat_print_pp; + /* DB_ENV PUBLIC HANDLE LIST END */ + + /* DB_ENV PRIVATE HANDLE LIST BEGIN */ + dbenv->prdbt = __db_prdbt; + /* DB_ENV PRIVATE HANDLE LIST END */ + + dbenv->shm_key = INVALID_REGION_SEGID; + dbenv->thread_id = __os_id; + dbenv->thread_id_string = __env_thread_id_string; + + env = dbenv->env; + __os_id(NULL, &env->pid_cache, NULL); + + env->db_ref = 0; + env->log_verify_wrap = __log_verify_wrap; + env->data_len = ENV_DEF_DATA_LEN; + TAILQ_INIT(&env->fdlist); + + if (!__db_isbigendian()) + F_SET(env, ENV_LITTLEENDIAN); + F_SET(env, ENV_NO_OUTPUT_SET); + + return (0); +} + +/* + * __env_err -- + * DbEnv.err method. + */ +static void +#ifdef STDC_HEADERS +__env_err(const DB_ENV *dbenv, int error, const char *fmt, ...) +#else +__env_err(dbenv, error, fmt, va_alist) + const DB_ENV *dbenv; + int error; + const char *fmt; + va_dcl +#endif +{ + /* Message with error string, to stderr by default. */ + DB_REAL_ERR(dbenv, error, DB_ERROR_SET, 1, fmt); +} + +/* + * __env_errx -- + * DbEnv.errx method. + */ +static void +#ifdef STDC_HEADERS +__env_errx(const DB_ENV *dbenv, const char *fmt, ...) +#else +__env_errx(dbenv, fmt, va_alist) + const DB_ENV *dbenv; + const char *fmt; + va_dcl +#endif +{ + /* Message without error string, to stderr by default. */ + DB_REAL_ERR(dbenv, 0, DB_ERROR_NOT_SET, 1, fmt); +} + +static int +__env_get_home(dbenv, homep) + DB_ENV *dbenv; + const char **homep; +{ + ENV *env; + + env = dbenv->env; + + ENV_ILLEGAL_BEFORE_OPEN(env, "DB_ENV->get_home"); + *homep = env->db_home; + + return (0); +} + +/* + * __env_get_alloc -- + * {DB_ENV,DB}->get_alloc. + * + * PUBLIC: int __env_get_alloc __P((DB_ENV *, void *(**)(size_t), + * PUBLIC: void *(**)(void *, size_t), void (**)(void *))); + */ +int +__env_get_alloc(dbenv, mal_funcp, real_funcp, free_funcp) + DB_ENV *dbenv; + void *(**mal_funcp) __P((size_t)); + void *(**real_funcp) __P((void *, size_t)); + void (**free_funcp) __P((void *)); +{ + + if (mal_funcp != NULL) + *mal_funcp = dbenv->db_malloc; + if (real_funcp != NULL) + *real_funcp = dbenv->db_realloc; + if (free_funcp != NULL) + *free_funcp = dbenv->db_free; + return (0); +} + +/* + * __env_set_alloc -- + * {DB_ENV,DB}->set_alloc. + * + * PUBLIC: int __env_set_alloc __P((DB_ENV *, void *(*)(size_t), + * PUBLIC: void *(*)(void *, size_t), void (*)(void *))); + */ +int +__env_set_alloc(dbenv, mal_func, real_func, free_func) + DB_ENV *dbenv; + void *(*mal_func) __P((size_t)); + void *(*real_func) __P((void *, size_t)); + void (*free_func) __P((void *)); +{ + ENV *env; + + env = dbenv->env; + + ENV_ILLEGAL_AFTER_OPEN(env, "DB_ENV->set_alloc"); + + dbenv->db_malloc = mal_func; + dbenv->db_realloc = real_func; + dbenv->db_free = free_func; + return (0); +} +/* + * __env_get_memory_init -- + * DB_ENV->get_memory_init. + * + * PUBLIC: int __env_get_memory_init __P((DB_ENV *, + * PUBLIC: DB_MEM_CONFIG, u_int32_t *)); + */ +int +__env_get_memory_init(dbenv, type, countp) + DB_ENV *dbenv; + DB_MEM_CONFIG type; + u_int32_t *countp; +{ + ENV *env; + + env = dbenv->env; + + switch (type) { + case DB_MEM_LOCK: + ENV_NOT_CONFIGURED(env, + env->lk_handle, "DB_ENV->get_memory_init", DB_INIT_LOCK); + if (LOCKING_ON(env)) + *countp = ((DB_LOCKREGION *) + env->lk_handle->reginfo.primary)->stat.st_initlocks; + else + *countp = dbenv->lk_init; + break; + case DB_MEM_LOCKOBJECT: + ENV_NOT_CONFIGURED(env, + env->lk_handle, "DB_ENV->get_memory_init", DB_INIT_LOCK); + if (LOCKING_ON(env)) + *countp = ((DB_LOCKREGION *) env-> + lk_handle->reginfo.primary)->stat.st_initobjects; + else + *countp = dbenv->lk_init_objects; + break; + case DB_MEM_LOCKER: + ENV_NOT_CONFIGURED(env, + env->lk_handle, "DB_ENV->get_memory_init", DB_INIT_LOCK); + if (LOCKING_ON(env)) + *countp = ((DB_LOCKREGION *) env-> + lk_handle->reginfo.primary)->stat.st_initlockers; + else + *countp = dbenv->lk_init_lockers; + break; + case DB_MEM_LOGID: + ENV_NOT_CONFIGURED(env, + env->lg_handle, "DB_ENV->get_memory_init", DB_INIT_LOG); + + if (LOGGING_ON(env)) + *countp = ((LOG *)env->lg_handle-> + reginfo.primary)->stat.st_fileid_init; + else + *countp = dbenv->lg_fileid_init; + break; + case DB_MEM_TRANSACTION: + ENV_NOT_CONFIGURED(env, + env->tx_handle, "DB_ENV->get_memory_init", DB_INIT_TXN); + + if (TXN_ON(env)) + *countp = ((DB_TXNREGION *) + env->tx_handle->reginfo.primary)->inittxns; + else + *countp = dbenv->tx_init; + break; + case DB_MEM_THREAD: + /* We always update thr_init when joining an env. */ + *countp = dbenv->thr_init; + break; + } + + return (0); +} + +/* + * __env_set_memory_init -- + * DB_ENV->set_memory_init. + * + * PUBLIC: int __env_set_memory_init __P((DB_ENV *, DB_MEM_CONFIG, u_int32_t)); + */ +int +__env_set_memory_init(dbenv, type, count) + DB_ENV *dbenv; + DB_MEM_CONFIG type; + u_int32_t count; +{ + ENV *env; + + env = dbenv->env; + + ENV_ILLEGAL_AFTER_OPEN(env, "DB_ENV->set_memory_init"); + switch (type) { + case DB_MEM_LOCK: + dbenv->lk_init = count; + break; + case DB_MEM_LOCKOBJECT: + dbenv->lk_init_objects = count; + break; + case DB_MEM_LOCKER: + dbenv->lk_init_lockers = count; + break; + case DB_MEM_LOGID: + dbenv->lg_fileid_init = count; + break; + case DB_MEM_TRANSACTION: + dbenv->tx_init = count; + break; + case DB_MEM_THREAD: + dbenv->thr_init = count; + break; + } + + return (0); +} +/* + * __env_get_memory_max -- + * DB_ENV->get_memory_max. + * + * PUBLIC: int __env_get_memory_max __P((DB_ENV *, u_int32_t *, u_int32_t *)); + */ +int +__env_get_memory_max(dbenv, gbytes, bytes) + DB_ENV *dbenv; + u_int32_t *gbytes, *bytes; +{ + ENV *env; + env = dbenv->env; + + if (F_ISSET(env, ENV_OPEN_CALLED)) { + *gbytes = (u_int32_t)(env->reginfo->rp->max / GIGABYTE); + *bytes = (u_int32_t)(env->reginfo->rp->max % GIGABYTE); + } else { + *gbytes = (u_int32_t)(dbenv->memory_max / GIGABYTE); + *bytes = (u_int32_t)(dbenv->memory_max % GIGABYTE); + } + return (0); +} + +/* + * __env_set_memory_max -- + * DB_ENV->set_memory_max. + * + * PUBLIC: int __env_set_memory_max __P((DB_ENV *, u_int32_t, u_int32_t)); + */ +int +__env_set_memory_max(dbenv, gbytes, bytes) + DB_ENV *dbenv; + u_int32_t gbytes, bytes; +{ + ENV *env; + + env = dbenv->env; + + ENV_ILLEGAL_AFTER_OPEN(env, "DB_ENV->set_memory_max"); + + /* + * If they are asking for 4GB exactly on a 32 bit platform, they + * really meant 4GB - 1. Give it to them. + */ + if (sizeof(roff_t) == 4 && gbytes == 4 && bytes == 0) { + --gbytes; + bytes = GIGABYTE - 1; + } + /* + * Make sure they wouldn't overflow the memory_max field on a + * 32 bit architecture. + */ + if (sizeof(roff_t) == 4 && gbytes >= 4) { + __db_errx(env, DB_STR("1588", + "Maximum memory size too large: maximum is 4GB")); + return (EINVAL); + } + dbenv->memory_max = ((roff_t)gbytes * GIGABYTE) + bytes; + return (0); +} + +/* + * __env_get_encrypt_flags -- + * {DB_ENV,DB}->get_encrypt_flags. + * + * PUBLIC: int __env_get_encrypt_flags __P((DB_ENV *, u_int32_t *)); + */ +int +__env_get_encrypt_flags(dbenv, flagsp) + DB_ENV *dbenv; + u_int32_t *flagsp; +{ +#ifdef HAVE_CRYPTO + DB_CIPHER *db_cipher; +#endif + ENV *env; + + env = dbenv->env; + +#ifdef HAVE_CRYPTO + db_cipher = env->crypto_handle; + if (db_cipher != NULL && db_cipher->alg == CIPHER_AES) + *flagsp = DB_ENCRYPT_AES; + else + *flagsp = 0; + return (0); +#else + COMPQUIET(flagsp, 0); + __db_errx(env, DB_STR("1555", + "library build did not include support for cryptography")); + return (DB_OPNOTSUP); +#endif +} + +/* + * __env_set_encrypt -- + * DB_ENV->set_encrypt. + * + * PUBLIC: int __env_set_encrypt __P((DB_ENV *, const char *, u_int32_t)); + */ +int +__env_set_encrypt(dbenv, passwd, flags) + DB_ENV *dbenv; + const char *passwd; + u_int32_t flags; +{ +#ifdef HAVE_CRYPTO + DB_THREAD_INFO *ip; + DB_CIPHER *db_cipher; + ENV *env; + int ret; + + env = dbenv->env; + + ENV_ILLEGAL_AFTER_OPEN(env, "DB_ENV->set_encrypt"); +#define OK_CRYPTO_FLAGS (DB_ENCRYPT_AES) + + if (flags != 0 && LF_ISSET(~OK_CRYPTO_FLAGS)) + return (__db_ferr(env, "DB_ENV->set_encrypt", 0)); + + if (passwd == NULL || strlen(passwd) == 0) { + __db_errx(env, DB_STR("1556", + "Empty password specified to set_encrypt")); + return (EINVAL); + } + ENV_ENTER(env, ip); + if (!CRYPTO_ON(env)) { + if ((ret = __os_calloc(env, 1, sizeof(DB_CIPHER), &db_cipher)) + != 0) + goto err; + env->crypto_handle = db_cipher; + } else + db_cipher = env->crypto_handle; + + if (dbenv->passwd != NULL) + __os_free(env, dbenv->passwd); + if ((ret = __os_strdup(env, passwd, &dbenv->passwd)) != 0) { + __os_free(env, db_cipher); + goto err; + } + /* + * We're going to need this often enough to keep around + */ + dbenv->passwd_len = strlen(dbenv->passwd) + 1; + /* + * The MAC key is for checksumming, and is separate from + * the algorithm. So initialize it here, even if they + * are using CIPHER_ANY. + */ + __db_derive_mac( + (u_int8_t *)dbenv->passwd, dbenv->passwd_len, db_cipher->mac_key); + switch (flags) { + case 0: + F_SET(db_cipher, CIPHER_ANY); + break; + case DB_ENCRYPT_AES: + if ((ret = + __crypto_algsetup(env, db_cipher, CIPHER_AES, 0)) != 0) + goto err1; + break; + default: /* Impossible. */ + break; + } + ENV_LEAVE(env, ip); + return (0); + +err1: + __os_free(env, dbenv->passwd); + __os_free(env, db_cipher); + env->crypto_handle = NULL; +err: + ENV_LEAVE(env, ip); + return (ret); +#else + COMPQUIET(passwd, NULL); + COMPQUIET(flags, 0); + + __db_errx(dbenv->env, DB_STR("1557", + "library build did not include support for cryptography")); + return (DB_OPNOTSUP); +#endif +} +#ifndef HAVE_BREW +static +#endif +const FLAG_MAP EnvMap[] = { + { DB_AUTO_COMMIT, DB_ENV_AUTO_COMMIT }, + { DB_CDB_ALLDB, DB_ENV_CDB_ALLDB }, + { DB_DATABASE_LOCKING, DB_ENV_DATABASE_LOCKING }, + { DB_DIRECT_DB, DB_ENV_DIRECT_DB }, + { DB_DSYNC_DB, DB_ENV_DSYNC_DB }, + { DB_HOTBACKUP_IN_PROGRESS, DB_ENV_HOTBACKUP }, + { DB_MULTIVERSION, DB_ENV_MULTIVERSION }, + { DB_NOFLUSH, DB_ENV_NOFLUSH }, + { DB_NOLOCKING, DB_ENV_NOLOCKING }, + { DB_NOMMAP, DB_ENV_NOMMAP }, + { DB_NOPANIC, DB_ENV_NOPANIC }, + { DB_OVERWRITE, DB_ENV_OVERWRITE }, + { DB_REGION_INIT, DB_ENV_REGION_INIT }, + { DB_TIME_NOTGRANTED, DB_ENV_TIME_NOTGRANTED }, + { DB_TXN_NOSYNC, DB_ENV_TXN_NOSYNC }, + { DB_TXN_NOWAIT, DB_ENV_TXN_NOWAIT }, + { DB_TXN_SNAPSHOT, DB_ENV_TXN_SNAPSHOT }, + { DB_TXN_WRITE_NOSYNC, DB_ENV_TXN_WRITE_NOSYNC }, + { DB_YIELDCPU, DB_ENV_YIELDCPU } +}; + +/* + * __env_map_flags -- map from external to internal flags. + * PUBLIC: void __env_map_flags __P((const FLAG_MAP *, + * PUBLIC: u_int, u_int32_t *, u_int32_t *)); + */ +void +__env_map_flags(flagmap, mapsize, inflagsp, outflagsp) + const FLAG_MAP *flagmap; + u_int mapsize; + u_int32_t *inflagsp, *outflagsp; +{ + + const FLAG_MAP *fmp; + u_int i; + + for (i = 0, fmp = flagmap; + i < mapsize / sizeof(flagmap[0]); ++i, ++fmp) + if (FLD_ISSET(*inflagsp, fmp->inflag)) { + FLD_SET(*outflagsp, fmp->outflag); + FLD_CLR(*inflagsp, fmp->inflag); + if (*inflagsp == 0) + break; + } +} + +/* + * __env_fetch_flags -- map from internal to external flags. + * PUBLIC: void __env_fetch_flags __P((const FLAG_MAP *, + * PUBLIC: u_int, u_int32_t *, u_int32_t *)); + */ +void +__env_fetch_flags(flagmap, mapsize, inflagsp, outflagsp) + const FLAG_MAP *flagmap; + u_int mapsize; + u_int32_t *inflagsp, *outflagsp; +{ + const FLAG_MAP *fmp; + u_int32_t i; + + *outflagsp = 0; + for (i = 0, fmp = flagmap; + i < mapsize / sizeof(flagmap[0]); ++i, ++fmp) + if (FLD_ISSET(*inflagsp, fmp->outflag)) + FLD_SET(*outflagsp, fmp->inflag); +} + +static int +__env_get_flags(dbenv, flagsp) + DB_ENV *dbenv; + u_int32_t *flagsp; +{ + ENV *env; + DB_THREAD_INFO *ip; + + __env_fetch_flags(EnvMap, sizeof(EnvMap), &dbenv->flags, flagsp); + + env = dbenv->env; + /* Some flags are persisted in the regions. */ + if (env->reginfo != NULL && + ((REGENV *)env->reginfo->primary)->panic != 0) + FLD_SET(*flagsp, DB_PANIC_ENVIRONMENT); + + /* If the hotbackup counter is positive, set the flag indicating so. */ + if (TXN_ON(env)) { + ENV_ENTER(env, ip); + TXN_SYSTEM_LOCK(env); + if (((DB_TXNREGION *) + env->tx_handle->reginfo.primary)->n_hotbackup > 0) + FLD_SET(*flagsp, DB_HOTBACKUP_IN_PROGRESS); + TXN_SYSTEM_UNLOCK(env); + ENV_LEAVE(env, ip); + } + + return (0); +} + +/* + * __env_set_flags -- + * DB_ENV->set_flags. + * + * PUBLIC: int __env_set_flags __P((DB_ENV *, u_int32_t, int)); + */ +int +__env_set_flags(dbenv, flags, on) + DB_ENV *dbenv; + u_int32_t flags; + int on; +{ + ENV *env; + DB_THREAD_INFO *ip; + u_int32_t mapped_flags; + int mem_on, ret; + + env = dbenv->env; + +#define OK_FLAGS \ + (DB_AUTO_COMMIT | DB_CDB_ALLDB | DB_DATABASE_LOCKING | \ + DB_DIRECT_DB | DB_DSYNC_DB | DB_MULTIVERSION | \ + DB_NOLOCKING | DB_NOMMAP | DB_NOPANIC | DB_OVERWRITE | \ + DB_PANIC_ENVIRONMENT | DB_REGION_INIT | \ + DB_TIME_NOTGRANTED | DB_TXN_NOSYNC | DB_TXN_NOWAIT | \ + DB_TXN_SNAPSHOT | DB_TXN_WRITE_NOSYNC | DB_YIELDCPU | \ + DB_HOTBACKUP_IN_PROGRESS | DB_NOFLUSH) + + if (LF_ISSET(~OK_FLAGS)) + return (__db_ferr(env, "DB_ENV->set_flags", 0)); + if (on) { + if ((ret = __db_fcchk(env, "DB_ENV->set_flags", + flags, DB_TXN_NOSYNC, DB_TXN_WRITE_NOSYNC)) != 0) + return (ret); + if (LF_ISSET(DB_DIRECT_DB) && __os_support_direct_io() == 0) { + __db_errx(env, + "DB_ENV->set_flags: direct I/O either not configured or not supported"); + return (EINVAL); + } + } + + if (LF_ISSET(DB_CDB_ALLDB)) + ENV_ILLEGAL_AFTER_OPEN(env, + "DB_ENV->set_flags: DB_CDB_ALLDB"); + if (LF_ISSET(DB_PANIC_ENVIRONMENT)) { + ENV_ILLEGAL_BEFORE_OPEN(env, + "DB_ENV->set_flags: DB_PANIC_ENVIRONMENT"); + if (on) { + __db_errx(env, DB_STR("1558", + "Environment panic set")); + (void)__env_panic(env, DB_RUNRECOVERY); + } else + __env_panic_set(env, 0); + } + if (LF_ISSET(DB_REGION_INIT)) + ENV_ILLEGAL_AFTER_OPEN(env, + "DB_ENV->set_flags: DB_REGION_INIT"); + + /* + * DB_LOG_IN_MEMORY, DB_TXN_NOSYNC and DB_TXN_WRITE_NOSYNC are + * mutually incompatible. If we're setting one of them, clear all + * current settings. If the environment is open, check to see that + * logging is not in memory. + */ + if (on && LF_ISSET(DB_TXN_NOSYNC | DB_TXN_WRITE_NOSYNC)) { + F_CLR(dbenv, DB_ENV_TXN_NOSYNC | DB_ENV_TXN_WRITE_NOSYNC); + if (!F_ISSET(env, ENV_OPEN_CALLED)) { + if ((ret = + __log_set_config(dbenv, DB_LOG_IN_MEMORY, 0)) != 0) + return (ret); + } else if (LOGGING_ON(env)) { + if ((ret = __log_get_config(dbenv, + DB_LOG_IN_MEMORY, &mem_on)) != 0) + return (ret); + if (mem_on == 1) { + __db_errx(env, DB_STR("1559", + "DB_TXN_NOSYNC and DB_TXN_WRITE_NOSYNC" + " may not be used with DB_LOG_IN_MEMORY")); + return (EINVAL); + } + } + } + + /* + * Settings of DB_HOTBACKUP_IN_PROGRESS are reference-counted + * in REGENV. + */ + if (LF_ISSET(DB_HOTBACKUP_IN_PROGRESS)) { + /* You can't take a hot backup without transactions. */ + ENV_REQUIRES_CONFIG(env, env->tx_handle, + "DB_ENV->set_flags: DB_HOTBACKUP_IN_PROGRESS", DB_INIT_TXN); + + COMPQUIET(ip, NULL); + } + + mapped_flags = 0; + __env_map_flags(EnvMap, sizeof(EnvMap), &flags, &mapped_flags); + if (on) + F_SET(dbenv, mapped_flags); + else + F_CLR(dbenv, mapped_flags); + + return (0); +} + +/* + * __env_set_backup -- + * PUBLIC: int __env_set_backup __P((ENV *, int)); + */ +int +__env_set_backup(env, on) + ENV *env; + int on; +{ + DB_TXNREGION *tenv; + int needs_checkpoint, ret; + + tenv = (DB_TXNREGION *)env->tx_handle->reginfo.primary; + needs_checkpoint = 0; + + TXN_SYSTEM_LOCK(env); + if (on) { + tenv->n_hotbackup++; + if (tenv->n_bulk_txn > 0) + needs_checkpoint = 1; + } else { + if (tenv->n_hotbackup == 0) + needs_checkpoint = -1; /* signal count error */ + else + tenv->n_hotbackup--; + } + TXN_SYSTEM_UNLOCK(env); + + if (needs_checkpoint == -1) { + __db_errx(env, DB_STR("1560", + "Attempt to decrement hotbackup counter past zero")); + return (EINVAL); + } + + if (needs_checkpoint && (ret = __txn_checkpoint(env, 0, 0, 0))) + return (ret); + return (0); +} + +static int +__env_get_data_dirs(dbenv, dirpp) + DB_ENV *dbenv; + const char ***dirpp; +{ + *dirpp = (const char **)dbenv->db_data_dir; + return (0); +} + +/* + * __env_set_data_dir -- + * DB_ENV->set_data_dir. + * + * PUBLIC: int __env_set_data_dir __P((DB_ENV *, const char *)); + */ +int +__env_set_data_dir(dbenv, dir) + DB_ENV *dbenv; + const char *dir; +{ + int ret; + + if ((ret = __env_add_data_dir(dbenv, dir)) != 0) + return (ret); + + if (dbenv->data_next == 1) + return (__env_set_create_dir(dbenv, dir)); + + return (0); +} + +/* + * __env_add_data_dir -- + * DB_ENV->add_data_dir. + * + * PUBLIC: int __env_add_data_dir __P((DB_ENV *, const char *)); + */ +int +__env_add_data_dir(dbenv, dir) + DB_ENV *dbenv; + const char *dir; +{ + ENV *env; + int ret; + + env = dbenv->env; + ENV_ILLEGAL_AFTER_OPEN(env, "DB_ENV->add_data_dir"); + + /* + * The array is NULL-terminated so it can be returned by get_data_dirs + * without a length. + */ + +#define DATA_INIT_CNT 20 /* Start with 20 data slots. */ + if (dbenv->db_data_dir == NULL) { + if ((ret = __os_calloc(env, DATA_INIT_CNT, + sizeof(char **), &dbenv->db_data_dir)) != 0) + return (ret); + dbenv->data_cnt = DATA_INIT_CNT; + } else if (dbenv->data_next == dbenv->data_cnt - 2) { + dbenv->data_cnt *= 2; + if ((ret = __os_realloc(env, + (u_int)dbenv->data_cnt * sizeof(char **), + &dbenv->db_data_dir)) != 0) + return (ret); + } + + ret = __os_strdup(env, + dir, &dbenv->db_data_dir[dbenv->data_next++]); + dbenv->db_data_dir[dbenv->data_next] = NULL; + return (ret); +} + +/* + * __env_set_create_dir -- + * DB_ENV->set_create_dir. + * The list of directories cannot change after opening the env and setting + * a pointer must be atomic so we do not need to mutex here even if multiple + * threads are using the DB_ENV handle. + * + * PUBLIC: int __env_set_create_dir __P((DB_ENV *, const char *)); + */ +int +__env_set_create_dir(dbenv, dir) + DB_ENV *dbenv; + const char *dir; +{ + ENV *env; + int i; + + env = dbenv->env; + + for (i = 0; i < dbenv->data_next; i++) + if (strcmp(dir, dbenv->db_data_dir[i]) == 0) + break; + + if (i == dbenv->data_next) { + __db_errx(env, DB_STR_A("1561", + "Directory %s not in environment list.", "%s"), dir); + return (EINVAL); + } + + dbenv->db_create_dir = dbenv->db_data_dir[i]; + return (0); +} + +static int +__env_get_create_dir(dbenv, dirp) + DB_ENV *dbenv; + const char **dirp; +{ + *dirp = dbenv->db_create_dir; + return (0); +} + +static int +__env_get_intermediate_dir_mode(dbenv, modep) + DB_ENV *dbenv; + const char **modep; +{ + *modep = dbenv->intermediate_dir_mode; + return (0); +} + +/* + * __env_set_metadata_dir -- + * DB_ENV->set_metadata_dir. + * + * PUBLIC: int __env_set_metadata_dir __P((DB_ENV *, const char *)); + */ +int +__env_set_metadata_dir(dbenv, dir) + DB_ENV *dbenv; + const char *dir; +{ + ENV *env; + int i, ret; + + env = dbenv->env; + + ENV_ILLEGAL_AFTER_OPEN(env, "DB_ENV->set_metadata_dir"); + + /* If metadata_dir is not already on data_dir list, add it. */ + for (i = 0; i < dbenv->data_next; i++) + if (strcmp(dir, dbenv->db_data_dir[i]) == 0) + break; + if (i == dbenv->data_next && + (ret = __env_add_data_dir(dbenv, dir)) != 0) { + __db_errx(env, DB_STR_A("1590", + "Could not add %s to environment list.", "%s"), dir); + return (ret); + } + + if (dbenv->db_md_dir != NULL) + __os_free(env, dbenv->db_md_dir); + return (__os_strdup(env, dir, &dbenv->db_md_dir)); +} + +static int +__env_get_metadata_dir(dbenv, dirp) + DB_ENV *dbenv; + const char **dirp; +{ + *dirp = dbenv->db_md_dir; + return (0); +} + +/* + * __env_set_data_len -- + * DB_ENV->set_data_len. + * + * PUBLIC: int __env_set_data_len __P((DB_ENV *, u_int32_t)); + */ +int +__env_set_data_len(dbenv, data_len) + DB_ENV *dbenv; + u_int32_t data_len; +{ + + dbenv->env->data_len = data_len; + return (0); +} + +static int +__env_get_data_len(dbenv, data_lenp) + DB_ENV *dbenv; + u_int32_t *data_lenp; +{ + *data_lenp = dbenv->env->data_len; + return (0); +} + +/* + * __env_set_intermediate_dir_mode -- + * DB_ENV->set_intermediate_dir_mode. + * + * PUBLIC: int __env_set_intermediate_dir_mode __P((DB_ENV *, const char *)); + */ +int +__env_set_intermediate_dir_mode(dbenv, mode) + DB_ENV *dbenv; + const char *mode; +{ + ENV *env; + u_int t; + int ret; + + env = dbenv->env; + + ENV_ILLEGAL_AFTER_OPEN(env, "DB_ENV->set_intermediate_dir_mode"); + +#define __SETMODE(offset, valid_ch, mask) { \ + if (mode[offset] == (valid_ch)) \ + t |= (mask); \ + else if (mode[offset] != '-') \ + goto format_err; \ +} + t = 0; + __SETMODE(0, 'r', S_IRUSR); + __SETMODE(1, 'w', S_IWUSR); + __SETMODE(2, 'x', S_IXUSR); + __SETMODE(3, 'r', S_IRGRP); + __SETMODE(4, 'w', S_IWGRP); + __SETMODE(5, 'x', S_IXGRP); + __SETMODE(6, 'r', S_IROTH); + __SETMODE(7, 'w', S_IWOTH); + __SETMODE(8, 'x', S_IXOTH); + if (mode[9] != '\0' || t == 0) { + /* + * We disallow modes of 0 -- we use 0 to decide the application + * never configured intermediate directory permissions, and we + * shouldn't create intermediate directories. Besides, setting + * the permissions to 0 makes no sense. + */ +format_err: __db_errx(env, + "DB_ENV->set_intermediate_dir_mode: illegal mode \"%s\"", mode); + return (EINVAL); + } + + if (dbenv->intermediate_dir_mode != NULL) + __os_free(env, dbenv->intermediate_dir_mode); + if ((ret = __os_strdup(env, mode, &dbenv->intermediate_dir_mode)) != 0) + return (ret); + + env->dir_mode = (int)t; + return (0); +} + +/* + * __env_get_errcall -- + * {DB_ENV,DB}->get_errcall. + * + * PUBLIC: void __env_get_errcall __P((DB_ENV *, + * PUBLIC: void (**)(const DB_ENV *, const char *, const char *))); + */ +void +__env_get_errcall(dbenv, errcallp) + DB_ENV *dbenv; + void (**errcallp) __P((const DB_ENV *, const char *, const char *)); +{ + *errcallp = dbenv->db_errcall; +} + +/* + * __env_set_errcall -- + * {DB_ENV,DB}->set_errcall. + * + * PUBLIC: void __env_set_errcall __P((DB_ENV *, + * PUBLIC: void (*)(const DB_ENV *, const char *, const char *))); + */ +void +__env_set_errcall(dbenv, errcall) + DB_ENV *dbenv; + void (*errcall) __P((const DB_ENV *, const char *, const char *)); +{ + ENV *env; + + env = dbenv->env; + + F_CLR(env, ENV_NO_OUTPUT_SET); + dbenv->db_errcall = errcall; +} + +/* + * __env_get_errfile -- + * {DB_ENV,DB}->get_errfile. + * + * PUBLIC: void __env_get_errfile __P((DB_ENV *, FILE **)); + */ +void +__env_get_errfile(dbenv, errfilep) + DB_ENV *dbenv; + FILE **errfilep; +{ + *errfilep = dbenv->db_errfile; +} + +/* + * __env_set_errfile -- + * {DB_ENV,DB}->set_errfile. + * + * PUBLIC: void __env_set_errfile __P((DB_ENV *, FILE *)); + */ +void +__env_set_errfile(dbenv, errfile) + DB_ENV *dbenv; + FILE *errfile; +{ + ENV *env; + + env = dbenv->env; + + F_CLR(env, ENV_NO_OUTPUT_SET); + dbenv->db_errfile = errfile; +} + +/* + * __env_get_errpfx -- + * {DB_ENV,DB}->get_errpfx. + * + * PUBLIC: void __env_get_errpfx __P((DB_ENV *, const char **)); + */ +void +__env_get_errpfx(dbenv, errpfxp) + DB_ENV *dbenv; + const char **errpfxp; +{ + *errpfxp = dbenv->db_errpfx; +} + +/* + * __env_set_errpfx -- + * {DB_ENV,DB}->set_errpfx. + * + * PUBLIC: void __env_set_errpfx __P((DB_ENV *, const char *)); + */ +void +__env_set_errpfx(dbenv, errpfx) + DB_ENV *dbenv; + const char *errpfx; +{ + dbenv->db_errpfx = errpfx; +} + +static int +__env_get_feedback(dbenv, feedbackp) + DB_ENV *dbenv; + void (**feedbackp) __P((DB_ENV *, int, int)); +{ + if (feedbackp != NULL) + *feedbackp = dbenv->db_feedback; + return (0); +} + +static int +__env_set_feedback(dbenv, feedback) + DB_ENV *dbenv; + void (*feedback) __P((DB_ENV *, int, int)); +{ + dbenv->db_feedback = feedback; + return (0); +} + +/* + * __env_get_thread_id_fn -- + * DB_ENV->get_thread_id_fn + */ +static int +__env_get_thread_id_fn(dbenv, idp) + DB_ENV *dbenv; + void (**idp) __P((DB_ENV *, pid_t *, db_threadid_t *)); +{ + if (idp != NULL) + *idp = dbenv->thread_id; + return (0); +} + +/* + * __env_set_thread_id -- + * DB_ENV->set_thread_id + */ +static int +__env_set_thread_id(dbenv, id) + DB_ENV *dbenv; + void (*id) __P((DB_ENV *, pid_t *, db_threadid_t *)); +{ + dbenv->thread_id = id; + return (0); +} + +/* + * __env_get_threadid_string_fn -- + * DB_ENV->get_threadid_string_fn + */ +static int +__env_get_thread_id_string_fn(dbenv, thread_id_stringp) + DB_ENV *dbenv; + char *(**thread_id_stringp) + __P((DB_ENV *, pid_t, db_threadid_t, char *)); +{ + if (thread_id_stringp != NULL) + *thread_id_stringp = dbenv->thread_id_string; + return (0); +} + +/* + * __env_set_threadid_string -- + * DB_ENV->set_threadid_string + */ +static int +__env_set_thread_id_string(dbenv, thread_id_string) + DB_ENV *dbenv; + char *(*thread_id_string) __P((DB_ENV *, pid_t, db_threadid_t, char *)); +{ + dbenv->thread_id_string = thread_id_string; + return (0); +} + +/* + * __env_get_thread_count -- + * DB_ENV->get_thread_count + */ +static int +__env_get_thread_count(dbenv, countp) + DB_ENV *dbenv; + u_int32_t *countp; +{ + *countp = dbenv->thr_max; + return (0); +} + +/* + * __env_set_thread_count -- + * DB_ENV->set_thread_count + * + * PUBLIC: int __env_set_thread_count __P((DB_ENV *, u_int32_t)); + */ +int +__env_set_thread_count(dbenv, count) + DB_ENV *dbenv; + u_int32_t count; +{ + ENV *env; + + env = dbenv->env; + + ENV_ILLEGAL_AFTER_OPEN(env, "DB_ENV->set_thread_count"); + dbenv->thr_max = count; + + return (0); +} + +/* + * __env_get_msgcall -- + * {DB_ENV,DB}->get_msgcall. + * + * PUBLIC: void __env_get_msgcall + * PUBLIC: __P((DB_ENV *, void (**)(const DB_ENV *, const char *))); + */ +void +__env_get_msgcall(dbenv, msgcallp) + DB_ENV *dbenv; + void (**msgcallp) __P((const DB_ENV *, const char *)); +{ + if (msgcallp != NULL) + *msgcallp = dbenv->db_msgcall; +} + +/* + * __env_set_msgcall -- + * {DB_ENV,DB}->set_msgcall. + * + * PUBLIC: void __env_set_msgcall + * PUBLIC: __P((DB_ENV *, void (*)(const DB_ENV *, const char *))); + */ +void +__env_set_msgcall(dbenv, msgcall) + DB_ENV *dbenv; + void (*msgcall) __P((const DB_ENV *, const char *)); +{ + dbenv->db_msgcall = msgcall; +} + +/* + * __env_get_msgfile -- + * {DB_ENV,DB}->get_msgfile. + * + * PUBLIC: void __env_get_msgfile __P((DB_ENV *, FILE **)); + */ +void +__env_get_msgfile(dbenv, msgfilep) + DB_ENV *dbenv; + FILE **msgfilep; +{ + *msgfilep = dbenv->db_msgfile; +} + +/* + * __env_set_msgfile -- + * {DB_ENV,DB}->set_msgfile. + * + * PUBLIC: void __env_set_msgfile __P((DB_ENV *, FILE *)); + */ +void +__env_set_msgfile(dbenv, msgfile) + DB_ENV *dbenv; + FILE *msgfile; +{ + dbenv->db_msgfile = msgfile; +} + +/* + * __env_set_paniccall -- + * {DB_ENV,DB}->set_paniccall. + * + * PUBLIC: int __env_set_paniccall __P((DB_ENV *, void (*)(DB_ENV *, int))); + */ +int +__env_set_paniccall(dbenv, paniccall) + DB_ENV *dbenv; + void (*paniccall) __P((DB_ENV *, int)); +{ + dbenv->db_paniccall = paniccall; + return (0); +} + +/* + * __env_set_event_notify -- + * DB_ENV->set_event_notify. + */ +static int +__env_set_event_notify(dbenv, event_func) + DB_ENV *dbenv; + void (*event_func) __P((DB_ENV *, u_int32_t, void *)); +{ + dbenv->db_event_func = event_func; + return (0); +} + +static int +__env_get_shm_key(dbenv, shm_keyp) + DB_ENV *dbenv; + long *shm_keyp; /* !!!: really a key_t *. */ +{ + *shm_keyp = dbenv->shm_key; + return (0); +} + +/* + * __env_set_shm_key -- + * DB_ENV->set_shm_key. + * + * PUBLIC: int __env_set_shm_key __P((DB_ENV *, long)); + */ +int +__env_set_shm_key(dbenv, shm_key) + DB_ENV *dbenv; + long shm_key; /* !!!: really a key_t. */ +{ + ENV *env; + + env = dbenv->env; + + ENV_ILLEGAL_AFTER_OPEN(env, "DB_ENV->set_shm_key"); + + dbenv->shm_key = shm_key; + return (0); +} + +static int +__env_get_tmp_dir(dbenv, dirp) + DB_ENV *dbenv; + const char **dirp; +{ + *dirp = dbenv->db_tmp_dir; + return (0); +} + +/* + * __env_set_tmp_dir -- + * DB_ENV->set_tmp_dir. + * + * PUBLIC: int __env_set_tmp_dir __P((DB_ENV *, const char *)); + */ +int +__env_set_tmp_dir(dbenv, dir) + DB_ENV *dbenv; + const char *dir; +{ + ENV *env; + + env = dbenv->env; + + if (dbenv->db_tmp_dir != NULL) + __os_free(env, dbenv->db_tmp_dir); + return (__os_strdup(env, dir, &dbenv->db_tmp_dir)); +} + +static int +__env_get_verbose(dbenv, which, onoffp) + DB_ENV *dbenv; + u_int32_t which; + int *onoffp; +{ + switch (which) { + case DB_VERB_BACKUP: + case DB_VERB_DEADLOCK: + case DB_VERB_FILEOPS: + case DB_VERB_FILEOPS_ALL: + case DB_VERB_RECOVERY: + case DB_VERB_REGISTER: + case DB_VERB_REPLICATION: + case DB_VERB_REP_ELECT: + case DB_VERB_REP_LEASE: + case DB_VERB_REP_MISC: + case DB_VERB_REP_MSGS: + case DB_VERB_REP_SYNC: + case DB_VERB_REP_SYSTEM: + case DB_VERB_REP_TEST: + case DB_VERB_REPMGR_CONNFAIL: + case DB_VERB_REPMGR_MISC: + case DB_VERB_WAITSFOR: + *onoffp = FLD_ISSET(dbenv->verbose, which) ? 1 : 0; + break; + default: + return (EINVAL); + } + return (0); +} + +/* + * __env_set_verbose -- + * DB_ENV->set_verbose. + * + * PUBLIC: int __env_set_verbose __P((DB_ENV *, u_int32_t, int)); + */ +int +__env_set_verbose(dbenv, which, on) + DB_ENV *dbenv; + u_int32_t which; + int on; +{ + switch (which) { + case DB_VERB_BACKUP: + case DB_VERB_DEADLOCK: + case DB_VERB_FILEOPS: + case DB_VERB_FILEOPS_ALL: + case DB_VERB_RECOVERY: + case DB_VERB_REGISTER: + case DB_VERB_REPLICATION: + case DB_VERB_REP_ELECT: + case DB_VERB_REP_LEASE: + case DB_VERB_REP_MISC: + case DB_VERB_REP_MSGS: + case DB_VERB_REP_SYNC: + case DB_VERB_REP_SYSTEM: + case DB_VERB_REP_TEST: + case DB_VERB_REPMGR_CONNFAIL: + case DB_VERB_REPMGR_MISC: + case DB_VERB_WAITSFOR: + if (on) + FLD_SET(dbenv->verbose, which); + else + FLD_CLR(dbenv->verbose, which); + break; + default: + return (EINVAL); + } + return (0); +} + +/* + * __db_mi_env -- + * Method illegally called with public environment. + * + * PUBLIC: int __db_mi_env __P((ENV *, const char *)); + */ +int +__db_mi_env(env, name) + ENV *env; + const char *name; +{ + __db_errx(env, DB_STR_A("1564", + "%s: method not permitted when environment specified", "%s"), + name); + return (EINVAL); +} + +/* + * __db_mi_open -- + * Method illegally called after open. + * + * PUBLIC: int __db_mi_open __P((ENV *, const char *, int)); + */ +int +__db_mi_open(env, name, after) + ENV *env; + const char *name; + int after; +{ + __db_errx(env, DB_STR_A("1565", + "%s: method not permitted %s handle's open method", "%s %s"), + name, after ? DB_STR_P("after") : DB_STR_P("before")); + return (EINVAL); +} + +/* + * __env_not_config -- + * Method or function called without required configuration. + * + * PUBLIC: int __env_not_config __P((ENV *, char *, u_int32_t)); + */ +int +__env_not_config(env, i, flags) + ENV *env; + char *i; + u_int32_t flags; +{ + char *sub; + int is_sub; + + is_sub = 1; + + switch (flags) { + case DB_INIT_CDB: + sub = "DB_INIT_CDB"; + is_sub = 0; + break; + case DB_INIT_LOCK: + sub = "locking"; + break; + case DB_INIT_LOG: + sub = "logging"; + break; + case DB_INIT_MPOOL: + sub = "memory pool"; + break; + case DB_INIT_MUTEX: + sub = "mutex"; + break; + case DB_INIT_REP: + sub = "replication"; + break; + case DB_INIT_TXN: + sub = "transaction"; + break; + default: + sub = ""; + break; + } + + if (is_sub) { + __db_errx(env, DB_STR_A("1566", + "%s interface requires an environment configured for the %s subsystem", + "%s %s"), i, sub); + } else { + __db_errx(env, DB_STR_A("1587", + "%s interface requires an environment configured with %s", + "%s %s"), i, sub); + } + + return (EINVAL); +} + +/* + * __env_get_timeout -- + * DB_ENV->get_timeout + */ +static int +__env_get_timeout(dbenv, timeoutp, flags) + DB_ENV *dbenv; + db_timeout_t *timeoutp; + u_int32_t flags; +{ + int ret; + + ret = 0; + if (flags == DB_SET_REG_TIMEOUT) { + *timeoutp = dbenv->envreg_timeout; + } else + ret = __lock_get_env_timeout(dbenv, timeoutp, flags); + return (ret); +} + +/* + * __env_set_timeout -- + * DB_ENV->set_timeout + * + * PUBLIC: int __env_set_timeout __P((DB_ENV *, db_timeout_t, u_int32_t)); + */ +int +__env_set_timeout(dbenv, timeout, flags) + DB_ENV *dbenv; + db_timeout_t timeout; + u_int32_t flags; +{ + int ret; + + ret = 0; + if (flags == DB_SET_REG_TIMEOUT) + dbenv->envreg_timeout = timeout; + else + ret = __lock_set_env_timeout(dbenv, timeout, flags); + return (ret); +} + +/* + * __env_thread_id_string -- + * Convert a thread id to a string. + * + * PUBLIC: char *__env_thread_id_string + * PUBLIC: __P((DB_ENV *, pid_t, db_threadid_t, char *)); + */ +char * +__env_thread_id_string(dbenv, pid, tid, buf) + DB_ENV *dbenv; + pid_t pid; + db_threadid_t tid; + char *buf; +{ +#ifdef HAVE_SIMPLE_THREAD_TYPE +#ifdef UINT64_FMT + char fmt[20]; + + snprintf(fmt, sizeof(fmt), "%s/%s", UINT64_FMT, UINT64_FMT); + snprintf(buf, + DB_THREADID_STRLEN, fmt, (u_int64_t)pid, (u_int64_t)(uintptr_t)tid); +#else + snprintf(buf, DB_THREADID_STRLEN, "%lu/%lu", (u_long)pid, (u_long)tid); +#endif +#else +#ifdef UINT64_FMT + char fmt[20]; + + snprintf(fmt, sizeof(fmt), "%s/TID", UINT64_FMT); + snprintf(buf, DB_THREADID_STRLEN, fmt, (u_int64_t)pid); +#else + snprintf(buf, DB_THREADID_STRLEN, "%lu/TID", (u_long)pid); +#endif +#endif + COMPQUIET(dbenv, NULL); + COMPQUIET(*(u_int8_t *)&tid, 0); + + return (buf); +} diff -r 000000000000 -r a1985f14b030 src/env/env_name.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/env/env_name.c Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,307 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 1996, 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + * $Id$ + */ + +#include "db_config.h" + +#include "db_int.h" + +static int __db_fullpath + __P((ENV *, const char *, const char *, int, int, char **)); + +#define DB_ADDSTR(add) { \ + /* \ + * The string might be NULL or zero-length, and the p[-1] \ + * might indirect to before the beginning of our buffer. \ + */ \ + if ((add) != NULL && (add)[0] != '\0') { \ + /* If leading slash, start over. */ \ + if (__os_abspath(add)) { \ + p = str; \ + slash = 0; \ + } \ + /* Append to the current string. */ \ + len = strlen(add); \ + if (slash) \ + *p++ = PATH_SEPARATOR[0]; \ + memcpy(p, add, len); \ + p += len; \ + slash = strchr(PATH_SEPARATOR, p[-1]) == NULL; \ + } \ +} + +/* + * __db_fullpath -- + * Constructs a path name relative to the environment home, and optionally + * checks whether the file or directory exist. + */ +static int +__db_fullpath(env, dir, file, check_file, check_dir, namep) + ENV *env; + const char *dir; + const char *file; + int check_file; + int check_dir; + char **namep; +{ + size_t len; + const char *home; + char *p, *str; + int isdir, ret, slash; + + /* All paths are relative to the environment home. */ + home = (env == NULL) ? NULL : env->db_home; + + len = + (home == NULL ? 0 : strlen(home) + 1) + + (dir == NULL ? 0 : strlen(dir) + 1) + + (file == NULL ? 0 : strlen(file) + 1); + + if ((ret = __os_malloc(env, len, &str)) != 0) + return (ret); + + slash = 0; + p = str; + DB_ADDSTR(home); + DB_ADDSTR(dir); + *p = '\0'; + if (check_dir && (__os_exists(env, str, &isdir) != 0 || !isdir)) { + __os_free(env, str); + return (ENOENT); + } + DB_ADDSTR(file); + *p = '\0'; + + /* + * If we're opening a data file, see if it exists. If not, keep + * trying. + */ + if (check_file && __os_exists(env, str, NULL) != 0) { + __os_free(env, str); + return (ENOENT); + } + + if (namep == NULL) + __os_free(env, str); + else + *namep = str; + return (0); +} + +#define DB_CHECKFILE(file, dir, check_file, check_dir, namep, ret_dir) do { \ + ret = __db_fullpath(env, dir, file, \ + check_file, check_dir, namep); \ + if (ret == 0 && (ret_dir) != NULL) \ + *(ret_dir) = (dir); \ + if (ret != ENOENT) \ + return (ret); \ +} while (0) + +/* + * __db_appname -- + * Given an optional DB environment, directory and file name and type + * of call, build a path based on the ENV->open rules, and return + * it in allocated space. Dirp can be used to specify a data directory + * to use. If not and one is used then drip will contain a pointer + * to the directory name. + * + * PUBLIC: int __db_appname __P((ENV *, APPNAME, + * PUBLIC: const char *, const char **, char **)); + */ +int +__db_appname(env, appname, file, dirp, namep) + ENV *env; + APPNAME appname; + const char *file; + const char **dirp; + char **namep; +{ + DB_ENV *dbenv; + char **ddp; + const char *dir; + int ret; + + dbenv = env->dbenv; + dir = NULL; + + if (namep != NULL) + *namep = NULL; + + /* + * Absolute path names are never modified. If the file is an absolute + * path, we're done. + */ + if (file != NULL && __os_abspath(file)) + return (__os_strdup(env, file, namep)); + + /* + * DB_APP_NONE: + * DB_HOME/file + * DB_APP_DATA: + * DB_HOME/DB_DATA_DIR/file + * DB_APP_LOG: + * DB_HOME/DB_LOG_DIR/file + * DB_APP_TMP: + * DB_HOME/DB_TMP_DIR/ + */ + switch (appname) { + case DB_APP_NONE: + break; + case DB_APP_RECOVER: + case DB_APP_DATA: + /* + * First, step through the data_dir entries, if any, looking + * for the file. + */ + if (dbenv != NULL && dbenv->db_data_dir != NULL) + for (ddp = dbenv->db_data_dir; *ddp != NULL; ddp++) + DB_CHECKFILE(file, *ddp, 1, 0, namep, dirp); + + /* Second, look in the environment home directory. */ + DB_CHECKFILE(file, NULL, 1, 0, namep, dirp); + + /* + * Otherwise, we're going to create. Use the specified + * directory unless we're in recovery and it doesn't exist. + */ + if (dirp != NULL && *dirp != NULL) + DB_CHECKFILE(file, *dirp, 0, + appname == DB_APP_RECOVER, namep, dirp); + + /* Finally, use the create directory, if set. */ + if (dbenv != NULL && dbenv->db_create_dir != NULL) + dir = dbenv->db_create_dir; + break; + case DB_APP_LOG: + if (dbenv != NULL) + dir = dbenv->db_log_dir; + break; + case DB_APP_TMP: + if (dbenv != NULL) + dir = dbenv->db_tmp_dir; + break; + case DB_APP_META: + if (dbenv != NULL) + dir = dbenv->db_md_dir; + break; + } + + /* + * Construct the full path. For temporary files, it is an error if the + * directory does not exist: if it doesn't, checking whether millions + * of temporary files exist inside it takes a *very* long time. + */ + DB_CHECKFILE(file, dir, 0, appname == DB_APP_TMP, namep, dirp); + + return (ret); +} + +/* + * __db_tmp_open -- + * Create a temporary file. + * + * PUBLIC: int __db_tmp_open __P((ENV *, u_int32_t, DB_FH **)); + */ +int +__db_tmp_open(env, oflags, fhpp) + ENV *env; + u_int32_t oflags; + DB_FH **fhpp; +{ + pid_t pid; + int filenum, i, ipid, ret; + char *path; + char *firstx, *trv; + + DB_ASSERT(env, fhpp != NULL); + *fhpp = NULL; + +#define DB_TRAIL "BDBXXXXX" + if ((ret = __db_appname(env, DB_APP_TMP, DB_TRAIL, NULL, &path)) != 0) + goto done; + + /* Replace the X's with the process ID (in decimal). */ + __os_id(env->dbenv, &pid, NULL); + ipid = (int)pid; + if (ipid < 0) + ipid = -ipid; + for (trv = path + strlen(path); *--trv == 'X'; ipid /= 10) + *trv = '0' + (u_char)(ipid % 10); + firstx = trv + 1; + + /* Loop, trying to open a file. */ + for (filenum = 1;; filenum++) { + if ((ret = __os_open(env, path, 0, + oflags | DB_OSO_CREATE | DB_OSO_EXCL | DB_OSO_TEMP, + DB_MODE_600, fhpp)) == 0) { + ret = 0; + goto done; + } + + /* + * !!!: + * If we don't get an EEXIST error, then there's something + * seriously wrong. Unfortunately, if the implementation + * doesn't return EEXIST for O_CREAT and O_EXCL regardless + * of other possible errors, we've lost. + */ + if (ret != EEXIST) { + __db_err(env, ret, DB_STR_A("1586", + "temporary open: %s", "%s"), path); + goto done; + } + + /* + * Generate temporary file names in a backwards-compatible way. + * If pid == 12345, the result is: + * /DB12345 (tried above, the first time through). + * /DBa2345 ... /DBz2345 + * /DBaa345 ... /DBaz345 + * /DBba345, and so on. + * + * XXX + * This algorithm is O(n**2) -- that is, creating 100 temporary + * files requires 5,000 opens, creating 1000 files requires + * 500,000. If applications open a lot of temporary files, we + * could improve performance by switching to timestamp-based + * file names. + */ + for (i = filenum, trv = firstx; i > 0; i = (i - 1) / 26) + if (*trv++ == '\0') { + ret = EINVAL; + goto done; + } + + for (i = filenum; i > 0; i = (i - 1) / 26) + *--trv = 'a' + ((i - 1) % 26); + } +done: + __os_free(env, path); + return (ret); +} diff -r 000000000000 -r a1985f14b030 src/env/env_open.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/env/env_open.c Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,1286 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 1996, 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + * $Id$ + */ + +#include "db_config.h" + +#include "db_int.h" +#include "dbinc/crypto.h" +#include "dbinc/db_page.h" +#include "dbinc/btree.h" +#include "dbinc/lock.h" +#include "dbinc/mp.h" +#include "dbinc/txn.h" + +static int __env_open_arg __P((DB_ENV *, u_int32_t)); +static int __file_handle_cleanup __P((ENV *)); + +/* + * db_version -- + * Return legacy version information, including DB Major Version, + * DB Minor Version, and DB Patch/Build numbers. + * + * EXTERN: char *db_version __P((int *, int *, int *)); + */ +char * +db_version(majverp, minverp, patchp) + int *majverp, *minverp, *patchp; +{ + if (majverp != NULL) + *majverp = DB_VERSION_MAJOR; + if (minverp != NULL) + *minverp = DB_VERSION_MINOR; + if (patchp != NULL) + *patchp = DB_VERSION_PATCH; + return ((char *)DB_VERSION_STRING); +} + +/* + * db_full_version -- + * Return complete version information, including Oracle Family, + * Oracle Release, DB Major Version, DB Minor Version, and DB + * Patch/Build numbers. + * + * EXTERN: char *db_full_version __P((int *, int *, int *, int *, int *)); + */ +char * +db_full_version(familyp, releasep, majverp, minverp, patchp) + int *familyp, *releasep, *majverp, *minverp, *patchp; +{ + if (familyp != NULL) + *familyp = DB_VERSION_FAMILY; + if (releasep != NULL) + *releasep = DB_VERSION_RELEASE; + if (majverp != NULL) + *majverp = DB_VERSION_MAJOR; + if (minverp != NULL) + *minverp = DB_VERSION_MINOR; + if (patchp != NULL) + *patchp = DB_VERSION_PATCH; + return ((char *)DB_VERSION_FULL_STRING); +} + +/* + * __env_open_pp -- + * DB_ENV->open pre/post processing. + * + * PUBLIC: int __env_open_pp __P((DB_ENV *, const char *, u_int32_t, int)); + */ +int +__env_open_pp(dbenv, db_home, flags, mode) + DB_ENV *dbenv; + const char *db_home; + u_int32_t flags; + int mode; +{ + ENV *env; + int ret; + + env = dbenv->env; + ENV_ILLEGAL_AFTER_OPEN(env, "DB_ENV->open"); + +#undef OKFLAGS +#define OKFLAGS \ + (DB_CREATE | DB_FAILCHK | DB_FAILCHK_ISALIVE | DB_INIT_CDB | \ + DB_INIT_LOCK | DB_INIT_LOG | DB_INIT_MPOOL | DB_INIT_REP | \ + DB_INIT_TXN | DB_LOCKDOWN | DB_NO_CHECKPOINT | DB_PRIVATE | \ + DB_RECOVER | DB_RECOVER_FATAL | DB_REGISTER | DB_SYSTEM_MEM | \ + DB_THREAD | DB_USE_ENVIRON | DB_USE_ENVIRON_ROOT) +#undef OKFLAGS_CDB +#define OKFLAGS_CDB \ + (DB_CREATE | DB_INIT_CDB | DB_INIT_MPOOL | DB_LOCKDOWN | \ + DB_PRIVATE | DB_SYSTEM_MEM | DB_THREAD | \ + DB_USE_ENVIRON | DB_USE_ENVIRON_ROOT) + + if ((ret = __db_fchk(env, "DB_ENV->open", flags, OKFLAGS)) != 0) + return (ret); + if ((ret = __db_fcchk( + env, "DB_ENV->open", flags, DB_INIT_CDB, ~OKFLAGS_CDB)) != 0) + return (ret); + +#if defined(HAVE_MIXED_SIZE_ADDRESSING) && (SIZEOF_CHAR_P == 8) + if (F_ISSET(env, DB_PRIVATE)) { + __db_errx(env, DB_STR("1589", "DB_PRIVATE is not " + "supported by 64-bit applications in " + "mixed-size-addressing mode")); + return (EINVAL); + } +#endif + + return (__env_open(dbenv, db_home, flags, mode)); +} + +/* + * __env_open -- + * DB_ENV->open. + * + * PUBLIC: int __env_open __P((DB_ENV *, const char *, u_int32_t, int)); + */ +int +__env_open(dbenv, db_home, flags, mode) + DB_ENV *dbenv; + const char *db_home; + u_int32_t flags; + int mode; +{ + DB_THREAD_INFO *ip; + ENV *env; + u_int32_t orig_flags; + int register_recovery, ret, t_ret; + + ip = NULL; + env = dbenv->env; + register_recovery = 0; + + /* Initial configuration. */ + if ((ret = __env_config(dbenv, db_home, &flags, mode)) != 0) + return (ret); + + /* + * Save the DB_ENV handle's configuration flags as set by user-called + * configuration methods and the environment directory's DB_CONFIG + * file. If we use this DB_ENV structure to recover the existing + * environment or to remove an environment we created after failure, + * we'll restore the DB_ENV flags to these values. + */ + orig_flags = dbenv->flags; + + /* Check open flags. */ + if ((ret = __env_open_arg(dbenv, flags)) != 0) + return (ret); + + /* + * If we're going to register with the environment, that's the first + * thing we do. + */ + if (LF_ISSET(DB_REGISTER)) { + /* + * Through the SQL interface (btree.c) we set + * DB_FAILCHK_ISALIVE. When set, we want to run failchk + * if a recovery is needed. Set up the infrastructure to run + * it. SQL applications have no way to specify the thread + * count or an isalive, so force it here. Failchk is run + * inside of register code. + */ + if (LF_ISSET(DB_FAILCHK_ISALIVE)) { + (void)__env_set_thread_count(dbenv, 50); + dbenv->is_alive = __envreg_isalive; + } + + if ((ret = + __envreg_register(env, ®ister_recovery, flags)) != 0) + goto err; + if (register_recovery) { + if (!LF_ISSET(DB_RECOVER)) { + __db_errx(env, DB_STR("1567", + "The DB_RECOVER flag was not specified, and recovery is needed")); + ret = DB_RUNRECOVERY; + goto err; + } + } else + LF_CLR(DB_RECOVER); + } + + /* + * If we're doing recovery, destroy the environment so that we create + * all the regions from scratch. The major concern I have is if the + * application stomps the environment with a rogue pointer. We have + * no way of detecting that, and we could be forced into a situation + * where we start up and then crash, repeatedly. + * + * We do not check any flags like DB_PRIVATE before calling remove. + * We don't care if the current environment was private or not, we + * want to remove files left over for any reason, from any session. + */ +retry: if (LF_ISSET(DB_RECOVER | DB_RECOVER_FATAL)) +#ifdef HAVE_REPLICATION + if ((ret = __rep_reset_init(env)) != 0 || + (ret = __env_remove_env(env)) != 0 || +#else + if ((ret = __env_remove_env(env)) != 0 || +#endif + (ret = __env_refresh(dbenv, orig_flags, 0)) != 0) + goto err; + + if ((ret = __env_attach_regions(dbenv, flags, orig_flags, 1)) != 0) + goto err; + + /* + * After attached to env, run failchk if not doing register + * recovery. Not providing this option with the DB_FAILCHK_ISALIVE + * flag. + */ + if (LF_ISSET(DB_FAILCHK) && !register_recovery) { + ENV_ENTER(env, ip); + if ((ret = __env_failchk_int(dbenv)) != 0) + goto err; + ENV_LEAVE(env, ip); + } + +err: if (ret != 0) + (void)__env_refresh(dbenv, orig_flags, 0); + + if (register_recovery) { + /* + * If recovery succeeded, release our exclusive lock, other + * processes can now proceed. + * + * If recovery failed, unregister now and let another process + * clean up. + */ + if (ret == 0 && (t_ret = __envreg_xunlock(env)) != 0) + ret = t_ret; + if (ret != 0) + (void)__envreg_unregister(env, 1); + } + + /* + * If the open is called with DB_REGISTER we can potentially skip + * running recovery on a panicked environment. We can't check the panic + * bit earlier since checking requires opening the environment. + * Only retry if DB_RECOVER was specified - the register_recovery flag + * indicates that. + */ + if (ret == DB_RUNRECOVERY && !register_recovery && + !LF_ISSET(DB_RECOVER) && LF_ISSET(DB_REGISTER)) { + LF_SET(DB_RECOVER); + goto retry; + } + + return (ret); +} + +/* + * __env_open_arg -- + * DB_ENV->open flags checking. + */ +static int +__env_open_arg(dbenv, flags) + DB_ENV *dbenv; + u_int32_t flags; +{ + ENV *env; + int ret; + + env = dbenv->env; + ret = 0; + + if (LF_ISSET(DB_REGISTER)) { + if (!__os_support_db_register()) { + __db_errx(env, DB_STR("1568", + "Berkeley DB library does not support DB_REGISTER on this system")); + return (EINVAL); + } + if ((ret = __db_fcchk(env, "DB_ENV->open", flags, + DB_PRIVATE, DB_REGISTER | DB_SYSTEM_MEM)) != 0) + return (ret); + if (LF_ISSET(DB_CREATE) && !LF_ISSET(DB_INIT_TXN)) { + __db_errx(env, DB_STR("1569", + "registration requires transaction support")); + return (EINVAL); + } + } + /* + * Only check for flags compatible with DB_INIT_REP when creating + * since otherwise it'll be ignored anyway. + */ + if (LF_ISSET(DB_INIT_REP) && LF_ISSET(DB_CREATE)) { + if (!__os_support_replication()) { + __db_errx(env, DB_STR("1570", + "Berkeley DB library does not support replication on this system")); + return (EINVAL); + } + if (!LF_ISSET(DB_INIT_LOCK)) { + __db_errx(env, DB_STR("1571", + "replication requires locking support")); + return (EINVAL); + } + if (!LF_ISSET(DB_INIT_TXN)) { + __db_errx(env, DB_STR("1572", + "replication requires transaction support")); + return (EINVAL); + } + } + if (LF_ISSET(DB_RECOVER | DB_RECOVER_FATAL)) { + if ((ret = __db_fcchk(env, + "DB_ENV->open", flags, DB_RECOVER, DB_RECOVER_FATAL)) != 0) + return (ret); + if ((ret = __db_fcchk(env, + "DB_ENV->open", flags, DB_REGISTER, DB_RECOVER_FATAL)) != 0) + return (ret); + if (!LF_ISSET(DB_CREATE)) { + __db_errx(env, DB_STR("1573", + "recovery requires the create flag")); + return (EINVAL); + } + if (!LF_ISSET(DB_INIT_TXN)) { + __db_errx(env, DB_STR("1574", + "recovery requires transaction support")); + return (EINVAL); + } + } + if (LF_ISSET(DB_FAILCHK)) { + if (!ALIVE_ON(env)) { + __db_errx(env, DB_STR("1575", + "DB_FAILCHK requires DB_ENV->is_alive be configured")); + return (EINVAL); + } + if (dbenv->thr_max == 0) { + __db_errx(env, DB_STR("1576", + "DB_FAILCHK requires DB_ENV->set_thread_count be configured")); + return (EINVAL); + } + } + +#ifdef HAVE_MUTEX_THREAD_ONLY + /* + * Currently we support one kind of mutex that is intra-process only, + * POSIX 1003.1 pthreads, because a variety of systems don't support + * the full pthreads API, and our only alternative is test-and-set. + */ + if (!LF_ISSET(DB_PRIVATE)) { + __db_errx(env, DB_STR("1577", + "Berkeley DB library configured to support only private environments")); + return (EINVAL); + } +#endif + +#ifdef HAVE_MUTEX_FCNTL + /* + * !!! + * We need a file descriptor for fcntl(2) locking. We use the file + * handle from the REGENV file for this purpose. + * + * Since we may be using shared memory regions, e.g., shmget(2), and + * not a mapped-in regular file, the backing file may be only a few + * bytes in length. So, this depends on the ability to call fcntl to + * lock file offsets much larger than the actual physical file. I + * think that's safe -- besides, very few systems actually need this + * kind of support, SunOS is the only one still in wide use of which + * I'm aware. + * + * The error case is if an application lacks spinlocks and wants to be + * threaded. That doesn't work because fcntl will lock the underlying + * process, including all its threads. + */ + if (F_ISSET(env, ENV_THREAD)) { + __db_errx(env, DB_STR("1578", + "architecture lacks fast mutexes: applications cannot be threaded")); + return (EINVAL); + } +#endif + return (ret); +} + +/* + * __env_remove -- + * DB_ENV->remove. + * + * PUBLIC: int __env_remove __P((DB_ENV *, const char *, u_int32_t)); + */ +int +__env_remove(dbenv, db_home, flags) + DB_ENV *dbenv; + const char *db_home; + u_int32_t flags; +{ + ENV *env; + int ret, t_ret; + + env = dbenv->env; + +#undef OKFLAGS +#define OKFLAGS \ + (DB_FORCE | DB_USE_ENVIRON | DB_USE_ENVIRON_ROOT) + + /* Validate arguments. */ + if ((ret = __db_fchk(env, "DB_ENV->remove", flags, OKFLAGS)) != 0) + return (ret); + + ENV_ILLEGAL_AFTER_OPEN(env, "DB_ENV->remove"); + + if ((ret = __env_config(dbenv, db_home, &flags, 0)) != 0) + return (ret); + + /* + * Turn the environment off -- if the environment is corrupted, this + * could fail. Ignore any error if we're forcing the question. + */ + if ((ret = __env_turn_off(env, flags)) == 0 || LF_ISSET(DB_FORCE)) + ret = __env_remove_env(env); + + if ((t_ret = __env_close(dbenv, 0)) != 0 && ret == 0) + ret = t_ret; + + return (ret); +} + +/* + * __env_config -- + * Argument-based initialization. + * + * PUBLIC: int __env_config __P((DB_ENV *, const char *, u_int32_t *, int)); + */ +int +__env_config(dbenv, db_home, flagsp, mode) + DB_ENV *dbenv; + const char *db_home; + u_int32_t *flagsp; + int mode; +{ + ENV *env; + int ret; + u_int32_t flags; + char *home, home_buf[DB_MAXPATHLEN]; + + env = dbenv->env; + flags = *flagsp; + + /* + * Set the database home. + * + * Use db_home by default, this allows utilities to reasonably + * override the environment either explicitly or by using a -h + * option. Otherwise, use the environment if it's permitted + * and initialized. + */ + home = (char *)db_home; + if (home == NULL && (LF_ISSET(DB_USE_ENVIRON) || + (LF_ISSET(DB_USE_ENVIRON_ROOT) && __os_isroot()))) { + home = home_buf; + if ((ret = __os_getenv( + env, "DB_HOME", &home, sizeof(home_buf))) != 0) + return (ret); + /* + * home set to NULL if __os_getenv failed to find DB_HOME. + */ + } + if (home != NULL) { + if (env->db_home != NULL) + __os_free(env, env->db_home); + if ((ret = __os_strdup(env, home, &env->db_home)) != 0) + return (ret); + } + + /* Save a copy of the DB_ENV->open method flags. */ + env->open_flags = flags; + + /* Default permissions are read-write for both owner and group. */ + env->db_mode = mode == 0 ? DB_MODE_660 : mode; + + /* Read the DB_CONFIG file. */ + if ((ret = __env_read_db_config(env)) != 0) + return (ret); + + /* + * Update the DB_ENV->open method flags. The copy of the flags might + * have been changed during reading DB_CONFIG file. + */ + flags = env->open_flags; + + /* + * If no temporary directory path was specified in the config file, + * choose one. + */ + if (dbenv->db_tmp_dir == NULL && (ret = __os_tmpdir(env, flags)) != 0) + return (ret); + + *flagsp = flags; + return (0); +} + +/* + * __env_close_pp -- + * DB_ENV->close pre/post processor. + * + * PUBLIC: int __env_close_pp __P((DB_ENV *, u_int32_t)); + */ +int +__env_close_pp(dbenv, flags) + DB_ENV *dbenv; + u_int32_t flags; +{ + DB_THREAD_INFO *ip; + ENV *env; + int rep_check, ret, t_ret; + u_int32_t close_flags, flags_orig; + + env = dbenv->env; + ret = 0; + close_flags = flags_orig = 0; + + /* + * Validate arguments, but as a DB_ENV handle destructor, we can't + * fail. + */ + if (flags != 0 && flags != DB_FORCESYNC && + (t_ret = __db_ferr(env, "DB_ENV->close", 0)) != 0 && ret == 0) + ret = t_ret; + +#define DBENV_FORCESYNC 0x00000001 +#define DBENV_CLOSE_REPCHECK 0x00000010 + if (flags == DB_FORCESYNC) + close_flags |= DBENV_FORCESYNC; + + /* + * If the environment has panic'd, all we do is try and discard + * the important resources. + */ + if (PANIC_ISSET(env)) { + /* clean up from registry file */ + if (dbenv->registry != NULL) { + /* + * Temporarily set no panic so we do not trigger the + * LAST_PANIC_CHECK_BEFORE_IO check in __os_physwr + * thus allowing the unregister to happen correctly. + */ + flags_orig = F_ISSET(dbenv, DB_ENV_NOPANIC); + F_SET(dbenv, DB_ENV_NOPANIC); + (void)__envreg_unregister(env, 0); + dbenv->registry = NULL; + if (!flags_orig) + F_CLR(dbenv, DB_ENV_NOPANIC); + } + + /* Close all underlying threads and sockets. */ + if (IS_ENV_REPLICATED(env)) + (void)__repmgr_close(env); + + /* Close all underlying file handles. */ + (void)__file_handle_cleanup(env); + + PANIC_CHECK(env); + } + + ENV_ENTER(env, ip); + + rep_check = IS_ENV_REPLICATED(env) ? 1 : 0; + if (rep_check) { +#ifdef HAVE_REPLICATION_THREADS + /* + * Shut down Replication Manager threads first of all. This + * must be done before __env_rep_enter to avoid a deadlock that + * could occur if repmgr's background threads try to do a rep + * operation that needs __rep_lockout. + */ + if ((t_ret = __repmgr_close(env)) != 0 && ret == 0) + ret = t_ret; +#endif + if ((t_ret = __env_rep_enter(env, 0)) != 0 && ret == 0) + ret = t_ret; + } + + if (rep_check) + close_flags |= DBENV_CLOSE_REPCHECK; + if ((t_ret = __env_close(dbenv, close_flags)) != 0 && ret == 0) + ret = t_ret; + + /* Don't ENV_LEAVE as we have already detached from the region. */ + return (ret); +} + +/* + * __env_close -- + * DB_ENV->close. + * + * PUBLIC: int __env_close __P((DB_ENV *, u_int32_t)); + */ +int +__env_close(dbenv, flags) + DB_ENV *dbenv; + u_int32_t flags; +{ + DB *dbp; + ENV *env; + int ret, rep_check, t_ret; + char **p; + u_int32_t close_flags; + + env = dbenv->env; + ret = 0; + close_flags = LF_ISSET(DBENV_FORCESYNC) ? 0 : DB_NOSYNC; + rep_check = LF_ISSET(DBENV_CLOSE_REPCHECK); + + /* + * Check to see if we were in the middle of restoring transactions and + * need to close the open files. + */ + if (TXN_ON(env) && (t_ret = __txn_preclose(env)) != 0 && ret == 0) + ret = t_ret; + +#ifdef HAVE_REPLICATION + if ((t_ret = __rep_env_close(env)) != 0 && ret == 0) + ret = t_ret; +#endif + + /* + * Close all databases opened in this environment after the rep region + * is closed. Rep region's internal database is already closed now. + */ + while ((dbp = TAILQ_FIRST(&env->dblist)) != NULL) { + /* + * Do not close the handle on a database partition, since it + * will be closed when closing the handle on the main database. + */ + while (dbp != NULL && F_ISSET(dbp, DB_AM_PARTDB)) + dbp = TAILQ_NEXT(dbp, dblistlinks); + DB_ASSERT(env, dbp != NULL); + /* + * Note down and ignore the error code. Since we can't do + * anything about the dbp handle anyway if the close + * operation fails. But we want to return the error to the + * caller. This is how this function takes care of various + * close operation errors. + */ + if (dbp->alt_close != NULL) + t_ret = dbp->alt_close(dbp, close_flags); + else + t_ret = __db_close(dbp, NULL, close_flags); + if (t_ret != 0 && ret == 0) + ret = t_ret; + } + + /* + * Detach from the regions and undo the allocations done by + * DB_ENV->open. + */ + if ((t_ret = __env_refresh(dbenv, 0, rep_check)) != 0 && ret == 0) + ret = t_ret; + +#ifdef HAVE_CRYPTO + /* + * Crypto comes last, because higher level close functions need + * cryptography. + */ + if ((t_ret = __crypto_env_close(env)) != 0 && ret == 0) + ret = t_ret; +#endif + + /* If we're registered, clean up. */ + if (dbenv->registry != NULL) { + (void)__envreg_unregister(env, 0); + dbenv->registry = NULL; + } + + /* Check we've closed all underlying file handles. */ + if ((t_ret = __file_handle_cleanup(env)) != 0 && ret == 0) + ret = t_ret; + + /* Release any string-based configuration parameters we've copied. */ + if (dbenv->db_log_dir != NULL) + __os_free(env, dbenv->db_log_dir); + dbenv->db_log_dir = NULL; + if (dbenv->db_tmp_dir != NULL) + __os_free(env, dbenv->db_tmp_dir); + dbenv->db_tmp_dir = NULL; + if (dbenv->db_md_dir != NULL) + __os_free(env, dbenv->db_md_dir); + dbenv->db_md_dir = NULL; + if (dbenv->db_data_dir != NULL) { + for (p = dbenv->db_data_dir; *p != NULL; ++p) + __os_free(env, *p); + __os_free(env, dbenv->db_data_dir); + dbenv->db_data_dir = NULL; + dbenv->data_next = 0; + } + if (dbenv->intermediate_dir_mode != NULL) + __os_free(env, dbenv->intermediate_dir_mode); + if (env->db_home != NULL) { + __os_free(env, env->db_home); + env->db_home = NULL; + } + + if (env->backup_handle != NULL) { + __os_free(env, env->backup_handle); + env->backup_handle = NULL; + } + + /* Discard the structure. */ + __db_env_destroy(dbenv); + + return (ret); +} + +/* + * __env_refresh -- + * Refresh the DB_ENV structure. + * PUBLIC: int __env_refresh __P((DB_ENV *, u_int32_t, int)); + */ +int +__env_refresh(dbenv, orig_flags, rep_check) + DB_ENV *dbenv; + u_int32_t orig_flags; + int rep_check; +{ + DB *ldbp; + DB_THREAD_INFO *ip; + ENV *env; + int ret, t_ret; + + env = dbenv->env; + ret = 0; + + /* + * Release resources allocated by DB_ENV->open, and return it to the + * state it was in just before __env_open was called. (This means + * state set by pre-open configuration functions must be preserved.) + * + * Refresh subsystems, in the reverse order they were opened (txn + * must be first, it may want to discard locks and flush the log). + * + * !!! + * Note that these functions, like all of __env_refresh, only undo + * the effects of __env_open. Functions that undo work done by + * db_env_create or by a configuration function should go in + * __env_close. + */ + if (TXN_ON(env) && + (t_ret = __txn_env_refresh(env)) != 0 && ret == 0) + ret = t_ret; + + if (LOGGING_ON(env) && + (t_ret = __log_env_refresh(env)) != 0 && ret == 0) + ret = t_ret; + + /* + * Locking should come after logging, because closing log results + * in files closing which may require locks being released. + */ + if (LOCKING_ON(env)) { + if (!F_ISSET(env, ENV_THREAD) && + env->env_lref != NULL && (t_ret = + __lock_id_free(env, env->env_lref)) != 0 && ret == 0) + ret = t_ret; + env->env_lref = NULL; + + if ((t_ret = __lock_env_refresh(env)) != 0 && ret == 0) + ret = t_ret; + } + + /* Discard the DB_ENV, ENV handle mutexes. */ + if ((t_ret = __mutex_free(env, &dbenv->mtx_db_env)) != 0 && ret == 0) + ret = t_ret; + if ((t_ret = __mutex_free(env, &env->mtx_env)) != 0 && ret == 0) + ret = t_ret; + + /* + * Discard DB list and its mutex. + * Discard the MT mutex. + * + * !!! + * This must be done after we close the log region, because we close + * database handles and so acquire this mutex when we close log file + * handles. + */ + if (env->db_ref != 0) { + __db_errx(env, DB_STR("1579", + "Database handles still open at environment close")); + TAILQ_FOREACH(ldbp, &env->dblist, dblistlinks) + __db_errx(env, DB_STR_A("1580", + "Open database handle: %s%s%s", "%s %s %s"), + ldbp->fname == NULL ? "unnamed" : ldbp->fname, + ldbp->dname == NULL ? "" : "/", + ldbp->dname == NULL ? "" : ldbp->dname); + if (ret == 0) + ret = EINVAL; + } + TAILQ_INIT(&env->dblist); + if ((t_ret = __mutex_free(env, &env->mtx_dblist)) != 0 && ret == 0) + ret = t_ret; + if ((t_ret = __mutex_free(env, &env->mtx_mt)) != 0 && ret == 0) + ret = t_ret; + + if (env->mt != NULL) { + __os_free(env, env->mt); + env->mt = NULL; + } + + if (MPOOL_ON(env)) { + /* + * If it's a private environment, flush the contents to disk. + * Recovery would have put everything back together, but it's + * faster and cleaner to flush instead. + * + * Ignore application max-write configuration, we're shutting + * down. + */ + if (F_ISSET(env, ENV_PRIVATE) && + !F_ISSET(dbenv, DB_ENV_NOFLUSH) && + (t_ret = __memp_sync_int(env, NULL, 0, + DB_SYNC_CACHE | DB_SYNC_SUPPRESS_WRITE, NULL, NULL)) != 0 && + ret == 0) + ret = t_ret; + + if ((t_ret = __memp_env_refresh(env)) != 0 && ret == 0) + ret = t_ret; + } + + /* + * If we're included in a shared replication handle count, this + * is our last chance to decrement that count. + * + * !!! + * We can't afford to do anything dangerous after we decrement the + * handle count, of course, as replication may be proceeding with + * client recovery. However, since we're discarding the regions + * as soon as we drop the handle count, there's little opportunity + * to do harm. + */ + if (rep_check && (t_ret = __env_db_rep_exit(env)) != 0 && ret == 0) + ret = t_ret; + + /* + * Refresh the replication region. + * + * Must come after we call __env_db_rep_exit above. + */ + if (REP_ON(env) && (t_ret = __rep_env_refresh(env)) != 0 && ret == 0) + ret = t_ret; + +#ifdef HAVE_CRYPTO + /* + * Crypto comes last, because higher level close functions need + * cryptography. + */ + if (env->reginfo != NULL && + (t_ret = __crypto_env_refresh(env)) != 0 && ret == 0) + ret = t_ret; +#endif + + /* + * Mark the thread as out of the env before we get rid of the handles + * needed to do so. + */ + if (env->thr_hashtab != NULL && + (t_ret = __env_set_state(env, &ip, THREAD_OUT)) != 0 && ret == 0) + ret = t_ret; + + /* + * We are about to detach from the mutex region. This is the last + * chance we have to acquire/destroy a mutex -- acquire/destroy the + * mutex and release our reference. + * + * !!! + * There are two DbEnv methods that care about environment reference + * counts: DbEnv.close and DbEnv.remove. The DbEnv.close method is + * not a problem because it only decrements the reference count and + * no actual resources are discarded -- lots of threads of control + * can call DbEnv.close at the same time, and regardless of racing + * on the reference count mutex, we wouldn't have a problem. Since + * the DbEnv.remove method actually discards resources, we can have + * a problem. + * + * If we decrement the reference count to 0 here, go to sleep, and + * the DbEnv.remove method is called, by the time we run again, the + * underlying shared regions could have been removed. That's fine, + * except we might actually need the regions to resolve outstanding + * operations in the various subsystems, and if we don't have hard + * OS references to the regions, we could get screwed. Of course, + * we should have hard OS references to everything we need, but just + * in case, we put off decrementing the reference count as long as + * possible. + */ + if ((t_ret = __env_ref_decrement(env)) != 0 && ret == 0) + ret = t_ret; + +#ifdef HAVE_MUTEX_SUPPORT + if (MUTEX_ON(env) && + (t_ret = __mutex_env_refresh(env)) != 0 && ret == 0) + ret = t_ret; +#endif + /* Free memory for thread tracking. */ + if (env->reginfo != NULL) { + if (F_ISSET(env, ENV_PRIVATE)) { + __env_thread_destroy(env); + t_ret = __env_detach(env, 1); + } else + t_ret = __env_detach(env, 0); + + if (t_ret != 0 && ret == 0) + ret = t_ret; + + /* + * !!! + * Don't free env->reginfo or set the reference to NULL, + * that was done by __env_detach(). + */ + } + + if (env->recover_dtab.int_dispatch != NULL) { + __os_free(env, env->recover_dtab.int_dispatch); + env->recover_dtab.int_size = 0; + env->recover_dtab.int_dispatch = NULL; + } + if (env->recover_dtab.ext_dispatch != NULL) { + __os_free(env, env->recover_dtab.ext_dispatch); + env->recover_dtab.ext_size = 0; + env->recover_dtab.ext_dispatch = NULL; + } + + dbenv->flags = orig_flags; + + return (ret); +} + +/* + * __file_handle_cleanup -- + * Close any underlying open file handles so we don't leak system + * resources. + */ +static int +__file_handle_cleanup(env) + ENV *env; +{ + DB_FH *fhp; + + if (TAILQ_FIRST(&env->fdlist) == NULL) + return (0); + + __db_errx(env, DB_STR("1581", + "File handles still open at environment close")); + while ((fhp = TAILQ_FIRST(&env->fdlist)) != NULL) { + __db_errx(env, DB_STR_A("1582", "Open file handle: %s", "%s"), + fhp->name); + (void)__os_closehandle(env, fhp); + } + return (EINVAL); +} + +/* + * __env_get_open_flags + * DbEnv.get_open_flags method. + * + * PUBLIC: int __env_get_open_flags __P((DB_ENV *, u_int32_t *)); + */ +int +__env_get_open_flags(dbenv, flagsp) + DB_ENV *dbenv; + u_int32_t *flagsp; +{ + ENV *env; + + env = dbenv->env; + + ENV_ILLEGAL_BEFORE_OPEN(env, "DB_ENV->get_open_flags"); + + *flagsp = env->open_flags; + return (0); +} +/* + * __env_attach_regions -- + * Perform attaches to env and required regions (subsystems) + * + * PUBLIC: int __env_attach_regions __P((DB_ENV *, u_int32_t, u_int32_t, int)); + */ +int +__env_attach_regions(dbenv, flags, orig_flags, retry_ok) + DB_ENV *dbenv; + u_int32_t flags; + u_int32_t orig_flags; + int retry_ok; +{ + DB_THREAD_INFO *ip; + ENV *env; + REGINFO *infop; + u_int32_t init_flags; + int create_ok, rep_check, ret; + + ip = NULL; + env = dbenv->env; + rep_check = 0; + + /* Convert the DB_ENV->open flags to internal flags. */ + create_ok = LF_ISSET(DB_CREATE) ? 1 : 0; + if (LF_ISSET(DB_LOCKDOWN)) + F_SET(env, ENV_LOCKDOWN); + if (LF_ISSET(DB_PRIVATE)) + F_SET(env, ENV_PRIVATE); + if (LF_ISSET(DB_RECOVER_FATAL)) + F_SET(env, ENV_RECOVER_FATAL); + if (LF_ISSET(DB_SYSTEM_MEM)) + F_SET(env, ENV_SYSTEM_MEM); + if (LF_ISSET(DB_THREAD)) + F_SET(env, ENV_THREAD); + + /* + * Create/join the environment. We pass in the flags of interest to + * a thread subsequently joining an environment we create. If we're + * not the ones to create the environment, our flags will be updated + * to match the existing environment. + */ + init_flags = 0; + if (LF_ISSET(DB_INIT_CDB)) + FLD_SET(init_flags, DB_INITENV_CDB); + if (F_ISSET(dbenv, DB_ENV_CDB_ALLDB)) + FLD_SET(init_flags, DB_INITENV_CDB_ALLDB); + if (LF_ISSET(DB_INIT_LOCK)) + FLD_SET(init_flags, DB_INITENV_LOCK); + if (LF_ISSET(DB_INIT_LOG)) + FLD_SET(init_flags, DB_INITENV_LOG); + if (LF_ISSET(DB_INIT_MPOOL)) + FLD_SET(init_flags, DB_INITENV_MPOOL); + if (LF_ISSET(DB_INIT_REP)) + FLD_SET(init_flags, DB_INITENV_REP); + if (LF_ISSET(DB_INIT_TXN)) + FLD_SET(init_flags, DB_INITENV_TXN); + if ((ret = __env_attach(env, &init_flags, create_ok, retry_ok)) != 0) + goto err; + + /* + * __env_attach will return the saved init_flags field, which contains + * the DB_INIT_* flags used when the environment was created. + * + * We may be joining an environment -- reset our flags to match the + * ones in the environment. + */ + if (FLD_ISSET(init_flags, DB_INITENV_CDB)) + LF_SET(DB_INIT_CDB); + if (FLD_ISSET(init_flags, DB_INITENV_LOCK)) + LF_SET(DB_INIT_LOCK); + if (FLD_ISSET(init_flags, DB_INITENV_LOG)) + LF_SET(DB_INIT_LOG); + if (FLD_ISSET(init_flags, DB_INITENV_MPOOL)) + LF_SET(DB_INIT_MPOOL); + if (FLD_ISSET(init_flags, DB_INITENV_REP)) + LF_SET(DB_INIT_REP); + if (FLD_ISSET(init_flags, DB_INITENV_TXN)) + LF_SET(DB_INIT_TXN); + if (FLD_ISSET(init_flags, DB_INITENV_CDB_ALLDB) && + (ret = __env_set_flags(dbenv, DB_CDB_ALLDB, 1)) != 0) + goto err; + + /* Initialize for CDB product. */ + if (LF_ISSET(DB_INIT_CDB)) { + LF_SET(DB_INIT_LOCK); + F_SET(env, ENV_CDB); + } + + /* + * Update the flags to match the database environment. The application + * may have specified flags of 0 to join the environment, and this line + * replaces that value with the flags corresponding to the existing, + * underlying set of subsystems. This means the DbEnv.get_open_flags + * method returns the flags to open the existing environment instead of + * the specific flags passed to the DbEnv.open method. + */ + env->open_flags = flags; + + /* + * The DB_ENV structure has now been initialized. Turn off further + * use of the DB_ENV structure and most initialization methods, we're + * about to act on the values we currently have. + */ + F_SET(env, ENV_OPEN_CALLED); + + infop = env->reginfo; + +#ifdef HAVE_MUTEX_SUPPORT + /* + * Initialize the mutex regions first before ENV_ENTER(). + * Mutexes need to be 'on' when attaching to an existing env + * in order to safely allocate the thread tracking info. + */ + if ((ret = __mutex_open(env, create_ok)) != 0) + goto err; + /* The MUTEX_REQUIRED() in __env_alloc() expects this to be set. */ + infop->mtx_alloc = ((REGENV *)infop->primary)->mtx_regenv; +#endif + /* + * Initialize thread tracking and enter the API. + */ + if ((ret = + __env_thread_init(env, F_ISSET(infop, REGION_CREATE) ? 1 : 0)) != 0) + goto err; + + ENV_ENTER(env, ip); + + /* + * Initialize the subsystems. + */ + /* + * We can now acquire/create mutexes: increment the region's reference + * count. + */ + if ((ret = __env_ref_increment(env)) != 0) + goto err; + + /* + * Initialize the handle mutexes. + */ + if ((ret = __mutex_alloc(env, + MTX_ENV_HANDLE, DB_MUTEX_PROCESS_ONLY, &dbenv->mtx_db_env)) != 0 || + (ret = __mutex_alloc(env, + MTX_ENV_HANDLE, DB_MUTEX_PROCESS_ONLY, &env->mtx_env)) != 0) + goto err; + + /* + * Initialize the replication area next, so that we can lock out this + * call if we're currently running recovery for replication. + */ + if (LF_ISSET(DB_INIT_REP) && (ret = __rep_open(env)) != 0) + goto err; + + rep_check = IS_ENV_REPLICATED(env) ? 1 : 0; + if (rep_check && (ret = __env_rep_enter(env, 0)) != 0) + goto err; + + if (LF_ISSET(DB_INIT_MPOOL)) { + if ((ret = __memp_open(env, create_ok)) != 0) + goto err; + + /* + * BDB does do cache I/O during recovery and when starting up + * replication. If creating a new environment, then suppress + * any application max-write configuration. + */ + if (create_ok) + (void)__memp_set_config( + dbenv, DB_MEMP_SUPPRESS_WRITE, 1); + + /* + * Initialize the DB list and its mutex. If the mpool is + * not initialized, we can't ever open a DB handle, which + * is why this code lives here. + */ + TAILQ_INIT(&env->dblist); + if ((ret = __mutex_alloc(env, MTX_ENV_DBLIST, + DB_MUTEX_PROCESS_ONLY, &env->mtx_dblist)) != 0) + goto err; + + /* Register DB's pgin/pgout functions. */ + if ((ret = __memp_register( + env, DB_FTYPE_SET, __db_pgin, __db_pgout)) != 0) + goto err; + } + + /* + * Initialize the ciphering area prior to any running of recovery so + * that we can initialize the keys, etc. before recovery, including + * the MT mutex. + * + * !!! + * This must be after the mpool init, but before the log initialization + * because log_open may attempt to run log_recover during its open. + */ + if (LF_ISSET(DB_INIT_MPOOL | DB_INIT_LOG | DB_INIT_TXN) && + (ret = __crypto_region_init(env)) != 0) + goto err; + if ((ret = __mutex_alloc( + env, MTX_TWISTER, DB_MUTEX_PROCESS_ONLY, &env->mtx_mt)) != 0) + goto err; + + /* + * Transactions imply logging but do not imply locking. While almost + * all applications want both locking and logging, it would not be + * unreasonable for a single threaded process to want transactions for + * atomicity guarantees, but not necessarily need concurrency. + */ + if (LF_ISSET(DB_INIT_LOG | DB_INIT_TXN)) + if ((ret = __log_open(env)) != 0) + goto err; + if (LF_ISSET(DB_INIT_LOCK)) + if ((ret = __lock_open(env)) != 0) + goto err; + + if (LF_ISSET(DB_INIT_TXN)) { + if ((ret = __txn_open(env)) != 0) + goto err; + + /* + * If the application is running with transactions, initialize + * the function tables. + */ + if ((ret = __env_init_rec(env, + ((LOG *)env->lg_handle->reginfo.primary)->persist.version)) + != 0) + goto err; + } + +#ifdef HAVE_TRANSACTIONS + /* Perform recovery for any previous run. */ + if (LF_ISSET(DB_RECOVER | DB_RECOVER_FATAL) && + (ret = __db_apprec(env, ip, NULL, NULL, 1, + LF_ISSET(DB_RECOVER | DB_RECOVER_FATAL | DB_NO_CHECKPOINT))) != 0) + goto err; + + /* + * If we've created the regions, are running with transactions, and did + * not just run recovery, we need to log the fact that the transaction + * IDs got reset. + * + * If we ran recovery, there may be prepared-but-not-yet-committed + * transactions that need to be resolved. Recovery resets the minimum + * transaction ID and logs the reset if that's appropriate, so we + * don't need to do anything here in the recover case. + */ + if (TXN_ON(env) && + !FLD_ISSET(dbenv->lg_flags, DB_LOG_IN_MEMORY) && + F_ISSET(infop, REGION_CREATE) && + !LF_ISSET(DB_RECOVER | DB_RECOVER_FATAL) && + (ret = __txn_reset(env)) != 0) + goto err; +#endif + + /* The database environment is ready for business. */ + if ((ret = __env_turn_on(env)) != 0) + goto err; + + if (rep_check) + ret = __env_db_rep_exit(env); + + /* Turn any application-specific max-write configuration back on. */ + if (LF_ISSET(DB_INIT_MPOOL)) + (void)__memp_set_config(dbenv, DB_MEMP_SUPPRESS_WRITE, 0); + +err: if (ret == 0) + ENV_LEAVE(env, ip); + else { + /* + * If we fail after creating regions, panic and remove them. + * + * !!! + * No need to call __env_db_rep_exit, that work is done by the + * calls to __env_refresh. + */ + infop = env->reginfo; + if (infop != NULL && F_ISSET(infop, REGION_CREATE)) { + ret = __env_panic(env, ret); + + /* Refresh the DB_ENV so can use it to call remove. */ + (void)__env_refresh(dbenv, orig_flags, rep_check); + (void)__env_remove_env(env); + (void)__env_refresh(dbenv, orig_flags, 0); + } else + (void)__env_refresh(dbenv, orig_flags, rep_check); + /* clear the fact that the region had been opened */ + F_CLR(env, ENV_OPEN_CALLED); + } + + return (ret); +} diff -r 000000000000 -r a1985f14b030 src/env/env_region.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/env/env_region.c Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,1519 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 1996, 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + * $Id$ + */ + +#include "db_config.h" + +#include "db_int.h" +#include "dbinc/mp.h" +#include "dbinc/lock.h" +#include "dbinc/log.h" +#include "dbinc/txn.h" + +static int __env_des_get __P((ENV *, REGINFO *, REGINFO *, REGION **)); +static int __env_faultmem __P((ENV *, void *, size_t, int)); +static int __env_sys_attach __P((ENV *, REGINFO *, REGION *)); +static int __env_sys_detach __P((ENV *, REGINFO *, int)); +static void __env_des_destroy __P((ENV *, REGION *)); +static void __env_remove_file __P((ENV *)); + +/* + * __env_attach + * Join/create the environment + * + * PUBLIC: int __env_attach __P((ENV *, u_int32_t *, int, int)); + */ +int +__env_attach(env, init_flagsp, create_ok, retry_ok) + ENV *env; + u_int32_t *init_flagsp; + int create_ok, retry_ok; +{ + DB_ENV *dbenv; + REGENV rbuf, *renv; + REGENV_REF ref; + REGINFO *infop; + REGION *rp, tregion; + size_t max, nrw, size; + long segid; + u_int32_t bytes, i, mbytes, nregions, signature; + u_int retry_cnt; + int majver, minver, patchver, ret; + char buf[sizeof(DB_REGION_FMT) + 20]; + + /* Initialization */ + dbenv = env->dbenv; + retry_cnt = 0; + signature = __env_struct_sig(); + + /* Repeated initialization. */ +loop: renv = NULL; + rp = NULL; + + /* Set up the ENV's REG_INFO structure. */ + if ((ret = __os_calloc(env, 1, sizeof(REGINFO), &infop)) != 0) + return (ret); + infop->env = env; + infop->type = REGION_TYPE_ENV; + infop->id = REGION_ID_ENV; + infop->flags = REGION_JOIN_OK; + if (create_ok) + F_SET(infop, REGION_CREATE_OK); + + /* Build the region name. */ + if (F_ISSET(env, ENV_PRIVATE)) + ret = __os_strdup(env, "process-private", &infop->name); + else { + (void)snprintf(buf, sizeof(buf), "%s", DB_REGION_ENV); + ret = __db_appname(env, DB_APP_NONE, buf, NULL, &infop->name); + } + if (ret != 0) + goto err; + + /* + * We have to single-thread the creation of the REGENV region. Once + * it exists, we can serialize using region mutexes, but until then + * we have to be the only player in the game. + * + * If this is a private environment, we are only called once and there + * are no possible race conditions. + * + * If this is a public environment, we use the filesystem to ensure + * the creation of the environment file is single-threaded. + * + * If the application has specified their own mapping functions, try + * and create the region. The application will have to let us know if + * it's actually a creation or not, and we'll have to fall-back to a + * join if it's not a create. + */ + if (F_ISSET(env, ENV_PRIVATE) || DB_GLOBAL(j_region_map) != NULL) + goto creation; + + /* + * Try to create the file, if we have the authority. We have to ensure + * that multiple threads/processes attempting to simultaneously create + * the file are properly ordered. Open using the O_CREAT and O_EXCL + * flags so that multiple attempts to create the region will return + * failure in all but one. POSIX 1003.1 requires that EEXIST be the + * errno return value -- I sure hope they're right. + */ + if (create_ok) { + if ((ret = __os_open(env, infop->name, 0, + DB_OSO_CREATE | DB_OSO_EXCL | DB_OSO_REGION, + env->db_mode, &env->lockfhp)) == 0) + goto creation; + if (ret != EEXIST) { + __db_err(env, ret, "%s", infop->name); + goto err; + } + } + + /* The region must exist, it's not okay to recreate it. */ + F_CLR(infop, REGION_CREATE_OK); + + /* + * If we couldn't create the file, try and open it. (If that fails, + * we're done.) + */ + if ((ret = __os_open( + env, infop->name, 0, DB_OSO_REGION, 0, &env->lockfhp)) != 0) + goto err; + + /* + * !!! + * The region may be in system memory not backed by the filesystem + * (more specifically, not backed by this file), and we're joining + * it. In that case, the process that created it will have written + * out a REGENV_REF structure as its only contents. We read that + * structure before we do anything further, e.g., we can't just map + * that file in and then figure out what's going on. + * + * All of this noise is because some systems don't have a coherent VM + * and buffer cache, and what's worse, when you mix operations on the + * VM and buffer cache, half the time you hang the system. + * + * If the file is the size of an REGENV_REF structure, then we know + * the real region is in some other memory. (The only way you get a + * file that size is to deliberately write it, as it's smaller than + * any possible disk sector created by writing a file or mapping the + * file into memory.) In which case, retrieve the structure from the + * file and use it to acquire the referenced memory. + * + * If the structure is larger than a REGENV_REF structure, then this + * file is backing the shared memory region, and we just map it into + * memory. + * + * And yes, this makes me want to take somebody and kill them. (I + * digress -- but you have no freakin' idea. This is unbelievably + * stupid and gross, and I've probably spent six months of my life, + * now, trying to make different versions of it work.) + */ + if ((ret = __os_ioinfo(env, infop->name, + env->lockfhp, &mbytes, &bytes, NULL)) != 0) { + __db_err(env, ret, "%s", infop->name); + goto err; + } + + /* + * !!! + * A size_t is OK -- regions get mapped into memory, and so can't + * be larger than a size_t. + */ + size = mbytes * MEGABYTE + bytes; + + /* + * If the size is less than the size of a REGENV_REF structure, the + * region (or, possibly, the REGENV_REF structure) has not yet been + * completely written. Shouldn't be possible, but there's no reason + * not to wait awhile and try again. + * + * If the region is precisely the size of a ref, then we don't + * have the region here, just the meta-data, which implies that + * that we are using SYSTEM V shared memory (SYSTEM_MEM). However, + * if the flags say that we are using SYSTEM_MEM and the region is + * bigger than the ref, something bad has happened -- we are storing + * something in the region file other than meta-data and that + * shouldn't happen. + */ + if (size < sizeof(ref)) + goto retry; + else { + + if (size == sizeof(ref)) + F_SET(env, ENV_SYSTEM_MEM); + else if (F_ISSET(env, ENV_SYSTEM_MEM)) { + ret = EINVAL; + __db_err(env, ret, DB_STR_A("1535", + "%s: existing environment not created in system memory", + "%s"), infop->name); + goto err; + } else { + if ((ret = __os_read(env, env->lockfhp, &rbuf, + sizeof(rbuf), &nrw)) != 0 || + nrw < (size_t)sizeof(rbuf) || + (ret = __os_seek(env, + env->lockfhp, 0, 0, rbuf.region_off)) != 0) { + __db_err(env, ret, DB_STR_A("1536", + "%s: unable to read region info", "%s"), + infop->name); + goto err; + } + } + + if ((ret = __os_read(env, env->lockfhp, &ref, + sizeof(ref), &nrw)) != 0 || nrw < (size_t)sizeof(ref)) { + if (ret == 0) + ret = EIO; + __db_err(env, ret, DB_STR_A("1537", + "%s: unable to read system-memory information", + "%s"), infop->name); + goto err; + } + size = ref.size; + max = ref.max; + segid = ref.segid; + } + +#ifndef HAVE_MUTEX_FCNTL + /* + * If we're not doing fcntl locking, we can close the file handle. We + * no longer need it and the less contact between the buffer cache and + * the VM, the better. + */ + (void)__os_closehandle(env, env->lockfhp); + env->lockfhp = NULL; +#endif + + /* Call the region join routine to acquire the region. */ + memset(&tregion, 0, sizeof(tregion)); + tregion.size = (roff_t)size; + tregion.max = (roff_t)max; + tregion.segid = segid; + if ((ret = __env_sys_attach(env, infop, &tregion)) != 0) + goto err; + +user_map_functions: + /* + * The environment's REGENV structure has to live at offset 0 instead + * of the usual alloc information. Set the primary reference and + * correct the "head" value to reference the alloc region. + */ + infop->primary = infop->addr; + infop->head = (u_int8_t *)infop->addr + sizeof(REGENV); + renv = infop->primary; + + /* + * Make sure the region matches our build. Special case a region + * that's all nul bytes, just treat it like any other corruption. + */ + if (renv->majver != DB_VERSION_MAJOR || + renv->minver != DB_VERSION_MINOR) { + if (renv->majver != 0 || renv->minver != 0) { + __db_errx(env, DB_STR_A("1538", + "Program version %d.%d doesn't match environment version %d.%d", + "%d %d %d %d"), DB_VERSION_MAJOR, DB_VERSION_MINOR, + renv->majver, renv->minver); + ret = DB_VERSION_MISMATCH; + } else + ret = EINVAL; + goto err; + } + if (renv->signature != signature) { + __db_errx(env, DB_STR("1539", + "Build signature doesn't match environment")); + ret = DB_VERSION_MISMATCH; + goto err; + } + + /* + * Check if the environment has had a catastrophic failure. + * + * Check the magic number to ensure the region is initialized. If the + * magic number isn't set, the lock may not have been initialized, and + * an attempt to use it could lead to random behavior. + * + * The panic and magic values aren't protected by any lock, so we never + * use them in any check that's more complex than set/not-set. + * + * !!! + * I'd rather play permissions games using the underlying file, but I + * can't because Windows/NT filesystems won't open files mode 0. + */ + if (renv->panic && !F_ISSET(dbenv, DB_ENV_NOPANIC)) { + ret = __env_panic_msg(env); + goto err; + } + if (renv->magic != DB_REGION_MAGIC) + goto retry; + + /* + * Get a reference to the underlying REGION information for this + * environment. + */ + if ((ret = __env_des_get(env, infop, infop, &rp)) != 0 || rp == NULL) + goto find_err; + infop->rp = rp; + + /* + * There's still a possibility for inconsistent data. When we acquired + * the size of the region and attached to it, it might have still been + * growing as part of its creation. We can detect this by checking the + * size we originally found against the region's current size. (The + * region's current size has to be final, the creator finished growing + * it before setting the magic number in the region.) + * + * !!! + * Skip this test when the application specified its own map functions. + * The size of the region is essentially unknown in that case: some + * other process asked the application's map function for some bytes, + * but we were never told the final size of the region. We could get + * a size back from the map function, but for all we know, our process' + * map function only knows how to join regions, it has no clue how big + * those regions are. + */ + if (DB_GLOBAL(j_region_map) == NULL && rp->size != size) + goto retry; + + /* + * Check our callers configuration flags, it's an error to configure + * incompatible or additional subsystems in an existing environment. + * Return the total set of flags to the caller so they initialize the + * correct set of subsystems. + */ + if (init_flagsp != NULL) { + FLD_CLR(*init_flagsp, renv->init_flags); + if (*init_flagsp != 0) { + __db_errx(env, DB_STR("1540", + "configured environment flags incompatible with existing environment")); + ret = EINVAL; + goto err; + } + *init_flagsp = renv->init_flags; + } + + /* + * Fault the pages into memory. Note, do this AFTER releasing the + * lock, because we're only reading the pages, not writing them. + */ + (void)__env_faultmem(env, infop->primary, rp->size, 0); + + /* Everything looks good, we're done. */ + env->reginfo = infop; + return (0); + +creation: + /* Create the environment region. */ + F_SET(infop, REGION_CREATE); + + /* + * Allocate room for REGION structures plus overhead. + */ + memset(&tregion, 0, sizeof(tregion)); + nregions = __memp_max_regions(env) + 5; + size = nregions * sizeof(REGION); + size += dbenv->passwd_len; + size += (dbenv->thr_max + dbenv->thr_max / 4) * + __env_alloc_size(sizeof(DB_THREAD_INFO)); + /* Space for replication buffer. */ + if (init_flagsp != NULL && FLD_ISSET(*init_flagsp, DB_INITENV_REP)) + size += MEGABYTE; + size += __txn_region_size(env); + size += __log_region_size(env); + size += __env_thread_size(env, size); + size += __lock_region_size(env, size); + + tregion.size = (roff_t)size; + tregion.segid = INVALID_REGION_SEGID; + + if ((tregion.max = dbenv->memory_max) == 0) { + /* Add some slop. */ + size += 16 * 1024; + tregion.max = (roff_t)size; + + tregion.max += (roff_t)__lock_region_max(env); + tregion.max += (roff_t)__txn_region_max(env); + tregion.max += (roff_t)__log_region_max(env); + tregion.max += (roff_t)__env_thread_max(env); + } else if (tregion.size > tregion.max) { + __db_errx(env, DB_STR_A("1542", + "Minimum environment memory size %ld is bigger than spcified max %ld.", + "%ld %ld"), (u_long)tregion.size, (u_long)tregion.max); + ret = EINVAL; + goto err; + } else if (F_ISSET(env, ENV_PRIVATE)) + infop->max_alloc = dbenv->memory_max; + + if ((ret = __env_sys_attach(env, infop, &tregion)) != 0) + goto err; + + /* + * If the application has specified its own mapping functions, we don't + * know until we get here if we are creating the region or not. The + * way we find out is underlying functions clear the REGION_CREATE flag. + */ + if (!F_ISSET(infop, REGION_CREATE)) + goto user_map_functions; + + /* + * Fault the pages into memory. Note, do this BEFORE we initialize + * anything, because we're writing the pages, not just reading them. + */ + (void)__env_faultmem(env, infop->addr, tregion.size, 1); + + /* + * The first object in the region is the REGENV structure. This is + * different from the other regions, and, from everything else in + * this region, where all objects are allocated from the pool, i.e., + * there aren't any fixed locations. The remaining space is made + * available for later allocation. + * + * The allocation space must be size_t aligned, because that's what + * the initialization routine is going to store there. To make sure + * that happens, the REGENV structure was padded with a final size_t. + * No other region needs to worry about it because all of them treat + * the entire region as allocation space. + * + * Set the primary reference and correct the "head" value to reference + * the alloc region. + */ + infop->primary = infop->addr; + infop->head = (u_int8_t *)infop->addr + sizeof(REGENV); + __env_alloc_init(infop, tregion.size - sizeof(REGENV)); + + /* + * Initialize the rest of the REGENV structure. (Don't set the magic + * number to the correct value, that would validate the environment). + */ + renv = infop->primary; + renv->magic = 0; + renv->panic = 0; + + (void)db_version(&majver, &minver, &patchver); + renv->majver = (u_int32_t)majver; + renv->minver = (u_int32_t)minver; + renv->patchver = (u_int32_t)patchver; + renv->signature = signature; + + (void)time(&renv->timestamp); + __os_unique_id(env, &renv->envid); + + /* + * Initialize init_flags to store the flags that any other environment + * handle that uses DB_JOINENV to join this environment will need. + */ + renv->init_flags = (init_flagsp == NULL) ? 0 : *init_flagsp; + + /* + * Set up the region array. We use an array rather than a linked list + * as we have to traverse this list after failure in some cases, and + * we don't want to infinitely loop should the application fail while + * we're manipulating the list. + */ + renv->region_cnt = nregions; + if ((ret = __env_alloc(infop, nregions * sizeof(REGION), &rp)) != 0) { + __db_err(env, ret, DB_STR("1543", + "unable to create new master region array")); + goto err; + } + renv->region_off = R_OFFSET(infop, rp); + for (i = 0; i < nregions; ++i, ++rp) + rp->id = INVALID_REGION_ID; + + renv->cipher_off = renv->thread_off = renv->rep_off = INVALID_ROFF; + renv->flags = 0; + renv->op_timestamp = renv->rep_timestamp = 0; + renv->mtx_regenv = MUTEX_INVALID; + renv->reg_panic = 0; + + /* + * Get the underlying REGION structure for this environment. Note, + * we created the underlying OS region before we acquired the REGION + * structure, which is backwards from the normal procedure. Update + * the REGION structure. + */ + if ((ret = __env_des_get(env, infop, infop, &rp)) != 0) { +find_err: __db_errx(env, DB_STR_A("1544", + "%s: unable to find environment", "%s"), infop->name); + if (ret == 0) + ret = EINVAL; + goto err; + } + infop->rp = rp; + rp->alloc = rp->size = tregion.size; + rp->max = tregion.max; + rp->segid = tregion.segid; + + /* + * !!! + * If we create an environment where regions are public and in system + * memory, we have to inform processes joining the environment how to + * attach to the shared memory segment. So, we write the shared memory + * identifier into the file, to be read by those other processes. + * + * XXX + * This is really OS-layer information, but I can't see any easy way + * to move it down there without passing down information that it has + * no right to know, e.g., that this is the one-and-only REGENV region + * and not some other random region. + */ + if (tregion.segid != INVALID_REGION_SEGID) { + ref.size = tregion.size; + ref.segid = tregion.segid; + ref.max = tregion.max; + if ((ret = __os_write( + env, env->lockfhp, &ref, sizeof(ref), &nrw)) != 0) { + __db_err(env, ret, DB_STR_A("1545", + "%s: unable to write out public environment ID", + "%s"), infop->name); + goto err; + } + } + +#ifndef HAVE_MUTEX_FCNTL + /* + * If we're not doing fcntl locking, we can close the file handle. We + * no longer need it and the less contact between the buffer cache and + * the VM, the better. + */ + if (env->lockfhp != NULL) { + (void)__os_closehandle(env, env->lockfhp); + env->lockfhp = NULL; + } +#endif + + /* Everything looks good, we're done. */ + env->reginfo = infop; + return (0); + +err: +retry: /* Close any open file handle. */ + if (env->lockfhp != NULL) { + (void)__os_closehandle(env, env->lockfhp); + env->lockfhp = NULL; + } + + /* + * If we joined or created the region, detach from it. If we created + * it, destroy it. Note, there's a path in the above code where we're + * using a temporary REGION structure because we haven't yet allocated + * the real one. In that case the region address (addr) will be filled + * in, but the REGION pointer (rp) won't. Fix it. + */ + if (infop->addr != NULL) { + if (infop->rp == NULL) + infop->rp = &tregion; + + (void)__env_sys_detach(env, + infop, F_ISSET(infop, REGION_CREATE)); + + if (rp != NULL && F_ISSET(env, DB_PRIVATE)) + __env_alloc_free(infop, rp); + } + + /* Free the allocated name and/or REGINFO structure. */ + if (infop->name != NULL) + __os_free(env, infop->name); + __os_free(env, infop); + + /* If we had a temporary error, wait awhile and try again. */ + if (ret == 0) { + if (!retry_ok || ++retry_cnt > 3) { + __db_errx(env, DB_STR("1546", + "unable to join the environment")); + ret = EAGAIN; + } else { + __os_yield(env, retry_cnt * 3, 0); + goto loop; + } + } + + return (ret); +} + +/* + * __env_turn_on -- + * Turn on the created environment. + * + * PUBLIC: int __env_turn_on __P((ENV *)); + */ +int +__env_turn_on(env) + ENV *env; +{ + REGENV *renv; + REGINFO *infop; + + infop = env->reginfo; + renv = infop->primary; + + /* If we didn't create the region, there's no need for further work. */ + if (!F_ISSET(infop, REGION_CREATE)) + return (0); + + /* + * Validate the file. All other threads of control are waiting + * on this value to be written -- "Let slip the hounds of war!" + */ + renv->magic = DB_REGION_MAGIC; + + return (0); +} + +/* + * __env_turn_off -- + * Turn off the environment. + * + * PUBLIC: int __env_turn_off __P((ENV *, u_int32_t)); + */ +int +__env_turn_off(env, flags) + ENV *env; + u_int32_t flags; +{ + REGENV *renv; + REGINFO *infop; + int ret, t_ret; + + ret = 0; + + /* + * Connect to the environment: If we can't join the environment, we + * guess it's because it doesn't exist and we're done. + * + * If the environment exists, attach and lock the environment. + */ + if (__env_attach(env, NULL, 0, 1) != 0) + return (0); + + infop = env->reginfo; + renv = infop->primary; + + MUTEX_LOCK(env, renv->mtx_regenv); + + /* + * If the environment is in use, we're done unless we're forcing the + * issue or the environment has panic'd. (If the environment panic'd, + * the thread holding the reference count may not have cleaned up, so + * we clean up. It's possible the application didn't plan on removing + * the environment in this particular call, but panic'd environments + * aren't useful to anyone.) + * + * Otherwise, panic the environment and overwrite the magic number so + * any thread of control attempting to connect (or racing with us) will + * back off and retry, or just die. + */ + if (renv->refcnt > 0 && !LF_ISSET(DB_FORCE) && !renv->panic) + ret = EBUSY; + else + renv->panic = 1; + + /* + * Unlock the environment (nobody should need this lock because + * we've poisoned the pool) and detach from the environment. + */ + MUTEX_UNLOCK(env, renv->mtx_regenv); + + if ((t_ret = __env_detach(env, 0)) != 0 && ret == 0) + ret = t_ret; + + return (ret); +} + +/* + * __env_panic_set -- + * Set/clear unrecoverable error. + * + * PUBLIC: void __env_panic_set __P((ENV *, int)); + */ +void +__env_panic_set(env, on) + ENV *env; + int on; +{ + if (env != NULL && env->reginfo != NULL) + ((REGENV *)env->reginfo->primary)->panic = on ? 1 : 0; +} + +/* + * __env_ref_increment -- + * Increment the environment's reference count. + * + * PUBLIC: int __env_ref_increment __P((ENV *)); + */ +int +__env_ref_increment(env) + ENV *env; +{ + REGENV *renv; + REGINFO *infop; + int ret; + + infop = env->reginfo; + renv = infop->primary; + + /* If we're creating the primary region, allocate a mutex. */ + if (F_ISSET(infop, REGION_CREATE)) { + if ((ret = __mutex_alloc( + env, MTX_ENV_REGION, 0, &renv->mtx_regenv)) != 0) + return (ret); + renv->refcnt = 1; + } else { + /* Lock the environment, increment the reference, unlock. */ + MUTEX_LOCK(env, renv->mtx_regenv); + ++renv->refcnt; + MUTEX_UNLOCK(env, renv->mtx_regenv); + } + + F_SET(env, ENV_REF_COUNTED); + return (0); +} + +/* + * __env_ref_decrement -- + * Decrement the environment's reference count. + * + * PUBLIC: int __env_ref_decrement __P((ENV *)); + */ +int +__env_ref_decrement(env) + ENV *env; +{ + REGENV *renv; + REGINFO *infop; + + /* Be cautious -- we may not have an environment. */ + if ((infop = env->reginfo) == NULL) + return (0); + + renv = infop->primary; + + /* Even if we have an environment, may not have reference counted it. */ + if (F_ISSET(env, ENV_REF_COUNTED)) { + /* Lock the environment, decrement the reference, unlock. */ + MUTEX_LOCK(env, renv->mtx_regenv); + if (renv->refcnt == 0) + __db_errx(env, DB_STR("1547", + "environment reference count went negative")); + else + --renv->refcnt; + MUTEX_UNLOCK(env, renv->mtx_regenv); + + F_CLR(env, ENV_REF_COUNTED); + } + + /* If a private environment, we're done with the mutex, destroy it. */ + return (F_ISSET(env, ENV_PRIVATE) ? + __mutex_free(env, &renv->mtx_regenv) : 0); +} + +/* + * __env_ref_get -- + * Get the number of environment references. This is an unprotected + * read of refcnt to simply provide a spot check of the value. It + * is only intended for use as an internal utility routine. + * + * PUBLIC: int __env_ref_get __P((DB_ENV *, u_int32_t *)); + */ +int +__env_ref_get(dbenv, countp) + DB_ENV *dbenv; + u_int32_t *countp; +{ + ENV *env; + REGENV *renv; + REGINFO *infop; + + env = dbenv->env; + infop = env->reginfo; + renv = infop->primary; + *countp = renv->refcnt; + return (0); +} + +/* + * __env_detach -- + * Detach from the environment. + * + * PUBLIC: int __env_detach __P((ENV *, int)); + */ +int +__env_detach(env, destroy) + ENV *env; + int destroy; +{ + REGENV *renv; + REGINFO *infop; + REGION rp; + int ret, t_ret; + + infop = env->reginfo; + renv = infop->primary; + ret = 0; + + /* Close the locking file handle. */ + if (env->lockfhp != NULL) { + if ((t_ret = + __os_closehandle(env, env->lockfhp)) != 0 && ret == 0) + ret = t_ret; + env->lockfhp = NULL; + } + + /* + * If a private region, return the memory to the heap. Not needed for + * filesystem-backed or system shared memory regions, that memory isn't + * owned by any particular process. + */ + if (destroy) { + /* + * Free the REGION array. + * + * The actual underlying region structure is allocated from the + * primary shared region, and we're about to free it. Save a + * copy on our stack for the REGINFO to reference when it calls + * down into the OS layer to release the shared memory segment. + */ + rp = *infop->rp; + infop->rp = &rp; + + if (renv->region_off != INVALID_ROFF) + __env_alloc_free( + infop, R_ADDR(infop, renv->region_off)); + } + + /* + * Set the ENV->reginfo field to NULL. BDB uses the ENV->reginfo + * field to decide if the underlying region can be accessed or needs + * cleanup. We're about to destroy what it references, so it needs to + * be cleared. + */ + env->reginfo = NULL; + env->thr_hashtab = NULL; + + if ((t_ret = __env_sys_detach(env, infop, destroy)) != 0 && ret == 0) + ret = t_ret; + if (infop->name != NULL) + __os_free(env, infop->name); + + /* Discard the ENV->reginfo field's memory. */ + __os_free(env, infop); + + return (ret); +} + +/* + * __env_remove_env -- + * Remove an environment. + * + * PUBLIC: int __env_remove_env __P((ENV *)); + */ +int +__env_remove_env(env) + ENV *env; +{ + DB_ENV *dbenv; + REGENV *renv; + REGINFO *infop, reginfo; + REGION *rp; + u_int32_t flags_orig, i; + + dbenv = env->dbenv; + + /* + * We do not want to hang on a mutex request, nor do we care about + * panics. + */ + flags_orig = F_ISSET(dbenv, DB_ENV_NOLOCKING | DB_ENV_NOPANIC); + F_SET(dbenv, DB_ENV_NOLOCKING | DB_ENV_NOPANIC); + + /* + * This routine has to walk a nasty line between not looking into the + * environment (which may be corrupted after an app or system crash), + * and removing everything that needs removing. + * + * Connect to the environment: If we can't join the environment, we + * guess it's because it doesn't exist. Remove the underlying files, + * at least. + */ + if (__env_attach(env, NULL, 0, 0) != 0) + goto remfiles; + + infop = env->reginfo; + renv = infop->primary; + + /* + * Kill the environment, if it's not already dead. + */ + renv->panic = 1; + + /* + * Walk the array of regions. Connect to each region and disconnect + * with the destroy flag set. This shouldn't cause any problems, even + * if the region is corrupted, because we never look inside the region + * (with the single exception of mutex regions on systems where we have + * to return resources to the underlying system). + */ + for (rp = R_ADDR(infop, renv->region_off), + i = 0; i < renv->region_cnt; ++i, ++rp) { + if (rp->id == INVALID_REGION_ID || rp->type == REGION_TYPE_ENV) + continue; + /* + * !!! + * The REGION_CREATE_OK flag is set for Windows/95 -- regions + * are zero'd out when the last reference to the region goes + * away, in which case the underlying OS region code requires + * callers be prepared to create the region in order to join it. + */ + memset(®info, 0, sizeof(reginfo)); + reginfo.id = rp->id; + reginfo.flags = REGION_CREATE_OK; + + /* + * If we get here and can't attach and/or detach to the + * region, it's a mess. Ignore errors, there's nothing + * we can do about them. + */ + if (__env_region_attach(env, ®info, 0, 0) != 0) + continue; + +#ifdef HAVE_MUTEX_SYSTEM_RESOURCES + /* + * If destroying the mutex region, return any system + * resources to the system. + */ + if (reginfo.type == REGION_TYPE_MUTEX) + __mutex_resource_return(env, ®info); +#endif + (void)__env_region_detach(env, ®info, 1); + } + + /* Detach from the environment's primary region. */ + (void)__env_detach(env, 1); + +remfiles: + /* + * Walk the list of files in the directory, unlinking files in the + * Berkeley DB name space. + */ + __env_remove_file(env); + + F_CLR(dbenv, DB_ENV_NOLOCKING | DB_ENV_NOPANIC); + F_SET(dbenv, flags_orig); + + return (0); +} + +/* + * __env_remove_file -- + * Discard any region files in the filesystem. + */ +static void +__env_remove_file(env) + ENV *env; +{ + int cnt, fcnt, lastrm, ret; + const char *dir; + char saved_char, *p, **names, *path, buf[sizeof(DB_REGION_FMT) + 20]; + + /* Get the full path of a file in the environment. */ + (void)snprintf(buf, sizeof(buf), "%s", DB_REGION_ENV); + if ((ret = __db_appname(env, + DB_APP_NONE, buf, NULL, &path)) != 0) + return; + + /* Get the parent directory for the environment. */ + if ((p = __db_rpath(path)) == NULL) { + p = path; + saved_char = *p; + + dir = PATH_DOT; + } else { + saved_char = *p; + *p = '\0'; + + dir = path; + } + + /* Get the list of file names. */ + if ((ret = __os_dirlist(env, dir, 0, &names, &fcnt)) != 0) + __db_err(env, ret, "%s", dir); + + /* Restore the path, and free it. */ + *p = saved_char; + __os_free(env, path); + + if (ret != 0) + return; + + /* + * Remove files from the region directory. + */ + for (lastrm = -1, cnt = fcnt; --cnt >= 0;) { + /* Skip anything outside our name space. */ + if (!IS_DB_FILE(names[cnt])) + continue; + + /* Skip queue extent files. */ + if (strncmp(names[cnt], "__dbq.", 6) == 0) + continue; + if (strncmp(names[cnt], "__dbp.", 6) == 0) + continue; + + /* Skip registry files. */ + if (strncmp(names[cnt], "__db.register", 13) == 0) + continue; + + /* Skip replication files. */ + if (strncmp(names[cnt], "__db.rep", 8) == 0) + continue; + + /* + * Remove the primary environment region last, because it's + * the key to this whole mess. + */ + if (strcmp(names[cnt], DB_REGION_ENV) == 0) { + lastrm = cnt; + continue; + } + + /* Remove the file. */ + if (__db_appname(env, + DB_APP_NONE, names[cnt], NULL, &path) == 0) { + /* + * Overwrite region files. Temporary files would have + * been maintained in encrypted format, so there's no + * reason to overwrite them. This is not an exact + * check on the file being a region file, but it's + * not likely to be wrong, and the worst thing that can + * happen is we overwrite a file that didn't need to be + * overwritten. + */ + (void)__os_unlink(env, path, 1); + __os_free(env, path); + } + } + + if (lastrm != -1) + if (__db_appname(env, + DB_APP_NONE, names[lastrm], NULL, &path) == 0) { + (void)__os_unlink(env, path, 1); + __os_free(env, path); + } + __os_dirfree(env, names, fcnt); +} + +/* + * __env_region_attach + * Join/create a region. + * + * PUBLIC: int __env_region_attach __P((ENV *, REGINFO *, size_t, size_t)); + */ +int +__env_region_attach(env, infop, init, max) + ENV *env; + REGINFO *infop; + size_t init, max; +{ + REGION *rp; + int ret; + char buf[sizeof(DB_REGION_FMT) + 20]; + + /* + * Find or create a REGION structure for this region. If we create + * it, the REGION_CREATE flag will be set in the infop structure. + */ + F_CLR(infop, REGION_CREATE); + if ((ret = __env_des_get(env, env->reginfo, infop, &rp)) != 0) + return (ret); + infop->env = env; + infop->rp = rp; + infop->type = rp->type; + infop->id = rp->id; + + /* + * __env_des_get may have created the region and reset the create + * flag. If we're creating the region, set the desired size. + */ + if (F_ISSET(infop, REGION_CREATE)) { + rp->alloc = rp->size = (roff_t)init; + rp->max = (roff_t)max; + } + + /* Join/create the underlying region. */ + (void)snprintf(buf, sizeof(buf), DB_REGION_FMT, infop->id); + if ((ret = __db_appname(env, + DB_APP_NONE, buf, NULL, &infop->name)) != 0) + goto err; + if ((ret = __env_sys_attach(env, infop, rp)) != 0) + goto err; + + /* + * Fault the pages into memory. Note, do this BEFORE we initialize + * anything because we're writing pages in created regions, not just + * reading them. + */ + (void)__env_faultmem(env, + infop->addr, rp->size, F_ISSET(infop, REGION_CREATE)); + + /* + * !!! + * The underlying layer may have just decided that we are going + * to create the region. There are various system issues that + * can result in a useless region that requires re-initialization. + * + * If we created the region, initialize it for allocation. + */ + if (F_ISSET(infop, REGION_CREATE)) + __env_alloc_init(infop, rp->size); + + return (0); + +err: /* Discard the underlying region. */ + if (infop->addr != NULL) + (void)__env_sys_detach(env, + infop, F_ISSET(infop, REGION_CREATE)); + else if (infop->name != NULL) { + __os_free(env, infop->name); + infop->name = NULL; + } + infop->rp = NULL; + infop->id = INVALID_REGION_ID; + + /* Discard the REGION structure if we created it. */ + if (F_ISSET(infop, REGION_CREATE)) { + __env_des_destroy(env, rp); + F_CLR(infop, REGION_CREATE); + } + + return (ret); +} + +/* + * __env_region_share + * Share the primary region. + * + * PUBLIC: int __env_region_share __P((ENV *, REGINFO *)); + */ +int +__env_region_share(env, infop) + ENV *env; + REGINFO *infop; +{ + REGINFO *envinfo; + REGION *rp; + + envinfo = env->reginfo; + rp = envinfo->rp; + F_SET(infop, F_ISSET(envinfo, REGION_CREATE) | REGION_SHARED); + infop->addr = envinfo->addr; + infop->head = envinfo->head; + + infop->env = env; + infop->rp = rp; + infop->name = envinfo->name; + infop->fhp = envinfo->fhp; + infop->type = rp->type; + infop->id = rp->id; + + return (0); +} + +/* + * __env_region_detach -- + * Detach from a region. + * + * PUBLIC: int __env_region_detach __P((ENV *, REGINFO *, int)); + */ +int +__env_region_detach(env, infop, destroy) + ENV *env; + REGINFO *infop; + int destroy; +{ + REGION *rp; + REGION_MEM *mem, *next; + int ret; + + if (F_ISSET(env, ENV_PRIVATE)) + destroy = 1; + else if (F_ISSET(infop, REGION_SHARED)) + return (0); + + rp = infop->rp; + + /* + * When discarding the regions as we shut down a database environment, + * discard any allocated shared memory segments. This is the last time + * we use them, and db_region_destroy is the last region-specific call + * we make. + */ + if (F_ISSET(env, ENV_PRIVATE) && infop->primary != NULL) { + for (mem = infop->mem; mem != NULL; mem = next) { + next = mem->next; + __env_alloc_free(infop, mem); + } + __env_alloc_free(infop, infop->primary); + } + + if (F_ISSET(infop, REGION_SHARED)) + return (0); + + /* Detach from the underlying OS region. */ + ret = __env_sys_detach(env, infop, destroy); + + /* If we destroyed the region, discard the REGION structure. */ + if (destroy) + __env_des_destroy(env, rp); + + /* Destroy the structure. */ + if (infop->name != NULL) + __os_free(env, infop->name); + + return (ret); +} + +/* + * __env_sys_attach -- + * Prep and call the underlying OS attach function. + */ +static int +__env_sys_attach(env, infop, rp) + ENV *env; + REGINFO *infop; + REGION *rp; +{ + int ret; + + /* + * All regions are created on 8K boundaries out of sheer paranoia, + * so we don't make some underlying VM unhappy. Make sure we don't + * overflow or underflow. + */ +#define OS_VMPAGESIZE (8 * 1024) +#define OS_VMROUNDOFF(i) { \ + if ((i) + OS_VMPAGESIZE - 1 > (i)) \ + (i) += OS_VMPAGESIZE - 1; \ + (i) -= (i) % OS_VMPAGESIZE; \ +} + if (F_ISSET(infop, REGION_CREATE)) { + OS_VMROUNDOFF(rp->size); + OS_VMROUNDOFF(rp->max); + } + +#ifdef DB_REGIONSIZE_MAX + /* Some architectures have hard limits on the maximum region size. */ + if (rp->size > DB_REGIONSIZE_MAX) { + __db_errx(env, DB_STR_A("1548", + "region size %lu is too large; maximum is %lu", "%lu %lu"), + (u_long)rp->size, (u_long)DB_REGIONSIZE_MAX); + return (EINVAL); + } + if (rp->max > DB_REGIONSIZE_MAX) { + __db_errx(env, DB_STR_A("1549", + "region max %lu is too large; maximum is %lu", "%lu %lu"), + (u_long)rp->max, (u_long)DB_REGIONSIZE_MAX); + return (EINVAL); + } +#endif + + /* + * If a region is private, malloc the memory. + * + * !!! + * If this fails because the region is too large to malloc, mmap(2) + * using the MAP_ANON or MAP_ANONYMOUS flags would be an alternative. + * I don't know of any architectures (yet!) where malloc is a problem. + */ + if (F_ISSET(env, ENV_PRIVATE)) { +#if defined(HAVE_MUTEX_HPPA_MSEM_INIT) + /* + * !!! + * There exist spinlocks that don't work in malloc memory, e.g., + * the HP/UX msemaphore interface. If we don't have locks that + * will work in malloc memory, we better not be private or not + * be threaded. + */ + if (F_ISSET(env, ENV_THREAD)) { + __db_errx(env, DB_STR("1550", +"architecture does not support locks inside process-local (malloc) memory")); + __db_errx(env, DB_STR("1551", + "application may not specify both DB_PRIVATE and DB_THREAD")); + return (EINVAL); + } +#endif + if ((ret = __os_malloc( + env, sizeof(REGENV), &infop->addr)) != 0) + return (ret); + + } else { +#if !defined(HAVE_MMAP_EXTEND) + /* Extend any disk file to its full size before mapping it. */ + rp->size = rp->max; +#endif + if ((ret = __os_attach(env, infop, rp)) != 0) + return (ret); + } + + /* Set the start of the allocation region. */ + infop->head = infop->addr; + + /* + * We require that the memory is aligned to fix the largest integral + * type. Otherwise, multiple processes mapping the same shared region + * would have to memcpy every value before reading it. + */ + if (infop->addr != ALIGNP_INC(infop->addr, sizeof(uintmax_t))) { + __db_errx(env, DB_STR("1552", + "region memory was not correctly aligned")); + (void)__env_sys_detach(env, infop, + F_ISSET(infop, REGION_CREATE)); + return (EINVAL); + } + + return (0); +} + +/* + * __env_sys_detach -- + * Prep and call the underlying OS detach function. + */ +static int +__env_sys_detach(env, infop, destroy) + ENV *env; + REGINFO *infop; + int destroy; +{ + + /* If a region is private, free the memory. */ + if (F_ISSET(env, ENV_PRIVATE)) { + __os_free(env, infop->addr); + return (0); + } + + return (__os_detach(env, infop, destroy)); +} + +/* + * __env_des_get -- + * Return a reference to the shared information for a REGION, + * optionally creating a new entry. + */ +static int +__env_des_get(env, env_infop, infop, rpp) + ENV *env; + REGINFO *env_infop, *infop; + REGION **rpp; +{ + REGENV *renv; + REGION *rp, *empty_slot, *first_type; + u_int32_t i, maxid; + + *rpp = NULL; + renv = env_infop->primary; + + /* + * If the caller wants to join a region, walk through the existing + * regions looking for a matching ID (if ID specified) or matching + * type (if type specified). If we return based on a matching type + * return the "primary" region, that is, the first region that was + * created of this type. + * + * Track the first empty slot and maximum region ID for new region + * allocation. + * + * MaxID starts at REGION_ID_ENV, the ID of the primary environment. + */ + maxid = REGION_ID_ENV; + empty_slot = first_type = NULL; + for (rp = R_ADDR(env_infop, renv->region_off), + i = 0; i < renv->region_cnt; ++i, ++rp) { + if (rp->id == INVALID_REGION_ID) { + if (empty_slot == NULL) + empty_slot = rp; + continue; + } + if (infop->id != INVALID_REGION_ID) { + if (infop->id == rp->id) + break; + continue; + } + if (infop->type == rp->type && + F_ISSET(infop, REGION_JOIN_OK) && + (first_type == NULL || first_type->id > rp->id)) + first_type = rp; + + if (rp->id > maxid) + maxid = rp->id; + } + + /* If we found a matching ID (or a matching type), return it. */ + if (i >= renv->region_cnt) + rp = first_type; + if (rp != NULL) { + *rpp = rp; + return (0); + } + + /* + * If we didn't find a region and we don't have permission to create + * the region, fail. The caller generates any error message. + */ + if (!F_ISSET(infop, REGION_CREATE_OK)) + return (ENOENT); + + /* + * If we didn't find a region and don't have room to create the region + * fail with an error message, there's a sizing problem. + */ + if (empty_slot == NULL) { + __db_errx(env, DB_STR("1553", + "no room remaining for additional REGIONs")); + return (ENOENT); + } + + /* + * Initialize a REGION structure for the caller. If id was set, use + * that value, otherwise we use the next available ID. + */ + memset(empty_slot, 0, sizeof(REGION)); + empty_slot->segid = INVALID_REGION_SEGID; + + /* + * Set the type and ID; if no region ID was specified, + * allocate one. + */ + empty_slot->type = infop->type; + empty_slot->id = infop->id == INVALID_REGION_ID ? maxid + 1 : infop->id; + + F_SET(infop, REGION_CREATE); + + *rpp = empty_slot; + return (0); +} + +/* + * __env_des_destroy -- + * Destroy a reference to a REGION. + */ +static void +__env_des_destroy(env, rp) + ENV *env; + REGION *rp; +{ + COMPQUIET(env, NULL); + + rp->id = INVALID_REGION_ID; +} + +/* + * __env_faultmem -- + * Fault the region into memory. + */ +static int +__env_faultmem(env, addr, size, created) + ENV *env; + void *addr; + size_t size; + int created; +{ + int ret; + u_int8_t *p, *t; + + /* Ignore heap regions. */ + if (F_ISSET(env, ENV_PRIVATE)) + return (0); + + /* + * It's sometimes significantly faster to page-fault in all of the + * region's pages before we run the application, as we see nasty + * side-effects when we page-fault while holding various locks, i.e., + * the lock takes a long time to acquire because of the underlying + * page fault, and the other threads convoy behind the lock holder. + * + * If we created the region, we write a non-zero value so that the + * system can't cheat. If we're just joining the region, we can + * only read the value and try to confuse the compiler sufficiently + * that it doesn't figure out that we're never really using it. + * + * Touch every page (assuming pages are 512B, the smallest VM page + * size used in any general purpose processor). + */ + ret = 0; + if (F_ISSET(env->dbenv, DB_ENV_REGION_INIT)) { + if (created) + for (p = addr, + t = (u_int8_t *)addr + size; p < t; p += 512) + p[0] = 0xdb; + else + for (p = addr, + t = (u_int8_t *)addr + size; p < t; p += 512) + ret |= p[0]; + } + + return (ret); +} diff -r 000000000000 -r a1985f14b030 src/env/env_sig.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/env/env_sig.c Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,223 @@ +/*- + * DO NOT EDIT: automatically built by dist/s_sig. + * + * Copyright (c) 1996, 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + * $Id$ + */ + +#include "db_config.h" + +#include "db_int.h" + +#include "dbinc/db_page.h" +#include "dbinc/btree.h" +#include "dbinc/crypto.h" +#include "dbinc/db_join.h" +#include "dbinc/db_verify.h" +#include "dbinc/hash.h" +#include "dbinc/heap.h" +#include "dbinc/lock.h" +#include "dbinc/log_verify.h" +#include "dbinc/mp.h" +#include "dbinc/partition.h" +#include "dbinc/qam.h" +#include "dbinc/txn.h" + +/* + * For a pure 32bit/64bit environment, we check all structures and calculate a + * signature. For compatible environment, we only check the structures in + * shared memory. + */ +#ifdef HAVE_MIXED_SIZE_ADDRESSING +#define __STRUCTURE_COUNT 41 +#else +#define __STRUCTURE_COUNT (41 + 104) +#endif + +/* + * __env_struct_sig -- + * Compute signature of structures. + * + * PUBLIC: u_int32_t __env_struct_sig __P((void)); + */ +u_int32_t +__env_struct_sig() +{ + u_short t[__STRUCTURE_COUNT + 5]; + u_int i; + + i = 0; +#define __ADD(s) (t[i++] = sizeof(struct s)) + +#ifdef HAVE_MUTEX_SUPPORT + __ADD(__db_mutex_stat); +#endif + __ADD(__db_lock_stat); + __ADD(__db_lock_hstat); + __ADD(__db_lock_pstat); + __ADD(__db_ilock); + __ADD(__db_lock_u); + __ADD(__db_lsn); + __ADD(__db_log_stat); + __ADD(__db_mpool_stat); + __ADD(__db_rep_stat); + __ADD(__db_repmgr_stat); + __ADD(__db_seq_stat); + __ADD(__db_bt_stat); + __ADD(__db_h_stat); + __ADD(__db_heap_stat); + __ADD(__db_qam_stat); + __ADD(__db_thread_info); + __ADD(__db_lockregion); + __ADD(__sh_dbt); + __ADD(__db_lockobj); + __ADD(__db_locker); + __ADD(__db_lockpart); + __ADD(__db_lock); + __ADD(__log); + __ADD(__mpool); + __ADD(__db_mpool_fstat_int); + __ADD(__mpoolfile); + __ADD(__bh); +#ifdef HAVE_MUTEX_SUPPORT + __ADD(__db_mutexregion); +#endif +#ifdef HAVE_MUTEX_SUPPORT + __ADD(__db_mutex_t); +#endif + __ADD(__db_reg_env); + __ADD(__db_region); + __ADD(__rep); + __ADD(__db_txn_stat_int); + __ADD(__db_txnregion); + +#ifndef HAVE_MIXED_SIZE_ADDRESSING + __ADD(__db_dbt); + __ADD(__db_lockreq); + __ADD(__db_log_cursor); + __ADD(__log_rec_spec); + __ADD(__db_mpoolfile); + __ADD(__db_mpool_fstat); + __ADD(__db_txn); + __ADD(__kids); + __ADD(__my_cursors); + __ADD(__femfs); + __ADD(__db_preplist); + __ADD(__db_txn_active); + __ADD(__db_txn_stat); + __ADD(__db_txn_token); + __ADD(__db_repmgr_site); + __ADD(__db_repmgr_conn_err); + __ADD(__db_seq_record); + __ADD(__db_sequence); + __ADD(__db); + __ADD(__cq_fq); + __ADD(__cq_aq); + __ADD(__cq_jq); + __ADD(__db_heap_rid); + __ADD(__dbc); + __ADD(__key_range); + __ADD(__db_compact); + __ADD(__db_env); + __ADD(__db_distab); + __ADD(__db_logvrfy_config); + __ADD(__db_channel); + __ADD(__db_site); + __ADD(__fn); + __ADD(__db_msgbuf); + __ADD(__pin_list); + __ADD(__env_thread_info); + __ADD(__flag_map); + __ADD(__db_backup_handle); + __ADD(__env); + __ADD(__dbc_internal); + __ADD(__dbpginfo); + __ADD(__epg); + __ADD(__cursor); + __ADD(__btree); + __ADD(__db_cipher); + __ADD(__db_foreign_info); + __ADD(__join_cursor); + __ADD(__pg_chksum); + __ADD(__pg_crypto); + __ADD(__heaphdr); + __ADD(__heaphdrsplt); + __ADD(__pglist); + __ADD(__vrfy_dbinfo); + __ADD(__vrfy_pageinfo); + __ADD(__vrfy_childinfo); + __ADD(__db_globals); + __ADD(__envq); + __ADD(__heap); + __ADD(__heap_cursor); + __ADD(__db_locktab); + __ADD(__db_entry); + __ADD(__fname); + __ADD(__db_log); + __ADD(__hdr); + __ADD(__log_persist); + __ADD(__db_commit); + __ADD(__db_filestart); + __ADD(__log_rec_hdr); + __ADD(__db_log_verify_info); + __ADD(__txn_verify_info); + __ADD(__lv_filereg_info); + __ADD(__lv_filelife); + __ADD(__lv_ckp_info); + __ADD(__lv_timestamp_info); + __ADD(__lv_txnrange); + __ADD(__add_recycle_params); + __ADD(__ckp_verify_params); + __ADD(__db_mpool); + __ADD(__db_mpreg); + __ADD(__db_mpool_hash); + __ADD(__bh_frozen_p); + __ADD(__bh_frozen_a); +#ifdef HAVE_MUTEX_SUPPORT + __ADD(__db_mutexmgr); +#endif + __ADD(__fh_t); + __ADD(__db_partition); + __ADD(__part_internal); + __ADD(__qcursor); + __ADD(__mpfarray); + __ADD(__qmpf); + __ADD(__queue); + __ADD(__qam_filelist); + __ADD(__db_reg_env_ref); + __ADD(__db_region_mem_t); + __ADD(__db_reginfo_t); + __ADD(__rep_waiter); + __ADD(__db_rep); + __ADD(__rep_lease_entry); + __ADD(__txn_detail); + __ADD(__db_txnmgr); + __ADD(__db_commit_info); + __ADD(__txn_logrec); +#endif + + return (__ham_func5(NULL, t, i * sizeof(t[0]))); +} diff -r 000000000000 -r a1985f14b030 src/env/env_stat.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/env/env_stat.c Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,901 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 1996, 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + * $Id$ + */ + +#include "db_config.h" + +#include "db_int.h" +#include "dbinc/db_page.h" +#include "dbinc/db_am.h" +#include "dbinc/lock.h" +#include "dbinc/mp.h" +#include "dbinc/txn.h" + +#ifdef HAVE_STATISTICS +static int __env_print_all __P((ENV *, u_int32_t)); +static int __env_print_dbenv_all __P((ENV *, u_int32_t)); +static int __env_print_env_all __P((ENV *, u_int32_t)); +static int __env_print_fh __P((ENV *)); +static int __env_print_stats __P((ENV *, u_int32_t)); +static int __env_print_thread __P((ENV *)); +static int __env_stat_print __P((ENV *, u_int32_t)); +static char *__env_thread_state_print __P((DB_THREAD_STATE)); +static const char * + __reg_type __P((reg_type_t)); + +/* + * __env_stat_print_pp -- + * ENV->stat_print pre/post processor. + * + * PUBLIC: int __env_stat_print_pp __P((DB_ENV *, u_int32_t)); + */ +int +__env_stat_print_pp(dbenv, flags) + DB_ENV *dbenv; + u_int32_t flags; +{ + DB_THREAD_INFO *ip; + ENV *env; + int ret; + + env = dbenv->env; + + ENV_ILLEGAL_BEFORE_OPEN(env, "DB_ENV->stat_print"); + + if ((ret = __db_fchk(env, "DB_ENV->stat_print", + flags, DB_STAT_ALL | DB_STAT_ALLOC | + DB_STAT_CLEAR | DB_STAT_SUBSYSTEM)) != 0) + return (ret); + + ENV_ENTER(env, ip); + REPLICATION_WRAP(env, (__env_stat_print(env, flags)), 0, ret); + ENV_LEAVE(env, ip); + return (ret); +} + +/* + * __env_stat_print -- + * ENV->stat_print method. + */ +static int +__env_stat_print(env, flags) + ENV *env; + u_int32_t flags; +{ + time_t now; + int ret; + char time_buf[CTIME_BUFLEN]; + + (void)time(&now); + __db_msg(env, "%.24s\tLocal time", __os_ctime(&now, time_buf)); + + if ((ret = __env_print_stats(env, flags)) != 0) + return (ret); + + if (LF_ISSET(DB_STAT_ALL) && + (ret = __env_print_all(env, flags)) != 0) + return (ret); + + if ((ret = __env_print_thread(env)) != 0) + return (ret); + + if ((ret = __env_print_fh(env)) != 0) + return (ret); + + if (!LF_ISSET(DB_STAT_SUBSYSTEM)) + return (0); + + if (LOGGING_ON(env)) { + __db_msg(env, "%s", DB_GLOBAL(db_line)); + if ((ret = __log_stat_print(env, flags)) != 0) + return (ret); + + __db_msg(env, "%s", DB_GLOBAL(db_line)); + if ((ret = __dbreg_stat_print(env, flags)) != 0) + return (ret); + } + + if (LOCKING_ON(env)) { + __db_msg(env, "%s", DB_GLOBAL(db_line)); + if ((ret = __lock_stat_print(env, flags)) != 0) + return (ret); + } + + if (MPOOL_ON(env)) { + __db_msg(env, "%s", DB_GLOBAL(db_line)); + if ((ret = __memp_stat_print(env, flags)) != 0) + return (ret); + } + + if (REP_ON(env)) { + __db_msg(env, "%s", DB_GLOBAL(db_line)); + if ((ret = __rep_stat_print(env, flags)) != 0) + return (ret); +#ifdef HAVE_REPLICATION_THREADS + if ((ret = __repmgr_stat_print(env, flags)) != 0) + return (ret); +#endif + } + + if (TXN_ON(env)) { + __db_msg(env, "%s", DB_GLOBAL(db_line)); + if ((ret = __txn_stat_print(env, flags)) != 0) + return (ret); + } + +#ifdef HAVE_MUTEX_SUPPORT + /* + * Dump the mutexes last. If DB_STAT_CLEAR is set this will + * clear out the mutex counters and we want to see them in + * the context of the other subsystems first. + */ + if (MUTEX_ON(env)) { + __db_msg(env, "%s", DB_GLOBAL(db_line)); + if ((ret = __mutex_stat_print(env, flags)) != 0) + return (ret); + } +#endif + + return (0); +} + +/* + * __env_print_stats -- + * Display the default environment statistics. + * + */ +static int +__env_print_stats(env, flags) + ENV *env; + u_int32_t flags; +{ + REGENV *renv; + REGINFO *infop; + char time_buf[CTIME_BUFLEN]; + + infop = env->reginfo; + renv = infop->primary; + + if (LF_ISSET(DB_STAT_ALL)) { + __db_msg(env, "%s", DB_GLOBAL(db_line)); + __db_msg(env, "Default database environment information:"); + } + STAT_HEX("Magic number", renv->magic); + STAT_LONG("Panic value", renv->panic); + __db_msg(env, "%d.%d.%d\tEnvironment version", + renv->majver, renv->minver, renv->patchver); + STAT_LONG("Btree version", DB_BTREEVERSION); + STAT_LONG("Hash version", DB_HASHVERSION); + STAT_LONG("Lock version", DB_LOCKVERSION); + STAT_LONG("Log version", DB_LOGVERSION); + STAT_LONG("Queue version", DB_QAMVERSION); + STAT_LONG("Sequence version", DB_SEQUENCE_VERSION); + STAT_LONG("Txn version", DB_TXNVERSION); + __db_msg(env, + "%.24s\tCreation time", __os_ctime(&renv->timestamp, time_buf)); + STAT_HEX("Environment ID", renv->envid); + __mutex_print_debug_single(env, + "Primary region allocation and reference count mutex", + renv->mtx_regenv, flags); + STAT_LONG("References", renv->refcnt); + __db_dlbytes(env, "Current region size", + (u_long)0, (u_long)0, (u_long)infop->rp->size); + __db_dlbytes(env, "Maximum region size", + (u_long)0, (u_long)0, (u_long)infop->rp->max); + + return (0); +} + +/* + * __env_print_all -- + * Display the debugging environment statistics. + */ +static int +__env_print_all(env, flags) + ENV *env; + u_int32_t flags; +{ + int ret, t_ret; + + /* + * There are two structures -- DB_ENV and ENV. + */ + ret = __env_print_dbenv_all(env, flags); + if ((t_ret = __env_print_env_all(env, flags)) != 0 && ret == 0) + ret = t_ret; + + return (ret); +} + +/* + * __env_print_dbenv_all -- + * Display the debugging environment statistics. + */ +static int +__env_print_dbenv_all(env, flags) + ENV *env; + u_int32_t flags; +{ + static const FN db_env_fn[] = { + { DB_ENV_AUTO_COMMIT, "DB_ENV_AUTO_COMMIT" }, + { DB_ENV_CDB_ALLDB, "DB_ENV_CDB_ALLDB" }, + { DB_ENV_DIRECT_DB, "DB_ENV_DIRECT_DB" }, + { DB_ENV_DSYNC_DB, "DB_ENV_DSYNC_DB" }, + { DB_ENV_MULTIVERSION, "DB_ENV_MULTIVERSION" }, + { DB_ENV_NOLOCKING, "DB_ENV_NOLOCKING" }, + { DB_ENV_NOMMAP, "DB_ENV_NOMMAP" }, + { DB_ENV_NOPANIC, "DB_ENV_NOPANIC" }, + { DB_ENV_OVERWRITE, "DB_ENV_OVERWRITE" }, + { DB_ENV_REGION_INIT, "DB_ENV_REGION_INIT" }, + { DB_ENV_TIME_NOTGRANTED, "DB_ENV_TIME_NOTGRANTED" }, + { DB_ENV_TXN_NOSYNC, "DB_ENV_TXN_NOSYNC" }, + { DB_ENV_TXN_NOWAIT, "DB_ENV_TXN_NOWAIT" }, + { DB_ENV_TXN_SNAPSHOT, "DB_ENV_TXN_SNAPSHOT" }, + { DB_ENV_TXN_WRITE_NOSYNC, "DB_ENV_TXN_WRITE_NOSYNC" }, + { DB_ENV_YIELDCPU, "DB_ENV_YIELDCPU" }, + { 0, NULL } + }; + static const FN vfn[] = { + { DB_VERB_DEADLOCK, "DB_VERB_DEADLOCK" }, + { DB_VERB_FILEOPS, "DB_VERB_FILEOPS" }, + { DB_VERB_FILEOPS_ALL, "DB_VERB_FILEOPS_ALL" }, + { DB_VERB_RECOVERY, "DB_VERB_RECOVERY" }, + { DB_VERB_REGISTER, "DB_VERB_REGISTER" }, + { DB_VERB_REPLICATION, "DB_VERB_REPLICATION" }, + { DB_VERB_REP_ELECT, "DB_VERB_REP_ELECT" }, + { DB_VERB_REP_LEASE, "DB_VERB_REP_LEASE" }, + { DB_VERB_REP_MISC, "DB_VERB_REP_MISC" }, + { DB_VERB_REP_MSGS, "DB_VERB_REP_MSGS" }, + { DB_VERB_REP_SYNC, "DB_VERB_REP_SYNC" }, + { DB_VERB_REP_SYSTEM, "DB_VERB_REP_SYSTEM" }, + { DB_VERB_REP_TEST, "DB_VERB_REP_TEST" }, + { DB_VERB_REPMGR_CONNFAIL, "DB_VERB_REPMGR_CONNFAIL" }, + { DB_VERB_REPMGR_MISC, "DB_VERB_REPMGR_MISC" }, + { DB_VERB_WAITSFOR, "DB_VERB_WAITSFOR" }, + { 0, NULL } + }; + DB_ENV *dbenv; + DB_MSGBUF mb; + char **p; + + dbenv = env->dbenv; + DB_MSGBUF_INIT(&mb); + + __db_msg(env, "%s", DB_GLOBAL(db_line)); + STAT_POINTER("ENV", dbenv->env); + __mutex_print_debug_single( + env, "DB_ENV handle mutex", dbenv->mtx_db_env, flags); + STAT_ISSET("Errcall", dbenv->db_errcall); + STAT_ISSET("Errfile", dbenv->db_errfile); + STAT_STRING("Errpfx", dbenv->db_errpfx); + STAT_ISSET("Msgfile", dbenv->db_msgfile); + STAT_ISSET("Msgcall", dbenv->db_msgcall); + + STAT_ISSET("AppDispatch", dbenv->app_dispatch); + STAT_ISSET("Event", dbenv->db_event_func); + STAT_ISSET("Feedback", dbenv->db_feedback); + STAT_ISSET("Free", dbenv->db_free); + STAT_ISSET("Panic", dbenv->db_paniccall); + STAT_ISSET("Malloc", dbenv->db_malloc); + STAT_ISSET("Realloc", dbenv->db_realloc); + STAT_ISSET("IsAlive", dbenv->is_alive); + STAT_ISSET("ThreadId", dbenv->thread_id); + STAT_ISSET("ThreadIdString", dbenv->thread_id_string); + + STAT_STRING("Log dir", dbenv->db_log_dir); + STAT_STRING("Metadata dir", dbenv->db_md_dir); + STAT_STRING("Tmp dir", dbenv->db_tmp_dir); + if (dbenv->db_data_dir == NULL) + STAT_ISSET("Data dir", dbenv->db_data_dir); + else { + for (p = dbenv->db_data_dir; *p != NULL; ++p) + __db_msgadd(env, &mb, "%s\tData dir", *p); + DB_MSGBUF_FLUSH(env, &mb); + } + + STAT_STRING( + "Intermediate directory mode", dbenv->intermediate_dir_mode); + + STAT_LONG("Shared memory key", dbenv->shm_key); + + STAT_ISSET("Password", dbenv->passwd); + + STAT_ISSET("App private", dbenv->app_private); + STAT_ISSET("Api1 internal", dbenv->api1_internal); + STAT_ISSET("Api2 internal", dbenv->api2_internal); + + __db_prflags(env, NULL, dbenv->verbose, vfn, NULL, "\tVerbose flags"); + + STAT_ULONG("Mutex align", dbenv->mutex_align); + STAT_ULONG("Mutex cnt", dbenv->mutex_cnt); + STAT_ULONG("Mutex inc", dbenv->mutex_inc); + STAT_ULONG("Mutex tas spins", dbenv->mutex_tas_spins); + + STAT_ISSET("Lock conflicts", dbenv->lk_conflicts); + STAT_LONG("Lock modes", dbenv->lk_modes); + STAT_ULONG("Lock detect", dbenv->lk_detect); + STAT_ULONG("Lock init", dbenv->lk_init); + STAT_ULONG("Lock init lockers", dbenv->lk_init_lockers); + STAT_ULONG("Lock init objects", dbenv->lk_init_objects); + STAT_ULONG("Lock max", dbenv->lk_max); + STAT_ULONG("Lock max lockers", dbenv->lk_max_lockers); + STAT_ULONG("Lock max objects", dbenv->lk_max_objects); + STAT_ULONG("Lock partitions", dbenv->lk_partitions); + STAT_ULONG("Lock object hash table size", dbenv->object_t_size); + STAT_ULONG("Lock timeout", dbenv->lk_timeout); + + STAT_ULONG("Log bsize", dbenv->lg_bsize); + STAT_FMT("Log file mode", "%#o", int, dbenv->lg_filemode); + STAT_ULONG("Log region max", dbenv->lg_regionmax); + STAT_ULONG("Log size", dbenv->lg_size); + + STAT_ULONG("Cache GB", dbenv->mp_gbytes); + STAT_ULONG("Cache B", dbenv->mp_bytes); + STAT_ULONG("Cache max GB", dbenv->mp_max_gbytes); + STAT_ULONG("Cache max B", dbenv->mp_max_bytes); + STAT_ULONG("Cache mmap size", dbenv->mp_mmapsize); + STAT_ULONG("Cache max open fd", dbenv->mp_maxopenfd); + STAT_ULONG("Cache max write", dbenv->mp_maxwrite); + STAT_ULONG("Cache number", dbenv->mp_ncache); + STAT_ULONG("Cache max write sleep", dbenv->mp_maxwrite_sleep); + + STAT_ULONG("Txn init", dbenv->tx_init); + STAT_ULONG("Txn max", dbenv->tx_max); + STAT_ULONG("Txn timestamp", dbenv->tx_timestamp); + STAT_ULONG("Txn timeout", dbenv->tx_timeout); + + STAT_ULONG("Thread count", dbenv->thr_max); + + STAT_ISSET("Registry", dbenv->registry); + STAT_ULONG("Registry offset", dbenv->registry_off); + STAT_ULONG("Registry timeout", dbenv->envreg_timeout); + + __db_prflags(env, + NULL, dbenv->flags, db_env_fn, NULL, "\tPublic environment flags"); + + return (0); +} + +/* + * __env_print_env_all -- + * Display the debugging environment statistics. + */ +static int +__env_print_env_all(env, flags) + ENV *env; + u_int32_t flags; +{ + static const FN env_fn[] = { + { ENV_CDB, "ENV_CDB" }, + { ENV_DBLOCAL, "ENV_DBLOCAL" }, + { ENV_LOCKDOWN, "ENV_LOCKDOWN" }, + { ENV_NO_OUTPUT_SET, "ENV_NO_OUTPUT_SET" }, + { ENV_OPEN_CALLED, "ENV_OPEN_CALLED" }, + { ENV_PRIVATE, "ENV_PRIVATE" }, + { ENV_RECOVER_FATAL, "ENV_RECOVER_FATAL" }, + { ENV_REF_COUNTED, "ENV_REF_COUNTED" }, + { ENV_SYSTEM_MEM, "ENV_SYSTEM_MEM" }, + { ENV_THREAD, "ENV_THREAD" }, + { 0, NULL } + }; + static const FN ofn[] = { + { DB_CREATE, "DB_CREATE" }, + { DB_FORCE, "DB_FORCE" }, + { DB_INIT_CDB, "DB_INIT_CDB" }, + { DB_INIT_LOCK, "DB_INIT_LOCK" }, + { DB_INIT_LOG, "DB_INIT_LOG" }, + { DB_INIT_MPOOL, "DB_INIT_MPOOL" }, + { DB_INIT_REP, "DB_INIT_REP" }, + { DB_INIT_TXN, "DB_INIT_TXN" }, + { DB_LOCKDOWN, "DB_LOCKDOWN" }, + { DB_NOMMAP, "DB_NOMMAP" }, + { DB_PRIVATE, "DB_PRIVATE" }, + { DB_RDONLY, "DB_RDONLY" }, + { DB_RECOVER, "DB_RECOVER" }, + { DB_RECOVER_FATAL, "DB_RECOVER_FATAL" }, + { DB_SYSTEM_MEM, "DB_SYSTEM_MEM" }, + { DB_THREAD, "DB_THREAD" }, + { DB_TRUNCATE, "DB_TRUNCATE" }, + { DB_TXN_NOSYNC, "DB_TXN_NOSYNC" }, + { DB_USE_ENVIRON, "DB_USE_ENVIRON" }, + { DB_USE_ENVIRON_ROOT, "DB_USE_ENVIRON_ROOT" }, + { 0, NULL } + }; + static const FN regenvfn[] = { + { DB_REGENV_REPLOCKED, "DB_REGENV_REPLOCKED" }, + { 0, NULL } + }; + REGENV *renv; + REGINFO *infop; + REGION *rp; + u_int32_t i; + char time_buf[CTIME_BUFLEN]; + + infop = env->reginfo; + renv = infop->primary; + + __db_msg(env, "%s", DB_GLOBAL(db_line)); + STAT_POINTER("DB_ENV", env->dbenv); + __mutex_print_debug_single( + env, "ENV handle mutex", env->mtx_env, flags); + + STAT_STRING("Home", env->db_home); + __db_prflags(env, NULL, env->open_flags, ofn, NULL, "\tOpen flags"); + STAT_FMT("Mode", "%#o", int, env->db_mode); + + STAT_ULONG("Pid cache", env->pid_cache); + + STAT_ISSET("Lockfhp", env->lockfhp); + + STAT_ISSET("Locker", env->env_lref); + + STAT_ISSET("Internal recovery table", env->recover_dtab.int_dispatch); + STAT_ULONG("Number of recovery table slots", + env->recover_dtab.int_size); + STAT_ISSET("External recovery table", env->recover_dtab.ext_dispatch); + STAT_ULONG("Number of recovery table slots", + env->recover_dtab.ext_size); + + STAT_ULONG("Thread hash buckets", env->thr_nbucket); + STAT_ISSET("Thread hash table", env->thr_hashtab); + + __mutex_print_debug_single( + env, "ENV list of DB handles mutex", env->mtx_dblist, flags); + STAT_LONG("DB reference count", env->db_ref); + + __mutex_print_debug_single(env, "MT mutex", env->mtx_mt, flags); + + STAT_ISSET("Crypto handle", env->crypto_handle); + STAT_ISSET("Lock handle", env->lk_handle); + STAT_ISSET("Log handle", env->lg_handle); + STAT_ISSET("Cache handle", env->mp_handle); + STAT_ISSET("Mutex handle", env->mutex_handle); + STAT_ISSET("Replication handle", env->rep_handle); + STAT_ISSET("Txn handle", env->tx_handle); + + STAT_ISSET("User copy", env->dbt_usercopy); + + STAT_LONG("Test abort", env->test_abort); + STAT_LONG("Test check", env->test_check); + STAT_LONG("Test copy", env->test_copy); + + __db_prflags(env, + NULL, env->flags, env_fn, NULL, "\tPrivate environment flags"); + + __db_print_reginfo(env, infop, "Primary", flags); + __db_msg(env, "%s", DB_GLOBAL(db_line)); + __db_msg(env, "Per region database environment information:"); + for (rp = R_ADDR(infop, renv->region_off), + i = 0; i < renv->region_cnt; ++i, ++rp) { + if (rp->id == INVALID_REGION_ID) + continue; + __db_msg(env, "%s Region:", __reg_type(rp->type)); + STAT_LONG("Region ID", rp->id); + STAT_LONG("Segment ID", rp->segid); + __db_dlbytes(env, + "Size", (u_long)0, (u_long)0, (u_long)rp->size); + } + __db_prflags(env, + NULL, renv->init_flags, ofn, NULL, "\tInitialization flags"); + STAT_ULONG("Region slots", renv->region_cnt); + __db_prflags(env, + NULL, renv->flags, regenvfn, NULL, "\tReplication flags"); + __db_msg(env, "%.24s\tOperation timestamp", + renv->op_timestamp == 0 ? + "!Set" : __os_ctime(&renv->op_timestamp, time_buf)); + __db_msg(env, "%.24s\tReplication timestamp", + renv->rep_timestamp == 0 ? + "!Set" : __os_ctime(&renv->rep_timestamp, time_buf)); + + return (0); +} + +static char * +__env_thread_state_print(state) + DB_THREAD_STATE state; +{ + switch (state) { + case THREAD_ACTIVE: + return ("active"); + case THREAD_BLOCKED: + return ("blocked"); + case THREAD_BLOCKED_DEAD: + return ("blocked and dead"); + case THREAD_OUT: + return ("out"); + default: + return ("unknown"); + } + /* NOTREACHED */ +} + +/* + * __env_print_thread -- + * Display the thread block state. + */ +static int +__env_print_thread(env) + ENV *env; +{ + BH *bhp; + DB_ENV *dbenv; + DB_HASHTAB *htab; + DB_MPOOL *dbmp; + DB_THREAD_INFO *ip; + PIN_LIST *list, *lp; + REGENV *renv; + REGINFO *infop; + THREAD_INFO *thread; + u_int32_t i; + char buf[DB_THREADID_STRLEN]; + + dbenv = env->dbenv; + + /* The thread table may not be configured. */ + if ((htab = env->thr_hashtab) == NULL) + return (0); + + dbmp = env->mp_handle; + __db_msg(env, "%s", DB_GLOBAL(db_line)); + __db_msg(env, "Thread tracking information"); + + /* Dump out the info we have on thread tracking. */ + infop = env->reginfo; + renv = infop->primary; + thread = R_ADDR(infop, renv->thread_off); + STAT_ULONG("Thread blocks allocated", thread->thr_count); + STAT_ULONG("Thread allocation threshold", thread->thr_max); + STAT_ULONG("Thread hash buckets", thread->thr_nbucket); + + /* Dump out the info we have on active threads. */ + __db_msg(env, "Thread status blocks:"); + for (i = 0; i < env->thr_nbucket; i++) + SH_TAILQ_FOREACH(ip, &htab[i], dbth_links, __db_thread_info) { + if (ip->dbth_state == THREAD_SLOT_NOT_IN_USE) + continue; + __db_msg(env, "\tprocess/thread %s: %s", + dbenv->thread_id_string( + dbenv, ip->dbth_pid, ip->dbth_tid, buf), + __env_thread_state_print(ip->dbth_state)); + list = R_ADDR(env->reginfo, ip->dbth_pinlist); + for (lp = list; lp < &list[ip->dbth_pinmax]; lp++) { + if (lp->b_ref == INVALID_ROFF) + continue; + bhp = R_ADDR( + &dbmp->reginfo[lp->region], lp->b_ref); + __db_msg(env, + "\t\tpins: %lu", (u_long)bhp->pgno); + } + } + return (0); +} + +/* + * __env_print_fh -- + * Display statistics for all handles open in this environment. + */ +static int +__env_print_fh(env) + ENV *env; +{ + DB_FH *fhp; + + if (TAILQ_FIRST(&env->fdlist) == NULL) + return (0); + + __db_msg(env, "%s", DB_GLOBAL(db_line)); + __db_msg(env, "Environment file handle information"); + + MUTEX_LOCK(env, env->mtx_env); + + TAILQ_FOREACH(fhp, &env->fdlist, q) + __db_print_fh(env, NULL, fhp, 0); + + MUTEX_UNLOCK(env, env->mtx_env); + + return (0); +} + +/* + * __db_print_fh -- + * Print out a file handle. + * + * PUBLIC: void __db_print_fh __P((ENV *, const char *, DB_FH *, u_int32_t)); + */ +void +__db_print_fh(env, tag, fh, flags) + ENV *env; + const char *tag; + DB_FH *fh; + u_int32_t flags; +{ + static const FN fn[] = { + { DB_FH_NOSYNC, "DB_FH_NOSYNC" }, + { DB_FH_OPENED, "DB_FH_OPENED" }, + { DB_FH_UNLINK, "DB_FH_UNLINK" }, + { 0, NULL } + }; + + if (fh == NULL) { + STAT_ISSET(tag, fh); + return; + } + + STAT_STRING("file-handle.file name", fh->name); + + __mutex_print_debug_single( + env, "file-handle.mutex", fh->mtx_fh, flags); + + STAT_LONG("file-handle.reference count", fh->ref); + STAT_LONG("file-handle.file descriptor", fh->fd); + + STAT_ULONG("file-handle.page number", fh->pgno); + STAT_ULONG("file-handle.page size", fh->pgsize); + STAT_ULONG("file-handle.page offset", fh->offset); + + STAT_ULONG("file-handle.seek count", fh->seek_count); + STAT_ULONG("file-handle.read count", fh->read_count); + STAT_ULONG("file-handle.write count", fh->write_count); + + __db_prflags(env, NULL, fh->flags, fn, NULL, "\tfile-handle.flags"); +} + +/* + * __db_print_fileid -- + * Print out a file ID. + * + * PUBLIC: void __db_print_fileid __P((ENV *, u_int8_t *, const char *)); + */ +void +__db_print_fileid(env, id, suffix) + ENV *env; + u_int8_t *id; + const char *suffix; +{ + DB_MSGBUF mb; + int i; + + if (id == NULL) { + STAT_ISSET("ID", id); + return; + } + + DB_MSGBUF_INIT(&mb); + for (i = 0; i < DB_FILE_ID_LEN; ++i, ++id) { + __db_msgadd(env, &mb, "%x", (u_int)*id); + if (i < DB_FILE_ID_LEN - 1) + __db_msgadd(env, &mb, " "); + } + if (suffix != NULL) + __db_msgadd(env, &mb, "%s", suffix); + DB_MSGBUF_FLUSH(env, &mb); +} + +/* + * __db_dl -- + * Display a big value. + * + * PUBLIC: void __db_dl __P((ENV *, const char *, u_long)); + */ +void +__db_dl(env, msg, value) + ENV *env; + const char *msg; + u_long value; +{ + /* + * Two formats: if less than 10 million, display as the number, if + * greater than 10 million display as ###M. + */ + if (value < 10000000) + __db_msg(env, "%lu\t%s", value, msg); + else + __db_msg(env, "%luM\t%s (%lu)", value / 1000000, msg, value); +} + +/* + * __db_dl_pct -- + * Display a big value, and related percentage. + * + * PUBLIC: void __db_dl_pct + * PUBLIC: __P((ENV *, const char *, u_long, int, const char *)); + */ +void +__db_dl_pct(env, msg, value, pct, tag) + ENV *env; + const char *msg, *tag; + u_long value; + int pct; +{ + DB_MSGBUF mb; + + DB_MSGBUF_INIT(&mb); + + /* + * Two formats: if less than 10 million, display as the number, if + * greater than 10 million, round it off and display as ###M. + */ + if (value < 10000000) + __db_msgadd(env, &mb, "%lu\t%s", value, msg); + else + __db_msgadd(env, + &mb, "%luM\t%s", (value + 500000) / 1000000, msg); + if (tag == NULL) + __db_msgadd(env, &mb, " (%d%%)", pct); + else + __db_msgadd(env, &mb, " (%d%% %s)", pct, tag); + + DB_MSGBUF_FLUSH(env, &mb); +} + +/* + * __db_dlbytes -- + * Display a big number of bytes. + * + * PUBLIC: void __db_dlbytes + * PUBLIC: __P((ENV *, const char *, u_long, u_long, u_long)); + */ +void +__db_dlbytes(env, msg, gbytes, mbytes, bytes) + ENV *env; + const char *msg; + u_long gbytes, mbytes, bytes; +{ + DB_MSGBUF mb; + const char *sep; + + DB_MSGBUF_INIT(&mb); + + /* Normalize the values. */ + while (bytes >= MEGABYTE) { + ++mbytes; + bytes -= MEGABYTE; + } + while (mbytes >= GIGABYTE / MEGABYTE) { + ++gbytes; + mbytes -= GIGABYTE / MEGABYTE; + } + + if (gbytes == 0 && mbytes == 0 && bytes == 0) + __db_msgadd(env, &mb, "0"); + else { + sep = ""; + if (gbytes > 0) { + __db_msgadd(env, &mb, "%luGB", gbytes); + sep = " "; + } + if (mbytes > 0) { + __db_msgadd(env, &mb, "%s%luMB", sep, mbytes); + sep = " "; + } + if (bytes >= 1024) { + __db_msgadd(env, &mb, "%s%luKB", sep, bytes / 1024); + bytes %= 1024; + sep = " "; + } + if (bytes > 0) + __db_msgadd(env, &mb, "%s%luB", sep, bytes); + } + + __db_msgadd(env, &mb, "\t%s", msg); + + DB_MSGBUF_FLUSH(env, &mb); +} + +/* + * __db_print_reginfo -- + * Print out underlying shared region information. + * + * PUBLIC: void __db_print_reginfo + * PUBLIC: __P((ENV *, REGINFO *, const char *, u_int32_t)); + */ +void +__db_print_reginfo(env, infop, s, flags) + ENV *env; + REGINFO *infop; + const char *s; + u_int32_t flags; +{ + static const FN fn[] = { + { REGION_CREATE, "REGION_CREATE" }, + { REGION_CREATE_OK, "REGION_CREATE_OK" }, + { REGION_JOIN_OK, "REGION_JOIN_OK" }, + { REGION_SHARED, "REGION_SHARED" }, + { 0, NULL } + }; + + __db_msg(env, "%s", DB_GLOBAL(db_line)); + __db_msg(env, "%s REGINFO information:", s); + STAT_STRING("Region type", __reg_type(infop->type)); + STAT_ULONG("Region ID", infop->id); + STAT_STRING("Region name", infop->name); + STAT_POINTER("Region address", infop->addr); + STAT_POINTER("Region allocation head", infop->head); + STAT_POINTER("Region primary address", infop->primary); + STAT_ULONG("Region maximum allocation", infop->max_alloc); + STAT_ULONG("Region allocated", infop->allocated); + __env_alloc_print(infop, flags); + + __db_prflags(env, NULL, infop->flags, fn, NULL, "\tRegion flags"); +} + +/* + * __reg_type -- + * Return the region type string. + */ +static const char * +__reg_type(t) + reg_type_t t; +{ + switch (t) { + case REGION_TYPE_ENV: + return ("Environment"); + case REGION_TYPE_LOCK: + return ("Lock"); + case REGION_TYPE_LOG: + return ("Log"); + case REGION_TYPE_MPOOL: + return ("Mpool"); + case REGION_TYPE_MUTEX: + return ("Mutex"); + case REGION_TYPE_TXN: + return ("Transaction"); + case INVALID_REGION_TYPE: + return ("Invalid"); + } + return ("Unknown"); +} + +#else /* !HAVE_STATISTICS */ + +/* + * __db_stat_not_built -- + * Common error routine when library not built with statistics. + * + * PUBLIC: int __db_stat_not_built __P((ENV *)); + */ +int +__db_stat_not_built(env) + ENV *env; +{ + __db_errx(env, DB_STR("1554", + "Library build did not include statistics support")); + return (DB_OPNOTSUP); +} + +int +__env_stat_print_pp(dbenv, flags) + DB_ENV *dbenv; + u_int32_t flags; +{ + COMPQUIET(flags, 0); + + return (__db_stat_not_built(dbenv->env)); +} +#endif diff -r 000000000000 -r a1985f14b030 src/fileops/fop_basic.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/fileops/fop_basic.c Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,340 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 2001, 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + * $Id$ + */ + +#include "db_config.h" + +#include "db_int.h" +#include "dbinc/db_page.h" +#include "dbinc/fop.h" +#include "dbinc/mp.h" +#include "dbinc/txn.h" +#include "dbinc/db_am.h" + +/* + * The transactional guarantees Berkeley DB provides for file + * system level operations (database physical file create, delete, + * rename) are based on our understanding of current file system + * semantics; a system that does not provide these semantics and + * guarantees could be in danger. + * + * First, as in standard database changes, fsync and fdatasync must + * work: when applied to the log file, the records written into the + * log must be transferred to stable storage. + * + * Second, it must not be possible for the log file to be removed + * without previous file system level operations being flushed to + * stable storage. Berkeley DB applications write log records + * describing file system operations into the log, then perform the + * file system operation, then commit the enclosing transaction + * (which flushes the log file to stable storage). Subsequently, + * a database environment checkpoint may make it possible for the + * application to remove the log file containing the record of the + * file system operation. DB's transactional guarantees for file + * system operations require the log file removal not succeed until + * all previous filesystem operations have been flushed to stable + * storage. In other words, the flush of the log file, or the + * removal of the log file, must block until all previous + * filesystem operations have been flushed to stable storage. This + * semantic is not, as far as we know, required by any existing + * standards document, but we have never seen a filesystem where + * it does not apply. + */ + +/* + * __fop_create -- + * Create a (transactionally protected) file system object. This is used + * to create DB files now, potentially blobs, queue extents and anything + * else you wish to store in a file system object. + * + * PUBLIC: int __fop_create __P((ENV *, DB_TXN *, + * PUBLIC: DB_FH **, const char *, const char **, APPNAME, int, u_int32_t)); + */ +int +__fop_create(env, txn, fhpp, name, dirp, appname, mode, flags) + ENV *env; + DB_TXN *txn; + DB_FH **fhpp; + const char *name, **dirp; + APPNAME appname; + int mode; + u_int32_t flags; +{ + DBT data, dirdata; + DB_FH *fhp; + DB_LSN lsn; + int ret; + char *real_name; + + real_name = NULL; + fhp = NULL; + + if ((ret = __db_appname(env, appname, name, dirp, &real_name)) != 0) + return (ret); + + if (mode == 0) + mode = DB_MODE_600; + + if (DBENV_LOGGING(env) +#if !defined(DEBUG_WOP) + && txn != NULL +#endif + ) { + DB_INIT_DBT(data, name, strlen(name) + 1); + if (dirp != NULL && *dirp != NULL) + DB_INIT_DBT(dirdata, *dirp, strlen(*dirp) + 1); + else + memset(&dirdata, 0, sizeof(dirdata)); + if ((ret = __fop_create_log(env, txn, &lsn, + flags | DB_FLUSH, + &data, &dirdata, (u_int32_t)appname, (u_int32_t)mode)) != 0) + goto err; + } + + DB_ENV_TEST_RECOVERY(env, DB_TEST_POSTLOG, ret, name); + + if (fhpp == NULL) + fhpp = &fhp; + ret = __os_open( + env, real_name, 0, DB_OSO_CREATE | DB_OSO_EXCL, mode, fhpp); + +err: +DB_TEST_RECOVERY_LABEL + if (fhpp == &fhp && fhp != NULL) + (void)__os_closehandle(env, fhp); + if (real_name != NULL) + __os_free(env, real_name); + return (ret); +} + +/* + * __fop_remove -- + * Remove a file system object. + * + * PUBLIC: int __fop_remove __P((ENV *, DB_TXN *, + * PUBLIC: u_int8_t *, const char *, const char **, APPNAME, u_int32_t)); + */ +int +__fop_remove(env, txn, fileid, name, dirp, appname, flags) + ENV *env; + DB_TXN *txn; + u_int8_t *fileid; + const char *name, **dirp; + APPNAME appname; + u_int32_t flags; +{ + DBT fdbt, ndbt; + DB_LSN lsn; + char *real_name; + int ret; + + real_name = NULL; + + if ((ret = __db_appname(env, appname, name, dirp, &real_name)) != 0) + goto err; + + if (!IS_REAL_TXN(txn)) { + if (fileid != NULL && (ret = __memp_nameop( + env, fileid, NULL, real_name, NULL, 0)) != 0) + goto err; + } else { + if (DBENV_LOGGING(env) +#if !defined(DEBUG_WOP) + && txn != NULL +#endif + ) { + memset(&fdbt, 0, sizeof(ndbt)); + fdbt.data = fileid; + fdbt.size = fileid == NULL ? 0 : DB_FILE_ID_LEN; + DB_INIT_DBT(ndbt, name, strlen(name) + 1); + if ((ret = __fop_remove_log(env, txn, &lsn, + flags, &ndbt, &fdbt, (u_int32_t)appname)) != 0) + goto err; + } + ret = __txn_remevent(env, txn, real_name, fileid, 0); + } + +err: if (real_name != NULL) + __os_free(env, real_name); + return (ret); +} + +/* + * __fop_write + * + * Write "size" bytes from "buf" to file "name" beginning at offset "off." + * If the file is open, supply a handle in fhp. Istmp indicate if this is + * an operation that needs to be undone in the face of failure (i.e., if + * this is a write to a temporary file, we're simply going to remove the + * file, so don't worry about undoing the write). + * + * Currently, we *only* use this with istmp true. If we need more general + * handling, then we'll have to zero out regions on abort (and possibly + * log the before image of the data in the log record). + * + * PUBLIC: int __fop_write __P((ENV *, DB_TXN *, + * PUBLIC: const char *, const char *, APPNAME, DB_FH *, u_int32_t, + * PUBLIC: db_pgno_t, u_int32_t, void *, u_int32_t, u_int32_t, u_int32_t)); + */ +int +__fop_write(env, txn, + name, dirname, appname, fhp, pgsize, pageno, off, buf, size, istmp, flags) + ENV *env; + DB_TXN *txn; + const char *name, *dirname; + APPNAME appname; + DB_FH *fhp; + u_int32_t pgsize; + db_pgno_t pageno; + u_int32_t off; + void *buf; + u_int32_t size, istmp, flags; +{ + DBT data, namedbt, dirdbt; + DB_LSN lsn; + size_t nbytes; + int local_open, ret, t_ret; + char *real_name; + + DB_ASSERT(env, istmp != 0); + + ret = local_open = 0; + real_name = NULL; + + if (DBENV_LOGGING(env) +#if !defined(DEBUG_WOP) + && txn != NULL +#endif + ) { + memset(&data, 0, sizeof(data)); + data.data = buf; + data.size = size; + DB_INIT_DBT(namedbt, name, strlen(name) + 1); + if (dirname != NULL) + DB_INIT_DBT(dirdbt, dirname, strlen(dirname) + 1); + else + memset(&dirdbt, 0, sizeof(dirdbt)); + if ((ret = __fop_write_log(env, txn, + &lsn, flags, &namedbt, &dirdbt, (u_int32_t)appname, + pgsize, pageno, off, &data, istmp)) != 0) + goto err; + } + + if (fhp == NULL) { + /* File isn't open; we need to reopen it. */ + if ((ret = __db_appname(env, + appname, name, &dirname, &real_name)) != 0) + return (ret); + + if ((ret = __os_open(env, real_name, 0, 0, 0, &fhp)) != 0) + goto err; + local_open = 1; + } + + /* Seek to offset. */ + if ((ret = __os_seek(env, fhp, pageno, pgsize, off)) != 0) + goto err; + + /* Now do the write. */ + if ((ret = __os_write(env, fhp, buf, size, &nbytes)) != 0) + goto err; + +err: if (local_open && + (t_ret = __os_closehandle(env, fhp)) != 0 && ret == 0) + ret = t_ret; + + if (real_name != NULL) + __os_free(env, real_name); + return (ret); +} + +/* + * __fop_rename -- + * Change a file's name. + * + * PUBLIC: int __fop_rename __P((ENV *, DB_TXN *, const char *, const char *, + * PUBLIC: const char **, u_int8_t *, APPNAME, int, u_int32_t)); + */ +int +__fop_rename(env, txn, oldname, newname, dirp, fid, appname, with_undo, flags) + ENV *env; + DB_TXN *txn; + const char *oldname; + const char *newname; + const char **dirp; + u_int8_t *fid; + APPNAME appname; + int with_undo; + u_int32_t flags; +{ + DBT fiddbt, dir, new, old; + DB_LSN lsn; + int ret; + char *n, *o; + + o = n = NULL; + if ((ret = __db_appname(env, appname, oldname, dirp, &o)) != 0) + goto err; + if ((ret = __db_appname(env, appname, newname, dirp, &n)) != 0) + goto err; + + if (DBENV_LOGGING(env) +#if !defined(DEBUG_WOP) + && txn != NULL +#endif + ) { + DB_INIT_DBT(old, oldname, strlen(oldname) + 1); + DB_INIT_DBT(new, newname, strlen(newname) + 1); + if (dirp != NULL && *dirp != NULL) + DB_INIT_DBT(dir, *dirp, strlen(*dirp) + 1); + else + memset(&dir, 0, sizeof(dir)); + memset(&fiddbt, 0, sizeof(fiddbt)); + fiddbt.data = fid; + fiddbt.size = DB_FILE_ID_LEN; + if (with_undo) + ret = __fop_rename_log(env, + txn, &lsn, flags | DB_FLUSH, + &old, &new, &dir, &fiddbt, (u_int32_t)appname); + else + ret = __fop_rename_noundo_log(env, + txn, &lsn, flags | DB_FLUSH, + &old, &new, &dir, &fiddbt, (u_int32_t)appname); + if (ret != 0) + goto err; + } + + ret = __memp_nameop(env, fid, newname, o, n, 0); + +err: if (o != NULL) + __os_free(env, o); + if (n != NULL) + __os_free(env, n); + return (ret); +} diff -r 000000000000 -r a1985f14b030 src/fileops/fop_util.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/fileops/fop_util.c Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,1192 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 2001, 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + * $Id$ + */ + +#include "db_config.h" + +#include "db_int.h" +#include "dbinc/db_page.h" +#include "dbinc/db_am.h" +#include "dbinc/hash.h" +#include "dbinc/fop.h" +#include "dbinc/lock.h" +#include "dbinc/mp.h" +#include "dbinc/txn.h" + +static int __fop_set_pgsize __P((DB *, DB_FH *, const char *)); +static int __fop_inmem_create __P((DB *, const char *, DB_TXN *, u_int32_t)); +static int __fop_inmem_read_meta __P((DB *, DB_TXN *, const char *, u_int32_t, + u_int32_t)); + +/* + * Acquire the environment meta-data lock. The parameters are the + * environment (ENV), the locker id to use in acquiring the lock (ID) + * and a pointer to a DB_LOCK. + * + * !!! + * Turn off locking for Critical Path. The application must do its own + * synchronization of open/create. Two threads creating and opening a + * file at the same time may have unpredictable results. + */ +#ifdef CRITICALPATH_10266 +#define GET_ENVLOCK(ENV, ID, L) (0) +#else +#define GET_ENVLOCK(ENV, ID, L) do { \ + DBT __dbt; \ + u_int32_t __lockval; \ + \ + if (LOCKING_ON((ENV))) { \ + __lockval = 1; \ + __dbt.data = &__lockval; \ + __dbt.size = sizeof(__lockval); \ + if ((ret = __lock_get((ENV), (ID), \ + 0, &__dbt, DB_LOCK_WRITE, (L))) != 0) \ + goto err; \ + } \ +} while (0) +#endif + +#define RESET_MPF(D, F) do { \ + (void)__memp_fclose((D)->mpf, (F)); \ + (D)->mpf = NULL; \ + F_CLR((D), DB_AM_OPEN_CALLED); \ + if ((ret = __memp_fcreate((D)->env, &(D)->mpf)) != 0) \ + goto err; \ +} while (0) + +/* + * If we open a file handle and our caller is doing fcntl(2) locking, + * we can't close the handle because that would discard the caller's + * lock. Save it until we close or refresh the DB handle. + */ +#define CLOSE_HANDLE(D, F) { \ + if ((F) != NULL) { \ + if (LF_ISSET(DB_FCNTL_LOCKING)) \ + (D)->saved_open_fhp = (F); \ + else if ((t_ret = \ + __os_closehandle((D)->env, (F))) != 0) { \ + if (ret == 0) \ + ret = t_ret; \ + goto err; \ + } \ + (F) = NULL; \ + } \ +} + +/* + * __fop_lock_handle -- + * + * Get the handle lock for a database. If the envlock is specified, do this + * as a lock_vec call that releases the environment lock before acquiring the + * handle lock. + * + * PUBLIC: int __fop_lock_handle __P((ENV *, + * PUBLIC: DB *, DB_LOCKER *, db_lockmode_t, DB_LOCK *, u_int32_t)); + * + */ +int +__fop_lock_handle(env, dbp, locker, mode, elockp, flags) + ENV *env; + DB *dbp; + DB_LOCKER *locker; + db_lockmode_t mode; + DB_LOCK *elockp; + u_int32_t flags; +{ + DBT fileobj; + DB_LOCKREQ reqs[2], *ereq; + DB_LOCK_ILOCK lock_desc; + int ret; + + if (!LOCKING_ON(env) || + F_ISSET(dbp, DB_AM_COMPENSATE | DB_AM_RECOVER)) + return (0); + + /* + * If we are in recovery, the only locking we should be + * doing is on the global environment. The one exception + * is if we are opening an exclusive database on a client + * syncing with the master. + */ + if (IS_RECOVERING(env) && !F2_ISSET(dbp, DB2_AM_INTEXCL)) + return (elockp == NULL ? 0 : __ENV_LPUT(env, *elockp)); + + memcpy(lock_desc.fileid, dbp->fileid, DB_FILE_ID_LEN); + lock_desc.pgno = dbp->meta_pgno; + lock_desc.type = DB_HANDLE_LOCK; + + memset(&fileobj, 0, sizeof(fileobj)); + fileobj.data = &lock_desc; + fileobj.size = sizeof(lock_desc); + DB_TEST_SUBLOCKS(env, flags); + if (F2_ISSET(dbp, DB2_AM_INTEXCL)) + flags |= DB_LOCK_IGNORE_REC; + if (elockp == NULL) + ret = __lock_get(env, locker, + flags, &fileobj, mode, &dbp->handle_lock); + else { + reqs[0].op = DB_LOCK_PUT; + reqs[0].lock = *elockp; + reqs[1].op = DB_LOCK_GET; + reqs[1].mode = mode; + reqs[1].obj = &fileobj; + reqs[1].timeout = 0; + if ((ret = __lock_vec(env, + locker, flags, reqs, 2, &ereq)) == 0) { + dbp->handle_lock = reqs[1].lock; + if (elockp != &dbp->handle_lock) + LOCK_INIT(*elockp); + } else if (ereq != reqs) + LOCK_INIT(*elockp); + } + + dbp->cur_locker = locker; + return (ret); +} + +/* + * __fop_file_setup -- + * + * Perform all the needed checking and locking to open up or create a + * file. + * + * There's a reason we don't push this code down into the buffer cache. + * The problem is that there's no information external to the file that + * we can use as a unique ID. UNIX has dev/inode pairs, but they are + * not necessarily unique after reboot, if the file was mounted via NFS. + * Windows has similar problems, as the FAT filesystem doesn't maintain + * dev/inode numbers across reboot. So, we must get something from the + * file we can use to ensure that, even after a reboot, the file we're + * joining in the cache is the right file for us to join. The solution + * we use is to maintain a file ID that's stored in the database, and + * that's why we have to open and read the file before calling into the + * buffer cache or obtaining a lock (we use this unique fileid to lock + * as well as to identify like files in the cache). + * + * There are a couple of idiosyncrasies that this code must support, in + * particular, DB_TRUNCATE and DB_FCNTL_LOCKING. First, we disallow + * DB_TRUNCATE in the presence of transactions, since opening a file with + * O_TRUNC will result in data being lost in an unrecoverable fashion. + * We also disallow DB_TRUNCATE if locking is enabled, because even in + * the presence of locking, we cannot avoid race conditions, so allowing + * DB_TRUNCATE with locking would be misleading. See SR [#7345] for more + * details. + * + * However, if you are running with neither locking nor transactions, then + * you can specify DB_TRUNCATE, and if you do so, we will truncate the file + * regardless of its contents. + * + * FCNTL locking introduces another set of complications. First, the only + * reason we support the DB_FCNTL_LOCKING flag is for historic compatibility + * with programs like Sendmail and Postfix. In these cases, the caller may + * already have a lock on the file; we need to make sure that any file handles + * we open remain open, because if we were to close them, the lock held by the + * caller would go away. Furthermore, Sendmail and/or Postfix need the ability + * to create databases in empty files. So, when you're doing FCNTL locking, + * it's reasonable that you are trying to create a database into a 0-length + * file and we allow it, while under normal conditions, we do not create + * databases if the files already exist and are not Berkeley DB files. + * + * PUBLIC: int __fop_file_setup __P((DB *, DB_THREAD_INFO *ip, + * PUBLIC: DB_TXN *, const char *, int, u_int32_t, u_int32_t *)); + */ +int +__fop_file_setup(dbp, ip, txn, name, mode, flags, retidp) + DB *dbp; + DB_THREAD_INFO *ip; + DB_TXN *txn; + const char *name; + int mode; + u_int32_t flags, *retidp; +{ + DBTYPE save_type; + DB_FH *fhp; + DB_LOCK elock; + DB_LOCKER *locker; + DB_TXN *stxn; + ENV *env; + size_t len; + APPNAME aflags; + u_int32_t dflags, oflags; + u_int8_t mbuf[DBMETASIZE]; + int created_locker, create_ok, ret, retries, t_ret, tmp_created; + int truncating, was_inval; + char *real_name, *real_tmpname, *tmpname; + db_lockmode_t lockmode; + + *retidp = TXN_INVALID; + + env = dbp->env; + fhp = NULL; + LOCK_INIT(elock); + stxn = NULL; + created_locker = tmp_created = truncating = was_inval = 0; + real_name = real_tmpname = tmpname = NULL; + dflags = F_ISSET(dbp, DB_AM_NOT_DURABLE) ? DB_LOG_NOT_DURABLE : 0; + aflags = LF_ISSET(DB_INTERNAL_PERSISTENT_DB) ? DB_APP_META : + (LF_ISSET(DB_INTERNAL_TEMPORARY_DB) ? DB_APP_NONE : DB_APP_DATA); + LF_CLR(DB_INTERNAL_PERSISTENT_DB | DB_INTERNAL_TEMPORARY_DB); + + ret = 0; + retries = 0; + save_type = dbp->type; + if (F2_ISSET(dbp, DB2_AM_EXCL)) + lockmode = DB_LOCK_WRITE; + else + lockmode = DB_LOCK_READ; + + /* + * Get a lockerid for this handle. There are paths through queue + * rename and remove where this dbp already has a locker, so make + * sure we don't clobber it and conflict. + */ + if (LOCKING_ON(env) && + !F_ISSET(dbp, DB_AM_COMPENSATE) && + !F_ISSET(dbp, DB_AM_RECOVER) && + dbp->locker == DB_LOCK_INVALIDID) { + if ((ret = __lock_id(env, NULL, &dbp->locker)) != 0) + goto err; + created_locker = 1; + } + LOCK_INIT(dbp->handle_lock); + + locker = dbp->locker; +#ifdef HAVE_TRANSACTIONS + if (txn != NULL && dbp->locker != NULL && F_ISSET(txn, TXN_INFAMILY)) { + if ((ret = __lock_addfamilylocker(env, + txn->txnid, dbp->locker->id, 1)) != 0) + goto err; + txn = NULL; + } + + if (txn != NULL) + locker = txn->locker; +#endif + + oflags = 0; + if (F_ISSET(dbp, DB_AM_INMEM)) + real_name = (char *)name; + else { + /* Get the real backing file name. */ + if ((ret = __db_appname(env, + aflags, name, &dbp->dirname, &real_name)) != 0) + goto err; + + /* Fill in the default file mode. */ + if (mode == 0) + mode = DB_MODE_660; + + if (LF_ISSET(DB_RDONLY)) + oflags |= DB_OSO_RDONLY; + if (LF_ISSET(DB_TRUNCATE)) + oflags |= DB_OSO_TRUNC; + } + + retries = 0; + create_ok = LF_ISSET(DB_CREATE); + LF_CLR(DB_CREATE); + +retry: + /* + * If we cannot create the file, only retry a few times. We + * think we might be in a race with another create, but it could + * be that the backup filename exists (that is, is left over from + * a previous crash). It is also possible to read the metadata + * page while it is being written and fail the checksum. + */ + if (++retries > DB_RETRY) { + __db_errx(env, DB_STR_A("0002", + "__fop_file_setup: Retry limit (%d) exceeded", "%d"), + DB_RETRY); + goto err; + } + if (!F_ISSET(dbp, DB_AM_COMPENSATE) && !F_ISSET(dbp, DB_AM_RECOVER)) + GET_ENVLOCK(env, locker, &elock); + if (name == NULL) + ret = ENOENT; + else if (F_ISSET(dbp, DB_AM_INMEM)) { + ret = __env_mpool(dbp, name, flags); + /* + * We are using __env_open as a check for existence. + * However, __env_mpool does an actual open and there + * are scenarios where the object exists, but cannot be + * opened, because our settings don't match those internally. + * We need to check for that explicitly. We'll need the + * mpool open to read the meta-data page, so we're going to + * have to temporarily turn this dbp into an UNKNOWN one. + */ + if (ret == EINVAL) { + was_inval = 1; + save_type = dbp->type; + dbp->type = DB_UNKNOWN; + ret = __env_mpool(dbp, name, flags); + dbp->type = save_type; + } + } else + ret = __os_exists(env, real_name, NULL); + + if (ret == 0) { + /* + * If the file exists, there are 5 possible cases: + * 1. DB_EXCL was specified so this is an error, unless + * this is a file left around after a rename and we + * are in the same transaction. This gets decomposed + * into several subcases, because we check for various + * errors before we know we're in rename. + * 2. We are truncating, and it doesn't matter what kind + * of file it is, we should open/create it. + * 3. It is 0-length, we are not doing transactions (i.e., + * we are sendmail), we should open/create into it. + * -- on-disk files only! + * 4. Is it a Berkeley DB file and we should simply open it. + * 5. It is not a BDB file and we should return an error. + */ + + /* Open file (if there is one). */ +reopen: if (!F_ISSET(dbp, DB_AM_INMEM) && (ret = + __os_open(env, real_name, 0, oflags, 0, &fhp)) != 0) + goto err; + + /* Case 2: DB_TRUNCATE: we must do the creation in place. */ + if (LF_ISSET(DB_TRUNCATE)) { + if (LF_ISSET(DB_EXCL)) { + /* Case 1a: DB_EXCL and DB_TRUNCATE. */ + ret = EEXIST; + goto err; + } + tmpname = (char *)name; + goto creat2; + } + + /* Cases 1,3-5: we need to read the meta-data page. */ + if (F_ISSET(dbp, DB_AM_INMEM)) { + if (LOGGING_ON(env) && (ret = __env_dbreg_setup(dbp, + txn, NULL, name, TXN_INVALID)) != 0) + return (ret); + ret = __fop_inmem_read_meta( + dbp, txn, name, flags, DB_CHK_META|DB_CHK_ONLY); + } else { + ret = __fop_read_meta(env, real_name, mbuf, + sizeof(mbuf), fhp, + LF_ISSET(DB_NOERROR) || + (LF_ISSET(DB_FCNTL_LOCKING) && txn == NULL) ? 1 : 0, + &len); + + /* Case 3: 0-length, no txns. */ + if (ret != 0 && len == 0 && txn == NULL) { + if (LF_ISSET(DB_EXCL)) { + /* + * Case 1b: DB_EXCL and + * 0-length file exists. + */ + ret = EEXIST; + goto err; + } + tmpname = (char *)name; + if (create_ok) + goto creat2; + goto done; + } + + /* + * Case 4: This is a valid file. Now check the + * checksum and decrypt the file so the file + * id can be obtained for the handle lock. Note that + * the checksum can fail if the database is being + * written (possible because the handle lock has + * not been obtained yet). So on checksum fail retry + * until the checksum succeeds or the number of + * retries is exhausted, then throw an error. + */ + if (ret == 0 && (ret = __db_chk_meta(env, dbp, + (DBMETA *)mbuf, DB_CHK_META)) == DB_CHKSUM_FAIL) { + if ((t_ret = __ENV_LPUT(env, elock)) != 0) { + ret = t_ret; + goto err; + } + /* + * Retry unless the number of retries is + * exhausted. + */ + if (!(retries < DB_RETRY)) { + __db_errx(env, DB_STR_A("0210", + "%s: metadata page checksum error", "%s"), real_name); + if (F_ISSET(dbp, DB_AM_RECOVER)) + ret = ENOENT; + else + ret = EINVAL; + goto err; + } + CLOSE_HANDLE(dbp, fhp); + goto retry; + } + /* Get the file id for the handle lock. */ + if (ret == 0) + memcpy(dbp->fileid, + ((DBMETA *)mbuf)->uid, DB_FILE_ID_LEN); + } + + /* Case 5: Invalid file. */ + if (ret != 0) + goto err; + + /* Now, get our handle lock. */ + if ((ret = __fop_lock_handle(env, + dbp, locker, lockmode, NULL, DB_LOCK_NOWAIT)) == 0) { + if ((ret = __ENV_LPUT(env, elock)) != 0) + goto err; + } else if (ret != DB_LOCK_NOTGRANTED || + ((txn != NULL && (F_ISSET(txn, TXN_NOWAIT))) || + F2_ISSET(dbp, DB2_AM_NOWAIT))) + goto err; + else { + PERFMON3(env, + race, fop_file_setup, (char *) name, ret, flags); + /* + * We were unable to acquire the handle lock without + * blocking. The fact that we are blocking might mean + * that someone else is trying to delete the file. + * Since some platforms cannot delete files while they + * are open (Windows), we are going to have to close + * the file. This would be a problem if we were doing + * FCNTL locking, because our closing the handle would + * release the FCNTL locks. Fortunately, if we are + * doing FCNTL locking, then we should never fail to + * acquire our handle lock, so we should never get here. + * We assert it here to make sure we aren't destroying + * any application level FCNTL semantics. + */ + DB_ASSERT(env, !LF_ISSET(DB_FCNTL_LOCKING)); + if (!F_ISSET(dbp, DB_AM_INMEM)) + CLOSE_HANDLE(dbp, fhp); + if ((ret = __fop_lock_handle(env, + dbp, locker, lockmode, &elock, 0)) != 0) { + if (F_ISSET(dbp, DB_AM_INMEM)) + RESET_MPF(dbp, 0); + goto err; + } + + /* + * If we had to wait, we might be waiting on a + * dummy file used in create/destroy of a database. + * To be sure we have the correct information we + * try again. + */ + if (F_ISSET(dbp, DB_AM_INMEM)) { + RESET_MPF(dbp, 0); + MAKE_INMEM(dbp); + } + if ((ret = + __ENV_LPUT(env, dbp->handle_lock)) != 0) { + LOCK_INIT(dbp->handle_lock); + goto err; + } + goto retry; + + } + + /* + * If we got here, then we have the handle lock, it is now + * safe to check the rest of the meta data, since the file + * will not be deleted out from under the handle. + */ + if (F_ISSET(dbp, DB_AM_INMEM)) { + if ((ret = __fop_inmem_read_meta( + dbp, txn, name, flags, DB_SKIP_CHK)) != 0) + goto err; + } else { + if ((ret = __db_meta_setup(env, dbp, real_name, + (DBMETA *)mbuf, flags, DB_SKIP_CHK)) != 0) + goto err; + } + + /* + * Check for a file in the midst of a rename. If we find that + * the file is in the midst of a rename, it must be the case + * that it is in our current transaction (else we would still + * be blocking), so we can continue along and create a new file + * with the same name. In that case, we have to close the file + * handle because we reuse it below. This is a case where + * a 'was_inval' above is OK. + */ + if (F_ISSET(dbp, DB_AM_IN_RENAME)) { + was_inval = 0; + if (create_ok) { + if (F_ISSET(dbp, DB_AM_INMEM)) { + RESET_MPF(dbp, DB_MPOOL_DISCARD); + } else + CLOSE_HANDLE(dbp, fhp); + LF_SET(DB_CREATE); + goto create; + } else { + ret = ENOENT; + goto err; + } + } + + /* If we get here, a was_inval is bad. */ + if (was_inval) { + ret = EINVAL; + goto err; + } + + /* + * Now, case 1: check for DB_EXCL, because the file that exists + * is not in the middle of a rename, so we have an error. This + * is a weird case, but we need to make sure that we don't + * continue to hold the handle lock, since technically, we + * should not have been allowed to open it. + */ + if (LF_ISSET(DB_EXCL)) { + ret = __ENV_LPUT(env, dbp->handle_lock); + LOCK_INIT(dbp->handle_lock); + if (ret == 0) + ret = EEXIST; + goto err; + } + goto done; + } + + /* File does not exist. */ +#ifdef HAVE_VXWORKS + /* + * VxWorks can return file-system specific error codes if the + * file does not exist, not ENOENT. + */ + if (!create_ok) +#else + if (!create_ok || ret != ENOENT) +#endif + goto err; + LF_SET(DB_CREATE); + /* + * If we were trying to open a non-existent master database + * readonly clear that here. + */ + LF_CLR(DB_RDONLY); + F_CLR(dbp, DB_AM_RDONLY); + ret = 0; + + /* + * We need to create file, which means that we need to set up the file, + * the fileid and the locks. Then we need to call the appropriate + * routines to create meta-data pages. For in-memory files, we retain + * the environment lock, while for on-disk files, we drop the env lock + * and create into a temporary. + */ + if (!F_ISSET(dbp, DB_AM_INMEM) && + (ret = __ENV_LPUT(env, elock)) != 0) + goto err; + +create: if (txn != NULL && IS_REP_CLIENT(env) && + !F_ISSET(dbp, DB_AM_NOT_DURABLE)) { + __db_errx(env, DB_STR("0003", + "Transactional create on replication client disallowed")); + ret = EINVAL; + goto err; + } + + if (F_ISSET(dbp, DB_AM_INMEM)) { + if (LOGGING_ON(env) && (ret = + __env_dbreg_setup(dbp, txn, NULL, name, TXN_INVALID)) != 0) + return (ret); + if ((ret = __fop_inmem_create(dbp, name, txn, flags)) != 0) + return (ret); + } else { + if ((ret = __db_backup_name(env, name, txn, &tmpname)) != 0) + goto err; + if (TXN_ON(env) && txn != NULL && + (ret = __txn_begin(env, NULL, txn, &stxn, 0)) != 0) + goto err; + if ((ret = __fop_create(env, stxn, &fhp, + tmpname, &dbp->dirname, aflags, mode, dflags)) != 0) { + /* + * If no transactions, there is a race on creating the + * backup file, as the backup file name is the same for + * all processes. Wait for the other process to finish + * with the name. + */ + if (!TXN_ON(env) && ret == EEXIST) { + PERFMON3(env, + race, fop_file_setup, tmpname, ret, flags); + __os_free(env, tmpname); + tmpname = NULL; + __os_yield(env, 1, 0); + goto retry; + } + goto err; + } + tmp_created = 1; + } + +creat2: if (!F_ISSET(dbp, DB_AM_INMEM)) { + if ((ret = __db_appname(env, + aflags, tmpname, &dbp->dirname, &real_tmpname)) != 0) + goto err; + + /* Set the pagesize if it isn't yet set. */ + if (dbp->pgsize == 0 && + (ret = __fop_set_pgsize(dbp, fhp, real_tmpname)) != 0) + goto errmsg; + + /* Construct a file_id. */ + if ((ret = + __os_fileid(env, real_tmpname, 1, dbp->fileid)) != 0) + goto errmsg; + } + + if ((ret = __db_new_file(dbp, ip, + F_ISSET(dbp, DB_AM_INMEM) ? txn : stxn, fhp, tmpname)) != 0) + goto err; + + /* Output the REOPEN record after we create. */ + if (F_ISSET(dbp, DB_AM_INMEM) && dbp->log_filename != NULL && (ret = + __dbreg_log_id(dbp, txn, dbp->log_filename->id, 0)) != 0) + return (ret); + + /* + * We need to close the handle here on platforms where remove and + * rename fail if a handle is open (including Windows). + */ + CLOSE_HANDLE(dbp, fhp); + + /* + * Now move the file into place unless we are creating in place (because + * we created a database in a file that started out 0-length). If + * this is an in-memory file, we may or may not hold the environment + * lock depending on how we got here. + */ + if (!F_ISSET(dbp, DB_AM_COMPENSATE) && + !F_ISSET(dbp, DB_AM_RECOVER) && !LOCK_ISSET(elock)) + GET_ENVLOCK(env, locker, &elock); + + if (F_ISSET(dbp, DB_AM_IN_RENAME)) { + F_CLR(dbp, DB_AM_IN_RENAME); + __txn_remrem(env, txn, real_name); + } else if (name == tmpname) { + /* We created it in place. */ + } else if (!F_ISSET(dbp, DB_AM_INMEM) && + __os_exists(env, real_name, NULL) == 0) { + /* + * Someone managed to create the file; remove our temp + * and try to open the file that now exists. + */ + (void)__fop_remove(env, NULL, + dbp->fileid, tmpname, &dbp->dirname, aflags, dflags); + (void)__ENV_LPUT(env, dbp->handle_lock); + LOCK_INIT(dbp->handle_lock); + + if (stxn != NULL) { + ret = __txn_abort(stxn); + stxn = NULL; + } + if (ret != 0) + goto err; + goto reopen; + } + + if (name != NULL && (ret = __fop_lock_handle(env, + dbp, locker, DB_LOCK_WRITE, NULL, NOWAIT_FLAG(txn)| + (F2_ISSET(dbp,DB2_AM_NOWAIT) ? DB_LOCK_NOWAIT : 0))) != 0) + goto err; + if (tmpname != NULL && + tmpname != name && (ret = __fop_rename(env, stxn, tmpname, + name, &dbp->dirname, dbp->fileid, aflags, 1, dflags)) != 0) + goto err; + if ((ret = __ENV_LPUT(env, elock)) != 0) + goto err; + +#ifdef HAVE_TRANSACTIONS + if (stxn != NULL) { + *retidp = stxn->txnid; + ret = __txn_commit(stxn, 0); + stxn = NULL; + } else +#endif + *retidp = TXN_INVALID; + + if (ret != 0) + goto err; + + F_SET(dbp, DB_AM_CREATED); + + if (0) { +errmsg: __db_err(env, ret, "%s", name); + +err: CLOSE_HANDLE(dbp, fhp); + if (stxn != NULL) + (void)__txn_abort(stxn); + if (tmp_created && txn == NULL) + (void)__fop_remove(env, + NULL, NULL, tmpname, NULL, aflags, dflags); + if (txn == NULL) + (void)__ENV_LPUT(env, dbp->handle_lock); + (void)__ENV_LPUT(env, elock); + if (created_locker) { + (void)__lock_id_free(env, dbp->locker); + dbp->locker = NULL; + } + } + +done: /* + * There are cases where real_name and tmpname take on the + * exact same string, so we need to make sure that we do not + * free twice. + */ + if (!truncating && tmpname != NULL && tmpname != name) + __os_free(env, tmpname); + if (real_name != name && real_name != NULL) + __os_free(env, real_name); + if (real_tmpname != NULL) + __os_free(env, real_tmpname); + CLOSE_HANDLE(dbp, fhp); + + return (ret); +} + +/* + * __fop_set_pgsize -- + * Set the page size based on file information. + */ +static int +__fop_set_pgsize(dbp, fhp, name) + DB *dbp; + DB_FH *fhp; + const char *name; +{ + ENV *env; + u_int32_t iopsize; + int ret; + + env = dbp->env; + + /* + * Use the filesystem's optimum I/O size as the pagesize if a pagesize + * not specified. Some filesystems have 64K as their optimum I/O size, + * but as that results in fairly large default caches, we limit the + * default pagesize to 16K. + */ + if ((ret = __os_ioinfo(env, name, fhp, NULL, NULL, &iopsize)) != 0) { + __db_err(env, ret, "%s", name); + return (ret); + } + if (iopsize < 512) + iopsize = 512; + if (iopsize > 16 * 1024) + iopsize = 16 * 1024; + + /* + * Sheer paranoia, but we don't want anything that's not a power-of-2 + * (we rely on that for alignment of various types on the pages), and + * we want a multiple of the sector size as well. If the value + * we got out of __os_ioinfo looks bad, use a default instead. + */ + if (!IS_VALID_PAGESIZE(iopsize)) + iopsize = DB_DEF_IOSIZE; + + dbp->pgsize = iopsize; + F_SET(dbp, DB_AM_PGDEF); + + return (0); +} + +/* + * __fop_remove_setup -- + * Open handle appropriately and lock for removal of a database file. + * + * PUBLIC: int __fop_remove_setup __P((DB *, + * PUBLIC: DB_TXN *, const char *, u_int32_t)); + */ +int +__fop_remove_setup(dbp, txn, name, flags) + DB *dbp; + DB_TXN *txn; + const char *name; + u_int32_t flags; +{ + DB_FH *fhp; + DB_LOCK elock; + ENV *env; + u_int8_t mbuf[DBMETASIZE]; + int ret; + + COMPQUIET(flags, 0); + + env = dbp->env; + + LOCK_INIT(elock); + fhp = NULL; + ret = 0; + + /* Create locker if necessary. */ +retry: if (LOCKING_ON(env)) { + if (IS_REAL_TXN(txn)) + dbp->locker = txn->locker; + else if (dbp->locker == DB_LOCK_INVALIDID) { + if ((ret = __lock_id(env, NULL, &dbp->locker)) != 0) + goto err; + if (txn != NULL && F_ISSET(txn, TXN_INFAMILY) && + (ret = __lock_addfamilylocker(env, + txn->txnid, dbp->locker->id, 1)) != 0) + goto err; + } + } + + /* + * We are about to open a file handle and then possibly close it. + * We cannot close handles if we are doing FCNTL locking. However, + * there is no way to pass the FCNTL flag into this routine via the + * user API. The only way we can get in here and be doing FCNTL + * locking is if we are trying to clean up an open that was called + * with FCNTL locking. In that case, the save_fhp should already be + * set. So, we use that field to tell us if we need to make sure + * that we shouldn't close the handle. + */ + fhp = dbp->saved_open_fhp; + DB_ASSERT(env, LF_ISSET(DB_FCNTL_LOCKING) || fhp == NULL); + + /* + * Lock environment to protect file open. That will enable us to + * read the meta-data page and get the fileid so that we can lock + * the handle. + */ + GET_ENVLOCK(env, dbp->locker, &elock); + + /* Open database. */ + if (F_ISSET(dbp, DB_AM_INMEM)) { + if ((ret = __env_mpool(dbp, name, flags)) == 0) + ret = __os_strdup(env, name, &dbp->dname); + } else if (fhp == NULL) + ret = __os_open(env, name, 0, DB_OSO_RDONLY, 0, &fhp); + if (ret != 0) + goto err; + + /* Get meta-data */ + if (F_ISSET(dbp, DB_AM_INMEM)) + ret = __fop_inmem_read_meta( + dbp, txn, name, flags, DB_CHK_META); + else if ((ret = __fop_read_meta(env, + name, mbuf, sizeof(mbuf), fhp, 0, NULL)) == 0) + ret = __db_meta_setup(env, dbp, + name, (DBMETA *)mbuf, flags, DB_CHK_META | DB_CHK_NOLSN); + if (ret != 0) + goto err; + + /* + * Now, get the handle lock. We first try with NOWAIT, because if + * we have to wait, we're going to have to close the file and reopen + * it, so that if there is someone else removing it, our open doesn't + * prevent that. + */ + if ((ret = __fop_lock_handle(env, + dbp, dbp->locker, DB_LOCK_WRITE, NULL, DB_LOCK_NOWAIT)) != 0) { + /* + * Close the file, block on the lock, clean up the dbp, and + * then start all over again. + */ + if (!F_ISSET(dbp, DB_AM_INMEM) && !LF_ISSET(DB_FCNTL_LOCKING)) { + (void)__os_closehandle(env, fhp); + fhp = NULL; + } + if (ret != DB_LOCK_NOTGRANTED || + (txn != NULL && F_ISSET(txn, TXN_NOWAIT))) + goto err; + else if ((ret = __fop_lock_handle(env, + dbp, dbp->locker, DB_LOCK_WRITE, &elock, 0)) != 0) + goto err; + + if (F_ISSET(dbp, DB_AM_INMEM)) { + (void)__lock_put(env, &dbp->handle_lock); + (void)__db_refresh(dbp, txn, DB_NOSYNC, NULL, 1); + } else { + if (txn != NULL) + dbp->locker = NULL; + (void)__db_refresh(dbp, txn, DB_NOSYNC, NULL, 0); + } + goto retry; + } else if ((ret = __ENV_LPUT(env, elock)) != 0) + goto err; + else if (F_ISSET(dbp, DB_AM_IN_RENAME)) + ret = ENOENT; + + if (0) { +err: (void)__ENV_LPUT(env, elock); + } + if (fhp != NULL && !LF_ISSET(DB_FCNTL_LOCKING)) + (void)__os_closehandle(env, fhp); + /* + * If this is a real file and we are going to proceed with the removal, + * then we need to make sure that we don't leave any pages around in the + * mpool since the file is closed and will be reopened again before + * access. However, this might be an in-memory file, in which case + * we will handle the discard from the mpool later as it's the "real" + * removal of the database. + */ + if (ret == 0 && !F_ISSET(dbp, DB_AM_INMEM)) + F_SET(dbp, DB_AM_DISCARD); + return (ret); +} + +/* + * __fop_read_meta -- + * Read the meta-data page from a file and return it in buf. + * + * PUBLIC: int __fop_read_meta __P((ENV *, const char *, + * PUBLIC: u_int8_t *, size_t, DB_FH *, int, size_t *)); + */ +int +__fop_read_meta(env, name, buf, size, fhp, errok, nbytesp) + ENV *env; + const char *name; + u_int8_t *buf; + size_t size; + DB_FH *fhp; + int errok; + size_t *nbytesp; +{ + size_t nr; + int ret; + + /* + * Our caller wants to know the number of bytes read, even if we + * return an error. + */ + if (nbytesp != NULL) + *nbytesp = 0; + + nr = 0; + ret = __os_read(env, fhp, buf, size, &nr); + if (nbytesp != NULL) + *nbytesp = nr; + + if (ret != 0) { + if (!errok) + __db_err(env, ret, "%s", name); + goto err; + } + + if (nr != size) { + if (!errok) + __db_errx(env, DB_STR_A("0004", + "fop_read_meta: %s: unexpected file type or format", + "%s"), name); + ret = EINVAL; + } + +err: + return (ret); +} + +/* + * __fop_dbrename -- + * Do the appropriate file locking and file system operations + * to effect a dbrename in the absence of transactions (__fop_dummy + * and the subsequent calls in __db_rename do the work for the + * transactional case). + * + * PUBLIC: int __fop_dbrename __P((DB *, const char *, const char *)); + */ +int +__fop_dbrename(dbp, old, new) + DB *dbp; + const char *old, *new; +{ + DB_LOCK elock; + ENV *env; + char *real_new, *real_old; + int ret, t_ret; + + env = dbp->env; + real_new = NULL; + real_old = NULL; + LOCK_INIT(elock); + + if (F_ISSET(dbp, DB_AM_INMEM)) { + real_new = (char *)new; + real_old = (char *)old; + } else { + /* Get full names. */ + if ((ret = __db_appname(env, + DB_APP_DATA, old, &dbp->dirname, &real_old)) != 0) + goto err; + + if ((ret = __db_appname(env, + DB_APP_DATA, new, &dbp->dirname, &real_new)) != 0) + goto err; + } + + /* + * It is an error to rename a file over one that already exists, + * as that wouldn't be transaction-safe. We check explicitly + * for ondisk files, but it's done memp_nameop for in-memory ones. + */ + GET_ENVLOCK(env, dbp->locker, &elock); + ret = F_ISSET(dbp, DB_AM_INMEM) ? ENOENT : + __os_exists(env, real_new, NULL); + + if (ret == 0) { + ret = EEXIST; + __db_errx(env, DB_STR_A("0005", + "rename: file %s exists", "%s"), real_new); + goto err; + } + + ret = __memp_nameop(env, + dbp->fileid, new, real_old, real_new, F_ISSET(dbp, DB_AM_INMEM)); + +err: if ((t_ret = __ENV_LPUT(env, elock)) != 0 && ret == 0) + ret = t_ret; + if (!F_ISSET(dbp, DB_AM_INMEM) && real_old != NULL) + __os_free(env, real_old); + if (!F_ISSET(dbp, DB_AM_INMEM) && real_new != NULL) + __os_free(env, real_new); + return (ret); +} + +static int +__fop_inmem_create(dbp, name, txn, flags) + DB *dbp; + const char *name; + DB_TXN *txn; + u_int32_t flags; +{ + DBT fid_dbt, name_dbt; + DB_LSN lsn; + ENV *env; + int ret; + int32_t lfid; + u_int32_t dflags, *p32; + + env = dbp->env; + dflags = F_ISSET(dbp, DB_AM_NOT_DURABLE) ? DB_LOG_NOT_DURABLE : 0; + + MAKE_INMEM(dbp); + + /* Set the pagesize if it isn't yet set. */ + if (dbp->pgsize == 0) + dbp->pgsize = DB_DEF_IOSIZE; + + /* + * Construct a file_id. + * + * If this file has no name, then we only need a fileid for locking. + * If this file has a name, we need the fileid both for locking and + * matching in the memory pool. So, with unnamed in-memory databases, + * use a lock_id. For named in-memory files, we need to find a value + * that we can use to uniquely identify a name/fid pair. We use a + * combination of a unique id (__os_unique_id) and a hash of the + * original name. + */ + if (name == NULL) { + if (LOCKING_ON(env) && (ret = + __lock_id(env, (u_int32_t *)dbp->fileid, NULL)) != 0) + goto err; + } else { + p32 = (u_int32_t *)(&dbp->fileid[0]); + __os_unique_id(env, p32); + p32++; + (void)strncpy( + (char *)p32, name, DB_FILE_ID_LEN - sizeof(u_int32_t)); + dbp->preserve_fid = 1; + + if (DBENV_LOGGING(env) && +#if !defined(DEBUG_WOP) && !defined(DIAGNOSTIC) + txn != NULL && +#endif + dbp->log_filename != NULL) + memcpy(dbp->log_filename->ufid, + dbp->fileid, DB_FILE_ID_LEN); + } + + /* Now, set the fileid. */ + if ((ret = __memp_set_fileid(dbp->mpf, dbp->fileid)) != 0) + goto err; + + if ((ret = __env_mpool(dbp, name, flags)) != 0) + goto err; + + if (DBENV_LOGGING(env) && +#if !defined(DEBUG_WOP) + txn != NULL && +#endif + name != NULL) { + DB_INIT_DBT(name_dbt, name, strlen(name) + 1); + memset(&fid_dbt, 0, sizeof(fid_dbt)); + fid_dbt.data = dbp->fileid; + fid_dbt.size = DB_FILE_ID_LEN; + lfid = dbp->log_filename == NULL ? + DB_LOGFILEID_INVALID : dbp->log_filename->id; + if ((ret = __crdel_inmem_create_log(env, txn, + &lsn, dflags, lfid, &name_dbt, &fid_dbt, dbp->pgsize)) != 0) + goto err; + } + + F_SET(dbp, DB_AM_CREATED); + +err: + return (ret); +} + +static int +__fop_inmem_read_meta(dbp, txn, name, flags, chkflags) + DB *dbp; + DB_TXN *txn; + const char *name; + u_int32_t flags; + u_int32_t chkflags; +{ + DBMETA *metap; + DB_THREAD_INFO *ip; + db_pgno_t pgno; + int ret, t_ret; + +#ifdef HAVE_TRANSACTIONS + if (txn != NULL) + ip = txn->thread_info; + else +#endif + ENV_GET_THREAD_INFO(dbp->env, ip); + + pgno = PGNO_BASE_MD; + if ((ret = __memp_fget(dbp->mpf, &pgno, ip, txn, 0, &metap)) != 0) + return (ret); + if (FLD_ISSET(chkflags, DB_CHK_ONLY)) { + if ((ret = __db_chk_meta(dbp->env, dbp, metap, chkflags)) == 0) + memcpy(dbp->fileid, + ((DBMETA *)metap)->uid, DB_FILE_ID_LEN); + } else + ret = __db_meta_setup( + dbp->env, dbp, name, metap, flags, chkflags); + + if ((t_ret = + __memp_fput(dbp->mpf, ip, metap, dbp->priority)) && ret == 0) + ret = t_ret; + + return (ret); +} diff -r 000000000000 -r a1985f14b030 src/hash/hash_func.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/hash/hash_func.c Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,262 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 1996, 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +/* + * Copyright (c) 1990, 1993 + * Margo Seltzer. All rights reserved. + */ +/* + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Margo Seltzer. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $Id$ + */ + +#include "db_config.h" + +#include "db_int.h" +#include "dbinc/db_page.h" +#include "dbinc/hash.h" + +/* + * __ham_func2 -- + * Phong Vo's linear congruential hash. + * + * PUBLIC: u_int32_t __ham_func2 __P((DB *, const void *, u_int32_t)); + */ +#define DCHARHASH(h, c) ((h) = 0x63c63cd9*(h) + 0x9c39c33d + (c)) + +u_int32_t +__ham_func2(dbp, key, len) + DB *dbp; + const void *key; + u_int32_t len; +{ + const u_int8_t *e, *k; + u_int32_t h; + u_int8_t c; + + if (dbp != NULL) + COMPQUIET(dbp, NULL); + + k = key; + e = k + len; + for (h = 0; k != e;) { + c = *k++; + if (!c && k > e) + break; + DCHARHASH(h, c); + } + return (h); +} + +/* + * __ham_func3 -- + * Ozan Yigit's original sdbm hash. + * + * Ugly, but fast. Break the string up into 8 byte units. On the first time + * through the loop get the "leftover bytes" (strlen % 8). On every other + * iteration, perform 8 HASHC's so we handle all 8 bytes. Essentially, this + * saves us 7 cmp & branch instructions. + * + * PUBLIC: u_int32_t __ham_func3 __P((DB *, const void *, u_int32_t)); + */ +u_int32_t +__ham_func3(dbp, key, len) + DB *dbp; + const void *key; + u_int32_t len; +{ + const u_int8_t *k; + u_int32_t n, loop; + + if (dbp != NULL) + COMPQUIET(dbp, NULL); + + if (len == 0) + return (0); + +#define HASHC n = *k++ + 65599 * n + n = 0; + k = key; + + loop = (len + 8 - 1) >> 3; + switch (len & (8 - 1)) { + case 0: + do { + HASHC; + case 7: + HASHC; + case 6: + HASHC; + case 5: + HASHC; + case 4: + HASHC; + case 3: + HASHC; + case 2: + HASHC; + case 1: + HASHC; + } while (--loop); + } + return (n); +} + +/* + * __ham_func4 -- + * Chris Torek's hash function. Although this function performs only + * slightly worse than __ham_func5 on strings, it performs horribly on + * numbers. + * + * PUBLIC: u_int32_t __ham_func4 __P((DB *, const void *, u_int32_t)); + */ +u_int32_t +__ham_func4(dbp, key, len) + DB *dbp; + const void *key; + u_int32_t len; +{ + const u_int8_t *k; + u_int32_t h, loop; + + if (dbp != NULL) + COMPQUIET(dbp, NULL); + + if (len == 0) + return (0); + +#define HASH4a h = (h << 5) - h + *k++; +#define HASH4b h = (h << 5) + h + *k++; +#define HASH4 HASH4b + h = 0; + k = key; + + loop = (len + 8 - 1) >> 3; + switch (len & (8 - 1)) { + case 0: + do { + HASH4; + case 7: + HASH4; + case 6: + HASH4; + case 5: + HASH4; + case 4: + HASH4; + case 3: + HASH4; + case 2: + HASH4; + case 1: + HASH4; + } while (--loop); + } + return (h); +} + +/* + * Fowler/Noll/Vo hash + * + * The basis of the hash algorithm was taken from an idea sent by email to the + * IEEE Posix P1003.2 mailing list from Phong Vo (kpv@research.att.com) and + * Glenn Fowler (gsf@research.att.com). Landon Curt Noll (chongo@toad.com) + * later improved on their algorithm. + * + * The magic is in the interesting relationship between the special prime + * 16777619 (2^24 + 403) and 2^32 and 2^8. + * + * This hash produces the fewest collisions of any function that we've seen so + * far, and works well on both numbers and strings. + * + * PUBLIC: u_int32_t __ham_func5 __P((DB *, const void *, u_int32_t)); + */ +u_int32_t +__ham_func5(dbp, key, len) + DB *dbp; + const void *key; + u_int32_t len; +{ + const u_int8_t *k, *e; + u_int32_t h; + + if (dbp != NULL) + COMPQUIET(dbp, NULL); + + k = key; + e = k + len; + for (h = 0; k < e; ++k) { + h *= 16777619; + h ^= *k; + } + return (h); +} + +/* + * __ham_test -- + * + * PUBLIC: u_int32_t __ham_test __P((DB *, const void *, u_int32_t)); + */ +u_int32_t +__ham_test(dbp, key, len) + DB *dbp; + const void *key; + u_int32_t len; +{ + COMPQUIET(dbp, NULL); + COMPQUIET(len, 0); + return ((u_int32_t)*(char *)key); +} diff -r 000000000000 -r a1985f14b030 src/hash/hash_stub.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/hash/hash_stub.c Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,492 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 1996, 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + * $Id$ + */ + +#ifndef HAVE_HASH +#include "db_config.h" + +#include "db_int.h" +#include "dbinc/db_page.h" +#include "dbinc/hash.h" + +/* + * If the library wasn't compiled with the Hash access method, various + * routines aren't available. Stub them here, returning an appropriate + * error. + */ + +/* + * __db_nohasham -- + * Error when a Berkeley DB build doesn't include the access method. + * + * PUBLIC: int __db_no_hash_am __P((ENV *)); + */ +int +__db_no_hash_am(env) + ENV *env; +{ + __db_errx(env, DB_STR("1133", + "library build did not include support for the Hash access method")); + return (DB_OPNOTSUP); +} + +int +__ham_30_hashmeta(dbp, real_name, obuf) + DB *dbp; + char *real_name; + u_int8_t *obuf; +{ + COMPQUIET(real_name, NULL); + COMPQUIET(obuf, NULL); + return (__db_no_hash_am(dbp->env)); +} + +int +__ham_30_sizefix(dbp, fhp, realname, metabuf) + DB *dbp; + DB_FH *fhp; + char *realname; + u_int8_t *metabuf; +{ + COMPQUIET(fhp, NULL); + COMPQUIET(realname, NULL); + COMPQUIET(metabuf, NULL); + return (__db_no_hash_am(dbp->env)); +} + +int +__ham_31_hash(dbp, real_name, flags, fhp, h, dirtyp) + DB *dbp; + char *real_name; + u_int32_t flags; + DB_FH *fhp; + PAGE *h; + int *dirtyp; +{ + COMPQUIET(real_name, NULL); + COMPQUIET(flags, 0); + COMPQUIET(fhp, NULL); + COMPQUIET(h, NULL); + COMPQUIET(dirtyp, NULL); + return (__db_no_hash_am(dbp->env)); +} + +int +__ham_31_hashmeta(dbp, real_name, flags, fhp, h, dirtyp) + DB *dbp; + char *real_name; + u_int32_t flags; + DB_FH *fhp; + PAGE *h; + int *dirtyp; +{ + COMPQUIET(real_name, NULL); + COMPQUIET(flags, 0); + COMPQUIET(fhp, NULL); + COMPQUIET(h, NULL); + COMPQUIET(dirtyp, NULL); + return (__db_no_hash_am(dbp->env)); +} + +int +__ham_46_hash(dbp, real_name, flags, fhp, h, dirtyp) + DB *dbp; + char *real_name; + u_int32_t flags; + DB_FH *fhp; + PAGE *h; + int *dirtyp; +{ + COMPQUIET(real_name, NULL); + COMPQUIET(flags, 0); + COMPQUIET(fhp, NULL); + COMPQUIET(h, NULL); + COMPQUIET(dirtyp, NULL); + return (__db_no_hash_am(dbp->env)); +} + +int +__ham_46_hashmeta(dbp, real_name, flags, fhp, h, dirtyp) + DB *dbp; + char *real_name; + u_int32_t flags; + DB_FH *fhp; + PAGE *h; + int *dirtyp; +{ + COMPQUIET(real_name, NULL); + COMPQUIET(flags, 0); + COMPQUIET(fhp, NULL); + COMPQUIET(h, NULL); + COMPQUIET(dirtyp, NULL); + return (__db_no_hash_am(dbp->env)); +} + +int +__hamc_cmp(dbc, other_dbc, result) + DBC *dbc, *other_dbc; + int *result; +{ + COMPQUIET(other_dbc, NULL); + COMPQUIET(result, NULL); + return (__db_no_hash_am(dbc->env)); +} + +int +__hamc_count(dbc, recnop) + DBC *dbc; + db_recno_t *recnop; +{ + COMPQUIET(recnop, NULL); + return (__db_no_hash_am(dbc->env)); +} + +int +__hamc_dup(orig_dbc, new_dbc) + DBC *orig_dbc, *new_dbc; +{ + COMPQUIET(new_dbc, NULL); + return (__db_no_hash_am(orig_dbc->env)); +} + +int +__hamc_init(dbc) + DBC *dbc; +{ + return (__db_no_hash_am(dbc->env)); +} + +int +__ham_db_close(dbp) + DB *dbp; +{ + COMPQUIET(dbp, NULL); + return (0); +} + +int +__ham_db_create(dbp) + DB *dbp; +{ + COMPQUIET(dbp, NULL); + return (0); +} + +int +__ham_init_print(env, dtabp) + ENV *env; + DB_DISTAB *dtabp; +{ + COMPQUIET(env, NULL); + COMPQUIET(dtabp, NULL); + return (0); +} + +int +__ham_init_recover(env, dtabp) + ENV *env; + DB_DISTAB *dtabp; +{ + COMPQUIET(env, NULL); + COMPQUIET(dtabp, NULL); + return (0); +} + +int +__ham_meta2pgset(dbp, vdp, hmeta, flags, pgset) + DB *dbp; + VRFY_DBINFO *vdp; + HMETA *hmeta; + u_int32_t flags; + DB *pgset; +{ + COMPQUIET(vdp, NULL); + COMPQUIET(hmeta, NULL); + COMPQUIET(flags, 0); + COMPQUIET(pgset, NULL); + return (__db_no_hash_am(dbp->env)); +} + +int +__ham_metachk(dbp, name, hashm) + DB *dbp; + const char *name; + HMETA *hashm; +{ + COMPQUIET(name, NULL); + COMPQUIET(hashm, NULL); + return (__db_no_hash_am(dbp->env)); +} + +int +__ham_metagroup_42_recover(env, dbtp, lsnp, op, info) + ENV *env; + DBT *dbtp; + DB_LSN *lsnp; + db_recops op; + void *info; +{ + COMPQUIET(dbtp, NULL); + COMPQUIET(lsnp, NULL); + COMPQUIET(op, (db_recops)0); + COMPQUIET(info, NULL); + return (__db_no_hash_am(env)); +} + +int +__ham_mswap(env, pg) + ENV *env; + void *pg; +{ + COMPQUIET(pg, NULL); + return (__db_no_hash_am(env)); +} + +int +__ham_groupalloc_42_recover(env, dbtp, lsnp, op, info) + ENV *env; + DBT *dbtp; + DB_LSN *lsnp; + db_recops op; + void *info; +{ + COMPQUIET(dbtp, NULL); + COMPQUIET(lsnp, NULL); + COMPQUIET(op, (db_recops)0); + COMPQUIET(info, NULL); + return (__db_no_hash_am(env)); +} + +int +__ham_new_file(dbp, ip, txn, fhp, name) + DB *dbp; + DB_THREAD_INFO *ip; + DB_TXN *txn; + DB_FH *fhp; + const char *name; +{ + COMPQUIET(ip, NULL); + COMPQUIET(txn, NULL); + COMPQUIET(fhp, NULL); + COMPQUIET(name, NULL); + return (__db_no_hash_am(dbp->env)); +} + +int +__ham_new_subdb(mdbp, dbp, ip, txn) + DB *mdbp, *dbp; + DB_THREAD_INFO *ip; + DB_TXN *txn; +{ + COMPQUIET(dbp, NULL); + COMPQUIET(txn, NULL); + COMPQUIET(ip, NULL); + return (__db_no_hash_am(mdbp->env)); +} + +int +__ham_open(dbp, ip, txn, name, base_pgno, flags) + DB *dbp; + DB_THREAD_INFO *ip; + DB_TXN *txn; + const char *name; + db_pgno_t base_pgno; + u_int32_t flags; +{ + COMPQUIET(ip, NULL); + COMPQUIET(txn, NULL); + COMPQUIET(name, NULL); + COMPQUIET(base_pgno, 0); + COMPQUIET(flags, 0); + return (__db_no_hash_am(dbp->env)); +} + +int +__ham_pgin(dbp, pg, pp, cookie) + DB *dbp; + db_pgno_t pg; + void *pp; + DBT *cookie; +{ + COMPQUIET(pg, 0); + COMPQUIET(pp, NULL); + COMPQUIET(cookie, NULL); + return (__db_no_hash_am(dbp->env)); +} + +int +__ham_pgout(dbp, pg, pp, cookie) + DB *dbp; + db_pgno_t pg; + void *pp; + DBT *cookie; +{ + COMPQUIET(pg, 0); + COMPQUIET(pp, NULL); + COMPQUIET(cookie, NULL); + return (__db_no_hash_am(dbp->env)); +} + +void +__ham_print_cursor(dbc) + DBC *dbc; +{ + (void)__db_no_hash_am(dbc->env); +} + +int +__ham_quick_delete(dbc) + DBC *dbc; +{ + return (__db_no_hash_am(dbc->env)); +} + +int +__ham_reclaim(dbp, ip, txn, flags) + DB *dbp; + DB_THREAD_INFO *ip; + DB_TXN *txn; + u_int32_t flags; +{ + COMPQUIET(txn, NULL); + COMPQUIET(ip, NULL); + COMPQUIET(flags, 0); + return (__db_no_hash_am(dbp->env)); +} + +int +__ham_salvage(dbp, vdp, pgno, h, handle, callback, flags) + DB *dbp; + VRFY_DBINFO *vdp; + db_pgno_t pgno; + PAGE *h; + void *handle; + int (*callback) __P((void *, const void *)); + u_int32_t flags; +{ + COMPQUIET(vdp, NULL); + COMPQUIET(pgno, 0); + COMPQUIET(h, NULL); + COMPQUIET(handle, NULL); + COMPQUIET(callback, NULL); + COMPQUIET(flags, 0); + return (__db_no_hash_am(dbp->env)); +} + +int +__ham_stat(dbc, spp, flags) + DBC *dbc; + void *spp; + u_int32_t flags; +{ + COMPQUIET(spp, NULL); + COMPQUIET(flags, 0); + return (__db_no_hash_am(dbc->env)); +} + +int +__ham_stat_print(dbc, flags) + DBC *dbc; + u_int32_t flags; +{ + COMPQUIET(flags, 0); + return (__db_no_hash_am(dbc->env)); +} + +int +__ham_truncate(dbc, countp) + DBC *dbc; + u_int32_t *countp; +{ + COMPQUIET(countp, NULL); + return (__db_no_hash_am(dbc->env)); +} + +int +__ham_vrfy(dbp, vdp, h, pgno, flags) + DB *dbp; + VRFY_DBINFO *vdp; + PAGE *h; + db_pgno_t pgno; + u_int32_t flags; +{ + COMPQUIET(vdp, NULL); + COMPQUIET(h, NULL); + COMPQUIET(pgno, 0); + COMPQUIET(flags, 0); + return (__db_no_hash_am(dbp->env)); +} + +int +__ham_vrfy_hashing(dbc, nentries, m, thisbucket, pgno, flags, hfunc) + DBC *dbc; + u_int32_t nentries; + HMETA *m; + u_int32_t thisbucket; + db_pgno_t pgno; + u_int32_t flags; + u_int32_t (*hfunc) __P((DB *, const void *, u_int32_t)); +{ + COMPQUIET(nentries, 0); + COMPQUIET(m, NULL); + COMPQUIET(thisbucket, 0); + COMPQUIET(pgno, 0); + COMPQUIET(flags, 0); + COMPQUIET(hfunc, NULL); + return (__db_no_hash_am(dbc->dbp->env)); +} + +int +__ham_vrfy_meta(dbp, vdp, m, pgno, flags) + DB *dbp; + VRFY_DBINFO *vdp; + HMETA *m; + db_pgno_t pgno; + u_int32_t flags; +{ + COMPQUIET(vdp, NULL); + COMPQUIET(m, NULL); + COMPQUIET(pgno, 0); + COMPQUIET(flags, 0); + return (__db_no_hash_am(dbp->env)); +} + +int +__ham_vrfy_structure(dbp, vdp, meta_pgno, flags) + DB *dbp; + VRFY_DBINFO *vdp; + db_pgno_t meta_pgno; + u_int32_t flags; +{ + COMPQUIET(vdp, NULL); + COMPQUIET(meta_pgno, 0); + COMPQUIET(flags, 0); + return (__db_no_hash_am(dbp->env)); +} +#endif /* !HAVE_HASH */ diff -r 000000000000 -r a1985f14b030 src/heap/heap_stub.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/heap/heap_stub.c Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,350 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 2010, 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + * $Id: + */ + +#ifndef HAVE_HEAP +#include "db_config.h" + +#include "db_int.h" +#include "dbinc/db_page.h" +#include "dbinc/heap.h" + +/* + * If the library wasn't compiled with the Heap access method, various + * routines aren't available. Stub them here, returning an appropriate + * error. + */ + +/* + * __db_no_heap_am -- + * Error when a Berkeley DB build doesn't include the access method. + * + * PUBLIC: int __db_no_heap_am __P((ENV *)); + */ +int +__db_no_heap_am(env) + ENV *env; +{ + __db_errx(env, + "library build did not include support for the Heap access method"); + return (DB_OPNOTSUP); +} + +int +__heap_db_create(dbp) + DB *dbp; +{ + COMPQUIET(dbp, NULL); + return (0); +} + +int +__heap_db_close(dbp) + DB *dbp; +{ + COMPQUIET(dbp, NULL); + return (0); +} + +int +__heap_get_heapsize(dbp, gbytes, bytes) + DB *dbp; + u_int32_t *gbytes, *bytes; +{ + COMPQUIET(gbytes, NULL); + COMPQUIET(bytes, NULL); + return (__db_no_heap_am(dbp->env)); +} + +int +__heapc_dup(orig_dbc, new_dbc) + DBC *orig_dbc, *new_dbc; +{ + COMPQUIET(new_dbc, NULL); + return (__db_no_heap_am(orig_dbc->env)); +} + +int +__heapc_gsplit(dbc, dbt, bpp, bpsz) + DBC *dbc; + DBT *dbt; + void **bpp; + u_int32_t *bpsz; +{ + COMPQUIET(dbt, NULL); + COMPQUIET(bpp, NULL); + COMPQUIET(bpsz, NULL); + return (__db_no_heap_am(dbc->env)); +} + +int +__heap_append(dbc, key, data) + DBC *dbc; + DBT *key, *data; +{ + COMPQUIET(key, NULL); + COMPQUIET(data, NULL); + return (__db_no_heap_am(dbc->env)); +} + +int +__heap_backup(dbenv, dbp, ip, fp, handle, flags) + DB_ENV *dbenv; + DB *dbp; + DB_THREAD_INFO *ip; + DB_FH *fp; + void *handle; + u_int32_t flags; +{ + COMPQUIET(dbp, NULL); + COMPQUIET(ip, NULL); + COMPQUIET(fp, NULL); + COMPQUIET(handle, NULL); + COMPQUIET(flags, 0); + return (__db_no_heap_am(dbenv->env)); +} + +int +__heapc_init(dbc) + DBC *dbc; +{ + return (__db_no_heap_am(dbc->env)); +} + +int +__heap_init_print(env, dtabp) + ENV *env; + DB_DISTAB *dtabp; +{ + COMPQUIET(env, NULL); + COMPQUIET(dtabp, NULL); + return (0); +} + +int +__heap_init_recover(env, dtabp) + ENV *env; + DB_DISTAB *dtabp; +{ + COMPQUIET(env, NULL); + COMPQUIET(dtabp, NULL); + return (0); +} + +int +__heap_meta2pgset(dbp, vdp, heapmeta, pgset) + DB *dbp; + VRFY_DBINFO *vdp; + HEAPMETA *heapmeta; + DB *pgset; +{ + COMPQUIET(vdp, NULL); + COMPQUIET(heapmeta, NULL); + COMPQUIET(pgset, NULL); + return (__db_no_heap_am(dbp->env)); +} + +int +__heap_metachk(dbp, name, hm) + DB *dbp; + const char *name; + HEAPMETA *hm; +{ + COMPQUIET(name, NULL); + COMPQUIET(hm, NULL); + return (__db_no_heap_am(dbp->env)); +} + +int +__heap_new_file(dbp, ip, txn, fhp, name) + DB *dbp; + DB_THREAD_INFO *ip; + DB_TXN *txn; + DB_FH *fhp; + const char *name; +{ + COMPQUIET(ip, NULL); + COMPQUIET(txn, NULL); + COMPQUIET(fhp, NULL); + COMPQUIET(name, NULL); + return (__db_no_heap_am(dbp->env)); +} + +int +__heap_open(dbp, ip, txn, name, base_pgno, flags) + DB *dbp; + DB_THREAD_INFO *ip; + DB_TXN *txn; + const char *name; + db_pgno_t base_pgno; + u_int32_t flags; +{ + COMPQUIET(ip, NULL); + COMPQUIET(txn, NULL); + COMPQUIET(name, NULL); + COMPQUIET(base_pgno, 0); + COMPQUIET(flags, 0); + return (__db_no_heap_am(dbp->env)); +} + +int +__heap_pgin(dbp, pg, pp, cookie) + DB *dbp; + db_pgno_t pg; + void *pp; + DBT *cookie; +{ + COMPQUIET(pg, 0); + COMPQUIET(pp, NULL); + COMPQUIET(cookie, NULL); + return (__db_no_heap_am(dbp->env)); +} + +int +__heap_pgout(dbp, pg, pp, cookie) + DB *dbp; + db_pgno_t pg; + void *pp; + DBT *cookie; +{ + COMPQUIET(pg, 0); + COMPQUIET(pp, NULL); + COMPQUIET(cookie, NULL); + return (__db_no_heap_am(dbp->env)); +} + +void +__heap_print_cursor(dbc) + DBC *dbc; +{ + (void)__db_no_heap_am(dbc->env); +} + +int +__heapc_refresh(dbc) + DBC *dbc; +{ + return (__db_no_heap_am(dbc->env)); +} + +int +__heap_salvage(dbp, vdp, pgno, h, handle, callback, flags) + DB *dbp; + VRFY_DBINFO *vdp; + db_pgno_t pgno; + PAGE *h; + void *handle; + int (*callback) __P((void *, const void *)); + u_int32_t flags; +{ + COMPQUIET(vdp, NULL); + COMPQUIET(pgno, 0); + COMPQUIET(handle, NULL); + COMPQUIET(h, NULL); + COMPQUIET(callback, NULL); + COMPQUIET(flags, 0); + return (__db_no_heap_am(dbp->env)); +} + +int +__heap_stat(dbc, spp, flags) + DBC *dbc; + void *spp; + u_int32_t flags; +{ + COMPQUIET(spp, NULL); + COMPQUIET(flags, 0); + return (__db_no_heap_am(dbc->env)); +} + +int +__heap_stat_print(dbc, flags) + DBC *dbc; + u_int32_t flags; +{ + COMPQUIET(flags, 0); + return (__db_no_heap_am(dbc->env)); +} + +int +__heap_truncate(dbc, countp) + DBC *dbc; + u_int32_t *countp; +{ + COMPQUIET(countp, NULL); + return (__db_no_heap_am(dbc->env)); +} + +int +__heap_vrfy(dbp, vdbp, h, pgno, flags) + DB *dbp; + VRFY_DBINFO *vdbp; + PAGE *h; + db_pgno_t pgno; + u_int32_t flags; +{ + COMPQUIET(h, NULL); + COMPQUIET(vdbp, NULL); + COMPQUIET(pgno, 0); + COMPQUIET(flags, 0); + return (__db_no_heap_am(dbp->env)); +} + +int +__heap_vrfy_meta(dbp, vdp, meta, pgno, flags) + DB *dbp; + VRFY_DBINFO *vdp; + HEAPMETA *meta; + db_pgno_t pgno; + u_int32_t flags; +{ + COMPQUIET(vdp, NULL); + COMPQUIET(meta, NULL); + COMPQUIET(pgno, 0); + COMPQUIET(flags, 0); + return (__db_no_heap_am(dbp->env)); +} + +int +__heap_vrfy_structure(dbp, vdp, flags) + DB *dbp; + VRFY_DBINFO *vdp; + u_int32_t flags; +{ + COMPQUIET(vdp, NULL); + COMPQUIET(flags, 0); + return (__db_no_heap_am(dbp->env)); +} + +int +__heap_exist() +{ + return (0); +} +#endif /* !HAVE_HEAP */ diff -r 000000000000 -r a1985f14b030 src/lock/lock_stub.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/lock/lock_stub.c Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,688 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 1996, 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + * $Id$ + */ + +#include "db_config.h" + +#include "db_int.h" +#include "dbinc/db_page.h" +#include "dbinc/lock.h" + +/* + * If the library wasn't compiled with locking support, various routines + * aren't available. Stub them here, returning an appropriate error. + */ +static int __db_nolocking __P((ENV *)); + +/* + * __db_nolocking -- + * Error when a Berkeley DB build doesn't include the locking subsystem. + */ +static int +__db_nolocking(env) + ENV *env; +{ + __db_errx(env, DB_STR("2054", + "library build did not include support for locking")); + return (DB_OPNOTSUP); +} + +int +__lock_env_create(dbenv) + DB_ENV *dbenv; +{ + COMPQUIET(dbenv, 0); + return (0); +} + +void +__lock_env_destroy(dbenv) + DB_ENV *dbenv; +{ + COMPQUIET(dbenv, 0); +} + +int +__lock_get_lk_conflicts(dbenv, lk_conflictsp, lk_modesp) + DB_ENV *dbenv; + const u_int8_t **lk_conflictsp; + int *lk_modesp; +{ + COMPQUIET(lk_conflictsp, NULL); + COMPQUIET(lk_modesp, NULL); + return (__db_nolocking(dbenv->env)); +} + +int +__lock_get_lk_detect(dbenv, lk_detectp) + DB_ENV *dbenv; + u_int32_t *lk_detectp; +{ + COMPQUIET(lk_detectp, NULL); + return (__db_nolocking(dbenv->env)); +} + +int +__lock_get_lk_init_lockers(dbenv, lk_initp) + DB_ENV *dbenv; + u_int32_t *lk_initp; +{ + COMPQUIET(lk_initp, NULL); + return (__db_nolocking(dbenv->env)); +} + +int +__lock_get_lk_init_locks(dbenv, lk_initp) + DB_ENV *dbenv; + u_int32_t *lk_initp; +{ + COMPQUIET(lk_initp, NULL); + return (__db_nolocking(dbenv->env)); +} + +int +__lock_get_lk_init_objects(dbenv, lk_initp) + DB_ENV *dbenv; + u_int32_t *lk_initp; +{ + COMPQUIET(lk_initp, NULL); + return (__db_nolocking(dbenv->env)); +} + +int +__lock_get_lk_max_lockers(dbenv, lk_maxp) + DB_ENV *dbenv; + u_int32_t *lk_maxp; +{ + COMPQUIET(lk_maxp, NULL); + return (__db_nolocking(dbenv->env)); +} + +int +__lock_get_lk_max_locks(dbenv, lk_maxp) + DB_ENV *dbenv; + u_int32_t *lk_maxp; +{ + COMPQUIET(lk_maxp, NULL); + return (__db_nolocking(dbenv->env)); +} + +int +__lock_get_lk_max_objects(dbenv, lk_maxp) + DB_ENV *dbenv; + u_int32_t *lk_maxp; +{ + COMPQUIET(lk_maxp, NULL); + return (__db_nolocking(dbenv->env)); +} + +int +__lock_get_lk_partitions(dbenv, lk_maxp) + DB_ENV *dbenv; + u_int32_t *lk_maxp; +{ + COMPQUIET(lk_maxp, NULL); + return (__db_nolocking(dbenv->env)); +} + +int +__lock_get_lk_tablesize(dbenv, lk_tablesizep) + DB_ENV *dbenv; + u_int32_t *lk_tablesizep; +{ + COMPQUIET(lk_tablesizep, NULL); + return (__db_nolocking(dbenv->env)); +} + +int +__lock_set_lk_tablesize(dbenv, lk_tablesize) + DB_ENV *dbenv; + u_int32_t lk_tablesize; +{ + COMPQUIET(lk_tablesize, 0); + return (__db_nolocking(dbenv->env)); +} + +int +__lock_get_lk_priority(dbenv, lockid, priorityp) + DB_ENV *dbenv; + u_int32_t lockid, *priorityp; +{ + COMPQUIET(lockid, 0); + COMPQUIET(priorityp, NULL); + return (__db_nolocking(dbenv->env)); +} + +int +__lock_set_lk_priority(dbenv, lockid, priority) + DB_ENV *dbenv; + u_int32_t lockid, priority; +{ + COMPQUIET(lockid, 0); + COMPQUIET(priority, 0); + return (__db_nolocking(dbenv->env)); +} + +int +__lock_get_env_timeout(dbenv, timeoutp, flag) + DB_ENV *dbenv; + db_timeout_t *timeoutp; + u_int32_t flag; +{ + COMPQUIET(timeoutp, NULL); + COMPQUIET(flag, 0); + return (__db_nolocking(dbenv->env)); +} + +int +__lock_detect_pp(dbenv, flags, atype, abortp) + DB_ENV *dbenv; + u_int32_t flags, atype; + int *abortp; +{ + COMPQUIET(flags, 0); + COMPQUIET(atype, 0); + COMPQUIET(abortp, NULL); + return (__db_nolocking(dbenv->env)); +} + +int +__lock_get_pp(dbenv, locker, flags, obj, lock_mode, lock) + DB_ENV *dbenv; + u_int32_t locker, flags; + DBT *obj; + db_lockmode_t lock_mode; + DB_LOCK *lock; +{ + COMPQUIET(locker, 0); + COMPQUIET(flags, 0); + COMPQUIET(obj, NULL); + COMPQUIET(lock_mode, 0); + COMPQUIET(lock, NULL); + return (__db_nolocking(dbenv->env)); +} + +int +__lock_id_pp(dbenv, idp) + DB_ENV *dbenv; + u_int32_t *idp; +{ + COMPQUIET(idp, NULL); + return (__db_nolocking(dbenv->env)); +} + +int +__lock_id_free_pp(dbenv, id) + DB_ENV *dbenv; + u_int32_t id; +{ + COMPQUIET(id, 0); + return (__db_nolocking(dbenv->env)); +} + +int +__lock_put_pp(dbenv, lock) + DB_ENV *dbenv; + DB_LOCK *lock; +{ + COMPQUIET(lock, NULL); + return (__db_nolocking(dbenv->env)); +} + +int +__lock_stat_pp(dbenv, statp, flags) + DB_ENV *dbenv; + DB_LOCK_STAT **statp; + u_int32_t flags; +{ + COMPQUIET(statp, NULL); + COMPQUIET(flags, 0); + return (__db_nolocking(dbenv->env)); +} + +int +__lock_stat_print_pp(dbenv, flags) + DB_ENV *dbenv; + u_int32_t flags; +{ + COMPQUIET(flags, 0); + return (__db_nolocking(dbenv->env)); +} + +int +__lock_vec_pp(dbenv, locker, flags, list, nlist, elistp) + DB_ENV *dbenv; + u_int32_t locker, flags; + int nlist; + DB_LOCKREQ *list, **elistp; +{ + COMPQUIET(locker, 0); + COMPQUIET(flags, 0); + COMPQUIET(list, NULL); + COMPQUIET(nlist, 0); + COMPQUIET(elistp, NULL); + return (__db_nolocking(dbenv->env)); +} + +int +__lock_set_lk_conflicts(dbenv, lk_conflicts, lk_modes) + DB_ENV *dbenv; + u_int8_t *lk_conflicts; + int lk_modes; +{ + COMPQUIET(lk_conflicts, NULL); + COMPQUIET(lk_modes, 0); + return (__db_nolocking(dbenv->env)); +} + +int +__lock_set_lk_detect(dbenv, lk_detect) + DB_ENV *dbenv; + u_int32_t lk_detect; +{ + COMPQUIET(lk_detect, 0); + return (__db_nolocking(dbenv->env)); +} + +int +__lock_set_lk_max_locks(dbenv, lk_max) + DB_ENV *dbenv; + u_int32_t lk_max; +{ + COMPQUIET(lk_max, 0); + return (__db_nolocking(dbenv->env)); +} + +int +__lock_set_lk_max_lockers(dbenv, lk_max) + DB_ENV *dbenv; + u_int32_t lk_max; +{ + COMPQUIET(lk_max, 0); + return (__db_nolocking(dbenv->env)); +} + +int +__lock_set_lk_max_objects(dbenv, lk_max) + DB_ENV *dbenv; + u_int32_t lk_max; +{ + COMPQUIET(lk_max, 0); + return (__db_nolocking(dbenv->env)); +} + +int +__lock_set_lk_partitions(dbenv, lk_max) + DB_ENV *dbenv; + u_int32_t lk_max; +{ + COMPQUIET(lk_max, 0); + return (__db_nolocking(dbenv->env)); +} + +int +__lock_set_env_timeout(dbenv, timeout, flags) + DB_ENV *dbenv; + db_timeout_t timeout; + u_int32_t flags; +{ + COMPQUIET(timeout, 0); + COMPQUIET(flags, 0); + return (__db_nolocking(dbenv->env)); +} + +int +__lock_open(env) + ENV *env; +{ + return (__db_nolocking(env)); +} + +u_int32_t +__lock_region_mutex_count(env) + ENV *env; +{ + COMPQUIET(env, NULL); + return (0); +} + +u_int32_t +__lock_region_mutex_max(env) + ENV *env; +{ + COMPQUIET(env, NULL); + return (0); +} + +size_t +__lock_region_max(env) + ENV *env; +{ + COMPQUIET(env, NULL); + return (0); +} + +size_t +__lock_region_size(env, other_alloc) + ENV *env; + size_t other_alloc; +{ + COMPQUIET(env, NULL); + COMPQUIET(other_alloc, 0); + return (0); +} + +int +__lock_id_free(env, sh_locker) + ENV *env; + DB_LOCKER *sh_locker; +{ + COMPQUIET(env, NULL); + COMPQUIET(sh_locker, 0); + return (0); +} + +int +__lock_env_refresh(env) + ENV *env; +{ + COMPQUIET(env, NULL); + return (0); +} + +int +__lock_stat_print(env, flags) + ENV *env; + u_int32_t flags; +{ + COMPQUIET(env, NULL); + COMPQUIET(flags, 0); + return (0); +} + +int +__lock_put(env, lock) + ENV *env; + DB_LOCK *lock; +{ + COMPQUIET(env, NULL); + COMPQUIET(lock, NULL); + return (0); +} + +int +__lock_vec(env, sh_locker, flags, list, nlist, elistp) + ENV *env; + DB_LOCKER *sh_locker; + u_int32_t flags; + int nlist; + DB_LOCKREQ *list, **elistp; +{ + COMPQUIET(env, NULL); + COMPQUIET(sh_locker, 0); + COMPQUIET(flags, 0); + COMPQUIET(list, NULL); + COMPQUIET(nlist, 0); + COMPQUIET(elistp, NULL); + return (0); +} + +int +__lock_get(env, locker, flags, obj, lock_mode, lock) + ENV *env; + DB_LOCKER *locker; + u_int32_t flags; + const DBT *obj; + db_lockmode_t lock_mode; + DB_LOCK *lock; +{ + COMPQUIET(env, NULL); + COMPQUIET(locker, NULL); + COMPQUIET(flags, 0); + COMPQUIET(obj, NULL); + COMPQUIET(lock_mode, 0); + COMPQUIET(lock, NULL); + return (0); +} + +int +__lock_id(env, idp, lkp) + ENV *env; + u_int32_t *idp; + DB_LOCKER **lkp; +{ + COMPQUIET(env, NULL); + COMPQUIET(idp, NULL); + COMPQUIET(lkp, NULL); + return (0); +} + +int +__lock_inherit_timeout(env, parent, locker) + ENV *env; + DB_LOCKER *parent, *locker; +{ + COMPQUIET(env, NULL); + COMPQUIET(parent, NULL); + COMPQUIET(locker, NULL); + return (0); +} + +int +__lock_set_timeout(env, locker, timeout, op) + ENV *env; + DB_LOCKER *locker; + db_timeout_t timeout; + u_int32_t op; +{ + COMPQUIET(env, NULL); + COMPQUIET(locker, NULL); + COMPQUIET(timeout, 0); + COMPQUIET(op, 0); + return (0); +} + +int +__lock_addfamilylocker(env, pid, id, is_family) + ENV *env; + u_int32_t pid, id, is_family; +{ + COMPQUIET(env, NULL); + COMPQUIET(pid, 0); + COMPQUIET(id, 0); + COMPQUIET(is_family, 0); + return (0); +} + +int +__lock_freelocker(lt, sh_locker) + DB_LOCKTAB *lt; + DB_LOCKER *sh_locker; +{ + COMPQUIET(lt, NULL); + COMPQUIET(sh_locker, NULL); + return (0); +} + +int +__lock_familyremove(lt, sh_locker) + DB_LOCKTAB *lt; + DB_LOCKER *sh_locker; +{ + COMPQUIET(lt, NULL); + COMPQUIET(sh_locker, NULL); + return (0); +} + +int +__lock_downgrade(env, lock, new_mode, flags) + ENV *env; + DB_LOCK *lock; + db_lockmode_t new_mode; + u_int32_t flags; +{ + COMPQUIET(env, NULL); + COMPQUIET(lock, NULL); + COMPQUIET(new_mode, 0); + COMPQUIET(flags, 0); + return (0); +} + +int +__lock_locker_same_family(env, locker1, locker2, retp) + ENV *env; + DB_LOCKER *locker1; + DB_LOCKER *locker2; + int *retp; +{ + COMPQUIET(env, NULL); + COMPQUIET(locker1, NULL); + COMPQUIET(locker2, NULL); + + *retp = 1; + return (0); +} + +void +__lock_set_thread_id(lref, pid, tid) + void *lref; + pid_t pid; + db_threadid_t tid; +{ + COMPQUIET(lref, NULL); + COMPQUIET(pid, 0); + COMPQUIET(tid, 0); +} + +int +__lock_failchk(env) + ENV *env; +{ + COMPQUIET(env, NULL); + return (0); +} + +int +__lock_get_list(env, locker, flags, lock_mode, list) + ENV *env; + DB_LOCKER *locker; + u_int32_t flags; + db_lockmode_t lock_mode; + DBT *list; +{ + COMPQUIET(env, NULL); + COMPQUIET(locker, NULL); + COMPQUIET(flags, 0); + COMPQUIET(lock_mode, 0); + COMPQUIET(list, NULL); + return (0); +} + +void +__lock_list_print(env, mbp, list) + ENV *env; + DB_MSGBUF *mbp; + DBT *list; +{ + COMPQUIET(env, NULL); + COMPQUIET(mbp, NULL); + COMPQUIET(list, NULL); +} + +int +__lock_getlocker(lt, locker, create, retp) + DB_LOCKTAB *lt; + u_int32_t locker; + int create; + DB_LOCKER **retp; +{ + COMPQUIET(locker, 0); + COMPQUIET(create, 0); + COMPQUIET(retp, NULL); + return (__db_nolocking(lt->env)); +} + +int +__lock_id_set(env, cur_id, max_id) + ENV *env; + u_int32_t cur_id, max_id; +{ + COMPQUIET(env, NULL); + COMPQUIET(cur_id, 0); + COMPQUIET(max_id, 0); + return (0); +} + +int +__lock_wakeup(env, obj) + ENV *env; + const DBT *obj; +{ + COMPQUIET(obj, NULL); + return (__db_nolocking(env)); +} + +int +__lock_change(env, old_lock, new_lock) + ENV *env; + DB_LOCK *old_lock, *new_lock; +{ + COMPQUIET(env, NULL); + COMPQUIET(old_lock, NULL); + COMPQUIET(new_lock, NULL); + return (0); +} + +int +__db_lget(dbc, action, pgno, mode, lkflags, lockp) + DBC *dbc; + int action; + db_pgno_t pgno; + db_lockmode_t mode; + u_int32_t lkflags; + DB_LOCK *lockp; +{ + COMPQUIET(dbc, NULL); + COMPQUIET(action, 0); + COMPQUIET(pgno, 0); + COMPQUIET(mode, 0); + COMPQUIET(lkflags, 0); + LOCK_INIT(*lockp); + return (0); +} + +int +__db_lput(dbc, lockp) + DBC *dbc; + DB_LOCK *lockp; +{ + COMPQUIET(lockp, NULL); + (void) __db_nolocking(dbc->env); + return (0); +} diff -r 000000000000 -r a1985f14b030 src/log/log_verify_stub.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/log/log_verify_stub.c Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,101 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 1996, 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + * $Id$ + */ + +#ifndef HAVE_VERIFY + +#include "db_config.h" +#include "db_int.h" + +static int __db_log_novrfy __P((ENV *)); +int __log_verify_pp __P((DB_ENV *, const DB_LOG_VERIFY_CONFIG *)); +int __log_verify __P((DB_ENV *, const DB_LOG_VERIFY_CONFIG *)); +int __log_verify_wrap __P((ENV *env, const char *, u_int32_t, const char *, + const char *, time_t, time_t, u_int32_t, u_int32_t, u_int32_t, u_int32_t, + int, int)); + +/* + * __db_log_novrfy -- + * Error when a Berkeley DB build doesn't include verification for logs. + */ +static int +__db_log_novrfy(env) + ENV *env; +{ + __db_errx(env, DB_STR("2523", + "library build did not include support for log verification")); + return (DB_OPNOTSUP); +} + +int +__log_verify_pp(dbenv, lvconfig) + DB_ENV *dbenv; + const DB_LOG_VERIFY_CONFIG *lvconfig; +{ + COMPQUIET(lvconfig, NULL); + + /* The dbenv is intact, callers should properly take care of it. */ + return (__db_log_novrfy(dbenv->env)); +} + +int +__log_verify(dbenv, lvconfig) + DB_ENV *dbenv; + const DB_LOG_VERIFY_CONFIG *lvconfig; +{ + COMPQUIET(lvconfig, NULL); + + return (__db_log_novrfy(dbenv->env)); +} + +int +__log_verify_wrap(env, envhome, cachesize, dbfile, dbname, + stime, etime, stfile, stoffset, efile, eoffset, caf, verbose) + ENV *env; + const char *envhome, *dbfile, *dbname; + time_t stime, etime; + u_int32_t cachesize, stfile, stoffset, efile, eoffset; + int caf, verbose; +{ + COMPQUIET(envhome, NULL); + COMPQUIET(dbfile, NULL); + COMPQUIET(dbname, NULL); + COMPQUIET(stime, 0); + COMPQUIET(etime, 0); + COMPQUIET(cachesize, 0); + COMPQUIET(stfile, 0); + COMPQUIET(stoffset, 0); + COMPQUIET(efile, 0); + COMPQUIET(eoffset, 0); + COMPQUIET(caf, 0); + COMPQUIET(verbose, 0); + return (__db_log_novrfy(env)); +} + +#endif /* !HAVE_VERIFY */ diff -r 000000000000 -r a1985f14b030 src/mp/mp_alloc.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/mp/mp_alloc.c Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,767 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 1996, 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + * $Id$ + */ + +#include "db_config.h" + +#include "db_int.h" +#include "dbinc/mp.h" +#include "dbinc/txn.h" + +/* + * This configuration parameter limits the number of hash buckets which + * __memp_alloc() searches through while excluding buffers with a 'high' + * priority. + */ +#if !defined(MPOOL_ALLOC_SEARCH_LIMIT) +#define MPOOL_ALLOC_SEARCH_LIMIT 500 +#endif + +/* + * __memp_alloc -- + * Allocate some space from a cache region. + * + * PUBLIC: int __memp_alloc __P((DB_MPOOL *, + * PUBLIC: REGINFO *, MPOOLFILE *, size_t, roff_t *, void *)); + */ +int +__memp_alloc(dbmp, infop, mfp, len, offsetp, retp) + DB_MPOOL *dbmp; + REGINFO *infop; + MPOOLFILE *mfp; + size_t len; + roff_t *offsetp; + void *retp; +{ + BH *bhp, *current_bhp; +#ifdef HAVE_TRANSACTIONS + BH *mvcc_bhp, *oldest_bhp; + BH_FROZEN_PAGE *frozen_bhp; + DB_LSN oldest_reader, vlsn; +#endif + DB_MPOOL_HASH *dbht, *hp, *hp_end, *hp_saved, *hp_tmp; + ENV *env; + MPOOL *c_mp; + MPOOLFILE *bh_mfp; + size_t freed_space; + u_int32_t buckets, bucket_priority, buffers, cache_reduction; + u_int32_t dirty_eviction, high_priority, priority, versions; + u_int32_t priority_saved, put_counter, lru_generation, total_buckets; + int aggressive, alloc_freeze, b_lock, giveup; + int h_locked, obsolete, ret, write_error; +#ifdef HAVE_TRANSACTIONS + int need_free; + u_int8_t *endp; +#endif + void *p; + + env = dbmp->env; + c_mp = infop->primary; + dbht = R_ADDR(infop, c_mp->htab); + hp_end = &dbht[c_mp->htab_buckets]; + hp_saved = NULL; + priority_saved = 0; + write_error = 0; + + buckets = buffers = put_counter = total_buckets = versions = 0; + aggressive = alloc_freeze = giveup = h_locked = 0; + + /* + * If we're allocating a buffer, and the one we're discarding is the + * same size, we don't want to waste the time to re-integrate it into + * the shared memory free list. If the DB_MPOOLFILE argument isn't + * NULL, we'll compare the underlying page sizes of the two buffers + * before free-ing and re-allocating buffers. + */ + if (mfp != NULL) { + len = SSZA(BH, buf) + mfp->pagesize; + /* Add space for alignment padding for MVCC diagnostics. */ + MVCC_BHSIZE(mfp, len); + } + + STAT_INC(env, mpool, nallocs, c_mp->stat.st_alloc, len); + + MPOOL_REGION_LOCK(env, infop); + + /* + * First we try to allocate from free memory. If that fails, scan the + * buffer pool to find buffers with low priorities. We consider small + * sets of hash buckets each time to limit the amount of work needing + * to be done. This approximates LRU, but not very well. We either + * find a buffer of the same size to use, or we will free 3 times what + * we need in the hopes it will coalesce into a contiguous chunk of the + * right size. In the latter case we branch back here and try again. + */ +alloc: if ((ret = __env_alloc(infop, len, &p)) == 0) { + if (mfp != NULL) { + /* + * For MVCC diagnostics, align the pointer so that the + * buffer starts on a page boundary. + */ + MVCC_BHALIGN(p); + bhp = (BH *)p; + + if ((ret = __mutex_alloc(env, MTX_MPOOL_BH, + DB_MUTEX_SHARED, &bhp->mtx_buf)) != 0) { + MVCC_BHUNALIGN(bhp); + __env_alloc_free(infop, bhp); + goto search; + } + c_mp->pages++; + } + MPOOL_REGION_UNLOCK(env, infop); +found: if (offsetp != NULL) + *offsetp = R_OFFSET(infop, p); + *(void **)retp = p; + + /* + * Update the search statistics. + * + * We're not holding the region locked here, these statistics + * can't be trusted. + */ +#ifdef HAVE_STATISTICS + total_buckets += buckets; + if (total_buckets != 0) { + if (total_buckets > c_mp->stat.st_alloc_max_buckets) + STAT_SET(env, mpool, alloc_max_buckets, + c_mp->stat.st_alloc_max_buckets, + total_buckets, infop->id); + STAT_ADJUST(env, mpool, alloc_buckets, + c_mp->stat.st_alloc_buckets, + total_buckets, infop->id); + } + if (buffers != 0) { + if (buffers > c_mp->stat.st_alloc_max_pages) + STAT_SET(env, mpool, alloc_max_pages, + c_mp->stat.st_alloc_max_pages, + buffers, infop->id); + STAT_ADJUST(env, mpool, alloc_pages, + c_mp->stat.st_alloc_pages, buffers, infop->id); + } +#endif + return (0); + } else if (giveup || c_mp->pages == 0) { + MPOOL_REGION_UNLOCK(env, infop); + + __db_errx(env, DB_STR("3017", + "unable to allocate space from the buffer cache")); + return ((ret == ENOMEM && write_error != 0) ? EIO : ret); + } + +search: + /* + * Anything newer than 1/10th of the buffer pool is ignored during the + * first MPOOL_SEARCH_ALLOC_LIMIT buckets worth of allocation. + */ + cache_reduction = c_mp->pages / 10; + high_priority = aggressive ? MPOOL_LRU_MAX : + c_mp->lru_priority - cache_reduction; + lru_generation = c_mp->lru_generation; + + ret = 0; +#ifdef HAVE_TRANSACTIONS + MAX_LSN(oldest_reader); +#endif + + /* + * We re-attempt the allocation every time we've freed 3 times what + * we need. Reset our free-space counter. + */ + freed_space = 0; + total_buckets += buckets; + buckets = 0; + + /* + * Walk the hash buckets and find the next two with potentially useful + * buffers. Free the buffer with the lowest priority from the buckets' + * chains. + */ + for (;;) { + /* All pages have been freed, make one last try */ + if (c_mp->pages == 0) + goto alloc; + + /* Check for wrap around. */ + hp = &dbht[c_mp->last_checked++]; + if (hp >= hp_end) { + c_mp->last_checked = 0; + hp = &dbht[c_mp->last_checked++]; + } + + /* + * The failure mode is when there are too many buffers we can't + * write or there's not enough memory in the system to support + * the number of pinned buffers. + * + * Get aggressive if we've reviewed the entire cache without + * freeing the needed space. (The code resets "aggressive" + * when we free any space.) Aggressive means: + * + * a: set a flag to attempt to flush high priority buffers as + * well as other buffers. + * b: look at a buffer in every hash bucket rather than choose + * the more preferable of two. + * c: start to think about giving up. + * + * If we get here three or more times, sync the mpool to force + * out queue extent pages. While we might not have enough + * space for what we want and flushing is expensive, why not? + * Then sleep for a second, hopefully someone else will run and + * free up some memory. + * + * Always try to allocate memory too, in case some other thread + * returns its memory to the region. + * + * We don't have any way to know an allocation has no way to + * succeed. Fail if no pages are returned to the cache after + * we've been trying for a relatively long time. + * + * !!! + * This test ignores pathological cases like no buffers in the + * system -- we check for that early on, so it isn't possible. + */ + if (buckets++ == c_mp->htab_buckets) { + if (freed_space > 0) + goto alloc; + MPOOL_REGION_UNLOCK(env, infop); + + aggressive++; + /* + * Once aggressive, we consider all buffers. By setting + * this to MPOOL_LRU_MAX, we'll still select a victim + * even if all buffers have the highest normal priority. + */ + high_priority = MPOOL_LRU_MAX; + PERFMON4(env, mpool, alloc_wrap, + len, infop->id, aggressive, c_mp->put_counter); + switch (aggressive) { + case 1: + break; + case 2: + put_counter = c_mp->put_counter; + break; + case 3: + case 4: + case 5: + case 6: + (void)__memp_sync_int( + env, NULL, 0, DB_SYNC_ALLOC, NULL, NULL); + + __os_yield(env, 1, 0); + break; + default: + aggressive = 1; + if (put_counter == c_mp->put_counter) + giveup = 1; + break; + } + + MPOOL_REGION_LOCK(env, infop); + goto alloc; + } + + /* + * Skip empty buckets. + * + * We can check for empty buckets before locking the hash + * bucket as we only care if the pointer is zero or non-zero. + */ + if (SH_TAILQ_FIRST(&hp->hash_bucket, __bh) == NULL) + continue; + + /* Set aggressive if we have already searched for too long. */ + if (aggressive == 0 && buckets >= MPOOL_ALLOC_SEARCH_LIMIT) { + aggressive = 1; + /* Once aggressive, we consider all buffers. */ + high_priority = MPOOL_LRU_MAX; + } + + /* Unlock the region and lock the hash bucket. */ + MPOOL_REGION_UNLOCK(env, infop); + MUTEX_READLOCK(env, hp->mtx_hash); + h_locked = 1; + b_lock = 0; + + /* + * Find a buffer we can use. + * + * We use the lowest-LRU singleton buffer if we find one and + * it's better than the result of another hash bucket we've + * reviewed. We do not use a buffer which has a priority + * greater than high_priority unless we are being aggressive. + * + * With MVCC buffers, the situation is more complicated: we + * don't want to free a buffer out of the middle of an MVCC + * chain, since that requires I/O. So, walk the buffers, + * looking for an obsolete buffer at the end of an MVCC chain. + * Once a buffer becomes obsolete, its LRU priority is + * irrelevant because that version can never be accessed again. + * + * If we don't find any obsolete MVCC buffers, we will get + * aggressive, and in that case consider the lowest priority + * buffer within a chain. + * + * Ignore referenced buffers, we can't get rid of them. + */ +retry_search: bhp = NULL; + bucket_priority = high_priority; + obsolete = 0; + SH_TAILQ_FOREACH(current_bhp, &hp->hash_bucket, hq, __bh) { + /* + * First, do the standard LRU check for singletons. + * We can use the buffer if it is unreferenced, has a + * priority that isn't too high (unless we are + * aggressive), and is better than the best candidate + * we have found so far in this bucket. + */ +#ifdef MPOOL_ALLOC_SEARCH_DYN + if (aggressive == 0 && + ++high_priority >= c_mp->lru_priority) + aggressive = 1; +#endif + + if (SH_CHAIN_SINGLETON(current_bhp, vc)) { + if (BH_REFCOUNT(current_bhp) != 0) + continue; + buffers++; + if (bucket_priority > current_bhp->priority) { + bucket_priority = current_bhp->priority; + if (bhp != NULL) + atomic_dec(env, &bhp->ref); + bhp = current_bhp; + atomic_inc(env, &bhp->ref); + } + continue; + } + +#ifdef HAVE_TRANSACTIONS + /* + * For MVCC buffers, walk through the chain. If we are + * aggressive, choose the best candidate from within + * the chain for freezing. + */ + for (mvcc_bhp = oldest_bhp = current_bhp; + mvcc_bhp != NULL; + oldest_bhp = mvcc_bhp, + mvcc_bhp = SH_CHAIN_PREV(mvcc_bhp, vc, __bh)) { +#ifdef MPOOL_ALLOC_SEARCH_DYN + if (aggressive == 0 && + ++high_priority >= c_mp->lru_priority) + aggressive = 1; +#endif + DB_ASSERT(env, mvcc_bhp != + SH_CHAIN_PREV(mvcc_bhp, vc, __bh)); + if ((aggressive < 2 && + ++versions < (buffers >> 2)) || + BH_REFCOUNT(mvcc_bhp) != 0) + continue; + buffers++; + if (!F_ISSET(mvcc_bhp, BH_FROZEN) && + (bhp == NULL || + bhp->priority > mvcc_bhp->priority)) { + if (bhp != NULL) + atomic_dec(env, &bhp->ref); + bhp = mvcc_bhp; + atomic_inc(env, &bhp->ref); + } + } + + /* + * oldest_bhp is the last buffer on the MVCC chain, and + * an obsolete buffer at the end of the MVCC chain gets + * used without further search. Before checking for + * obsolescence, update the cached oldest reader LSN in + * the bucket if it is older than call's oldest_reader. + */ + if (BH_REFCOUNT(oldest_bhp) != 0) + continue; + + if (LOG_COMPARE(&oldest_reader, &hp->old_reader) > 0) { + if (IS_MAX_LSN(oldest_reader) && + (ret = __txn_oldest_reader( + env, &oldest_reader)) != 0) { + MUTEX_UNLOCK(env, hp->mtx_hash); + if (bhp != NULL) + atomic_dec(env, &bhp->ref); + return (ret); + } + if (LOG_COMPARE(&oldest_reader, + &hp->old_reader) > 0) + hp->old_reader = oldest_reader; + } + + if (BH_OBSOLETE(oldest_bhp, hp->old_reader, vlsn)) { + if (aggressive < 2) + buffers++; + obsolete = 1; + if (bhp != NULL) + atomic_dec(env, &bhp->ref); + bhp = oldest_bhp; + atomic_inc(env, &bhp->ref); + goto this_buffer; + } +#endif + } + + /* + * bhp is either NULL or the best candidate buffer. + * We'll use the chosen buffer only if we have compared its + * priority against one chosen from another hash bucket. + */ + if (bhp == NULL) + goto next_hb; + + priority = bhp->priority; + + /* + * Compare two hash buckets and select the one with the lower + * priority. Performance testing showed looking at two improves + * the LRU-ness and looking at more only does a little better. + */ + if (hp_saved == NULL) { + hp_saved = hp; + priority_saved = priority; + goto next_hb; + } + + /* + * If the buffer we just found is a better choice than our + * previous choice, use it. + * + * If the previous choice was better, pretend we're moving + * from this hash bucket to the previous one and re-do the + * search. + * + * We don't worry about simply swapping between two buckets + * because that could only happen if a buffer was removed + * from the chain, or its priority updated. If a buffer + * is removed from the chain, some other thread has managed + * to discard a buffer, so we're moving forward. Updating + * a buffer's priority will make it a high-priority buffer, + * so we'll ignore it when we search again, and so we will + * eventually zero in on a buffer to use, or we'll decide + * there are no buffers we can use. + * + * If there's only a single hash bucket with buffers, we'll + * search the bucket once, choose a buffer, walk the entire + * list of buckets and search it again. In the case of a + * system that's busy, it's possible to imagine a case where + * we'd loop for a long while. For that reason, and because + * the test is easy, we special case and test for it. + */ + if (priority > priority_saved && hp != hp_saved) { + MUTEX_UNLOCK(env, hp->mtx_hash); + hp_tmp = hp_saved; + hp_saved = hp; + hp = hp_tmp; + priority_saved = priority; + MUTEX_READLOCK(env, hp->mtx_hash); + h_locked = 1; + DB_ASSERT(env, BH_REFCOUNT(bhp) > 0); + atomic_dec(env, &bhp->ref); + goto retry_search; + } + + /* + * If another thread has called __memp_reset_lru() while we were + * looking for this buffer, it is possible that we've picked a + * poor choice for a victim. If so toss it and start over. + */ + if (lru_generation != c_mp->lru_generation) { + DB_ASSERT(env, BH_REFCOUNT(bhp) > 0); + atomic_dec(env, &bhp->ref); + MUTEX_UNLOCK(env, hp->mtx_hash); + MPOOL_REGION_LOCK(env, infop); + hp_saved = NULL; + goto search; + } + +#ifdef HAVE_TRANSACTIONS +this_buffer: +#endif + /* + * Discard any previously remembered hash bucket, we've got + * a winner. + */ + hp_saved = NULL; + + /* Drop the hash mutex and lock the buffer exclusively. */ + MUTEX_UNLOCK(env, hp->mtx_hash); + h_locked = 0; + + /* Don't bother trying to latch a busy buffer. */ + if (BH_REFCOUNT(bhp) > 1) + goto next_hb; + + /* We cannot block as the caller is probably holding locks. */ + if ((ret = MUTEX_TRYLOCK(env, bhp->mtx_buf)) != 0) { + if (ret != DB_LOCK_NOTGRANTED) + return (ret); + goto next_hb; + } + F_SET(bhp, BH_EXCLUSIVE); + b_lock = 1; + + /* Someone may have grabbed it while we got the lock. */ + if (BH_REFCOUNT(bhp) != 1) + goto next_hb; + + /* Find the associated MPOOLFILE. */ + bh_mfp = R_ADDR(dbmp->reginfo, bhp->mf_offset); + + /* If the page is dirty, write it. */ + ret = 0; + dirty_eviction = 0; + if (F_ISSET(bhp, BH_DIRTY)) { + DB_ASSERT(env, atomic_read(&hp->hash_page_dirty) > 0); + ret = __memp_bhwrite(dbmp, hp, bh_mfp, bhp, 0); + DB_ASSERT(env, atomic_read(&bhp->ref) > 0); + + /* + * If a write fails for any reason, we can't proceed. + * + * If there's a write error and we're having problems + * finding something to allocate, avoid selecting this + * buffer again by maximizing its priority. + */ + if (ret != 0) { + if (ret != EPERM && ret != EAGAIN) { + write_error++; + __db_errx(env, DB_STR_A("3018", + "%s: unwritable page %d remaining in the cache after error %d", + "%s %d %d"), + __memp_fns(dbmp, bh_mfp), + bhp->pgno, ret); + } + bhp->priority = MPOOL_LRU_REDZONE; + + goto next_hb; + } + + dirty_eviction = 1; + } + +#ifdef HAVE_TRANSACTIONS + /* + * Freeze this buffer, if necessary. That is, if the buffer is + * part of an MVCC chain and could be required by a reader. + */ + if (SH_CHAIN_HASPREV(bhp, vc) || + (SH_CHAIN_HASNEXT(bhp, vc) && !obsolete)) { + if (!aggressive || + F_ISSET(bhp, BH_DIRTY | BH_FROZEN)) + goto next_hb; + ret = __memp_bh_freeze( + dbmp, infop, hp, bhp, &alloc_freeze); + if (ret == EIO) + write_error++; + if (ret == EBUSY || ret == EIO || + ret == ENOMEM || ret == ENOSPC) { + ret = 0; + goto next_hb; + } else if (ret != 0) { + DB_ASSERT(env, BH_REFCOUNT(bhp) > 0); + atomic_dec(env, &bhp->ref); + DB_ASSERT(env, b_lock); + F_CLR(bhp, BH_EXCLUSIVE); + MUTEX_UNLOCK(env, bhp->mtx_buf); + DB_ASSERT(env, !h_locked); + return (ret); + } + } +#endif + + MUTEX_LOCK(env, hp->mtx_hash); + h_locked = 1; + + /* + * We released the hash bucket lock while doing I/O, so another + * thread may have acquired this buffer and incremented the ref + * count or dirtied the buffer or installed a new version after + * we wrote it, in which case we can't have it. + */ + if (BH_REFCOUNT(bhp) != 1 || F_ISSET(bhp, BH_DIRTY)) + goto next_hb; + +#ifdef HAVE_TRANSACTIONS + if ((SH_CHAIN_HASNEXT(bhp, vc) && + SH_CHAIN_NEXTP(bhp, vc, __bh)->td_off != bhp->td_off && + !BH_OBSOLETE(bhp, hp->old_reader, vlsn))) + goto next_hb; + + /* + * If the buffer is frozen, thaw it and look for another one + * we can use. (Calling __memp_bh_freeze above will not + * mark bhp BH_FROZEN.) + */ + if (F_ISSET(bhp, BH_FROZEN)) { + DB_ASSERT(env, obsolete || SH_CHAIN_SINGLETON(bhp, vc)); + DB_ASSERT(env, BH_REFCOUNT(bhp) > 0); + if (!F_ISSET(bhp, BH_THAWED)) { + /* + * This call releases the hash bucket mutex. + * We're going to retry the search, so we need + * to re-lock it. + */ + if ((ret = __memp_bh_thaw(dbmp, + infop, hp, bhp, NULL)) != 0) + return (ret); + MUTEX_READLOCK(env, hp->mtx_hash); + } else { + need_free = (atomic_dec(env, &bhp->ref) == 0); + F_CLR(bhp, BH_EXCLUSIVE); + MUTEX_UNLOCK(env, bhp->mtx_buf); + if (need_free) { + MPOOL_REGION_LOCK(env, infop); + SH_TAILQ_INSERT_TAIL(&c_mp->free_frozen, + bhp, hq); + MPOOL_REGION_UNLOCK(env, infop); + } + } + bhp = NULL; + b_lock = alloc_freeze = 0; + goto retry_search; + } +#endif + + /* We are certainly freeing this buf; now update statistic. */ + if (dirty_eviction) + STAT_INC(env, mpool, + dirty_eviction, c_mp->stat.st_rw_evict, infop->id); + else + STAT_INC(env, mpool, + clean_eviction, c_mp->stat.st_ro_evict, infop->id); +#ifdef HAVE_TRANSACTIONS + /* + * If we need some empty buffer headers for freezing, turn the + * buffer we've found into frozen headers and put them on the + * free list. Only reset alloc_freeze if we've actually + * allocated some frozen buffer headers. + */ + if (alloc_freeze) { + if ((ret = __memp_bhfree(dbmp, + infop, bh_mfp, hp, bhp, 0)) != 0) + return (ret); + b_lock = 0; + h_locked = 0; + + MVCC_MPROTECT(bhp->buf, bh_mfp->pagesize, + PROT_READ | PROT_WRITE | PROT_EXEC); + + MPOOL_REGION_LOCK(env, infop); + SH_TAILQ_INSERT_TAIL(&c_mp->alloc_frozen, + (BH_FROZEN_ALLOC *)bhp, links); + frozen_bhp = (BH_FROZEN_PAGE *) + ((BH_FROZEN_ALLOC *)bhp + 1); + endp = (u_int8_t *)bhp->buf + bh_mfp->pagesize; + while ((u_int8_t *)(frozen_bhp + 1) < endp) { + frozen_bhp->header.mtx_buf = MUTEX_INVALID; + SH_TAILQ_INSERT_TAIL(&c_mp->free_frozen, + (BH *)frozen_bhp, hq); + frozen_bhp++; + } + MPOOL_REGION_UNLOCK(env, infop); + + alloc_freeze = 0; + MUTEX_READLOCK(env, hp->mtx_hash); + h_locked = 1; + goto retry_search; + } +#endif + + /* + * Check to see if the buffer is the size we're looking for. + * If so, we can simply reuse it. Otherwise, free the buffer + * and its space and keep looking. + */ + if (mfp != NULL && mfp->pagesize == bh_mfp->pagesize) { + if ((ret = __memp_bhfree(dbmp, + infop, bh_mfp, hp, bhp, 0)) != 0) + return (ret); + p = bhp; + goto found; + } + + freed_space += sizeof(*bhp) + bh_mfp->pagesize; + if ((ret = + __memp_bhfree(dbmp, infop, + bh_mfp, hp, bhp, BH_FREE_FREEMEM)) != 0) + return (ret); + + /* Reset "aggressive" and "write_error" if we free any space. */ + if (aggressive > 1) + aggressive = 1; + write_error = 0; + + /* + * Unlock this buffer and re-acquire the region lock. If + * we're reaching here as a result of calling memp_bhfree, the + * buffer lock has already been discarded. + */ + if (0) { +next_hb: if (bhp != NULL) { + DB_ASSERT(env, BH_REFCOUNT(bhp) > 0); + atomic_dec(env, &bhp->ref); + if (b_lock) { + F_CLR(bhp, BH_EXCLUSIVE); + MUTEX_UNLOCK(env, bhp->mtx_buf); + } + } + if (h_locked) + MUTEX_UNLOCK(env, hp->mtx_hash); + h_locked = 0; + } + MPOOL_REGION_LOCK(env, infop); + + /* + * Retry the allocation as soon as we've freed up sufficient + * space. We're likely to have to coalesce of memory to + * satisfy the request, don't try until it's likely (possible?) + * we'll succeed. + */ + if (freed_space >= 3 * len) + goto alloc; + } + /* NOTREACHED */ +} + +/* + * __memp_free -- + * Free some space from a cache region. + * + * PUBLIC: void __memp_free __P((REGINFO *, void *)); + */ +void +__memp_free(infop, buf) + REGINFO *infop; + void *buf; +{ + __env_alloc_free(infop, buf); +} diff -r 000000000000 -r a1985f14b030 src/mp/mp_bh.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/mp/mp_bh.c Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,716 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 1996, 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + * $Id$ + */ + +#include "db_config.h" + +#include "db_int.h" +#include "dbinc/db_page.h" /* Required for diagnostic code. */ +#include "dbinc/mp.h" +#include "dbinc/log.h" +#include "dbinc/txn.h" + +static int __memp_pgwrite + __P((ENV *, DB_MPOOLFILE *, DB_MPOOL_HASH *, BH *)); + +/* + * __memp_bhwrite -- + * Write the page associated with a given buffer header. + * + * PUBLIC: int __memp_bhwrite __P((DB_MPOOL *, + * PUBLIC: DB_MPOOL_HASH *, MPOOLFILE *, BH *, int)); + */ +int +__memp_bhwrite(dbmp, hp, mfp, bhp, open_extents) + DB_MPOOL *dbmp; + DB_MPOOL_HASH *hp; + MPOOLFILE *mfp; + BH *bhp; + int open_extents; +{ + DB_MPOOLFILE *dbmfp; + DB_MPREG *mpreg; + ENV *env; + int opened, ret; + + env = dbmp->env; + opened = 0; + + /* + * If the file has been removed or is a closed temporary file, we're + * done -- the page-write function knows how to handle the fact that + * we don't have (or need!) any real file descriptor information. + */ + if (mfp->deadfile) + return (__memp_pgwrite(env, NULL, hp, bhp)); + + /* + * Walk the process' DB_MPOOLFILE list and find a file descriptor for + * the file. We also check that the descriptor is open for writing. + */ + MUTEX_LOCK(env, dbmp->mutex); + TAILQ_FOREACH(dbmfp, &dbmp->dbmfq, q) + if (dbmfp->mfp == mfp && !F_ISSET(dbmfp, MP_READONLY)) { + ++dbmfp->ref; + break; + } + MUTEX_UNLOCK(env, dbmp->mutex); + + if (dbmfp != NULL) { + /* + * Temporary files may not have been created. We only handle + * temporary files in this path, because only the process that + * created a temporary file will ever flush buffers to it. + */ + if (dbmfp->fhp == NULL) { + /* We may not be allowed to create backing files. */ + if (mfp->no_backing_file) { + --dbmfp->ref; + return (EPERM); + } + + MUTEX_LOCK(env, dbmp->mutex); + if (dbmfp->fhp == NULL) { + ret = __db_tmp_open(env, + F_ISSET(env->dbenv, DB_ENV_DIRECT_DB) ? + DB_OSO_DIRECT : 0, &dbmfp->fhp); + } else + ret = 0; + MUTEX_UNLOCK(env, dbmp->mutex); + if (ret != 0) { + __db_errx(env, DB_STR("3014", + "unable to create temporary backing file")); + --dbmfp->ref; + return (ret); + } + } + + goto pgwrite; + } + + /* + * There's no file handle for this file in our process. + * + * !!! + * It's the caller's choice if we're going to open extent files. + */ + if (!open_extents && F_ISSET(mfp, MP_EXTENT)) + return (EPERM); + + /* + * !!! + * Don't try to attach to temporary files. There are two problems in + * trying to do that. First, if we have different privileges than the + * process that "owns" the temporary file, we might create the backing + * disk file such that the owning process couldn't read/write its own + * buffers, e.g., memp_trickle running as root creating a file owned + * as root, mode 600. Second, if the temporary file has already been + * created, we don't have any way of finding out what its real name is, + * and, even if we did, it was already unlinked (so that it won't be + * left if the process dies horribly). This decision causes a problem, + * however: if the temporary file consumes the entire buffer cache, + * and the owner doesn't flush the buffers to disk, we could end up + * with resource starvation, and the memp_trickle thread couldn't do + * anything about it. That's a pretty unlikely scenario, though. + * + * Note we should never get here when the temporary file in question + * has already been closed in another process, in which case it should + * be marked dead. + */ + if (F_ISSET(mfp, MP_TEMP) || mfp->no_backing_file) + return (EPERM); + + /* + * It's not a page from a file we've opened. If the file requires + * application-specific input/output processing, see if this process + * has ever registered information as to how to write this type of + * file. If not, there's nothing we can do. + */ + if (mfp->ftype != 0 && mfp->ftype != DB_FTYPE_SET) { + MUTEX_LOCK(env, dbmp->mutex); + LIST_FOREACH(mpreg, &dbmp->dbregq, q) + if (mpreg->ftype == mfp->ftype) + break; + MUTEX_UNLOCK(env, dbmp->mutex); + if (mpreg == NULL) + return (EPERM); + } + + /* + * Try and open the file, specifying the known underlying shared area. + * + * !!! + * There's no negative cache, so we may repeatedly try and open files + * that we have previously tried (and failed) to open. + */ + if ((ret = __memp_fcreate(env, &dbmfp)) != 0) + return (ret); + /* + * The open will set MP_FLUSH and so we need to keep + * a checkpoint from closing this before we finish with it. + */ + dbmfp->ref++; + opened = 1; + if ((ret = __memp_fopen(dbmfp, mfp, NULL, + NULL, DB_FLUSH | DB_DURABLE_UNKNOWN, 0, mfp->pagesize)) != 0) { + dbmfp->ref--; + (void)__memp_fclose(dbmfp, 0); + + /* + * Ignore any error if the file is marked dead, assume the file + * was removed from under us. + */ + if (!mfp->deadfile) + return (ret); + + dbmfp = NULL; + } + +pgwrite: + MVCC_MPROTECT(bhp->buf, mfp->pagesize, + PROT_READ | PROT_WRITE | PROT_EXEC); + ret = __memp_pgwrite(env, dbmfp, hp, bhp); + if (dbmfp == NULL) + return (ret); + + /* + * Discard our reference, and, if we're the last reference, make sure + * the file eventually gets closed. + */ + MUTEX_LOCK(env, dbmp->mutex); + if (!opened && dbmfp->ref == 1) { + /* + * If we are the last reference, then we need to mark + * this as having been used to flush. If this dbmf + * has not been counted as a neutral reference do it. + * + * Getting the mfp mutex while holding the dbmp is + * ok we never do it in the reverse order. + */ + if (!F_ISSET(dbmfp, MP_FLUSH)) { + F_SET(dbmfp, MP_FLUSH); + MUTEX_LOCK(env,dbmfp->mfp->mutex); + if (!F_ISSET(dbmfp, MP_FOR_FLUSH)) { + mfp->neutral_cnt++; + F_SET(dbmfp, MP_FOR_FLUSH); + } + MUTEX_UNLOCK(env, dbmfp->mfp->mutex); + } + } else + --dbmfp->ref; + MUTEX_UNLOCK(env, dbmp->mutex); + + return (ret); +} + +/* + * __memp_pgread -- + * Read a page from a file. + * + * PUBLIC: int __memp_pgread __P((DB_MPOOLFILE *, BH *, int)); + */ +int +__memp_pgread(dbmfp, bhp, can_create) + DB_MPOOLFILE *dbmfp; + BH *bhp; + int can_create; +{ + ENV *env; + MPOOLFILE *mfp; + size_t len, nr; + u_int32_t pagesize; + int ret; + + env = dbmfp->env; + mfp = dbmfp->mfp; + pagesize = mfp->pagesize; + + /* We should never be called with a dirty or unlocked buffer. */ + DB_ASSERT(env, !F_ISSET(bhp, BH_DIRTY_CREATE | BH_FROZEN)); + DB_ASSERT(env, can_create || + F_ISSET(bhp, BH_TRASH) || !F_ISSET(bhp, BH_DIRTY)); + DB_ASSERT(env, F_ISSET(bhp, BH_EXCLUSIVE)); + + /* Mark the buffer as in transition. */ + F_SET(bhp, BH_TRASH); + + /* + * Temporary files may not yet have been created. We don't create + * them now, we create them when the pages have to be flushed. + */ + nr = 0; + if (dbmfp->fhp != NULL) { + PERFMON3(env, mpool, read, __memp_fn(dbmfp), bhp->pgno, bhp); + if ((ret = __os_io(env, DB_IO_READ, dbmfp->fhp, + bhp->pgno, pagesize, 0, pagesize, bhp->buf, &nr)) != 0) + goto err; + } + + /* + * The page may not exist; if it doesn't, nr may well be 0, but we + * expect the underlying OS calls not to return an error code in + * this case. + */ + if (nr < pagesize) { + /* + * Don't output error messages for short reads. In particular, + * DB recovery processing may request pages never written to + * disk or for which only some part have been written to disk, + * in which case we won't find the page. The caller must know + * how to handle the error. + */ + if (!can_create) { + ret = DB_PAGE_NOTFOUND; + goto err; + } + + /* Clear any bytes that need to be cleared. */ + len = mfp->clear_len == DB_CLEARLEN_NOTSET ? + pagesize : mfp->clear_len; + memset(bhp->buf, 0, len); + +#if defined(DIAGNOSTIC) || defined(UMRW) + /* + * If we're running in diagnostic mode, corrupt any bytes on + * the page that are unknown quantities for the caller. + */ + if (len < pagesize) + memset(bhp->buf + len, CLEAR_BYTE, pagesize - len); +#endif + STAT_INC_VERB(env, mpool, page_create, + mfp->stat.st_page_create, __memp_fn(dbmfp), bhp->pgno); + } else + STAT_INC_VERB(env, mpool, page_in, + mfp->stat.st_page_in, __memp_fn(dbmfp), bhp->pgno); + + /* Call any pgin function. */ + ret = mfp->ftype == 0 ? 0 : __memp_pg(dbmfp, bhp->pgno, bhp->buf, 1); + + /* + * If no errors occurred, the data is now valid, clear the BH_TRASH + * flag. + */ + if (ret == 0) + F_CLR(bhp, BH_TRASH); +err: return (ret); +} + +/* + * __memp_pgwrite -- + * Write a page to a file. + */ +static int +__memp_pgwrite(env, dbmfp, hp, bhp) + ENV *env; + DB_MPOOLFILE *dbmfp; + DB_MPOOL_HASH *hp; + BH *bhp; +{ + DB_LSN lsn; + MPOOLFILE *mfp; + size_t nw; + int ret; + void * buf; + + /* + * Since writing does not require exclusive access, another thread + * could have already written this buffer. + */ + if (!F_ISSET(bhp, BH_DIRTY)) + return (0); + + mfp = dbmfp == NULL ? NULL : dbmfp->mfp; + ret = 0; + buf = NULL; + + /* We should never be called with a frozen or trashed buffer. */ + DB_ASSERT(env, !F_ISSET(bhp, BH_FROZEN | BH_TRASH)); + + /* + * It's possible that the underlying file doesn't exist, either + * because of an outright removal or because it was a temporary + * file that's been closed. + * + * !!! + * Once we pass this point, we know that dbmfp and mfp aren't NULL, + * and that we have a valid file reference. + */ + if (mfp == NULL || mfp->deadfile) + goto file_dead; + + /* + * If the page is in a file for which we have LSN information, we have + * to ensure the appropriate log records are on disk. + */ + if (LOGGING_ON(env) && mfp->lsn_off != DB_LSN_OFF_NOTSET && + !IS_CLIENT_PGRECOVER(env)) { + memcpy(&lsn, bhp->buf + mfp->lsn_off, sizeof(DB_LSN)); + if (!IS_NOT_LOGGED_LSN(lsn) && + (ret = __log_flush(env, &lsn)) != 0) + goto err; + } + +#ifdef DIAGNOSTIC + /* + * Verify write-ahead logging semantics. + * + * !!! + * Two special cases. There is a single field on the meta-data page, + * the last-page-number-in-the-file field, for which we do not log + * changes. If the page was originally created in a database that + * didn't have logging turned on, we can see a page marked dirty but + * for which no corresponding log record has been written. However, + * the only way that a page can be created for which there isn't a + * previous log record and valid LSN is when the page was created + * without logging turned on, and so we check for that special-case + * LSN value. + * + * Second, when a client is reading database pages from a master + * during an internal backup, we may get pages modified after + * the current end-of-log. + */ + if (LOGGING_ON(env) && !IS_NOT_LOGGED_LSN(LSN(bhp->buf)) && + !IS_CLIENT_PGRECOVER(env)) { + /* + * There is a potential race here. If we are in the midst of + * switching log files, it's possible we could test against the + * old file and the new offset in the log region's LSN. If we + * fail the first test, acquire the log mutex and check again. + */ + DB_LOG *dblp; + LOG *lp; + + dblp = env->lg_handle; + lp = dblp->reginfo.primary; + if (!lp->db_log_inmemory && + LOG_COMPARE(&lp->s_lsn, &LSN(bhp->buf)) <= 0) { + MUTEX_LOCK(env, lp->mtx_flush); + DB_ASSERT(env, F_ISSET(env->dbenv, DB_ENV_NOLOCKING) || + LOG_COMPARE(&lp->s_lsn, &LSN(bhp->buf)) > 0); + MUTEX_UNLOCK(env, lp->mtx_flush); + } + } +#endif + +#ifndef HAVE_ATOMICFILEREAD + if (mfp->backup_in_progress != 0) { + MUTEX_READLOCK(env, mfp->mtx_write); + if (bhp->pgno >= mfp->low_pgno && bhp->pgno <= mfp->high_pgno) { + MUTEX_UNLOCK(env, mfp->mtx_write); + ret = EAGAIN; + goto err; + } + atomic_inc(env, &mfp->writers); + MUTEX_UNLOCK(env, mfp->mtx_write); + } else + atomic_inc(env, &mfp->writers); +#endif + + /* + * Call any pgout function. If we have the page exclusive then + * we are going to reuse it otherwise make a copy of the page so + * that others can continue looking at the page while we write it. + */ + buf = bhp->buf; + if (mfp->ftype != 0) { + if (F_ISSET(bhp, BH_EXCLUSIVE)) + F_SET(bhp, BH_TRASH); + else { + if ((ret = __os_malloc(env, mfp->pagesize, &buf)) != 0) + goto err; + memcpy(buf, bhp->buf, mfp->pagesize); + } + if ((ret = __memp_pg(dbmfp, bhp->pgno, buf, 0)) != 0) + goto err; + } + + PERFMON3(env, mpool, write, __memp_fn(dbmfp), bhp->pgno, bhp); + /* Write the page. */ + if ((ret = __os_io(env, DB_IO_WRITE, dbmfp->fhp, bhp->pgno, + mfp->pagesize, 0, mfp->pagesize, buf, &nw)) != 0) { +#ifndef HAVE_ATOMICFILEREAD + atomic_dec(env, &mfp->writers); +#endif + __db_errx(env, DB_STR_A("3015", + "%s: write failed for page %lu", "%s %lu"), + __memp_fn(dbmfp), (u_long)bhp->pgno); + goto err; + } +#ifndef HAVE_ATOMICFILEREAD + atomic_dec(env, &mfp->writers); +#endif + STAT_INC_VERB(env, mpool, page_out, + mfp->stat.st_page_out, __memp_fn(dbmfp), bhp->pgno); + if (bhp->pgno > mfp->last_flushed_pgno) { + MUTEX_LOCK(env, mfp->mutex); + if (bhp->pgno > mfp->last_flushed_pgno) + mfp->last_flushed_pgno = bhp->pgno; + MUTEX_UNLOCK(env, mfp->mutex); + } + +err: +file_dead: + if (buf != NULL && buf != bhp->buf) + __os_free(env, buf); + /* + * !!! + * Once we pass this point, dbmfp and mfp may be NULL, we may not have + * a valid file reference. + */ + + /* + * Update the hash bucket statistics, reset the flags. If we were + * successful, the page is no longer dirty. Someone else may have + * also written the page so we need to latch the hash bucket here + * to get the accounting correct. Since we have the buffer + * shared it cannot be marked dirty again till we release it. + * This is the only place we update the flags field only holding + * a shared latch. + */ + if (F_ISSET(bhp, BH_DIRTY | BH_TRASH)) { + MUTEX_LOCK(env, hp->mtx_hash); + DB_ASSERT(env, !SH_CHAIN_HASNEXT(bhp, vc)); + if (ret == 0 && F_ISSET(bhp, BH_DIRTY)) { + F_CLR(bhp, BH_DIRTY | BH_DIRTY_CREATE); + DB_ASSERT(env, atomic_read(&hp->hash_page_dirty) > 0); + atomic_dec(env, &hp->hash_page_dirty); + } + + /* put the page back if necessary. */ + if ((ret != 0 || BH_REFCOUNT(bhp) > 1) && + F_ISSET(bhp, BH_TRASH)) { + ret = __memp_pg(dbmfp, bhp->pgno, bhp->buf, 1); + F_CLR(bhp, BH_TRASH); + } + MUTEX_UNLOCK(env, hp->mtx_hash); + } + + return (ret); +} + +/* + * __memp_pg -- + * Call the pgin/pgout routine. + * + * PUBLIC: int __memp_pg __P((DB_MPOOLFILE *, db_pgno_t, void *, int)); + */ +int +__memp_pg(dbmfp, pgno, buf, is_pgin) + DB_MPOOLFILE *dbmfp; + db_pgno_t pgno; + void *buf; + int is_pgin; +{ + DBT dbt, *dbtp; + DB_MPOOL *dbmp; + DB_MPREG *mpreg; + ENV *env; + MPOOLFILE *mfp; + int ftype, ret; + + env = dbmfp->env; + dbmp = env->mp_handle; + mfp = dbmfp->mfp; + + if ((ftype = mfp->ftype) == DB_FTYPE_SET) + mpreg = dbmp->pg_inout; + else { + MUTEX_LOCK(env, dbmp->mutex); + LIST_FOREACH(mpreg, &dbmp->dbregq, q) + if (ftype == mpreg->ftype) + break; + MUTEX_UNLOCK(env, dbmp->mutex); + } + if (mpreg == NULL) + return (0); + + if (mfp->pgcookie_len == 0) + dbtp = NULL; + else { + DB_SET_DBT(dbt, R_ADDR( + dbmp->reginfo, mfp->pgcookie_off), mfp->pgcookie_len); + dbtp = &dbt; + } + + if (is_pgin) { + if (mpreg->pgin != NULL && (ret = + mpreg->pgin(env->dbenv, pgno, buf, dbtp)) != 0) + goto err; + } else + if (mpreg->pgout != NULL && (ret = + mpreg->pgout(env->dbenv, pgno, buf, dbtp)) != 0) + goto err; + + return (0); + +err: __db_errx(env, DB_STR_A("3016", + "%s: %s failed for page %lu", "%s %s %lu"), __memp_fn(dbmfp), + is_pgin ? DB_STR_P("pgin") : DB_STR_P("pgout"), (u_long)pgno); + return (ret); +} + +/* + * __memp_bhfree -- + * Free a bucket header and its referenced data. + * + * PUBLIC: int __memp_bhfree __P((DB_MPOOL *, + * PUBLIC: REGINFO *, MPOOLFILE *, DB_MPOOL_HASH *, BH *, u_int32_t)); + */ +int +__memp_bhfree(dbmp, infop, mfp, hp, bhp, flags) + DB_MPOOL *dbmp; + REGINFO *infop; + MPOOLFILE *mfp; + DB_MPOOL_HASH *hp; + BH *bhp; + u_int32_t flags; +{ + ENV *env; +#ifdef DIAGNOSTIC + DB_LSN vlsn; +#endif + BH *prev_bhp; + MPOOL *c_mp; + int ret, t_ret; +#ifdef DIAG_MVCC + size_t pagesize; +#endif + + ret = 0; + + /* + * Assumes the hash bucket is locked and the MPOOL is not. + */ + env = dbmp->env; +#ifdef DIAG_MVCC + if (mfp != NULL) + pagesize = mfp->pagesize; +#endif + + DB_ASSERT(env, LF_ISSET(BH_FREE_UNLOCKED) || + (hp != NULL && MUTEX_IS_OWNED(env, hp->mtx_hash))); + DB_ASSERT(env, BH_REFCOUNT(bhp) == 1 && + !F_ISSET(bhp, BH_DIRTY | BH_FROZEN)); + DB_ASSERT(env, LF_ISSET(BH_FREE_UNLOCKED) || + SH_CHAIN_SINGLETON(bhp, vc) || (SH_CHAIN_HASNEXT(bhp, vc) && + (SH_CHAIN_NEXTP(bhp, vc, __bh)->td_off == bhp->td_off || + bhp->td_off == INVALID_ROFF || + IS_MAX_LSN(*VISIBLE_LSN(env, bhp)) || + BH_OBSOLETE(bhp, hp->old_reader, vlsn)))); + + PERFMON3(env, mpool, evict, __memp_fns(dbmp, mfp), bhp->pgno, bhp); + + /* + * Delete the buffer header from the hash bucket queue or the + * version chain. + */ + if (hp == NULL) + goto no_hp; + prev_bhp = SH_CHAIN_PREV(bhp, vc, __bh); + if (!SH_CHAIN_HASNEXT(bhp, vc)) { + if (prev_bhp != NULL) + SH_TAILQ_INSERT_AFTER(&hp->hash_bucket, + bhp, prev_bhp, hq, __bh); + SH_TAILQ_REMOVE(&hp->hash_bucket, bhp, hq, __bh); + } + SH_CHAIN_REMOVE(bhp, vc, __bh); + + /* + * Remove the reference to this buffer from the transaction that + * created it, if any. When the BH_FREE_UNLOCKED flag is set, we're + * discarding the environment, so the transaction region is already + * gone. + */ + if (bhp->td_off != INVALID_ROFF && !LF_ISSET(BH_FREE_UNLOCKED)) { + ret = __txn_remove_buffer( + env, BH_OWNER(env, bhp), hp->mtx_hash); + bhp->td_off = INVALID_ROFF; + } + + /* + * We're going to use the memory for something else -- it had better be + * accessible. + */ +no_hp: if (mfp != NULL) + MVCC_MPROTECT(bhp->buf, + pagesize, PROT_READ | PROT_WRITE | PROT_EXEC); + + /* + * Discard the hash bucket's mutex, it's no longer needed, and + * we don't want to be holding it when acquiring other locks. + */ + if (!LF_ISSET(BH_FREE_UNLOCKED)) + MUTEX_UNLOCK(env, hp->mtx_hash); + + /* + * If we're only removing this header from the chain for reuse, we're + * done. + */ + if (LF_ISSET(BH_FREE_REUSE)) + return (ret); + + /* + * If we're not reusing the buffer immediately, free the buffer for + * real. + */ + if (!LF_ISSET(BH_FREE_UNLOCKED)) + MUTEX_UNLOCK(env, bhp->mtx_buf); + if (LF_ISSET(BH_FREE_FREEMEM)) { + if ((ret = __mutex_free(env, &bhp->mtx_buf)) != 0) + return (ret); + MPOOL_REGION_LOCK(env, infop); + + MVCC_BHUNALIGN(bhp); + __memp_free(infop, bhp); + c_mp = infop->primary; + c_mp->pages--; + + MPOOL_REGION_UNLOCK(env, infop); + } + + if (mfp == NULL) + return (ret); + + /* + * Decrement the reference count of the underlying MPOOLFILE. + * If this is its last reference, remove it. + */ + MUTEX_LOCK(env, mfp->mutex); + if (--mfp->block_cnt == 0 && mfp->mpf_cnt == 0) { + if ((t_ret = __memp_mf_discard(dbmp, mfp, 0)) != 0 && ret == 0) + ret = t_ret; + } else + MUTEX_UNLOCK(env, mfp->mutex); + +#ifdef DIAGNOSTIC + COMPQUIET(vlsn.file, 0); +#endif + + return (ret); +} diff -r 000000000000 -r a1985f14b030 src/mp/mp_fget.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/mp/mp_fget.c Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,1223 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 1996, 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + * $Id$ + */ + +#include "db_config.h" + +#include "db_int.h" +#include "dbinc/log.h" +#include "dbinc/mp.h" +#include "dbinc/txn.h" +#ifdef DIAGNOSTIC +#include "dbinc/db_page.h" +#include "dbinc/db_am.h" +#include "dbinc/lock.h" +#endif + +/* + * __memp_fget_pp -- + * DB_MPOOLFILE->get pre/post processing. + * + * PUBLIC: int __memp_fget_pp + * PUBLIC: __P((DB_MPOOLFILE *, db_pgno_t *, DB_TXN *, u_int32_t, void *)); + */ +int +__memp_fget_pp(dbmfp, pgnoaddr, txnp, flags, addrp) + DB_MPOOLFILE *dbmfp; + db_pgno_t *pgnoaddr; + DB_TXN *txnp; + u_int32_t flags; + void *addrp; +{ + DB_THREAD_INFO *ip; + ENV *env; + int rep_blocked, ret; + + env = dbmfp->env; + + MPF_ILLEGAL_BEFORE_OPEN(dbmfp, "DB_MPOOLFILE->get"); + + /* + * Validate arguments. + * + * !!! + * Don't test for DB_MPOOL_CREATE and DB_MPOOL_NEW flags for readonly + * files here, and create non-existent pages in readonly files if the + * flags are set, later. The reason is that the hash access method + * wants to get empty pages that don't really exist in readonly files. + * The only alternative is for hash to write the last "bucket" all the + * time, which we don't want to do because one of our big goals in life + * is to keep database files small. It's sleazy as hell, but we catch + * any attempt to actually write the file in memp_fput(). + */ +#undef OKFLAGS +#define OKFLAGS (DB_MPOOL_CREATE | DB_MPOOL_DIRTY | \ + DB_MPOOL_EDIT | DB_MPOOL_LAST | DB_MPOOL_NEW) + if (flags != 0) { + if ((ret = __db_fchk(env, "memp_fget", flags, OKFLAGS)) != 0) + return (ret); + + switch (FLD_CLR(flags, DB_MPOOL_DIRTY | DB_MPOOL_EDIT)) { + case DB_MPOOL_CREATE: + case DB_MPOOL_LAST: + case DB_MPOOL_NEW: + case 0: + break; + default: + return (__db_ferr(env, "memp_fget", 1)); + } + } + + ENV_ENTER(env, ip); + + rep_blocked = 0; + if (txnp == NULL && IS_ENV_REPLICATED(env)) { + if ((ret = __op_rep_enter(env, 0, 1)) != 0) + goto err; + rep_blocked = 1; + } + ret = __memp_fget(dbmfp, pgnoaddr, ip, txnp, flags, addrp); + /* + * We only decrement the count in op_rep_exit if the operation fails. + * Otherwise the count will be decremented when the page is no longer + * pinned in memp_fput. + */ + if (ret != 0 && rep_blocked) + (void)__op_rep_exit(env); + + /* Similarly if an app has a page pinned it is ACTIVE. */ +err: if (ret != 0) + ENV_LEAVE(env, ip); + + return (ret); +} + +/* + * __memp_fget -- + * Get a page from the file. + * + * PUBLIC: int __memp_fget __P((DB_MPOOLFILE *, + * PUBLIC: db_pgno_t *, DB_THREAD_INFO *, DB_TXN *, u_int32_t, void *)); + */ +int +__memp_fget(dbmfp, pgnoaddr, ip, txn, flags, addrp) + DB_MPOOLFILE *dbmfp; + db_pgno_t *pgnoaddr; + DB_THREAD_INFO *ip; + DB_TXN *txn; + u_int32_t flags; + void *addrp; +{ + enum { FIRST_FOUND, FIRST_MISS, SECOND_FOUND, SECOND_MISS } state; + BH *alloc_bhp, *bhp, *oldest_bhp; + ENV *env; + DB_LSN *read_lsnp, vlsn; + DB_MPOOL *dbmp; + DB_MPOOL_HASH *hp; + MPOOL *c_mp; + MPOOLFILE *mfp; + PIN_LIST *list, *lp; + REGENV *renv; + REGINFO *infop, *t_infop, *reginfo; + TXN_DETAIL *td; + roff_t list_off, mf_offset; + u_int32_t bucket, pinmax, st_hsearch; + int b_incr, b_lock, h_locked, dirty, extending; + int makecopy, mvcc, need_free, ret; +#ifdef DIAGNOSTIC + DB_LOCKTAB *lt; + DB_LOCKER *locker; +#endif + + *(void **)addrp = NULL; + COMPQUIET(c_mp, NULL); + COMPQUIET(infop, NULL); + COMPQUIET(vlsn.file, 0); + + env = dbmfp->env; + dbmp = env->mp_handle; + + mfp = dbmfp->mfp; + mvcc = atomic_read(&mfp->multiversion) && (txn != NULL); + mf_offset = R_OFFSET(dbmp->reginfo, mfp); + alloc_bhp = bhp = oldest_bhp = NULL; + read_lsnp = NULL; + td = NULL; + hp = NULL; + b_incr = b_lock = h_locked = extending = makecopy = ret = 0; + + if (LF_ISSET(DB_MPOOL_DIRTY)) { + if (F_ISSET(dbmfp, MP_READONLY)) { + __db_errx(env, DB_STR_A("3021", + "%s: dirty flag set for readonly file page", + "%s"), __memp_fn(dbmfp)); + return (EINVAL); + } + if ((ret = __db_fcchk(env, "DB_MPOOLFILE->get", + flags, DB_MPOOL_DIRTY, DB_MPOOL_EDIT)) != 0) + return (ret); + } + + dirty = LF_ISSET(DB_MPOOL_DIRTY | DB_MPOOL_EDIT | DB_MPOOL_FREE); + LF_CLR(DB_MPOOL_DIRTY | DB_MPOOL_EDIT); + +#ifdef HAVE_TRANSACTIONS + /* + * If the transaction is being used to update a multiversion database + * for the first time, set the read LSN. In addition, if this is an + * update, allocate a mutex. If no transaction has been supplied, that + * will be caught later, when we know whether one is required. + */ + if (mvcc && txn != NULL && txn->td != NULL) { + /* We're only interested in the ultimate parent transaction. */ + while (txn->parent != NULL) + txn = txn->parent; + td = (TXN_DETAIL *)txn->td; + if (F_ISSET(txn, TXN_SNAPSHOT)) { + read_lsnp = &td->read_lsn; + if (IS_MAX_LSN(*read_lsnp) && + (ret = __log_current_lsn_int(env, read_lsnp, + NULL, NULL)) != 0) + return (ret); + } + if ((dirty || LF_ISSET(DB_MPOOL_CREATE | DB_MPOOL_NEW)) && + td->mvcc_mtx == MUTEX_INVALID && (ret = + __mutex_alloc(env, MTX_TXN_MVCC, 0, &td->mvcc_mtx)) != 0) + return (ret); + } +#endif + + switch (flags) { + case DB_MPOOL_LAST: + /* Get the last page number in the file. */ + MUTEX_LOCK(env, mfp->mutex); + *pgnoaddr = mfp->last_pgno; + MUTEX_UNLOCK(env, mfp->mutex); + break; + case DB_MPOOL_NEW: + /* + * If always creating a page, skip the first search + * of the hash bucket. + */ + goto newpg; + case DB_MPOOL_CREATE: + default: + break; + } + + /* + * If mmap'ing the file and the page is not past the end of the file, + * just return a pointer. We can't use R_ADDR here: this is an offset + * into an mmap'd file, not a shared region, and doesn't change for + * private environments. + * + * The page may be past the end of the file, so check the page number + * argument against the original length of the file. If we previously + * returned pages past the original end of the file, last_pgno will + * have been updated to match the "new" end of the file, and checking + * against it would return pointers past the end of the mmap'd region. + * + * If another process has opened the file for writing since we mmap'd + * it, we will start playing the game by their rules, i.e. everything + * goes through the cache. All pages previously returned will be safe, + * as long as the correct locking protocol was observed. + * + * We don't discard the map because we don't know when all of the + * pages will have been discarded from the process' address space. + * It would be possible to do so by reference counting the open + * pages from the mmap, but it's unclear to me that it's worth it. + */ + if (dbmfp->addr != NULL && + F_ISSET(mfp, MP_CAN_MMAP) && *pgnoaddr <= mfp->orig_last_pgno) { + *(void **)addrp = (u_int8_t *)dbmfp->addr + + (*pgnoaddr * mfp->pagesize); + STAT_INC_VERB(env, + mpool, map, mfp->stat.st_map, __memp_fn(dbmfp), *pgnoaddr); + return (0); + } + + /* + * Determine the cache and hash bucket where this page lives and get + * local pointers to them. Reset on each pass through this code, the + * page number can change. + */ + MP_GET_BUCKET(env, mfp, *pgnoaddr, &infop, hp, bucket, ret); + if (ret != 0) + return (ret); + c_mp = infop->primary; + + if (0) { + /* if we search again, get an exclusive lock. */ +retry: MUTEX_LOCK(env, hp->mtx_hash); + } + + /* Search the hash chain for the page. */ + st_hsearch = 0; + h_locked = 1; + SH_TAILQ_FOREACH(bhp, &hp->hash_bucket, hq, __bh) { + ++st_hsearch; + if (bhp->pgno != *pgnoaddr || bhp->mf_offset != mf_offset) + continue; + + /* Snapshot reads -- get the version visible at read_lsn. */ + if (read_lsnp != NULL) { + while (bhp != NULL && + !BH_OWNED_BY(env, bhp, txn) && + !BH_VISIBLE(env, bhp, read_lsnp, vlsn)) + bhp = SH_CHAIN_PREV(bhp, vc, __bh); + + /* + * We can get a null bhp if we are looking for a + * page that was created after the transaction was + * started so its not visible (i.e. page added to + * the BTREE in a subsequent txn). + */ + if (bhp == NULL) { + ret = DB_PAGE_NOTFOUND; + goto err; + } + } + + makecopy = mvcc && dirty && !BH_OWNED_BY(env, bhp, txn); + + /* + * Increment the reference count. This signals that the + * buffer may not be discarded. We must drop the hash + * mutex before we lock the buffer mutex. + */ + if (BH_REFCOUNT(bhp) == UINT16_MAX) { + __db_errx(env, DB_STR_A("3022", + "%s: page %lu: reference count overflow", + "%s %lu"), __memp_fn(dbmfp), (u_long)bhp->pgno); + ret = __env_panic(env, EINVAL); + goto err; + } + atomic_inc(env, &bhp->ref); + b_incr = 1; + + /* + * Lock the buffer. If the page is being read in or modified it + * will be exclusively locked and we will block. + */ + MUTEX_UNLOCK(env, hp->mtx_hash); + h_locked = 0; + if (dirty || extending || makecopy || F_ISSET(bhp, BH_FROZEN)) { +xlatch: if (LF_ISSET(DB_MPOOL_TRY)) { + if ((ret = + MUTEX_TRYLOCK(env, bhp->mtx_buf)) != 0) + goto err; + } else + MUTEX_LOCK(env, bhp->mtx_buf); + F_SET(bhp, BH_EXCLUSIVE); + } else if (LF_ISSET(DB_MPOOL_TRY)) { + if ((ret = MUTEX_TRY_READLOCK(env, bhp->mtx_buf)) != 0) + goto err; + } else + MUTEX_READLOCK(env, bhp->mtx_buf); + +#ifdef HAVE_SHARED_LATCHES + /* + * If buffer is still in transit once we have a shared latch, + * upgrade to an exclusive latch. + */ + if (F_ISSET(bhp, BH_FREED | BH_TRASH) && + !F_ISSET(bhp, BH_EXCLUSIVE)) { + MUTEX_UNLOCK(env, bhp->mtx_buf); + goto xlatch; + } +#else + F_SET(bhp, BH_EXCLUSIVE); +#endif + b_lock = 1; + + /* + * If the buffer was frozen before we waited for any I/O to + * complete and is still frozen, we will need to thaw it. + * Otherwise, it was thawed while we waited, and we need to + * search again. + */ + if (F_ISSET(bhp, BH_THAWED)) { + need_free = (atomic_dec(env, &bhp->ref) == 0); + b_incr = 0; + MUTEX_UNLOCK(env, bhp->mtx_buf); + b_lock = 0; + if (need_free) { + MPOOL_REGION_LOCK(env, infop); + SH_TAILQ_INSERT_TAIL(&c_mp->free_frozen, + bhp, hq); + MPOOL_REGION_UNLOCK(env, infop); + } + bhp = NULL; + goto retry; + } + + /* + * If the buffer we wanted was frozen or thawed while we + * waited, we need to start again. That is indicated by + * a new buffer header in the version chain owned by the same + * transaction as the one we pinned. + * + * Also, if we're doing an unversioned read on a multiversion + * file, another thread may have dirtied this buffer while we + * swapped from the hash bucket lock to the buffer lock. + */ + if (SH_CHAIN_HASNEXT(bhp, vc) && + (SH_CHAIN_NEXTP(bhp, vc, __bh)->td_off == bhp->td_off || + (!dirty && read_lsnp == NULL))) { + DB_ASSERT(env, b_incr && BH_REFCOUNT(bhp) != 0); + atomic_dec(env, &bhp->ref); + b_incr = 0; + MUTEX_UNLOCK(env, bhp->mtx_buf); + b_lock = 0; + bhp = NULL; + goto retry; + } else if (dirty && SH_CHAIN_HASNEXT(bhp, vc)) { + ret = DB_LOCK_DEADLOCK; + goto err; + } else if (F_ISSET(bhp, BH_FREED) && flags != DB_MPOOL_CREATE && + flags != DB_MPOOL_NEW && flags != DB_MPOOL_FREE) { + ret = DB_PAGE_NOTFOUND; + goto err; + } + + /* Is it worthwhile to publish oh-so-frequent cache hits? */ + STAT_INC_VERB(env, mpool, hit, + mfp->stat.st_cache_hit, __memp_fn(dbmfp), *pgnoaddr); + break; + } + +#ifdef HAVE_STATISTICS + /* + * Update the hash bucket search statistics -- do now because our next + * search may be for a different bucket. Are these too frequent also? + */ + STAT_INC_VERB(env, mpool, hash_search, + c_mp->stat.st_hash_searches, __memp_fn(dbmfp), *pgnoaddr); + if (st_hsearch > c_mp->stat.st_hash_longest) + STAT_SET_VERB(env, mpool, hash_longest, + c_mp->stat.st_hash_longest, + st_hsearch, __memp_fn(dbmfp), *pgnoaddr); + STAT_ADJUST_VERB(env, mpool, hash_examined, c_mp->stat.st_hash_searches, + st_hsearch, __memp_fn(dbmfp), *pgnoaddr); +#endif + + /* + * There are 4 possible paths to this location: + * + * FIRST_MISS: + * Didn't find the page in the hash bucket on our first pass: + * bhp == NULL, alloc_bhp == NULL + * + * FIRST_FOUND: + * Found the page in the hash bucket on our first pass: + * bhp != NULL, alloc_bhp == NULL + * + * SECOND_FOUND: + * Didn't find the page in the hash bucket on the first pass, + * allocated space, and found the page in the hash bucket on + * our second pass: + * bhp != NULL, alloc_bhp != NULL + * + * SECOND_MISS: + * Didn't find the page in the hash bucket on the first pass, + * allocated space, and didn't find the page in the hash bucket + * on our second pass: + * bhp == NULL, alloc_bhp != NULL + */ + state = bhp == NULL ? + (alloc_bhp == NULL ? FIRST_MISS : SECOND_MISS) : + (alloc_bhp == NULL ? FIRST_FOUND : SECOND_FOUND); + + switch (state) { + case FIRST_FOUND: + /* + * If we are to free the buffer, then this had better be the + * only reference. If so, just free the buffer. If not, + * complain and get out. + */ + if (flags == DB_MPOOL_FREE) { +freebuf: MUTEX_LOCK(env, hp->mtx_hash); + h_locked = 1; + if (F_ISSET(bhp, BH_DIRTY)) { + F_CLR(bhp, BH_DIRTY | BH_DIRTY_CREATE); + DB_ASSERT(env, + atomic_read(&hp->hash_page_dirty) > 0); + atomic_dec(env, &hp->hash_page_dirty); + } + + /* + * If the buffer we found is already freed, we're done. + * If the ref count is not 1 then someone may be + * peeking at the buffer. We cannot free it until they + * determine that it is not what they want. Clear the + * buffer so that waiting threads get an empty page. + */ + if (F_ISSET(bhp, BH_FREED)) + goto done; + else if (BH_REFCOUNT(bhp) != 1 || + !SH_CHAIN_SINGLETON(bhp, vc)) { + /* + * Create an empty page in the chain for + * subsequent gets. Otherwise, a thread that + * re-creates this page while it is still in + * cache will see stale data. + */ + F_SET(bhp, BH_FREED); + F_CLR(bhp, BH_TRASH); +#ifdef HAVE_TRANSACTIONS + } else if (F_ISSET(bhp, BH_FROZEN)) { + /* + * Freeing a singleton frozen buffer: just free + * it. This call will release the hash bucket + * mutex. + */ + ret = + __memp_bh_thaw(dbmp, infop, hp, bhp, NULL); + bhp = NULL; + b_incr = b_lock = h_locked = 0; +#endif + } else { + ret = __memp_bhfree(dbmp, infop, mfp, + hp, bhp, BH_FREE_FREEMEM); + bhp = NULL; + b_incr = b_lock = h_locked = 0; + } + goto done; + } else if (F_ISSET(bhp, BH_FREED | BH_TRASH)) { +revive: if (F_ISSET(bhp, BH_FREED)) + makecopy = makecopy || + (mvcc && !BH_OWNED_BY(env, bhp, txn)) || + F_ISSET(bhp, BH_FROZEN); + if (flags == DB_MPOOL_CREATE) { + MUTEX_LOCK(env, mfp->mutex); + if (*pgnoaddr > mfp->last_pgno) + mfp->last_pgno = *pgnoaddr; + MUTEX_UNLOCK(env, mfp->mutex); + } + /* We can race with a thread trying to free this. */ + if (F_ISSET(bhp, BH_TRASH) && + *pgnoaddr <= mfp->last_pgno) + break; + + /* Otherwise this page does not currently exist. */ + if (flags != DB_MPOOL_CREATE && flags != DB_MPOOL_NEW) { + ret = DB_PAGE_NOTFOUND; + goto done; + } + } + if (mvcc) { + /* + * With multiversion databases, we might need to + * allocate a new buffer into which we can copy the one + * that we found. In that case, check the last buffer + * in the chain to see whether we can reuse an obsolete + * buffer. + * + * To provide snapshot isolation, we need to make sure + * that we've seen a buffer older than the oldest + * snapshot read LSN. + */ +reuse: if ((makecopy || F_ISSET(bhp, BH_FROZEN)) && + !h_locked) { + MUTEX_LOCK(env, hp->mtx_hash); + h_locked = 1; + } + if ((makecopy || F_ISSET(bhp, BH_FROZEN)) && + SH_CHAIN_HASPREV(bhp, vc)) { + oldest_bhp = SH_CHAIN_PREVP(bhp, vc, __bh); + while (SH_CHAIN_HASPREV(oldest_bhp, vc)) + oldest_bhp = SH_CHAIN_PREVP( + oldest_bhp, vc, __bh); + + if (BH_REFCOUNT(oldest_bhp) == 0 && + !BH_OBSOLETE( + oldest_bhp, hp->old_reader, vlsn) && + (ret = __txn_oldest_reader(env, + &hp->old_reader)) != 0) + goto err; + + if (BH_OBSOLETE( + oldest_bhp, hp->old_reader, vlsn) && + BH_REFCOUNT(oldest_bhp) == 0) { + DB_ASSERT(env, + !F_ISSET(oldest_bhp, BH_DIRTY)); + atomic_inc(env, &oldest_bhp->ref); + if (F_ISSET(oldest_bhp, BH_FROZEN)) { + /* + * This call will release the + * hash bucket mutex. + */ + ret = __memp_bh_thaw(dbmp, + infop, hp, oldest_bhp, + NULL); + h_locked = 0; + if (ret != 0) + goto err; + goto reuse; + } + if ((ret = __memp_bhfree(dbmp, + infop, mfp, hp, oldest_bhp, + BH_FREE_REUSE)) != 0) + goto err; + alloc_bhp = oldest_bhp; + h_locked = 0; + } + + DB_ASSERT(env, alloc_bhp == NULL || + !F_ISSET(alloc_bhp, BH_FROZEN)); + } + } + + /* We found the buffer or we're ready to copy -- we're done. */ + if (!(makecopy || F_ISSET(bhp, BH_FROZEN)) || alloc_bhp != NULL) + break; + + /* FALLTHROUGH */ + case FIRST_MISS: + /* + * We didn't find the buffer in our first check. Figure out + * if the page exists, and allocate structures so we can add + * the page to the buffer pool. + */ + if (h_locked) + MUTEX_UNLOCK(env, hp->mtx_hash); + h_locked = 0; + + /* + * The buffer is not in the pool, so we don't need to free it. + */ + if (LF_ISSET(DB_MPOOL_FREE) && + (bhp == NULL || F_ISSET(bhp, BH_FREED) || !makecopy)) + goto done; + + if (bhp != NULL) + goto alloc; + +newpg: /* + * If DB_MPOOL_NEW is set, we have to allocate a page number. + * If neither DB_MPOOL_CREATE or DB_MPOOL_NEW is set, then + * it's an error to try and get a page past the end of file. + */ + DB_ASSERT(env, !h_locked); + MUTEX_LOCK(env, mfp->mutex); + switch (flags) { + case DB_MPOOL_NEW: + extending = 1; + if (mfp->maxpgno != 0 && + mfp->last_pgno >= mfp->maxpgno) { + __db_errx(env, DB_STR_A("3023", + "%s: file limited to %lu pages", "%s %lu"), + __memp_fn(dbmfp), (u_long)mfp->maxpgno); + ret = ENOSPC; + } else + *pgnoaddr = mfp->last_pgno + 1; + break; + case DB_MPOOL_CREATE: + if (mfp->maxpgno != 0 && *pgnoaddr > mfp->maxpgno) { + __db_errx(env, DB_STR_A("3024", + "%s: file limited to %lu pages", "%s %lu"), + __memp_fn(dbmfp), (u_long)mfp->maxpgno); + ret = ENOSPC; + } else if (!extending) + extending = *pgnoaddr > mfp->last_pgno; + break; + default: + ret = *pgnoaddr > mfp->last_pgno ? DB_PAGE_NOTFOUND : 0; + break; + } + MUTEX_UNLOCK(env, mfp->mutex); + if (ret != 0) + goto err; + + /* + * !!! + * In the DB_MPOOL_NEW code path, hp, infop and c_mp have + * not yet been initialized. + */ + if (hp == NULL) { + MP_GET_BUCKET(env, + mfp, *pgnoaddr, &infop, hp, bucket, ret); + if (ret != 0) + goto err; + MUTEX_UNLOCK(env, hp->mtx_hash); + c_mp = infop->primary; + } + +alloc: /* Allocate a new buffer header and data space. */ + if (alloc_bhp == NULL && (ret = + __memp_alloc(dbmp, infop, mfp, 0, NULL, &alloc_bhp)) != 0) + goto err; + + /* Initialize enough so we can call __memp_bhfree. */ + alloc_bhp->flags = 0; + atomic_init(&alloc_bhp->ref, 1); +#ifdef DIAGNOSTIC + if ((uintptr_t)alloc_bhp->buf & (sizeof(size_t) - 1)) { + __db_errx(env, DB_STR("3025", + "DB_MPOOLFILE->get: buffer data is NOT size_t aligned")); + ret = __env_panic(env, EINVAL); + goto err; + } +#endif + + /* + * If we're doing copy-on-write, we will already have the + * buffer header. In that case, we don't need to search again. + */ + if (bhp != NULL) + break; + + /* + * If we are extending the file, we'll need the mfp lock + * again. + */ + if (extending) + MUTEX_LOCK(env, mfp->mutex); + + /* + * DB_MPOOL_NEW does not guarantee you a page unreferenced by + * any other thread of control. (That guarantee is interesting + * for DB_MPOOL_NEW, unlike DB_MPOOL_CREATE, because the caller + * did not specify the page number, and so, may reasonably not + * have any way to lock the page outside of mpool.) Regardless, + * if we allocate the page, and some other thread of control + * requests the page by number, we will not detect that and the + * thread of control that allocated using DB_MPOOL_NEW may not + * have a chance to initialize the page. (Note: we *could* + * detect this case if we set a flag in the buffer header which + * guaranteed that no gets of the page would succeed until the + * reference count went to 0, that is, until the creating page + * put the page.) What we do guarantee is that if two threads + * of control are both doing DB_MPOOL_NEW calls, they won't + * collide, that is, they won't both get the same page. + * + * There's a possibility that another thread allocated the page + * we were planning to allocate while we were off doing buffer + * allocation. We can do that by making sure the page number + * we were going to use is still available. If it's not, then + * we check to see if the next available page number hashes to + * the same mpool region as the old one -- if it does, we can + * continue, otherwise, we have to start over. + */ + if (flags == DB_MPOOL_NEW && *pgnoaddr != mfp->last_pgno + 1) { + *pgnoaddr = mfp->last_pgno + 1; + MP_GET_REGION(dbmfp, *pgnoaddr, &t_infop, ret); + if (ret != 0) + goto err; + if (t_infop != infop) { + /* + * flags == DB_MPOOL_NEW, so extending is set + * and we're holding the mfp locked. + */ + MUTEX_UNLOCK(env, mfp->mutex); + hp = NULL; + goto newpg; + } + } + + /* + * We released the mfp lock, so another thread might have + * extended the file. Update the last_pgno and initialize + * the file, as necessary, if we extended the file. + */ + if (extending) { + if (*pgnoaddr > mfp->last_pgno) + mfp->last_pgno = *pgnoaddr; + else + extending = 0; + MUTEX_UNLOCK(env, mfp->mutex); + if (ret != 0) + goto err; + } + goto retry; + case SECOND_FOUND: + /* + * We allocated buffer space for the requested page, but then + * found the page in the buffer cache on our second check. + * That's OK -- we can use the page we found in the pool, + * unless DB_MPOOL_NEW is set. If we're about to copy-on-write, + * this is exactly the situation we want. + * + * For multiversion files, we may have left some pages in cache + * beyond the end of a file after truncating. In that case, we + * would get to here with extending set. If so, we need to + * insert the new page in the version chain similar to when + * we copy on write. + */ + if (F_ISSET(bhp, BH_FREED) && + (flags == DB_MPOOL_NEW || flags == DB_MPOOL_CREATE)) + goto revive; + else if (flags == DB_MPOOL_FREE) + goto freebuf; + else if (makecopy || F_ISSET(bhp, BH_FROZEN)) + break; + + /* + * We can't use the page we found in the pool if DB_MPOOL_NEW + * was set. (For details, see the above comment beginning + * "DB_MPOOL_NEW does not guarantee you a page unreferenced by + * any other thread of control".) If DB_MPOOL_NEW is set, we + * release our pin on this particular buffer, and try to get + * another one. + */ + if (flags == DB_MPOOL_NEW) { + DB_ASSERT(env, b_incr && BH_REFCOUNT(bhp) != 0); + atomic_dec(env, &bhp->ref); + b_incr = 0; + if (F_ISSET(bhp, BH_EXCLUSIVE)) + F_CLR(bhp, BH_EXCLUSIVE); + MUTEX_UNLOCK(env, bhp->mtx_buf); + b_lock = 0; + bhp = NULL; + hp = NULL; + goto newpg; + } + + break; + case SECOND_MISS: + /* + * We allocated buffer space for the requested page, and found + * the page still missing on our second pass through the buffer + * cache. Instantiate the page. + */ + DB_ASSERT(env, alloc_bhp != NULL); + bhp = alloc_bhp; + alloc_bhp = NULL; + + /* + * Initialize all the BH and hash bucket fields so we can call + * __memp_bhfree if an error occurs. + * + * Append the buffer to the tail of the bucket list. + */ + bhp->priority = MPOOL_LRU_REDZONE; + bhp->pgno = *pgnoaddr; + bhp->mf_offset = mf_offset; + bhp->bucket = bucket; + bhp->region = (int)(infop - dbmp->reginfo); + bhp->td_off = INVALID_ROFF; + SH_CHAIN_INIT(bhp, vc); + bhp->flags = 0; + + /* + * Reference the buffer and lock exclusive. We either + * need to read the buffer or create it from scratch + * and don't want anyone looking at it till we do. + */ + MUTEX_LOCK(env, bhp->mtx_buf); + b_lock = 1; + F_SET(bhp, BH_EXCLUSIVE); + b_incr = 1; + + /* We created a new page, it starts dirty. */ + if (extending) { + atomic_inc(env, &hp->hash_page_dirty); + F_SET(bhp, BH_DIRTY | BH_DIRTY_CREATE); + } + + MUTEX_REQUIRED(env, hp->mtx_hash); + SH_TAILQ_INSERT_HEAD(&hp->hash_bucket, bhp, hq, __bh); + MUTEX_UNLOCK(env, hp->mtx_hash); + h_locked = 0; + + /* + * If we created the page, zero it out. If we didn't create + * the page, read from the backing file. + * + * !!! + * DB_MPOOL_NEW doesn't call the pgin function. + * + * If DB_MPOOL_CREATE is used, then the application's pgin + * function has to be able to handle pages of 0's -- if it + * uses DB_MPOOL_NEW, it can detect all of its page creates, + * and not bother. + * + * If we're running in diagnostic mode, smash any bytes on the + * page that are unknown quantities for the caller. + * + * Otherwise, read the page into memory, optionally creating it + * if DB_MPOOL_CREATE is set. + */ + if (extending) { + MVCC_MPROTECT(bhp->buf, mfp->pagesize, + PROT_READ | PROT_WRITE); + memset(bhp->buf, 0, + (mfp->clear_len == DB_CLEARLEN_NOTSET) ? + mfp->pagesize : mfp->clear_len); +#if defined(DIAGNOSTIC) || defined(UMRW) + if (mfp->clear_len != DB_CLEARLEN_NOTSET) + memset(bhp->buf + mfp->clear_len, CLEAR_BYTE, + mfp->pagesize - mfp->clear_len); +#endif + + if (flags == DB_MPOOL_CREATE && mfp->ftype != 0 && + (ret = __memp_pg(dbmfp, + bhp->pgno, bhp->buf, 1)) != 0) + goto err; + + STAT_INC_VERB(env, mpool, page_create, + mfp->stat.st_page_create, + __memp_fn(dbmfp), *pgnoaddr); + } else { + F_SET(bhp, BH_TRASH); + STAT_INC_VERB(env, mpool, miss, mfp->stat.st_cache_miss, + __memp_fn(dbmfp), *pgnoaddr); + } + + makecopy = mvcc && dirty && !extending; + + /* Increment buffer count referenced by MPOOLFILE. */ + MUTEX_LOCK(env, mfp->mutex); + ++mfp->block_cnt; + MUTEX_UNLOCK(env, mfp->mutex); + } + + DB_ASSERT(env, bhp != NULL && BH_REFCOUNT(bhp) != 0 && b_lock); + DB_ASSERT(env, !F_ISSET(bhp, BH_FROZEN) || !F_ISSET(bhp, BH_FREED) || + makecopy); + + /* + * BH_TRASH -- + * The buffer we found may need to be filled from the disk. + * + * It's possible for the read function to fail, which means we fail + * as well. Discard the buffer on failure unless another thread + * is waiting on our I/O to complete. It's OK to leave the buffer + * around, as the waiting thread will see the BH_TRASH flag set, + * and will also attempt to discard it. If there's a waiter, + * we need to decrement our reference count. + */ + if (F_ISSET(bhp, BH_TRASH) && + flags != DB_MPOOL_FREE && !F_ISSET(bhp, BH_FREED)) { + MVCC_MPROTECT(bhp->buf, mfp->pagesize, + PROT_READ | PROT_WRITE); + if ((ret = __memp_pgread(dbmfp, + bhp, LF_ISSET(DB_MPOOL_CREATE) ? 1 : 0)) != 0) + goto err; + DB_ASSERT(env, read_lsnp != NULL || !SH_CHAIN_HASNEXT(bhp, vc)); + } + + /* Copy-on-write. */ + if (makecopy) { + /* + * If we read a page from disk that we want to modify, we now + * need to make copy, so we now need to allocate another buffer + * to hold the new copy. + */ + if (alloc_bhp == NULL) + goto reuse; + + DB_ASSERT(env, bhp != NULL && alloc_bhp != bhp); + DB_ASSERT(env, bhp->td_off == INVALID_ROFF || + !IS_MAX_LSN(*VISIBLE_LSN(env, bhp)) || + (F_ISSET(bhp, BH_FREED) && F_ISSET(bhp, BH_FROZEN))); + DB_ASSERT(env, txn != NULL || + (F_ISSET(bhp, BH_FROZEN) && F_ISSET(bhp, BH_FREED))); + DB_ASSERT(env, (extending || flags == DB_MPOOL_FREE || + F_ISSET(bhp, BH_FREED)) || + !F_ISSET(bhp, BH_FROZEN | BH_TRASH)); + MUTEX_REQUIRED(env, bhp->mtx_buf); + + if (BH_REFCOUNT(bhp) == 1) + MVCC_MPROTECT(bhp->buf, mfp->pagesize, + PROT_READ); + + atomic_init(&alloc_bhp->ref, 1); + MUTEX_LOCK(env, alloc_bhp->mtx_buf); + alloc_bhp->priority = bhp->priority; + alloc_bhp->pgno = bhp->pgno; + alloc_bhp->bucket = bhp->bucket; + alloc_bhp->region = bhp->region; + alloc_bhp->mf_offset = bhp->mf_offset; + alloc_bhp->td_off = INVALID_ROFF; + if (txn == NULL) { + DB_ASSERT(env, + F_ISSET(bhp, BH_FROZEN) && F_ISSET(bhp, BH_FREED)); + if (bhp->td_off != INVALID_ROFF && (ret = + __memp_bh_settxn(dbmp, mfp, alloc_bhp, + BH_OWNER(env, bhp))) != 0) + goto err; + } else if ((ret = + __memp_bh_settxn(dbmp, mfp, alloc_bhp, td)) != 0) + goto err; + MVCC_MPROTECT(alloc_bhp->buf, mfp->pagesize, + PROT_READ | PROT_WRITE); + if (extending || + F_ISSET(bhp, BH_FREED) || flags == DB_MPOOL_FREE) { + memset(alloc_bhp->buf, 0, + (mfp->clear_len == DB_CLEARLEN_NOTSET) ? + mfp->pagesize : mfp->clear_len); +#if defined(DIAGNOSTIC) || defined(UMRW) + if (mfp->clear_len != DB_CLEARLEN_NOTSET) + memset(alloc_bhp->buf + mfp->clear_len, + CLEAR_BYTE, + mfp->pagesize - mfp->clear_len); +#endif + if (mfp->ftype != 0 && (ret = __memp_pg(dbmfp, + alloc_bhp->pgno, alloc_bhp->buf, 1)) != 0) + goto err; + } else + memcpy(alloc_bhp->buf, bhp->buf, mfp->pagesize); + MVCC_MPROTECT(alloc_bhp->buf, mfp->pagesize, 0); + + if (h_locked == 0) + MUTEX_LOCK(env, hp->mtx_hash); + MUTEX_REQUIRED(env, hp->mtx_hash); + h_locked = 1; + + alloc_bhp->flags = BH_EXCLUSIVE | + ((flags == DB_MPOOL_FREE) ? BH_FREED : + F_ISSET(bhp, BH_DIRTY | BH_DIRTY_CREATE)); + DB_ASSERT(env, flags != DB_MPOOL_FREE || + !F_ISSET(bhp, BH_DIRTY)); + F_CLR(bhp, BH_DIRTY | BH_DIRTY_CREATE); + DB_ASSERT(env, !SH_CHAIN_HASNEXT(bhp, vc)); + SH_CHAIN_INSERT_AFTER(bhp, alloc_bhp, vc, __bh); + SH_TAILQ_INSERT_BEFORE(&hp->hash_bucket, + bhp, alloc_bhp, hq, __bh); + SH_TAILQ_REMOVE(&hp->hash_bucket, bhp, hq, __bh); + MUTEX_UNLOCK(env, hp->mtx_hash); + h_locked = 0; + DB_ASSERT(env, b_incr && BH_REFCOUNT(bhp) > 0); + if (atomic_dec(env, &bhp->ref) == 0) { + bhp->priority = c_mp->lru_priority; + MVCC_MPROTECT(bhp->buf, mfp->pagesize, 0); + } + F_CLR(bhp, BH_EXCLUSIVE); + MUTEX_UNLOCK(env, bhp->mtx_buf); + + bhp = alloc_bhp; + DB_ASSERT(env, BH_REFCOUNT(bhp) > 0); + b_incr = 1; + MUTEX_REQUIRED(env, bhp->mtx_buf); + b_lock = 1; + + if (alloc_bhp != oldest_bhp) { + MUTEX_LOCK(env, mfp->mutex); + ++mfp->block_cnt; + MUTEX_UNLOCK(env, mfp->mutex); + } + + alloc_bhp = NULL; + } else if (mvcc && extending && + (ret = __memp_bh_settxn(dbmp, mfp, bhp, td)) != 0) + goto err; + + if (flags == DB_MPOOL_FREE) { + DB_ASSERT(env, !SH_CHAIN_HASNEXT(bhp, vc)); + /* If we have created an empty buffer, it is not returned. */ + if (!F_ISSET(bhp, BH_FREED)) + goto freebuf; + goto done; + } + + /* + * Free the allocated memory, we no longer need it. + */ + if (alloc_bhp != NULL) { + if ((ret = __memp_bhfree(dbmp, infop, NULL, + NULL, alloc_bhp, BH_FREE_FREEMEM | BH_FREE_UNLOCKED)) != 0) + goto err; + alloc_bhp = NULL; + } + + if (dirty || extending || + (F_ISSET(bhp, BH_FREED) && + (flags == DB_MPOOL_CREATE || flags == DB_MPOOL_NEW))) { + MUTEX_REQUIRED(env, bhp->mtx_buf); + if (F_ISSET(bhp, BH_FREED)) { + DB_ASSERT(env, bhp->pgno <= mfp->last_pgno); + memset(bhp->buf, 0, + (mfp->clear_len == DB_CLEARLEN_NOTSET) ? + mfp->pagesize : mfp->clear_len); + F_CLR(bhp, BH_FREED); + if (mfp->ftype != 0 && (ret = + __memp_pg(dbmfp, bhp->pgno, bhp->buf, 1)) != 0) + goto err; + } + if (!F_ISSET(bhp, BH_DIRTY)) { +#ifdef DIAGNOSTIC + MUTEX_LOCK(env, hp->mtx_hash); +#endif + DB_ASSERT(env, !SH_CHAIN_HASNEXT(bhp, vc)); + atomic_inc(env, &hp->hash_page_dirty); + F_SET(bhp, BH_DIRTY); +#ifdef DIAGNOSTIC + MUTEX_UNLOCK(env, hp->mtx_hash); +#endif + } + } else if (F_ISSET(bhp, BH_EXCLUSIVE)) { + F_CLR(bhp, BH_EXCLUSIVE); +#ifdef HAVE_SHARED_LATCHES + MUTEX_UNLOCK(env, bhp->mtx_buf); + MUTEX_READLOCK(env, bhp->mtx_buf); + /* + * If another thread has dirtied the page while we + * switched locks, we have to go through it all again. + */ + if (SH_CHAIN_HASNEXT(bhp, vc) && read_lsnp == NULL) { + atomic_dec(env, &bhp->ref); + b_incr = 0; + MUTEX_UNLOCK(env, bhp->mtx_buf); + b_lock = 0; + bhp = NULL; + goto retry; + } +#endif + } + + MVCC_MPROTECT(bhp->buf, mfp->pagesize, PROT_READ | + (dirty || extending || F_ISSET(bhp, BH_DIRTY) ? + PROT_WRITE : 0)); + +#ifdef DIAGNOSTIC + MUTEX_LOCK(env, hp->mtx_hash); + { + BH *next_bhp = SH_CHAIN_NEXT(bhp, vc, __bh); + + DB_ASSERT(env, !atomic_read(&mfp->multiversion) || read_lsnp != NULL || + next_bhp == NULL); + DB_ASSERT(env, !mvcc || read_lsnp == NULL || + bhp->td_off == INVALID_ROFF || BH_OWNED_BY(env, bhp, txn) || + (BH_VISIBLE(env, bhp, read_lsnp, vlsn) && + (next_bhp == NULL || F_ISSET(next_bhp, BH_FROZEN) || + (next_bhp->td_off != INVALID_ROFF && + (BH_OWNER(env, next_bhp)->status != TXN_COMMITTED || + IS_ZERO_LSN(BH_OWNER(env, next_bhp)->last_lsn) || + !BH_VISIBLE(env, next_bhp, read_lsnp, vlsn)))))); + } + MUTEX_UNLOCK(env, hp->mtx_hash); +#endif + + /* + * Record this pin for this thread. Holding the page pinned + * without recording the pin is ok since we do not recover from + * a death from within the library itself. + */ + if (ip != NULL) { + reginfo = env->reginfo; + if (ip->dbth_pincount == ip->dbth_pinmax) { + pinmax = ip->dbth_pinmax; + renv = reginfo->primary; + MUTEX_LOCK(env, renv->mtx_regenv); + if ((ret = __env_alloc(reginfo, + 2 * pinmax * sizeof(PIN_LIST), &list)) != 0) { + MUTEX_UNLOCK(env, renv->mtx_regenv); + goto err; + } + + memcpy(list, R_ADDR(reginfo, ip->dbth_pinlist), + pinmax * sizeof(PIN_LIST)); + memset(&list[pinmax], 0, pinmax * sizeof(PIN_LIST)); + list_off = R_OFFSET(reginfo, list); + list = R_ADDR(reginfo, ip->dbth_pinlist); + ip->dbth_pinmax = 2 * pinmax; + ip->dbth_pinlist = list_off; + if (list != ip->dbth_pinarray) + __env_alloc_free(reginfo, list); + MUTEX_UNLOCK(env, renv->mtx_regenv); + } + list = R_ADDR(reginfo, ip->dbth_pinlist); + for (lp = list; lp < &list[ip->dbth_pinmax]; lp++) + if (lp->b_ref == INVALID_ROFF) + break; + + ip->dbth_pincount++; + lp->b_ref = R_OFFSET(infop, bhp); + lp->region = (int)(infop - dbmp->reginfo); +#ifdef DIAGNOSTIC + if (dirty && ip->dbth_locker != INVALID_ROFF && + ip->dbth_check_off == 0) { + lt = env->lk_handle; + locker = (DB_LOCKER *) + (R_ADDR(<->reginfo, ip->dbth_locker)); + DB_ASSERT(env, __db_has_pagelock(env, locker, dbmfp, + (PAGE*)bhp->buf, DB_LOCK_WRITE) == 0); + } +#endif + + } + /* + * During recovery we can read past the end of the file. Also + * last_pgno is not versioned, so if this is an older version + * that is ok as well. + */ + DB_ASSERT(env, IS_RECOVERING(env) || + bhp->pgno <= mfp->last_pgno || !SH_CHAIN_SINGLETON(bhp, vc)); + +#ifdef DIAGNOSTIC + /* Update the file's pinned reference count. */ + MPOOL_SYSTEM_LOCK(env); + ++dbmfp->pinref; + MPOOL_SYSTEM_UNLOCK(env); + + /* + * We want to switch threads as often as possible, and at awkward + * times. Yield every time we get a new page to ensure contention. + */ + if (F_ISSET(env->dbenv, DB_ENV_YIELDCPU)) + __os_yield(env, 0, 0); +#endif + + DB_ASSERT(env, alloc_bhp == NULL); + DB_ASSERT(env, !(dirty || extending) || + atomic_read(&hp->hash_page_dirty) > 0); + DB_ASSERT(env, BH_REFCOUNT(bhp) > 0 && + !F_ISSET(bhp, BH_FREED | BH_FROZEN | BH_TRASH)); + + *(void **)addrp = bhp->buf; + return (0); + +done: +err: /* + * We should only get to here with ret == 0 if freeing a buffer. + * In that case, check that it has in fact been freed. + */ + DB_ASSERT(env, ret != 0 || flags != DB_MPOOL_FREE || bhp == NULL || + (F_ISSET(bhp, BH_FREED) && !SH_CHAIN_HASNEXT(bhp, vc))); + + if (bhp != NULL) { + if (b_incr) + atomic_dec(env, &bhp->ref); + if (b_lock) { + F_CLR(bhp, BH_EXCLUSIVE); + MUTEX_UNLOCK(env, bhp->mtx_buf); + } + } + + if (h_locked) + MUTEX_UNLOCK(env, hp->mtx_hash); + + /* If alloc_bhp is set, free the memory. */ + if (alloc_bhp != NULL) + (void)__memp_bhfree(dbmp, infop, NULL, + NULL, alloc_bhp, BH_FREE_FREEMEM | BH_FREE_UNLOCKED); + + return (ret); +} diff -r 000000000000 -r a1985f14b030 src/mp/mp_fmethod.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/mp/mp_fmethod.c Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,611 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 1996, 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + * $Id$ + */ + +#include "db_config.h" + +#include "db_int.h" +#include "dbinc/log.h" +#include "dbinc/mp.h" + +static int __memp_get_clear_len __P((DB_MPOOLFILE *, u_int32_t *)); +static int __memp_get_lsn_offset __P((DB_MPOOLFILE *, int32_t *)); +static int __memp_get_maxsize __P((DB_MPOOLFILE *, u_int32_t *, u_int32_t *)); +static int __memp_set_maxsize __P((DB_MPOOLFILE *, u_int32_t, u_int32_t)); +static int __memp_set_priority __P((DB_MPOOLFILE *, DB_CACHE_PRIORITY)); +static int __memp_get_last_pgno_pp __P((DB_MPOOLFILE *, db_pgno_t *)); + +/* + * __memp_fcreate_pp -- + * ENV->memp_fcreate pre/post processing. + * + * PUBLIC: int __memp_fcreate_pp __P((DB_ENV *, DB_MPOOLFILE **, u_int32_t)); + */ +int +__memp_fcreate_pp(dbenv, retp, flags) + DB_ENV *dbenv; + DB_MPOOLFILE **retp; + u_int32_t flags; +{ + DB_THREAD_INFO *ip; + ENV *env; + int ret; + + env = dbenv->env; + + /* Validate arguments. */ + if ((ret = + __db_fchk(env, "DB_ENV->memp_fcreate", flags, DB_VERIFY)) != 0) + return (ret); + + /* We look the other way on mpool operations if we're verifying. */ + if (REP_ON(env) && !LF_ISSET(DB_VERIFY)) { + __db_errx(env, DB_STR("3029", +"DB_ENV->memp_fcreate: method not permitted when replication is configured")); + return (EINVAL); + } + + ENV_ENTER(env, ip); + ret = __memp_fcreate(env, retp); + ENV_LEAVE(env, ip); + return (ret); +} + +/* + * __memp_fcreate -- + * ENV->memp_fcreate. + * + * PUBLIC: int __memp_fcreate __P((ENV *, DB_MPOOLFILE **)); + */ +int +__memp_fcreate(env, retp) + ENV *env; + DB_MPOOLFILE **retp; +{ + DB_MPOOLFILE *dbmfp; + int ret; + + /* Allocate and initialize the per-process structure. */ + if ((ret = __os_calloc(env, 1, sizeof(DB_MPOOLFILE), &dbmfp)) != 0) + return (ret); + + dbmfp->ref = 1; + dbmfp->lsn_offset = DB_LSN_OFF_NOTSET; + dbmfp->env = env; + dbmfp->mfp = INVALID_ROFF; + + dbmfp->close = __memp_fclose_pp; + dbmfp->get = __memp_fget_pp; + dbmfp->get_clear_len = __memp_get_clear_len; + dbmfp->get_fileid = __memp_get_fileid; + dbmfp->get_flags = __memp_get_flags; + dbmfp->get_ftype = __memp_get_ftype; + dbmfp->get_last_pgno = __memp_get_last_pgno_pp; + dbmfp->get_lsn_offset = __memp_get_lsn_offset; + dbmfp->get_maxsize = __memp_get_maxsize; + dbmfp->get_pgcookie = __memp_get_pgcookie; + dbmfp->get_priority = __memp_get_priority; + dbmfp->open = __memp_fopen_pp; + dbmfp->put = __memp_fput_pp; + dbmfp->set_clear_len = __memp_set_clear_len; + dbmfp->set_fileid = __memp_set_fileid; + dbmfp->set_flags = __memp_set_flags; + dbmfp->set_ftype = __memp_set_ftype; + dbmfp->set_lsn_offset = __memp_set_lsn_offset; + dbmfp->set_maxsize = __memp_set_maxsize; + dbmfp->set_pgcookie = __memp_set_pgcookie; + dbmfp->set_priority = __memp_set_priority; + dbmfp->sync = __memp_fsync_pp; + + *retp = dbmfp; + return (0); +} + +/* + * __memp_get_clear_len -- + * Get the clear length. + */ +static int +__memp_get_clear_len(dbmfp, clear_lenp) + DB_MPOOLFILE *dbmfp; + u_int32_t *clear_lenp; +{ + *clear_lenp = dbmfp->clear_len; + return (0); +} + +/* + * __memp_set_clear_len -- + * DB_MPOOLFILE->set_clear_len. + * + * PUBLIC: int __memp_set_clear_len __P((DB_MPOOLFILE *, u_int32_t)); + */ +int +__memp_set_clear_len(dbmfp, clear_len) + DB_MPOOLFILE *dbmfp; + u_int32_t clear_len; +{ + MPF_ILLEGAL_AFTER_OPEN(dbmfp, "DB_MPOOLFILE->set_clear_len"); + + dbmfp->clear_len = clear_len; + return (0); +} + +/* + * __memp_get_fileid -- + * DB_MPOOLFILE->get_fileid. + * + * PUBLIC: int __memp_get_fileid __P((DB_MPOOLFILE *, u_int8_t *)); + */ +int +__memp_get_fileid(dbmfp, fileid) + DB_MPOOLFILE *dbmfp; + u_int8_t *fileid; +{ + if (!F_ISSET(dbmfp, MP_FILEID_SET)) { + __db_errx(dbmfp->env, DB_STR("3030", + "get_fileid: file ID not set")); + return (EINVAL); + } + + memcpy(fileid, dbmfp->fileid, DB_FILE_ID_LEN); + return (0); +} + +/* + * __memp_set_fileid -- + * DB_MPOOLFILE->set_fileid. + * + * PUBLIC: int __memp_set_fileid __P((DB_MPOOLFILE *, u_int8_t *)); + */ +int +__memp_set_fileid(dbmfp, fileid) + DB_MPOOLFILE *dbmfp; + u_int8_t *fileid; +{ + MPF_ILLEGAL_AFTER_OPEN(dbmfp, "DB_MPOOLFILE->set_fileid"); + + memcpy(dbmfp->fileid, fileid, DB_FILE_ID_LEN); + F_SET(dbmfp, MP_FILEID_SET); + + return (0); +} + +/* + * __memp_get_flags -- + * Get the DB_MPOOLFILE flags; + * + * PUBLIC: int __memp_get_flags __P((DB_MPOOLFILE *, u_int32_t *)); + */ +int +__memp_get_flags(dbmfp, flagsp) + DB_MPOOLFILE *dbmfp; + u_int32_t *flagsp; +{ + MPOOLFILE *mfp; + + mfp = dbmfp->mfp; + + *flagsp = 0; + + if (mfp == NULL) + *flagsp = FLD_ISSET(dbmfp->config_flags, + DB_MPOOL_NOFILE | DB_MPOOL_UNLINK); + else { + if (mfp->no_backing_file) + FLD_SET(*flagsp, DB_MPOOL_NOFILE); + if (mfp->unlink_on_close) + FLD_SET(*flagsp, DB_MPOOL_UNLINK); + } + return (0); +} + +/* + * __memp_set_flags -- + * Set the DB_MPOOLFILE flags; + * + * PUBLIC: int __memp_set_flags __P((DB_MPOOLFILE *, u_int32_t, int)); + */ +int +__memp_set_flags(dbmfp, flags, onoff) + DB_MPOOLFILE *dbmfp; + u_int32_t flags; + int onoff; +{ + ENV *env; + MPOOLFILE *mfp; + int ret; + + env = dbmfp->env; + mfp = dbmfp->mfp; + + switch (flags) { + case DB_MPOOL_NOFILE: + if (mfp == NULL) + if (onoff) + FLD_SET(dbmfp->config_flags, DB_MPOOL_NOFILE); + else + FLD_CLR(dbmfp->config_flags, DB_MPOOL_NOFILE); + else + mfp->no_backing_file = onoff; + break; + case DB_MPOOL_UNLINK: + if (mfp == NULL) + if (onoff) + FLD_SET(dbmfp->config_flags, DB_MPOOL_UNLINK); + else + FLD_CLR(dbmfp->config_flags, DB_MPOOL_UNLINK); + else + mfp->unlink_on_close = onoff; + break; + default: + if ((ret = __db_fchk(env, "DB_MPOOLFILE->set_flags", + flags, DB_MPOOL_NOFILE | DB_MPOOL_UNLINK)) != 0) + return (ret); + break; + } + return (0); +} + +/* + * __memp_get_ftype -- + * Get the file type (as registered). + * + * PUBLIC: int __memp_get_ftype __P((DB_MPOOLFILE *, int *)); + */ +int +__memp_get_ftype(dbmfp, ftypep) + DB_MPOOLFILE *dbmfp; + int *ftypep; +{ + *ftypep = dbmfp->ftype; + return (0); +} + +/* + * __memp_set_ftype -- + * DB_MPOOLFILE->set_ftype. + * + * PUBLIC: int __memp_set_ftype __P((DB_MPOOLFILE *, int)); + */ +int +__memp_set_ftype(dbmfp, ftype) + DB_MPOOLFILE *dbmfp; + int ftype; +{ + MPF_ILLEGAL_AFTER_OPEN(dbmfp, "DB_MPOOLFILE->set_ftype"); + + dbmfp->ftype = ftype; + return (0); +} + +/* + * __memp_get_lsn_offset -- + * Get the page's LSN offset. + */ +static int +__memp_get_lsn_offset(dbmfp, lsn_offsetp) + DB_MPOOLFILE *dbmfp; + int32_t *lsn_offsetp; +{ + *lsn_offsetp = dbmfp->lsn_offset; + return (0); +} + +/* + * __memp_set_lsn_offset -- + * Set the page's LSN offset. + * + * PUBLIC: int __memp_set_lsn_offset __P((DB_MPOOLFILE *, int32_t)); + */ +int +__memp_set_lsn_offset(dbmfp, lsn_offset) + DB_MPOOLFILE *dbmfp; + int32_t lsn_offset; +{ + MPF_ILLEGAL_AFTER_OPEN(dbmfp, "DB_MPOOLFILE->set_lsn_offset"); + + dbmfp->lsn_offset = lsn_offset; + return (0); +} + +/* + * __memp_get_maxsize -- + * Get the file's maximum size. + */ +static int +__memp_get_maxsize(dbmfp, gbytesp, bytesp) + DB_MPOOLFILE *dbmfp; + u_int32_t *gbytesp, *bytesp; +{ + DB_THREAD_INFO *ip; + ENV *env; + MPOOLFILE *mfp; + + if ((mfp = dbmfp->mfp) == NULL) { + *gbytesp = dbmfp->gbytes; + *bytesp = dbmfp->bytes; + } else { + env = dbmfp->env; + ENV_ENTER(env, ip); + + MUTEX_LOCK(env, mfp->mutex); + *gbytesp = (u_int32_t) + (mfp->maxpgno / (GIGABYTE / mfp->pagesize)); + *bytesp = (u_int32_t) + ((mfp->maxpgno % (GIGABYTE / mfp->pagesize)) * + mfp->pagesize); + MUTEX_UNLOCK(env, mfp->mutex); + + ENV_LEAVE(env, ip); + } + + return (0); +} + +/* + * __memp_set_maxsize -- + * Set the file's maximum size. + */ +static int +__memp_set_maxsize(dbmfp, gbytes, bytes) + DB_MPOOLFILE *dbmfp; + u_int32_t gbytes, bytes; +{ + DB_THREAD_INFO *ip; + ENV *env; + MPOOLFILE *mfp; + + if ((mfp = dbmfp->mfp) == NULL) { + dbmfp->gbytes = gbytes; + dbmfp->bytes = bytes; + } else { + env = dbmfp->env; + ENV_ENTER(env, ip); + + MUTEX_LOCK(env, mfp->mutex); + mfp->maxpgno = (db_pgno_t) + (gbytes * (GIGABYTE / mfp->pagesize)); + mfp->maxpgno += (db_pgno_t) + ((bytes + mfp->pagesize - 1) / mfp->pagesize); + MUTEX_UNLOCK(env, mfp->mutex); + + ENV_LEAVE(env, ip); + } + + return (0); +} + +/* + * __memp_get_pgcookie -- + * Get the pgin/pgout cookie. + * + * PUBLIC: int __memp_get_pgcookie __P((DB_MPOOLFILE *, DBT *)); + */ +int +__memp_get_pgcookie(dbmfp, pgcookie) + DB_MPOOLFILE *dbmfp; + DBT *pgcookie; +{ + if (dbmfp->pgcookie == NULL) { + pgcookie->size = 0; + pgcookie->data = ""; + } else + memcpy(pgcookie, dbmfp->pgcookie, sizeof(DBT)); + return (0); +} + +/* + * __memp_set_pgcookie -- + * Set the pgin/pgout cookie. + * + * PUBLIC: int __memp_set_pgcookie __P((DB_MPOOLFILE *, DBT *)); + */ +int +__memp_set_pgcookie(dbmfp, pgcookie) + DB_MPOOLFILE *dbmfp; + DBT *pgcookie; +{ + DBT *cookie; + ENV *env; + int ret; + + MPF_ILLEGAL_AFTER_OPEN(dbmfp, "DB_MPOOLFILE->set_pgcookie"); + env = dbmfp->env; + + if ((ret = __os_calloc(env, 1, sizeof(*cookie), &cookie)) != 0) + return (ret); + if ((ret = __os_malloc(env, pgcookie->size, &cookie->data)) != 0) { + __os_free(env, cookie); + return (ret); + } + + memcpy(cookie->data, pgcookie->data, pgcookie->size); + cookie->size = pgcookie->size; + + dbmfp->pgcookie = cookie; + return (0); +} + +/* + * __memp_get_priority -- + * Set the cache priority for pages from this file. + * + * PUBLIC: int __memp_get_priority __P((DB_MPOOLFILE *, DB_CACHE_PRIORITY *)); + */ +int +__memp_get_priority(dbmfp, priorityp) + DB_MPOOLFILE *dbmfp; + DB_CACHE_PRIORITY *priorityp; +{ + switch (dbmfp->priority) { + case MPOOL_PRI_VERY_LOW: + *priorityp = DB_PRIORITY_VERY_LOW; + break; + case MPOOL_PRI_LOW: + *priorityp = DB_PRIORITY_LOW; + break; + case MPOOL_PRI_DEFAULT: + *priorityp = DB_PRIORITY_DEFAULT; + break; + case MPOOL_PRI_HIGH: + *priorityp = DB_PRIORITY_HIGH; + break; + case MPOOL_PRI_VERY_HIGH: + *priorityp = DB_PRIORITY_VERY_HIGH; + break; + default: + __db_errx(dbmfp->env, DB_STR_A("3031", + "DB_MPOOLFILE->get_priority: unknown priority value: %d", + "%d"), dbmfp->priority); + return (EINVAL); + } + + return (0); +} + +/* + * __memp_set_priority -- + * Set the cache priority for pages from this file. + */ +static int +__memp_set_priority(dbmfp, priority) + DB_MPOOLFILE *dbmfp; + DB_CACHE_PRIORITY priority; +{ + switch (priority) { + case DB_PRIORITY_VERY_LOW: + dbmfp->priority = MPOOL_PRI_VERY_LOW; + break; + case DB_PRIORITY_LOW: + dbmfp->priority = MPOOL_PRI_LOW; + break; + case DB_PRIORITY_DEFAULT: + dbmfp->priority = MPOOL_PRI_DEFAULT; + break; + case DB_PRIORITY_HIGH: + dbmfp->priority = MPOOL_PRI_HIGH; + break; + case DB_PRIORITY_VERY_HIGH: + dbmfp->priority = MPOOL_PRI_VERY_HIGH; + break; + default: + __db_errx(dbmfp->env, DB_STR_A("3032", + "DB_MPOOLFILE->set_priority: unknown priority value: %d", + "%d"), priority); + return (EINVAL); + } + + /* Update the underlying file if we've already opened it. */ + if (dbmfp->mfp != NULL) + dbmfp->mfp->priority = dbmfp->priority; + + return (0); +} + +/* + * __memp_get_last_pgno -- + * Return the page number of the last page in the file. + * + * !!! + * The method is undocumented, but the handle is exported, users occasionally + * ask for it. + * + * PUBLIC: int __memp_get_last_pgno __P((DB_MPOOLFILE *, db_pgno_t *)); + */ +int +__memp_get_last_pgno(dbmfp, pgnoaddr) + DB_MPOOLFILE *dbmfp; + db_pgno_t *pgnoaddr; +{ + ENV *env; + MPOOLFILE *mfp; + + env = dbmfp->env; + mfp = dbmfp->mfp; + + MUTEX_LOCK(env, mfp->mutex); + *pgnoaddr = mfp->last_pgno; + MUTEX_UNLOCK(env, mfp->mutex); + + return (0); +} + +/* + * __memp_get_last_pgno_pp -- + * pre/post processing for __memp_get_last_pgno. + * + */ +static int +__memp_get_last_pgno_pp(dbmfp, pgnoaddr) + DB_MPOOLFILE *dbmfp; + db_pgno_t *pgnoaddr; +{ + DB_THREAD_INFO *ip; + int ret; + + ret = 0; + ENV_ENTER(dbmfp->env, ip); + + ret = __memp_get_last_pgno(dbmfp, pgnoaddr); + + ENV_LEAVE(dbmfp->env, ip); + return (ret); +} + +/* + * __memp_fn -- + * On errors we print whatever is available as the file name. + * + * PUBLIC: char * __memp_fn __P((DB_MPOOLFILE *)); + */ +char * +__memp_fn(dbmfp) + DB_MPOOLFILE *dbmfp; +{ + return (__memp_fns(dbmfp->env->mp_handle, dbmfp->mfp)); +} + +/* + * __memp_fns -- + * On errors we print whatever is available as the file name. + * + * PUBLIC: char * __memp_fns __P((DB_MPOOL *, MPOOLFILE *)); + * + */ +char * +__memp_fns(dbmp, mfp) + DB_MPOOL *dbmp; + MPOOLFILE *mfp; +{ + if (mfp == NULL || mfp->path_off == 0) + return ((char *)"unknown"); + + return ((char *)R_ADDR(dbmp->reginfo, mfp->path_off)); +} diff -r 000000000000 -r a1985f14b030 src/mp/mp_fopen.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/mp/mp_fopen.c Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,1275 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 1996, 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + * $Id$ + */ + +#include "db_config.h" + +#include "db_int.h" +#include "dbinc/log.h" +#include "dbinc/mp.h" +#include "dbinc/db_page.h" +#include "dbinc/hash.h" + +static int __memp_mpf_alloc __P((DB_MPOOL *, + DB_MPOOLFILE *, const char *, u_int32_t, u_int32_t, MPOOLFILE **)); +static int __memp_mpf_find __P((ENV *, + DB_MPOOLFILE *, DB_MPOOL_HASH *, const char *, u_int32_t, MPOOLFILE **)); + +/* + * __memp_fopen_pp -- + * DB_MPOOLFILE->open pre/post processing. + * + * PUBLIC: int __memp_fopen_pp + * PUBLIC: __P((DB_MPOOLFILE *, const char *, u_int32_t, int, size_t)); + */ +int +__memp_fopen_pp(dbmfp, path, flags, mode, pagesize) + DB_MPOOLFILE *dbmfp; + const char *path; + u_int32_t flags; + int mode; + size_t pagesize; +{ + DB_THREAD_INFO *ip; + ENV *env; + int ret; + + env = dbmfp->env; + + /* Validate arguments. */ + if ((ret = __db_fchk(env, "DB_MPOOLFILE->open", flags, + DB_CREATE | DB_DIRECT | DB_EXTENT | DB_MULTIVERSION | + DB_NOMMAP | DB_ODDFILESIZE | DB_RDONLY | DB_TRUNCATE)) != 0) + return (ret); + + /* + * Require a power-of-two pagesize, smaller than the clear length. A + * non-zero page size is only allowed if opening an existing, in-memory + * db. + */ + if (!POWER_OF_TWO(pagesize) || + (pagesize == 0 && (LF_ISSET(DB_CREATE) || + !FLD_ISSET(dbmfp->config_flags, DB_MPOOL_NOFILE)))) { + __db_errx(env, DB_STR("3033", + "DB_MPOOLFILE->open: page sizes must be a power-of-2")); + return (EINVAL); + } + if (pagesize != 0 && dbmfp->clear_len > pagesize) { + __db_errx(env, DB_STR("3034", + "DB_MPOOLFILE->open: clear length larger than page size")); + return (EINVAL); + } + + /* Read-only checks, and local flag. */ + if (LF_ISSET(DB_RDONLY) && path == NULL) { + __db_errx(env, DB_STR("3035", + "DB_MPOOLFILE->open: temporary files can't be readonly")); + return (EINVAL); + } + + if (LF_ISSET(DB_MULTIVERSION) && !TXN_ON(env)) { + __db_errx(env, DB_STR("3036", + "DB_MPOOLFILE->open: DB_MULTIVERSION requires transactions")); + return (EINVAL); + } + + ENV_ENTER(env, ip); + REPLICATION_WRAP(env, + (__memp_fopen(dbmfp, NULL, + path, NULL, flags, mode, pagesize)), 0, ret); + ENV_LEAVE(env, ip); + return (ret); +} + +/* + * Generate the number of user opens. If there is no backing file + * there is an extra open count to keep the in memory db around. + */ +#define MFP_OPEN_CNT(mfp) ((mfp)->mpf_cnt - ((mfp)->neutral_cnt + \ + (u_int32_t)(mfp)->no_backing_file)) +#define MP_IOINFO_RETRIES 5 +/* + * __memp_fopen -- + * DB_MPOOLFILE->open. + * + * PUBLIC: int __memp_fopen __P((DB_MPOOLFILE *, MPOOLFILE *, + * PUBLIC: const char *, const char **, u_int32_t, int, size_t)); + */ +int +__memp_fopen(dbmfp, mfp, path, dirp, flags, mode, pgsize) + DB_MPOOLFILE *dbmfp; + MPOOLFILE *mfp; + const char *path; + const char **dirp; + u_int32_t flags; + int mode; + size_t pgsize; +{ + DB_ENV *dbenv; + DB_MPOOL *dbmp; + DB_MPOOLFILE *tmp_dbmfp; + DB_MPOOL_HASH *hp; + ENV *env; + MPOOL *mp; + MPOOLFILE *alloc_mfp; + size_t maxmap; + db_pgno_t last_pgno; + u_int32_t bucket, mbytes, bytes, oflags, pagesize; + int isdir, refinc, ret, tries; + char *rpath; + + /* If this handle is already open, return. */ + if (F_ISSET(dbmfp, MP_OPEN_CALLED)) + return (0); + + env = dbmfp->env; + dbmp = env->mp_handle; + dbenv = env->dbenv; + mp = dbmp->reginfo[0].primary; + alloc_mfp = NULL; + mbytes = bytes = 0; + refinc = ret = isdir = 0; + rpath = NULL; + + /* + * We're keeping the page size as a size_t in the public API, but + * it's a u_int32_t everywhere internally. + */ + pagesize = (u_int32_t)pgsize; + + /* + * We're called internally with a specified mfp, in which case the + * path is NULL, but we'll get the path from the underlying region + * information. Otherwise, if the path is NULL, it's a temporary + * file -- we know we can't join any existing files, and we'll delay + * the open until we actually need to write the file. All temporary + * files will go into the first hash bucket. + */ + DB_ASSERT(env, mfp == NULL || path == NULL); + + bucket = 0; + hp = R_ADDR(dbmp->reginfo, mp->ftab); + if (mfp == NULL) { + if (path == NULL) + goto alloc; + + /* + * If fileid is not set but the file exists on the disk, + * we try to use __os_fileid to set it. We do this + * because we want to use the fileid to check if we have + * opened the mpoolfile as early as possible. + * + * Note: DB layer always calls __memp_fopen with fileid set, + * so this is only for using mpool api to open a file. + */ + + if (!FLD_ISSET(dbmfp->config_flags, DB_MPOOL_NOFILE) && + !F_ISSET(dbmfp, MP_FILEID_SET)) { + if ((ret = __db_appname(env, + DB_APP_DATA, path, dirp, &rpath)) != 0) + goto err; + ret = __os_exists(env, rpath, &isdir); + if (ret == 0 && isdir) { + ret = EINVAL; + goto err; + } else if (ret == 0) { + if ((ret = __os_fileid(env, + rpath, 0, dbmfp->fileid)) != 0) + goto err; + F_SET(dbmfp, MP_FILEID_SET); + } + } + + /* + * Hash to the proper file table entry and walk it. + * + * The fileID is a filesystem unique number (e.g., a + * UNIX dev/inode pair) plus a timestamp. If files are + * removed and created in less than a second, the fileID + * can be repeated. The problem with repetition happens + * when the file that previously had the fileID value still + * has pages in the pool, since we don't want to use them + * to satisfy requests for the new file. Because the + * DB_TRUNCATE flag reuses the dev/inode pair, repeated + * opens with that flag set guarantees matching fileIDs + * when the machine can open a file and then re-open + * with truncate within a second. For this reason, we + * pass that flag down, and, if we find a matching entry, + * we ensure that it's never found again, and we create + * a new entry for the current request. + */ + if (FLD_ISSET(dbmfp->config_flags, DB_MPOOL_NOFILE) || + F_ISSET(dbmfp, MP_FILEID_SET)) { + if (FLD_ISSET(dbmfp->config_flags, DB_MPOOL_NOFILE)) + bucket = FNBUCKET(path, strlen(path)); + else + bucket = FNBUCKET(dbmfp->fileid, + DB_FILE_ID_LEN); + + hp += bucket; + /* + * If we find the MPOOLFILE and inc its ref count. + * That way it cannot go away while we open it. + */ + MUTEX_LOCK(env, hp->mtx_hash); + ret = + __memp_mpf_find(env, dbmfp, hp, path, flags, &mfp); + if (ret == 0 && mfp != NULL) { + refinc = 1; + + if (LF_ISSET(DB_MULTIVERSION)) { + if (MFP_OPEN_CNT(mfp) > (u_int32_t) + (LF_ISSET(DB_RDONLY) ? 0 : 1) && + atomic_read( + &mfp->multiversion) == 0) { + MUTEX_UNLOCK(env, hp->mtx_hash); + goto mvcc_err; + } + atomic_inc(env, &mfp->multiversion); + F_SET(dbmfp, MP_MULTIVERSION); + } + } + MUTEX_UNLOCK(env, hp->mtx_hash); + if (ret != 0) + goto err; + } + } else { + /* + * Deadfile can only be set if mpf_cnt goes to zero (or if we + * failed creating the file DB_AM_DISCARD). Increment the ref + * count so the file cannot become dead and be unlinked. + */ + MUTEX_LOCK(env, mfp->mutex); + if (!mfp->deadfile) { + if (LF_ISSET(DB_MULTIVERSION)) { + MUTEX_UNLOCK(env, mfp->mutex); + if (MFP_OPEN_CNT(mfp) > 0 && + atomic_read(&mfp->multiversion) == 0) { +mvcc_err: __db_errx(env, DB_STR("3041", +"DB_MULTIVERSION cannot be specified on a database file which is already open")); + ret = EINVAL; + goto err; + } + + atomic_inc(env, &mfp->multiversion); + F_SET(dbmfp, MP_MULTIVERSION); + } + /* + * Increment the reference count. We also track + * those references that don't effect the ability + * to convert the handle to either NOT_DURABLE or + * MVCC. These are readonly opens or threads that + * are using the handle just to flush a buffer. + */ + ++mfp->mpf_cnt; + if (LF_ISSET(DB_FLUSH | DB_RDONLY)) + ++mfp->neutral_cnt; + if (LF_ISSET(DB_FLUSH)) + F_SET(dbmfp, MP_FOR_FLUSH); + refinc = 1; + } + MUTEX_UNLOCK(env, mfp->mutex); + + /* + * Test one last time to see if the file is dead -- it may have + * been removed. This happens when a checkpoint trying to open + * the file to flush a buffer races with the Db::remove method. + * The error will be ignored, so don't output an error message. + */ + if (mfp->deadfile) { + ret = EINVAL; + goto err; + } + } + + if (LF_ISSET(DB_RDONLY)) + F_SET(dbmfp, MP_READONLY); + if (LF_ISSET(DB_FLUSH)) + F_SET(dbmfp, MP_FLUSH); + /* + * Share the underlying file descriptor if that's possible. + */ + if (mfp != NULL && !FLD_ISSET(dbmfp->config_flags, DB_MPOOL_NOFILE)) { + MUTEX_LOCK(env, dbmp->mutex); + TAILQ_FOREACH(tmp_dbmfp, &dbmp->dbmfq, q) + if (mfp == tmp_dbmfp->mfp && + (F_ISSET(dbmfp, MP_READONLY) || + !F_ISSET(tmp_dbmfp, MP_READONLY))) { + ++tmp_dbmfp->fhp->ref; + dbmfp->fhp = tmp_dbmfp->fhp; + dbmfp->addr = tmp_dbmfp->addr; + dbmfp->len = tmp_dbmfp->len; + break; + } + MUTEX_UNLOCK(env, dbmp->mutex); + if (dbmfp->fhp != NULL) + goto have_mfp; + } + + /* + * If there's no backing file, we can join existing files in the cache, + * but there's nothing to read from disk. + */ + if (!FLD_ISSET(dbmfp->config_flags, DB_MPOOL_NOFILE)) { + /* Convert MP open flags to DB OS-layer open flags. */ + oflags = 0; + if (LF_ISSET(DB_CREATE)) + oflags |= DB_OSO_CREATE; + if (LF_ISSET(DB_DIRECT)) + oflags |= DB_OSO_DIRECT; + if (LF_ISSET(DB_RDONLY)) + oflags |= DB_OSO_RDONLY; + + /* + * XXX + * A grievous layering violation, the DB_DSYNC_DB flag + * was left in the ENV structure and not driven through + * the cache API. This needs to be fixed when the general + * API configuration is fixed. + */ + if (F_ISSET(env->dbenv, DB_ENV_DSYNC_DB)) + oflags |= DB_OSO_DSYNC; + + /* + * Get the real name for this file and open it. + * + * Supply a page size so os_open can decide whether to + * turn buffering off if the DB_DIRECT_DB flag is set. + * + * Acquire the region lock if we're using a path from + * an underlying MPOOLFILE -- there's a race in accessing + * the path name stored in the region, __memp_nameop may + * be simultaneously renaming the file. + */ + + ret = 0; + if (mfp != NULL) { + MPOOL_SYSTEM_LOCK(env); + path = R_ADDR(dbmp->reginfo, mfp->path_off); + if (rpath != NULL) { + __os_free(env, rpath); + rpath = NULL; + } + } + if (rpath == NULL) + ret = __db_appname(env, + DB_APP_DATA, path, dirp, &rpath); + if (ret == 0) + ret = __os_open(env, rpath, + (u_int32_t)pagesize, oflags, mode, &dbmfp->fhp); + if (mfp != NULL) + MPOOL_SYSTEM_UNLOCK(env); + if (ret != 0) + goto err; + + /* + * Cache file handles are shared, and have mutexes to + * protect the underlying file handle across seek and + * read/write calls. + */ + dbmfp->fhp->ref = 1; + if ((ret = __mutex_alloc(env, MTX_MPOOL_FH, + DB_MUTEX_PROCESS_ONLY, &dbmfp->fhp->mtx_fh)) != 0) + goto err; + + /* Figure out the file's size. */ + if ((ret = __os_ioinfo( + env, rpath, dbmfp->fhp, &mbytes, &bytes, NULL)) != 0) { + __db_err(env, ret, "%s", rpath); + goto err; + } + + /* + * Don't permit files that aren't a multiple of the pagesize, + * and find the number of the last page in the file, all the + * time being careful not to overflow 32 bits. + * + * During verify or recovery, we might have to cope with a + * truncated file; if the file size is not a multiple of the + * page size, round down to a page, we'll take care of the + * partial page outside the mpool system. + * + * Pagesize of 0 is only allowed for in-mem dbs. + */ + DB_ASSERT(env, pagesize != 0); + if (bytes % pagesize != 0) { + if (LF_ISSET(DB_ODDFILESIZE)) + bytes -= (u_int32_t)(bytes % pagesize); + else { + /* + * If the file size is not a multiple of the + * pagesize, it is likely because the ioinfo + * call is racing with a write that is extending + * the file. Many file systems will extend + * in fs block size units, and if the pagesize + * is larger than that, we can briefly see a + * file size that is not a multiple of pagesize. + * + * Yield the processor to allow that to finish + * and try again a few times. + */ + tries = 0; + STAT((mp->stat.st_oddfsize_detect++)); + while (tries < MP_IOINFO_RETRIES) { + if ((ret = __os_ioinfo(env, rpath, + dbmfp->fhp, &mbytes, &bytes, + NULL)) != 0) { + __db_err(env, ret, "%s", rpath); + goto err; + } + if (bytes % pagesize != 0) { + __os_yield(env, 0, 50000); + tries++; + } else { + STAT((mp->stat.st_oddfsize_resolve++)); + break; + } + } + if (tries == MP_IOINFO_RETRIES) { + __db_errx(env, DB_STR_A("3037", + "%s: file size (%lu %lu) not a multiple of the pagesize %lu", + "%s %lu %lu %lu"), + rpath, (u_long)mbytes, (u_long)bytes, (u_long)pagesize); + ret = EINVAL; + goto err; + } + } + } + + /* + * Get the file id if we weren't given one. Generated file id's + * don't use timestamps, otherwise there'd be no chance of any + * other process joining the party. Don't bother looking for + * this id in the hash table, its new. + */ + if (mfp == NULL && !F_ISSET(dbmfp, MP_FILEID_SET)) { + if ((ret = + __os_fileid(env, rpath, 0, dbmfp->fileid)) != 0) + goto err; + F_SET(dbmfp, MP_FILEID_SET); + bucket = FNBUCKET(dbmfp->fileid, DB_FILE_ID_LEN); + hp += bucket; + goto alloc; + } + } + + if (mfp != NULL) + goto have_mfp; + + /* + * We can race with another process opening the same file when + * we allocate the mpoolfile structure. We will come back + * here and check the hash table again to see if it has appeared. + * For most files this is not a problem, since the name is locked + * at a higher layer but QUEUE extent files are not locked. + */ +check: MUTEX_LOCK(env, hp->mtx_hash); + if ((ret = __memp_mpf_find(env, dbmfp, hp, path, flags, &mfp) != 0)) + goto err; + + if (alloc_mfp != NULL && mfp == NULL) { + mfp = alloc_mfp; + alloc_mfp = NULL; + SH_TAILQ_INSERT_HEAD(&hp->hash_bucket, mfp, q, __mpoolfile); + } else if (mfp != NULL) { + refinc = 1; + /* + * Some things about a file cannot be changed: the clear length, + * page size, or LSN location. However, if this is an attempt + * to open a named in-memory file, we may not yet have that + * information. so accept uninitialized entries. + * + * The file type can change if the application's pre- and post- + * processing needs change. For example, an application that + * created a hash subdatabase in a database that was previously + * all btree. + * + * !!! + * We do not check to see if the pgcookie information changed, + * or update it if it is. + */ + if ((dbmfp->clear_len != DB_CLEARLEN_NOTSET && + mfp->clear_len != DB_CLEARLEN_NOTSET && + dbmfp->clear_len != mfp->clear_len) || + (pagesize != 0 && pagesize != mfp->pagesize) || + (dbmfp->lsn_offset != DB_LSN_OFF_NOTSET && + mfp->lsn_off != DB_LSN_OFF_NOTSET && + dbmfp->lsn_offset != mfp->lsn_off)) { + __db_errx(env, DB_STR_A("3038", + "%s: clear length, page size or LSN location changed", + "%s"), path); + MUTEX_UNLOCK(env, hp->mtx_hash); + ret = EINVAL; + goto err; + } + } + if (mfp != NULL && LF_ISSET(DB_MULTIVERSION)) { + if (MFP_OPEN_CNT(mfp) > 1 && + atomic_read(&mfp->multiversion) == 0) { + MUTEX_UNLOCK(env, hp->mtx_hash); + goto mvcc_err; + } + atomic_inc(env, &mfp->multiversion); + F_SET(dbmfp, MP_MULTIVERSION); + } + + MUTEX_UNLOCK(env, hp->mtx_hash); + if (alloc_mfp != NULL) { + MUTEX_LOCK(env, alloc_mfp->mutex); + if ((ret = __memp_mf_discard(dbmp, alloc_mfp, 0)) != 0) + goto err; + } + + if (mfp == NULL) { + /* + * If we didn't find the file and this is an in-memory file, + * then the create flag should be set. + */ + if (FLD_ISSET(dbmfp->config_flags, DB_MPOOL_NOFILE) && + !LF_ISSET(DB_CREATE)) { + ret = ENOENT; + goto err; + } + +alloc: if ((ret = __memp_mpf_alloc(dbmp, + dbmfp, path, pagesize, flags, &alloc_mfp)) != 0) + goto err; + + /* + * If the user specifies DB_MPOOL_LAST or DB_MPOOL_NEW on a + * page get, we have to increment the last page in the file. + * Figure it out and save it away. + * + * Note correction: page numbers are zero-based, not 1-based. + */ + DB_ASSERT(env, pagesize != 0); + last_pgno = (db_pgno_t)(mbytes * (MEGABYTE / pagesize)); + last_pgno += (db_pgno_t)(bytes / pagesize); + if (last_pgno != 0) + --last_pgno; + + alloc_mfp->last_flushed_pgno = alloc_mfp->orig_last_pgno = + alloc_mfp->last_pgno = last_pgno; + + alloc_mfp->bucket = bucket; + + /* Go back and see if someone else has opened the file. */ + if (path != NULL) + goto check; + + mfp = alloc_mfp; + + if (LF_ISSET(DB_MULTIVERSION)) { + atomic_inc(env, &mfp->multiversion); + F_SET(dbmfp, MP_MULTIVERSION); + } + + /* This is a temp, noone else can see it, put it at the end. */ + MUTEX_LOCK(env, hp->mtx_hash); + SH_TAILQ_INSERT_TAIL(&hp->hash_bucket, mfp, q); + MUTEX_UNLOCK(env, hp->mtx_hash); + } +have_mfp: + /* + * We need to verify that all handles open a file either durable or not + * durable. This needs to be cross process and cross sub-databases, so + * mpool is the place to do it. + */ + if (!LF_ISSET(DB_DURABLE_UNKNOWN | DB_RDONLY)) { + if (F_ISSET(mfp, MP_DURABLE_UNKNOWN)) { + if (LF_ISSET(DB_TXN_NOT_DURABLE)) + F_SET(mfp, MP_NOT_DURABLE); + F_CLR(mfp, MP_DURABLE_UNKNOWN); + } else if (!LF_ISSET(DB_TXN_NOT_DURABLE) != + !F_ISSET(mfp, MP_NOT_DURABLE)) { + __db_errx(env, DB_STR("3039", + "Cannot open DURABLE and NOT DURABLE handles in the same file")); + ret = EINVAL; + goto err; + } + } + + /* + * All paths to here have initialized the mfp variable to reference + * the selected (or allocated) MPOOLFILE. + */ + dbmfp->mfp = mfp; + + /* + * Check to see if we can mmap the file. If a file: + * + isn't temporary + * + is read-only + * + doesn't require any pgin/pgout support + * + the DB_NOMMAP flag wasn't set (in either the file open or + * the environment in which it was opened) + * + and is less than mp_mmapsize bytes in size + * + * we can mmap it instead of reading/writing buffers. Don't do error + * checking based on the mmap call failure. We want to do normal I/O + * on the file if the reason we failed was because the file was on an + * NFS mounted partition, and we can fail in buffer I/O just as easily + * as here. + * + * We'd like to test to see if the file is too big to mmap. Since we + * don't know what size or type off_t's or size_t's are, or the largest + * unsigned integral type is, or what random insanity the local C + * compiler will perpetrate, doing the comparison in a portable way is + * flatly impossible. Hope that mmap fails if the file is too large. + */ +#define DB_MAXMMAPSIZE (10 * 1024 * 1024) /* 10 MB. */ + if (F_ISSET(mfp, MP_CAN_MMAP) && dbmfp->addr == NULL) { + maxmap = dbenv->mp_mmapsize == 0 ? + DB_MAXMMAPSIZE : dbenv->mp_mmapsize; + if (path == NULL || + FLD_ISSET(dbmfp->config_flags, DB_MPOOL_NOFILE)) + F_CLR(mfp, MP_CAN_MMAP); + else if (!F_ISSET(dbmfp, MP_READONLY)) + F_CLR(mfp, MP_CAN_MMAP); + else if (dbmfp->ftype != 0) + F_CLR(mfp, MP_CAN_MMAP); + else if (LF_ISSET(DB_NOMMAP) || F_ISSET(dbenv, DB_ENV_NOMMAP)) + F_CLR(mfp, MP_CAN_MMAP); + else { + MPOOL_SYSTEM_LOCK(env); + maxmap = mp->mp_mmapsize == 0 ? + DB_MAXMMAPSIZE : mp->mp_mmapsize; + MPOOL_SYSTEM_UNLOCK(env); + if (mbytes > maxmap / MEGABYTE || + (mbytes == maxmap / MEGABYTE && + bytes >= maxmap % MEGABYTE)) + F_CLR(mfp, MP_CAN_MMAP); + } + + dbmfp->addr = NULL; + if (F_ISSET(mfp, MP_CAN_MMAP)) { + dbmfp->len = (size_t)mbytes * MEGABYTE + bytes; + if (__os_mapfile(env, rpath, + dbmfp->fhp, dbmfp->len, 1, &dbmfp->addr) != 0) { + dbmfp->addr = NULL; + F_CLR(mfp, MP_CAN_MMAP); + } + } + } + + F_SET(dbmfp, MP_OPEN_CALLED); + + /* + * Add the file to the process' list of DB_MPOOLFILEs. + */ + MUTEX_LOCK(env, dbmp->mutex); + TAILQ_INSERT_TAIL(&dbmp->dbmfq, dbmfp, q); + MUTEX_UNLOCK(env, dbmp->mutex); + + if (0) { +err: if (refinc) { + /* + * If mpf_cnt goes to zero here and unlink_on_close is + * set, then we missed the last close, but there was an + * error trying to open the file, so we probably cannot + * unlink it anyway. + */ + MUTEX_LOCK(env, mfp->mutex); + --mfp->mpf_cnt; + if (LF_ISSET(DB_FLUSH | DB_RDONLY)) { + DB_ASSERT(env, mfp->neutral_cnt != 0); + --mfp->neutral_cnt; + } + MUTEX_UNLOCK(env, mfp->mutex); + } + + } + if (rpath != NULL) + __os_free(env, rpath); + return (ret); +} + +/* + * __memp_mpf_find -- + * Search a hash bucket for a MPOOLFILE. + */ +static int +__memp_mpf_find(env, dbmfp, hp, path, flags, mfpp) + ENV *env; + DB_MPOOLFILE *dbmfp; + DB_MPOOL_HASH *hp; + const char *path; + u_int32_t flags; + MPOOLFILE **mfpp; +{ + DB_MPOOL *dbmp; + MPOOLFILE *mfp; + + dbmp = env->mp_handle; + + SH_TAILQ_FOREACH(mfp, &hp->hash_bucket, q, __mpoolfile) { + /* Skip dead files and temporary files. */ + if (mfp->deadfile || F_ISSET(mfp, MP_TEMP)) + continue; + + /* + * Any remaining DB_MPOOL_NOFILE databases are in-memory + * named databases and need only match other in-memory + * databases with the same name. + */ + if (FLD_ISSET(dbmfp->config_flags, DB_MPOOL_NOFILE)) { + if (!mfp->no_backing_file) + continue; + + if (strcmp(path, R_ADDR(dbmp->reginfo, mfp->path_off))) + continue; + + /* + * We matched an in-memory file; grab the fileid if + * it is set in the region, but not in the dbmfp. + */ + if (!F_ISSET(dbmfp, MP_FILEID_SET)) + (void)__memp_set_fileid(dbmfp, + R_ADDR(dbmp->reginfo, mfp->fileid_off)); + } else + if (memcmp(dbmfp->fileid, R_ADDR(dbmp->reginfo, + mfp->fileid_off), DB_FILE_ID_LEN) != 0) + continue; + + /* + * If the file is being truncated, remove it from the system + * and create a new entry. + * + * !!! + * We should be able to set mfp to NULL and break out of the + * loop, but I like the idea of checking all the entries. + */ + if (LF_ISSET(DB_TRUNCATE)) { + MUTEX_LOCK(env, mfp->mutex); + mfp->deadfile = 1; + MUTEX_UNLOCK(env, mfp->mutex); + continue; + } + + /* + * Check to see if this file has died while we waited. + * + * We normally don't lock the deadfile field when we read it as + * we only care if the field is zero or non-zero. We do lock + * on read when searching for a matching MPOOLFILE so that two + * threads of control don't race between setting the deadfile + * bit and incrementing the reference count, that is, a thread + * of control decrementing the reference count and then setting + * deadfile because the reference count is 0 blocks us finding + * the file without knowing it's about to be marked dead. + */ + MUTEX_LOCK(env, mfp->mutex); + if (mfp->deadfile) { + MUTEX_UNLOCK(env, mfp->mutex); + continue; + } + ++mfp->mpf_cnt; + if (LF_ISSET(DB_FLUSH | DB_RDONLY)) + ++mfp->neutral_cnt; + if (LF_ISSET(DB_FLUSH)) + F_SET(dbmfp, MP_FOR_FLUSH); + MUTEX_UNLOCK(env, mfp->mutex); + + /* Initialize any fields that are not yet set. */ + if (dbmfp->ftype != 0) + mfp->ftype = dbmfp->ftype; + if (dbmfp->clear_len != DB_CLEARLEN_NOTSET) + mfp->clear_len = dbmfp->clear_len; + if (dbmfp->lsn_offset != -1) + mfp->lsn_off = dbmfp->lsn_offset; + + break; + } + + *mfpp = mfp; + return (0); +} + +static int +__memp_mpf_alloc(dbmp, dbmfp, path, pagesize, flags, retmfp) + DB_MPOOL *dbmp; + DB_MPOOLFILE *dbmfp; + const char *path; + u_int32_t pagesize; + u_int32_t flags; + MPOOLFILE **retmfp; +{ + ENV *env; + MPOOLFILE *mfp; + int ret; + void *p; + + env = dbmp->env; + ret = 0; + /* Allocate and initialize a new MPOOLFILE. */ + if ((ret = __memp_alloc(dbmp, + dbmp->reginfo, NULL, sizeof(MPOOLFILE), NULL, &mfp)) != 0) + goto err; + memset(mfp, 0, sizeof(MPOOLFILE)); + mfp->mpf_cnt = 1; + if (LF_ISSET(DB_FLUSH | DB_RDONLY)) + mfp->neutral_cnt = 1; + if (LF_ISSET(DB_FLUSH)) + F_SET(dbmfp, MP_FOR_FLUSH); + mfp->ftype = dbmfp->ftype; + mfp->pagesize = pagesize; + mfp->lsn_off = dbmfp->lsn_offset; + mfp->clear_len = dbmfp->clear_len; + mfp->priority = dbmfp->priority; + if (dbmfp->gbytes != 0 || dbmfp->bytes != 0) { + mfp->maxpgno = (db_pgno_t) + (dbmfp->gbytes * (GIGABYTE / mfp->pagesize)); + mfp->maxpgno += (db_pgno_t) + ((dbmfp->bytes + mfp->pagesize - 1) / + mfp->pagesize); + } + if (FLD_ISSET(dbmfp->config_flags, DB_MPOOL_NOFILE)) + mfp->no_backing_file = 1; + if (FLD_ISSET(dbmfp->config_flags, DB_MPOOL_UNLINK)) + mfp->unlink_on_close = 1; + + F_SET(mfp, MP_CAN_MMAP); + if (F_ISSET(env->dbenv, DB_ENV_DATABASE_LOCKING)) + F_SET(mfp, MP_DATABASE_LOCKING); + if (LF_ISSET(DB_DIRECT)) + F_SET(mfp, MP_DIRECT); + if (LF_ISSET(DB_DURABLE_UNKNOWN | DB_RDONLY)) + F_SET(mfp, MP_DURABLE_UNKNOWN); + if (LF_ISSET(DB_EXTENT)) + F_SET(mfp, MP_EXTENT); + if (LF_ISSET(DB_TXN_NOT_DURABLE)) + F_SET(mfp, MP_NOT_DURABLE); + + /* + * An in-memory database with no name is a temp file. Named + * in-memory databases get an artificially bumped reference + * count so they don't disappear on close; they need a remove + * to make them disappear. + */ + if (path == NULL) + F_SET(mfp, MP_TEMP); + else if (FLD_ISSET(dbmfp->config_flags, DB_MPOOL_NOFILE)) + mfp->mpf_cnt++; + + /* Copy the file identification string into shared memory. */ + if (F_ISSET(dbmfp, MP_FILEID_SET)) { + if ((ret = __memp_alloc(dbmp, dbmp->reginfo, + NULL, DB_FILE_ID_LEN, &mfp->fileid_off, &p)) != 0) + goto err; + memcpy(p, dbmfp->fileid, DB_FILE_ID_LEN); + } + + /* Copy the file path into shared memory. */ + if (path != NULL) { + if ((ret = __memp_alloc(dbmp, dbmp->reginfo, + NULL, strlen(path) + 1, &mfp->path_off, &p)) != 0) + goto err; + memcpy(p, path, strlen(path) + 1); + } + + /* Copy the page cookie into shared memory. */ + if (dbmfp->pgcookie == NULL || dbmfp->pgcookie->size == 0) { + mfp->pgcookie_len = 0; + mfp->pgcookie_off = 0; + } else { + if ((ret = __memp_alloc(dbmp, dbmp->reginfo, + NULL, dbmfp->pgcookie->size, + &mfp->pgcookie_off, &p)) != 0) + goto err; + memcpy(p, + dbmfp->pgcookie->data, dbmfp->pgcookie->size); + mfp->pgcookie_len = dbmfp->pgcookie->size; + } + + if ((ret = __mutex_alloc(env, + MTX_MPOOLFILE_HANDLE, 0, &mfp->mutex)) != 0) + goto err; +#ifndef HAVE_ATOMICFILEREAD + if ((ret = __mutex_alloc(env, + MTX_MPOOLFILE_HANDLE, DB_MUTEX_SHARED, &mfp->mtx_write)) != 0) + goto err; +#endif + *retmfp = mfp; + +err: return (ret); +} + +/* + * memp_fclose_pp -- + * DB_MPOOLFILE->close pre/post processing. + * + * PUBLIC: int __memp_fclose_pp __P((DB_MPOOLFILE *, u_int32_t)); + */ +int +__memp_fclose_pp(dbmfp, flags) + DB_MPOOLFILE *dbmfp; + u_int32_t flags; +{ + DB_THREAD_INFO *ip; + ENV *env; + int ret; + + env = dbmfp->env; + + /* + * Validate arguments, but as a handle destructor, we can't fail. + */ + if (flags != 0) + (void)__db_ferr(env, "DB_MPOOLFILE->close", 0); + + ENV_ENTER(env, ip); + REPLICATION_WRAP(env, (__memp_fclose(dbmfp, 0)), 0, ret); + ENV_LEAVE(env, ip); + return (ret); +} + +/* + * __memp_fclose -- + * DB_MPOOLFILE->close. + * + * PUBLIC: int __memp_fclose __P((DB_MPOOLFILE *, u_int32_t)); + */ +int +__memp_fclose(dbmfp, flags) + DB_MPOOLFILE *dbmfp; + u_int32_t flags; +{ + DB_MPOOL *dbmp; + ENV *env; + MPOOLFILE *mfp; + char *rpath; + u_int32_t ref; + int deleted, ret, t_ret; + + env = dbmfp->env; + dbmp = env->mp_handle; + ret = 0; + + /* + * Remove the DB_MPOOLFILE from the process' list. + * + * It's possible the underlying mpool cache may never have been created. + * In that case, all we have is a structure, discard it. + * + * It's possible the DB_MPOOLFILE was never added to the DB_MPOOLFILE + * file list, check the MP_OPEN_CALLED flag to be sure. + */ + if (dbmp == NULL) + goto done; + + MUTEX_LOCK(env, dbmp->mutex); + + DB_ASSERT(env, dbmfp->ref >= 1); + if ((ref = --dbmfp->ref) == 0 && F_ISSET(dbmfp, MP_OPEN_CALLED)) + TAILQ_REMOVE(&dbmp->dbmfq, dbmfp, q); + + /* + * Decrement the file descriptor's ref count -- if we're the last ref, + * we'll discard the file descriptor. + */ + if (ref == 0 && dbmfp->fhp != NULL && --dbmfp->fhp->ref > 0) + dbmfp->fhp = NULL; + MUTEX_UNLOCK(env, dbmp->mutex); + if (ref != 0) + return (0); + + /* Complain if pinned blocks never returned. */ + if (dbmfp->pinref != 0) { + __db_errx(env, DB_STR_A("3040", + "%s: close: %lu blocks left pinned", "%s %lu"), + __memp_fn(dbmfp), (u_long)dbmfp->pinref); + ret = __env_panic(env, DB_RUNRECOVERY); + } + + /* Discard any mmap information. */ + if (dbmfp->addr != NULL && dbmfp->fhp != NULL && + (ret = __os_unmapfile(env, dbmfp->addr, dbmfp->len)) != 0) + __db_err(env, ret, "%s", __memp_fn(dbmfp)); + + /* + * Close the file and discard the descriptor structure; temporary + * files may not yet have been created. + */ + if (dbmfp->fhp != NULL) { + if ((t_ret = + __mutex_free(env, &dbmfp->fhp->mtx_fh)) != 0 && ret == 0) + ret = t_ret; + if ((t_ret = __os_closehandle(env, dbmfp->fhp)) != 0) { + __db_err(env, t_ret, "%s", __memp_fn(dbmfp)); + if (ret == 0) + ret = t_ret; + } + dbmfp->fhp = NULL; + } + + /* + * Discard our reference on the underlying MPOOLFILE, and close it + * if it's no longer useful to anyone. It possible the open of the + * file never happened or wasn't successful, in which case, mpf will + * be NULL and MP_OPEN_CALLED will not be set. + */ + mfp = dbmfp->mfp; + DB_ASSERT(env, + (F_ISSET(dbmfp, MP_OPEN_CALLED) && mfp != NULL) || + (!F_ISSET(dbmfp, MP_OPEN_CALLED) && mfp == NULL)); + if (!F_ISSET(dbmfp, MP_OPEN_CALLED)) + goto done; + + /* + * If it's a temp file, all outstanding references belong to unflushed + * buffers. (A temp file can only be referenced by one DB_MPOOLFILE). + * We don't care about preserving any of those buffers, so mark the + * MPOOLFILE as dead so that even the dirty ones just get discarded + * when we try to flush them. + */ + deleted = 0; + if (!LF_ISSET(DB_MPOOL_NOLOCK)) + MUTEX_LOCK(env, mfp->mutex); + if (F_ISSET(dbmfp, MP_MULTIVERSION)) + atomic_dec(env, &mfp->multiversion); + if (F_ISSET(dbmfp, MP_READONLY) || + (LF_ISSET(DB_FLUSH) && F_ISSET(dbmfp, MP_FOR_FLUSH))) { + DB_ASSERT(env, mfp->neutral_cnt != 0); + --mfp->neutral_cnt; + } + DB_ASSERT(env, mfp->neutral_cnt < mfp->mpf_cnt); + if (--mfp->mpf_cnt == 0 || LF_ISSET(DB_MPOOL_DISCARD)) { + if (LF_ISSET(DB_MPOOL_DISCARD) || + F_ISSET(mfp, MP_TEMP) || mfp->unlink_on_close) { + mfp->deadfile = 1; + } + if (mfp->unlink_on_close) { + if ((t_ret = __db_appname(dbmp->env, DB_APP_DATA, + R_ADDR(dbmp->reginfo, mfp->path_off), NULL, + &rpath)) != 0 && ret == 0) + ret = t_ret; + if (t_ret == 0) { + if ((t_ret = __os_unlink( + dbmp->env, rpath, 0)) != 0 && ret == 0) + ret = t_ret; + __os_free(env, rpath); + } + } + if (MFP_OPEN_CNT(mfp) == 0) { + F_CLR(mfp, MP_NOT_DURABLE); + F_SET(mfp, MP_DURABLE_UNKNOWN); + } + if (mfp->block_cnt == 0) { + /* + * We should never discard this mp file if our caller + * is holding the lock on it. See comment in + * __memp_sync_file. + */ + DB_ASSERT(env, !LF_ISSET(DB_MPOOL_NOLOCK)); + if ((t_ret = + __memp_mf_discard(dbmp, mfp, 0)) != 0 && ret == 0) + ret = t_ret; + deleted = 1; + } + } + if (!deleted && !LF_ISSET(DB_MPOOL_NOLOCK)) + MUTEX_UNLOCK(env, mfp->mutex); + +done: /* Discard the DB_MPOOLFILE structure. */ + if (dbmfp->pgcookie != NULL) { + __os_free(env, dbmfp->pgcookie->data); + __os_free(env, dbmfp->pgcookie); + } + __os_free(env, dbmfp); + + return (ret); +} + +/* + * __memp_mf_discard -- + * Discard an MPOOLFILE. + * + * PUBLIC: int __memp_mf_discard __P((DB_MPOOL *, MPOOLFILE *, int)); + */ +int +__memp_mf_discard(dbmp, mfp, hp_locked) + DB_MPOOL *dbmp; + MPOOLFILE *mfp; + int hp_locked; +{ + DB_MPOOL_HASH *hp; + ENV *env; +#ifdef HAVE_STATISTICS + DB_MPOOL_STAT *sp; +#endif + MPOOL *mp; + int need_sync, ret, t_ret; + + env = dbmp->env; + mp = dbmp->reginfo[0].primary; + hp = R_ADDR(dbmp->reginfo, mp->ftab); + hp += mfp->bucket; + ret = 0; + + /* + * Expects caller to be holding the MPOOLFILE mutex. + * + * When discarding a file, we have to flush writes from it to disk. + * The scenario is that dirty buffers from this file need to be + * flushed to satisfy a future checkpoint, but when the checkpoint + * calls mpool sync, the sync code won't know anything about them. + * Ignore files not written, discarded, or only temporary. + */ + need_sync = mfp->file_written && !mfp->deadfile && + !F_ISSET(mfp, MP_TEMP) && !mfp->no_backing_file; + + /* + * We have to release the MPOOLFILE mutex before acquiring the region + * mutex so we don't deadlock. Make sure nobody ever looks at this + * structure again. + */ + mfp->deadfile = 1; + + /* Discard the mutex we're holding and return it too the pool. */ + MUTEX_UNLOCK(env, mfp->mutex); + if ((t_ret = __mutex_free(env, &mfp->mutex)) != 0 && ret == 0) + ret = t_ret; +#ifndef HAVE_ATOMICFILEREAD + if ((ret = __mutex_free(env, &mfp->mtx_write)) != 0 && ret == 0) + ret = t_ret; +#endif + + /* + * Lock the bucket and delete from the list of MPOOLFILEs. + * If this function is called by __memp_discard_all_mpfs, + * the MPOOLFILE hash bucket is already locked. + */ + if (!hp_locked) + MUTEX_LOCK(env, hp->mtx_hash); + SH_TAILQ_REMOVE(&hp->hash_bucket, mfp, q, __mpoolfile); + if (!hp_locked) + MUTEX_UNLOCK(env, hp->mtx_hash); + + /* Lock the region and collect stats and free the space. */ + MPOOL_SYSTEM_LOCK(env); + if (need_sync && + (t_ret = __memp_mf_sync(dbmp, mfp, 0)) != 0 && ret == 0) + ret = t_ret; + +#ifdef HAVE_STATISTICS + /* Copy the statistics into the region. */ + sp = &mp->stat; + sp->st_cache_hit += mfp->stat.st_cache_hit; + sp->st_cache_miss += mfp->stat.st_cache_miss; + sp->st_map += mfp->stat.st_map; + sp->st_page_create += mfp->stat.st_page_create; + sp->st_page_in += mfp->stat.st_page_in; + sp->st_page_out += mfp->stat.st_page_out; +#endif + + /* Free the space. */ + if (mfp->path_off != 0) + __memp_free(&dbmp->reginfo[0], + R_ADDR(dbmp->reginfo, mfp->path_off)); + if (mfp->fileid_off != 0) + __memp_free(&dbmp->reginfo[0], + R_ADDR(dbmp->reginfo, mfp->fileid_off)); + if (mfp->pgcookie_off != 0) + __memp_free(&dbmp->reginfo[0], + R_ADDR(dbmp->reginfo, mfp->pgcookie_off)); + __memp_free(&dbmp->reginfo[0], mfp); + + MPOOL_SYSTEM_UNLOCK(env); + + return (ret); +} + +/* + * __memp_inmemlist -- + * Return a list of the named in-memory databases. + * + * PUBLIC: int __memp_inmemlist __P((ENV *, char ***, int *)); + */ +int +__memp_inmemlist(env, namesp, cntp) + ENV *env; + char ***namesp; + int *cntp; +{ + DB_MPOOL *dbmp; + DB_MPOOL_HASH *hp; + MPOOL *mp; + MPOOLFILE *mfp; + int arraysz, cnt, i, ret; + char **names; + + names = NULL; + dbmp = env->mp_handle; + mp = dbmp->reginfo[0].primary; + hp = R_ADDR(dbmp->reginfo, mp->ftab); + + arraysz = cnt = 0; + for (i = 0; i < MPOOL_FILE_BUCKETS; i++, hp++) { + MUTEX_LOCK(env, hp->mtx_hash); + SH_TAILQ_FOREACH(mfp, &hp->hash_bucket, q, __mpoolfile) { + /* Skip dead files and temporary files. */ + if (mfp->deadfile || F_ISSET(mfp, MP_TEMP)) + continue; + + /* Skip entries that allow files. */ + if (!mfp->no_backing_file) + continue; + + /* We found one. */ + if (cnt >= arraysz) { + arraysz += 100; + if ((ret = __os_realloc(env, + (u_int)arraysz * sizeof(names[0]), + &names)) != 0) + goto nomem; + } + if ((ret = __os_strdup(env, + R_ADDR(dbmp->reginfo, mfp->path_off), + &names[cnt])) != 0) + goto nomem; + + cnt++; + } + MUTEX_UNLOCK(env, hp->mtx_hash); + } + *namesp = names; + *cntp = cnt; + return (0); + +nomem: MUTEX_UNLOCK(env, hp->mtx_hash); + if (names != NULL) { + while (--cnt >= 0) + __os_free(env, names[cnt]); + __os_free(env, names); + } + + /* Make sure we don't return any garbage. */ + *cntp = 0; + *namesp = NULL; + return (ret); +} diff -r 000000000000 -r a1985f14b030 src/mp/mp_fput.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/mp/mp_fput.c Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,396 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 1996, 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + * $Id$ + */ + +#include "db_config.h" + +#include "db_int.h" +#include "dbinc/log.h" +#include "dbinc/mp.h" + +static int __memp_reset_lru __P((ENV *, REGINFO *)); + +/* + * __memp_fput_pp -- + * DB_MPOOLFILE->put pre/post processing. + * + * PUBLIC: int __memp_fput_pp + * PUBLIC: __P((DB_MPOOLFILE *, void *, DB_CACHE_PRIORITY, u_int32_t)); + */ +int +__memp_fput_pp(dbmfp, pgaddr, priority, flags) + DB_MPOOLFILE *dbmfp; + void *pgaddr; + DB_CACHE_PRIORITY priority; + u_int32_t flags; +{ + DB_THREAD_INFO *ip; + ENV *env; + int ret, t_ret; + + env = dbmfp->env; + + if (flags != 0) + return (__db_ferr(env, "DB_MPOOLFILE->put", 0)); + + MPF_ILLEGAL_BEFORE_OPEN(dbmfp, "DB_MPOOLFILE->put"); + + ENV_ENTER(env, ip); + + ret = __memp_fput(dbmfp, ip, pgaddr, priority); + if (IS_ENV_REPLICATED(env) && + (t_ret = __op_rep_exit(env)) != 0 && ret == 0) + ret = t_ret; + + ENV_LEAVE(env, ip); + return (ret); +} + +/* + * __memp_fput -- + * DB_MPOOLFILE->put. + * + * PUBLIC: int __memp_fput __P((DB_MPOOLFILE *, + * PUBLIC: DB_THREAD_INFO *, void *, DB_CACHE_PRIORITY)); + */ +int +__memp_fput(dbmfp, ip, pgaddr, priority) + DB_MPOOLFILE *dbmfp; + DB_THREAD_INFO *ip; + void *pgaddr; + DB_CACHE_PRIORITY priority; +{ + BH *bhp; + DB_ENV *dbenv; + DB_MPOOL *dbmp; + DB_MPOOL_HASH *hp; + ENV *env; + MPOOL *c_mp; + MPOOLFILE *mfp; + PIN_LIST *list, *lp; + REGINFO *infop, *reginfo; + roff_t b_ref; + int region; + int adjust, pfactor, ret, t_ret; + char buf[DB_THREADID_STRLEN]; + + env = dbmfp->env; + dbenv = env->dbenv; + dbmp = env->mp_handle; + mfp = dbmfp->mfp; + bhp = (BH *)((u_int8_t *)pgaddr - SSZA(BH, buf)); + ret = 0; + + /* + * If this is marked dummy, we are using it to unpin a buffer for + * another thread. + */ + if (F_ISSET(dbmfp, MP_DUMMY)) + goto unpin; + + /* + * If we're mapping the file, there's nothing to do. Because we can + * stop mapping the file at any time, we have to check on each buffer + * to see if the address we gave the application was part of the map + * region. + */ + if (dbmfp->addr != NULL && pgaddr >= dbmfp->addr && + (u_int8_t *)pgaddr <= (u_int8_t *)dbmfp->addr + dbmfp->len) + return (0); + + DB_ASSERT(env, IS_RECOVERING(env) || bhp->pgno <= mfp->last_pgno || + F_ISSET(bhp, BH_FREED) || !SH_CHAIN_SINGLETON(bhp, vc)); +#ifdef DIAGNOSTIC + /* + * Decrement the per-file pinned buffer count (mapped pages aren't + * counted). + */ + MPOOL_SYSTEM_LOCK(env); + if (dbmfp->pinref == 0) { + MPOOL_SYSTEM_UNLOCK(env); + __db_errx(env, DB_STR_A("3011", + "%s: more pages returned than retrieved", "%s"), + __memp_fn(dbmfp)); + return (__env_panic(env, EACCES)); + } + --dbmfp->pinref; + MPOOL_SYSTEM_UNLOCK(env); +#endif + +unpin: + infop = &dbmp->reginfo[bhp->region]; + c_mp = infop->primary; + hp = R_ADDR(infop, c_mp->htab); + hp = &hp[bhp->bucket]; + + /* + * Check for a reference count going to zero. This can happen if the + * application returns a page twice. + */ + if (atomic_read(&bhp->ref) == 0) { + __db_errx(env, DB_STR_A("3012", + "%s: page %lu: unpinned page returned", "%s %lu"), + __memp_fn(dbmfp), (u_long)bhp->pgno); + DB_ASSERT(env, atomic_read(&bhp->ref) != 0); + return (__env_panic(env, EACCES)); + } + + /* Note the activity so allocation won't decide to quit. */ + ++c_mp->put_counter; + + if (ip != NULL) { + reginfo = env->reginfo; + list = R_ADDR(reginfo, ip->dbth_pinlist); + region = (int)(infop - dbmp->reginfo); + b_ref = R_OFFSET(infop, bhp); + for (lp = list; lp < &list[ip->dbth_pinmax]; lp++) + if (lp->b_ref == b_ref && lp->region == region) + break; + + if (lp == &list[ip->dbth_pinmax]) { + __db_errx(env, DB_STR_A("3013", + "__memp_fput: pinned buffer not found for thread %s", + "%s"), dbenv->thread_id_string(dbenv, + ip->dbth_pid, ip->dbth_tid, buf)); + return (__env_panic(env, EINVAL)); + } + + lp->b_ref = INVALID_ROFF; + ip->dbth_pincount--; + } + + /* + * Mark the file dirty. + */ + if (F_ISSET(bhp, BH_EXCLUSIVE) && F_ISSET(bhp, BH_DIRTY)) { + DB_ASSERT(env, atomic_read(&hp->hash_page_dirty) > 0); + mfp->file_written = 1; + } + + /* + * If more than one reference to the page we're done. Ignore the + * discard flags (for now) and leave the buffer's priority alone. + * We are doing this a little early as the remaining ref may or + * may not be a write behind. If it is we set the priority + * here, if not it will get set again later. We might race + * and miss setting the priority which would leave it wrong + * for a while. + */ + DB_ASSERT(env, atomic_read(&bhp->ref) != 0); + if (atomic_dec(env, &bhp->ref) > 1 || (atomic_read(&bhp->ref) == 1 && + !F_ISSET(bhp, BH_DIRTY))) { + /* + * __memp_pgwrite only has a shared lock while it clears + * the BH_DIRTY bit. If we only have a shared latch then + * we can't touch the flags bits. + */ + if (F_ISSET(bhp, BH_EXCLUSIVE)) + F_CLR(bhp, BH_EXCLUSIVE); + MUTEX_UNLOCK(env, bhp->mtx_buf); + return (0); + } + + /* The buffer should not be accessed again. */ +#ifdef DIAG_MVCC + MUTEX_LOCK(env, hp->mtx_hash); + if (BH_REFCOUNT(bhp) == 0) + MVCC_MPROTECT(bhp->buf, mfp->pagesize, 0); + MUTEX_UNLOCK(env, hp->mtx_hash); +#endif + + /* Update priority values. */ + if (priority == DB_PRIORITY_VERY_LOW || + mfp->priority == MPOOL_PRI_VERY_LOW) + bhp->priority = 0; + else { + /* + * We don't lock the LRU priority or the pages field, if + * we get garbage (which won't happen on a 32-bit machine), it + * only means a buffer has the wrong priority. + */ + bhp->priority = c_mp->lru_priority; + + switch (priority) { + default: + case DB_PRIORITY_UNCHANGED: + pfactor = mfp->priority; + break; + case DB_PRIORITY_VERY_LOW: + pfactor = MPOOL_PRI_VERY_LOW; + break; + case DB_PRIORITY_LOW: + pfactor = MPOOL_PRI_LOW; + break; + case DB_PRIORITY_DEFAULT: + pfactor = MPOOL_PRI_DEFAULT; + break; + case DB_PRIORITY_HIGH: + pfactor = MPOOL_PRI_HIGH; + break; + case DB_PRIORITY_VERY_HIGH: + pfactor = MPOOL_PRI_VERY_HIGH; + break; + } + + adjust = 0; + if (pfactor != 0) + adjust = (int)c_mp->pages / pfactor; + + if (F_ISSET(bhp, BH_DIRTY)) + adjust += (int)c_mp->pages / MPOOL_PRI_DIRTY; + + if (adjust > 0) { + if (MPOOL_LRU_REDZONE - bhp->priority >= + (u_int32_t)adjust) + bhp->priority += adjust; + } else if (adjust < 0) + if (bhp->priority > (u_int32_t)-adjust) + bhp->priority += adjust; + } + + /* + * __memp_pgwrite only has a shared lock while it clears the + * BH_DIRTY bit. If we only have a shared latch then we can't + * touch the flags bits. + */ + if (F_ISSET(bhp, BH_EXCLUSIVE)) + F_CLR(bhp, BH_EXCLUSIVE); + MUTEX_UNLOCK(env, bhp->mtx_buf); + + /* + * On every buffer put we update the cache lru priority and check + * for wraparound. The increment doesn't need to be atomic: occasional + * lost increments are okay; __memp_reset_lru handles race conditions. + */ + if (++c_mp->lru_priority >= MPOOL_LRU_REDZONE && + (t_ret = __memp_reset_lru(env, infop)) != 0 && ret == 0) + ret = t_ret; + + return (ret); +} + +/* + * __memp_reset_lru -- + * Reset the cache LRU priority when it reaches the upper limit. + */ +static int +__memp_reset_lru(env, infop) + ENV *env; + REGINFO *infop; +{ + BH *bhp, *tbhp; + DB_MPOOL_HASH *hp; + MPOOL *c_mp; + u_int32_t bucket; + int reset; + + /* + * Update the priority so all future allocations will start at the + * bottom. Lock this cache region to ensure that exactly one thread + * will reset this cache's buffers. + */ + c_mp = infop->primary; + MPOOL_REGION_LOCK(env, infop); + reset = c_mp->lru_priority >= MPOOL_LRU_DECREMENT; + if (reset) { + c_mp->lru_priority -= MPOOL_LRU_DECREMENT; + c_mp->lru_generation++; + } + MPOOL_REGION_UNLOCK(env, infop); + + if (!reset) + return (0); + + /* Reduce the priority of every buffer in this cache region. */ + for (hp = R_ADDR(infop, c_mp->htab), + bucket = 0; bucket < c_mp->htab_buckets; ++hp, ++bucket) { + /* + * Skip empty buckets. + * + * We can check for empty buckets before locking as we + * only care if the pointer is zero or non-zero. + */ + if (SH_TAILQ_FIRST(&hp->hash_bucket, __bh) == NULL) + continue; + + MUTEX_LOCK(env, hp->mtx_hash); + SH_TAILQ_FOREACH(bhp, &hp->hash_bucket, hq, __bh) { + for (tbhp = bhp; tbhp != NULL; + tbhp = SH_CHAIN_PREV(tbhp, vc, __bh)) { + if (tbhp->priority > MPOOL_LRU_DECREMENT) + tbhp->priority -= MPOOL_LRU_DECREMENT; + else + tbhp->priority = 0; + } + } + MUTEX_UNLOCK(env, hp->mtx_hash); + } + + COMPQUIET(env, NULL); + return (0); +} + +/* + * __memp_unpin_buffers -- + * Unpin buffers pinned by a thread. + * + * PUBLIC: int __memp_unpin_buffers __P((ENV *, DB_THREAD_INFO *)); + */ +int +__memp_unpin_buffers(env, ip) + ENV *env; + DB_THREAD_INFO *ip; +{ + BH *bhp; + DB_MPOOL *dbmp; + DB_MPOOLFILE dbmf; + PIN_LIST *list, *lp; + REGINFO *rinfop, *reginfo; + int ret; + + memset(&dbmf, 0, sizeof(dbmf)); + dbmf.env = env; + dbmf.flags = MP_DUMMY; + dbmp = env->mp_handle; + reginfo = env->reginfo; + + list = R_ADDR(reginfo, ip->dbth_pinlist); + for (lp = list; lp < &list[ip->dbth_pinmax]; lp++) { + if (lp->b_ref == INVALID_ROFF) + continue; + rinfop = &dbmp->reginfo[lp->region]; + bhp = R_ADDR(rinfop, lp->b_ref); + dbmf.mfp = R_ADDR(dbmp->reginfo, bhp->mf_offset); + if ((ret = __memp_fput(&dbmf, ip, + (u_int8_t *)bhp + SSZA(BH, buf), + DB_PRIORITY_UNCHANGED)) != 0) + return (ret); + } + return (0); +} diff -r 000000000000 -r a1985f14b030 src/mp/mp_fset.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/mp/mp_fset.c Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,145 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 1996, 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + * $Id$ + */ + +#include "db_config.h" + +#include "db_int.h" +#include "dbinc/log.h" +#include "dbinc/mp.h" +#include "dbinc/txn.h" + +/* + * __memp_dirty -- + * Upgrade a page from a read-only to a writable pointer. + * + * PUBLIC: int __memp_dirty __P((DB_MPOOLFILE *, void *, + * PUBLIC: DB_THREAD_INFO *, DB_TXN *, DB_CACHE_PRIORITY, u_int32_t)); + */ +int +__memp_dirty(dbmfp, addrp, ip, txn, priority, flags) + DB_MPOOLFILE *dbmfp; + void *addrp; + DB_THREAD_INFO *ip; + DB_TXN *txn; + DB_CACHE_PRIORITY priority; + u_int32_t flags; +{ + BH *bhp; + DB_MPOOL *dbmp; + DB_MPOOL_HASH *hp; + ENV *env; + MPOOL *c_mp; + REGINFO *infop; + db_pgno_t pgno; + void *pgaddr; + + env = dbmfp->env; + dbmp = env->mp_handle; + + /* Convert the page address to a buffer header. */ + pgaddr = *(void **)addrp; + bhp = (BH *)((u_int8_t *)pgaddr - SSZA(BH, buf)); + pgno = bhp->pgno; + + /* If we have it exclusively then its already dirty. */ + if (F_ISSET(bhp, BH_EXCLUSIVE)) { + DB_ASSERT(env, F_ISSET(bhp, BH_DIRTY)); + return (0); + } + + if (flags == 0) + flags = DB_MPOOL_DIRTY; + DB_ASSERT(env, flags == DB_MPOOL_DIRTY || flags == DB_MPOOL_EDIT); + + if (F_ISSET(dbmfp, MP_READONLY)) { + __db_errx(env, DB_STR_A("3008", + "%s: dirty flag set for readonly file page", "%s"), + __memp_fn(dbmfp)); + return (EACCES); + } + + infop = &dbmp->reginfo[bhp->region]; + c_mp = infop->primary; + hp = R_ADDR(infop, c_mp->htab); + hp = &hp[bhp->bucket]; + + /* Drop the shared latch and get an exclusive. We have the buf ref'ed.*/ + MUTEX_UNLOCK(env, bhp->mtx_buf); + MUTEX_LOCK(env, bhp->mtx_buf); + DB_ASSERT(env, !F_ISSET(bhp, BH_EXCLUSIVE)); + F_SET(bhp, BH_EXCLUSIVE); + + /* Set/clear the page bits. */ + if (!F_ISSET(bhp, BH_DIRTY)) { +#ifdef DIAGNOSTIC + MUTEX_LOCK(env, hp->mtx_hash); +#endif + atomic_inc(env, &hp->hash_page_dirty); + F_SET(bhp, BH_DIRTY); +#ifdef DIAGNOSTIC + MUTEX_UNLOCK(env, hp->mtx_hash); +#endif + } + + DB_ASSERT(env, !F_ISSET(bhp, BH_DIRTY) || + atomic_read(&hp->hash_page_dirty) != 0); + COMPQUIET(ip, NULL); + COMPQUIET(txn, NULL); + COMPQUIET(priority, 0); + return (0); +} + +/* + * __memp_shared -- + * Downgrade a page from exlusively held to shared. + * + * PUBLIC: int __memp_shared __P((DB_MPOOLFILE *, void *)); + */ +int +__memp_shared(dbmfp, pgaddr) + DB_MPOOLFILE *dbmfp; + void *pgaddr; +{ + BH *bhp; + ENV *env; + + env = dbmfp->env; + /* Convert the page address to a buffer header. */ + bhp = (BH *)((u_int8_t *)pgaddr - SSZA(BH, buf)); + + if (F_ISSET(bhp, BH_DIRTY)) + dbmfp->mfp->file_written = 1; + DB_ASSERT(env, F_ISSET(bhp, BH_EXCLUSIVE)); + F_CLR(bhp, BH_EXCLUSIVE); + MUTEX_UNLOCK(env, bhp->mtx_buf); + MUTEX_READLOCK(env, bhp->mtx_buf); + + return (0); +} diff -r 000000000000 -r a1985f14b030 src/mp/mp_method.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/mp/mp_method.c Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,1113 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 1996, 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + * $Id$ + */ + +#include "db_config.h" + +#include "db_int.h" +#include "dbinc/mp.h" +#include "dbinc/db_page.h" +#include "dbinc/hash.h" + +/* + * __memp_env_create -- + * Mpool specific creation of the DB_ENV structure. + * + * PUBLIC: int __memp_env_create __P((DB_ENV *)); + */ +int +__memp_env_create(dbenv) + DB_ENV *dbenv; +{ + /* + * !!! + * Our caller has not yet had the opportunity to reset the panic + * state or turn off mutex locking, and so we can neither check + * the panic state or acquire a mutex in the DB_ENV create path. + * + * We default to 32 8K pages. We don't default to a flat 256K, because + * we want to include the size of the buffer header which can vary + * from system to system. + */ + dbenv->mp_bytes = + 32 * ((8 * 1024) + sizeof(BH)) + 37 * sizeof(DB_MPOOL_HASH); + dbenv->mp_ncache = 1; + + return (0); +} + +/* + * __memp_env_destroy -- + * Mpool specific destruction of the DB_ENV structure. + * + * PUBLIC: void __memp_env_destroy __P((DB_ENV *)); + */ +void +__memp_env_destroy(dbenv) + DB_ENV *dbenv; +{ + COMPQUIET(dbenv, NULL); +} + +/* + * __memp_get_cachesize -- + * {DB_ENV,DB}->get_cachesize. + * + * PUBLIC: int __memp_get_cachesize + * PUBLIC: __P((DB_ENV *, u_int32_t *, u_int32_t *, int *)); + */ +int +__memp_get_cachesize(dbenv, gbytesp, bytesp, ncachep) + DB_ENV *dbenv; + u_int32_t *gbytesp, *bytesp; + int *ncachep; +{ + DB_MPOOL *dbmp; + ENV *env; + MPOOL *mp; + + env = dbenv->env; + + ENV_NOT_CONFIGURED(env, + env->mp_handle, "DB_ENV->get_cachesize", DB_INIT_MPOOL); + + if (MPOOL_ON(env)) { + dbmp = env->mp_handle; + mp = dbmp->reginfo[0].primary; + if (gbytesp != NULL) + *gbytesp = mp->gbytes; + if (bytesp != NULL) + *bytesp = mp->bytes; + if (ncachep != NULL) + *ncachep = (int)mp->nreg; + } else { + if (gbytesp != NULL) + *gbytesp = dbenv->mp_gbytes; + if (bytesp != NULL) + *bytesp = dbenv->mp_bytes; + if (ncachep != NULL) + *ncachep = (int)dbenv->mp_ncache; + } + + return (0); +} + +/* + * __memp_set_cachesize -- + * {DB_ENV,DB}->set_cachesize. + * + * PUBLIC: int __memp_set_cachesize __P((DB_ENV *, u_int32_t, u_int32_t, int)); + */ +int +__memp_set_cachesize(dbenv, gbytes, bytes, arg_ncache) + DB_ENV *dbenv; + u_int32_t gbytes, bytes; + int arg_ncache; +{ + ENV *env; + DB_THREAD_INFO *ip; + u_int ncache; + int ret; + + env = dbenv->env; + ret = 0; + ENV_NOT_CONFIGURED(env, + env->mp_handle, "DB_ENV->set_cachesize", DB_INIT_MPOOL); + + /* Normalize the cache count. */ + ncache = arg_ncache <= 0 ? 1 : (u_int)arg_ncache; + + /* + * You can only store 4GB-1 in an unsigned 32-bit value, so correct for + * applications that specify 4GB cache sizes -- we know what they meant. + */ + if (sizeof(roff_t) == 4 && gbytes / ncache == 4 && bytes == 0) { + --gbytes; + bytes = GIGABYTE - 1; + } else { + gbytes += bytes / GIGABYTE; + bytes %= GIGABYTE; + } + + /* + * !!! + * With 32-bit region offsets, individual cache regions must be smaller + * than 4GB. Also, cache sizes larger than 10TB would cause 32-bit + * wrapping in the calculation of the number of hash buckets. See + * __memp_open for details. + */ + if (!F_ISSET(env, ENV_OPEN_CALLED)) { + if (sizeof(roff_t) <= 4 && gbytes / ncache >= 4) { + __db_errx(env, DB_STR("3003", + "individual cache size too large: maximum is 4GB")); + return (EINVAL); + } + if (gbytes / ncache > 10000) { + __db_errx(env, DB_STR("3004", + "individual cache size too large: maximum is 10TB")); + return (EINVAL); + } + } + + /* + * If the application requested less than 500Mb, increase the cachesize + * by 25% and factor in the size of the hash buckets to account for our + * overhead. (I'm guessing caches over 500Mb are specifically sized, + * that is, it's a large server and the application actually knows how + * much memory is available. We only document the 25% overhead number, + * not the hash buckets, but I don't see a reason to confuse the issue, + * it shouldn't matter to an application.) + * + * There is a minimum cache size, regardless. + */ + if (gbytes == 0) { + if (bytes < 500 * MEGABYTE) + bytes += (bytes / 4) + 37 * sizeof(DB_MPOOL_HASH); + if (bytes / ncache < DB_CACHESIZE_MIN) + bytes = ncache * DB_CACHESIZE_MIN; + } + + if (F_ISSET(env, ENV_OPEN_CALLED)) { + ENV_ENTER(env, ip); + ret = __memp_resize(env->mp_handle, gbytes, bytes); + ENV_LEAVE(env, ip); + return ret; + } + + dbenv->mp_gbytes = gbytes; + dbenv->mp_bytes = bytes; + dbenv->mp_ncache = ncache; + + return (0); +} + +/* + * __memp_set_config -- + * Set the cache subsystem configuration. + * + * PUBLIC: int __memp_set_config __P((DB_ENV *, u_int32_t, int)); + */ +int +__memp_set_config(dbenv, which, on) + DB_ENV *dbenv; + u_int32_t which; + int on; +{ + DB_MPOOL *dbmp; + ENV *env; + MPOOL *mp; + + env = dbenv->env; + + ENV_NOT_CONFIGURED(env, + env->mp_handle, "DB_ENV->memp_set_config", DB_INIT_MPOOL); + + switch (which) { + case DB_MEMP_SUPPRESS_WRITE: + case DB_MEMP_SYNC_INTERRUPT: + if (MPOOL_ON(env)) { + dbmp = env->mp_handle; + mp = dbmp->reginfo[0].primary; + if (on) + FLD_SET(mp->config_flags, which); + else + FLD_CLR(mp->config_flags, which); + } + break; + default: + return (EINVAL); + } + return (0); +} + +/* + * __memp_get_config -- + * Return the cache subsystem configuration. + * + * PUBLIC: int __memp_get_config __P((DB_ENV *, u_int32_t, int *)); + */ +int +__memp_get_config(dbenv, which, onp) + DB_ENV *dbenv; + u_int32_t which; + int *onp; +{ + DB_MPOOL *dbmp; + ENV *env; + MPOOL *mp; + + env = dbenv->env; + + ENV_REQUIRES_CONFIG(env, + env->mp_handle, "DB_ENV->memp_get_config", DB_INIT_MPOOL); + + switch (which) { + case DB_MEMP_SUPPRESS_WRITE: + case DB_MEMP_SYNC_INTERRUPT: + if (MPOOL_ON(env)) { + dbmp = env->mp_handle; + mp = dbmp->reginfo[0].primary; + *onp = FLD_ISSET(mp->config_flags, which) ? 1 : 0; + } else + *onp = 0; + break; + default: + return (EINVAL); + } + return (0); +} + +/* + * PUBLIC: int __memp_get_mp_max_openfd __P((DB_ENV *, int *)); + */ +int +__memp_get_mp_max_openfd(dbenv, maxopenfdp) + DB_ENV *dbenv; + int *maxopenfdp; +{ + DB_MPOOL *dbmp; + DB_THREAD_INFO *ip; + ENV *env; + MPOOL *mp; + + env = dbenv->env; + + ENV_NOT_CONFIGURED(env, + env->mp_handle, "DB_ENV->get_mp_max_openfd", DB_INIT_MPOOL); + + if (MPOOL_ON(env)) { + dbmp = env->mp_handle; + mp = dbmp->reginfo[0].primary; + ENV_ENTER(env, ip); + MPOOL_SYSTEM_LOCK(env); + *maxopenfdp = mp->mp_maxopenfd; + MPOOL_SYSTEM_UNLOCK(env); + ENV_LEAVE(env, ip); + } else + *maxopenfdp = dbenv->mp_maxopenfd; + return (0); +} + +/* + * __memp_set_mp_max_openfd -- + * Set the maximum number of open fd's when flushing the cache. + * PUBLIC: int __memp_set_mp_max_openfd __P((DB_ENV *, int)); + */ +int +__memp_set_mp_max_openfd(dbenv, maxopenfd) + DB_ENV *dbenv; + int maxopenfd; +{ + DB_MPOOL *dbmp; + DB_THREAD_INFO *ip; + ENV *env; + MPOOL *mp; + + env = dbenv->env; + + ENV_NOT_CONFIGURED(env, + env->mp_handle, "DB_ENV->set_mp_max_openfd", DB_INIT_MPOOL); + + if (MPOOL_ON(env)) { + dbmp = env->mp_handle; + mp = dbmp->reginfo[0].primary; + ENV_ENTER(env, ip); + MPOOL_SYSTEM_LOCK(env); + mp->mp_maxopenfd = maxopenfd; + MPOOL_SYSTEM_UNLOCK(env); + ENV_LEAVE(env, ip); + } else + dbenv->mp_maxopenfd = maxopenfd; + return (0); +} + +/* + * PUBLIC: int __memp_get_mp_max_write __P((DB_ENV *, int *, db_timeout_t *)); + */ +int +__memp_get_mp_max_write(dbenv, maxwritep, maxwrite_sleepp) + DB_ENV *dbenv; + int *maxwritep; + db_timeout_t *maxwrite_sleepp; +{ + DB_MPOOL *dbmp; + DB_THREAD_INFO *ip; + ENV *env; + MPOOL *mp; + + env = dbenv->env; + + ENV_NOT_CONFIGURED(env, + env->mp_handle, "DB_ENV->get_mp_max_write", DB_INIT_MPOOL); + + if (MPOOL_ON(env)) { + dbmp = env->mp_handle; + mp = dbmp->reginfo[0].primary; + ENV_ENTER(env, ip); + MPOOL_SYSTEM_LOCK(env); + *maxwritep = mp->mp_maxwrite; + *maxwrite_sleepp = mp->mp_maxwrite_sleep; + MPOOL_SYSTEM_UNLOCK(env); + ENV_LEAVE(env, ip); + } else { + *maxwritep = dbenv->mp_maxwrite; + *maxwrite_sleepp = dbenv->mp_maxwrite_sleep; + } + return (0); +} + +/* + * __memp_set_mp_max_write -- + * Set the maximum continuous I/O count. + * + * PUBLIC: int __memp_set_mp_max_write __P((DB_ENV *, int, db_timeout_t)); + */ +int +__memp_set_mp_max_write(dbenv, maxwrite, maxwrite_sleep) + DB_ENV *dbenv; + int maxwrite; + db_timeout_t maxwrite_sleep; +{ + DB_MPOOL *dbmp; + DB_THREAD_INFO *ip; + ENV *env; + MPOOL *mp; + + env = dbenv->env; + + ENV_NOT_CONFIGURED(env, + env->mp_handle, "DB_ENV->get_mp_max_write", DB_INIT_MPOOL); + + if (MPOOL_ON(env)) { + dbmp = env->mp_handle; + mp = dbmp->reginfo[0].primary; + ENV_ENTER(env, ip); + MPOOL_SYSTEM_LOCK(env); + mp->mp_maxwrite = maxwrite; + mp->mp_maxwrite_sleep = maxwrite_sleep; + MPOOL_SYSTEM_UNLOCK(env); + ENV_LEAVE(env, ip); + } else { + dbenv->mp_maxwrite = maxwrite; + dbenv->mp_maxwrite_sleep = maxwrite_sleep; + } + return (0); +} + +/* + * PUBLIC: int __memp_get_mp_mmapsize __P((DB_ENV *, size_t *)); + */ +int +__memp_get_mp_mmapsize(dbenv, mp_mmapsizep) + DB_ENV *dbenv; + size_t *mp_mmapsizep; +{ + DB_MPOOL *dbmp; + DB_THREAD_INFO *ip; + ENV *env; + MPOOL *mp; + + env = dbenv->env; + + ENV_NOT_CONFIGURED(env, + env->mp_handle, "DB_ENV->get_mp_max_mmapsize", DB_INIT_MPOOL); + + if (MPOOL_ON(env)) { + dbmp = env->mp_handle; + mp = dbmp->reginfo[0].primary; + ENV_ENTER(env, ip); + MPOOL_SYSTEM_LOCK(env); + *mp_mmapsizep = mp->mp_mmapsize; + MPOOL_SYSTEM_UNLOCK(env); + ENV_LEAVE(env, ip); + } else + *mp_mmapsizep = dbenv->mp_mmapsize; + return (0); +} + +/* + * __memp_set_mp_mmapsize -- + * DB_ENV->set_mp_mmapsize. + * + * PUBLIC: int __memp_set_mp_mmapsize __P((DB_ENV *, size_t)); + */ +int +__memp_set_mp_mmapsize(dbenv, mp_mmapsize) + DB_ENV *dbenv; + size_t mp_mmapsize; +{ + DB_MPOOL *dbmp; + DB_THREAD_INFO *ip; + ENV *env; + MPOOL *mp; + + env = dbenv->env; + + ENV_NOT_CONFIGURED(env, + env->mp_handle, "DB_ENV->set_mp_max_mmapsize", DB_INIT_MPOOL); + + if (MPOOL_ON(env)) { + dbmp = env->mp_handle; + mp = dbmp->reginfo[0].primary; + ENV_ENTER(env, ip); + MPOOL_SYSTEM_LOCK(env); + /* + * We need to cast here because size_t and db_size_t can be + * different on a 64 bit build, when building in 32 bit + * compatibility mode. The cast is safe, because we check for + * overflow when the fields are assigned. + */ + mp->mp_mmapsize = (db_size_t)mp_mmapsize; + MPOOL_SYSTEM_UNLOCK(env); + ENV_LEAVE(env, ip); + } else + dbenv->mp_mmapsize = (db_size_t)mp_mmapsize; + return (0); +} + +/* + * PUBLIC: int __memp_get_mp_pagesize __P((DB_ENV *, u_int32_t *)); + */ +int +__memp_get_mp_pagesize(dbenv, mp_pagesizep) + DB_ENV *dbenv; + u_int32_t *mp_pagesizep; +{ + DB_MPOOL *dbmp; + ENV *env; + MPOOL *mp; + + env = dbenv->env; + + ENV_NOT_CONFIGURED(env, + env->mp_handle, "DB_ENV->get_mp_max_pagesize", DB_INIT_MPOOL); + + if (MPOOL_ON(env)) { + dbmp = env->mp_handle; + mp = dbmp->reginfo[0].primary; + *mp_pagesizep = mp->pagesize; + } else { + *mp_pagesizep = dbenv->mp_pagesize; + } + return (0); +} + +/* + * __memp_set_mp_pagesize -- + * DB_ENV->set_mp_pagesize. + * + * PUBLIC: int __memp_set_mp_pagesize __P((DB_ENV *, u_int32_t)); + */ +int +__memp_set_mp_pagesize(dbenv, mp_pagesize) + DB_ENV *dbenv; + u_int32_t mp_pagesize; +{ + ENV *env; + + env = dbenv->env; + + ENV_NOT_CONFIGURED(env, + env->mp_handle, "DB_ENV->get_mp_max_mmapsize", DB_INIT_MPOOL); + ENV_ILLEGAL_AFTER_OPEN(env, "DB_ENV->set_mp_pagesize"); + + dbenv->mp_pagesize = mp_pagesize; + return (0); +} + +/* + * PUBLIC: int __memp_get_mp_tablesize __P((DB_ENV *, u_int32_t *)); + */ +int +__memp_get_mp_tablesize(dbenv, mp_tablesizep) + DB_ENV *dbenv; + u_int32_t *mp_tablesizep; +{ + DB_MPOOL *dbmp; + ENV *env; + MPOOL *mp; + + env = dbenv->env; + + ENV_NOT_CONFIGURED(env, + env->mp_handle, "DB_ENV->get_mp_max_tablesize", DB_INIT_MPOOL); + + if (MPOOL_ON(env)) { + dbmp = env->mp_handle; + mp = dbmp->reginfo[0].primary; + *mp_tablesizep = mp->htab_buckets; + } else + *mp_tablesizep = dbenv->mp_tablesize; + return (0); +} + +/* + * __memp_set_mp_tablesize -- + * DB_ENV->set_mp_tablesize. + * + * PUBLIC: int __memp_set_mp_tablesize __P((DB_ENV *, u_int32_t)); + */ +int +__memp_set_mp_tablesize(dbenv, mp_tablesize) + DB_ENV *dbenv; + u_int32_t mp_tablesize; +{ + ENV *env; + + env = dbenv->env; + + ENV_NOT_CONFIGURED(env, + env->mp_handle, "DB_ENV->get_mp_max_mmapsize", DB_INIT_MPOOL); + ENV_ILLEGAL_AFTER_OPEN(env, "DB_ENV->set_mp_tablesize"); + + dbenv->mp_tablesize = mp_tablesize; + return (0); +} + +/* + * PUBLIC: int __memp_get_mp_mtxcount __P((DB_ENV *, u_int32_t *)); + */ +int +__memp_get_mp_mtxcount(dbenv, mp_mtxcountp) + DB_ENV *dbenv; + u_int32_t *mp_mtxcountp; +{ + DB_MPOOL *dbmp; + ENV *env; + MPOOL *mp; + + env = dbenv->env; + + ENV_NOT_CONFIGURED(env, + env->mp_handle, "DB_ENV->get_mp_max_mtxcount", DB_INIT_MPOOL); + + if (MPOOL_ON(env)) { + dbmp = env->mp_handle; + mp = dbmp->reginfo[0].primary; + *mp_mtxcountp = mp->htab_mutexes; + } else + *mp_mtxcountp = dbenv->mp_mtxcount; + return (0); +} + +/* + * __memp_set_mp_mtxcount -- + * DB_ENV->set_mp_mtxcount. + * + * PUBLIC: int __memp_set_mp_mtxcount __P((DB_ENV *, u_int32_t)); + */ +int +__memp_set_mp_mtxcount(dbenv, mp_mtxcount) + DB_ENV *dbenv; + u_int32_t mp_mtxcount; +{ + ENV *env; + + env = dbenv->env; + + ENV_NOT_CONFIGURED(env, + env->mp_handle, "DB_ENV->get_mp_max_mmapsize", DB_INIT_MPOOL); + ENV_ILLEGAL_AFTER_OPEN(env, "DB_ENV->set_mp_mtxcount"); + + dbenv->mp_mtxcount = mp_mtxcount; + return (0); +} + +/* + * __memp_nameop + * Remove or rename a file in the pool. + * + * PUBLIC: int __memp_nameop __P((ENV *, + * PUBLIC: u_int8_t *, const char *, const char *, const char *, int)); + * + * XXX + * Undocumented interface: DB private. + */ +int +__memp_nameop(env, fileid, newname, fullold, fullnew, inmem) + ENV *env; + u_int8_t *fileid; + const char *newname, *fullold, *fullnew; + int inmem; +{ + DB_MPOOL *dbmp; + DB_MPOOL_HASH *hp, *nhp; + MPOOL *mp; + MPOOLFILE *mfp; + roff_t newname_off; + u_int32_t bucket; + int locked, ret; + size_t nlen; + void *p; + +#undef op_is_remove +#define op_is_remove (newname == NULL) + + COMPQUIET(bucket, 0); + COMPQUIET(hp, NULL); + COMPQUIET(newname_off, 0); + COMPQUIET(nlen, 0); + + dbmp = NULL; + mfp = NULL; + nhp = NULL; + p = NULL; + locked = ret = 0; + + if (!MPOOL_ON(env)) + goto fsop; + + dbmp = env->mp_handle; + mp = dbmp->reginfo[0].primary; + hp = R_ADDR(dbmp->reginfo, mp->ftab); + + if (!op_is_remove) { + nlen = strlen(newname); + if ((ret = __memp_alloc(dbmp, dbmp->reginfo, + NULL, nlen + 1, &newname_off, &p)) != 0) + return (ret); + memcpy(p, newname, nlen + 1); + } + + /* + * Remove or rename a file that the mpool might know about. We assume + * that the fop layer has the file locked for exclusive access, so we + * don't worry about locking except for the mpool mutexes. Checkpoint + * can happen at any time, independent of file locking, so we have to + * do the actual unlink or rename system call while holding + * all affected buckets locked. + * + * If this is a rename and this is a memory file then we need + * to make sure that the new name does not exist. Since we + * are locking two buckets lock them in ascending order. + */ + if (inmem) { + DB_ASSERT(env, fullold != NULL); + hp += FNBUCKET(fullold, strlen(fullold)); + if (!op_is_remove) { + bucket = FNBUCKET(newname, nlen); + nhp = R_ADDR(dbmp->reginfo, mp->ftab); + nhp += bucket; + } + } else + hp += FNBUCKET(fileid, DB_FILE_ID_LEN); + + if (nhp != NULL && nhp < hp) + MUTEX_LOCK(env, nhp->mtx_hash); + MUTEX_LOCK(env, hp->mtx_hash); + if (nhp != NULL && nhp > hp) + MUTEX_LOCK(env, nhp->mtx_hash); + locked = 1; + + if (!op_is_remove && inmem) { + SH_TAILQ_FOREACH(mfp, &nhp->hash_bucket, q, __mpoolfile) + if (!mfp->deadfile && + mfp->no_backing_file && strcmp(newname, + R_ADDR(dbmp->reginfo, mfp->path_off)) == 0) + break; + if (mfp != NULL) { + ret = EEXIST; + goto err; + } + } + + /* + * Find the file -- if mpool doesn't know about this file, that may + * not be an error. + */ + SH_TAILQ_FOREACH(mfp, &hp->hash_bucket, q, __mpoolfile) { + /* Ignore non-active files. */ + if (mfp->deadfile || F_ISSET(mfp, MP_TEMP)) + continue; + + /* Try to match on fileid. */ + if (memcmp(fileid, R_ADDR( + dbmp->reginfo, mfp->fileid_off), DB_FILE_ID_LEN) != 0) + continue; + + break; + } + + if (mfp == NULL) { + if (inmem) { + ret = ENOENT; + goto err; + } + goto fsop; + } + + if (op_is_remove) { + MUTEX_LOCK(env, mfp->mutex); + /* + * In-memory dbs have an artificially incremented ref count so + * they do not get reclaimed as long as they exist. Since we + * are now deleting the database, we need to dec that count. + */ + if (mfp->no_backing_file) + mfp->mpf_cnt--; + mfp->deadfile = 1; + MUTEX_UNLOCK(env, mfp->mutex); + } else { + /* + * Else, it's a rename. We've allocated memory for the new + * name. Swap it with the old one. If it's in memory we + * need to move it the right bucket. + */ + p = R_ADDR(dbmp->reginfo, mfp->path_off); + mfp->path_off = newname_off; + + if (inmem && hp != nhp) { + DB_ASSERT(env, nhp != NULL); + SH_TAILQ_REMOVE(&hp->hash_bucket, mfp, q, __mpoolfile); + mfp->bucket = bucket; + SH_TAILQ_INSERT_TAIL(&nhp->hash_bucket, mfp, q); + } + } + +fsop: /* + * If this is a real file, then mfp could be NULL, because + * mpool isn't turned on, and we still need to do the file ops. + */ + if (mfp == NULL || !mfp->no_backing_file) { + if (op_is_remove) { + /* + * !!! + * Replication may ask us to unlink a file that's been + * renamed. Don't complain if it doesn't exist. + */ + if ((ret = __os_unlink(env, fullold, 0)) == ENOENT) + ret = 0; + } else { + /* + * Defensive only, fullnew should never be + * NULL. + */ + DB_ASSERT(env, fullnew != NULL); + if (fullnew == NULL) { + ret = EINVAL; + goto err; + } + ret = __os_rename(env, fullold, fullnew, 1); + } + } + + /* Delete the memory we no longer need. */ +err: if (p != NULL) { + MPOOL_REGION_LOCK(env, &dbmp->reginfo[0]); + __memp_free(&dbmp->reginfo[0], p); + MPOOL_REGION_UNLOCK(env, &dbmp->reginfo[0]); + } + + /* If we have buckets locked, unlock them when done moving files. */ + if (locked == 1) { + MUTEX_UNLOCK(env, hp->mtx_hash); + if (nhp != NULL && nhp != hp) + MUTEX_UNLOCK(env, nhp->mtx_hash); + } + return (ret); +} + +/* + * __memp_ftruncate __ + * Truncate the file. + * + * PUBLIC: int __memp_ftruncate __P((DB_MPOOLFILE *, DB_TXN *, + * PUBLIC: DB_THREAD_INFO *, db_pgno_t, u_int32_t)); + */ +int +__memp_ftruncate(dbmfp, txn, ip, pgno, flags) + DB_MPOOLFILE *dbmfp; + DB_TXN *txn; + DB_THREAD_INFO *ip; + db_pgno_t pgno; + u_int32_t flags; +{ + ENV *env; + MPOOLFILE *mfp; + void *pagep; + db_pgno_t last_pgno, pg; + int ret; + + env = dbmfp->env; + mfp = dbmfp->mfp; + ret = 0; + + MUTEX_LOCK(env, mfp->mutex); + last_pgno = mfp->last_pgno; + MUTEX_UNLOCK(env, mfp->mutex); + + if (pgno > last_pgno) { + if (LF_ISSET(MP_TRUNC_RECOVER)) + return (0); + __db_errx(env, DB_STR("3005", + "Truncate beyond the end of file")); + return (EINVAL); + } + + pg = pgno; + if (!LF_ISSET(MP_TRUNC_NOCACHE)) + do { + if (mfp->block_cnt == 0) + break; + if ((ret = __memp_fget(dbmfp, &pg, + ip, txn, DB_MPOOL_FREE, &pagep)) != 0) + return (ret); + } while (pg++ < last_pgno); + + /* + * If we are aborting an extend of a file, the call to __os_truncate + * could extend the file if the new page(s) had not yet been + * written to disk. We do not want to extend the file to pages + * whose log records are not yet flushed [#14031]. In addition if + * we are out of disk space we can generate an error [#12743]. + */ + MUTEX_LOCK(env, mfp->mutex); + if (!F_ISSET(mfp, MP_TEMP) && + !mfp->no_backing_file && pgno <= mfp->last_flushed_pgno) +#ifdef HAVE_FTRUNCATE + ret = __os_truncate(env, + dbmfp->fhp, pgno, mfp->pagesize); +#else + ret = __db_zero_extend(env, + dbmfp->fhp, pgno, mfp->last_pgno, mfp->pagesize); +#endif + + /* + * This set could race with another thread of control that extending + * the file. It's not a problem because we should have the page + * locked at a higher level of the system. + */ + if (ret == 0) { + mfp->last_pgno = pgno - 1; + if (mfp->last_flushed_pgno > mfp->last_pgno) + mfp->last_flushed_pgno = mfp->last_pgno; + } + MUTEX_UNLOCK(env, mfp->mutex); + + return (ret); +} + +#ifdef HAVE_FTRUNCATE +/* + * Support routines for maintaining a sorted freelist while we try to rearrange + * and truncate the file. + */ + +/* + * __memp_alloc_freelist -- + * Allocate mpool space for the freelist. + * + * PUBLIC: int __memp_alloc_freelist __P((DB_MPOOLFILE *, + * PUBLIC: u_int32_t, db_pgno_t **)); + */ +int +__memp_alloc_freelist(dbmfp, nelems, listp) + DB_MPOOLFILE *dbmfp; + u_int32_t nelems; + db_pgno_t **listp; +{ + DB_MPOOL *dbmp; + ENV *env; + MPOOLFILE *mfp; + void *retp; + int ret; + + env = dbmfp->env; + dbmp = env->mp_handle; + mfp = dbmfp->mfp; + + *listp = NULL; + + /* + * These fields are protected because the database layer + * has the metapage locked while manipulating them. + */ + mfp->free_ref++; + if (mfp->free_size != 0) + return (EBUSY); + + /* Allocate at least a few slots. */ + mfp->free_cnt = nelems; + if (nelems == 0) + nelems = 50; + + if ((ret = __memp_alloc(dbmp, dbmp->reginfo, + NULL, nelems * sizeof(db_pgno_t), &mfp->free_list, &retp)) != 0) + return (ret); + + mfp->free_size = nelems * sizeof(db_pgno_t); + *listp = retp; + return (0); +} + +/* + * __memp_free_freelist -- + * Free the list. + * + * PUBLIC: int __memp_free_freelist __P((DB_MPOOLFILE *)); + */ +int +__memp_free_freelist(dbmfp) + DB_MPOOLFILE *dbmfp; +{ + DB_MPOOL *dbmp; + ENV *env; + MPOOLFILE *mfp; + + env = dbmfp->env; + dbmp = env->mp_handle; + mfp = dbmfp->mfp; + + DB_ASSERT(env, mfp->free_ref > 0); + if (--mfp->free_ref > 0) + return (0); + + DB_ASSERT(env, mfp->free_size != 0); + + MPOOL_SYSTEM_LOCK(env); + __memp_free(dbmp->reginfo, R_ADDR(dbmp->reginfo, mfp->free_list)); + MPOOL_SYSTEM_UNLOCK(env); + + mfp->free_cnt = 0; + mfp->free_list = 0; + mfp->free_size = 0; + return (0); +} + +/* + * __memp_get_freelst -- + * Return current list. + * + * PUBLIC: int __memp_get_freelist __P(( + * PUBLIC: DB_MPOOLFILE *, u_int32_t *, db_pgno_t **)); + */ +int +__memp_get_freelist(dbmfp, nelemp, listp) + DB_MPOOLFILE *dbmfp; + u_int32_t *nelemp; + db_pgno_t **listp; +{ + DB_MPOOL *dbmp; + ENV *env; + MPOOLFILE *mfp; + + env = dbmfp->env; + dbmp = env->mp_handle; + mfp = dbmfp->mfp; + + if (mfp->free_size == 0) { + *nelemp = 0; + *listp = NULL; + } else { + *nelemp = mfp->free_cnt; + *listp = R_ADDR(dbmp->reginfo, mfp->free_list); + } + + return (0); +} + +/* + * __memp_extend_freelist -- + * Extend the list. + * + * PUBLIC: int __memp_extend_freelist __P(( + * PUBLIC: DB_MPOOLFILE *, u_int32_t , db_pgno_t **)); + */ +int +__memp_extend_freelist(dbmfp, count, listp) + DB_MPOOLFILE *dbmfp; + u_int32_t count; + db_pgno_t **listp; +{ + DB_MPOOL *dbmp; + ENV *env; + MPOOLFILE *mfp; + int ret; + size_t size; + void *retp; + + env = dbmfp->env; + dbmp = env->mp_handle; + mfp = dbmfp->mfp; + + if (mfp->free_size == 0) + return (EINVAL); + + if (count * sizeof(db_pgno_t) > mfp->free_size) { + size = (size_t)DB_ALIGN(count * sizeof(db_pgno_t), 512); +#ifdef HAVE_MIXED_SIZE_ADDRESSING + if (size >= 0xFFFFFFFF) { + __db_errx(env, DB_STR("3006", + "Can't get the required free size while" + "operating in mixed-size-addressing mode")); + return EINVAL; + } +#endif + *listp = R_ADDR(dbmp->reginfo, mfp->free_list); + if ((ret = __memp_alloc(dbmp, dbmp->reginfo, + NULL, size, &mfp->free_list, &retp)) != 0) + return (ret); + mfp->free_size = (db_size_t)size; + + memcpy(retp, *listp, mfp->free_cnt * sizeof(db_pgno_t)); + + MPOOL_SYSTEM_LOCK(env); + __memp_free(dbmp->reginfo, *listp); + MPOOL_SYSTEM_UNLOCK(env); + } + + mfp->free_cnt = count; + *listp = R_ADDR(dbmp->reginfo, mfp->free_list); + + return (0); +} +#endif + +/* + * __memp_set_last_pgno -- set the last page of the file + * + * PUBLIC: int __memp_set_last_pgno __P((DB_MPOOLFILE *, db_pgno_t)); + */ +int +__memp_set_last_pgno(dbmfp, pgno) + DB_MPOOLFILE *dbmfp; + db_pgno_t pgno; +{ + MPOOLFILE *mfp; + + mfp = dbmfp->mfp; + + if (mfp->mpf_cnt == 1) { + MUTEX_LOCK(dbmfp->env, mfp->mutex); + if (mfp->mpf_cnt == 1) + dbmfp->mfp->last_pgno = pgno; + MUTEX_UNLOCK(dbmfp->env, mfp->mutex); + } + return (0); +} diff -r 000000000000 -r a1985f14b030 src/mp/mp_region.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/mp/mp_region.c Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,642 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 1996, 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + * $Id$ + */ + +#include "db_config.h" + +#include "db_int.h" +#include "dbinc/mp.h" + +static int __memp_init_config __P((ENV *, MPOOL *)); +static void __memp_region_size __P((ENV *, roff_t *, u_int32_t *)); + +#define MPOOL_DEFAULT_PAGESIZE (4 * 1024) + +/* + * __memp_open -- + * Internal version of memp_open: only called from ENV->open. + * + * PUBLIC: int __memp_open __P((ENV *, int)); + */ +int +__memp_open(env, create_ok) + ENV *env; + int create_ok; +{ + DB_ENV *dbenv; + DB_MPOOL *dbmp; + MPOOL *mp, *mp_i; + REGINFO reginfo; + roff_t cache_size, max_size, reg_size; + u_int i, max_nreg; + u_int32_t htab_buckets, *regids; + int ret; + + dbenv = env->dbenv; + cache_size = 0; + + /* Calculate the region size and hash bucket count. */ + __memp_region_size(env, &max_size, &htab_buckets); + + /* Create and initialize the DB_MPOOL structure. */ + if ((ret = __os_calloc(env, 1, sizeof(*dbmp), &dbmp)) != 0) + return (ret); + LIST_INIT(&dbmp->dbregq); + TAILQ_INIT(&dbmp->dbmfq); + dbmp->env = env; + + /* Join/create the first mpool region. */ + memset(®info, 0, sizeof(REGINFO)); + reginfo.env = env; + reginfo.type = REGION_TYPE_MPOOL; + reginfo.id = INVALID_REGION_ID; + reginfo.flags = REGION_JOIN_OK; + + /* Calculate the minimum allocation. */ + reg_size = sizeof(MPOOL); + reg_size += MPOOL_FILE_BUCKETS * sizeof(DB_MPOOL_HASH); + reg_size += htab_buckets * sizeof(DB_MPOOL_HASH); + reg_size += (dbenv->mp_pagesize == 0 ? + MPOOL_DEFAULT_PAGESIZE : dbenv->mp_pagesize) * 10; + if (reg_size > max_size) + reg_size = max_size; + + if (create_ok) + F_SET(®info, REGION_CREATE_OK); + if ((ret = __env_region_attach(env, ®info, reg_size, max_size)) != 0) + goto err; + cache_size = reginfo.rp->max; + if (F_ISSET(env, ENV_PRIVATE)) + reginfo.max_alloc = reginfo.rp->max; + + /* + * If we created the region, initialize it. Create or join any + * additional regions. + */ + if (F_ISSET(®info, REGION_CREATE)) { + /* + * We define how many regions there are going to be, allocate + * the REGINFO structures and create them. Make sure we don't + * clear the wrong entries on error. + */ + max_nreg = __memp_max_regions(env); + if ((ret = __os_calloc(env, + max_nreg, sizeof(REGINFO), &dbmp->reginfo)) != 0) + goto err; + /* Make sure we don't clear the wrong entries on error. */ + dbmp->reginfo[0] = reginfo; + for (i = 1; i < max_nreg; ++i) + dbmp->reginfo[i].id = INVALID_REGION_ID; + + /* Initialize the first region. */ + if ((ret = __memp_init(env, dbmp, + 0, htab_buckets, max_nreg)) != 0) + goto err; + + /* + * Create/initialize remaining regions and copy their IDs into + * the first region. + */ + mp = R_ADDR(dbmp->reginfo, dbmp->reginfo[0].rp->primary); + regids = R_ADDR(dbmp->reginfo, mp->regids); + regids[0] = dbmp->reginfo[0].id; + for (i = 1; i < dbenv->mp_ncache; ++i) { + dbmp->reginfo[i].env = env; + dbmp->reginfo[i].type = REGION_TYPE_MPOOL; + dbmp->reginfo[i].id = INVALID_REGION_ID; + dbmp->reginfo[i].flags = REGION_CREATE_OK; + if ((ret = __env_region_attach( + env, &dbmp->reginfo[i], reg_size, max_size)) != 0) + goto err; + if (F_ISSET(env, ENV_PRIVATE)) + dbmp->reginfo[i].max_alloc = max_size; + cache_size += dbmp->reginfo[i].rp->max; + if ((ret = __memp_init(env, dbmp, + i, htab_buckets, max_nreg)) != 0) + goto err; + + regids[i] = dbmp->reginfo[i].id; + } + mp->gbytes = (u_int32_t) (cache_size / GIGABYTE); + mp->bytes = (u_int32_t) (cache_size % GIGABYTE); + } else { + /* + * Determine how many regions there are going to be, allocate + * the REGINFO structures and fill in local copies of that + * information. + */ + mp = R_ADDR(®info, reginfo.rp->primary); + dbenv->mp_ncache = mp->nreg; + if ((ret = __os_calloc(env, + mp->max_nreg, sizeof(REGINFO), &dbmp->reginfo)) != 0) + goto err; + /* Make sure we don't clear the wrong entries on error. */ + for (i = 0; i < dbenv->mp_ncache; ++i) + dbmp->reginfo[i].id = INVALID_REGION_ID; + dbmp->reginfo[0] = reginfo; + + /* Join remaining regions. */ + regids = R_ADDR(dbmp->reginfo, mp->regids); + for (i = 1; i < dbenv->mp_ncache; ++i) { + dbmp->reginfo[i].env = env; + dbmp->reginfo[i].type = REGION_TYPE_MPOOL; + dbmp->reginfo[i].id = regids[i]; + dbmp->reginfo[i].flags = REGION_JOIN_OK; + if ((ret = __env_region_attach( + env, &dbmp->reginfo[i], 0, 0)) != 0) + goto err; + } + } + + /* Set the local addresses for the regions. */ + for (i = 0; i < dbenv->mp_ncache; ++i) { + mp_i = dbmp->reginfo[i].primary = + R_ADDR(&dbmp->reginfo[i], dbmp->reginfo[i].rp->primary); + dbmp->reginfo[i].mtx_alloc = mp_i->mtx_region; + } + + /* If the region is threaded, allocate a mutex to lock the handles. */ + if ((ret = __mutex_alloc(env, + MTX_MPOOL_HANDLE, DB_MUTEX_PROCESS_ONLY, &dbmp->mutex)) != 0) + goto err; + + env->mp_handle = dbmp; + + /* A process joining the region may reset the mpool configuration. */ + if ((ret = __memp_init_config(env, mp)) != 0) + return (ret); + + return (0); + +err: env->mp_handle = NULL; + if (dbmp->reginfo != NULL && dbmp->reginfo[0].addr != NULL) { + for (i = 0; i < dbenv->mp_ncache; ++i) + if (dbmp->reginfo[i].id != INVALID_REGION_ID) + (void)__env_region_detach( + env, &dbmp->reginfo[i], 0); + __os_free(env, dbmp->reginfo); + } + + (void)__mutex_free(env, &dbmp->mutex); + __os_free(env, dbmp); + return (ret); +} + +/* + * __memp_init -- + * Initialize a MPOOL structure in shared memory. + * + * PUBLIC: int __memp_init + * PUBLIC: __P((ENV *, DB_MPOOL *, u_int, u_int32_t, u_int)); + */ +int +__memp_init(env, dbmp, reginfo_off, htab_buckets, max_nreg) + ENV *env; + DB_MPOOL *dbmp; + u_int reginfo_off, max_nreg; + u_int32_t htab_buckets; +{ + BH *frozen_bhp; + BH_FROZEN_ALLOC *frozen; + DB_ENV *dbenv; + DB_MPOOL_HASH *htab, *hp; + MPOOL *mp, *main_mp; + REGINFO *infop; + db_mutex_t mtx_base, mtx_discard, mtx_prev; + u_int32_t i; + int ret; + void *p; + + dbenv = env->dbenv; + + infop = &dbmp->reginfo[reginfo_off]; + if ((ret = __env_alloc(infop, sizeof(MPOOL), &infop->primary)) != 0) + goto mem_err; + infop->rp->primary = R_OFFSET(infop, infop->primary); + mp = infop->primary; + memset(mp, 0, sizeof(*mp)); + + if ((ret = + __mutex_alloc(env, MTX_MPOOL_REGION, 0, &mp->mtx_region)) != 0) + return (ret); + + if (reginfo_off == 0) { + ZERO_LSN(mp->lsn); + + mp->nreg = dbenv->mp_ncache; + mp->max_nreg = max_nreg; + if ((ret = __env_alloc(&dbmp->reginfo[0], + max_nreg * sizeof(u_int32_t), &p)) != 0) + goto mem_err; + mp->regids = R_OFFSET(dbmp->reginfo, p); + mp->nbuckets = dbenv->mp_ncache * htab_buckets; + + /* Allocate file table space and initialize it. */ + if ((ret = __env_alloc(infop, + MPOOL_FILE_BUCKETS * sizeof(DB_MPOOL_HASH), &htab)) != 0) + goto mem_err; + mp->ftab = R_OFFSET(infop, htab); + for (i = 0; i < MPOOL_FILE_BUCKETS; i++) { + if ((ret = __mutex_alloc(env, + MTX_MPOOL_FILE_BUCKET, 0, &htab[i].mtx_hash)) != 0) + return (ret); + SH_TAILQ_INIT(&htab[i].hash_bucket); + atomic_init(&htab[i].hash_page_dirty, 0); + } + + /* + * Allocate all of the hash bucket mutexes up front. We do + * this so that we don't need to free and reallocate mutexes as + * the cache is resized. + */ + mtx_base = mtx_prev = MUTEX_INVALID; + if (!MUTEX_ON(env) || F_ISSET(env, ENV_PRIVATE)) + goto no_prealloc; + for (i = 0; i < mp->max_nreg * dbenv->mp_mtxcount; i++) { + if ((ret = __mutex_alloc(env, MTX_MPOOL_HASH_BUCKET, + DB_MUTEX_SHARED, &mtx_discard)) != 0) + return (ret); + if (i == 0) + mtx_base = mtx_discard; + else + DB_ASSERT(env, mtx_base == MUTEX_INVALID || + mtx_discard == mtx_prev + 1); + mtx_prev = mtx_discard; + } + } else { + main_mp = dbmp->reginfo[0].primary; + htab = R_ADDR(&dbmp->reginfo[0], main_mp->htab); + mtx_base = htab[0].mtx_hash; + } + + /* + * We preallocated all of the mutexes in a block, so for regions after + * the first, we skip mutexes in use in earlier regions. Each region + * has the same number of buckets + */ +no_prealloc: + if (MUTEX_ON(env)) + mtx_base += reginfo_off * dbenv->mp_mtxcount; + + /* Allocate hash table space and initialize it. */ + if ((ret = __env_alloc(infop, + htab_buckets * sizeof(DB_MPOOL_HASH), &htab)) != 0) + goto mem_err; + mp->htab = R_OFFSET(infop, htab); + for (i = 0; i < htab_buckets; i++) { + hp = &htab[i]; + if (!MUTEX_ON(env) || dbenv->mp_mtxcount == 0) + hp->mtx_hash = MUTEX_INVALID; + else if (F_ISSET(env, ENV_PRIVATE)) { + if (i >= dbenv->mp_mtxcount) + hp->mtx_hash = + htab[i % dbenv->mp_mtxcount].mtx_hash; + else if + ((ret = __mutex_alloc(env, MTX_MPOOL_HASH_BUCKET, + DB_MUTEX_SHARED, &hp->mtx_hash)) != 0) + return (ret); + } else + hp->mtx_hash = mtx_base + (i % dbenv->mp_mtxcount); + SH_TAILQ_INIT(&hp->hash_bucket); + atomic_init(&hp->hash_page_dirty, 0); +#ifdef HAVE_STATISTICS + hp->hash_io_wait = 0; + hp->hash_frozen = hp->hash_thawed = hp->hash_frozen_freed = 0; +#endif + hp->flags = 0; + ZERO_LSN(hp->old_reader); + } + mp->htab_buckets = htab_buckets; + mp->htab_mutexes = dbenv->mp_mtxcount; + mp->pagesize = dbenv->mp_pagesize == 0 ? + MPOOL_DEFAULT_PAGESIZE : dbenv->mp_pagesize; + + SH_TAILQ_INIT(&mp->free_frozen); + SH_TAILQ_INIT(&mp->alloc_frozen); + + /* + * Pre-allocate one frozen buffer header. This avoids situations where + * the cache becomes full of pages and we don't even have the 28 bytes + * (or so) available to allocate a frozen buffer header. + */ + if ((ret = __env_alloc(infop, + sizeof(BH_FROZEN_ALLOC) + sizeof(BH_FROZEN_PAGE), &frozen)) != 0) + goto mem_err; + SH_TAILQ_INSERT_TAIL(&mp->alloc_frozen, frozen, links); + frozen_bhp = (BH *)(frozen + 1); + frozen_bhp->mtx_buf = MUTEX_INVALID; + SH_TAILQ_INSERT_TAIL(&mp->free_frozen, frozen_bhp, hq); + + /* + * Only the environment creator knows the total cache size, + * fill in those fields now. + */ + mp->gbytes = dbenv->mp_gbytes; + mp->bytes = dbenv->mp_bytes; + infop->mtx_alloc = mp->mtx_region; + return (0); + +mem_err:__db_errx(env, DB_STR("3026", + "Unable to allocate memory for mpool region")); + return (ret); +} + +/* + * PUBLIC: u_int32_t __memp_max_regions __P((ENV *)); + */ +u_int32_t +__memp_max_regions(env) + ENV *env; +{ + DB_ENV *dbenv; + roff_t reg_size, max_size; + size_t max_nreg; + + dbenv = env->dbenv; + + if (dbenv->mp_max_gbytes == 0 && dbenv->mp_max_bytes == 0) + return (dbenv->mp_ncache); + __memp_region_size(env, ®_size, NULL); + max_size = + (roff_t)dbenv->mp_max_gbytes * GIGABYTE + dbenv->mp_max_bytes; + max_nreg = (max_size + reg_size / 2) / reg_size; + + /* Sanity check that the number of regions fits in 32 bits. */ + DB_ASSERT(env, max_nreg == (u_int32_t)max_nreg); + + if (max_nreg <= dbenv->mp_ncache) + max_nreg = dbenv->mp_ncache; + return ((u_int32_t)max_nreg); +} + +/* + * __memp_region_size -- + * Size the region and figure out how many hash buckets we'll have. + */ +static void +__memp_region_size(env, reg_sizep, htab_bucketsp) + ENV *env; + roff_t *reg_sizep; + u_int32_t *htab_bucketsp; +{ + DB_ENV *dbenv; + roff_t reg_size, cache_size; + u_int32_t pgsize; + + dbenv = env->dbenv; + + /* + * Figure out how big each cache region is. Cast an operand to roff_t + * so we do 64-bit arithmetic as appropriate. + */ + cache_size = (roff_t)dbenv->mp_gbytes * GIGABYTE + dbenv->mp_bytes; + reg_size = cache_size / dbenv->mp_ncache; + if (reg_sizep != NULL) + *reg_sizep = reg_size; + + /* + * Figure out how many hash buckets each region will have. Assume we + * want to keep the hash chains with under 3 pages on each chain. We + * don't know the pagesize in advance, and it may differ for different + * files. Use a pagesize of 4K for the calculation -- we walk these + * chains a lot, they must be kept short. We use 2.5 as this maintains + * compatibility with previous releases. + * + * XXX + * Cache sizes larger than 10TB would cause 32-bit wrapping in the + * calculation of the number of hash buckets. This probably isn't + * something we need to worry about right now, but is checked when the + * cache size is set. + */ + if (htab_bucketsp != NULL) { + if (dbenv->mp_tablesize != 0) + *htab_bucketsp = __db_tablesize(dbenv->mp_tablesize); + else { + if ((pgsize = dbenv->mp_pagesize) == 0) + pgsize = MPOOL_DEFAULT_PAGESIZE; + *htab_bucketsp = __db_tablesize( + (u_int32_t)(reg_size / (2.5 * pgsize))); + } + } + +} + +/* + * __memp_region_mutex_count -- + * Return the number of mutexes the mpool region will need. + * + * PUBLIC: u_int32_t __memp_region_mutex_count __P((ENV *)); + */ +u_int32_t +__memp_region_mutex_count(env) + ENV *env; +{ + DB_ENV *dbenv; + u_int32_t htab_buckets; + roff_t reg_size; + u_int32_t max_region, num_per_cache, pgsize; + + dbenv = env->dbenv; + + __memp_region_size(env, ®_size, &htab_buckets); + if (F_ISSET(env->dbenv, DB_ENV_MULTIVERSION)) + pgsize = sizeof(BH_FROZEN_ALLOC) + sizeof(BH_FROZEN_PAGE); + if ((pgsize = dbenv->mp_pagesize) == 0) + pgsize = MPOOL_DEFAULT_PAGESIZE; + max_region = __memp_max_regions(env); + + /* + * We need a couple of mutexes for the region itself, one for each + * file handle (MPOOLFILE) the application allocates, one for each + * of the MPOOL_FILE_BUCKETS, and each cache has one mutex per + * hash bucket. We then need one mutex per page in the cache, + * the worst case is really big if the pages are 512 bytes. + */ + if (dbenv->mp_mtxcount != 0) + htab_buckets = dbenv->mp_mtxcount; + else + dbenv->mp_mtxcount = htab_buckets; + num_per_cache = htab_buckets + (u_int32_t)(reg_size / pgsize); + return ((max_region * num_per_cache) + 50 + MPOOL_FILE_BUCKETS); +} + +/* + * __memp_init_config -- + * Initialize shared configuration information. + */ +static int +__memp_init_config(env, mp) + ENV *env; + MPOOL *mp; +{ + DB_ENV *dbenv; + + dbenv = env->dbenv; + + MPOOL_SYSTEM_LOCK(env); + if (dbenv->mp_mmapsize != 0) + mp->mp_mmapsize = (db_size_t)dbenv->mp_mmapsize; + if (dbenv->mp_maxopenfd != 0) + mp->mp_maxopenfd = dbenv->mp_maxopenfd; + if (dbenv->mp_maxwrite != 0) + mp->mp_maxwrite = dbenv->mp_maxwrite; + if (dbenv->mp_maxwrite_sleep != 0) + mp->mp_maxwrite_sleep = dbenv->mp_maxwrite_sleep; + MPOOL_SYSTEM_UNLOCK(env); + + return (0); +} + +/* + * __memp_env_refresh -- + * Clean up after the mpool system on a close or failed open. + * + * PUBLIC: int __memp_env_refresh __P((ENV *)); + */ +int +__memp_env_refresh(env) + ENV *env; +{ + BH *bhp; + BH_FROZEN_ALLOC *frozen_alloc; + DB_MPOOL *dbmp; + DB_MPOOLFILE *dbmfp; + DB_MPOOL_HASH *hp; + DB_MPREG *mpreg; + MPOOL *mp, *c_mp; + REGINFO *infop; + u_int32_t bucket, i, nreg; + int ret, t_ret; + + ret = 0; + dbmp = env->mp_handle; + mp = dbmp->reginfo[0].primary; + nreg = mp->nreg; + hp = R_ADDR(&dbmp->reginfo[0], mp->htab); + + /* + * If a private region, return the memory to the heap. Not needed for + * filesystem-backed or system shared memory regions, that memory isn't + * owned by any particular process. + */ + if (!F_ISSET(env, ENV_PRIVATE)) + goto not_priv; + + /* Discard buffers. */ + for (i = 0; i < nreg; ++i) { + infop = &dbmp->reginfo[i]; + c_mp = infop->primary; + for (hp = R_ADDR(infop, c_mp->htab), bucket = 0; + bucket < c_mp->htab_buckets; ++hp, ++bucket) { + while ((bhp = SH_TAILQ_FIRST( + &hp->hash_bucket, __bh)) != NULL) + if (F_ISSET(bhp, BH_FROZEN)) + SH_TAILQ_REMOVE( + &hp->hash_bucket, bhp, + hq, __bh); + else { + if (F_ISSET(bhp, BH_DIRTY)) { + atomic_dec(env, + &hp->hash_page_dirty); + F_CLR(bhp, + BH_DIRTY | BH_DIRTY_CREATE); + } + atomic_inc(env, &bhp->ref); + if ((t_ret = __memp_bhfree(dbmp, infop, + R_ADDR(dbmp->reginfo, + bhp->mf_offset), hp, bhp, + BH_FREE_FREEMEM | + BH_FREE_UNLOCKED)) != 0 && ret == 0) + ret = t_ret; + } + } + MPOOL_REGION_LOCK(env, infop); + while ((frozen_alloc = SH_TAILQ_FIRST( + &c_mp->alloc_frozen, __bh_frozen_a)) != NULL) { + SH_TAILQ_REMOVE(&c_mp->alloc_frozen, frozen_alloc, + links, __bh_frozen_a); + __env_alloc_free(infop, frozen_alloc); + } + MPOOL_REGION_UNLOCK(env, infop); + } + +not_priv: + /* Discard DB_MPOOLFILEs. */ + while ((dbmfp = TAILQ_FIRST(&dbmp->dbmfq)) != NULL) + if ((t_ret = __memp_fclose(dbmfp, DB_FLUSH)) != 0 && ret == 0) + ret = t_ret; + + /* Discard DB_MPREGs. */ + if (dbmp->pg_inout != NULL) + __os_free(env, dbmp->pg_inout); + while ((mpreg = LIST_FIRST(&dbmp->dbregq)) != NULL) { + LIST_REMOVE(mpreg, q); + __os_free(env, mpreg); + } + + /* Discard the DB_MPOOL thread mutex. */ + if ((t_ret = __mutex_free(env, &dbmp->mutex)) != 0 && ret == 0) + ret = t_ret; + + if (F_ISSET(env, ENV_PRIVATE)) { + /* Discard REGION IDs. */ + infop = &dbmp->reginfo[0]; + infop->mtx_alloc = MUTEX_INVALID; + __memp_free(infop, R_ADDR(infop, mp->regids)); + + /* Discard all the MPOOLFILEs. */ + if ((t_ret = __memp_discard_all_mpfs(env, mp)) != 0 && ret == 0) + ret = t_ret; + /* Discard the File table. */ + __memp_free(infop, R_ADDR(infop, mp->ftab)); + + /* Discard Hash tables. */ + for (i = 0; i < nreg; ++i) { + infop = &dbmp->reginfo[i]; + c_mp = infop->primary; + infop->mtx_alloc = MUTEX_INVALID; + __memp_free(infop, R_ADDR(infop, c_mp->htab)); + } + } + + /* Detach from the region. */ + for (i = 0; i < nreg; ++i) { + infop = &dbmp->reginfo[i]; + if ((t_ret = + __env_region_detach(env, infop, 0)) != 0 && ret == 0) + ret = t_ret; + } + + /* Discard DB_MPOOL. */ + __os_free(env, dbmp->reginfo); + __os_free(env, dbmp); + + env->mp_handle = NULL; + return (ret); +} diff -r 000000000000 -r a1985f14b030 src/mp/mp_register.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/mp/mp_register.c Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,138 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 1996, 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + * $Id$ + */ + +#include "db_config.h" + +#include "db_int.h" +#include "dbinc/log.h" +#include "dbinc/mp.h" + +/* + * memp_register_pp -- + * ENV->memp_register pre/post processing. + * + * PUBLIC: int __memp_register_pp __P((DB_ENV *, int, + * PUBLIC: int (*)(DB_ENV *, db_pgno_t, void *, DBT *), + * PUBLIC: int (*)(DB_ENV *, db_pgno_t, void *, DBT *))); + */ +int +__memp_register_pp(dbenv, ftype, pgin, pgout) + DB_ENV *dbenv; + int ftype; + int (*pgin) __P((DB_ENV *, db_pgno_t, void *, DBT *)); + int (*pgout) __P((DB_ENV *, db_pgno_t, void *, DBT *)); +{ + DB_THREAD_INFO *ip; + ENV *env; + int ret; + + env = dbenv->env; + + ENV_REQUIRES_CONFIG(env, + env->mp_handle, "DB_ENV->memp_register", DB_INIT_MPOOL); + + if (REP_ON(env)) { + __db_errx(env, DB_STR_A("3001", + "%smethod not permitted when replication is configured", + "%s"), "DB_ENV->memp_register: "); + return (EINVAL); + } + + ENV_ENTER(env, ip); + ret = __memp_register(env, ftype, pgin, pgout); + ENV_LEAVE(env, ip); + return (ret); +} + +/* + * memp_register -- + * ENV->memp_register. + * + * PUBLIC: int __memp_register __P((ENV *, int, + * PUBLIC: int (*)(DB_ENV *, db_pgno_t, void *, DBT *), + * PUBLIC: int (*)(DB_ENV *, db_pgno_t, void *, DBT *))); + */ +int +__memp_register(env, ftype, pgin, pgout) + ENV *env; + int ftype; + int (*pgin) __P((DB_ENV *, db_pgno_t, void *, DBT *)); + int (*pgout) __P((DB_ENV *, db_pgno_t, void *, DBT *)); +{ + DB_MPOOL *dbmp; + DB_MPREG *mpreg; + int ret; + + dbmp = env->mp_handle; + + /* + * We keep the DB pgin/pgout functions outside of the linked list + * to avoid locking/unlocking the linked list on every page I/O. + * + * The Berkeley DB I/O conversion functions are registered when the + * environment is first created, so there's no need for locking here. + */ + if (ftype == DB_FTYPE_SET) { + if (dbmp->pg_inout != NULL) + return (0); + if ((ret = + __os_malloc(env, sizeof(DB_MPREG), &dbmp->pg_inout)) != 0) + return (ret); + dbmp->pg_inout->ftype = ftype; + dbmp->pg_inout->pgin = pgin; + dbmp->pg_inout->pgout = pgout; + return (0); + } + + /* + * The item may already have been registered. If already registered, + * just update the entry, although it's probably unchanged. + */ + MUTEX_LOCK(env, dbmp->mutex); + LIST_FOREACH(mpreg, &dbmp->dbregq, q) + if (mpreg->ftype == ftype) { + mpreg->pgin = pgin; + mpreg->pgout = pgout; + break; + } + + if (mpreg == NULL) { /* New entry. */ + if ((ret = __os_malloc(env, sizeof(DB_MPREG), &mpreg)) != 0) + return (ret); + mpreg->ftype = ftype; + mpreg->pgin = pgin; + mpreg->pgout = pgout; + + LIST_INSERT_HEAD(&dbmp->dbregq, mpreg, q); + } + MUTEX_UNLOCK(env, dbmp->mutex); + + return (0); +} diff -r 000000000000 -r a1985f14b030 src/mp/mp_resize.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/mp/mp_resize.c Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,583 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 2006, 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + * $Id$ + */ + +#include "db_config.h" + +#include "db_int.h" +#include "dbinc/mp.h" +#include "dbinc/txn.h" + +static int __memp_add_bucket __P((DB_MPOOL *)); +static int __memp_add_region __P((DB_MPOOL *)); +static int __memp_map_regions __P((DB_MPOOL *)); +static int __memp_merge_buckets + __P((DB_MPOOL *, u_int32_t, u_int32_t, u_int32_t)); +static int __memp_remove_bucket __P((DB_MPOOL *)); +static int __memp_remove_region __P((DB_MPOOL *)); + +/* + * PUBLIC: int __memp_get_bucket __P((ENV *, MPOOLFILE *, + * PUBLIC: db_pgno_t, REGINFO **, DB_MPOOL_HASH **, u_int32_t *)); + */ +int +__memp_get_bucket(env, mfp, pgno, infopp, hpp, bucketp) + ENV *env; + MPOOLFILE *mfp; + db_pgno_t pgno; + REGINFO **infopp; + DB_MPOOL_HASH **hpp; + u_int32_t *bucketp; +{ + DB_MPOOL *dbmp; + DB_MPOOL_HASH *hp; + MPOOL *c_mp, *mp; + REGINFO *infop; + roff_t mf_offset; + u_int32_t bucket, nbuckets, new_bucket, new_nbuckets, region; + u_int32_t *regids; + int ret; + + dbmp = env->mp_handle; + mf_offset = R_OFFSET(dbmp->reginfo, mfp); + mp = dbmp->reginfo[0].primary; + ret = 0; + + for (;;) { + nbuckets = mp->nbuckets; + MP_BUCKET(mf_offset, pgno, nbuckets, bucket); + + /* + * Once we work out which region we are looking in, we have to + * check that we have that region mapped, and that the version + * we have matches the ID in the main mpool region. Otherwise + * we have to go and map in any regions that don't match and + * retry. + */ + region = NREGION(mp, bucket); + regids = R_ADDR(dbmp->reginfo, mp->regids); + + for (;;) { + infop = *infopp = &dbmp->reginfo[region]; + c_mp = infop->primary; + + /* If we have the correct region mapped, we're done. */ + if (c_mp != NULL && regids[region] == infop->id) + break; + if ((ret = __memp_map_regions(dbmp)) != 0) + return (ret); + } + + /* If our caller wants the hash bucket, lock it here. */ + if (hpp != NULL) { + hp = R_ADDR(infop, c_mp->htab); + hp = &hp[bucket - region * mp->htab_buckets]; + + MUTEX_READLOCK(env, hp->mtx_hash); + + /* + * Check that we still have the correct region mapped. + */ + if (regids[region] != infop->id) { + MUTEX_UNLOCK(env, hp->mtx_hash); + continue; + } + + /* + * Now that the bucket is locked, we need to check that + * the cache has not been resized while we waited. + */ + new_nbuckets = mp->nbuckets; + if (nbuckets != new_nbuckets) { + MP_BUCKET(mf_offset, pgno, new_nbuckets, + new_bucket); + + if (new_bucket != bucket) { + MUTEX_UNLOCK(env, hp->mtx_hash); + continue; + } + } + + *hpp = hp; + } + + break; + } + + if (bucketp != NULL) + *bucketp = bucket - region * mp->htab_buckets; + return (ret); +} + +static int +__memp_merge_buckets(dbmp, new_nbuckets, old_bucket, new_bucket) + DB_MPOOL *dbmp; + u_int32_t new_nbuckets, old_bucket, new_bucket; +{ + BH *alloc_bhp, *bhp, *current_bhp, *new_bhp, *next_bhp; + DB_MPOOL_HASH *new_hp, *old_hp; + ENV *env; + MPOOL *mp, *new_mp, *old_mp; + MPOOLFILE *mfp; + REGINFO *new_infop, *old_infop; + u_int32_t bucket, high_mask, new_region, old_region; + int ret; + + env = dbmp->env; + mp = dbmp->reginfo[0].primary; + new_bhp = NULL; + ret = 0; + + MP_MASK(new_nbuckets, high_mask); + + old_region = NREGION(mp, old_bucket); + old_infop = &dbmp->reginfo[old_region]; + old_mp = old_infop->primary; + old_hp = R_ADDR(old_infop, old_mp->htab); + old_hp = &old_hp[old_bucket - old_region * mp->htab_buckets]; + + new_region = NREGION(mp, new_bucket); + new_infop = &dbmp->reginfo[new_region]; + new_mp = new_infop->primary; + new_hp = R_ADDR(new_infop, new_mp->htab); + new_hp = &new_hp[new_bucket - new_region * mp->htab_buckets]; + + /* + * Before merging, we need to check that there are no old buffers left + * in the target hash bucket after a previous split. + */ +free_old: + MUTEX_LOCK(env, new_hp->mtx_hash); + SH_TAILQ_FOREACH(bhp, &new_hp->hash_bucket, hq, __bh) { + MP_BUCKET(bhp->mf_offset, bhp->pgno, mp->nbuckets, bucket); + + if (bucket != new_bucket) { + /* + * There is no way that an old buffer can be locked + * after a split, since everyone will look for it in + * the new hash bucket. + */ + DB_ASSERT(env, !F_ISSET(bhp, BH_DIRTY) && + atomic_read(&bhp->ref) == 0); + atomic_inc(env, &bhp->ref); + mfp = R_ADDR(dbmp->reginfo, bhp->mf_offset); + if ((ret = __memp_bhfree(dbmp, new_infop, + mfp, new_hp, bhp, BH_FREE_FREEMEM)) != 0) { + MUTEX_UNLOCK(env, new_hp->mtx_hash); + return (ret); + } + + /* + * The free has modified the list of buffers and + * dropped the mutex. We need to start again. + */ + goto free_old; + } + } + MUTEX_UNLOCK(env, new_hp->mtx_hash); + + /* + * Before we begin, make sure that all of the buffers we care about are + * not in use and not frozen. We do this because we can't drop the old + * hash bucket mutex once we start moving buffers around. + */ +retry: MUTEX_LOCK(env, old_hp->mtx_hash); + SH_TAILQ_FOREACH(bhp, &old_hp->hash_bucket, hq, __bh) { + MP_HASH_BUCKET(MP_HASH(bhp->mf_offset, bhp->pgno), + new_nbuckets, high_mask, bucket); + + if (bucket == new_bucket && atomic_read(&bhp->ref) != 0) { + MUTEX_UNLOCK(env, old_hp->mtx_hash); + __os_yield(env, 0, 0); + goto retry; + } + } + + /* + * We now know that all of the buffers we care about are unlocked and + * unreferenced. Go ahead and copy them. + */ + SH_TAILQ_FOREACH(bhp, &old_hp->hash_bucket, hq, __bh) { + MP_HASH_BUCKET(MP_HASH(bhp->mf_offset, bhp->pgno), + new_nbuckets, high_mask, bucket); + mfp = R_ADDR(dbmp->reginfo, bhp->mf_offset); + + /* + * We ignore buffers that don't hash to the new bucket. We + * could also ignore clean buffers which are not part of a + * multiversion chain as long as they have a backing file. + */ + if (bucket != new_bucket || (!F_ISSET(bhp, BH_DIRTY) && + SH_CHAIN_SINGLETON(bhp, vc) && !mfp->no_backing_file)) + continue; + + for (current_bhp = bhp, next_bhp = NULL; + current_bhp != NULL; + current_bhp = SH_CHAIN_PREV(current_bhp, vc, __bh), + next_bhp = alloc_bhp) { + /* Allocate in the new region. */ + if ((ret = __memp_alloc(dbmp, + new_infop, mfp, 0, NULL, &alloc_bhp)) != 0) + break; + + alloc_bhp->ref = current_bhp->ref; + alloc_bhp->priority = current_bhp->priority; + alloc_bhp->pgno = current_bhp->pgno; + alloc_bhp->mf_offset = current_bhp->mf_offset; + alloc_bhp->flags = current_bhp->flags; + alloc_bhp->td_off = current_bhp->td_off; + + /* + * We've duplicated the buffer, so now we need to + * update reference counts, including the counts in the + * per-MPOOLFILE and the transaction detail (for MVCC + * buffers). + */ + MUTEX_LOCK(env, mfp->mutex); + ++mfp->block_cnt; + MUTEX_UNLOCK(env, mfp->mutex); + + if (alloc_bhp->td_off != INVALID_ROFF && + (ret = __txn_add_buffer(env, + R_ADDR(&env->tx_handle->reginfo, + alloc_bhp->td_off))) != 0) + break; + + memcpy(alloc_bhp->buf, bhp->buf, mfp->pagesize); + + /* + * We build up the MVCC chain first, then insert the + * head (stored in new_bhp) once. + */ + if (next_bhp == NULL) { + SH_CHAIN_INIT(alloc_bhp, vc); + new_bhp = alloc_bhp; + } else + SH_CHAIN_INSERT_BEFORE( + next_bhp, alloc_bhp, vc, __bh); + } + + DB_ASSERT(env, new_hp->mtx_hash != old_hp->mtx_hash); + MUTEX_LOCK(env, new_hp->mtx_hash); + SH_TAILQ_INSERT_TAIL(&new_hp->hash_bucket, new_bhp, hq); + if (F_ISSET(new_bhp, BH_DIRTY)) + atomic_inc(env, &new_hp->hash_page_dirty); + + if (F_ISSET(bhp, BH_DIRTY)) { + F_CLR(bhp, BH_DIRTY); + atomic_dec(env, &old_hp->hash_page_dirty); + } + MUTEX_UNLOCK(env, new_hp->mtx_hash); + } + + if (ret == 0) + mp->nbuckets = new_nbuckets; + MUTEX_UNLOCK(env, old_hp->mtx_hash); + + return (ret); +} + +static int +__memp_add_bucket(dbmp) + DB_MPOOL *dbmp; +{ + ENV *env; + MPOOL *mp; + u_int32_t high_mask, new_bucket, old_bucket; + + env = dbmp->env; + mp = dbmp->reginfo[0].primary; + + new_bucket = mp->nbuckets; + /* We should always be adding buckets to the last region. */ + DB_ASSERT(env, NREGION(mp, new_bucket) == mp->nreg - 1); + MP_MASK(mp->nbuckets, high_mask); + old_bucket = new_bucket & (high_mask >> 1); + + /* + * With fixed-sized regions, the new region is always smaller than the + * existing total cache size, so buffers always need to be copied. If + * we implement variable region sizes, it's possible that we will be + * splitting a hash bucket in the new region. Catch that here. + */ + DB_ASSERT(env, NREGION(mp, old_bucket) != NREGION(mp, new_bucket)); + + return (__memp_merge_buckets(dbmp, mp->nbuckets + 1, + old_bucket, new_bucket)); +} + +static int +__memp_add_region(dbmp) + DB_MPOOL *dbmp; +{ + ENV *env; + MPOOL *mp; + REGINFO *infop; + int ret; + roff_t cache_size, reg_size; + u_int i; + u_int32_t *regids; + + env = dbmp->env; + mp = dbmp->reginfo[0].primary; + cache_size = (roff_t)mp->gbytes * GIGABYTE + mp->bytes; + + /* All cache regions are the same size. */ + reg_size = dbmp->reginfo[0].rp->size; + ret = 0; + + infop = &dbmp->reginfo[mp->nreg]; + infop->env = env; + infop->type = REGION_TYPE_MPOOL; + infop->id = INVALID_REGION_ID; + infop->flags = REGION_CREATE_OK; + if ((ret = __env_region_attach(env, infop, reg_size, reg_size)) != 0) + return (ret); + if ((ret = __memp_init(env, + dbmp, mp->nreg, mp->htab_buckets, mp->max_nreg)) != 0) + return (ret); + cache_size += reg_size; + mp->gbytes = (u_int32_t)(cache_size / GIGABYTE); + mp->bytes = (u_int32_t)(cache_size % GIGABYTE); + regids = R_ADDR(dbmp->reginfo, mp->regids); + regids[mp->nreg++] = infop->id; + + for (i = 0; i < mp->htab_buckets; i++) + if ((ret = __memp_add_bucket(dbmp)) != 0) + break; + + return (ret); +} + +static int +__memp_remove_bucket(dbmp) + DB_MPOOL *dbmp; +{ + ENV *env; + MPOOL *mp; + u_int32_t high_mask, new_bucket, old_bucket; + + env = dbmp->env; + mp = dbmp->reginfo[0].primary; + + old_bucket = mp->nbuckets - 1; + + /* We should always be removing buckets from the last region. */ + DB_ASSERT(env, NREGION(mp, old_bucket) == mp->nreg - 1); + MP_MASK(mp->nbuckets - 1, high_mask); + new_bucket = old_bucket & (high_mask >> 1); + + return (__memp_merge_buckets(dbmp, mp->nbuckets - 1, + old_bucket, new_bucket)); +} + +static int +__memp_remove_region(dbmp) + DB_MPOOL *dbmp; +{ + DB_MPOOL_HASH *hp; + ENV *env; + MPOOL *mp; + REGINFO *infop; + int ret; + roff_t cache_size, reg_size; + u_int i; + + env = dbmp->env; + mp = dbmp->reginfo[0].primary; + reg_size = dbmp->reginfo[0].rp->size; + cache_size = (roff_t)mp->gbytes * GIGABYTE + mp->bytes; + ret = 0; + + if (mp->nreg == 1) { + __db_errx(env, DB_STR("3019", + "cannot remove the last cache")); + return (EINVAL); + } + + for (i = 0; i < mp->htab_buckets; i++) + if ((ret = __memp_remove_bucket(dbmp)) != 0) + return (ret); + + /* Detach from the region then destroy it. */ + infop = &dbmp->reginfo[mp->nreg]; + if (F_ISSET(env, ENV_PRIVATE)) { + hp = R_ADDR(infop, ((MPOOL*)infop->primary)->htab); + for (i = 0; i < env->dbenv->mp_mtxcount; i++) + if ((ret = __mutex_free(env, &hp[i].mtx_hash)) != 0) + return (ret); + } + + ret = __env_region_detach(env, infop, 1); + if (ret == 0) { + mp->nreg--; + cache_size -= reg_size; + mp->gbytes = (u_int32_t)(cache_size / GIGABYTE); + mp->bytes = (u_int32_t)(cache_size % GIGABYTE); + } + + return (ret); +} + +static int +__memp_map_regions(dbmp) + DB_MPOOL *dbmp; +{ + ENV *env; + MPOOL *mp; + int ret; + u_int i; + u_int32_t *regids; + + env = dbmp->env; + mp = dbmp->reginfo[0].primary; + regids = R_ADDR(dbmp->reginfo, mp->regids); + ret = 0; + + for (i = 1; i < mp->nreg; ++i) { + if (dbmp->reginfo[i].primary != NULL && + dbmp->reginfo[i].id == regids[i]) + continue; + + if (dbmp->reginfo[i].primary != NULL) + ret = __env_region_detach(env, &dbmp->reginfo[i], 0); + + dbmp->reginfo[i].env = env; + dbmp->reginfo[i].type = REGION_TYPE_MPOOL; + dbmp->reginfo[i].id = regids[i]; + dbmp->reginfo[i].flags = REGION_JOIN_OK; + if ((ret = + __env_region_attach(env, &dbmp->reginfo[i], 0, 0)) != 0) + return (ret); + dbmp->reginfo[i].primary = R_ADDR(&dbmp->reginfo[i], + dbmp->reginfo[i].rp->primary); + } + + for (; i < mp->max_nreg; i++) + if (dbmp->reginfo[i].primary != NULL && + (ret = __env_region_detach(env, + &dbmp->reginfo[i], 0)) != 0) + break; + + return (ret); +} + +/* + * PUBLIC: int __memp_resize __P((DB_MPOOL *, u_int32_t, u_int32_t)); + */ +int +__memp_resize(dbmp, gbytes, bytes) + DB_MPOOL *dbmp; + u_int32_t gbytes, bytes; +{ + ENV *env; + MPOOL *mp; + int ret; + u_int32_t ncache; + roff_t reg_size, total_size; + + env = dbmp->env; + mp = dbmp->reginfo[0].primary; + reg_size = dbmp->reginfo[0].rp->size; + total_size = (roff_t)gbytes * GIGABYTE + bytes; + ncache = (u_int32_t)((total_size + reg_size / 2) / reg_size); + + if (ncache < 1) + ncache = 1; + else if (ncache > mp->max_nreg) { + __db_errx(env, DB_STR_A("3020", + "cannot resize to %lu cache regions: maximum is %lu", + "%lu %lu"), (u_long)ncache, (u_long)mp->max_nreg); + return (EINVAL); + } + + ret = 0; + MUTEX_LOCK(env, mp->mtx_resize); + while (mp->nreg != ncache) + if ((ret = (mp->nreg < ncache ? + __memp_add_region(dbmp) : + __memp_remove_region(dbmp))) != 0) + break; + MUTEX_UNLOCK(env, mp->mtx_resize); + + return (ret); +} + +/* + * PUBLIC: int __memp_get_cache_max __P((DB_ENV *, u_int32_t *, u_int32_t *)); + */ +int +__memp_get_cache_max(dbenv, max_gbytesp, max_bytesp) + DB_ENV *dbenv; + u_int32_t *max_gbytesp, *max_bytesp; +{ + DB_MPOOL *dbmp; + ENV *env; + MPOOL *mp; + roff_t reg_size, max_size; + + env = dbenv->env; + + ENV_NOT_CONFIGURED(env, + env->mp_handle, "DB_ENV->get_mp_max_ncache", DB_INIT_MPOOL); + + if (MPOOL_ON(env)) { + /* Cannot be set after open, no lock required to read. */ + dbmp = env->mp_handle; + mp = dbmp->reginfo[0].primary; + reg_size = dbmp->reginfo[0].rp->size; + max_size = mp->max_nreg * reg_size; + *max_gbytesp = (u_int32_t)(max_size / GIGABYTE); + *max_bytesp = (u_int32_t)(max_size % GIGABYTE); + } else { + *max_gbytesp = dbenv->mp_max_gbytes; + *max_bytesp = dbenv->mp_max_bytes; + } + + return (0); +} + +/* + * PUBLIC: int __memp_set_cache_max __P((DB_ENV *, u_int32_t, u_int32_t)); + */ +int +__memp_set_cache_max(dbenv, max_gbytes, max_bytes) + DB_ENV *dbenv; + u_int32_t max_gbytes, max_bytes; +{ + ENV *env; + + env = dbenv->env; + + ENV_ILLEGAL_AFTER_OPEN(env, "DB_ENV->set_cache_max"); + dbenv->mp_max_gbytes = max_gbytes; + dbenv->mp_max_bytes = max_bytes; + + return (0); +} diff -r 000000000000 -r a1985f14b030 src/mp/mp_stat.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/mp/mp_stat.c Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,931 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 1996, 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + * $Id$ + */ + +#include "db_config.h" + +#include "db_int.h" +#include "dbinc/db_page.h" +#include "dbinc/db_am.h" +#include "dbinc/mp.h" +#include "dbinc/txn.h" + +#ifdef HAVE_STATISTICS +static void __memp_print_bh __P((ENV *, + DB_MPOOL *, const char *, BH *, roff_t *)); +static int __memp_print_all __P((ENV *, u_int32_t)); +static int __memp_print_stats __P((ENV *, u_int32_t)); +static int __memp_print_hash __P((ENV *, + DB_MPOOL *, REGINFO *, roff_t *, u_int32_t)); +static int __memp_stat __P((ENV *, + DB_MPOOL_STAT **, DB_MPOOL_FSTAT ***, u_int32_t)); +static void __memp_stat_wait + __P((ENV *, REGINFO *, MPOOL *, DB_MPOOL_STAT *, u_int32_t)); +static int __memp_file_stats __P((ENV *, + MPOOLFILE *, void *, u_int32_t *, u_int32_t)); +static int __memp_count_files __P((ENV *, + MPOOLFILE *, void *, u_int32_t *, u_int32_t)); +static int __memp_get_files __P((ENV *, + MPOOLFILE *, void *, u_int32_t *, u_int32_t)); +static int __memp_print_files __P((ENV *, + MPOOLFILE *, void *, u_int32_t *, u_int32_t)); + +/* + * __memp_stat_pp -- + * DB_ENV->memp_stat pre/post processing. + * + * PUBLIC: int __memp_stat_pp + * PUBLIC: __P((DB_ENV *, DB_MPOOL_STAT **, DB_MPOOL_FSTAT ***, u_int32_t)); + */ +int +__memp_stat_pp(dbenv, gspp, fspp, flags) + DB_ENV *dbenv; + DB_MPOOL_STAT **gspp; + DB_MPOOL_FSTAT ***fspp; + u_int32_t flags; +{ + DB_THREAD_INFO *ip; + ENV *env; + int ret; + + env = dbenv->env; + + ENV_REQUIRES_CONFIG(env, + env->mp_handle, "DB_ENV->memp_stat", DB_INIT_MPOOL); + + if ((ret = __db_fchk(env, + "DB_ENV->memp_stat", flags, DB_STAT_CLEAR)) != 0) + return (ret); + + ENV_ENTER(env, ip); + REPLICATION_WRAP(env, (__memp_stat(env, gspp, fspp, flags)), 0, ret); + ENV_LEAVE(env, ip); + return (ret); +} + +/* + * __memp_stat -- + * ENV->memp_stat + */ +static int +__memp_stat(env, gspp, fspp, flags) + ENV *env; + DB_MPOOL_STAT **gspp; + DB_MPOOL_FSTAT ***fspp; + u_int32_t flags; +{ + DB_MPOOL *dbmp; + DB_MPOOL_FSTAT **tfsp; + DB_MPOOL_STAT *sp; + MPOOL *c_mp, *mp; + size_t len; + int ret; + u_int32_t i; + uintmax_t tmp_wait, tmp_nowait; + + dbmp = env->mp_handle; + mp = dbmp->reginfo[0].primary; + + /* Global statistics. */ + if (gspp != NULL) { + *gspp = NULL; + + if ((ret = __os_umalloc(env, sizeof(**gspp), gspp)) != 0) + return (ret); + memset(*gspp, 0, sizeof(**gspp)); + sp = *gspp; + + /* + * Initialization and information that is not maintained on + * a per-cache basis. Note that configuration information + * may be modified at any time, and so we have to lock. + */ + sp->st_gbytes = mp->gbytes; + sp->st_bytes = mp->bytes; + sp->st_pagesize = mp->pagesize; + sp->st_ncache = mp->nreg; + sp->st_max_ncache = mp->max_nreg; + sp->st_regsize = dbmp->reginfo[0].rp->size; + sp->st_regmax = dbmp->reginfo[0].rp->max; + sp->st_sync_interrupted = mp->stat.st_sync_interrupted; + + MPOOL_SYSTEM_LOCK(env); + sp->st_mmapsize = mp->mp_mmapsize; + sp->st_maxopenfd = mp->mp_maxopenfd; + sp->st_maxwrite = mp->mp_maxwrite; + sp->st_maxwrite_sleep = mp->mp_maxwrite_sleep; + MPOOL_SYSTEM_UNLOCK(env); + + /* Walk the cache list and accumulate the global information. */ + for (i = 0; i < mp->nreg; ++i) { + c_mp = dbmp->reginfo[i].primary; + + sp->st_map += c_mp->stat.st_map; + sp->st_cache_hit += c_mp->stat.st_cache_hit; + sp->st_cache_miss += c_mp->stat.st_cache_miss; + sp->st_page_create += c_mp->stat.st_page_create; + sp->st_page_in += c_mp->stat.st_page_in; + sp->st_page_out += c_mp->stat.st_page_out; + sp->st_ro_evict += c_mp->stat.st_ro_evict; + sp->st_rw_evict += c_mp->stat.st_rw_evict; + sp->st_page_trickle += c_mp->stat.st_page_trickle; + sp->st_pages += c_mp->pages; + sp->st_oddfsize_detect += + c_mp->stat.st_oddfsize_detect; + sp->st_oddfsize_resolve += + c_mp->stat.st_oddfsize_resolve; + /* + * st_page_dirty calculated by __memp_stat_hash + * st_page_clean calculated here + */ + __memp_stat_hash( + &dbmp->reginfo[i], c_mp, &sp->st_page_dirty); + sp->st_page_clean = sp->st_pages - sp->st_page_dirty; + sp->st_hash_buckets += c_mp->htab_buckets; + sp->st_hash_mutexes += c_mp->htab_mutexes; + sp->st_hash_searches += c_mp->stat.st_hash_searches; + sp->st_hash_longest += c_mp->stat.st_hash_longest; + sp->st_hash_examined += c_mp->stat.st_hash_examined; + /* + * st_hash_nowait calculated by __memp_stat_wait + * st_hash_wait + */ + __memp_stat_wait( + env, &dbmp->reginfo[i], c_mp, sp, flags); + __mutex_set_wait_info(env, + c_mp->mtx_region, &tmp_wait, &tmp_nowait); + sp->st_region_nowait += tmp_nowait; + sp->st_region_wait += tmp_wait; + sp->st_alloc += c_mp->stat.st_alloc; + sp->st_alloc_buckets += c_mp->stat.st_alloc_buckets; + if (sp->st_alloc_max_buckets < + c_mp->stat.st_alloc_max_buckets) + sp->st_alloc_max_buckets = + c_mp->stat.st_alloc_max_buckets; + sp->st_alloc_pages += c_mp->stat.st_alloc_pages; + if (sp->st_alloc_max_pages < + c_mp->stat.st_alloc_max_pages) + sp->st_alloc_max_pages = + c_mp->stat.st_alloc_max_pages; + + if (LF_ISSET(DB_STAT_CLEAR)) { + if (!LF_ISSET(DB_STAT_SUBSYSTEM)) + __mutex_clear(env, c_mp->mtx_region); + + memset(&c_mp->stat, 0, sizeof(c_mp->stat)); + } + } + + /* + * We have duplicate statistics fields in per-file structures + * and the cache. The counters are only incremented in the + * per-file structures, except if a file is flushed from the + * mpool, at which time we copy its information into the cache + * statistics. We added the cache information above, now we + * add the per-file information. + */ + if ((ret = __memp_walk_files(env, mp, __memp_file_stats, + sp, NULL, fspp == NULL ? LF_ISSET(DB_STAT_CLEAR) : 0)) != 0) + return (ret); + } + + /* Per-file statistics. */ + if (fspp != NULL) { + *fspp = NULL; + + /* Count the MPOOLFILE structures. */ + i = 0; + len = 0; + if ((ret = __memp_walk_files(env, + mp, __memp_count_files, &len, &i, flags)) != 0) + return (ret); + + if (i == 0) + return (0); + len += sizeof(DB_MPOOL_FSTAT *); /* Trailing NULL */ + + /* Allocate space */ + if ((ret = __os_umalloc(env, len, fspp)) != 0) + return (ret); + + tfsp = *fspp; + *tfsp = NULL; + + /* + * Files may have been opened since we counted, don't walk + * off the end of the allocated space. + */ + if ((ret = __memp_walk_files(env, + mp, __memp_get_files, &tfsp, &i, flags)) != 0) + return (ret); + + *++tfsp = NULL; + } + + return (0); +} + +static int +__memp_file_stats(env, mfp, argp, countp, flags) + ENV *env; + MPOOLFILE *mfp; + void *argp; + u_int32_t *countp; + u_int32_t flags; +{ + DB_MPOOL_STAT *sp; + + COMPQUIET(env, NULL); + COMPQUIET(countp, NULL); + + sp = argp; + + sp->st_map += mfp->stat.st_map; + sp->st_cache_hit += mfp->stat.st_cache_hit; + sp->st_cache_miss += mfp->stat.st_cache_miss; + sp->st_page_create += mfp->stat.st_page_create; + sp->st_page_in += mfp->stat.st_page_in; + sp->st_page_out += mfp->stat.st_page_out; + if (LF_ISSET(DB_STAT_CLEAR)) + memset(&mfp->stat, 0, sizeof(mfp->stat)); + + return (0); +} + +static int +__memp_count_files(env, mfp, argp, countp, flags) + ENV *env; + MPOOLFILE *mfp; + void *argp; + u_int32_t *countp; + u_int32_t flags; +{ + DB_MPOOL *dbmp; + size_t len; + + COMPQUIET(flags, 0); + dbmp = env->mp_handle; + len = *(size_t *)argp; + + (*countp)++; + len += sizeof(DB_MPOOL_FSTAT *) + + sizeof(DB_MPOOL_FSTAT) + strlen(__memp_fns(dbmp, mfp)) + 1; + + *(size_t *)argp = len; + return (0); +} + +/* + * __memp_get_files -- + * get file specific statistics + * + * Build each individual entry. We assume that an array of pointers are + * aligned correctly to be followed by an array of structures, which should + * be safe (in this particular case, the first element of the structure + * is a pointer, so we're doubly safe). The array is followed by space + * for the text file names. + */ +static int +__memp_get_files(env, mfp, argp, countp, flags) + ENV *env; + MPOOLFILE *mfp; + void *argp; + u_int32_t *countp; + u_int32_t flags; +{ + DB_MPOOL *dbmp; + DB_MPOOL_FSTAT **tfsp, *tstruct; + char *name, *tname; + size_t nlen; + + if (*countp == 0) + return (0); + + dbmp = env->mp_handle; + tfsp = *(DB_MPOOL_FSTAT ***)argp; + + if (*tfsp == NULL) { + /* Add 1 to count because we need to skip over the NULL. */ + tstruct = (DB_MPOOL_FSTAT *)(tfsp + *countp + 1); + tname = (char *)(tstruct + *countp); + *tfsp = tstruct; + } else { + tstruct = *tfsp + 1; + tname = (*tfsp)->file_name + strlen((*tfsp)->file_name) + 1; + *++tfsp = tstruct; + } + + name = __memp_fns(dbmp, mfp); + nlen = strlen(name) + 1; + memcpy(tname, name, nlen); + memcpy(tstruct, &mfp->stat, sizeof(mfp->stat)); + tstruct->file_name = tname; + + /* Grab the pagesize from the mfp. */ + tstruct->st_pagesize = mfp->pagesize; + + *(DB_MPOOL_FSTAT ***)argp = tfsp; + (*countp)--; + + if (LF_ISSET(DB_STAT_CLEAR)) + memset(&mfp->stat, 0, sizeof(mfp->stat)); + + return (0); +} + +/* + * __memp_stat_print_pp -- + * ENV->memp_stat_print pre/post processing. + * + * PUBLIC: int __memp_stat_print_pp __P((DB_ENV *, u_int32_t)); + */ +int +__memp_stat_print_pp(dbenv, flags) + DB_ENV *dbenv; + u_int32_t flags; +{ + DB_THREAD_INFO *ip; + ENV *env; + int ret; + + env = dbenv->env; + + ENV_REQUIRES_CONFIG(env, + env->mp_handle, "DB_ENV->memp_stat_print", DB_INIT_MPOOL); + +#define DB_STAT_MEMP_FLAGS \ + (DB_STAT_ALL | DB_STAT_ALLOC | DB_STAT_CLEAR | DB_STAT_MEMP_HASH) + if ((ret = __db_fchk(env, + "DB_ENV->memp_stat_print", flags, DB_STAT_MEMP_FLAGS)) != 0) + return (ret); + + ENV_ENTER(env, ip); + REPLICATION_WRAP(env, (__memp_stat_print(env, flags)), 0, ret); + ENV_LEAVE(env, ip); + return (ret); +} + +#define FMAP_ENTRIES 200 /* Files we map. */ + +/* + * __memp_stat_print -- + * ENV->memp_stat_print method. + * + * PUBLIC: int __memp_stat_print __P((ENV *, u_int32_t)); + */ +int +__memp_stat_print(env, flags) + ENV *env; + u_int32_t flags; +{ + u_int32_t orig_flags; + int ret; + + orig_flags = flags; + LF_CLR(DB_STAT_CLEAR | DB_STAT_SUBSYSTEM); + if (flags == 0 || LF_ISSET(DB_STAT_ALL)) { + ret = __memp_print_stats(env, + LF_ISSET(DB_STAT_ALL) ? flags : orig_flags); + if (flags == 0 || ret != 0) + return (ret); + } + + if (LF_ISSET(DB_STAT_ALL | DB_STAT_MEMP_HASH) && + (ret = __memp_print_all(env, orig_flags)) != 0) + return (ret); + + return (0); +} + +/* + * __memp_print_stats -- + * Display default mpool region statistics. + */ +static int +__memp_print_stats(env, flags) + ENV *env; + u_int32_t flags; +{ + DB_MPOOL_FSTAT **fsp, **tfsp; + DB_MPOOL_STAT *gsp; + int ret; + + if ((ret = __memp_stat(env, &gsp, &fsp, flags)) != 0) + return (ret); + + if (LF_ISSET(DB_STAT_ALL)) + __db_msg(env, "Default cache region information:"); + __db_dlbytes(env, "Total cache size", + (u_long)gsp->st_gbytes, (u_long)0, (u_long)gsp->st_bytes); + __db_dl(env, "Number of caches", (u_long)gsp->st_ncache); + __db_dl(env, "Maximum number of caches", (u_long)gsp->st_max_ncache); + __db_dlbytes(env, "Pool individual cache size", + (u_long)0, (u_long)0, (u_long)gsp->st_regsize); + __db_dlbytes(env, "Pool individual cache max", + (u_long)0, (u_long)0, (u_long)gsp->st_regmax); + __db_dlbytes(env, "Maximum memory-mapped file size", + (u_long)0, (u_long)0, (u_long)gsp->st_mmapsize); + STAT_LONG("Maximum open file descriptors", gsp->st_maxopenfd); + STAT_LONG("Maximum sequential buffer writes", gsp->st_maxwrite); + STAT_LONG("Sleep after writing maximum sequential buffers", + gsp->st_maxwrite_sleep); + __db_dl(env, + "Requested pages mapped into the process' address space", + (u_long)gsp->st_map); + __db_dl_pct(env, "Requested pages found in the cache", + (u_long)gsp->st_cache_hit, DB_PCT( + gsp->st_cache_hit, gsp->st_cache_hit + gsp->st_cache_miss), NULL); + __db_dl(env, "Requested pages not found in the cache", + (u_long)gsp->st_cache_miss); + __db_dl(env, + "Pages created in the cache", (u_long)gsp->st_page_create); + __db_dl(env, "Pages read into the cache", (u_long)gsp->st_page_in); + __db_dl(env, "Pages written from the cache to the backing file", + (u_long)gsp->st_page_out); + __db_dl(env, "Clean pages forced from the cache", + (u_long)gsp->st_ro_evict); + __db_dl(env, "Dirty pages forced from the cache", + (u_long)gsp->st_rw_evict); + __db_dl(env, "Dirty pages written by trickle-sync thread", + (u_long)gsp->st_page_trickle); + __db_dl(env, "Current total page count", + (u_long)gsp->st_pages); + __db_dl(env, "Current clean page count", + (u_long)gsp->st_page_clean); + __db_dl(env, "Current dirty page count", + (u_long)gsp->st_page_dirty); + __db_dl(env, "Number of hash buckets used for page location", + (u_long)gsp->st_hash_buckets); + __db_dl(env, "Number of mutexes for the hash buckets", + (u_long)gsp->st_hash_mutexes); + __db_dl(env, "Assumed page size used", + (u_long)gsp->st_pagesize); + __db_dl(env, + "Total number of times hash chains searched for a page", + (u_long)gsp->st_hash_searches); + __db_dl(env, "The longest hash chain searched for a page", + (u_long)gsp->st_hash_longest); + __db_dl(env, + "Total number of hash chain entries checked for page", + (u_long)gsp->st_hash_examined); + __db_dl_pct(env, + "The number of hash bucket locks that required waiting", + (u_long)gsp->st_hash_wait, DB_PCT( + gsp->st_hash_wait, gsp->st_hash_wait + gsp->st_hash_nowait), NULL); + __db_dl_pct(env, + "The maximum number of times any hash bucket lock was waited for", + (u_long)gsp->st_hash_max_wait, DB_PCT(gsp->st_hash_max_wait, + gsp->st_hash_max_wait + gsp->st_hash_max_nowait), NULL); + __db_dl_pct(env, + "The number of region locks that required waiting", + (u_long)gsp->st_region_wait, DB_PCT(gsp->st_region_wait, + gsp->st_region_wait + gsp->st_region_nowait), NULL); + __db_dl(env, "The number of buffers frozen", + (u_long)gsp->st_mvcc_frozen); + __db_dl(env, "The number of buffers thawed", + (u_long)gsp->st_mvcc_thawed); + __db_dl(env, "The number of frozen buffers freed", + (u_long)gsp->st_mvcc_freed); + __db_dl(env, "The number of page allocations", (u_long)gsp->st_alloc); + __db_dl(env, + "The number of hash buckets examined during allocations", + (u_long)gsp->st_alloc_buckets); + __db_dl(env, + "The maximum number of hash buckets examined for an allocation", + (u_long)gsp->st_alloc_max_buckets); + __db_dl(env, "The number of pages examined during allocations", + (u_long)gsp->st_alloc_pages); + __db_dl(env, "The max number of pages examined for an allocation", + (u_long)gsp->st_alloc_max_pages); + __db_dl(env, "Threads waited on page I/O", (u_long)gsp->st_io_wait); + __db_dl(env, "The number of times a sync is interrupted", + (u_long)gsp->st_sync_interrupted); + + for (tfsp = fsp; fsp != NULL && *tfsp != NULL; ++tfsp) { + if (LF_ISSET(DB_STAT_ALL)) + __db_msg(env, "%s", DB_GLOBAL(db_line)); + __db_msg(env, "Pool File: %s", (*tfsp)->file_name); + __db_dl(env, "Page size", (u_long)(*tfsp)->st_pagesize); + __db_dl(env, + "Requested pages mapped into the process' address space", + (u_long)(*tfsp)->st_map); + __db_dl_pct(env, "Requested pages found in the cache", + (u_long)(*tfsp)->st_cache_hit, DB_PCT((*tfsp)->st_cache_hit, + (*tfsp)->st_cache_hit + (*tfsp)->st_cache_miss), NULL); + __db_dl(env, "Requested pages not found in the cache", + (u_long)(*tfsp)->st_cache_miss); + __db_dl(env, "Pages created in the cache", + (u_long)(*tfsp)->st_page_create); + __db_dl(env, "Pages read into the cache", + (u_long)(*tfsp)->st_page_in); + __db_dl(env, + "Pages written from the cache to the backing file", + (u_long)(*tfsp)->st_page_out); + if ((*tfsp)->st_backup_spins != 0) + __db_dl(env, + "Spins while trying to backup the file", + (u_long)(*tfsp)->st_backup_spins); + } + + __os_ufree(env, fsp); + __os_ufree(env, gsp); + return (0); +} + +/* + * __memp_print_all -- + * Display debugging mpool region statistics. + */ +static int +__memp_print_all(env, flags) + ENV *env; + u_int32_t flags; +{ + static const FN cfn[] = { + { DB_MPOOL_NOFILE, "DB_MPOOL_NOFILE" }, + { DB_MPOOL_UNLINK, "DB_MPOOL_UNLINK" }, + { 0, NULL } + }; + DB_MPOOL *dbmp; + DB_MPOOLFILE *dbmfp; + MPOOL *mp; + roff_t fmap[FMAP_ENTRIES + 1]; + u_int32_t i, cnt; + int ret; + + dbmp = env->mp_handle; + mp = dbmp->reginfo[0].primary; + ret = 0; + + MPOOL_SYSTEM_LOCK(env); + + __db_print_reginfo(env, dbmp->reginfo, "Mpool", flags); + __db_msg(env, "%s", DB_GLOBAL(db_line)); + + __db_msg(env, "MPOOL structure:"); + __mutex_print_debug_single( + env, "MPOOL region mutex", mp->mtx_region, flags); + STAT_LSN("Maximum checkpoint LSN", &mp->lsn); + STAT_ULONG("Hash table entries", mp->htab_buckets); + STAT_ULONG("Hash table mutexes", mp->htab_mutexes); + + __db_msg(env, "%s", DB_GLOBAL(db_line)); + __db_msg(env, "DB_MPOOL handle information:"); + __mutex_print_debug_single( + env, "DB_MPOOL handle mutex", dbmp->mutex, flags); + STAT_ULONG("Underlying cache regions", mp->nreg); + + __db_msg(env, "%s", DB_GLOBAL(db_line)); + __db_msg(env, "DB_MPOOLFILE structures:"); + for (cnt = 0, dbmfp = TAILQ_FIRST(&dbmp->dbmfq); + dbmfp != NULL; dbmfp = TAILQ_NEXT(dbmfp, q), ++cnt) { + __db_msg(env, "File #%lu: %s: per-process, %s", + (u_long)cnt + 1, __memp_fn(dbmfp), + F_ISSET(dbmfp, MP_READONLY) ? "readonly" : "read/write"); + STAT_ULONG("Reference count", dbmfp->ref); + STAT_ULONG("Pinned block reference count", dbmfp->ref); + STAT_ULONG("Clear length", dbmfp->clear_len); + __db_print_fileid(env, dbmfp->fileid, "\tID"); + STAT_ULONG("File type", dbmfp->ftype); + STAT_ULONG("LSN offset", dbmfp->lsn_offset); + STAT_ULONG("Max gbytes", dbmfp->gbytes); + STAT_ULONG("Max bytes", dbmfp->bytes); + STAT_ULONG("Cache priority", dbmfp->priority); + STAT_POINTER("mmap address", dbmfp->addr); + STAT_ULONG("mmap length", dbmfp->len); + __db_prflags(env, NULL, dbmfp->flags, cfn, NULL, "\tFlags"); + __db_print_fh(env, "File handle", dbmfp->fhp, flags); + } + + __db_msg(env, "%s", DB_GLOBAL(db_line)); + __db_msg(env, "MPOOLFILE structures:"); + cnt = 0; + ret = __memp_walk_files(env, mp, __memp_print_files, fmap, &cnt, flags); + MPOOL_SYSTEM_UNLOCK(env); + if (ret != 0) + return (ret); + + if (cnt < FMAP_ENTRIES) + fmap[cnt] = INVALID_ROFF; + else + fmap[FMAP_ENTRIES] = INVALID_ROFF; + + /* Dump the individual caches. */ + for (i = 0; i < mp->nreg; ++i) { + __db_msg(env, "%s", DB_GLOBAL(db_line)); + __db_msg(env, "Cache #%d:", i + 1); + if (i > 0) + __env_alloc_print(&dbmp->reginfo[i], flags); + if ((ret = __memp_print_hash( + env, dbmp, &dbmp->reginfo[i], fmap, flags)) != 0) + break; + } + + return (ret); +} + +static int +__memp_print_files(env, mfp, argp, countp, flags) + ENV *env; + MPOOLFILE *mfp; + void *argp; + u_int32_t *countp; + u_int32_t flags; +{ + roff_t *fmap; + DB_MPOOL *dbmp; + u_int32_t mfp_flags; + static const FN fn[] = { + { MP_CAN_MMAP, "MP_CAN_MMAP" }, + { MP_DIRECT, "MP_DIRECT" }, + { MP_EXTENT, "MP_EXTENT" }, + { MP_FAKE_DEADFILE, "deadfile" }, + { MP_FAKE_FILEWRITTEN, "file written" }, + { MP_FAKE_NB, "no backing file" }, + { MP_FAKE_UOC, "unlink on close" }, + { MP_NOT_DURABLE, "not durable" }, + { MP_TEMP, "MP_TEMP" }, + { 0, NULL } + }; + + dbmp = env->mp_handle; + fmap = argp; + + __db_msg(env, "File #%d: %s", *countp + 1, __memp_fns(dbmp, mfp)); + __mutex_print_debug_single(env, "Mutex", mfp->mutex, flags); + + MUTEX_LOCK(env, mfp->mutex); + STAT_ULONG("Revision count", mfp->revision); + STAT_ULONG("Reference count", mfp->mpf_cnt); + STAT_ULONG("Sync/read only open count", mfp->neutral_cnt); + STAT_ULONG("Block count", mfp->block_cnt); + STAT_ULONG("Last page number", mfp->last_pgno); + STAT_ULONG("Original last page number", mfp->orig_last_pgno); + STAT_ULONG("Maximum page number", mfp->maxpgno); + STAT_LONG("Type", mfp->ftype); + STAT_LONG("Priority", mfp->priority); + STAT_LONG("Page's LSN offset", mfp->lsn_off); + STAT_LONG("Page's clear length", mfp->clear_len); + + __db_print_fileid(env, + R_ADDR(dbmp->reginfo, mfp->fileid_off), "\tID"); + + mfp_flags = 0; + if (mfp->deadfile) + FLD_SET(mfp_flags, MP_FAKE_DEADFILE); + if (mfp->file_written) + FLD_SET(mfp_flags, MP_FAKE_FILEWRITTEN); + if (mfp->no_backing_file) + FLD_SET(mfp_flags, MP_FAKE_NB); + if (mfp->unlink_on_close) + FLD_SET(mfp_flags, MP_FAKE_UOC); + __db_prflags(env, NULL, mfp_flags, fn, NULL, "\tFlags"); + + if (*countp < FMAP_ENTRIES) + fmap[*countp] = R_OFFSET(dbmp->reginfo, mfp); + (*countp)++; + MUTEX_UNLOCK(env, mfp->mutex); + return (0); +} + +/* + * __memp_print_hash -- + * Display hash bucket statistics for a cache. + */ +static int +__memp_print_hash(env, dbmp, reginfo, fmap, flags) + ENV *env; + DB_MPOOL *dbmp; + REGINFO *reginfo; + roff_t *fmap; + u_int32_t flags; +{ + BH *bhp, *vbhp; + DB_MPOOL_HASH *hp; + DB_MSGBUF mb; + MPOOL *c_mp; + u_int32_t bucket; + + c_mp = reginfo->primary; + DB_MSGBUF_INIT(&mb); + STAT_ULONG("Hash table last-checked", c_mp->last_checked); + STAT_ULONG("Hash table LRU priority", c_mp->lru_priority); + STAT_ULONG("Hash table LRU generation", c_mp->lru_generation); + STAT_ULONG("Put counter", c_mp->put_counter); + + /* Display the hash table list of BH's. */ + __db_msg(env, + "BH hash table (%lu hash slots)", (u_long)c_mp->htab_buckets); + __db_msg(env, "bucket #: priority, I/O wait, [mutex]"); + __db_msg(env, "\tpageno, file, ref, LSN, address, priority, flags"); + + for (hp = R_ADDR(reginfo, c_mp->htab), + bucket = 0; bucket < c_mp->htab_buckets; ++hp, ++bucket) { + MUTEX_READLOCK(env, hp->mtx_hash); + if ((bhp = SH_TAILQ_FIRST(&hp->hash_bucket, __bh)) != NULL) { + __db_msgadd(env, &mb, + "bucket %lu: %lu (%lu dirty)", + (u_long)bucket, (u_long)hp->hash_io_wait, + (u_long)atomic_read(&hp->hash_page_dirty)); + if (hp->hash_frozen != 0) + __db_msgadd(env, &mb, "(MVCC %lu/%lu/%lu) ", + (u_long)hp->hash_frozen, + (u_long)hp->hash_thawed, + (u_long)hp->hash_frozen_freed); + __mutex_print_debug_stats( + env, &mb, hp->mtx_hash, flags); + DB_MSGBUF_FLUSH(env, &mb); + } + for (; bhp != NULL; bhp = SH_TAILQ_NEXT(bhp, hq, __bh)) { + __memp_print_bh(env, dbmp, NULL, bhp, fmap); + + /* Print the version chain, if it exists. */ + for (vbhp = SH_CHAIN_PREV(bhp, vc, __bh); + vbhp != NULL; + vbhp = SH_CHAIN_PREV(vbhp, vc, __bh)) { + __memp_print_bh(env, dbmp, + " next:\t", vbhp, fmap); + } + } + MUTEX_UNLOCK(env, hp->mtx_hash); + } + + return (0); +} + +/* + * __memp_print_bh -- + * Display a BH structure. + */ +static void +__memp_print_bh(env, dbmp, prefix, bhp, fmap) + ENV *env; + DB_MPOOL *dbmp; + const char *prefix; + BH *bhp; + roff_t *fmap; +{ + static const FN fn[] = { + { BH_CALLPGIN, "callpgin" }, + { BH_DIRTY, "dirty" }, + { BH_DIRTY_CREATE, "created" }, + { BH_DISCARD, "discard" }, + { BH_EXCLUSIVE, "exclusive" }, + { BH_FREED, "freed" }, + { BH_FROZEN, "frozen" }, + { BH_TRASH, "trash" }, + { BH_THAWED, "thawed" }, + { 0, NULL } + }; + DB_MSGBUF mb; + int i; + + DB_MSGBUF_INIT(&mb); + + if (prefix != NULL) + __db_msgadd(env, &mb, "%s", prefix); + else + __db_msgadd(env, &mb, "\t"); + + for (i = 0; i < FMAP_ENTRIES; ++i) + if (fmap[i] == INVALID_ROFF || fmap[i] == bhp->mf_offset) + break; + + if (fmap[i] == INVALID_ROFF) + __db_msgadd(env, &mb, "%5lu, %lu, ", + (u_long)bhp->pgno, (u_long)bhp->mf_offset); + else + __db_msgadd( + env, &mb, "%5lu, #%d, ", (u_long)bhp->pgno, i + 1); + + __db_msgadd(env, &mb, "%2lu, %lu/%lu", (u_long)atomic_read(&bhp->ref), + F_ISSET(bhp, BH_FROZEN) ? 0 : (u_long)LSN(bhp->buf).file, + F_ISSET(bhp, BH_FROZEN) ? 0 : (u_long)LSN(bhp->buf).offset); + if (bhp->td_off != INVALID_ROFF) + __db_msgadd(env, &mb, " (@%lu/%lu 0x%x)", + (u_long)VISIBLE_LSN(env, bhp)->file, + (u_long)VISIBLE_LSN(env, bhp)->offset, + BH_OWNER(env, bhp)->txnid); + __db_msgadd(env, &mb, ", %#08lx, %lu", + (u_long)R_OFFSET(dbmp->reginfo, bhp), (u_long)bhp->priority); + __db_prflags(env, &mb, bhp->flags, fn, " (", ")"); + DB_MSGBUF_FLUSH(env, &mb); +} + +/* + * __memp_stat_wait -- + * Total hash bucket wait stats into the region. + */ +static void +__memp_stat_wait(env, reginfo, mp, mstat, flags) + ENV *env; + REGINFO *reginfo; + MPOOL *mp; + DB_MPOOL_STAT *mstat; + u_int32_t flags; +{ + DB_MPOOL_HASH *hp; + u_int32_t i; + uintmax_t tmp_nowait, tmp_wait; + + mstat->st_hash_max_wait = 0; + hp = R_ADDR(reginfo, mp->htab); + for (i = 0; i < mp->htab_buckets; i++, hp++) { + __mutex_set_wait_info( + env, hp->mtx_hash, &tmp_wait, &tmp_nowait); + mstat->st_hash_nowait += tmp_nowait; + mstat->st_hash_wait += tmp_wait; + if (tmp_wait > mstat->st_hash_max_wait) { + mstat->st_hash_max_wait = tmp_wait; + mstat->st_hash_max_nowait = tmp_nowait; + } + if (LF_ISSET(DB_STAT_CLEAR | + DB_STAT_SUBSYSTEM) == DB_STAT_CLEAR) + __mutex_clear(env, hp->mtx_hash); + + mstat->st_io_wait += hp->hash_io_wait; + mstat->st_mvcc_frozen += hp->hash_frozen; + mstat->st_mvcc_thawed += hp->hash_thawed; + mstat->st_mvcc_freed += hp->hash_frozen_freed; + if (LF_ISSET(DB_STAT_CLEAR)) { + hp->hash_io_wait = 0; + hp->hash_frozen = 0; + hp->hash_thawed = 0; + hp->hash_frozen_freed = 0; + } + } +} + +#else /* !HAVE_STATISTICS */ + +int +__memp_stat_pp(dbenv, gspp, fspp, flags) + DB_ENV *dbenv; + DB_MPOOL_STAT **gspp; + DB_MPOOL_FSTAT ***fspp; + u_int32_t flags; +{ + COMPQUIET(gspp, NULL); + COMPQUIET(fspp, NULL); + COMPQUIET(flags, 0); + + return (__db_stat_not_built(dbenv->env)); +} + +int +__memp_stat_print_pp(dbenv, flags) + DB_ENV *dbenv; + u_int32_t flags; +{ + COMPQUIET(flags, 0); + + return (__db_stat_not_built(dbenv->env)); +} +#endif + +/* + * __memp_stat_hash -- + * Total hash bucket stats (other than mutex wait) into the region. + * + * PUBLIC: void __memp_stat_hash __P((REGINFO *, MPOOL *, u_int32_t *)); + */ +void +__memp_stat_hash(reginfo, mp, dirtyp) + REGINFO *reginfo; + MPOOL *mp; + u_int32_t *dirtyp; +{ + DB_MPOOL_HASH *hp; + u_int32_t dirty, i; + + hp = R_ADDR(reginfo, mp->htab); + for (i = 0, dirty = 0; i < mp->htab_buckets; i++, hp++) + dirty += (u_int32_t)atomic_read(&hp->hash_page_dirty); + *dirtyp = dirty; +} diff -r 000000000000 -r a1985f14b030 src/mp/mp_sync.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/mp/mp_sync.c Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,987 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 1996, 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + * $Id$ + */ + +#include "db_config.h" + +#include "db_int.h" +#include "dbinc/log.h" +#include "dbinc/mp.h" +#include "dbinc/db_page.h" +#include "dbinc/hash.h" + +typedef struct { + DB_MPOOL_HASH *track_hp; /* Hash bucket. */ + + roff_t track_off; /* Page file offset. */ + db_pgno_t track_pgno; /* Page number. */ +} BH_TRACK; + +static int __bhcmp __P((const void *, const void *)); +static int __memp_close_flush_files __P((ENV *, int)); +static int __memp_sync_files __P((ENV *)); +static int __memp_sync_file __P((ENV *, + MPOOLFILE *, void *, u_int32_t *, u_int32_t)); + +/* + * __memp_walk_files -- + * PUBLIC: int __memp_walk_files __P((ENV *, MPOOL *, + * PUBLIC: int (*) __P((ENV *, MPOOLFILE *, void *, + * PUBLIC: u_int32_t *, u_int32_t)), void *, u_int32_t *, u_int32_t)); + */ +int +__memp_walk_files(env, mp, func, arg, countp, flags) + ENV *env; + MPOOL *mp; + int (*func)__P((ENV *, MPOOLFILE *, void *, u_int32_t *, u_int32_t)); + void *arg; + u_int32_t *countp; + u_int32_t flags; +{ + DB_MPOOL *dbmp; + DB_MPOOL_HASH *hp; + MPOOLFILE *mfp; + int i, ret, t_ret; + + dbmp = env->mp_handle; + ret = 0; + + hp = R_ADDR(dbmp->reginfo, mp->ftab); + for (i = 0; i < MPOOL_FILE_BUCKETS; i++, hp++) { + MUTEX_LOCK(env, hp->mtx_hash); + SH_TAILQ_FOREACH(mfp, &hp->hash_bucket, q, __mpoolfile) { + if ((t_ret = func(env, + mfp, arg, countp, flags)) != 0 && ret == 0) + ret = t_ret; + if (ret != 0 && !LF_ISSET(DB_STAT_MEMP_NOERROR)) + break; + } + MUTEX_UNLOCK(env, hp->mtx_hash); + if (ret != 0 && !LF_ISSET(DB_STAT_MEMP_NOERROR)) + break; + } + return (ret); +} + +/* + * __memp_discard_all_mpfs -- + * Force discard all mpoolfiles. When closing a private environment, we + * always want to discard all mpoolfiles to avoid memory leak. + * + * PUBLIC: int __memp_discard_all_mpfs __P((ENV *, MPOOL *)); + */ +int +__memp_discard_all_mpfs (env, mp) + ENV *env; + MPOOL *mp; +{ + DB_MPOOL *dbmp; + DB_MPOOL_HASH *hp; + MPOOLFILE *mfp; + int i, ret, t_ret; + + ret = t_ret = 0; + mfp = NULL; + hp = NULL; + dbmp = env->mp_handle; + + hp = R_ADDR(dbmp->reginfo, mp->ftab); + for (i = 0; i < MPOOL_FILE_BUCKETS; i++, hp++) { + MUTEX_LOCK(env, hp->mtx_hash); + while ((mfp = SH_TAILQ_FIRST( + &hp->hash_bucket, __mpoolfile)) != NULL) { + MUTEX_LOCK(env, mfp->mutex); + if ((t_ret = __memp_mf_discard(dbmp, mfp, 1)) != 0 && + ret == 0) + ret = t_ret; + } + MUTEX_UNLOCK(env, hp->mtx_hash); + } + return (ret); +} + +/* + * __memp_sync_pp -- + * ENV->memp_sync pre/post processing. + * + * PUBLIC: int __memp_sync_pp __P((DB_ENV *, DB_LSN *)); + */ +int +__memp_sync_pp(dbenv, lsnp) + DB_ENV *dbenv; + DB_LSN *lsnp; +{ + DB_THREAD_INFO *ip; + ENV *env; + int ret; + + env = dbenv->env; + + ENV_REQUIRES_CONFIG(env, + env->mp_handle, "memp_sync", DB_INIT_MPOOL); + + /* + * If no LSN is provided, flush the entire cache (reasonable usage + * even if there's no log subsystem configured). + */ + if (lsnp != NULL) + ENV_REQUIRES_CONFIG(env, + env->lg_handle, "memp_sync", DB_INIT_LOG); + + ENV_ENTER(env, ip); + REPLICATION_WRAP(env, (__memp_sync(env, DB_SYNC_CACHE, lsnp)), 0, ret); + ENV_LEAVE(env, ip); + return (ret); +} + +/* + * __memp_sync -- + * ENV->memp_sync. + * + * PUBLIC: int __memp_sync __P((ENV *, u_int32_t, DB_LSN *)); + */ +int +__memp_sync(env, flags, lsnp) + ENV *env; + u_int32_t flags; + DB_LSN *lsnp; +{ + DB_MPOOL *dbmp; + MPOOL *mp; + int interrupted, ret; + + dbmp = env->mp_handle; + mp = dbmp->reginfo[0].primary; + + /* If we've flushed to the requested LSN, return that information. */ + if (lsnp != NULL) { + MPOOL_SYSTEM_LOCK(env); + if (LOG_COMPARE(lsnp, &mp->lsn) <= 0) { + *lsnp = mp->lsn; + + MPOOL_SYSTEM_UNLOCK(env); + return (0); + } + MPOOL_SYSTEM_UNLOCK(env); + } + + if ((ret = + __memp_sync_int(env, NULL, 0, flags, NULL, &interrupted)) != 0) + return (ret); + + if (!interrupted && lsnp != NULL) { + MPOOL_SYSTEM_LOCK(env); + if (LOG_COMPARE(lsnp, &mp->lsn) > 0) + mp->lsn = *lsnp; + MPOOL_SYSTEM_UNLOCK(env); + } + + return (0); +} + +/* + * __memp_fsync_pp -- + * DB_MPOOLFILE->sync pre/post processing. + * + * PUBLIC: int __memp_fsync_pp __P((DB_MPOOLFILE *)); + */ +int +__memp_fsync_pp(dbmfp) + DB_MPOOLFILE *dbmfp; +{ + DB_THREAD_INFO *ip; + ENV *env; + int ret; + + env = dbmfp->env; + + MPF_ILLEGAL_BEFORE_OPEN(dbmfp, "DB_MPOOLFILE->sync"); + + ENV_ENTER(env, ip); + REPLICATION_WRAP(env, (__memp_fsync(dbmfp)), 0, ret); + ENV_LEAVE(env, ip); + return (ret); +} + +/* + * __memp_fsync -- + * DB_MPOOLFILE->sync. + * + * PUBLIC: int __memp_fsync __P((DB_MPOOLFILE *)); + */ +int +__memp_fsync(dbmfp) + DB_MPOOLFILE *dbmfp; +{ + MPOOLFILE *mfp; + + mfp = dbmfp->mfp; + + /* + * If this handle doesn't have a file descriptor that's open for + * writing, or if the file is a temporary, or if the file hasn't + * been written since it was flushed, there's no reason to proceed + * further. + */ + if (F_ISSET(dbmfp, MP_READONLY)) + return (0); + + if (F_ISSET(dbmfp->mfp, MP_TEMP) || dbmfp->mfp->no_backing_file) + return (0); + + if (mfp->file_written == 0) + return (0); + + return (__memp_sync_int( + dbmfp->env, dbmfp, 0, DB_SYNC_FILE, NULL, NULL)); +} + +/* + * __mp_xxx_fh -- + * Return a file descriptor for DB 1.85 compatibility locking. + * + * PUBLIC: int __mp_xxx_fh __P((DB_MPOOLFILE *, DB_FH **)); + */ +int +__mp_xxx_fh(dbmfp, fhp) + DB_MPOOLFILE *dbmfp; + DB_FH **fhp; +{ + int ret; + + /* + * This is a truly spectacular layering violation, intended ONLY to + * support compatibility for the DB 1.85 DB->fd call. + * + * Sync the database file to disk, creating the file as necessary. + * + * We skip the MP_READONLY and MP_TEMP tests done by memp_fsync(3). + * The MP_READONLY test isn't interesting because we will either + * already have a file descriptor (we opened the database file for + * reading) or we aren't readonly (we created the database which + * requires write privileges). The MP_TEMP test isn't interesting + * because we want to write to the backing file regardless so that + * we get a file descriptor to return. + */ + if ((*fhp = dbmfp->fhp) != NULL) + return (0); + + if ((ret = __memp_sync_int( + dbmfp->env, dbmfp, 0, DB_SYNC_FILE, NULL, NULL)) == 0) + *fhp = dbmfp->fhp; + return (ret); +} + +/* + * __memp_sync_int -- + * Mpool sync internal function. + * + * PUBLIC: int __memp_sync_int __P((ENV *, + * PUBLIC: DB_MPOOLFILE *, u_int32_t, u_int32_t, u_int32_t *, int *)); + */ +int +__memp_sync_int(env, dbmfp, trickle_max, flags, wrote_totalp, interruptedp) + ENV *env; + DB_MPOOLFILE *dbmfp; + u_int32_t trickle_max, flags, *wrote_totalp; + int *interruptedp; +{ + BH *bhp; + BH_TRACK *bharray; + DB_MPOOL *dbmp; + DB_MPOOL_HASH *hp; + MPOOL *c_mp, *mp; + MPOOLFILE *mfp; + db_mutex_t mutex; + roff_t last_mf_offset; + u_int32_t ar_cnt, ar_max, i, n_cache, remaining, wrote_total; + int32_t wrote_cnt; + int dirty, filecnt, maxopenfd, required_write, ret, t_ret; + + dbmp = env->mp_handle; + mp = dbmp->reginfo[0].primary; + last_mf_offset = INVALID_ROFF; + filecnt = wrote_total = 0; + + if (wrote_totalp != NULL) + *wrote_totalp = 0; + if (interruptedp != NULL) + *interruptedp = 0; + + /* + * If we're flushing the cache, it's a checkpoint or we're flushing a + * specific file, we really have to write the blocks and we have to + * confirm they made it to disk. Otherwise, we can skip a block if + * it's hard to get. + */ + required_write = LF_ISSET(DB_SYNC_CACHE | + DB_SYNC_CHECKPOINT | DB_SYNC_FILE | DB_SYNC_QUEUE_EXTENT); + + /* Get shared configuration information. */ + MPOOL_SYSTEM_LOCK(env); + maxopenfd = mp->mp_maxopenfd; + MPOOL_SYSTEM_UNLOCK(env); + + /* Assume one dirty page per bucket. */ + ar_max = mp->nreg * mp->htab_buckets; + if ((ret = + __os_malloc(env, ar_max * sizeof(BH_TRACK), &bharray)) != 0) + return (ret); + + /* + * Walk each cache's list of buffers and mark all dirty buffers to be + * written and all dirty buffers to be potentially written, depending + * on our flags. + */ + for (ar_cnt = 0, n_cache = 0; n_cache < mp->nreg; ++n_cache) { + c_mp = dbmp->reginfo[n_cache].primary; + + hp = R_ADDR(&dbmp->reginfo[n_cache], c_mp->htab); + for (i = 0; i < c_mp->htab_buckets; i++, hp++) { + /* + * We can check for empty buckets before locking as + * we only care if the pointer is zero or non-zero. + * We can ignore empty or clean buckets because we + * only need write buffers that were dirty before + * we started. + */ +#ifdef DIAGNOSTIC + if (SH_TAILQ_FIRST(&hp->hash_bucket, __bh) == NULL) +#else + if (atomic_read(&hp->hash_page_dirty) == 0) +#endif + continue; + + dirty = 0; + MUTEX_LOCK(env, hp->mtx_hash); + SH_TAILQ_FOREACH(bhp, &hp->hash_bucket, hq, __bh) { + /* Always ignore clean pages. */ + if (!F_ISSET(bhp, BH_DIRTY)) + continue; + + dirty++; + mfp = R_ADDR(dbmp->reginfo, bhp->mf_offset); + + /* + * Ignore in-memory files, unless the file is + * specifically being flushed. + */ + if (mfp->no_backing_file) + continue; + if (!LF_ISSET(DB_SYNC_FILE) && + F_ISSET(mfp, MP_TEMP)) + continue; + + /* + * Ignore files that aren't involved in DB's + * transactional operations during checkpoints. + */ + if (LF_ISSET(DB_SYNC_CHECKPOINT) && + mfp->lsn_off == DB_LSN_OFF_NOTSET) + continue; + + /* + * Ignore files that aren't Queue extent files + * if we're flushing a Queue file with extents. + */ + if (LF_ISSET(DB_SYNC_QUEUE_EXTENT) && + !F_ISSET(mfp, MP_EXTENT)) + continue; + + /* + * If we're flushing a specific file, see if + * this page is from that file. + */ + if (dbmfp != NULL && mfp != dbmfp->mfp) + continue; + + /* Track the buffer, we want it. */ + bharray[ar_cnt].track_hp = hp; + bharray[ar_cnt].track_pgno = bhp->pgno; + bharray[ar_cnt].track_off = bhp->mf_offset; + ar_cnt++; + + /* + * If we run out of space, double and continue. + * Don't stop at trickle_max, we want to sort + * as large a sample set as possible in order + * to minimize disk seeks. + */ + if (ar_cnt >= ar_max) { + if ((ret = __os_realloc(env, + (ar_max * 2) * sizeof(BH_TRACK), + &bharray)) != 0) + break; + ar_max *= 2; + } + } + + if (ret != 0) + goto err; + /* + * We are only checking this in diagnostic mode + * since it requires extra latching to keep the count + * in sync with the number of bits counted. + */ + DB_ASSERT(env, + dirty == (int)atomic_read(&hp->hash_page_dirty)); + MUTEX_UNLOCK(env, hp->mtx_hash); + + /* Check if the call has been interrupted. */ + if (LF_ISSET(DB_SYNC_INTERRUPT_OK) && FLD_ISSET( + mp->config_flags, DB_MEMP_SYNC_INTERRUPT)) { + STAT(++mp->stat.st_sync_interrupted); + if (interruptedp != NULL) + *interruptedp = 1; + goto err; + } + } + } + + /* If there no buffers to write, we're done. */ + if (ar_cnt == 0) + goto done; + + /* + * Write the buffers in file/page order, trying to reduce seeks by the + * filesystem and, when pages are smaller than filesystem block sizes, + * reduce the actual number of writes. + */ + if (ar_cnt > 1) + qsort(bharray, ar_cnt, sizeof(BH_TRACK), __bhcmp); + + /* + * If we're trickling buffers, only write enough to reach the correct + * percentage. + */ + if (LF_ISSET(DB_SYNC_TRICKLE) && ar_cnt > trickle_max) + ar_cnt = trickle_max; + + /* + * Flush the log. We have to ensure the log records reflecting the + * changes on the database pages we're writing have already made it + * to disk. We still have to check the log each time we write a page + * (because pages we are about to write may be modified after we have + * flushed the log), but in general this will at least avoid any I/O + * on the log's part. + */ + if (LOGGING_ON(env) && (ret = __log_flush(env, NULL)) != 0) + goto err; + + /* + * Walk the array, writing buffers. When we write a buffer, we NULL + * out its hash bucket pointer so we don't process a slot more than + * once. + */ + for (i = wrote_cnt = 0, remaining = ar_cnt; remaining > 0; ++i) { + if (i >= ar_cnt) { + i = 0; + __os_yield(env, 1, 0); + } + if ((hp = bharray[i].track_hp) == NULL) + continue; + + /* Lock the hash bucket and find the buffer. */ + mutex = hp->mtx_hash; + MUTEX_READLOCK(env, mutex); + SH_TAILQ_FOREACH(bhp, &hp->hash_bucket, hq, __bh) + if (bhp->pgno == bharray[i].track_pgno && + bhp->mf_offset == bharray[i].track_off) + break; + + /* + * If we can't find the buffer we're done, somebody else had + * to have written it. + * + * If the buffer isn't dirty, we're done, there's no work + * needed. + */ + if (bhp == NULL || !F_ISSET(bhp, BH_DIRTY)) { + MUTEX_UNLOCK(env, mutex); + --remaining; + bharray[i].track_hp = NULL; + continue; + } + + /* + * If the buffer is locked by another thread, ignore it, we'll + * come back to it. + */ + if (F_ISSET(bhp, BH_EXCLUSIVE)) { + MUTEX_UNLOCK(env, mutex); + if (!required_write) { + --remaining; + bharray[i].track_hp = NULL; + } + continue; + } + + /* Pin the buffer into memory. */ + atomic_inc(env, &bhp->ref); + MUTEX_UNLOCK(env, mutex); + MUTEX_READLOCK(env, bhp->mtx_buf); + DB_ASSERT(env, !F_ISSET(bhp, BH_EXCLUSIVE)); + + /* + * When swapping the hash bucket mutex for the buffer mutex, + * we may have raced with an MVCC update. In that case, we + * no longer have the most recent version, and need to retry + * (the buffer header we have pinned will no longer be marked + * dirty, so we can't just write it). + */ + if (SH_CHAIN_HASNEXT(bhp, vc)) { + atomic_dec(env, &bhp->ref); + MUTEX_UNLOCK(env, bhp->mtx_buf); + continue; + } + + /* + * If we've switched files, check to see if we're configured + * to close file descriptors. + */ + if (maxopenfd != 0 && bhp->mf_offset != last_mf_offset) { + if (++filecnt >= maxopenfd) { + filecnt = 0; + if ((t_ret = __memp_close_flush_files( + env, 1)) != 0 && ret == 0) + ret = t_ret; + } + last_mf_offset = bhp->mf_offset; + } + + /* + * If the buffer is dirty, we write it. We only try to + * write the buffer once. + */ + if (F_ISSET(bhp, BH_DIRTY)) { + mfp = R_ADDR(dbmp->reginfo, bhp->mf_offset); + if ((t_ret = + __memp_bhwrite(dbmp, hp, mfp, bhp, 1)) == 0) { + ++wrote_cnt; + ++wrote_total; + } else { + /* The buffer is being backed up, try again. */ + if (t_ret == EAGAIN) { + atomic_dec(env, &bhp->ref); + MUTEX_UNLOCK(env, bhp->mtx_buf); + continue; + } + if (ret == 0) + ret = t_ret; + __db_errx(env, DB_STR_A("3027", + "%s: unable to flush page: %lu", "%s %lu"), + __memp_fns(dbmp, mfp), (u_long)bhp->pgno); + + } + } + + /* we disposed of this buffer. */ + --remaining; + bharray[i].track_hp = NULL; + + /* Discard our buffer reference. */ + DB_ASSERT(env, atomic_read(&bhp->ref) > 0); + atomic_dec(env, &bhp->ref); + MUTEX_UNLOCK(env, bhp->mtx_buf); + + /* Check if the call has been interrupted. */ + if (LF_ISSET(DB_SYNC_INTERRUPT_OK) && + FLD_ISSET(mp->config_flags, DB_MEMP_SYNC_INTERRUPT)) { + STAT(++mp->stat.st_sync_interrupted); + if (interruptedp != NULL) + *interruptedp = 1; + goto err; + } + + /* + * Sleep after some number of writes to avoid disk saturation. + * Don't cache the max writes value, an application shutting + * down might reset the value in order to do a fast flush or + * checkpoint. + */ + if (!LF_ISSET(DB_SYNC_SUPPRESS_WRITE) && + !FLD_ISSET(mp->config_flags, DB_MEMP_SUPPRESS_WRITE) && + mp->mp_maxwrite != 0 && wrote_cnt >= mp->mp_maxwrite) { + wrote_cnt = 0; + __os_yield(env, 0, (u_long)mp->mp_maxwrite_sleep); + } + } + +done: /* + * If a write is required, we have to force the pages to disk. We + * don't do this as we go along because we want to give the OS as + * much time as possible to lazily flush, and because we have to flush + * files that might not even have had dirty buffers in the cache, so + * we have to walk the files list. + */ + if (ret == 0 && required_write) { + if (dbmfp == NULL) + ret = __memp_sync_files(env); + else + ret = __os_fsync(env, dbmfp->fhp); + } + + /* If we've opened files to flush pages, close them. */ + if ((t_ret = __memp_close_flush_files(env, 0)) != 0 && ret == 0) + ret = t_ret; + +err: __os_free(env, bharray); + if (wrote_totalp != NULL) + *wrote_totalp = wrote_total; + + return (ret); +} + +static int +__memp_sync_file(env, mfp, argp, countp, flags) + ENV *env; + MPOOLFILE *mfp; + void *argp; + u_int32_t *countp; + u_int32_t flags; +{ + DB_MPOOL *dbmp; + DB_MPOOLFILE *dbmfp; + int ret, t_ret; + + COMPQUIET(countp, NULL); + COMPQUIET(flags, 0); + + if (!mfp->file_written || mfp->no_backing_file || + mfp->deadfile || F_ISSET(mfp, MP_TEMP)) + return (0); + /* + * Pin the MPOOLFILE structure into memory, and release the + * region mutex allowing us to walk the linked list. We'll + * re-acquire that mutex to move to the next entry in the list. + * + * This works because we only need to flush current entries, + * we don't care about new entries being added, and the linked + * list is never re-ordered, a single pass is sufficient. It + * requires MPOOLFILE structures removed before we get to them + * be flushed to disk, but that's nothing new, they could have + * been removed while checkpoint was running, too. + * + * Once we have the MPOOLFILE lock, re-check the MPOOLFILE is + * not being discarded. (A thread removing the MPOOLFILE + * will: hold the MPOOLFILE mutex, set deadfile, drop the + * MPOOLFILE mutex and then acquire the region MUTEX to walk + * the linked list and remove the MPOOLFILE structure. Make + * sure the MPOOLFILE wasn't marked dead while we waited for + * the mutex. + */ + MUTEX_LOCK(env, mfp->mutex); + if (!mfp->file_written || mfp->deadfile) { + MUTEX_UNLOCK(env, mfp->mutex); + return (0); + } + ++mfp->mpf_cnt; + ++mfp->neutral_cnt; + MUTEX_UNLOCK(env, mfp->mutex); + + /* + * Look for an already open, writable handle (fsync doesn't + * work on read-only Windows handles). + */ + dbmp = env->mp_handle; + MUTEX_LOCK(env, dbmp->mutex); + TAILQ_FOREACH(dbmfp, &dbmp->dbmfq, q) { + if (dbmfp->mfp != mfp || F_ISSET(dbmfp, MP_READONLY)) + continue; + /* + * We don't want to hold the mutex while calling sync. + * Increment the DB_MPOOLFILE handle ref count to pin + * it into memory. + */ + ++dbmfp->ref; + break; + } + MUTEX_UNLOCK(env, dbmp->mutex); + + /* If we don't find a handle we can use, open one. */ + if (dbmfp == NULL) { + if ((ret = __memp_mf_sync(dbmp, mfp, 1)) != 0) { + __db_err(env, ret, DB_STR_A("3028", + "%s: unable to flush", "%s"), (char *) + R_ADDR(dbmp->reginfo, mfp->path_off)); + } + } else + ret = __os_fsync(env, dbmfp->fhp); + + /* + * Re-acquire the MPOOLFILE mutex, we need it to modify the + * reference count. + */ + MUTEX_LOCK(env, mfp->mutex); + + /* + * If we wrote the file and there are no other references (or there + * is a single reference, and it's the one we opened to write + * buffers during checkpoint), clear the file_written flag. We + * do this so that applications opening thousands of files don't + * loop here opening and flushing those files during checkpoint. + * + * The danger here is if a buffer were to be written as part of + * a checkpoint, and then not be flushed to disk. This cannot + * happen because we only clear file_written when there are no + * other users of the MPOOLFILE in the system, and, as we hold + * the region lock, no possibility of another thread of control + * racing with us to open a MPOOLFILE. + */ + if (mfp->mpf_cnt == 1 || (mfp->mpf_cnt == 2 && + dbmfp != NULL && F_ISSET(dbmfp, MP_FLUSH))) { + mfp->file_written = 0; + + /* + * We may be the last reference for a MPOOLFILE, as we + * weren't holding the MPOOLFILE mutex when flushing + * it's buffers to disk. If we can discard it, set + * a flag to schedule a clean-out pass. (Not likely, + * I mean, what are the chances that there aren't any + * buffers in the pool? Regardless, it might happen.) + */ + if (mfp->mpf_cnt == 1 && mfp->block_cnt == 0) + *(int *)argp = 1; + } + + /* + * If we found the file we must close it in case we are the last + * reference to the dbmfp. NOTE: since we have incremented + * mfp->mpf_cnt this cannot be the last reference to the mfp. + * This is important since we are called with the hash bucket + * locked. The mfp will get freed via the cleanup pass. + */ + if (dbmfp != NULL && + (t_ret = __memp_fclose(dbmfp, DB_MPOOL_NOLOCK)) != 0 && ret == 0) + ret = t_ret; + + --mfp->mpf_cnt; + DB_ASSERT(env, mfp->neutral_cnt != 0); + --mfp->neutral_cnt; + + /* Unlock the MPOOLFILE. */ + MUTEX_UNLOCK(env, mfp->mutex); + return (ret); +} + +/* + * __memp_sync_files -- + * Sync all the files in the environment, open or not. + */ +static int +__memp_sync_files(env) + ENV *env; +{ + DB_MPOOL *dbmp; + DB_MPOOL_HASH *hp; + MPOOL *mp; + MPOOLFILE *mfp, *next_mfp; + int i, need_discard_pass, ret; + + dbmp = env->mp_handle; + mp = dbmp->reginfo[0].primary; + need_discard_pass = ret = 0; + + ret = __memp_walk_files(env, + mp, __memp_sync_file, &need_discard_pass, 0, DB_STAT_MEMP_NOERROR); + + /* + * We may need to do a last pass through the MPOOLFILE list -- if we + * were the last reference to an MPOOLFILE, we need to clean it out. + */ + if (!need_discard_pass) + return (ret); + + hp = R_ADDR(dbmp->reginfo, mp->ftab); + for (i = 0; i < MPOOL_FILE_BUCKETS; i++, hp++) { +retry: MUTEX_LOCK(env, hp->mtx_hash); + for (mfp = SH_TAILQ_FIRST(&hp->hash_bucket, + __mpoolfile); mfp != NULL; mfp = next_mfp) { + next_mfp = SH_TAILQ_NEXT(mfp, q, __mpoolfile); + /* + * Do a fast check -- we can check for zero/non-zero + * without a mutex on the MPOOLFILE. If likely to + * succeed, lock the MPOOLFILE down and look for real. + */ + if (mfp->deadfile || + mfp->block_cnt != 0 || mfp->mpf_cnt != 0) + continue; + + MUTEX_LOCK(env, mfp->mutex); + if (!mfp->deadfile && + mfp->block_cnt == 0 && mfp->mpf_cnt == 0) { + MUTEX_UNLOCK(env, hp->mtx_hash); + (void)__memp_mf_discard(dbmp, mfp, 0); + goto retry; + } else + MUTEX_UNLOCK(env, mfp->mutex); + } + MUTEX_UNLOCK(env, hp->mtx_hash); + } + return (ret); +} + +/* + * __memp_mf_sync -- + * Flush an MPOOLFILE, when no currently open handle is available. + * + * PUBLIC: int __memp_mf_sync __P((DB_MPOOL *, MPOOLFILE *, int)); + */ +int +__memp_mf_sync(dbmp, mfp, locked) + DB_MPOOL *dbmp; + MPOOLFILE *mfp; + int locked; +{ + DB_FH *fhp; + DB_MPOOL_HASH *hp; + ENV *env; + MPOOL *mp; + int ret, t_ret; + char *rpath; + + COMPQUIET(hp, NULL); + env = dbmp->env; + + /* + * We need to be holding the hash lock: we're using the path name + * and __memp_nameop might try and rename the file. + */ + if (!locked) { + mp = dbmp->reginfo[0].primary; + hp = R_ADDR(dbmp->reginfo, mp->ftab); + hp += FNBUCKET( + R_ADDR(dbmp->reginfo, mfp->fileid_off), DB_FILE_ID_LEN); + MUTEX_LOCK(env, hp->mtx_hash); + } + + if ((ret = __db_appname(env, DB_APP_DATA, + R_ADDR(dbmp->reginfo, mfp->path_off), NULL, &rpath)) == 0) { + if ((ret = __os_open(env, rpath, 0, 0, 0, &fhp)) == 0) { + ret = __os_fsync(env, fhp); + if ((t_ret = + __os_closehandle(env, fhp)) != 0 && ret == 0) + ret = t_ret; + } + __os_free(env, rpath); + } + + if (!locked) + MUTEX_UNLOCK(env, hp->mtx_hash); + + return (ret); +} + +/* + * __memp_close_flush_files -- + * Close files opened only to flush buffers. + */ +static int +__memp_close_flush_files(env, dosync) + ENV *env; + int dosync; +{ + DB_MPOOL *dbmp; + DB_MPOOLFILE *dbmfp; + MPOOLFILE *mfp; + int ret; + + dbmp = env->mp_handle; + + /* + * The routine exists because we must close files opened by sync to + * flush buffers. There are two cases: first, extent files have to + * be closed so they may be removed when empty. Second, regular + * files have to be closed so we don't run out of descriptors (for + * example, an application partitioning its data into databases + * based on timestamps, so there's a continually increasing set of + * files). + * + * We mark files opened in the __memp_bhwrite() function with the + * MP_FLUSH flag. Here we walk through our file descriptor list, + * and, if a file was opened by __memp_bhwrite(), we close it. + */ +retry: MUTEX_LOCK(env, dbmp->mutex); + TAILQ_FOREACH(dbmfp, &dbmp->dbmfq, q) + if (F_ISSET(dbmfp, MP_FLUSH)) { + F_CLR(dbmfp, MP_FLUSH); + MUTEX_UNLOCK(env, dbmp->mutex); + if (dosync) { + /* + * If we have the only open handle on the file, + * clear the dirty flag so we don't re-open and + * sync it again when discarding the MPOOLFILE + * structure. Clear the flag before the sync + * so can't race with a thread writing the file. + */ + mfp = dbmfp->mfp; + if (mfp->mpf_cnt == 1) { + MUTEX_LOCK(env, mfp->mutex); + if (mfp->mpf_cnt == 1) + mfp->file_written = 0; + MUTEX_UNLOCK(env, mfp->mutex); + } + if ((ret = __os_fsync(env, dbmfp->fhp)) != 0) + return (ret); + } + if ((ret = __memp_fclose(dbmfp, DB_FLUSH)) != 0) + return (ret); + goto retry; + } + MUTEX_UNLOCK(env, dbmp->mutex); + + return (0); +} + +static int +__bhcmp(p1, p2) + const void *p1, *p2; +{ + BH_TRACK *bhp1, *bhp2; + + bhp1 = (BH_TRACK *)p1; + bhp2 = (BH_TRACK *)p2; + + /* Sort by file (shared memory pool offset). */ + if (bhp1->track_off < bhp2->track_off) + return (-1); + if (bhp1->track_off > bhp2->track_off) + return (1); + + /* + * !!! + * Defend against badly written quicksort code calling the comparison + * function with two identical pointers (e.g., WATCOM C++ (Power++)). + */ + if (bhp1->track_pgno < bhp2->track_pgno) + return (-1); + if (bhp1->track_pgno > bhp2->track_pgno) + return (1); + return (0); +} diff -r 000000000000 -r a1985f14b030 src/mp/mp_trickle.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/mp/mp_trickle.c Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,134 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 1996, 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + * $Id$ + */ + +#include "db_config.h" + +#include "db_int.h" +#include "dbinc/log.h" +#include "dbinc/mp.h" + +static int __memp_trickle __P((ENV *, int, int *)); + +/* + * __memp_trickle_pp -- + * ENV->memp_trickle pre/post processing. + * + * PUBLIC: int __memp_trickle_pp __P((DB_ENV *, int, int *)); + */ +int +__memp_trickle_pp(dbenv, pct, nwrotep) + DB_ENV *dbenv; + int pct, *nwrotep; +{ + DB_THREAD_INFO *ip; + ENV *env; + int ret; + + env = dbenv->env; + + ENV_REQUIRES_CONFIG(env, + env->mp_handle, "memp_trickle", DB_INIT_MPOOL); + + ENV_ENTER(env, ip); + REPLICATION_WRAP(env, (__memp_trickle(env, pct, nwrotep)), 0, ret); + ENV_LEAVE(env, ip); + return (ret); +} + +/* + * __memp_trickle -- + * ENV->memp_trickle. + */ +static int +__memp_trickle(env, pct, nwrotep) + ENV *env; + int pct, *nwrotep; +{ + DB_MPOOL *dbmp; + MPOOL *c_mp, *mp; + u_int32_t clean, dirty, i, need_clean, total, dtmp, wrote; + int ret; + + dbmp = env->mp_handle; + mp = dbmp->reginfo[0].primary; + + if (nwrotep != NULL) + *nwrotep = 0; + + if (pct < 1 || pct > 100) { + __db_errx(env, DB_STR_A("3007", + "DB_ENV->memp_trickle: %d: percent must be between 1 and 100", + "%d"), pct); + return (EINVAL); + } + + /* + * Loop through the caches counting total/dirty buffers. + * + * XXX + * Using hash_page_dirty is our only choice at the moment, but it's not + * as correct as we might like in the presence of pools having more + * than one page size, as a free 512B buffer may not be equivalent to + * having a free 8KB buffer. + */ + for (ret = 0, i = dirty = total = 0; i < mp->nreg; ++i) { + c_mp = dbmp->reginfo[i].primary; + total += c_mp->pages; + __memp_stat_hash(&dbmp->reginfo[i], c_mp, &dtmp); + dirty += dtmp; + } + + /* + * If there are sufficient clean buffers, no buffers or no dirty + * buffers, we're done. + */ + if (total == 0 || dirty == 0) + return (0); + + /* + * The total number of pages is an exact number, but the dirty page + * count can change while we're walking the hash buckets, and it's + * even possible the dirty page count ends up larger than the total + * number of pages. + */ + clean = total > dirty ? total - dirty : 0; + need_clean = (total * (u_int)pct) / 100; + if (clean >= need_clean) + return (0); + + need_clean -= clean; + ret = __memp_sync_int(env, NULL, + need_clean, DB_SYNC_TRICKLE | DB_SYNC_INTERRUPT_OK, &wrote, NULL); + STAT((mp->stat.st_page_trickle += wrote)); + if (nwrotep != NULL) + *nwrotep = (int)wrote; + + return (ret); +} diff -r 000000000000 -r a1985f14b030 src/mutex/mut_alloc.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/mutex/mut_alloc.c Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,313 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 1999, 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + * $Id$ + */ + +#include "db_config.h" + +#include "db_int.h" + +/* + * __mutex_alloc -- + * Allocate a mutex from the mutex region. + * + * PUBLIC: int __mutex_alloc __P((ENV *, int, u_int32_t, db_mutex_t *)); + */ +int +__mutex_alloc(env, alloc_id, flags, indxp) + ENV *env; + int alloc_id; + u_int32_t flags; + db_mutex_t *indxp; +{ + /* The caller may depend on us to initialize. */ + *indxp = MUTEX_INVALID; + + /* + * If this is not an application lock, and we've turned off locking, + * or the ENV handle isn't thread-safe, and this is a thread lock + * or the environment isn't multi-process by definition, there's no + * need to mutex at all. + */ + if (alloc_id != MTX_APPLICATION && alloc_id != MTX_MUTEX_TEST && + (F_ISSET(env->dbenv, DB_ENV_NOLOCKING) || + (!F_ISSET(env, ENV_THREAD) && + (LF_ISSET(DB_MUTEX_PROCESS_ONLY) || + F_ISSET(env, ENV_PRIVATE))))) + return (0); + + /* Private environments never share mutexes. */ + if (F_ISSET(env, ENV_PRIVATE)) + LF_SET(DB_MUTEX_PROCESS_ONLY); + + /* + * If we have a region in which to allocate the mutexes, lock it and + * do the allocation. + */ + if (!MUTEX_ON(env)) { + __db_errx(env, DB_STR("2033", + "Mutex allocated before mutex region.")); + return (__env_panic(env, EINVAL)); + } + return (__mutex_alloc_int(env, 1, alloc_id, flags, indxp)); +} + +/* + * __mutex_alloc_int -- + * Internal routine to allocate a mutex. + * + * PUBLIC: int __mutex_alloc_int + * PUBLIC: __P((ENV *, int, int, u_int32_t, db_mutex_t *)); + */ +int +__mutex_alloc_int(env, locksys, alloc_id, flags, indxp) + ENV *env; + int locksys, alloc_id; + u_int32_t flags; + db_mutex_t *indxp; +{ + DB_ENV *dbenv; + DB_MUTEX *mutexp; + DB_MUTEXMGR *mtxmgr; + DB_MUTEXREGION *mtxregion; + db_mutex_t i; + size_t len; + u_int32_t cnt; + int ret; + + dbenv = env->dbenv; + mtxmgr = env->mutex_handle; + mtxregion = mtxmgr->reginfo.primary; + ret = 0; + + /* + * If we're not initializing the mutex region, then lock the region to + * allocate new mutexes. Drop the lock before initializing the mutex, + * mutex initialization may require a system call. + */ + if (locksys) + MUTEX_SYSTEM_LOCK(env); + + if (mtxregion->mutex_next == MUTEX_INVALID) { + if (mtxregion->stat.st_mutex_max != 0 && + mtxregion->stat.st_mutex_cnt >= + mtxregion->stat.st_mutex_max) { +nomem: __db_errx(env, DB_STR("2034", + "unable to allocate memory for mutex; resize mutex region")); + if (locksys) + MUTEX_SYSTEM_UNLOCK(env); + return (ret == 0 ? ENOMEM : ret); + } + cnt = mtxregion->stat.st_mutex_cnt / 2; + if (cnt < 8) + cnt = 8; + if (mtxregion->stat.st_mutex_max != 0 && + mtxregion->stat.st_mutex_cnt + cnt > + mtxregion->stat.st_mutex_max) + cnt = mtxregion->stat.st_mutex_max - + mtxregion->stat.st_mutex_cnt; + if (F_ISSET(env, ENV_PRIVATE)) { + F_SET(&mtxmgr->reginfo, REGION_TRACKED); + while (__env_alloc(&mtxmgr->reginfo, + (cnt * mtxregion->mutex_size) + + mtxregion->stat.st_mutex_align, &i) != 0) + if ((cnt >> 1) == 0) + break; + F_CLR(&mtxmgr->reginfo, REGION_TRACKED); + i = (db_mutex_t)ALIGNP_INC(i, + mtxregion->stat.st_mutex_align); + } else { + len = cnt * mtxregion->mutex_size; + if ((ret = __env_alloc_extend(&mtxmgr->reginfo, + R_ADDR(&mtxmgr->reginfo, + mtxregion->mutex_off_alloc), &len)) != 0) + goto nomem; + cnt = (u_int32_t)(len / mtxregion->mutex_size); + i = mtxregion->stat.st_mutex_cnt + 1; + } + if (cnt == 0) + goto nomem; + mutexp = MUTEXP_SET(env, i); + mtxregion->stat.st_mutex_free = cnt; + mtxregion->mutex_next = i; + mtxregion->stat.st_mutex_cnt += cnt; + while (--cnt > 0) { + mutexp->flags = 0; + if (F_ISSET(env, ENV_PRIVATE)) + mutexp->mutex_next_link = + (uintptr_t)(mutexp + 1); + else + mutexp->mutex_next_link = ++i; + mutexp++; + } + mutexp->flags = 0; + mutexp->mutex_next_link = MUTEX_INVALID; + } + + *indxp = mtxregion->mutex_next; + mutexp = MUTEXP_SET(env, *indxp); + DB_ASSERT(env, + ((uintptr_t)mutexp & (dbenv->mutex_align - 1)) == 0); + mtxregion->mutex_next = mutexp->mutex_next_link; + + --mtxregion->stat.st_mutex_free; + ++mtxregion->stat.st_mutex_inuse; + if (mtxregion->stat.st_mutex_inuse > mtxregion->stat.st_mutex_inuse_max) + mtxregion->stat.st_mutex_inuse_max = + mtxregion->stat.st_mutex_inuse; + if (locksys) + MUTEX_SYSTEM_UNLOCK(env); + + /* Initialize the mutex. */ + memset(mutexp, 0, sizeof(*mutexp)); + F_SET(mutexp, DB_MUTEX_ALLOCATED | + LF_ISSET(DB_MUTEX_LOGICAL_LOCK | + DB_MUTEX_PROCESS_ONLY | DB_MUTEX_SHARED)); + + /* + * If the mutex is associated with a single process, set the process + * ID. If the application ever calls DbEnv::failchk, we'll need the + * process ID to know if the mutex is still in use. + */ + if (LF_ISSET(DB_MUTEX_PROCESS_ONLY)) + dbenv->thread_id(dbenv, &mutexp->pid, NULL); + +#ifdef HAVE_STATISTICS + mutexp->alloc_id = alloc_id; +#else + COMPQUIET(alloc_id, 0); +#endif + + if ((ret = __mutex_init(env, *indxp, flags)) != 0) + (void)__mutex_free_int(env, locksys, indxp); + + return (ret); +} + +/* + * __mutex_free -- + * Free a mutex. + * + * PUBLIC: int __mutex_free __P((ENV *, db_mutex_t *)); + */ +int +__mutex_free(env, indxp) + ENV *env; + db_mutex_t *indxp; +{ + /* + * There is no explicit ordering in how the regions are cleaned up + * up and/or discarded when an environment is destroyed (either a + * private environment is closed or a public environment is removed). + * The way we deal with mutexes is to clean up all remaining mutexes + * when we close the mutex environment (because we have to be able to + * do that anyway, after a crash), which means we don't have to deal + * with region cleanup ordering on normal environment destruction. + * All that said, what it really means is we can get here without a + * mpool region. It's OK, the mutex has been, or will be, destroyed. + * + * If the mutex has never been configured, we're done. + */ + if (!MUTEX_ON(env) || *indxp == MUTEX_INVALID) + return (0); + + return (__mutex_free_int(env, 1, indxp)); +} + +/* + * __mutex_free_int -- + * Internal routine to free a mutex. + * + * PUBLIC: int __mutex_free_int __P((ENV *, int, db_mutex_t *)); + */ +int +__mutex_free_int(env, locksys, indxp) + ENV *env; + int locksys; + db_mutex_t *indxp; +{ + DB_MUTEX *mutexp; + DB_MUTEXMGR *mtxmgr; + DB_MUTEXREGION *mtxregion; + db_mutex_t mutex; + int ret; + + mutex = *indxp; + *indxp = MUTEX_INVALID; + + mtxmgr = env->mutex_handle; + mtxregion = mtxmgr->reginfo.primary; + mutexp = MUTEXP_SET(env, mutex); + + DB_ASSERT(env, F_ISSET(mutexp, DB_MUTEX_ALLOCATED)); + F_CLR(mutexp, DB_MUTEX_ALLOCATED); + + ret = __mutex_destroy(env, mutex); + + if (locksys) + MUTEX_SYSTEM_LOCK(env); + + /* Link the mutex on the head of the free list. */ + mutexp->mutex_next_link = mtxregion->mutex_next; + mtxregion->mutex_next = mutex; + ++mtxregion->stat.st_mutex_free; + --mtxregion->stat.st_mutex_inuse; + + if (locksys) + MUTEX_SYSTEM_UNLOCK(env); + + return (ret); +} + +/* + * __mutex_refresh -- + * Reinitialize a mutex, if we are not sure of its state. + * + * PUBLIC: int __mutex_refresh __P((ENV *, db_mutex_t)); + */ +int +__mutex_refresh(env, mutex) + ENV *env; + db_mutex_t mutex; +{ + DB_MUTEX *mutexp; + u_int32_t flags; + int ret; + + mutexp = MUTEXP_SET(env, mutex); + flags = mutexp->flags; + if ((ret = __mutex_destroy(env, mutex)) == 0) { + memset(mutexp, 0, sizeof(*mutexp)); + F_SET(mutexp, DB_MUTEX_ALLOCATED | + LF_ISSET(DB_MUTEX_LOGICAL_LOCK | + DB_MUTEX_PROCESS_ONLY | DB_MUTEX_SHARED)); + LF_CLR(DB_MUTEX_LOCKED); + ret = __mutex_init(env, mutex, flags); + } + return (ret); +} diff -r 000000000000 -r a1985f14b030 src/mutex/mut_method.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/mutex/mut_method.c Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,504 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 1996, 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + * $Id$ + */ + +#include "db_config.h" + +#include "db_int.h" + +/* + * __mutex_alloc_pp -- + * Allocate a mutex, application method. + * + * PUBLIC: int __mutex_alloc_pp __P((DB_ENV *, u_int32_t, db_mutex_t *)); + */ +int +__mutex_alloc_pp(dbenv, flags, indxp) + DB_ENV *dbenv; + u_int32_t flags; + db_mutex_t *indxp; +{ + DB_THREAD_INFO *ip; + ENV *env; + int ret; + + env = dbenv->env; + + if ((ret = __db_fchk(env, "DB_ENV->mutex_alloc", + flags, DB_MUTEX_PROCESS_ONLY | DB_MUTEX_SELF_BLOCK)) != 0) + return (ret); + + ENV_ENTER(env, ip); + ret = __mutex_alloc(env, MTX_APPLICATION, flags, indxp); + ENV_LEAVE(env, ip); + + return (ret); +} + +/* + * __mutex_free_pp -- + * Destroy a mutex, application method. + * + * PUBLIC: int __mutex_free_pp __P((DB_ENV *, db_mutex_t)); + */ +int +__mutex_free_pp(dbenv, indx) + DB_ENV *dbenv; + db_mutex_t indx; +{ + DB_THREAD_INFO *ip; + ENV *env; + int ret; + + env = dbenv->env; + + if (indx == MUTEX_INVALID) + return (EINVAL); + + /* + * Internally Berkeley DB passes around the db_mutex_t address on + * free, because we want to make absolutely sure the slot gets + * overwritten with MUTEX_INVALID. We don't export MUTEX_INVALID, + * so we don't export that part of the API, either. + */ + ENV_ENTER(env, ip); + ret = __mutex_free(env, &indx); + ENV_LEAVE(env, ip); + + return (ret); +} + +/* + * __mutex_lock -- + * Lock a mutex, application method. + * + * PUBLIC: int __mutex_lock_pp __P((DB_ENV *, db_mutex_t)); + */ +int +__mutex_lock_pp(dbenv, indx) + DB_ENV *dbenv; + db_mutex_t indx; +{ + DB_THREAD_INFO *ip; + ENV *env; + int ret; + + env = dbenv->env; + + if (indx == MUTEX_INVALID) + return (EINVAL); + + ENV_ENTER(env, ip); + ret = __mutex_lock(env, indx); + ENV_LEAVE(env, ip); + return (ret); +} + +/* + * __mutex_unlock -- + * Unlock a mutex, application method. + * + * PUBLIC: int __mutex_unlock_pp __P((DB_ENV *, db_mutex_t)); + */ +int +__mutex_unlock_pp(dbenv, indx) + DB_ENV *dbenv; + db_mutex_t indx; +{ + DB_THREAD_INFO *ip; + ENV *env; + int ret; + + env = dbenv->env; + + if (indx == MUTEX_INVALID) + return (EINVAL); + + ENV_ENTER(env, ip); + ret = __mutex_unlock(env, indx); + ENV_LEAVE(env, ip); + return (ret); +} + +/* + * __mutex_get_align -- + * DB_ENV->mutex_get_align. + * + * PUBLIC: int __mutex_get_align __P((DB_ENV *, u_int32_t *)); + */ +int +__mutex_get_align(dbenv, alignp) + DB_ENV *dbenv; + u_int32_t *alignp; +{ + ENV *env; + + env = dbenv->env; + + if (MUTEX_ON(env)) { + /* Cannot be set after open, no lock required to read. */ + *alignp = ((DB_MUTEXREGION *) + env->mutex_handle->reginfo.primary)->stat.st_mutex_align; + } else + *alignp = dbenv->mutex_align; + return (0); +} + +/* + * __mutex_set_align -- + * DB_ENV->mutex_set_align. + * + * PUBLIC: int __mutex_set_align __P((DB_ENV *, u_int32_t)); + */ +int +__mutex_set_align(dbenv, align) + DB_ENV *dbenv; + u_int32_t align; +{ + ENV *env; + + env = dbenv->env; + + ENV_ILLEGAL_AFTER_OPEN(env, "DB_ENV->set_mutex_align"); + + if (align == 0 || !POWER_OF_TWO(align)) { + __db_errx(env, DB_STR("2018", +"DB_ENV->mutex_set_align: alignment value must be a non-zero power-of-two")); + return (EINVAL); + } + + dbenv->mutex_align = align; + return (0); +} + +/* + * __mutex_get_increment -- + * DB_ENV->mutex_get_increment. + * + * PUBLIC: int __mutex_get_increment __P((DB_ENV *, u_int32_t *)); + */ +int +__mutex_get_increment(dbenv, incrementp) + DB_ENV *dbenv; + u_int32_t *incrementp; +{ + /* + * We don't maintain the increment in the region (it just makes + * no sense). Return whatever we have configured on this handle, + * nobody is ever going to notice. + */ + *incrementp = dbenv->mutex_inc; + return (0); +} + +/* + * __mutex_set_increment -- + * DB_ENV->mutex_set_increment. + * + * PUBLIC: int __mutex_set_increment __P((DB_ENV *, u_int32_t)); + */ +int +__mutex_set_increment(dbenv, increment) + DB_ENV *dbenv; + u_int32_t increment; +{ + ENV *env; + + env = dbenv->env; + + ENV_ILLEGAL_AFTER_OPEN(env, "DB_ENV->set_mutex_increment"); + + dbenv->mutex_cnt = 0; + dbenv->mutex_inc = increment; + return (0); +} + +/* + * __mutex_get_init -- + * DB_ENV->mutex_get_init. + * + * PUBLIC: int __mutex_get_init __P((DB_ENV *, u_int32_t *)); + */ +int +__mutex_get_init(dbenv, initp) + DB_ENV *dbenv; + u_int32_t *initp; +{ + ENV *env; + + env = dbenv->env; + + if (MUTEX_ON(env)) { + /* Cannot be set after open, no lock required to read. */ + *initp = ((DB_MUTEXREGION *) + env->mutex_handle->reginfo.primary)->stat.st_mutex_init; + } else + *initp = dbenv->mutex_cnt; + return (0); +} + +/* + * __mutex_set_init -- + * DB_ENV->mutex_set_init. + * + * PUBLIC: int __mutex_set_init __P((DB_ENV *, u_int32_t)); + */ +int +__mutex_set_init(dbenv, init) + DB_ENV *dbenv; + u_int32_t init; +{ + ENV *env; + + env = dbenv->env; + + ENV_ILLEGAL_AFTER_OPEN(env, "DB_ENV->set_mutex_init"); + + dbenv->mutex_cnt = init; + dbenv->mutex_inc = 0; + return (0); +} + +/* + * __mutex_get_max -- + * DB_ENV->mutex_get_max. + * + * PUBLIC: int __mutex_get_max __P((DB_ENV *, u_int32_t *)); + */ +int +__mutex_get_max(dbenv, maxp) + DB_ENV *dbenv; + u_int32_t *maxp; +{ + ENV *env; + + env = dbenv->env; + + if (MUTEX_ON(env)) { + /* Cannot be set after open, no lock required to read. */ + *maxp = ((DB_MUTEXREGION *) + env->mutex_handle->reginfo.primary)->stat.st_mutex_max; + } else + *maxp = dbenv->mutex_max; + return (0); +} + +/* + * __mutex_set_max -- + * DB_ENV->mutex_set_max. + * + * PUBLIC: int __mutex_set_max __P((DB_ENV *, u_int32_t)); + */ +int +__mutex_set_max(dbenv, max) + DB_ENV *dbenv; + u_int32_t max; +{ + ENV *env; + + env = dbenv->env; + + ENV_ILLEGAL_AFTER_OPEN(env, "DB_ENV->set_mutex_max"); + + dbenv->mutex_max = max; + dbenv->mutex_inc = 0; + return (0); +} + +/* + * __mutex_get_tas_spins -- + * DB_ENV->mutex_get_tas_spins. + * + * PUBLIC: int __mutex_get_tas_spins __P((DB_ENV *, u_int32_t *)); + */ +int +__mutex_get_tas_spins(dbenv, tas_spinsp) + DB_ENV *dbenv; + u_int32_t *tas_spinsp; +{ + ENV *env; + + env = dbenv->env; + + if (MUTEX_ON(env)) { + /* Cannot be set after open, no lock required to read. */ + *tas_spinsp = ((DB_MUTEXREGION *)env-> + mutex_handle->reginfo.primary)->stat.st_mutex_tas_spins; + } else + *tas_spinsp = dbenv->mutex_tas_spins; + return (0); +} + +/* + * __mutex_set_tas_spins -- + * DB_ENV->mutex_set_tas_spins. + * + * PUBLIC: int __mutex_set_tas_spins __P((DB_ENV *, u_int32_t)); + */ +int +__mutex_set_tas_spins(dbenv, tas_spins) + DB_ENV *dbenv; + u_int32_t tas_spins; +{ + ENV *env; + + env = dbenv->env; + + /* + * Bound the value -- less than 1 makes no sense, greater than 1M + * makes no sense. + */ + if (tas_spins == 0) + tas_spins = 1; + else if (tas_spins > 1000000) + tas_spins = 1000000; + + /* + * There's a theoretical race here, but I'm not interested in locking + * the test-and-set spin count. The worst possibility is a thread + * reads out a bad spin count and spins until it gets the lock, but + * that's awfully unlikely. + */ + if (MUTEX_ON(env)) + ((DB_MUTEXREGION *)env->mutex_handle + ->reginfo.primary)->stat.st_mutex_tas_spins = tas_spins; + else + dbenv->mutex_tas_spins = tas_spins; + return (0); +} + +#if !defined(HAVE_ATOMIC_SUPPORT) && defined(HAVE_MUTEX_SUPPORT) +/* + * Provide atomic operations for platforms which have mutexes yet do not have + * native atomic operations configured. They are emulated by protected the + * operation with a mutex. The address of the atomic value selects which + * mutex to use. + */ +/* + * atomic_get_mutex - + * Map an address to the mutex to use to atomically modify it + */ +static inline db_mutex_t atomic_get_mutex(env, v) + ENV *env; + db_atomic_t *v; +{ + u_int index; + DB_MUTEXREGION *mtxreg; + + if (!MUTEX_ON(env)) + return (MUTEX_INVALID); + index = (u_int)(((uintptr_t) (v)) >> 6) % MAX_ATOMIC_MUTEXES; + mtxreg = (DB_MUTEXREGION *)env->mutex_handle->reginfo.primary; + return (mtxreg->mtx_atomic[index]); +} + +/* + * __atomic_inc + * Use a mutex to provide an atomic increment function + * + * PUBLIC: #if !defined(HAVE_ATOMIC_SUPPORT) && defined(HAVE_MUTEX_SUPPORT) + * PUBLIC: atomic_value_t __atomic_inc __P((ENV *, db_atomic_t *)); + * PUBLIC: #endif + */ +atomic_value_t +__atomic_inc(env, v) + ENV *env; + db_atomic_t *v; +{ + db_mutex_t mtx; + int ret; + + mtx = atomic_get_mutex(env, v); + MUTEX_LOCK(env, mtx); + ret = ++v->value; + MUTEX_UNLOCK(env, mtx); + + return (ret); +} + +/* + * __atomic_dec + * Use a mutex to provide an atomic decrement function + * + * PUBLIC: #if !defined(HAVE_ATOMIC_SUPPORT) && defined(HAVE_MUTEX_SUPPORT) + * PUBLIC: atomic_value_t __atomic_dec __P((ENV *, db_atomic_t *)); + * PUBLIC: #endif + */ +atomic_value_t +__atomic_dec(env, v) + ENV *env; + db_atomic_t *v; +{ + db_mutex_t mtx; + int ret; + + mtx = atomic_get_mutex(env, v); + MUTEX_LOCK(env, mtx); + ret = --v->value; + MUTEX_UNLOCK(env, mtx); + + return (ret); +} + +/* + * atomic_compare_exchange + * Use a mutex to provide an atomic decrement function + * + * PUBLIC: #if !defined(HAVE_ATOMIC_SUPPORT) && defined(HAVE_MUTEX_SUPPORT) + * PUBLIC: int atomic_compare_exchange + * PUBLIC: __P((ENV *, db_atomic_t *, atomic_value_t, atomic_value_t)); + * PUBLIC: #endif + * Returns 1 if the *v was equal to oldval, else 0 + * + * Side Effect: + * Sets the value to newval if and only if returning 1 + */ +int +atomic_compare_exchange(env, v, oldval, newval) + ENV *env; + db_atomic_t *v; + atomic_value_t oldval; + atomic_value_t newval; +{ + db_mutex_t mtx; + int ret; + + if (atomic_read(v) != oldval) + return (0); + + mtx = atomic_get_mutex(env, v); + MUTEX_LOCK(env, mtx); + ret = atomic_read(v) == oldval; + if (ret) + atomic_init(v, newval); + MUTEX_UNLOCK(env, mtx); + + return (ret); +} +#endif diff -r 000000000000 -r a1985f14b030 src/mutex/mut_pthread.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/mutex/mut_pthread.c Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,792 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 1999, 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + * $Id$ + */ + +#include "db_config.h" + +#include "db_int.h" +#include "dbinc/lock.h" + +/* + * This is where we load in architecture/compiler specific mutex code. + */ +#define LOAD_ACTUAL_MUTEX_CODE + +#ifdef HAVE_MUTEX_SOLARIS_LWP +#define pthread_cond_destroy(x) 0 +#define pthread_cond_signal _lwp_cond_signal +#define pthread_cond_broadcast _lwp_cond_broadcast +#define pthread_cond_wait _lwp_cond_wait +#define pthread_mutex_destroy(x) 0 +#define pthread_mutex_lock _lwp_mutex_lock +#define pthread_mutex_trylock _lwp_mutex_trylock +#define pthread_mutex_unlock _lwp_mutex_unlock +#endif +#ifdef HAVE_MUTEX_UI_THREADS +#define pthread_cond_destroy(x) cond_destroy +#define pthread_cond_broadcast cond_broadcast +#define pthread_cond_wait cond_wait +#define pthread_mutex_destroy mutex_destroy +#define pthread_mutex_lock mutex_lock +#define pthread_mutex_trylock mutex_trylock +#define pthread_mutex_unlock mutex_unlock +#endif + +/* + * According to HP-UX engineers contacted by Netscape, + * pthread_mutex_unlock() will occasionally return EFAULT for no good reason + * on mutexes in shared memory regions, and the correct caller behavior + * is to try again. Do so, up to EFAULT_RETRY_ATTEMPTS consecutive times. + * Note that we don't bother to restrict this to HP-UX; + * it should be harmless elsewhere. [#2471] + */ +#define EFAULT_RETRY_ATTEMPTS 5 +#define RETRY_ON_EFAULT(func_invocation, ret) do { \ + int i; \ + i = EFAULT_RETRY_ATTEMPTS; \ + do { \ + RET_SET((func_invocation), ret); \ + } while (ret == EFAULT && --i > 0); \ +} while (0) + +/* + * IBM's MVS pthread mutex implementation returns -1 and sets errno rather than + * returning errno itself. As -1 is not a valid errno value, assume functions + * returning -1 have set errno. If they haven't, return a random error value. + */ +#define RET_SET(f, ret) do { \ + if (((ret) = (f)) == -1 && ((ret) = errno) == 0) \ + (ret) = EAGAIN; \ +} while (0) + +/* + * __db_pthread_mutex_init -- + * Initialize a pthread mutex: either a native one or + * just the mutex for block/wakeup of a hybrid test-and-set mutex + * + * + * PUBLIC: int __db_pthread_mutex_init __P((ENV *, db_mutex_t, u_int32_t)); + */ +int +__db_pthread_mutex_init(env, mutex, flags) + ENV *env; + db_mutex_t mutex; + u_int32_t flags; +{ + DB_MUTEX *mutexp; + int ret; + + mutexp = MUTEXP_SET(env, mutex); + ret = 0; + +#ifndef HAVE_MUTEX_HYBRID + /* Can't have self-blocking shared latches. */ + DB_ASSERT(env, !LF_ISSET(DB_MUTEX_SELF_BLOCK) || + !LF_ISSET(DB_MUTEX_SHARED)); +#endif + +#ifdef HAVE_MUTEX_PTHREADS + { +#ifndef HAVE_MUTEX_THREAD_ONLY + pthread_condattr_t condattr; + pthread_mutexattr_t mutexattr; +#endif + pthread_condattr_t *condattrp = NULL; + pthread_mutexattr_t *mutexattrp = NULL; + +#ifndef HAVE_MUTEX_HYBRID + if (LF_ISSET(DB_MUTEX_SHARED)) { +#if defined(HAVE_SHARED_LATCHES) + pthread_rwlockattr_t rwlockattr, *rwlockattrp = NULL; +#ifndef HAVE_MUTEX_THREAD_ONLY + if (!LF_ISSET(DB_MUTEX_PROCESS_ONLY)) { + RET_SET((pthread_rwlockattr_init(&rwlockattr)), ret); + if (ret != 0) + goto err; + RET_SET((pthread_rwlockattr_setpshared( + &rwlockattr, PTHREAD_PROCESS_SHARED)), ret); + rwlockattrp = &rwlockattr; + } +#endif + + if (ret == 0) + RET_SET((pthread_rwlock_init(&mutexp->u.rwlock, + rwlockattrp)), ret); + if (rwlockattrp != NULL) + (void)pthread_rwlockattr_destroy(rwlockattrp); + + F_SET(mutexp, DB_MUTEX_SHARED); + /* For rwlocks, we're done - cannot use the mutex or cond */ + goto err; +#endif + } +#endif +#ifndef HAVE_MUTEX_THREAD_ONLY + if (!LF_ISSET(DB_MUTEX_PROCESS_ONLY)) { + RET_SET((pthread_mutexattr_init(&mutexattr)), ret); + if (ret != 0) + goto err; + RET_SET((pthread_mutexattr_setpshared( + &mutexattr, PTHREAD_PROCESS_SHARED)), ret); + mutexattrp = &mutexattr; + } +#endif + + if (ret == 0) + RET_SET( + (pthread_mutex_init(&mutexp->u.m.mutex, mutexattrp)), ret); + + if (mutexattrp != NULL) + (void)pthread_mutexattr_destroy(mutexattrp); + if (ret != 0) + goto err; + if (LF_ISSET(DB_MUTEX_SELF_BLOCK)) { +#ifndef HAVE_MUTEX_THREAD_ONLY + if (!LF_ISSET(DB_MUTEX_PROCESS_ONLY)) { + RET_SET((pthread_condattr_init(&condattr)), ret); + if (ret != 0) + goto err; + + condattrp = &condattr; + RET_SET((pthread_condattr_setpshared( + &condattr, PTHREAD_PROCESS_SHARED)), ret); + } +#endif + + if (ret == 0) + RET_SET((pthread_cond_init( + &mutexp->u.m.cond, condattrp)), ret); + + F_SET(mutexp, DB_MUTEX_SELF_BLOCK); + if (condattrp != NULL) + (void)pthread_condattr_destroy(condattrp); + } + + } +#endif +#ifdef HAVE_MUTEX_SOLARIS_LWP + /* + * XXX + * Gcc complains about missing braces in the static initializations of + * lwp_cond_t and lwp_mutex_t structures because the structures contain + * sub-structures/unions and the Solaris include file that defines the + * initialization values doesn't have surrounding braces. There's not + * much we can do. + */ + if (LF_ISSET(DB_MUTEX_PROCESS_ONLY)) { + static lwp_mutex_t mi = DEFAULTMUTEX; + + mutexp->mutex = mi; + } else { + static lwp_mutex_t mi = SHAREDMUTEX; + + mutexp->mutex = mi; + } + if (LF_ISSET(DB_MUTEX_SELF_BLOCK)) { + if (LF_ISSET(DB_MUTEX_PROCESS_ONLY)) { + static lwp_cond_t ci = DEFAULTCV; + + mutexp->cond = ci; + } else { + static lwp_cond_t ci = SHAREDCV; + + mutexp->cond = ci; + } + F_SET(mutexp, DB_MUTEX_SELF_BLOCK); + } +#endif +#ifdef HAVE_MUTEX_UI_THREADS + { + int type; + + type = LF_ISSET(DB_MUTEX_PROCESS_ONLY) ? USYNC_THREAD : USYNC_PROCESS; + + ret = mutex_init(&mutexp->mutex, type, NULL); + if (ret == 0 && LF_ISSET(DB_MUTEX_SELF_BLOCK)) { + ret = cond_init(&mutexp->cond, type, NULL); + + F_SET(mutexp, DB_MUTEX_SELF_BLOCK); + }} +#endif + +err: if (ret != 0) { + __db_err(env, ret, DB_STR("2021", + "unable to initialize mutex")); + } + return (ret); +} + +/* + * __db_pthread_mutex_prep + * Prepare to use a pthread-based DB_MUTEX. + * + * This exclusively locks a DB_MUTEX's pthread_mutex_t or pthread_rwlock_t, + * before locking, unlocking, or waiting for the DB mutex to be become + * available in the requested mode (exclusive == 1, shared == 0). + * + * Test for failchk concerns here too, to avoid hanging on a dead pid/tid. + */ +inline static int +__db_pthread_mutex_prep(env, mutex, mutexp, exclusive) + ENV *env; + db_mutex_t mutex; + DB_MUTEX *mutexp; + int exclusive; +{ + DB_ENV *dbenv; + DB_THREAD_INFO *ip; + int ret; + + dbenv = env->dbenv; + PERFMON4(env, + mutex, suspend, mutex, exclusive, mutexp->alloc_id, mutexp); + if (F_ISSET(dbenv, DB_ENV_FAILCHK)) { + for (;;) { + RET_SET_PTHREAD_TRYLOCK(mutexp, ret); + if (ret != EBUSY) + break; + if (dbenv->is_alive(dbenv, + mutexp->pid, mutexp->tid, 0) == 0) { + ret = __env_set_state(env, &ip, THREAD_VERIFY); + if (ret != 0 || + ip->dbth_state == THREAD_FAILCHK) { + ret = DB_RUNRECOVERY; + } else { + /* + * Some thread other than the true + * FAILCHK thread in this process is + * asking for the mutex held by the + * dead process/thread. We will block + * here until someone else does the + * cleanup. Same behavior as if we + * hadn't gone down the 'if + * DB_ENV_FAILCHK' path to start with. + */ + RET_SET_PTHREAD_LOCK(mutexp, ret); + break; + } + } + } + } else + RET_SET_PTHREAD_LOCK(mutexp, ret); + + PERFMON4(env, + mutex, resume, mutex, exclusive, mutexp->alloc_id, mutexp); + COMPQUIET(mutex, 0); + COMPQUIET(exclusive, 0); + return (ret); +} + +/* + * __db_pthread_mutex_condwait + * Perform a pthread condition wait for a DB_MUTEX. + * + * This will be a timed wait when a timespec has been specified. EINTR and + * spurious ETIME* values are mapped to 0, and hence success. The + * mutexp->u.m.mutex must be locked upon entry. When returning a success + * or timeout status it will have been locked again. + * + * Returns: + * 0 if it is safe to retry to get the mutex + * DB_TIMEOUT if the timeout exceeded + * a fatal error. The mutexp->u.m.mutex has been unlocked. + */ +inline static int +__db_pthread_mutex_condwait(env, mutex, mutexp, timespec) + ENV *env; + db_mutex_t mutex; + DB_MUTEX *mutexp; + db_timespec *timespec; +{ + int ret; + +#ifdef MUTEX_DIAG + printf("condwait %ld %x wait busy %x count %d\n", + mutex, pthread_self(), MUTEXP_BUSY_FIELD(mutexp), mutexp->wait); +#endif + PERFMON4(env, mutex, suspend, mutex, TRUE, mutexp->alloc_id, mutexp); + + if (timespec != NULL) { + RET_SET((pthread_cond_timedwait(&mutexp->u.m.cond, + &mutexp->u.m.mutex, (struct timespec *) timespec)), ret); + if (ret == ETIMEDOUT) { + ret = DB_TIMEOUT; + goto ret; + } + } else + RET_SET((pthread_cond_wait(&mutexp->u.m.cond, + &mutexp->u.m.mutex)), ret); +#ifdef MUTEX_DIAG + printf("condwait %ld %x wait returns %d busy %x\n", + mutex, pthread_self(), ret, MUTEXP_BUSY_FIELD(mutexp)); +#endif + /* + * !!! + * Solaris bug workaround: pthread_cond_wait() sometimes returns ETIME + * -- out of sheer paranoia, check both ETIME and ETIMEDOUT. We + * believe this happens when the application uses SIGALRM for some + * purpose, e.g., the C library sleep call, and Solaris delivers the + * signal to the wrong LWP. + */ + if (ret != 0) { + if (ret == ETIMEDOUT || +#ifdef ETIME + ret == ETIME || +#endif + ret == EINTR) + ret = 0; + else + /* Failure, caller shouldn't condwait again. */ + (void)pthread_mutex_unlock(&mutexp->u.m.mutex); + } + +ret: + PERFMON4(env, mutex, resume, mutex, TRUE, mutexp->alloc_id, mutexp); + + COMPQUIET(mutex, 0); + COMPQUIET(env, 0); + return (ret); +} + +#ifndef HAVE_MUTEX_HYBRID +/* + * __db_pthread_mutex_lock + * Lock on a mutex, blocking if necessary. + * Timeouts are supported only for self-blocking mutexes. + * + * Self-blocking shared latches are not supported. + * + * PUBLIC: #ifndef HAVE_MUTEX_HYBRID + * PUBLIC: int __db_pthread_mutex_lock __P((ENV *, db_mutex_t, db_timeout_t)); + * PUBLIC: #endif + */ +int +__db_pthread_mutex_lock(env, mutex, timeout) + ENV *env; + db_mutex_t mutex; + db_timeout_t timeout; +{ + DB_ENV *dbenv; + DB_MUTEX *mutexp; + db_timespec timespec; + int ret, t_ret; + + dbenv = env->dbenv; + + if (!MUTEX_ON(env) || F_ISSET(dbenv, DB_ENV_NOLOCKING)) + return (0); + + t_ret = 0; + mutexp = MUTEXP_SET(env, mutex); + + CHECK_MTX_THREAD(env, mutexp); + +#if defined(HAVE_STATISTICS) + /* + * We want to know which mutexes are contentious, but don't want to + * do an interlocked test here -- that's slower when the underlying + * system has adaptive mutexes and can perform optimizations like + * spinning only if the thread holding the mutex is actually running + * on a CPU. Make a guess, using a normal load instruction. + */ + if (F_ISSET(mutexp, DB_MUTEX_LOCKED)) + STAT_INC(env, mutex, set_wait, mutexp->mutex_set_wait, mutex); + else + STAT_INC(env, + mutex, set_nowait, mutexp->mutex_set_nowait, mutex); +#endif + + /* Single-thread the next block, except during the possible condwait. */ + if ((ret = __db_pthread_mutex_prep(env, mutex, mutexp, TRUE)) != 0) + goto err; + + if (F_ISSET(mutexp, DB_MUTEX_SELF_BLOCK)) { + if (timeout != 0) + timespecclear(×pec); + while (MUTEXP_IS_BUSY(mutexp)) { + /* Set expiration timer upon first need. */ + if (timeout != 0 && !timespecisset(×pec)) { + timespecclear(×pec); + __clock_set_expires(env, ×pec, timeout); + } + t_ret = __db_pthread_mutex_condwait(env, + mutex, mutexp, timeout == 0 ? NULL : ×pec); + if (t_ret != 0) { + if (t_ret == DB_TIMEOUT) + goto out; + ret = t_ret; + goto err; + } + } + + F_SET(mutexp, DB_MUTEX_LOCKED); + dbenv->thread_id(dbenv, &mutexp->pid, &mutexp->tid); +out: + /* #2471: HP-UX can sporadically return EFAULT. See above */ + RETRY_ON_EFAULT(pthread_mutex_unlock(&mutexp->u.m.mutex), ret); + if (ret != 0) + goto err; + } else { +#ifdef DIAGNOSTIC + if (F_ISSET(mutexp, DB_MUTEX_LOCKED)) { + char buf[DB_THREADID_STRLEN]; + (void)dbenv->thread_id_string(dbenv, + mutexp->pid, mutexp->tid, buf); + __db_errx(env, DB_STR_A("2022", + "pthread lock failed: lock currently in use: pid/tid: %s", + "%s"), buf); + ret = EINVAL; + goto err; + } +#endif + F_SET(mutexp, DB_MUTEX_LOCKED); + dbenv->thread_id(dbenv, &mutexp->pid, &mutexp->tid); + } + +#ifdef DIAGNOSTIC + /* + * We want to switch threads as often as possible. Yield every time + * we get a mutex to ensure contention. + */ + if (F_ISSET(dbenv, DB_ENV_YIELDCPU)) + __os_yield(env, 0, 0); +#endif + return (t_ret); + +err: + __db_err(env, ret, DB_STR("2023", "pthread lock failed")); + return (__env_panic(env, ret)); +} +#endif + +#if defined(HAVE_SHARED_LATCHES) && !defined(HAVE_MUTEX_HYBRID) +/* + * __db_pthread_mutex_readlock + * Take a shared lock on a mutex, blocking if necessary. + * + * PUBLIC: #if defined(HAVE_SHARED_LATCHES) + * PUBLIC: int __db_pthread_mutex_readlock __P((ENV *, db_mutex_t)); + * PUBLIC: #endif + */ +int +__db_pthread_mutex_readlock(env, mutex) + ENV *env; + db_mutex_t mutex; +{ + DB_ENV *dbenv; + DB_MUTEX *mutexp; + int ret; + + dbenv = env->dbenv; + + if (!MUTEX_ON(env) || F_ISSET(dbenv, DB_ENV_NOLOCKING)) + return (0); + + mutexp = MUTEXP_SET(env, mutex); + DB_ASSERT(env, F_ISSET(mutexp, DB_MUTEX_SHARED)); + + CHECK_MTX_THREAD(env, mutexp); + +#if defined(HAVE_STATISTICS) + /* + * We want to know which mutexes are contentious, but don't want to + * do an interlocked test here -- that's slower when the underlying + * system has adaptive mutexes and can perform optimizations like + * spinning only if the thread holding the mutex is actually running + * on a CPU. Make a guess, using a normal load instruction. + */ + if (F_ISSET(mutexp, DB_MUTEX_LOCKED)) + STAT_INC(env, + mutex, set_rd_wait, mutexp->mutex_set_rd_wait, mutex); + else + STAT_INC(env, + mutex, set_rd_nowait, mutexp->mutex_set_rd_nowait, mutex); +#endif + + PERFMON4(env, mutex, suspend, mutex, FALSE, mutexp->alloc_id, mutexp); + RET_SET((pthread_rwlock_rdlock(&mutexp->u.rwlock)), ret); + PERFMON4(env, mutex, resume, mutex, FALSE, mutexp->alloc_id, mutexp); + DB_ASSERT(env, !F_ISSET(mutexp, DB_MUTEX_LOCKED)); + if (ret != 0) + goto err; + +#ifdef DIAGNOSTIC + /* + * We want to switch threads as often as possible. Yield every time + * we get a mutex to ensure contention. + */ + if (F_ISSET(dbenv, DB_ENV_YIELDCPU)) + __os_yield(env, 0, 0); +#endif + return (0); + +err: __db_err(env, ret, DB_STR("2024", "pthread readlock failed")); + return (__env_panic(env, ret)); +} +#endif + +#ifdef HAVE_MUTEX_HYBRID +/* + * __db_hybrid_mutex_suspend + * Suspend this thread until the mutex is free enough to give the caller a + * good chance of getting the mutex in the requested exclusivity mode. + * + * The major difference between this and the old __db_pthread_mutex_lock() + * is the additional 'exclusive' parameter. + * + * PUBLIC: #ifdef HAVE_MUTEX_HYBRID + * PUBLIC: int __db_hybrid_mutex_suspend + * PUBLIC: __P((ENV *, db_mutex_t, db_timespec *, int)); + * PUBLIC: #endif + */ +int +__db_hybrid_mutex_suspend(env, mutex, timespec, exclusive) + ENV *env; + db_mutex_t mutex; + db_timespec *timespec; + int exclusive; +{ + DB_MUTEX *mutexp; + int ret, t_ret; + + t_ret = 0; + mutexp = MUTEXP_SET(env, mutex); + + if (!exclusive) + DB_ASSERT(env, F_ISSET(mutexp, DB_MUTEX_SHARED)); + DB_ASSERT(env, F_ISSET(mutexp, DB_MUTEX_SELF_BLOCK)); + + if ((ret = __db_pthread_mutex_prep(env, mutex, mutexp, exclusive)) != 0) + goto err; + + /* + * Since this is only for hybrid mutexes the pthread mutex + * is only used to wait after spinning on the TAS mutex. + * Set the wait flag before checking to see if the mutex + * is still locked. The holder will clear DB_MUTEX_LOCKED + * before checking the wait counter. + */ + mutexp->wait++; + MUTEX_MEMBAR(mutexp->wait); + while (exclusive ? MUTEXP_IS_BUSY(mutexp) : + atomic_read(&mutexp->sharecount) == MUTEX_SHARE_ISEXCLUSIVE) { + t_ret = __db_pthread_mutex_condwait(env, + mutex, mutexp, timespec); + if (t_ret != 0) { + if (t_ret == DB_TIMEOUT) + break; + ret = t_ret; + goto err; + } + MUTEX_MEMBAR(mutexp->flags); + } + + mutexp->wait--; + + /* #2471: HP-UX can sporadically return EFAULT. See above */ + RETRY_ON_EFAULT(pthread_mutex_unlock(&mutexp->u.m.mutex), ret); + if (ret != 0) + goto err; + + PERFMON4(env, + mutex, resume, mutex, exclusive, mutexp->alloc_id, mutexp); + +#ifdef DIAGNOSTIC + /* + * We want to switch threads as often as possible. Yield every time + * we get a mutex to ensure contention. + */ + if (F_ISSET(env->dbenv, DB_ENV_YIELDCPU)) + __os_yield(env, 0, 0); +#endif + return (t_ret); + +err: + PERFMON4(env, + mutex, resume, mutex, exclusive, mutexp->alloc_id, mutexp); + __db_err(env, ret, "pthread suspend failed"); + return (__env_panic(env, ret)); +} +#endif + +/* + * __db_pthread_mutex_unlock -- + * Release a mutex, or, if hybrid, wake a thread up from a suspend. + * + * PUBLIC: int __db_pthread_mutex_unlock __P((ENV *, db_mutex_t)); + */ +int +__db_pthread_mutex_unlock(env, mutex) + ENV *env; + db_mutex_t mutex; +{ + DB_ENV *dbenv; + DB_MUTEX *mutexp; + int ret; +#if defined(MUTEX_DIAG) && defined(HAVE_MUTEX_HYBRID) + int waiters; +#endif + + dbenv = env->dbenv; + + if (!MUTEX_ON(env) || F_ISSET(dbenv, DB_ENV_NOLOCKING)) + return (0); + + mutexp = MUTEXP_SET(env, mutex); +#if defined(MUTEX_DIAG) && defined(HAVE_MUTEX_HYBRID) + waiters = mutexp->wait; +#endif + +#if !defined(HAVE_MUTEX_HYBRID) && defined(DIAGNOSTIC) + if (!F_ISSET(mutexp, DB_MUTEX_LOCKED | DB_MUTEX_SHARED)) { + __db_errx(env, DB_STR("2025", + "pthread unlock failed: lock already unlocked")); + return (__env_panic(env, EACCES)); + } +#endif + if (F_ISSET(mutexp, DB_MUTEX_SELF_BLOCK)) { + ret = __db_pthread_mutex_prep(env, mutex, mutexp, TRUE); + if (ret != 0) + goto err; + +#ifdef HAVE_MUTEX_HYBRID + STAT_INC(env, + mutex, hybrid_wakeup, mutexp->hybrid_wakeup, mutex); +#else + F_CLR(mutexp, DB_MUTEX_LOCKED); /* nop if DB_MUTEX_SHARED */ +#endif + + if (F_ISSET(mutexp, DB_MUTEX_SHARED)) + RET_SET( + (pthread_cond_broadcast(&mutexp->u.m.cond)), ret); + else + RET_SET((pthread_cond_signal(&mutexp->u.m.cond)), ret); + if (ret != 0) + goto err; + } else { +#ifndef HAVE_MUTEX_HYBRID + F_CLR(mutexp, DB_MUTEX_LOCKED); +#endif + } + + /* See comment above; workaround for [#2471]. */ +#if defined(HAVE_SHARED_LATCHES) && !defined(HAVE_MUTEX_HYBRID) + if (F_ISSET(mutexp, DB_MUTEX_SHARED)) + RETRY_ON_EFAULT(pthread_rwlock_unlock(&mutexp->u.rwlock), ret); + else +#endif + RETRY_ON_EFAULT(pthread_mutex_unlock(&mutexp->u.m.mutex), ret); + +err: if (ret != 0) { + __db_err(env, ret, "pthread unlock failed"); + return (__env_panic(env, ret)); + } +#if defined(MUTEX_DIAG) && defined(HAVE_MUTEX_HYBRID) + if (!MUTEXP_IS_BUSY(mutexp) && mutexp->wait != 0) + printf("unlock %ld %x busy %x waiters %d/%d\n", + mutex, pthread_self(), ret, + MUTEXP_BUSY_FIELD(mutexp), waiters, mutexp->wait); +#endif + return (ret); +} + +/* + * __db_pthread_mutex_destroy -- + * Destroy a mutex. + * If it is a native shared latch (not hybrid) then + * destroy only one half of the rwlock/mutex&cond union, + * depending whether it was allocated as shared + * + * PUBLIC: int __db_pthread_mutex_destroy __P((ENV *, db_mutex_t)); + */ +int +__db_pthread_mutex_destroy(env, mutex) + ENV *env; + db_mutex_t mutex; +{ + DB_MUTEX *mutexp; + DB_THREAD_INFO *ip; + int ret, t_ret, failchk_thread; + + if (!MUTEX_ON(env)) + return (0); + + mutexp = MUTEXP_SET(env, mutex); + + ret = 0; + failchk_thread = FALSE; + /* Get information to determine if we are really the failchk thread. */ + if (F_ISSET(env->dbenv, DB_ENV_FAILCHK)) { + ret = __env_set_state(env, &ip, THREAD_VERIFY); + if (ip != NULL && ip->dbth_state == THREAD_FAILCHK) + failchk_thread = TRUE; + } + +#ifndef HAVE_MUTEX_HYBRID + if (F_ISSET(mutexp, DB_MUTEX_SHARED)) { +#if defined(HAVE_SHARED_LATCHES) + /* + * If there were dead processes waiting on the condition + * we may not be able to destroy it. Let failchk thread skip + * this, unless destroy is required. + * XXX What operating system resources might this leak? + */ +#ifdef HAVE_PTHREAD_RWLOCK_REINIT_OKAY + if (!failchk_thread) +#endif + RET_SET( + (pthread_rwlock_destroy(&mutexp->u.rwlock)), ret); + /* For rwlocks, we're done - must not destroy rest of union */ + return (ret); +#endif + } +#endif + if (F_ISSET(mutexp, DB_MUTEX_SELF_BLOCK)) { + /* + * If there were dead processes waiting on the condition + * we may not be able to destroy it. Let failchk thread + * skip this, unless destroy is required. + */ +#ifdef HAVE_PTHREAD_COND_REINIT_OKAY + if (!failchk_thread) +#endif + RET_SET((pthread_cond_destroy(&mutexp->u.m.cond)), ret); + if (ret != 0) + __db_err(env, ret, DB_STR("2026", + "unable to destroy cond")); + } + RET_SET((pthread_mutex_destroy(&mutexp->u.m.mutex)), t_ret); + if (t_ret != 0 && !failchk_thread) { + __db_err(env, t_ret, DB_STR("2027", + "unable to destroy mutex")); + if (ret == 0) + ret = t_ret; + } + return (ret); +} diff -r 000000000000 -r a1985f14b030 src/mutex/mut_region.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/mutex/mut_region.c Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,490 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 1996, 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + * $Id$ + */ + +#include "db_config.h" + +#include "db_int.h" +#include "dbinc/log.h" +#include "dbinc/lock.h" +#include "dbinc/mp.h" +#include "dbinc/txn.h" + +static db_size_t __mutex_align_size __P((ENV *)); +static int __mutex_region_init __P((ENV *, DB_MUTEXMGR *)); +static size_t __mutex_region_size __P((ENV *)); +static size_t __mutex_region_max __P((ENV *)); + +/* + * __mutex_open -- + * Open a mutex region. + * + * PUBLIC: int __mutex_open __P((ENV *, int)); + */ +int +__mutex_open(env, create_ok) + ENV *env; + int create_ok; +{ + DB_ENV *dbenv; + DB_MUTEXMGR *mtxmgr; + DB_MUTEXREGION *mtxregion; + size_t size; + u_int32_t cpu_count; + int ret; +#ifndef HAVE_ATOMIC_SUPPORT + u_int i; +#endif + + dbenv = env->dbenv; + if (dbenv->mutex_max == 0 && + dbenv->mutex_cnt == 0 && dbenv->mutex_inc == 0 && + F_ISSET(env, ENV_PRIVATE | ENV_THREAD) == ENV_PRIVATE) + return (0); + + /* + * Initialize the ENV handle information if not already initialized. + * + * Align mutexes on the byte boundaries specified by the application. + */ + if (dbenv->mutex_align == 0) + dbenv->mutex_align = MUTEX_ALIGN; + if (dbenv->mutex_tas_spins == 0) { + cpu_count = __os_cpu_count(); + if ((ret = __mutex_set_tas_spins(dbenv, cpu_count == 1 ? + cpu_count : cpu_count * MUTEX_SPINS_PER_PROCESSOR)) != 0) + return (ret); + } + + /* + * If the user didn't set an absolute value on the number of mutexes + * we'll need, figure it out. We're conservative in our allocation, + * we need mutexes for DB handles, group-commit queues and other things + * applications allocate at run-time. The application may have kicked + * up our count to allocate its own mutexes, add that in. + */ + if (dbenv->mutex_cnt == 0 && + F_ISSET(env, ENV_PRIVATE | ENV_THREAD) != ENV_PRIVATE) + dbenv->mutex_cnt = + __lock_region_mutex_count(env) + + __log_region_mutex_count(env) + + __memp_region_mutex_count(env) + + __txn_region_mutex_count(env); + + if (dbenv->mutex_max != 0 && dbenv->mutex_cnt > dbenv->mutex_max) + dbenv->mutex_cnt = dbenv->mutex_max; + + /* Create/initialize the mutex manager structure. */ + if ((ret = __os_calloc(env, 1, sizeof(DB_MUTEXMGR), &mtxmgr)) != 0) + return (ret); + + /* Join/create the mutex region. */ + mtxmgr->reginfo.env = env; + mtxmgr->reginfo.type = REGION_TYPE_MUTEX; + mtxmgr->reginfo.id = INVALID_REGION_ID; + mtxmgr->reginfo.flags = REGION_JOIN_OK; + size = __mutex_region_size(env); + if (create_ok) + F_SET(&mtxmgr->reginfo, REGION_CREATE_OK); + if ((ret = __env_region_attach(env, + &mtxmgr->reginfo, size, size + __mutex_region_max(env))) != 0) + goto err; + + /* If we created the region, initialize it. */ + if (F_ISSET(&mtxmgr->reginfo, REGION_CREATE)) + if ((ret = __mutex_region_init(env, mtxmgr)) != 0) + goto err; + + /* Set the local addresses. */ + mtxregion = mtxmgr->reginfo.primary = + R_ADDR(&mtxmgr->reginfo, mtxmgr->reginfo.rp->primary); + mtxmgr->mutex_array = R_ADDR(&mtxmgr->reginfo, mtxregion->mutex_off); + + env->mutex_handle = mtxmgr; + +#ifndef HAVE_ATOMIC_SUPPORT + /* If necessary allocate the atomic emulation mutexes. */ + if (F_ISSET(&mtxmgr->reginfo, REGION_CREATE)) + for (i = 0; i != MAX_ATOMIC_MUTEXES; i++) + if ((ret = __mutex_alloc_int( + env, 0, MTX_ATOMIC_EMULATION, + 0, &mtxregion->mtx_atomic[i])) != 0) + return (ret); +#endif + + return (0); + +err: env->mutex_handle = NULL; + if (mtxmgr->reginfo.addr != NULL) + (void)__env_region_detach(env, &mtxmgr->reginfo, 0); + + __os_free(env, mtxmgr); + return (ret); +} + +/* + * __mutex_region_init -- + * Initialize a mutex region in shared memory. + */ +static int +__mutex_region_init(env, mtxmgr) + ENV *env; + DB_MUTEXMGR *mtxmgr; +{ + DB_ENV *dbenv; + DB_MUTEX *mutexp; + DB_MUTEXREGION *mtxregion; + db_mutex_t mutex; + int ret; + void *mutex_array; + + dbenv = env->dbenv; + + COMPQUIET(mutexp, NULL); + + if ((ret = __env_alloc(&mtxmgr->reginfo, + sizeof(DB_MUTEXREGION), &mtxmgr->reginfo.primary)) != 0) { + __db_errx(env, DB_STR("2013", + "Unable to allocate memory for the mutex region")); + return (ret); + } + mtxmgr->reginfo.rp->primary = + R_OFFSET(&mtxmgr->reginfo, mtxmgr->reginfo.primary); + mtxregion = mtxmgr->reginfo.primary; + memset(mtxregion, 0, sizeof(*mtxregion)); + + mtxregion->mutex_size = __mutex_align_size(env); + + mtxregion->stat.st_mutex_align = dbenv->mutex_align; + if (dbenv->mutex_cnt == 0) + dbenv->mutex_cnt = 1; + mtxregion->stat.st_mutex_init = + mtxregion->stat.st_mutex_cnt = dbenv->mutex_cnt; + mtxregion->stat.st_mutex_max = dbenv->mutex_max; + if (mtxregion->stat.st_mutex_max != 0) + mtxregion->stat.st_mutex_max += dbenv->mutex_inc; + mtxregion->stat.st_mutex_tas_spins = dbenv->mutex_tas_spins; + + /* + * Get a chunk of memory to be used for the mutexes themselves. Each + * piece of the memory must be properly aligned, and that alignment + * may be more restrictive than the memory alignment returned by the + * underlying allocation code. We already know how much memory each + * mutex in the array will take up, but we need to offset the first + * mutex in the array so the array begins properly aligned. + * + * The OOB mutex (MUTEX_INVALID) is 0. To make this work, we ignore + * the first allocated slot when we build the free list. We have to + * correct the count by 1 here, though, otherwise our counter will be + * off by 1. + */ + if ((ret = __env_alloc(&mtxmgr->reginfo, + mtxregion->stat.st_mutex_align + + (mtxregion->stat.st_mutex_cnt + 1) * mtxregion->mutex_size, + &mutex_array)) != 0) { + __db_errx(env, DB_STR("2014", + "Unable to allocate memory for mutexes from the region")); + return (ret); + } + + mtxregion->mutex_off_alloc = R_OFFSET(&mtxmgr->reginfo, mutex_array); + mutex_array = ALIGNP_INC(mutex_array, mtxregion->stat.st_mutex_align); + mtxregion->mutex_off = R_OFFSET(&mtxmgr->reginfo, mutex_array); + mtxmgr->mutex_array = mutex_array; + + /* + * Put the mutexes on a free list and clear the allocated flag. + * + * The OOB mutex (MUTEX_INVALID) is 0, skip it. + * + * The comparison is <, not <=, because we're looking ahead one + * in each link. + */ + env->mutex_handle = mtxmgr; + if (F_ISSET(env, ENV_PRIVATE)) { + mutexp = (DB_MUTEX *)mutex_array; + mutexp++; + mutexp = ALIGNP_INC(mutexp, mtxregion->stat.st_mutex_align); + mtxregion->mutex_next = (db_mutex_t)mutexp; + } else { + mtxregion->mutex_next = 1; + mutexp = MUTEXP_SET(env, 1); + } + for (mutex = 1; mutex < mtxregion->stat.st_mutex_cnt; ++mutex) { + mutexp->flags = 0; + if (F_ISSET(env, ENV_PRIVATE)) + mutexp->mutex_next_link = (db_mutex_t)(mutexp + 1); + else + mutexp->mutex_next_link = mutex + 1; + mutexp++; + mutexp = ALIGNP_INC(mutexp, mtxregion->stat.st_mutex_align); + } + mutexp->flags = 0; + mutexp->mutex_next_link = MUTEX_INVALID; + mtxregion->stat.st_mutex_free = mtxregion->stat.st_mutex_cnt; + mtxregion->stat.st_mutex_inuse = mtxregion->stat.st_mutex_inuse_max = 0; + if ((ret = __mutex_alloc(env, MTX_MUTEX_REGION, 0, &mutex)) != 0) + return (ret); + mtxmgr->reginfo.mtx_alloc = mtxregion->mtx_region = mutex; + + /* + * This is the first place we can test mutexes and we need to + * know if they're working. (They CAN fail, for example on + * SunOS, when using fcntl(2) for locking and using an + * in-memory filesystem as the database environment directory. + * But you knew that, I'm sure -- it probably wasn't worth + * mentioning.) + */ + mutex = MUTEX_INVALID; + if ((ret = + __mutex_alloc(env, MTX_MUTEX_TEST, 0, &mutex) != 0) || + (ret = __mutex_lock(env, mutex)) != 0 || + (ret = __mutex_unlock(env, mutex)) != 0 || + (ret = __mutex_trylock(env, mutex)) != 0 || + (ret = __mutex_unlock(env, mutex)) != 0 || + (ret = __mutex_free(env, &mutex)) != 0) { + __db_errx(env, DB_STR("2015", + "Unable to acquire/release a mutex; check configuration")); + return (ret); + } +#ifdef HAVE_SHARED_LATCHES + if ((ret = + __mutex_alloc(env, + MTX_MUTEX_TEST, DB_MUTEX_SHARED, &mutex) != 0) || + (ret = __mutex_lock(env, mutex)) != 0 || + (ret = __mutex_tryrdlock(env, mutex)) != DB_LOCK_NOTGRANTED || + (ret = __mutex_unlock(env, mutex)) != 0 || + (ret = __mutex_rdlock(env, mutex)) != 0 || + (ret = __mutex_rdlock(env, mutex)) != 0 || + (ret = __mutex_unlock(env, mutex)) != 0 || + (ret = __mutex_unlock(env, mutex)) != 0 || + (ret = __mutex_free(env, &mutex)) != 0) { + __db_errx(env, DB_STR("2016", + "Unable to acquire/release a shared latch; check configuration")); + return (ret); + } +#endif + + return (0); +} + +/* + * __mutex_env_refresh -- + * Clean up after the mutex region on a close or failed open. + * + * PUBLIC: int __mutex_env_refresh __P((ENV *)); + */ +int +__mutex_env_refresh(env) + ENV *env; +{ + DB_MUTEXMGR *mtxmgr; + DB_MUTEXREGION *mtxregion; + REGINFO *reginfo; + int ret; + + mtxmgr = env->mutex_handle; + reginfo = &mtxmgr->reginfo; + mtxregion = mtxmgr->reginfo.primary; + + /* + * If a private region, return the memory to the heap. Not needed for + * filesystem-backed or system shared memory regions, that memory isn't + * owned by any particular process. + */ + if (F_ISSET(env, ENV_PRIVATE)) { + reginfo->mtx_alloc = MUTEX_INVALID; + +#ifdef HAVE_MUTEX_SYSTEM_RESOURCES + /* + * If destroying the mutex region, return any system resources + * to the system. + */ + __mutex_resource_return(env, reginfo); +#endif + /* Discard the mutex array. */ + __env_alloc_free( + reginfo, R_ADDR(reginfo, mtxregion->mutex_off_alloc)); + } + + /* Detach from the region. */ + ret = __env_region_detach(env, reginfo, 0); + + __os_free(env, mtxmgr); + + env->mutex_handle = NULL; + + return (ret); +} + +/* + * __mutex_align_size -- + * Return how much memory each mutex will take up if an array of them + * are to be properly aligned, individually, within the array. + */ +static db_size_t +__mutex_align_size(env) + ENV *env; +{ + DB_ENV *dbenv; + + dbenv = env->dbenv; + + return ((db_size_t)DB_ALIGN(sizeof(DB_MUTEX), dbenv->mutex_align)); +} + +/* + * __mutex_region_size -- + * Return the amount of space needed for the mutex region. + */ +static size_t +__mutex_region_size(env) + ENV *env; +{ + DB_ENV *dbenv; + size_t s; + + dbenv = env->dbenv; + + s = sizeof(DB_MUTEXMGR) + 1024; + + /* We discard one mutex for the OOB slot. */ + s += __env_alloc_size( + (dbenv->mutex_cnt + 1) *__mutex_align_size(env)); + + return (s); +} + +/* + * __mutex_region_max -- + * Return the amount of space needed to reach the maximum size. + */ +static size_t +__mutex_region_max(env) + ENV *env; +{ + DB_ENV *dbenv; + u_int32_t max; + + dbenv = env->dbenv; + + if ((max = dbenv->mutex_max) == 0) { + if (F_ISSET(env, ENV_PRIVATE | ENV_THREAD) == ENV_PRIVATE) + max = dbenv->mutex_inc + 1; + else + max = __lock_region_mutex_max(env) + + __txn_region_mutex_max(env) + + __log_region_mutex_max(env) + + dbenv->mutex_inc + 100; + } else if (max <= dbenv->mutex_cnt) + return (0); + else + max -= dbenv->mutex_cnt; + + return ( __env_alloc_size(max * __mutex_align_size(env))); +} + +#ifdef HAVE_MUTEX_SYSTEM_RESOURCES +/* + * __mutex_resource_return + * Return any system-allocated mutex resources to the system. + * + * PUBLIC: void __mutex_resource_return __P((ENV *, REGINFO *)); + */ +void +__mutex_resource_return(env, infop) + ENV *env; + REGINFO *infop; +{ + DB_MUTEX *mutexp; + DB_MUTEXMGR *mtxmgr, mtxmgr_st; + DB_MUTEXREGION *mtxregion; + db_mutex_t i, indx; + void *orig_handle, *chunk; + uintmax_t size; + + /* + * This routine is called in two cases: when discarding the regions + * from a previous Berkeley DB run, during recovery, and two, when + * discarding regions as we shut down the database environment. + * + * Walk the list of mutexes and destroy any live ones. + * + * This is just like joining a region -- the REGINFO we're handed is + * the same as the one returned by __env_region_attach(), all we have + * to do is fill in the links. + * + * !!! + * The region may be corrupted, of course. We're safe because the + * only things we look at are things that are initialized when the + * region is created, and never modified after that. + */ + memset(&mtxmgr_st, 0, sizeof(mtxmgr_st)); + mtxmgr = &mtxmgr_st; + mtxmgr->reginfo = *infop; + mtxregion = mtxmgr->reginfo.primary = + R_ADDR(&mtxmgr->reginfo, mtxmgr->reginfo.rp->primary); + mtxmgr->mutex_array = R_ADDR(&mtxmgr->reginfo, mtxregion->mutex_off); + + /* + * This is a little strange, but the mutex_handle is what all of the + * underlying mutex routines will use to determine if they should do + * any work and to find their information. Save/restore the handle + * around the work loop. + * + * The OOB mutex (MUTEX_INVALID) is 0, skip it. + */ + orig_handle = env->mutex_handle; + env->mutex_handle = mtxmgr; + if (F_ISSET(env, ENV_PRIVATE)) { + mutexp = (DB_MUTEX *)mtxmgr->mutex_array + 1; + chunk = NULL; + size = __env_elem_size(env, + (void *)mtxregion->mutex_off_alloc); + size -= sizeof(*mutexp); + } else + mutexp = MUTEXP_SET(env, 1); + for (i = 1; i <= mtxregion->stat.st_mutex_cnt; ++i) { + if (F_ISSET(env, ENV_PRIVATE)) + indx = (db_mutex_t)mutexp; + else + indx = i; + if (F_ISSET(mutexp, DB_MUTEX_ALLOCATED)) + (void)__mutex_destroy(env, indx); + mutexp++; + if (F_ISSET(env, ENV_PRIVATE) && + (size -= sizeof(*mutexp)) < sizeof(*mutexp)) { + mutexp = __env_get_chunk(&mtxmgr->reginfo, + &chunk, &size); + } + mutexp = ALIGNP_INC(mutexp, mtxregion->stat.st_mutex_align); + } + env->mutex_handle = orig_handle; +} +#endif diff -r 000000000000 -r a1985f14b030 src/mutex/mut_stat.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/mutex/mut_stat.c Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,601 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 1996, 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + * $Id$ + */ + +#include "db_config.h" + +#include "db_int.h" +#include "dbinc/db_page.h" +#include "dbinc/db_am.h" + +#ifdef HAVE_STATISTICS +static int __mutex_print_all __P((ENV *, u_int32_t)); +static const char *__mutex_print_id __P((int)); +static int __mutex_print_stats __P((ENV *, u_int32_t)); +static void __mutex_print_summary __P((ENV *)); +static int __mutex_stat __P((ENV *, DB_MUTEX_STAT **, u_int32_t)); + +/* + * __mutex_stat_pp -- + * ENV->mutex_stat pre/post processing. + * + * PUBLIC: int __mutex_stat_pp __P((DB_ENV *, DB_MUTEX_STAT **, u_int32_t)); + */ +int +__mutex_stat_pp(dbenv, statp, flags) + DB_ENV *dbenv; + DB_MUTEX_STAT **statp; + u_int32_t flags; +{ + DB_THREAD_INFO *ip; + ENV *env; + int ret; + + env = dbenv->env; + + ENV_REQUIRES_CONFIG(env, + env->mutex_handle, "DB_ENV->mutex_stat", DB_INIT_MUTEX); + + if ((ret = __db_fchk(env, + "DB_ENV->mutex_stat", flags, DB_STAT_CLEAR)) != 0) + return (ret); + + ENV_ENTER(env, ip); + REPLICATION_WRAP(env, (__mutex_stat(env, statp, flags)), 0, ret); + ENV_LEAVE(env, ip); + return (ret); +} + +/* + * __mutex_stat -- + * ENV->mutex_stat. + */ +static int +__mutex_stat(env, statp, flags) + ENV *env; + DB_MUTEX_STAT **statp; + u_int32_t flags; +{ + DB_MUTEXMGR *mtxmgr; + DB_MUTEXREGION *mtxregion; + DB_MUTEX_STAT *stats; + int ret; + + *statp = NULL; + mtxmgr = env->mutex_handle; + mtxregion = mtxmgr->reginfo.primary; + + if ((ret = __os_umalloc(env, sizeof(DB_MUTEX_STAT), &stats)) != 0) + return (ret); + + MUTEX_SYSTEM_LOCK(env); + + /* + * Most fields are maintained in the underlying region structure. + * Region size and region mutex are not. + */ + *stats = mtxregion->stat; + stats->st_regsize = mtxmgr->reginfo.rp->size; + stats->st_regmax = mtxmgr->reginfo.rp->max; + __mutex_set_wait_info(env, mtxregion->mtx_region, + &stats->st_region_wait, &stats->st_region_nowait); + if (LF_ISSET(DB_STAT_CLEAR)) + __mutex_clear(env, mtxregion->mtx_region); + + MUTEX_SYSTEM_UNLOCK(env); + + *statp = stats; + return (0); +} + +/* + * __mutex_stat_print_pp -- + * ENV->mutex_stat_print pre/post processing. + * + * PUBLIC: int __mutex_stat_print_pp __P((DB_ENV *, u_int32_t)); + */ +int +__mutex_stat_print_pp(dbenv, flags) + DB_ENV *dbenv; + u_int32_t flags; +{ + DB_THREAD_INFO *ip; + ENV *env; + int ret; + + env = dbenv->env; + + ENV_REQUIRES_CONFIG(env, + env->mutex_handle, "DB_ENV->mutex_stat_print", DB_INIT_MUTEX); + + if ((ret = __db_fchk(env, "DB_ENV->mutex_stat_print", + flags, DB_STAT_ALL | DB_STAT_ALLOC | DB_STAT_CLEAR)) != 0) + return (ret); + + ENV_ENTER(env, ip); + REPLICATION_WRAP(env, (__mutex_stat_print(env, flags)), 0, ret); + ENV_LEAVE(env, ip); + return (ret); +} + +/* + * __mutex_stat_print + * ENV->mutex_stat_print method. + * + * PUBLIC: int __mutex_stat_print __P((ENV *, u_int32_t)); + */ +int +__mutex_stat_print(env, flags) + ENV *env; + u_int32_t flags; +{ + u_int32_t orig_flags; + int ret; + + orig_flags = flags; + LF_CLR(DB_STAT_CLEAR | DB_STAT_SUBSYSTEM); + if (flags == 0 || LF_ISSET(DB_STAT_ALL)) { + ret = __mutex_print_stats(env, orig_flags); + __mutex_print_summary(env); + if (flags == 0 || ret != 0) + return (ret); + } + + if (LF_ISSET(DB_STAT_ALL)) + ret = __mutex_print_all(env, orig_flags); + + return (0); +} + +static void +__mutex_print_summary(env) + ENV *env; +{ + DB_MUTEX *mutexp; + DB_MUTEXMGR *mtxmgr; + DB_MUTEXREGION *mtxregion; + void *chunk; + db_mutex_t i; + u_int32_t counts[MTX_MAX_ENTRY + 2]; + uintmax_t size; + int alloc_id; + + mtxmgr = env->mutex_handle; + mtxregion = mtxmgr->reginfo.primary; + memset(counts, 0, sizeof(counts)); + size = 0; + + if (F_ISSET(env, ENV_PRIVATE)) { + mutexp = (DB_MUTEX *)mtxmgr->mutex_array + 1; + chunk = NULL; + size = __env_elem_size(env, + ROFF_TO_P(mtxregion->mutex_off_alloc)); + size -= sizeof(*mutexp); + } else + mutexp = MUTEXP_SET(env, 1); + for (i = 1; i <= mtxregion->stat.st_mutex_cnt; ++i) { + if (!F_ISSET(mutexp, DB_MUTEX_ALLOCATED)) + counts[0]++; + else if (mutexp->alloc_id > MTX_MAX_ENTRY) + counts[MTX_MAX_ENTRY + 1]++; + else + counts[mutexp->alloc_id]++; + + mutexp++; + if (F_ISSET(env, ENV_PRIVATE) && + (size -= sizeof(*mutexp)) < sizeof(*mutexp)) { + mutexp = + __env_get_chunk(&mtxmgr->reginfo, &chunk, &size); + } + mutexp = ALIGNP_INC(mutexp, mtxregion->stat.st_mutex_align); + } + __db_msg(env, "Mutex counts"); + __db_msg(env, "%d\tUnallocated", counts[0]); + for (alloc_id = 1; alloc_id <= MTX_TXN_REGION + 1; alloc_id++) + if (counts[alloc_id] != 0) + __db_msg(env, "%lu\t%s", + (u_long)counts[alloc_id], + __mutex_print_id(alloc_id)); + +} + +/* + * __mutex_print_stats -- + * Display default mutex region statistics. + */ +static int +__mutex_print_stats(env, flags) + ENV *env; + u_int32_t flags; +{ + DB_MUTEX_STAT *sp; + int ret; + + if ((ret = __mutex_stat(env, &sp, LF_ISSET(DB_STAT_CLEAR))) != 0) + return (ret); + + if (LF_ISSET(DB_STAT_ALL)) + __db_msg(env, "Default mutex region information:"); + + __db_dlbytes(env, "Mutex region size", + (u_long)0, (u_long)0, (u_long)sp->st_regsize); + __db_dlbytes(env, "Mutex region max size", + (u_long)0, (u_long)0, (u_long)sp->st_regmax); + __db_dl_pct(env, + "The number of region locks that required waiting", + (u_long)sp->st_region_wait, DB_PCT(sp->st_region_wait, + sp->st_region_wait + sp->st_region_nowait), NULL); + STAT_ULONG("Mutex alignment", sp->st_mutex_align); + STAT_ULONG("Mutex test-and-set spins", sp->st_mutex_tas_spins); + STAT_ULONG("Mutex initial count", sp->st_mutex_init); + STAT_ULONG("Mutex total count", sp->st_mutex_cnt); + STAT_ULONG("Mutex max count", sp->st_mutex_max); + STAT_ULONG("Mutex free count", sp->st_mutex_free); + STAT_ULONG("Mutex in-use count", sp->st_mutex_inuse); + STAT_ULONG("Mutex maximum in-use count", sp->st_mutex_inuse_max); + + __os_ufree(env, sp); + + return (0); +} + +/* + * __mutex_print_all -- + * Display debugging mutex region statistics. + */ +static int +__mutex_print_all(env, flags) + ENV *env; + u_int32_t flags; +{ + static const FN fn[] = { + { DB_MUTEX_ALLOCATED, "alloc" }, + { DB_MUTEX_LOCKED, "locked" }, + { DB_MUTEX_LOGICAL_LOCK, "logical" }, + { DB_MUTEX_PROCESS_ONLY, "process-private" }, + { DB_MUTEX_SELF_BLOCK, "self-block" }, + { 0, NULL } + }; + DB_MSGBUF mb, *mbp; + DB_MUTEX *mutexp; + DB_MUTEXMGR *mtxmgr; + DB_MUTEXREGION *mtxregion; + db_mutex_t i; + uintmax_t size; + void *chunk; + + DB_MSGBUF_INIT(&mb); + mbp = &mb; + + mtxmgr = env->mutex_handle; + mtxregion = mtxmgr->reginfo.primary; + + __db_print_reginfo(env, &mtxmgr->reginfo, "Mutex", flags); + __db_msg(env, "%s", DB_GLOBAL(db_line)); + + __db_msg(env, "DB_MUTEXREGION structure:"); + __mutex_print_debug_single(env, + "DB_MUTEXREGION region mutex", mtxregion->mtx_region, flags); + STAT_ULONG("Size of the aligned mutex", mtxregion->mutex_size); + STAT_ULONG("Next free mutex", mtxregion->mutex_next); + + /* + * The OOB mutex (MUTEX_INVALID) is 0, skip it. + * + * We're not holding the mutex region lock, so we're racing threads of + * control allocating mutexes. That's OK, it just means we display or + * clear statistics while mutexes are moving. + */ + __db_msg(env, "%s", DB_GLOBAL(db_line)); + __db_msg(env, "mutex\twait/nowait, pct wait, holder, flags"); + size = 0; + if (F_ISSET(env, ENV_PRIVATE)) { + mutexp = (DB_MUTEX *)mtxmgr->mutex_array + 1; + chunk = NULL; + size = __env_elem_size(env, + ROFF_TO_P(mtxregion->mutex_off_alloc)); + size -= sizeof(*mutexp); + } else + mutexp = MUTEXP_SET(env, 1); + for (i = 1; i <= mtxregion->stat.st_mutex_cnt; ++i) { + if (F_ISSET(mutexp, DB_MUTEX_ALLOCATED)) { + __db_msgadd(env, mbp, "%5lu\t", (u_long)i); + + __mutex_print_debug_stats(env, mbp, + F_ISSET(env, ENV_PRIVATE) ? + (db_mutex_t)mutexp : i, flags); + + if (mutexp->alloc_id != 0) + __db_msgadd(env, mbp, + ", %s", __mutex_print_id(mutexp->alloc_id)); + + __db_prflags(env, mbp, mutexp->flags, fn, " (", ")"); + + DB_MSGBUF_FLUSH(env, mbp); + } + + mutexp++; + if (F_ISSET(env, ENV_PRIVATE) && + (size -= sizeof(*mutexp)) < sizeof(*mutexp)) { + mutexp = + __env_get_chunk(&mtxmgr->reginfo, &chunk, &size); + } + mutexp = ALIGNP_INC(mutexp, mtxregion->stat.st_mutex_align); + } + + return (0); +} + +/* + * __mutex_print_debug_single -- + * Print mutex internal debugging statistics for a single mutex on a + * single output line. + * + * PUBLIC: void __mutex_print_debug_single + * PUBLIC: __P((ENV *, const char *, db_mutex_t, u_int32_t)); + */ +void +__mutex_print_debug_single(env, tag, mutex, flags) + ENV *env; + const char *tag; + db_mutex_t mutex; + u_int32_t flags; +{ + DB_MSGBUF mb, *mbp; + + DB_MSGBUF_INIT(&mb); + mbp = &mb; + + if (LF_ISSET(DB_STAT_SUBSYSTEM)) + LF_CLR(DB_STAT_CLEAR); + __db_msgadd(env, mbp, "%lu\t%s ", (u_long)mutex, tag); + __mutex_print_debug_stats(env, mbp, mutex, flags); + DB_MSGBUF_FLUSH(env, mbp); +} + +/* + * __mutex_print_debug_stats -- + * Print mutex internal debugging statistics, that is, the statistics + * in the [] square brackets. + * + * PUBLIC: void __mutex_print_debug_stats + * PUBLIC: __P((ENV *, DB_MSGBUF *, db_mutex_t, u_int32_t)); + */ +void +__mutex_print_debug_stats(env, mbp, mutex, flags) + ENV *env; + DB_MSGBUF *mbp; + db_mutex_t mutex; + u_int32_t flags; +{ + DB_ENV *dbenv; + DB_MUTEX *mutexp; + u_long value; + char buf[DB_THREADID_STRLEN]; +#if defined(HAVE_SHARED_LATCHES) && (defined(HAVE_MUTEX_HYBRID) || \ + !defined(HAVE_MUTEX_PTHREADS)) + int sharecount; +#endif + + if (mutex == MUTEX_INVALID) { + __db_msgadd(env, mbp, "[!Set]"); + return; + } + + dbenv = env->dbenv; + mutexp = MUTEXP_SET(env, mutex); + + __db_msgadd(env, mbp, "["); + if ((value = mutexp->mutex_set_wait) < 10000000) + __db_msgadd(env, mbp, "%lu", value); + else + __db_msgadd(env, mbp, "%luM", value / 1000000); + if ((value = mutexp->mutex_set_nowait) < 10000000) + __db_msgadd(env, mbp, "/%lu", value); + else + __db_msgadd(env, mbp, "/%luM", value / 1000000); + + __db_msgadd(env, mbp, " %d%% ", + DB_PCT(mutexp->mutex_set_wait, + mutexp->mutex_set_wait + mutexp->mutex_set_nowait)); + +#if defined(HAVE_SHARED_LATCHES) + if (F_ISSET(mutexp, DB_MUTEX_SHARED)) { + __db_msgadd(env, mbp, " rd "); + if ((value = mutexp->mutex_set_rd_wait) < 10000000) + __db_msgadd(env, mbp, "%lu", value); + else + __db_msgadd(env, mbp, "%luM", value / 1000000); + if ((value = mutexp->mutex_set_rd_nowait) < 10000000) + __db_msgadd(env, mbp, "/%lu", value); + else + __db_msgadd(env, mbp, "/%luM", value / 1000000); + __db_msgadd(env, mbp, " %d%% ", + DB_PCT(mutexp->mutex_set_rd_wait, + mutexp->mutex_set_rd_wait + mutexp->mutex_set_rd_nowait)); + } +#endif + + if (F_ISSET(mutexp, DB_MUTEX_LOCKED)) + __db_msgadd(env, mbp, "%s]", + dbenv->thread_id_string(dbenv, + mutexp->pid, mutexp->tid, buf)); + /* Pthreads-based shared latches do not expose the share count. */ +#if defined(HAVE_SHARED_LATCHES) && (defined(HAVE_MUTEX_HYBRID) || \ + !defined(HAVE_MUTEX_PTHREADS)) + else if (F_ISSET(mutexp, DB_MUTEX_SHARED) && + (sharecount = atomic_read(&mutexp->sharecount)) != 0) { + if (sharecount == 1) + __db_msgadd(env, mbp, "1 reader"); + else + __db_msgadd(env, mbp, "%d readers", sharecount); + /* Show the thread which last acquired the latch. */ + __db_msgadd(env, mbp, " %s]", + dbenv->thread_id_string(dbenv, + mutexp->pid, mutexp->tid, buf)); + } +#endif + else + __db_msgadd(env, mbp, "!Own]"); + +#ifdef HAVE_MUTEX_HYBRID + if (mutexp->hybrid_wait != 0 || mutexp->hybrid_wakeup != 0) + __db_msgadd(env, mbp, " ", + mutexp->hybrid_wait, mutexp->hybrid_wakeup); +#endif + + if (LF_ISSET(DB_STAT_CLEAR)) + __mutex_clear(env, mutex); +} + +static const char * +__mutex_print_id(alloc_id) + int alloc_id; +{ + switch (alloc_id) { + case MTX_APPLICATION: return ("application allocated"); + case MTX_ATOMIC_EMULATION: return ("atomic emulation"); + case MTX_DB_HANDLE: return ("db handle"); + case MTX_ENV_DBLIST: return ("env dblist"); + case MTX_ENV_EXCLDBLIST: return ("env exclusive dblist"); + case MTX_ENV_HANDLE: return ("env handle"); + case MTX_ENV_REGION: return ("env region"); + case MTX_LOCK_REGION: return ("lock region"); + case MTX_LOGICAL_LOCK: return ("logical lock"); + case MTX_LOG_FILENAME: return ("log filename"); + case MTX_LOG_FLUSH: return ("log flush"); + case MTX_LOG_HANDLE: return ("log handle"); + case MTX_LOG_REGION: return ("log region"); + case MTX_MPOOLFILE_HANDLE: return ("mpoolfile handle"); + case MTX_MPOOL_BH: return ("mpool buffer"); + case MTX_MPOOL_FH: return ("mpool filehandle"); + case MTX_MPOOL_FILE_BUCKET: return ("mpool file bucket"); + case MTX_MPOOL_HANDLE: return ("mpool handle"); + case MTX_MPOOL_HASH_BUCKET: return ("mpool hash bucket"); + case MTX_MPOOL_REGION: return ("mpool region"); + case MTX_MUTEX_REGION: return ("mutex region"); + case MTX_MUTEX_TEST: return ("mutex test"); + case MTX_REPMGR: return ("replication manager"); + case MTX_REP_CHKPT: return ("replication checkpoint"); + case MTX_REP_DATABASE: return ("replication database"); + case MTX_REP_DIAG: return ("replication diagnostics"); + case MTX_REP_EVENT: return ("replication event"); + case MTX_REP_REGION: return ("replication region"); + case MTX_REP_START: return ("replication role config"); + case MTX_REP_WAITER: return ("replication txn apply"); + case MTX_SEQUENCE: return ("sequence"); + case MTX_TWISTER: return ("twister"); + case MTX_TCL_EVENTS: return ("Tcl events"); + case MTX_TXN_ACTIVE: return ("txn active list"); + case MTX_TXN_CHKPT: return ("transaction checkpoint"); + case MTX_TXN_COMMIT: return ("txn commit"); + case MTX_TXN_MVCC: return ("txn mvcc"); + case MTX_TXN_REGION: return ("txn region"); + default: return ("unknown mutex type"); + /* NOTREACHED */ + } +} + +/* + * __mutex_set_wait_info -- + * Return mutex statistics. + * + * PUBLIC: void __mutex_set_wait_info + * PUBLIC: __P((ENV *, db_mutex_t, uintmax_t *, uintmax_t *)); + */ +void +__mutex_set_wait_info(env, mutex, waitp, nowaitp) + ENV *env; + db_mutex_t mutex; + uintmax_t *waitp, *nowaitp; +{ + DB_MUTEX *mutexp; + + if (mutex == MUTEX_INVALID) { + *waitp = 0; + *nowaitp = 0; + return; + } + mutexp = MUTEXP_SET(env, mutex); + + *waitp = mutexp->mutex_set_wait; + *nowaitp = mutexp->mutex_set_nowait; +} + +/* + * __mutex_clear -- + * Clear mutex statistics. + * + * PUBLIC: void __mutex_clear __P((ENV *, db_mutex_t)); + */ +void +__mutex_clear(env, mutex) + ENV *env; + db_mutex_t mutex; +{ + DB_MUTEX *mutexp; + + if (!MUTEX_ON(env)) + return; + + mutexp = MUTEXP_SET(env, mutex); + + mutexp->mutex_set_wait = mutexp->mutex_set_nowait = 0; +#ifdef HAVE_SHARED_LATCHES + mutexp->mutex_set_rd_wait = mutexp->mutex_set_rd_nowait = 0; +#endif +#ifdef HAVE_MUTEX_HYBRID + mutexp->hybrid_wait = mutexp->hybrid_wakeup = 0; +#endif +} + +#else /* !HAVE_STATISTICS */ + +int +__mutex_stat_pp(dbenv, statp, flags) + DB_ENV *dbenv; + DB_MUTEX_STAT **statp; + u_int32_t flags; +{ + COMPQUIET(statp, NULL); + COMPQUIET(flags, 0); + + return (__db_stat_not_built(dbenv->env)); +} + +int +__mutex_stat_print_pp(dbenv, flags) + DB_ENV *dbenv; + u_int32_t flags; +{ + COMPQUIET(flags, 0); + + return (__db_stat_not_built(dbenv->env)); +} +#endif diff -r 000000000000 -r a1985f14b030 src/mutex/mut_tas.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/mutex/mut_tas.c Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,630 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 1996, 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + * $Id$ + */ + +#include "db_config.h" + +#include "db_int.h" +#include "dbinc/lock.h" + +static inline int __db_tas_mutex_lock_int + __P((ENV *, db_mutex_t, db_timeout_t, int)); +static inline int __db_tas_mutex_readlock_int __P((ENV *, db_mutex_t, int)); + +/* + * __db_tas_mutex_init -- + * Initialize a test-and-set mutex. + * + * PUBLIC: int __db_tas_mutex_init __P((ENV *, db_mutex_t, u_int32_t)); + */ +int +__db_tas_mutex_init(env, mutex, flags) + ENV *env; + db_mutex_t mutex; + u_int32_t flags; +{ + DB_ENV *dbenv; + DB_MUTEX *mutexp; + int ret; + +#ifndef HAVE_MUTEX_HYBRID + COMPQUIET(flags, 0); +#endif + + dbenv = env->dbenv; + mutexp = MUTEXP_SET(env, mutex); + + /* Check alignment. */ + if (((uintptr_t)mutexp & (dbenv->mutex_align - 1)) != 0) { + __db_errx(env, DB_STR("2028", + "TAS: mutex not appropriately aligned")); + return (EINVAL); + } + +#ifdef HAVE_SHARED_LATCHES + if (F_ISSET(mutexp, DB_MUTEX_SHARED)) + atomic_init(&mutexp->sharecount, 0); + else +#endif + if (MUTEX_INIT(&mutexp->tas)) { + ret = __os_get_syserr(); + __db_syserr(env, ret, DB_STR("2029", + "TAS: mutex initialize")); + return (__os_posix_err(ret)); + } +#ifdef HAVE_MUTEX_HYBRID + if ((ret = __db_pthread_mutex_init(env, + mutex, flags | DB_MUTEX_SELF_BLOCK)) != 0) + return (ret); +#endif + return (0); +} + +/* + * __db_tas_mutex_lock_int + * Internal function to lock a mutex, or just try to lock it without waiting + */ +inline static int +__db_tas_mutex_lock_int(env, mutex, timeout, nowait) + ENV *env; + db_mutex_t mutex; + db_timeout_t timeout; + int nowait; +{ + DB_ENV *dbenv; + DB_MUTEX *mutexp; + DB_MUTEXMGR *mtxmgr; + DB_MUTEXREGION *mtxregion; + DB_THREAD_INFO *ip; + db_timespec now, timespec; + u_int32_t nspins; + int ret; +#ifdef HAVE_MUTEX_HYBRID + const u_long micros = 0; +#else + u_long micros, max_micros; + db_timeout_t time_left; +#endif + + dbenv = env->dbenv; + + if (!MUTEX_ON(env) || F_ISSET(dbenv, DB_ENV_NOLOCKING)) + return (0); + + mtxmgr = env->mutex_handle; + mtxregion = mtxmgr->reginfo.primary; + mutexp = MUTEXP_SET(env, mutex); + + CHECK_MTX_THREAD(env, mutexp); + +#ifdef HAVE_STATISTICS + if (F_ISSET(mutexp, DB_MUTEX_LOCKED)) + STAT_INC(env, mutex, set_wait, mutexp->mutex_set_wait, mutex); + else + STAT_INC(env, + mutex, set_nowait, mutexp->mutex_set_nowait, mutex); +#endif + +#ifndef HAVE_MUTEX_HYBRID + /* + * Wait 1ms initially, up to 10ms for mutexes backing logical database + * locks, and up to 25 ms for mutual exclusion data structure mutexes. + * SR: #7675 + */ + micros = 1000; + max_micros = F_ISSET(mutexp, DB_MUTEX_LOGICAL_LOCK) ? 10000 : 25000; +#endif + + /* Clear the ending timespec so it'll be initialed upon first need. */ + if (timeout != 0) + timespecclear(×pec); + + /* + * Only check the thread state once, by initializing the thread + * control block pointer to null. If it is not the failchk + * thread, then ip will have a valid value subsequent times + * in the loop. + */ + ip = NULL; + +loop: /* Attempt to acquire the resource for N spins. */ + for (nspins = + mtxregion->stat.st_mutex_tas_spins; nspins > 0; --nspins) { +#ifdef HAVE_MUTEX_S390_CC_ASSEMBLY + tsl_t zero; + + zero = 0; +#endif + +#ifdef HAVE_MUTEX_HPPA_MSEM_INIT + relock: +#endif + /* + * Avoid interlocked instructions until they're likely to + * succeed by first checking whether it is held + */ + if (MUTEXP_IS_BUSY(mutexp) || !MUTEXP_ACQUIRE(mutexp)) { + if (F_ISSET(dbenv, DB_ENV_FAILCHK) && + ip == NULL && dbenv->is_alive(dbenv, + mutexp->pid, mutexp->tid, 0) == 0) { + ret = __env_set_state(env, &ip, THREAD_VERIFY); + if (ret != 0 || + ip->dbth_state == THREAD_FAILCHK) + return (DB_RUNRECOVERY); + } + if (nowait) + return (DB_LOCK_NOTGRANTED); + /* + * Some systems (notably those with newer Intel CPUs) + * need a small pause here. [#6975] + */ + MUTEX_PAUSE + continue; + } + + MEMBAR_ENTER(); + +#ifdef HAVE_MUTEX_HPPA_MSEM_INIT + /* + * HP semaphores are unlocked automatically when a holding + * process exits. If the mutex appears to be locked + * (F_ISSET(DB_MUTEX_LOCKED)) but we got here, assume this + * has happened. Set the pid and tid into the mutex and + * lock again. (The default state of the mutexes used to + * block in __lock_get_internal is locked, so exiting with + * a locked mutex is reasonable behavior for a process that + * happened to initialize or use one of them.) + */ + if (F_ISSET(mutexp, DB_MUTEX_LOCKED)) { + dbenv->thread_id(dbenv, &mutexp->pid, &mutexp->tid); + goto relock; + } + /* + * If we make it here, the mutex isn't locked, the diagnostic + * won't fire, and we were really unlocked by someone calling + * the DB mutex unlock function. + */ +#endif +#ifdef DIAGNOSTIC + if (F_ISSET(mutexp, DB_MUTEX_LOCKED)) { + char buf[DB_THREADID_STRLEN]; + __db_errx(env, DB_STR_A("2030", + "TAS lock failed: lock %ld currently in use: ID: %s", + "%ld %s"), (long)mutex, + dbenv->thread_id_string(dbenv, + mutexp->pid, mutexp->tid, buf)); + return (__env_panic(env, EACCES)); + } +#endif + F_SET(mutexp, DB_MUTEX_LOCKED); + dbenv->thread_id(dbenv, &mutexp->pid, &mutexp->tid); + +#ifdef DIAGNOSTIC + /* + * We want to switch threads as often as possible. Yield + * every time we get a mutex to ensure contention. + */ + if (F_ISSET(dbenv, DB_ENV_YIELDCPU)) + __os_yield(env, 0, 0); +#endif + return (0); + } + + /* + * We need to wait for the lock to become available. + * Possibly setup timeouts if this is the first wait, or + * check expiration times for the second and subsequent waits. + */ + if (timeout != 0) { + /* Set the expiration time if this is the first sleep . */ + if (!timespecisset(×pec)) + __clock_set_expires(env, ×pec, timeout); + else { + timespecclear(&now); + if (__clock_expired(env, &now, ×pec)) + return (DB_TIMEOUT); +#ifndef HAVE_MUTEX_HYBRID + timespecsub(&now, ×pec); + DB_TIMESPEC_TO_TIMEOUT(time_left, &now, 0); + time_left = timeout - time_left; + if (micros > time_left) + micros = time_left; +#endif + } + } + + /* + * This yields for a while for tas mutexes, and just gives up the + * processor for hybrid mutexes. + * By yielding here we can get the other thread to give up the + * mutex before calling the more expensive library mutex call. + * Tests have shown this to be a big win when there is contention. + */ + PERFMON4(env, mutex, suspend, mutex, TRUE, mutexp->alloc_id, mutexp); + __os_yield(env, 0, micros); + PERFMON4(env, mutex, resume, mutex, TRUE, mutexp->alloc_id, mutexp); + +#if defined(HAVE_MUTEX_HYBRID) + if (!MUTEXP_IS_BUSY(mutexp)) + goto loop; + /* Wait until the mutex can be obtained exclusively or it times out. */ + if ((ret = __db_hybrid_mutex_suspend(env, + mutex, timeout == 0 ? NULL : ×pec, TRUE)) != 0) + return (ret); +#else + if ((micros <<= 1) > max_micros) + micros = max_micros; +#endif + + /* + * We're spinning. The environment might be hung, and somebody else + * has already recovered it. The first thing recovery does is panic + * the environment. Check to see if we're never going to get this + * mutex. + */ + PANIC_CHECK(env); + + goto loop; +} + +/* + * __db_tas_mutex_lock + * Lock on a mutex, blocking if necessary. + * + * PUBLIC: int __db_tas_mutex_lock __P((ENV *, db_mutex_t, db_timeout_t)); + */ +int +__db_tas_mutex_lock(env, mutex, timeout) + ENV *env; + db_mutex_t mutex; + db_timeout_t timeout; +{ + return (__db_tas_mutex_lock_int(env, mutex, timeout, 0)); +} + +/* + * __db_tas_mutex_trylock + * Try to exclusively lock a mutex without ever blocking - ever! + * + * Returns 0 on success, + * DB_LOCK_NOTGRANTED on timeout + * Possibly DB_RUNRECOVERY if DB_ENV_FAILCHK or panic. + * + * This will work for DB_MUTEX_SHARED, though it always tries + * for exclusive access. + * + * PUBLIC: int __db_tas_mutex_trylock __P((ENV *, db_mutex_t)); + */ +int +__db_tas_mutex_trylock(env, mutex) + ENV *env; + db_mutex_t mutex; +{ + return (__db_tas_mutex_lock_int(env, mutex, 0, 1)); +} + +#if defined(HAVE_SHARED_LATCHES) +/* + * __db_tas_mutex_readlock_int + * Internal function to get a shared lock on a latch, blocking if necessary. + * + */ +static inline int +__db_tas_mutex_readlock_int(env, mutex, nowait) + ENV *env; + db_mutex_t mutex; + int nowait; +{ + DB_ENV *dbenv; + DB_MUTEX *mutexp; + DB_MUTEXMGR *mtxmgr; + DB_MUTEXREGION *mtxregion; + DB_THREAD_INFO *ip; + int lock; + u_int32_t nspins; + int ret; +#ifndef HAVE_MUTEX_HYBRID + u_long micros, max_micros; +#endif + dbenv = env->dbenv; + + if (!MUTEX_ON(env) || F_ISSET(dbenv, DB_ENV_NOLOCKING)) + return (0); + + mtxmgr = env->mutex_handle; + mtxregion = mtxmgr->reginfo.primary; + mutexp = MUTEXP_SET(env, mutex); + + CHECK_MTX_THREAD(env, mutexp); + + DB_ASSERT(env, F_ISSET(mutexp, DB_MUTEX_SHARED)); +#ifdef HAVE_STATISTICS + if (F_ISSET(mutexp, DB_MUTEX_LOCKED)) + STAT_INC(env, + mutex, set_rd_wait, mutexp->mutex_set_rd_wait, mutex); + else + STAT_INC(env, + mutex, set_rd_nowait, mutexp->mutex_set_rd_nowait, mutex); +#endif + +#ifndef HAVE_MUTEX_HYBRID + /* + * Wait 1ms initially, up to 10ms for mutexes backing logical database + * locks, and up to 25 ms for mutual exclusion data structure mutexes. + * SR: #7675 + */ + micros = 1000; + max_micros = F_ISSET(mutexp, DB_MUTEX_LOGICAL_LOCK) ? 10000 : 25000; +#endif + +loop: /* Attempt to acquire the resource for N spins. */ + for (nspins = + mtxregion->stat.st_mutex_tas_spins; nspins > 0; --nspins) { + lock = atomic_read(&mutexp->sharecount); + if (lock == MUTEX_SHARE_ISEXCLUSIVE || + !atomic_compare_exchange(env, + &mutexp->sharecount, lock, lock + 1)) { + /* + * Some systems (notably those with newer Intel CPUs) + * need a small pause here. [#6975] + */ + MUTEX_PAUSE + continue; + } + + MEMBAR_ENTER(); + /* For shared latches the threadid is the last requestor's id. + */ + dbenv->thread_id(dbenv, &mutexp->pid, &mutexp->tid); + + return (0); + } + + /* + * Waiting for the latched must be avoided when it could allow a + * 'failchk'ing thread to hang. + */ + if (F_ISSET(dbenv, DB_ENV_FAILCHK) && + dbenv->is_alive(dbenv, mutexp->pid, mutexp->tid, 0) == 0) { + ret = __env_set_state(env, &ip, THREAD_VERIFY); + if (ret != 0 || ip->dbth_state == THREAD_FAILCHK) + return (DB_RUNRECOVERY); + } + + /* + * It is possible to spin out when the latch is just shared, due to + * many threads or interrupts interfering with the compare&exchange. + * Avoid spurious DB_LOCK_NOTGRANTED returns by retrying. + */ + if (nowait) { + if (atomic_read(&mutexp->sharecount) != MUTEX_SHARE_ISEXCLUSIVE) + goto loop; + return (DB_LOCK_NOTGRANTED); + } + + /* Wait for the lock to become available. */ +#ifdef HAVE_MUTEX_HYBRID + /* + * By yielding here we can get the other thread to give up the + * mutex before calling the more expensive library mutex call. + * Tests have shown this to be a big win when there is contention. + */ + PERFMON4(env, mutex, suspend, mutex, FALSE, mutexp->alloc_id, mutexp); + __os_yield(env, 0, 0); + PERFMON4(env, mutex, resume, mutex, FALSE, mutexp->alloc_id, mutexp); + if (atomic_read(&mutexp->sharecount) != MUTEX_SHARE_ISEXCLUSIVE) + goto loop; + /* Wait until the mutex is no longer exclusively locked. */ + if ((ret = __db_hybrid_mutex_suspend(env, mutex, NULL, FALSE)) != 0) + return (ret); +#else + PERFMON4(env, mutex, suspend, mutex, FALSE, mutexp->alloc_id, mutexp); + __os_yield(env, 0, micros); + PERFMON4(env, mutex, resume, mutex, FALSE, mutexp->alloc_id, mutexp); + if ((micros <<= 1) > max_micros) + micros = max_micros; +#endif + + /* + * We're spinning. The environment might be hung, and somebody else + * has already recovered it. The first thing recovery does is panic + * the environment. Check to see if we're never going to get this + * mutex. + */ + PANIC_CHECK(env); + + goto loop; +} + +/* + * __db_tas_mutex_readlock + * Get a shared lock on a latch, waiting if necessary. + * + * PUBLIC: #if defined(HAVE_SHARED_LATCHES) + * PUBLIC: int __db_tas_mutex_readlock __P((ENV *, db_mutex_t)); + * PUBLIC: #endif + */ +int +__db_tas_mutex_readlock(env, mutex) + ENV *env; + db_mutex_t mutex; +{ + return (__db_tas_mutex_readlock_int(env, mutex, 0)); +} + +/* + * __db_tas_mutex_tryreadlock + * Try to get a shared lock on a latch; don't wait when busy. + * + * PUBLIC: #if defined(HAVE_SHARED_LATCHES) + * PUBLIC: int __db_tas_mutex_tryreadlock __P((ENV *, db_mutex_t)); + * PUBLIC: #endif + */ +int +__db_tas_mutex_tryreadlock(env, mutex) + ENV *env; + db_mutex_t mutex; +{ + return (__db_tas_mutex_readlock_int(env, mutex, 1)); +} +#endif + +/* + * __db_tas_mutex_unlock -- + * Release a mutex. + * + * PUBLIC: int __db_tas_mutex_unlock __P((ENV *, db_mutex_t)); + * + * Hybrid shared latch wakeup + * When an exclusive requester waits for the last shared holder to + * release, it increments mutexp->wait and pthread_cond_wait()'s. The + * last shared unlock calls __db_pthread_mutex_unlock() to wake it. + */ +int +__db_tas_mutex_unlock(env, mutex) + ENV *env; + db_mutex_t mutex; +{ + DB_ENV *dbenv; + DB_MUTEX *mutexp; +#ifdef HAVE_MUTEX_HYBRID + int ret; +#ifdef MUTEX_DIAG + int waiters; +#endif +#endif +#ifdef HAVE_SHARED_LATCHES + int sharecount; +#endif + dbenv = env->dbenv; + + if (!MUTEX_ON(env) || F_ISSET(dbenv, DB_ENV_NOLOCKING)) + return (0); + + mutexp = MUTEXP_SET(env, mutex); +#if defined(HAVE_MUTEX_HYBRID) && defined(MUTEX_DIAG) + waiters = mutexp->wait; +#endif + +#if defined(DIAGNOSTIC) +#if defined(HAVE_SHARED_LATCHES) + if (F_ISSET(mutexp, DB_MUTEX_SHARED)) { + if (atomic_read(&mutexp->sharecount) == 0) { + __db_errx(env, DB_STR_A("2031", + "shared unlock %ld already unlocked", "%ld"), + (long)mutex); + return (__env_panic(env, EACCES)); + } + } else +#endif + if (!F_ISSET(mutexp, DB_MUTEX_LOCKED)) { + __db_errx(env, DB_STR_A("2032", + "unlock %ld already unlocked", "%ld"), (long)mutex); + return (__env_panic(env, EACCES)); + } +#endif + +#ifdef HAVE_SHARED_LATCHES + if (F_ISSET(mutexp, DB_MUTEX_SHARED)) { + sharecount = atomic_read(&mutexp->sharecount); + /*MUTEX_MEMBAR(mutexp->sharecount);*/ /* XXX why? */ + if (sharecount == MUTEX_SHARE_ISEXCLUSIVE) { + F_CLR(mutexp, DB_MUTEX_LOCKED); + /* Flush flag update before zeroing count */ + MEMBAR_EXIT(); + atomic_init(&mutexp->sharecount, 0); + } else { + DB_ASSERT(env, sharecount > 0); + MEMBAR_EXIT(); + sharecount = atomic_dec(env, &mutexp->sharecount); + DB_ASSERT(env, sharecount >= 0); + if (sharecount > 0) + return (0); + } + } else +#endif + { + F_CLR(mutexp, DB_MUTEX_LOCKED); + MUTEX_UNSET(&mutexp->tas); + } + +#ifdef HAVE_MUTEX_HYBRID +#ifdef DIAGNOSTIC + if (F_ISSET(dbenv, DB_ENV_YIELDCPU)) + __os_yield(env, 0, 0); +#endif + + /* Prevent the load of wait from being hoisted before MUTEX_UNSET */ + MUTEX_MEMBAR(mutexp->flags); + if (mutexp->wait && + (ret = __db_pthread_mutex_unlock(env, mutex)) != 0) + return (ret); + +#ifdef MUTEX_DIAG + if (mutexp->wait) + printf("tas_unlock %ld %x waiters! busy %x waiters %d/%d\n", + mutex, pthread_self(), + MUTEXP_BUSY_FIELD(mutexp), waiters, mutexp->wait); +#endif +#endif + + return (0); +} + +/* + * __db_tas_mutex_destroy -- + * Destroy a mutex. + * + * PUBLIC: int __db_tas_mutex_destroy __P((ENV *, db_mutex_t)); + */ +int +__db_tas_mutex_destroy(env, mutex) + ENV *env; + db_mutex_t mutex; +{ + DB_MUTEX *mutexp; +#ifdef HAVE_MUTEX_HYBRID + int ret; +#endif + + if (!MUTEX_ON(env)) + return (0); + + mutexp = MUTEXP_SET(env, mutex); + + MUTEX_DESTROY(&mutexp->tas); + +#ifdef HAVE_MUTEX_HYBRID + if ((ret = __db_pthread_mutex_destroy(env, mutex)) != 0) + return (ret); +#endif + + COMPQUIET(mutexp, NULL); /* MUTEX_DESTROY may not be defined. */ + return (0); +} diff -r 000000000000 -r a1985f14b030 src/mutex/mut_win32.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/mutex/mut_win32.c Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,611 @@ +/* + * See the file LICENSE for redistribution information. + * + * Copyright (c) 2002, 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + * $Id$ + */ + +#include "db_config.h" + +#define LOAD_ACTUAL_MUTEX_CODE +#include "db_int.h" + +#include "dbinc/atomic.h" +/* + * This is where we load in the actual mutex declarations. + */ +#include "dbinc/mutex_int.h" + +/* + * Common code to get an event handle. This is executed whenever a mutex + * blocks, or when unlocking a mutex that a thread is waiting on. We can't + * keep these handles around, since the mutex structure is in shared memory, + * and each process gets its own handle value. + * + * We pass security attributes so that the created event is accessible by all + * users, in case a Windows service is sharing an environment with a local + * process run as a different user. + */ +static _TCHAR hex_digits[] = _T("0123456789abcdef"); + +static __inline int get_handle(env, mutexp, eventp) + ENV *env; + DB_MUTEX *mutexp; + HANDLE *eventp; +{ + _TCHAR idbuf[] = _T("db.m00000000"); + _TCHAR *p = idbuf + 12; + int ret = 0; + u_int32_t id; + + for (id = (mutexp)->id; id != 0; id >>= 4) + *--p = hex_digits[id & 0xf]; + +#ifndef DB_WINCE + if (DB_GLOBAL(win_sec_attr) == NULL) { + InitializeSecurityDescriptor(&DB_GLOBAL(win_default_sec_desc), + SECURITY_DESCRIPTOR_REVISION); + SetSecurityDescriptorDacl(&DB_GLOBAL(win_default_sec_desc), + TRUE, 0, FALSE); + DB_GLOBAL(win_default_sec_attr).nLength = + sizeof(SECURITY_ATTRIBUTES); + DB_GLOBAL(win_default_sec_attr).bInheritHandle = FALSE; + DB_GLOBAL(win_default_sec_attr).lpSecurityDescriptor = + &DB_GLOBAL(win_default_sec_desc); + DB_GLOBAL(win_sec_attr) = &DB_GLOBAL(win_default_sec_attr); + } +#endif + + if ((*eventp = CreateEvent(DB_GLOBAL(win_sec_attr), + FALSE, FALSE, idbuf)) == NULL) { + ret = __os_get_syserr(); + __db_syserr(env, ret, DB_STR("2002", + "Win32 create event failed")); + } + + return (ret); +} + +/* + * __db_win32_mutex_lock_int + * Internal function to lock a win32 mutex + * + * If the wait parameter is 0, this function will return DB_LOCK_NOTGRANTED + * rather than wait. + * + */ +static __inline int +__db_win32_mutex_lock_int(env, mutex, timeout, wait) + ENV *env; + db_mutex_t mutex; + db_timeout_t timeout; + int wait; +{ + DB_ENV *dbenv; + DB_MUTEX *mutexp; + DB_MUTEXMGR *mtxmgr; + DB_MUTEXREGION *mtxregion; + DB_THREAD_INFO *ip; + HANDLE event; + u_int32_t ms, nspins; + db_timespec now, tempspec, timeoutspec; + db_timeout_t time_left; + int ret; +#ifdef MUTEX_DIAG + LARGE_INTEGER now; +#endif + dbenv = env->dbenv; + + if (!MUTEX_ON(env) || F_ISSET(dbenv, DB_ENV_NOLOCKING)) + return (0); + + mtxmgr = env->mutex_handle; + mtxregion = mtxmgr->reginfo.primary; + mutexp = MUTEXP_SET(env, mutex); + + CHECK_MTX_THREAD(env, mutexp); + + if (timeout != 0) { + timespecclear(&timeoutspec); + __clock_set_expires(env, &timeoutspec, timeout); + } + + /* + * See WINCE_ATOMIC_MAGIC definition for details. + * Use sharecount, because the value just needs to be a db_atomic_t + * memory mapped onto the same page as those being Interlocked*. + */ + WINCE_ATOMIC_MAGIC(&mutexp->sharecount); + + event = NULL; + ms = 50; + ret = 0; + + /* + * Only check the thread state once, by initializing the thread + * control block pointer to null. If it is not the failchk + * thread, then ip will have a valid value subsequent times + * in the loop. + */ + ip = NULL; + +loop: /* Attempt to acquire the mutex mutex_tas_spins times, if waiting. */ + for (nspins = + mtxregion->stat.st_mutex_tas_spins; nspins > 0; --nspins) { + /* + * We can avoid the (expensive) interlocked instructions if + * the mutex is already busy. + */ + if (MUTEXP_IS_BUSY(mutexp) || !MUTEXP_ACQUIRE(mutexp)) { + if (F_ISSET(dbenv, DB_ENV_FAILCHK) && + ip == NULL && dbenv->is_alive(dbenv, + mutexp->pid, mutexp->tid, 0) == 0) { + ret = __env_set_state(env, &ip, THREAD_VERIFY); + if (ret != 0 || + ip->dbth_state == THREAD_FAILCHK) + return (DB_RUNRECOVERY); + } + if (!wait) + return (DB_LOCK_NOTGRANTED); + /* + * Some systems (notably those with newer Intel CPUs) + * need a small pause before retrying. [#6975] + */ + MUTEX_PAUSE + continue; + } + +#ifdef DIAGNOSTIC + if (F_ISSET(mutexp, DB_MUTEX_LOCKED)) { + char buf[DB_THREADID_STRLEN]; + __db_errx(env, DB_STR_A("2003", + "Win32 lock failed: mutex already locked by %s", + "%s"), dbenv->thread_id_string(dbenv, + mutexp->pid, mutexp->tid, buf)); + return (__env_panic(env, EACCES)); + } +#endif + F_SET(mutexp, DB_MUTEX_LOCKED); + dbenv->thread_id(dbenv, &mutexp->pid, &mutexp->tid); + +#ifdef HAVE_STATISTICS + if (event == NULL) + ++mutexp->mutex_set_nowait; + else + ++mutexp->mutex_set_wait; +#endif + if (event != NULL) { + CloseHandle(event); + InterlockedDecrement(&mutexp->nwaiters); +#ifdef MUTEX_DIAG + if (ret != WAIT_OBJECT_0) { + QueryPerformanceCounter(&diag_now); + printf(DB_STR_A("2004", + "[%I64d]: Lost signal on mutex %p, " + "id %d, ms %d\n", "%I64d %p %d %d"), + diag_now.QuadPart, mutexp, mutexp->id, ms); + } +#endif + } + +#ifdef DIAGNOSTIC + /* + * We want to switch threads as often as possible. Yield + * every time we get a mutex to ensure contention. + */ + if (F_ISSET(dbenv, DB_ENV_YIELDCPU)) + __os_yield(env, 0, 0); +#endif + + return (0); + } + + /* + * Yield the processor; wait 50 ms initially, up to 1 second. This + * loop is needed to work around a race where the signal from the + * unlocking thread gets lost. We start at 50 ms because it's unlikely + * to happen often and we want to avoid wasting CPU. + */ + if (timeout != 0) { + timespecclear(&now); + if (__clock_expired(env, &now, &timeoutspec)) { + if (event != NULL) { + CloseHandle(event); + InterlockedDecrement(&mutexp->nwaiters); + } + return (DB_TIMEOUT); + } + /* Reduce the event wait if the timeout would happen first. */ + tempspec = timeoutspec; + timespecsub(&tempspec, &now); + DB_TIMESPEC_TO_TIMEOUT(time_left, &tempspec, 0); + time_left /= US_PER_MS; + if (ms > time_left) + ms = time_left; + } + if (event == NULL) { +#ifdef MUTEX_DIAG + QueryPerformanceCounter(&diag_now); + printf(DB_STR_A("2005", + "[%I64d]: Waiting on mutex %p, id %d\n", + "%I64d %p %d"), diag_now.QuadPart, mutexp, mutexp->id); +#endif + InterlockedIncrement(&mutexp->nwaiters); + if ((ret = get_handle(env, mutexp, &event)) != 0) + goto err; + } + if ((ret = WaitForSingleObject(event, ms)) == WAIT_FAILED) { + ret = __os_get_syserr(); + goto err; + } + if ((ms <<= 1) > MS_PER_SEC) + ms = MS_PER_SEC; + + PANIC_CHECK(env); + goto loop; + +err: __db_syserr(env, ret, DB_STR("2006", "Win32 lock failed")); + return (__env_panic(env, __os_posix_err(ret))); +} + +/* + * __db_win32_mutex_init -- + * Initialize a Win32 mutex. + * + * PUBLIC: int __db_win32_mutex_init __P((ENV *, db_mutex_t, u_int32_t)); + */ +int +__db_win32_mutex_init(env, mutex, flags) + ENV *env; + db_mutex_t mutex; + u_int32_t flags; +{ + DB_MUTEX *mutexp; + + mutexp = MUTEXP_SET(env, mutex); + mutexp->id = ((getpid() & 0xffff) << 16) ^ P_TO_UINT32(mutexp); + F_SET(mutexp, flags); + + return (0); +} + +/* + * __db_win32_mutex_lock + * Lock on a mutex, blocking if necessary. + * + * PUBLIC: int __db_win32_mutex_lock __P((ENV *, db_mutex_t, db_timeout_t)); + */ +int +__db_win32_mutex_lock(env, mutex, timeout) + ENV *env; + db_mutex_t mutex; + db_timeout_t timeout; +{ + return (__db_win32_mutex_lock_int(env, mutex, timeout, 1)); +} + +/* + * __db_win32_mutex_trylock + * Try to lock a mutex, returning without waiting if it is busy + * + * PUBLIC: int __db_win32_mutex_trylock __P((ENV *, db_mutex_t)); + */ +int +__db_win32_mutex_trylock(env, mutex) + ENV *env; + db_mutex_t mutex; +{ + return (__db_win32_mutex_lock_int(env, mutex, 0)); +} + +#if defined(HAVE_SHARED_LATCHES) +/* + * __db_win32_mutex_readlock_int + * Try to lock a mutex, possibly waiting if requested and necessary. + */ +int +__db_win32_mutex_readlock_int(env, mutex, nowait) + ENV *env; + db_mutex_t mutex; + int nowait; +{ + DB_ENV *dbenv; + DB_MUTEX *mutexp; + DB_MUTEXMGR *mtxmgr; + DB_MUTEXREGION *mtxregion; + HANDLE event; + u_int32_t nspins; + int ms, ret; + long exch_ret, mtx_val; +#ifdef MUTEX_DIAG + LARGE_INTEGER diag_now; +#endif + dbenv = env->dbenv; + + if (!MUTEX_ON(env) || F_ISSET(dbenv, DB_ENV_NOLOCKING)) + return (0); + + mtxmgr = env->mutex_handle; + mtxregion = mtxmgr->reginfo.primary; + mutexp = MUTEXP_SET(env, mutex); + + CHECK_MTX_THREAD(env, mutexp); + + /* + * See WINCE_ATOMIC_MAGIC definition for details. + * Use sharecount, because the value just needs to be a db_atomic_t + * memory mapped onto the same page as those being Interlocked*. + */ + WINCE_ATOMIC_MAGIC(&mutexp->sharecount); + + event = NULL; + ms = 50; + ret = 0; + /* + * This needs to be initialized, since if mutexp->tas + * is write locked on the first pass, it needs a value. + */ + exch_ret = 0; + +loop: /* Attempt to acquire the resource for N spins. */ + for (nspins = + mtxregion->stat.st_mutex_tas_spins; nspins > 0; --nspins) { + /* + * We can avoid the (expensive) interlocked instructions if + * the mutex is already "set". + */ +retry: mtx_val = atomic_read(&mutexp->sharecount); + if (mtx_val == MUTEX_SHARE_ISEXCLUSIVE) { + if (nowait) + return (DB_LOCK_NOTGRANTED); + + continue; + } else if (!atomic_compare_exchange(env, &mutexp->sharecount, + mtx_val, mtx_val + 1)) { + /* + * Some systems (notably those with newer Intel CPUs) + * need a small pause here. [#6975] + */ + MUTEX_PAUSE + goto retry; + } + +#ifdef HAVE_STATISTICS + if (event == NULL) + ++mutexp->mutex_set_rd_nowait; + else + ++mutexp->mutex_set_rd_wait; +#endif + if (event != NULL) { + CloseHandle(event); + InterlockedDecrement(&mutexp->nwaiters); +#ifdef MUTEX_DIAG + if (ret != WAIT_OBJECT_0) { + QueryPerformanceCounter(&diag_now); + printf(DB_STR_A("2007", + "[%I64d]: Lost signal on mutex %p, " + "id %d, ms %d\n", "%I64d %p %d %d"), + diag_now.QuadPart, mutexp, mutexp->id, ms); + } +#endif + } + +#ifdef DIAGNOSTIC + /* + * We want to switch threads as often as possible. Yield + * every time we get a mutex to ensure contention. + */ + if (F_ISSET(dbenv, DB_ENV_YIELDCPU)) + __os_yield(env, 0, 0); +#endif + + return (0); + } + + /* + * Yield the processor; wait 50 ms initially, up to 1 second. This + * loop is needed to work around a race where the signal from the + * unlocking thread gets lost. We start at 50 ms because it's unlikely + * to happen often and we want to avoid wasting CPU. + */ + if (event == NULL) { +#ifdef MUTEX_DIAG + QueryPerformanceCounter(&diag_now); + printf(DB_STR_A("2008", + "[%I64d]: Waiting on mutex %p, id %d\n", + "%I64d %p %d"), diag_now.QuadPart, mutexp, mutexp->id); +#endif + InterlockedIncrement(&mutexp->nwaiters); + if ((ret = get_handle(env, mutexp, &event)) != 0) + goto err; + } + if ((ret = WaitForSingleObject(event, ms)) == WAIT_FAILED) { + ret = __os_get_syserr(); + goto err; + } + if ((ms <<= 1) > MS_PER_SEC) + ms = MS_PER_SEC; + + PANIC_CHECK(env); + goto loop; + +err: __db_syserr(env, ret, DB_STR("2009", + "Win32 read lock failed")); + return (__env_panic(env, __os_posix_err(ret))); +} + +/* + * __db_win32_mutex_readlock + * Get a shared lock on a latch + * + * PUBLIC: #if defined(HAVE_SHARED_LATCHES) + * PUBLIC: int __db_win32_mutex_readlock __P((ENV *, db_mutex_t)); + * PUBLIC: #endif + */ +int +__db_win32_mutex_readlock(env, mutex) + ENV *env; + db_mutex_t mutex; +{ + return (__db_win32_mutex_readlock_int(env, mutex, 0)); +} + +/* + * __db_win32_mutex_tryreadlock + * Try to a shared lock on a latch + * + * PUBLIC: #if defined(HAVE_SHARED_LATCHES) + * PUBLIC: int __db_win32_mutex_tryreadlock __P((ENV *, db_mutex_t)); + * PUBLIC: #endif + */ +int +__db_win32_mutex_tryreadlock(env, mutex) + ENV *env; + db_mutex_t mutex; +{ + return (__db_win32_mutex_readlock_int(env, mutex, 1)); +} +#endif + +/* + * __db_win32_mutex_unlock -- + * Release a mutex. + * + * PUBLIC: int __db_win32_mutex_unlock __P((ENV *, db_mutex_t)); + */ +int +__db_win32_mutex_unlock(env, mutex) + ENV *env; + db_mutex_t mutex; +{ + DB_ENV *dbenv; + DB_MUTEX *mutexp; + HANDLE event; + int ret; +#ifdef MUTEX_DIAG + LARGE_INTEGER diag_now; +#endif + dbenv = env->dbenv; + + if (!MUTEX_ON(env) || F_ISSET(dbenv, DB_ENV_NOLOCKING)) + return (0); + + mutexp = MUTEXP_SET(env, mutex); + +#ifdef DIAGNOSTIC + if (!MUTEXP_IS_BUSY(mutexp) || !(F_ISSET(mutexp, DB_MUTEX_SHARED) || + F_ISSET(mutexp, DB_MUTEX_LOCKED))) { + __db_errx(env, DB_STR_A("2010", + "Win32 unlock failed: lock already unlocked: mutex %d busy %d", + "%d %d"), mutex, MUTEXP_BUSY_FIELD(mutexp)); + return (__env_panic(env, EACCES)); + } +#endif + /* + * If we have a shared latch, and a read lock (DB_MUTEX_LOCKED is only + * set for write locks), then decrement the latch. If the readlock is + * still held by other threads, just return. Otherwise go ahead and + * notify any waiting threads. + */ +#ifdef HAVE_SHARED_LATCHES + if (F_ISSET(mutexp, DB_MUTEX_SHARED)) { + if (F_ISSET(mutexp, DB_MUTEX_LOCKED)) { + F_CLR(mutexp, DB_MUTEX_LOCKED); + if ((ret = InterlockedExchange( + (interlocked_val)(&atomic_read( + &mutexp->sharecount)), 0)) != + MUTEX_SHARE_ISEXCLUSIVE) { + ret = DB_RUNRECOVERY; + goto err; + } + } else if (InterlockedDecrement( + (interlocked_val)(&atomic_read(&mutexp->sharecount))) > 0) + return (0); + } else +#endif + { + F_CLR(mutexp, DB_MUTEX_LOCKED); + MUTEX_UNSET(&mutexp->tas); + } + + if (mutexp->nwaiters > 0) { + if ((ret = get_handle(env, mutexp, &event)) != 0) + goto err; + +#ifdef MUTEX_DIAG + QueryPerformanceCounter(&diag_now); + printf(DB_STR_A("2011", + "[%I64d]: Signalling mutex %p, id %d\n", + "%I64d %p %d"), diag_now.QuadPart, mutexp, mutexp->id); +#endif + if (!PulseEvent(event)) { + ret = __os_get_syserr(); + CloseHandle(event); + goto err; + } + + CloseHandle(event); + } + + return (0); + +err: __db_syserr(env, ret, DB_STR("2012", "Win32 unlock failed")); + return (__env_panic(env, __os_posix_err(ret))); +} + +/* + * __db_win32_mutex_destroy -- + * Destroy a mutex. + * + * PUBLIC: int __db_win32_mutex_destroy __P((ENV *, db_mutex_t)); + */ +int +__db_win32_mutex_destroy(env, mutex) + ENV *env; + db_mutex_t mutex; +{ + return (0); +} + +#ifndef DB_WINCE +/* + * db_env_set_win_security + * + * Set the SECURITY_ATTRIBUTES to be used by BDB on Windows. + * It should not be called while any BDB mutexes are locked. + * + * EXTERN: #if defined(DB_WIN32) && !defined(DB_WINCE) + * EXTERN: int db_env_set_win_security __P((SECURITY_ATTRIBUTES *sa)); + * EXTERN: #endif + */ +int +db_env_set_win_security(sa) + SECURITY_ATTRIBUTES *sa; +{ + DB_GLOBAL(win_sec_attr) = sa; + return (0); +} +#endif diff -r 000000000000 -r a1985f14b030 src/os/os_abort.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/os/os_abort.c Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,55 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 2005, 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + * $Id$ + */ + +#include "db_config.h" + +#include "db_int.h" + +/* + * __os_abort -- + * + * PUBLIC: void __os_abort __P((ENV *)); + */ +void +__os_abort(env) + ENV *env; +{ + __os_stack(env); /* Try and get a stack trace. */ + +#ifdef HAVE_ABORT + abort(); /* Try and drop core. */ + /* NOTREACHED */ +#endif +#ifdef SIGABRT + (void)raise(SIGABRT); /* Try and drop core. */ +#endif + exit(1); /* Quit anyway. */ + /* NOTREACHED */ +} diff -r 000000000000 -r a1985f14b030 src/os/os_abs.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/os/os_abs.c Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,46 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 1997, 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + * $Id$ + */ + +#include "db_config.h" + +#include "db_int.h" + +/* + * __os_abspath -- + * Return if a path is an absolute path. + * + * PUBLIC: int __os_abspath __P((const char *)); + */ +int +__os_abspath(path) + const char *path; +{ + return (path[0] == '/'); +} diff -r 000000000000 -r a1985f14b030 src/os/os_addrinfo.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/os/os_addrinfo.c Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,201 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 2006, 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + * $Id$ + */ + +#include "db_config.h" + +#include "db_int.h" + +/* + * __os_getaddrinfo and __os_freeaddrinfo wrap the getaddrinfo and freeaddrinfo + * calls, as well as the associated platform dependent error handling, mapping + * the error return to a ANSI C/POSIX error return. + */ + +/* + * __os_getaddrinfo -- + * + * PUBLIC: #if defined(HAVE_REPLICATION_THREADS) + * PUBLIC: int __os_getaddrinfo __P((ENV *, const char *, u_int, + * PUBLIC: const char *, const ADDRINFO *, ADDRINFO **)); + * PUBLIC: #endif + */ +int +__os_getaddrinfo(env, nodename, port, servname, hints, res) + ENV *env; + const char *nodename, *servname; + u_int port; + const ADDRINFO *hints; + ADDRINFO **res; +{ +#ifdef HAVE_GETADDRINFO + int ret; + + if ((ret = getaddrinfo(nodename, servname, hints, res)) == 0) + return (0); + + __db_errx(env, DB_STR_A("0153", + "%s(%u): host lookup failed: %s", "%s %u %s"), + nodename == NULL ? "" : nodename, port, +#ifdef DB_WIN32 + gai_strerrorA(ret)); +#else + gai_strerror(ret)); +#endif + return (__os_posix_err(ret)); +#else + ADDRINFO *answer; + struct hostent *hostaddr; + struct sockaddr_in sin; + u_int32_t tmpaddr; + int ret; + + COMPQUIET(hints, NULL); + COMPQUIET(servname, NULL); + + /* INADDR_NONE is not defined on Solaris 2.6, 2.7 or 2.8. */ +#ifndef INADDR_NONE +#define INADDR_NONE ((u_long)0xffffffff) +#endif + + /* + * Basic implementation of IPv4 component of getaddrinfo. + * Limited to the functionality used by repmgr. + */ + memset(&sin, 0, sizeof(sin)); + sin.sin_family = AF_INET; + if (nodename) { + if (nodename[0] == '\0') + sin.sin_addr.s_addr = htonl(INADDR_ANY); + else if ((tmpaddr = inet_addr(CHAR_STAR_CAST nodename)) != + INADDR_NONE) { + sin.sin_addr.s_addr = tmpaddr; + } else { + hostaddr = gethostbyname(nodename); + if (hostaddr == NULL) { +#ifdef DB_WIN32 + ret = __os_get_neterr(); + __db_syserr(env, ret, DB_STR_A("0154", + "%s(%u): host lookup failed", "%s %u"), + nodename == NULL ? "" : nodename, port); + return (__os_posix_err(ret)); +#else + /* + * Historic UNIX systems used the h_errno + * global variable to return gethostbyname + * errors. The only function we currently + * use that needs h_errno is gethostbyname, + * so we deal with it here. + * + * hstrerror is not available on Solaris 2.6 + * (it is in libresolv but is a private, + * unexported symbol). + */ +#ifdef HAVE_HSTRERROR + __db_errx(env, DB_STR_A("0155", + "%s(%u): host lookup failed: %s", + "%s %u %s"), + nodename == NULL ? "" : nodename, port, + hstrerror(h_errno)); +#else + __db_errx(env, DB_STR_A("0156", + "%s(%u): host lookup failed: %d", + "%s %u %d"), + nodename == NULL ? "" : nodename, port, + h_errno); +#endif + switch (h_errno) { + case HOST_NOT_FOUND: + case NO_DATA: + return (EHOSTUNREACH); + case TRY_AGAIN: + return (EAGAIN); + case NO_RECOVERY: + default: + return (EFAULT); + } + /* NOTREACHED */ +#endif + } + memcpy(&(sin.sin_addr), + hostaddr->h_addr, (size_t)hostaddr->h_length); + } + } else /* No host specified. */ + sin.sin_addr.s_addr = htonl(INADDR_ANY); + sin.sin_port = htons((u_int16_t)port); + + if ((ret = __os_calloc(env, 1, sizeof(ADDRINFO), &answer)) != 0) + return (ret); + if ((ret = __os_malloc(env, sizeof(sin), &answer->ai_addr)) != 0) { + __os_free(env, answer); + return (ret); + } + + answer->ai_family = AF_INET; + answer->ai_protocol = IPPROTO_TCP; + answer->ai_socktype = SOCK_STREAM; + answer->ai_addrlen = sizeof(sin); + memcpy(answer->ai_addr, &sin, sizeof(sin)); + *res = answer; + + return (0); +#endif /* HAVE_GETADDRINFO */ +} + +/* + * __os_freeaddrinfo -- + * + * PUBLIC: #if defined(HAVE_REPLICATION_THREADS) + * PUBLIC: void __os_freeaddrinfo __P((ENV *, ADDRINFO *)); + * PUBLIC: #endif + */ +void +__os_freeaddrinfo(env, ai) + ENV *env; + ADDRINFO *ai; +{ +#ifdef HAVE_GETADDRINFO + COMPQUIET(env, NULL); + + freeaddrinfo(ai); +#else + ADDRINFO *next, *tmpaddr; + + for (next = ai; next != NULL; next = tmpaddr) { + if (next->ai_canonname != NULL) + __os_free(env, next->ai_canonname); + + if (next->ai_addr != NULL) + __os_free(env, next->ai_addr); + + tmpaddr = next->ai_next; + __os_free(env, next); + } +#endif +} diff -r 000000000000 -r a1985f14b030 src/os/os_alloc.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/os/os_alloc.c Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,486 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 1997, 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + * $Id$ + */ + +#include "db_config.h" + +#include "db_int.h" + +#ifdef DIAGNOSTIC +static void __os_guard __P((ENV *)); + +typedef union { + size_t size; + uintmax_t align; +} db_allocinfo_t; +#endif + +/* + * !!! + * Correct for systems that return NULL when you allocate 0 bytes of memory. + * There are several places in DB where we allocate the number of bytes held + * by the key/data item, and it can be 0. Correct here so that malloc never + * returns a NULL for that reason (which behavior is permitted by ANSI). We + * could make these calls macros on non-Alpha architectures (that's where we + * saw the problem), but it's probably not worth the autoconf complexity. + * + * !!! + * Correct for systems that don't set errno when malloc and friends fail. + * + * Out of memory. + * We wish to hold the whole sky, + * But we never will. + */ + +/* + * __os_umalloc -- + * Allocate memory to be used by the application. + * + * Use, in order of preference, the allocation function specified to the + * ENV handle, the allocation function specified as a replacement for + * the library malloc, or the library malloc(). + * + * PUBLIC: int __os_umalloc __P((ENV *, size_t, void *)); + */ +int +__os_umalloc(env, size, storep) + ENV *env; + size_t size; + void *storep; +{ + DB_ENV *dbenv; + int ret; + + dbenv = env == NULL ? NULL : env->dbenv; + + /* Never allocate 0 bytes -- some C libraries don't like it. */ + if (size == 0) + ++size; + + if (dbenv == NULL || dbenv->db_malloc == NULL) { + if (DB_GLOBAL(j_malloc) != NULL) + *(void **)storep = DB_GLOBAL(j_malloc)(size); + else + *(void **)storep = malloc(size); + if (*(void **)storep == NULL) { + /* + * Correct error return, see __os_malloc. + */ + if ((ret = __os_get_errno_ret_zero()) == 0) { + ret = ENOMEM; + __os_set_errno(ENOMEM); + } + __db_err(env, ret, DB_STR_A("0143", "malloc: %lu", + "%lu"), (u_long)size); + return (ret); + } + return (0); + } + + if ((*(void **)storep = dbenv->db_malloc(size)) == NULL) { + __db_errx(env, DB_STR("0144", + "user-specified malloc function returned NULL")); + return (ENOMEM); + } + + return (0); +} + +/* + * __os_urealloc -- + * Allocate memory to be used by the application. + * + * A realloc(3) counterpart to __os_umalloc's malloc(3). + * + * PUBLIC: int __os_urealloc __P((ENV *, size_t, void *)); + */ +int +__os_urealloc(env, size, storep) + ENV *env; + size_t size; + void *storep; +{ + DB_ENV *dbenv; + int ret; + void *ptr; + + dbenv = env == NULL ? NULL : env->dbenv; + ptr = *(void **)storep; + + /* Never allocate 0 bytes -- some C libraries don't like it. */ + if (size == 0) + ++size; + + if (dbenv == NULL || dbenv->db_realloc == NULL) { + if (ptr == NULL) + return (__os_umalloc(env, size, storep)); + + if (DB_GLOBAL(j_realloc) != NULL) + *(void **)storep = DB_GLOBAL(j_realloc)(ptr, size); + else + *(void **)storep = realloc(ptr, size); + if (*(void **)storep == NULL) { + /* + * Correct errno, see __os_realloc. + */ + if ((ret = __os_get_errno_ret_zero()) == 0) { + ret = ENOMEM; + __os_set_errno(ENOMEM); + } + __db_err(env, ret, DB_STR_A("0145", + "realloc: %lu", "%lu"), (u_long)size); + return (ret); + } + return (0); + } + + if ((*(void **)storep = dbenv->db_realloc(ptr, size)) == NULL) { + __db_errx(env, DB_STR("0146", + "User-specified realloc function returned NULL")); + return (ENOMEM); + } + + return (0); +} + +/* + * __os_ufree -- + * Free memory used by the application. + * + * A free(3) counterpart to __os_umalloc's malloc(3). + * + * PUBLIC: void __os_ufree __P((ENV *, void *)); + */ +void +__os_ufree(env, ptr) + ENV *env; + void *ptr; +{ + DB_ENV *dbenv; + + dbenv = env == NULL ? NULL : env->dbenv; + + if (dbenv != NULL && dbenv->db_free != NULL) + dbenv->db_free(ptr); + else if (DB_GLOBAL(j_free) != NULL) + DB_GLOBAL(j_free)(ptr); + else + free(ptr); +} + +/* + * __os_strdup -- + * The strdup(3) function for DB. + * + * PUBLIC: int __os_strdup __P((ENV *, const char *, void *)); + */ +int +__os_strdup(env, str, storep) + ENV *env; + const char *str; + void *storep; +{ + size_t size; + int ret; + void *p; + + *(void **)storep = NULL; + + size = strlen(str) + 1; + if ((ret = __os_malloc(env, size, &p)) != 0) + return (ret); + + memcpy(p, str, size); + + *(void **)storep = p; + return (0); +} + +/* + * __os_calloc -- + * The calloc(3) function for DB. + * + * PUBLIC: int __os_calloc __P((ENV *, size_t, size_t, void *)); + */ +int +__os_calloc(env, num, size, storep) + ENV *env; + size_t num, size; + void *storep; +{ + int ret; + + size *= num; + if ((ret = __os_malloc(env, size, storep)) != 0) + return (ret); + + memset(*(void **)storep, 0, size); + + return (0); +} + +/* + * __os_malloc -- + * The malloc(3) function for DB. + * + * PUBLIC: int __os_malloc __P((ENV *, size_t, void *)); + */ +int +__os_malloc(env, size, storep) + ENV *env; + size_t size; + void *storep; +{ + int ret; + void *p; + + *(void **)storep = NULL; + + /* Never allocate 0 bytes -- some C libraries don't like it. */ + if (size == 0) + ++size; + +#ifdef DIAGNOSTIC + /* Add room for size and a guard byte. */ + size += sizeof(db_allocinfo_t) + 1; +#endif + + if (DB_GLOBAL(j_malloc) != NULL) + p = DB_GLOBAL(j_malloc)(size); + else + p = malloc(size); + if (p == NULL) { + /* + * Some C libraries don't correctly set errno when malloc(3) + * fails. We'd like to 0 out errno before calling malloc, + * but it turns out that setting errno is quite expensive on + * Windows/NT in an MT environment. + */ + if ((ret = __os_get_errno_ret_zero()) == 0) { + ret = ENOMEM; + __os_set_errno(ENOMEM); + } + __db_err(env, ret, DB_STR_A("0147", "malloc: %lu", "%lu"), + (u_long)size); + return (ret); + } + +#ifdef DIAGNOSTIC + /* Overwrite memory. */ + memset(p, CLEAR_BYTE, size); + + /* + * Guard bytes: if #DIAGNOSTIC is defined, we allocate an additional + * byte after the memory and set it to a special value that we check + * for when the memory is free'd. + */ + ((u_int8_t *)p)[size - 1] = CLEAR_BYTE; + + ((db_allocinfo_t *)p)->size = size; + p = &((db_allocinfo_t *)p)[1]; +#endif + *(void **)storep = p; + + return (0); +} + +/* + * __os_realloc -- + * The realloc(3) function for DB. + * + * PUBLIC: int __os_realloc __P((ENV *, size_t, void *)); + */ +int +__os_realloc(env, size, storep) + ENV *env; + size_t size; + void *storep; +{ + int ret; + void *p, *ptr; + + ptr = *(void **)storep; + + /* Never allocate 0 bytes -- some C libraries don't like it. */ + if (size == 0) + ++size; + + /* If we haven't yet allocated anything yet, simply call malloc. */ + if (ptr == NULL) + return (__os_malloc(env, size, storep)); + +#ifdef DIAGNOSTIC + /* Add room for size and a guard byte. */ + size += sizeof(db_allocinfo_t) + 1; + + /* Back up to the real beginning */ + ptr = &((db_allocinfo_t *)ptr)[-1]; + + { + size_t s; + + s = ((db_allocinfo_t *)ptr)->size; + if (((u_int8_t *)ptr)[s - 1] != CLEAR_BYTE) + __os_guard(env); + } +#endif + + /* + * Don't overwrite the original pointer, there are places in DB we + * try to continue after realloc fails. + */ + if (DB_GLOBAL(j_realloc) != NULL) + p = DB_GLOBAL(j_realloc)(ptr, size); + else + p = realloc(ptr, size); + if (p == NULL) { + /* + * Some C libraries don't correctly set errno when malloc(3) + * fails. We'd like to 0 out errno before calling malloc, + * but it turns out that setting errno is quite expensive on + * Windows/NT in an MT environment. + */ + if ((ret = __os_get_errno_ret_zero()) == 0) { + ret = ENOMEM; + __os_set_errno(ENOMEM); + } + __db_err(env, ret, DB_STR_A("0148", "realloc: %lu", "%lu"), + (u_long)size); + return (ret); + } +#ifdef DIAGNOSTIC + ((u_int8_t *)p)[size - 1] = CLEAR_BYTE; /* Initialize guard byte. */ + + ((db_allocinfo_t *)p)->size = size; + p = &((db_allocinfo_t *)p)[1]; +#endif + + *(void **)storep = p; + + return (0); +} + +/* + * __os_free -- + * The free(3) function for DB. + * + * PUBLIC: void __os_free __P((ENV *, void *)); + */ +void +__os_free(env, ptr) + ENV *env; + void *ptr; +{ +#ifdef DIAGNOSTIC + size_t size; +#endif + + /* + * ANSI C requires free(NULL) work. Don't depend on the underlying + * library. + */ + if (ptr == NULL) + return; + +#ifdef DIAGNOSTIC + /* + * Check that the guard byte (one past the end of the memory) is + * still CLEAR_BYTE. + */ + ptr = &((db_allocinfo_t *)ptr)[-1]; + size = ((db_allocinfo_t *)ptr)->size; + if (((u_int8_t *)ptr)[size - 1] != CLEAR_BYTE) + __os_guard(env); + + /* Overwrite memory. */ + if (size != 0) + memset(ptr, CLEAR_BYTE, size); +#else + COMPQUIET(env, NULL); +#endif + + if (DB_GLOBAL(j_free) != NULL) + DB_GLOBAL(j_free)(ptr); + else + free(ptr); +} + +#ifdef DIAGNOSTIC +/* + * __os_guard -- + * Complain and abort. + */ +static void +__os_guard(env) + ENV *env; +{ + __db_errx(env, DB_STR("0149", + "Guard byte incorrect during free")); + __os_abort(env); + /* NOTREACHED */ +} +#endif + +/* + * __ua_memcpy -- + * Copy memory to memory without relying on any kind of alignment. + * + * There are places in DB that we have unaligned data, for example, + * when we've stored a structure in a log record as a DBT, and now + * we want to look at it. Unfortunately, if you have code like: + * + * struct a { + * int x; + * } *p; + * + * void *func_argument; + * int local; + * + * p = (struct a *)func_argument; + * memcpy(&local, p->x, sizeof(local)); + * + * compilers optimize to use inline instructions requiring alignment, + * and records in the log don't have any particular alignment. (This + * isn't a compiler bug, because it's a structure they're allowed to + * assume alignment.) + * + * Casting the memcpy arguments to (u_int8_t *) appears to work most + * of the time, but we've seen examples where it wasn't sufficient + * and there's nothing in ANSI C that requires that work. + * + * PUBLIC: void *__ua_memcpy __P((void *, const void *, size_t)); + */ +void * +__ua_memcpy(dst, src, len) + void *dst; + const void *src; + size_t len; +{ + return ((void *)memcpy(dst, src, len)); +} diff -r 000000000000 -r a1985f14b030 src/os/os_clock.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/os/os_clock.c Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,94 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 2001, 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + * $Id$ + */ + +#include "db_config.h" + +#include "db_int.h" + +/* + * __os_gettime -- + * Return the current time-of-day clock in seconds and nanoseconds. + * + * PUBLIC: void __os_gettime __P((ENV *, db_timespec *, int)); + */ +void +__os_gettime(env, tp, monotonic) + ENV *env; + db_timespec *tp; + int monotonic; +{ + const char *sc; + int ret; + +#if defined(HAVE_CLOCK_GETTIME) +#if defined(HAVE_CLOCK_MONOTONIC) + if (monotonic) + RETRY_CHK((clock_gettime( + CLOCK_MONOTONIC, (struct timespec *)tp)), ret); + else +#endif + RETRY_CHK((clock_gettime( + CLOCK_REALTIME, (struct timespec *)tp)), ret); + + if (ret != 0) { + sc = "clock_gettime"; + goto err; + } +#elif defined(HAVE_GETTIMEOFDAY) + struct timeval v; + + RETRY_CHK((gettimeofday(&v, NULL)), ret); + if (ret != 0) { + sc = "gettimeofday"; + goto err; + } + + tp->tv_sec = v.tv_sec; + tp->tv_nsec = v.tv_usec * NS_PER_US; +#elif defined(HAVE_TIME) + time_t now; + + RETRY_CHK((time(&now) == (time_t)-1 ? 1 : 0), ret); + if (ret != 0) { + sc = "time"; + goto err; + } + + tp->tv_sec = now; + tp->tv_nsec = 0; +#else + NO AVAILABLE CLOCK IMPLEMENTATION +#endif + COMPQUIET(monotonic, 0); + return; + +err: __db_syserr(env, ret, "%s", sc); + (void)__env_panic(env, __os_posix_err(ret)); +} diff -r 000000000000 -r a1985f14b030 src/os/os_config.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/os/os_config.c Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,92 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 1998, 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + * $Id$ + */ + +#include "db_config.h" + +#include "db_int.h" + +/* + * __os_fs_notzero -- + * Return 1 if allocated filesystem blocks are not zeroed. + * + * PUBLIC: int __os_fs_notzero __P((void)); + */ +int +__os_fs_notzero() +{ + /* Most filesystems zero out implicitly created pages. */ + return (0); +} + +/* + * __os_support_direct_io -- + * Return 1 if we support direct I/O. + * + * PUBLIC: int __os_support_direct_io __P((void)); + */ +int +__os_support_direct_io() +{ + int ret; + + ret = 0; + +#ifdef HAVE_O_DIRECT + ret = 1; +#endif +#if defined(HAVE_DIRECTIO) && defined(DIRECTIO_ON) + ret = 1; +#endif + return (ret); +} + +/* + * __os_support_db_register -- + * Return 1 if the system supports DB_REGISTER. + * + * PUBLIC: int __os_support_db_register __P((void)); + */ +int +__os_support_db_register() +{ + return (1); +} + +/* + * __os_support_replication -- + * Return 1 if the system supports replication. + * + * PUBLIC: int __os_support_replication __P((void)); + */ +int +__os_support_replication() +{ + return (1); +} diff -r 000000000000 -r a1985f14b030 src/os/os_cpu.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/os/os_cpu.c Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,69 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 1997, 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + * $Id$ + */ + +#include "db_config.h" + +#include "db_int.h" + +#ifdef HAVE_SYSTEM_INCLUDE_FILES +#if defined(HAVE_PSTAT_GETDYNAMIC) +#include +#endif +#endif + +/* + * __os_cpu_count -- + * Return the number of CPUs. + * + * PUBLIC: u_int32_t __os_cpu_count __P((void)); + */ +u_int32_t +__os_cpu_count() +{ +#if defined(HAVE_PSTAT_GETDYNAMIC) + /* + * HP/UX. + */ + struct pst_dynamic psd; + + return ((u_int32_t)pstat_getdynamic(&psd, + sizeof(psd), (size_t)1, 0) == -1 ? 1 : psd.psd_proc_cnt); +#elif defined(HAVE_SYSCONF) && defined(_SC_NPROCESSORS_ONLN) + /* + * Solaris, Linux. + */ + long nproc; + + nproc = sysconf(_SC_NPROCESSORS_ONLN); + return ((u_int32_t)(nproc > 1 ? nproc : 1)); +#else + return (1); +#endif +} diff -r 000000000000 -r a1985f14b030 src/os/os_ctime.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/os/os_ctime.c Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,69 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 2001, 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + * $Id$ + */ + +#include "db_config.h" + +#include "db_int.h" + +/* + * __os_ctime -- + * Format a time-stamp. + * + * PUBLIC: char *__os_ctime __P((const time_t *, char *)); + */ +char * +__os_ctime(tod, time_buf) + const time_t *tod; + char *time_buf; +{ + time_buf[CTIME_BUFLEN - 1] = '\0'; + + /* + * The ctime_r interface is the POSIX standard, thread-safe version of + * ctime. However, it was implemented in three different ways (with + * and without a buffer length argument, and where the buffer length + * argument was an int vs. a size_t *). Also, you can't depend on a + * return of (char *) from ctime_r, HP-UX 10.XX's version returned an + * int. + */ +#if defined(HAVE_VXWORKS) + { + size_t buflen = CTIME_BUFLEN; + (void)ctime_r(tod, time_buf, &buflen); + } +#elif defined(HAVE_CTIME_R_3ARG) + (void)ctime_r(tod, time_buf, CTIME_BUFLEN); +#elif defined(HAVE_CTIME_R) + (void)ctime_r(tod, time_buf); +#else + (void)strncpy(time_buf, ctime(tod), CTIME_BUFLEN - 1); +#endif + return (time_buf); +} diff -r 000000000000 -r a1985f14b030 src/os/os_dir.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/os/os_dir.c Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,162 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 1997, 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + * $Id$ + */ + +#include "db_config.h" + +#if HAVE_DIRENT_H +# include +# define NAMLEN(dirent) strlen((dirent)->d_name) +#else +# define dirent direct +# define NAMLEN(dirent) (dirent)->d_namlen +# if HAVE_SYS_NDIR_H +# include +# endif +# if HAVE_SYS_DIR_H +# include +# endif +# if HAVE_NDIR_H +# include +# endif +#endif + +#include "db_int.h" + +/* + * __os_dirlist -- + * Return a list of the files in a directory. + * + * PUBLIC: int __os_dirlist __P((ENV *, const char *, int, char ***, int *)); + */ +int +__os_dirlist(env, dir, returndir, namesp, cntp) + ENV *env; + const char *dir; + int returndir, *cntp; + char ***namesp; +{ + DB_ENV *dbenv; + struct dirent *dp; + DIR *dirp; + struct stat sb; + int arraysz, cnt, ret; + char **names, buf[DB_MAXPATHLEN]; + + *namesp = NULL; + *cntp = 0; + + dbenv = env == NULL ? NULL : env->dbenv; + + if (dbenv != NULL && + FLD_ISSET(dbenv->verbose, DB_VERB_FILEOPS | DB_VERB_FILEOPS_ALL)) + __db_msg(env, DB_STR_A("0159", + "fileops: directory list %s", "%s"), dir); + + if (DB_GLOBAL(j_dirlist) != NULL) + return (DB_GLOBAL(j_dirlist)(dir, namesp, cntp)); + + if ((dirp = opendir(CHAR_STAR_CAST dir)) == NULL) + return (__os_get_errno()); + names = NULL; + for (arraysz = cnt = 0; (dp = readdir(dirp)) != NULL;) { + snprintf(buf, sizeof(buf), "%s/%s", dir, dp->d_name); + + RETRY_CHK(stat(buf, &sb), ret); + if (ret != 0) { + ret = __os_posix_err(ret); + /* Ignore entries that no longer exist. */ + if (ret == ENOENT) + continue; + + goto err; + } + + /* + * We return regular files, and optionally return directories + * (except for dot and dot-dot). + * + * Shared memory files are of a different type on QNX, and we + * return those as well. + */ +#ifdef HAVE_QNX + if (!S_ISREG(sb.st_mode) && !S_TYPEISSHM(&sb)) { +#else + if (!S_ISREG(sb.st_mode)) { +#endif + if (!returndir || !S_ISDIR(sb.st_mode)) + continue; + if (dp->d_name[0] == '.' && (dp->d_name[1] == '\0' || + (dp->d_name[1] == '.' && dp->d_name[2] == '\0'))) + continue; + } + + if (cnt >= arraysz) { + arraysz += 100; + if ((ret = __os_realloc(env, + (u_int)arraysz * sizeof(names[0]), &names)) != 0) + goto err; + } + if ((ret = __os_strdup(env, dp->d_name, &names[cnt])) != 0) + goto err; + cnt++; + } + (void)closedir(dirp); + + *namesp = names; + *cntp = cnt; + return (0); + +err: if (names != NULL) + __os_dirfree(env, names, cnt); + if (dirp != NULL) + (void)closedir(dirp); + return (ret); +} + +/* + * __os_dirfree -- + * Free the list of files. + * + * PUBLIC: void __os_dirfree __P((ENV *, char **, int)); + */ +void +__os_dirfree(env, names, cnt) + ENV *env; + char **names; + int cnt; +{ + if (DB_GLOBAL(j_dirfree) != NULL) + DB_GLOBAL(j_dirfree)(names, cnt); + else { + while (cnt > 0) + __os_free(env, names[--cnt]); + __os_free(env, names); + } +} diff -r 000000000000 -r a1985f14b030 src/os/os_errno.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/os/os_errno.c Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,151 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 1999, 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + * $Id$ + */ + +#include "db_config.h" + +#include "db_int.h" + +/* + * __os_get_errno_ret_zero -- + * Return the last system error, including an error of zero. + * + * PUBLIC: int __os_get_errno_ret_zero __P((void)); + */ +int +__os_get_errno_ret_zero() +{ + /* This routine must be able to return the same value repeatedly. */ + return (errno); +} + +/* + * We've seen cases where system calls failed but errno was never set. For + * that reason, __os_get_errno() and __os_get_syserr set errno to EAGAIN if + * it's not already set, to work around the problem. For obvious reasons, + * we can only call this function if we know an error has occurred, that + * is, we can't test the return for a non-zero value after the get call. + * + * __os_get_errno -- + * Return the last ANSI C "errno" value or EAGAIN if the last error + * is zero. + * + * PUBLIC: int __os_get_errno __P((void)); + */ +int +__os_get_errno() +{ + /* This routine must be able to return the same value repeatedly. */ + return (__os_get_syserr()); +} + +#if 0 +/* + * __os_get_neterr -- + * Return the last network-related error or EAGAIN if the last + * error is zero. + * + * PUBLIC: int __os_get_neterr __P((void)); + */ +int +__os_get_neterr() +{ + /* This routine must be able to return the same value repeatedly. */ + return (__os_get_syserr()); +} +#endif + +/* + * __os_get_syserr -- + * Return the last system error or EAGAIN if the last error is zero. + * + * PUBLIC: int __os_get_syserr __P((void)); + */ +int +__os_get_syserr() +{ + /* This routine must be able to return the same value repeatedly. */ + if (errno == 0) + __os_set_errno(EAGAIN); + return (errno); +} + +/* + * __os_set_errno -- + * Set the value of errno. + * + * PUBLIC: void __os_set_errno __P((int)); + */ +void +__os_set_errno(evalue) + int evalue; +{ + /* + * This routine is called by the compatibility interfaces (DB 1.85, + * dbm and hsearch). Force values > 0, that is, not one of DB 2.X + * and later's public error returns. If something bad has happened, + * default to EFAULT -- a nasty return. Otherwise, default to EINVAL. + * As the compatibility APIs aren't included on Windows, the Windows + * version of this routine doesn't need this behavior. + */ + errno = + evalue >= 0 ? evalue : (evalue == DB_RUNRECOVERY ? EFAULT : EINVAL); +} + +/* + * __os_strerror -- + * Return a string associated with the system error. + * + * PUBLIC: char *__os_strerror __P((int, char *, size_t)); + */ +char * +__os_strerror(error, buf, len) + int error; + char *buf; + size_t len; +{ + /* No translation is needed in the POSIX layer. */ + (void)strncpy(buf, strerror(error), len - 1); + buf[len - 1] = '\0'; + + return (buf); +} + +/* + * __os_posix_err + * Convert a system error to a POSIX error. + * + * PUBLIC: int __os_posix_err __P((int)); + */ +int +__os_posix_err(error) + int error; +{ + return (error); +} diff -r 000000000000 -r a1985f14b030 src/os/os_fid.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/os/os_fid.c Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,157 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 1996, 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + * $Id$ + */ + +#include "db_config.h" + +#include "db_int.h" + +/* + * __os_fileid -- + * Return a unique identifier for a file. + * + * PUBLIC: int __os_fileid __P((ENV *, const char *, int, u_int8_t *)); + */ +int +__os_fileid(env, fname, unique_okay, fidp) + ENV *env; + const char *fname; + int unique_okay; + u_int8_t *fidp; +{ + pid_t pid; + size_t i; + u_int32_t tmp; + u_int8_t *p; + +#ifdef HAVE_STAT + struct stat sb; + int ret; + + /* + * The structure of a fileid on a POSIX/UNIX system is: + * + * ino[4] dev[4] unique-ID[4] serial-counter[4] empty[4]. + * + * For real files, which have a backing inode and device, the first + * 8 bytes are filled in and the following bytes are left 0. For + * temporary files, the following 12 bytes are filled in. + * + * Clear the buffer. + */ + memset(fidp, 0, DB_FILE_ID_LEN); + RETRY_CHK((stat(CHAR_STAR_CAST fname, &sb)), ret); + if (ret != 0) { + __db_syserr(env, ret, DB_STR_A("0158", + "stat: %s", "%s"), fname); + return (__os_posix_err(ret)); + } + + /* + * !!! + * Nothing is ever big enough -- on Sparc V9, st_ino, st_dev and the + * time_t types are all 8 bytes. As DB_FILE_ID_LEN is only 20 bytes, + * we convert to a (potentially) smaller fixed-size type and use it. + * + * We don't worry about byte sexing or the actual variable sizes. + * + * When this routine is called from the DB access methods, it's only + * called once -- whatever ID is generated when a database is created + * is stored in the database file's metadata, and that is what is + * saved in the mpool region's information to uniquely identify the + * file. + * + * When called from the mpool layer this routine will be called each + * time a new thread of control wants to share the file, which makes + * things tougher. As far as byte sexing goes, since the mpool region + * lives on a single host, there's no issue of that -- the entire + * region is byte sex dependent. As far as variable sizes go, we make + * the simplifying assumption that 32-bit and 64-bit processes will + * get the same 32-bit values if we truncate any returned 64-bit value + * to a 32-bit value. When we're called from the mpool layer, though, + * we need to be careful not to include anything that isn't + * reproducible for a given file, such as the timestamp or serial + * number. + */ + tmp = (u_int32_t)sb.st_ino; + for (p = (u_int8_t *)&tmp, i = sizeof(u_int32_t); i > 0; --i) + *fidp++ = *p++; + + tmp = (u_int32_t)sb.st_dev; + for (p = (u_int8_t *)&tmp, i = sizeof(u_int32_t); i > 0; --i) + *fidp++ = *p++; +#else + /* + * Use the file name. + * + * XXX + * Cast the first argument, the BREW ARM compiler is unhappy if + * we don't. + */ + (void)strncpy((char *)fidp, fname, DB_FILE_ID_LEN); +#endif /* HAVE_STAT */ + + if (unique_okay) { + /* Add in 32-bits of (hopefully) unique number. */ + __os_unique_id(env, &tmp); + for (p = (u_int8_t *)&tmp, i = sizeof(u_int32_t); i > 0; --i) + *fidp++ = *p++; + + /* + * Initialize/increment the serial number we use to help + * avoid fileid collisions. Note we don't bother with + * locking; it's unpleasant to do from down in here, and + * if we race on this no real harm will be done, since the + * finished fileid has so many other components. + * + * We use the bottom 32-bits of the process ID, hoping they + * are more random than the top 32-bits (should we be on a + * machine with 64-bit process IDs). + * + * We increment by 100000 on each call as a simple way of + * randomizing; simply incrementing seems potentially less + * useful if pids are also simply incremented, since this + * is process-local and we may be one of a set of processes + * starting up. 100000 pushes us out of pid space on most + * 32-bit platforms, and has few interesting properties in + * base 2. + */ + if (DB_GLOBAL(fid_serial) == 0) { + __os_id(env->dbenv, &pid, NULL); + DB_GLOBAL(fid_serial) = (u_int32_t)pid; + } else + DB_GLOBAL(fid_serial) += 100000; + + for (p = (u_int8_t *) + &DB_GLOBAL(fid_serial), i = sizeof(u_int32_t); i > 0; --i) + *fidp++ = *p++; + } + + return (0); +} diff -r 000000000000 -r a1985f14b030 src/os/os_flock.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/os/os_flock.c Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,86 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 1997, 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + * $Id$ + */ + +#include "db_config.h" + +#include "db_int.h" + +/* + * __os_fdlock -- + * Acquire/release a lock on a byte in a file. + * + * PUBLIC: int __os_fdlock __P((ENV *, DB_FH *, off_t, int, int)); + */ +int +__os_fdlock(env, fhp, offset, acquire, nowait) + ENV *env; + DB_FH *fhp; + int acquire, nowait; + off_t offset; +{ +#ifdef HAVE_FCNTL + DB_ENV *dbenv; + struct flock fl; + int ret, t_ret; + + dbenv = env == NULL ? NULL : env->dbenv; + + DB_ASSERT(env, F_ISSET(fhp, DB_FH_OPENED) && fhp->fd != -1); + + if (dbenv != NULL && FLD_ISSET(dbenv->verbose, DB_VERB_FILEOPS_ALL)) + __db_msg(env, DB_STR_A("0138", + "fileops: flock %s %s offset %lu", "%s %s %lu"), fhp->name, + acquire ? DB_STR_P("acquire"): DB_STR_P("release"), + (u_long)offset); + + fl.l_start = offset; + fl.l_len = 1; + fl.l_type = acquire ? F_WRLCK : F_UNLCK; + fl.l_whence = SEEK_SET; + + RETRY_CHK_EINTR_ONLY( + (fcntl(fhp->fd, nowait ? F_SETLK : F_SETLKW, &fl)), ret); + + if (ret == 0) + return (0); + + if ((t_ret = __os_posix_err(ret)) != EACCES && t_ret != EAGAIN) + __db_syserr(env, ret, DB_STR("0139", "fcntl")); + return (t_ret); +#else + COMPQUIET(fhp, NULL); + COMPQUIET(acquire, 0); + COMPQUIET(nowait, 0); + COMPQUIET(offset, 0); + __db_syserr(env, DB_OPNOTSUP, DB_STR("0140", + "advisory file locking unavailable")); + return (DB_OPNOTSUP); +#endif +} diff -r 000000000000 -r a1985f14b030 src/os/os_fsync.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/os/os_fsync.c Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,126 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 1997, 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + * $Id$ + */ + +#include "db_config.h" + +#include "db_int.h" + +#ifdef HAVE_VXWORKS +#include "ioLib.h" + +#define fsync(fd) __vx_fsync(fd) + +int +__vx_fsync(fd) + int fd; +{ + int ret; + + /* + * The results of ioctl are driver dependent. Some will return the + * number of bytes sync'ed. Only if it returns 'ERROR' should we + * flag it. + */ + if ((ret = ioctl(fd, FIOSYNC, 0)) != ERROR) + return (0); + return (ret); +} +#endif + +#ifdef __hp3000s900 +#define fsync(fd) __mpe_fsync(fd) + +int +__mpe_fsync(fd) + int fd; +{ + extern FCONTROL(short, short, void *); + + FCONTROL(_MPE_FILENO(fd), 2, NULL); /* Flush the buffers */ + FCONTROL(_MPE_FILENO(fd), 6, NULL); /* Write the EOF */ + return (0); +} +#endif + +/* + * __os_fsync -- + * Flush a file descriptor. + * + * PUBLIC: int __os_fsync __P((ENV *, DB_FH *)); + */ +int +__os_fsync(env, fhp) + ENV *env; + DB_FH *fhp; +{ + DB_ENV *dbenv; + int ret; + + dbenv = env == NULL ? NULL : env->dbenv; + + DB_ASSERT(env, F_ISSET(fhp, DB_FH_OPENED) && fhp->fd != -1); + + /* + * Do nothing if the file descriptor has been marked as not requiring + * any sync to disk. + */ + if (F_ISSET(fhp, DB_FH_NOSYNC)) + return (0); + + if (dbenv != NULL && FLD_ISSET(dbenv->verbose, DB_VERB_FILEOPS_ALL)) + __db_msg(env, DB_STR_A("0150", "fileops: flush %s", "%s"), + fhp->name); + + if (DB_GLOBAL(j_fsync) != NULL) + ret = DB_GLOBAL(j_fsync)(fhp->fd); + else { +#if defined(F_FULLFSYNC) + RETRY_CHK((fcntl(fhp->fd, F_FULLFSYNC, 0)), ret); + /* + * On OS X, F_FULLSYNC only works on HFS+, so we need to fall + * back to regular fsync on other filesystems. + */ + if (ret == ENOTSUP) + RETRY_CHK((fsync(fhp->fd)), ret); +#elif defined(HAVE_QNX) + ret = __qnx_fsync(fhp); +#elif defined(HAVE_FDATASYNC) + RETRY_CHK((fdatasync(fhp->fd)), ret); +#else + RETRY_CHK((fsync(fhp->fd)), ret); +#endif + } + + if (ret != 0) { + __db_syserr(env, ret, DB_STR("0151", "fsync")); + ret = __os_posix_err(ret); + } + return (ret); +} diff -r 000000000000 -r a1985f14b030 src/os/os_getenv.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/os/os_getenv.c Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,80 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 1997, 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + * $Id$ + */ + +#include "db_config.h" + +#include "db_int.h" + +/* + * __os_getenv -- + * Retrieve an environment variable. + * + * PUBLIC: int __os_getenv __P((ENV *, const char *, char **, size_t)); + */ +int +__os_getenv(env, name, bpp, buflen) + ENV *env; + const char *name; + char **bpp; + size_t buflen; +{ + /* + * If we have getenv, there's a value and the buffer is large enough: + * copy value into the pointer, return 0 + * If we have getenv, there's a value and the buffer is too short: + * set pointer to NULL, return EINVAL + * If we have getenv and there's no value: + * set pointer to NULL, return 0 + * If we don't have getenv: + * set pointer to NULL, return 0 + */ +#ifdef HAVE_GETENV + char *p; + + if ((p = getenv(name)) != NULL) { + if (strlen(p) < buflen) { + (void)strcpy(*bpp, p); + return (0); + } + + *bpp = NULL; + __db_errx(env, DB_STR_A("0157", + "%s: buffer too small to hold environment variable %s", + "%s %s"), name, p); + return (EINVAL); + } +#else + COMPQUIET(env, NULL); + COMPQUIET(name, NULL); + COMPQUIET(buflen, 0); +#endif + *bpp = NULL; + return (0); +} diff -r 000000000000 -r a1985f14b030 src/os/os_handle.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/os/os_handle.c Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,265 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 1998, 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + * $Id$ + */ + +#include "db_config.h" + +#include "db_int.h" + +/* + * __os_openhandle -- + * Open a file, using POSIX 1003.1 open flags. + * + * PUBLIC: int __os_openhandle + * PUBLIC: __P((ENV *, const char *, int, int, DB_FH **)); + */ +int +__os_openhandle(env, name, flags, mode, fhpp) + ENV *env; + const char *name; + int flags, mode; + DB_FH **fhpp; +{ + DB_FH *fhp; + u_int nrepeat, retries; + int fcntl_flags, ret; +#ifdef HAVE_VXWORKS + int newflags; +#endif + /* + * Allocate the file handle and copy the file name. We generally only + * use the name for verbose or error messages, but on systems where we + * can't unlink temporary files immediately, we use the name to unlink + * the temporary file when the file handle is closed. + * + * Lock the ENV handle and insert the new file handle on the list. + */ + if ((ret = __os_calloc(env, 1, sizeof(DB_FH), &fhp)) != 0) + return (ret); + if ((ret = __os_strdup(env, name, &fhp->name)) != 0) + goto err; + if (env != NULL) { + MUTEX_LOCK(env, env->mtx_env); + TAILQ_INSERT_TAIL(&env->fdlist, fhp, q); + MUTEX_UNLOCK(env, env->mtx_env); + F_SET(fhp, DB_FH_ENVLINK); + } + + /* If the application specified an interface, use it. */ + if (DB_GLOBAL(j_open) != NULL) { + if ((fhp->fd = DB_GLOBAL(j_open)(name, flags, mode)) == -1) { + ret = __os_posix_err(__os_get_syserr()); + goto err; + } + goto done; + } + + retries = 0; + for (nrepeat = 1; nrepeat < 4; ++nrepeat) { + ret = 0; +#ifdef HAVE_VXWORKS + /* + * VxWorks does not support O_CREAT on open, you have to use + * creat() instead. (It does not support O_EXCL or O_TRUNC + * either, even though they are defined "for future support".) + * We really want the POSIX behavior that if O_CREAT is set, + * we open if it exists, or create it if it doesn't exist. + * If O_CREAT is specified, single thread and try to open the + * file. If successful, and O_EXCL return EEXIST. If + * unsuccessful call creat and then end single threading. + */ + if (LF_ISSET(O_CREAT)) { + DB_BEGIN_SINGLE_THREAD; + newflags = flags & ~(O_CREAT | O_EXCL); + if ((fhp->fd = open(name, newflags, mode)) != -1) { + /* + * We need to mark the file opened at this + * point so that if we get any error below + * we will properly close the fd we just + * opened on the error path. + */ + F_SET(fhp, DB_FH_OPENED); + if (LF_ISSET(O_EXCL)) { + /* + * If we get here, want O_EXCL create, + * and the file exists. Close and + * return EEXISTS. + */ + DB_END_SINGLE_THREAD; + ret = EEXIST; + goto err; + } + /* + * XXX + * Assume any error means non-existence. + * Unfortunately return values (even for + * non-existence) are driver specific so + * there is no single error we can use to + * verify we truly got the equivalent of + * ENOENT. + */ + } else + fhp->fd = creat(name, newflags); + DB_END_SINGLE_THREAD; + } else + /* FALLTHROUGH */ +#endif +#ifdef __VMS + /* + * !!! + * Open with full sharing on VMS. + * + * We use these flags because they are the ones set by the VMS + * CRTL mmap() call when it opens a file, and we have to be + * able to open files that mmap() has previously opened, e.g., + * when we're joining already existing DB regions. + */ + fhp->fd = open(name, flags, mode, "shr=get,put,upd,del,upi"); +#else + fhp->fd = open(name, flags, mode); +#endif + if (fhp->fd != -1) { + ret = 0; + break; + } + + switch (ret = __os_posix_err(__os_get_syserr())) { + case EMFILE: + case ENFILE: + case ENOSPC: + /* + * If it's a "temporary" error, we retry up to 3 times, + * waiting up to 12 seconds. While it's not a problem + * if we can't open a database, an inability to open a + * log file is cause for serious dismay. + */ + __os_yield(env, nrepeat * 2, 0); + break; + case EAGAIN: + case EBUSY: + case EINTR: + /* + * If an EAGAIN, EBUSY or EINTR, retry immediately for + * DB_RETRY times. + */ + if (++retries < DB_RETRY) + --nrepeat; + break; + default: + /* Open is silent on error. */ + goto err; + } + } + + if (ret == 0) { +#if defined(HAVE_FCNTL_F_SETFD) + /* Deny file descriptor access to any child process. */ + if ((fcntl_flags = fcntl(fhp->fd, F_GETFD)) == -1 || + fcntl(fhp->fd, F_SETFD, fcntl_flags | FD_CLOEXEC) == -1) { + ret = __os_get_syserr(); + __db_syserr(env, ret, DB_STR("0162", + "fcntl(F_SETFD)")); + ret = __os_posix_err(ret); + goto err; + } +#else + COMPQUIET(fcntl_flags, 0); +#endif + +done: F_SET(fhp, DB_FH_OPENED); + *fhpp = fhp; + return (0); + } + +err: (void)__os_closehandle(env, fhp); + return (ret); +} + +/* + * __os_closehandle -- + * Close a file. + * + * PUBLIC: int __os_closehandle __P((ENV *, DB_FH *)); + */ +int +__os_closehandle(env, fhp) + ENV *env; + DB_FH *fhp; +{ + DB_ENV *dbenv; + int ret; + + ret = 0; + + /* + * If we linked the DB_FH handle into the ENV, it needs to be + * unlinked. + */ + DB_ASSERT(env, env != NULL || !F_ISSET(fhp, DB_FH_ENVLINK)); + + if (env != NULL) { + dbenv = env->dbenv; + if (fhp->name != NULL && FLD_ISSET( + dbenv->verbose, DB_VERB_FILEOPS | DB_VERB_FILEOPS_ALL)) + __db_msg(env, DB_STR_A("0163", + "fileops: close %s", "%s"), fhp->name); + + if (F_ISSET(fhp, DB_FH_ENVLINK)) { + /* + * Lock the ENV handle and remove this file + * handle from the list. + */ + MUTEX_LOCK(env, env->mtx_env); + TAILQ_REMOVE(&env->fdlist, fhp, q); + MUTEX_UNLOCK(env, env->mtx_env); + } + } + + /* Discard any underlying system file reference. */ + if (F_ISSET(fhp, DB_FH_OPENED)) { + if (DB_GLOBAL(j_close) != NULL) + ret = DB_GLOBAL(j_close)(fhp->fd); + else + RETRY_CHK((close(fhp->fd)), ret); + if (ret != 0) { + __db_syserr(env, ret, DB_STR("0164", "close")); + ret = __os_posix_err(ret); + } + } + + /* Unlink the file if we haven't already done so. */ + if (F_ISSET(fhp, DB_FH_UNLINK)) + (void)__os_unlink(env, fhp->name, 0); + + if (fhp->name != NULL) + __os_free(env, fhp->name); + __os_free(env, fhp); + + return (ret); +} diff -r 000000000000 -r a1985f14b030 src/os/os_map.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/os/os_map.c Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,629 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 1996, 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + * $Id$ + */ + +#include "db_config.h" + +#include "db_int.h" + +#ifdef HAVE_SYSTEM_INCLUDE_FILES +#ifdef HAVE_MMAP +#include +#endif + +#ifdef HAVE_SHMGET +#include +#include +#endif +#endif + +#ifdef HAVE_MMAP +static int __os_map __P((ENV *, char *, DB_FH *, size_t, int, int, void **)); +#endif +#ifdef HAVE_SHMGET +static int __shm_mode __P((ENV *)); +#else +static int __no_system_mem __P((ENV *)); +#endif + +/* + * __os_attach -- + * Create/join a shared memory region. + * + * PUBLIC: int __os_attach __P((ENV *, REGINFO *, REGION *)); + */ +int +__os_attach(env, infop, rp) + ENV *env; + REGINFO *infop; + REGION *rp; +{ + DB_ENV *dbenv; + int create_ok, ret; + + /* + * We pass a DB_ENV handle to the user's replacement map function, + * so there must be a valid handle. + */ + DB_ASSERT(env, env != NULL && env->dbenv != NULL); + dbenv = env->dbenv; + + if (DB_GLOBAL(j_region_map) != NULL) { + /* + * We have to find out if the region is being created. Ask + * the underlying map function, and use the REGINFO structure + * to pass that information back to our caller. + */ + create_ok = F_ISSET(infop, REGION_CREATE) ? 1 : 0; + ret = DB_GLOBAL(j_region_map) + (dbenv, infop->name, rp->max, &create_ok, &infop->addr); + if (create_ok) + F_SET(infop, REGION_CREATE); + else + F_CLR(infop, REGION_CREATE); + return (ret); + } + + if (F_ISSET(env, ENV_SYSTEM_MEM)) { + /* + * If the region is in system memory on UNIX, we use shmget(2). + * + * !!! + * There exist spinlocks that don't work in shmget memory, e.g., + * the HP/UX msemaphore interface. If we don't have locks that + * will work in shmget memory, we better be private and not be + * threaded. If we reach this point, we know we're public, so + * it's an error. + */ +#if defined(HAVE_MUTEX_HPPA_MSEM_INIT) + __db_errx(env, DB_STR("0114", + "architecture does not support locks inside system shared memory")); + return (EINVAL); +#endif +#if defined(HAVE_SHMGET) + { + key_t segid; + int id, mode; + + /* + * We could potentially create based on REGION_CREATE_OK, but + * that's dangerous -- we might get crammed in sideways if + * some of the expected regions exist but others do not. Also, + * if the requested size differs from an existing region's + * actual size, then all sorts of nasty things can happen. + * Basing create solely on REGION_CREATE is much safer -- a + * recovery will get us straightened out. + */ + if (F_ISSET(infop, REGION_CREATE)) { + /* + * The application must give us a base System V IPC key + * value. Adjust that value based on the region's ID, + * and correct so the user's original value appears in + * the ipcs output. + */ + if (dbenv->shm_key == INVALID_REGION_SEGID) { + __db_errx(env, DB_STR("0115", + "no base system shared memory ID specified")); + return (EINVAL); + } + + /* + * !!! + * The BDB API takes a "long" as the base segment ID, + * then adds an unsigned 32-bit value and stores it + * in a key_t. Wrong, admittedly, but not worth an + * API change to fix. + */ + segid = (key_t) + ((u_long)dbenv->shm_key + (infop->id - 1)); + + /* + * If map to an existing region, assume the application + * crashed and we're restarting. Delete the old region + * and re-try. If that fails, return an error, the + * application will have to select a different segment + * ID or clean up some other way. + */ + if ((id = shmget(segid, 0, 0)) != -1) { + (void)shmctl(id, IPC_RMID, NULL); + if ((id = shmget(segid, 0, 0)) != -1) { + __db_errx(env, DB_STR_A("0116", + "shmget: key: %ld: shared system memory region already exists", + "%ld"), (long)segid); + return (EAGAIN); + } + } + + /* + * Map the DbEnv::open method file mode permissions to + * shmget call permissions. + */ + mode = IPC_CREAT | __shm_mode(env); + if ((id = shmget(segid, rp->max, mode)) == -1) { + ret = __os_get_syserr(); + __db_syserr(env, ret, DB_STR_A("0117", + "shmget: key: %ld: unable to create shared system memory region", + "%ld"), (long)segid); + return (__os_posix_err(ret)); + } + rp->size = rp->max; + rp->segid = id; + } else + id = rp->segid; + + if ((infop->addr = shmat(id, NULL, 0)) == (void *)-1) { + infop->addr = NULL; + ret = __os_get_syserr(); + __db_syserr(env, ret, DB_STR_A("0118", + "shmat: id %d: unable to attach to shared system memory region", + "%d"), id); + return (__os_posix_err(ret)); + } + + /* Optionally lock the memory down. */ + if (F_ISSET(env, ENV_LOCKDOWN)) { +#ifdef HAVE_SHMCTL_SHM_LOCK + ret = shmctl( + id, SHM_LOCK, NULL) == 0 ? 0 : __os_get_syserr(); +#else + ret = DB_OPNOTSUP; +#endif + if (ret != 0) { + __db_syserr(env, ret, DB_STR_A("0119", + "shmctl/SHM_LOCK: id %d: unable to lock down shared memory region", + "%d"), id); + return (__os_posix_err(ret)); + } + } + + return (0); + } +#else + return (__no_system_mem(env)); +#endif + } + +#ifdef HAVE_MMAP + { + infop->fhp = NULL; + + /* + * Try to open/create the shared region file. We DO NOT need to ensure + * that multiple threads/processes attempting to simultaneously create + * the region are properly ordered, our caller has already taken care + * of that. + */ + if ((ret = __os_open(env, infop->name, 0, + DB_OSO_REGION | + (F_ISSET(infop, REGION_CREATE_OK) ? DB_OSO_CREATE : 0), + env->db_mode, &infop->fhp)) != 0) + __db_err(env, ret, "%s", infop->name); + + /* + * If we created the file, grow it before mapping it in. We really want + * to avoid touching the buffer cache after mmap() is called, doing + * anything else confuses the hell out of systems without merged + * VM/buffer cache systems, or, more to the point, *badly* merged + * VM/buffer cache systems. + */ + if (rp->max < rp->size) + rp->max = rp->size; + if (ret == 0 && F_ISSET(infop, REGION_CREATE)) { + if (F_ISSET(dbenv, DB_ENV_REGION_INIT)) + ret = __db_file_write(env, infop->fhp, + rp->size / MEGABYTE, rp->size % MEGABYTE, 0x00); + else + ret = __db_file_extend(env, infop->fhp, rp->size); + } + + /* Map the file in. */ + if (ret == 0) + ret = __os_map(env, + infop->name, infop->fhp, rp->max, 1, 0, &infop->addr); + + if (ret != 0 && infop->fhp != NULL) { + (void)__os_closehandle(env, infop->fhp); + infop->fhp = NULL; + } + + return (ret); + } +#else + COMPQUIET(infop, NULL); + COMPQUIET(rp, NULL); + __db_errx(env, DB_STR("0120", + "architecture lacks mmap(2), shared environments not possible")); + return (DB_OPNOTSUP); +#endif +} + +/* + * __os_detach -- + * Detach from a shared memory region. + * + * PUBLIC: int __os_detach __P((ENV *, REGINFO *, int)); + */ +int +__os_detach(env, infop, destroy) + ENV *env; + REGINFO *infop; + int destroy; +{ + DB_ENV *dbenv; + REGION *rp; + int ret; + + /* + * We pass a DB_ENV handle to the user's replacement unmap function, + * so there must be a valid handle. + */ + DB_ASSERT(env, env != NULL && env->dbenv != NULL); + dbenv = env->dbenv; + + rp = infop->rp; + + /* If the user replaced the unmap call, call through their interface. */ + if (DB_GLOBAL(j_region_unmap) != NULL) + return (DB_GLOBAL(j_region_unmap)(dbenv, infop->addr)); + + if (F_ISSET(env, ENV_SYSTEM_MEM)) { +#ifdef HAVE_SHMGET + int segid; + + /* + * We may be about to remove the memory referenced by rp, + * save the segment ID, and (optionally) wipe the original. + */ + segid = rp->segid; + if (destroy) + rp->segid = INVALID_REGION_SEGID; + + if (shmdt(infop->addr) != 0) { + ret = __os_get_syserr(); + __db_syserr(env, ret, DB_STR("0121", "shmdt")); + return (__os_posix_err(ret)); + } + + if (destroy && shmctl(segid, IPC_RMID, + NULL) != 0 && (ret = __os_get_syserr()) != EINVAL) { + __db_syserr(env, ret, DB_STR_A("0122", + "shmctl: id %d: unable to delete system shared memory region", + "%d"), segid); + return (__os_posix_err(ret)); + } + + return (0); +#else + return (__no_system_mem(env)); +#endif + } + +#ifdef HAVE_MMAP +#ifdef HAVE_MUNLOCK + if (F_ISSET(env, ENV_LOCKDOWN)) + (void)munlock(infop->addr, rp->max); +#endif + if (infop->fhp != NULL) { + ret = __os_closehandle(env, infop->fhp); + infop->fhp = NULL; + if (ret != 0) + return (ret); + } + + if (munmap(infop->addr, rp->max) != 0) { + ret = __os_get_syserr(); + __db_syserr(env, ret, DB_STR("0123", "munmap")); + return (__os_posix_err(ret)); + } + + if (destroy && (ret = __os_unlink(env, infop->name, 1)) != 0) + return (ret); + + return (0); +#else + COMPQUIET(destroy, 0); + COMPQUIET(ret, 0); + return (EINVAL); +#endif +} + +/* + * __os_mapfile -- + * Map in a shared memory file. + * + * PUBLIC: int __os_mapfile __P((ENV *, char *, DB_FH *, size_t, int, void **)); + */ +int +__os_mapfile(env, path, fhp, len, is_rdonly, addrp) + ENV *env; + char *path; + DB_FH *fhp; + int is_rdonly; + size_t len; + void **addrp; +{ +#if defined(HAVE_MMAP) && !defined(HAVE_QNX) + DB_ENV *dbenv; + + /* If the user replaced the map call, call through their interface. */ + if (DB_GLOBAL(j_file_map) != NULL) { + /* + * We pass a DB_ENV handle to the user's replacement map + * function, so there must be a valid handle. + */ + DB_ASSERT(env, env != NULL && env->dbenv != NULL); + dbenv = env->dbenv; + + return ( + DB_GLOBAL(j_file_map)(dbenv, path, len, is_rdonly, addrp)); + } + + return (__os_map(env, path, fhp, len, 0, is_rdonly, addrp)); +#else + COMPQUIET(env, NULL); + COMPQUIET(path, NULL); + COMPQUIET(fhp, NULL); + COMPQUIET(is_rdonly, 0); + COMPQUIET(len, 0); + COMPQUIET(addrp, NULL); + return (DB_OPNOTSUP); +#endif +} + +/* + * __os_unmapfile -- + * Unmap the shared memory file. + * + * PUBLIC: int __os_unmapfile __P((ENV *, void *, size_t)); + */ +int +__os_unmapfile(env, addr, len) + ENV *env; + void *addr; + size_t len; +{ + DB_ENV *dbenv; + int ret; + + /* + * We pass a DB_ENV handle to the user's replacement unmap function, + * so there must be a valid handle. + */ + DB_ASSERT(env, env != NULL && env->dbenv != NULL); + dbenv = env->dbenv; + + if (FLD_ISSET(dbenv->verbose, DB_VERB_FILEOPS | DB_VERB_FILEOPS_ALL)) + __db_msg(env, DB_STR("0124", "fileops: munmap")); + + /* If the user replaced the map call, call through their interface. */ + if (DB_GLOBAL(j_file_unmap) != NULL) + return (DB_GLOBAL(j_file_unmap)(dbenv, addr)); + +#ifdef HAVE_MMAP +#ifdef HAVE_MUNLOCK + if (F_ISSET(env, ENV_LOCKDOWN)) + RETRY_CHK((munlock(addr, len)), ret); + /* + * !!! + * The return value is ignored. + */ +#else + COMPQUIET(env, NULL); +#endif + RETRY_CHK((munmap(addr, len)), ret); + ret = __os_posix_err(ret); +#else + COMPQUIET(env, NULL); + ret = EINVAL; +#endif + return (ret); +} + +#ifdef HAVE_MMAP +/* + * __os_map -- + * Call the mmap(2) function. + */ +static int +__os_map(env, path, fhp, len, is_region, is_rdonly, addrp) + ENV *env; + char *path; + DB_FH *fhp; + int is_region, is_rdonly; + size_t len; + void **addrp; +{ + DB_ENV *dbenv; + int flags, prot, ret; + void *p; + + /* + * We pass a DB_ENV handle to the user's replacement map function, + * so there must be a valid handle. + */ + DB_ASSERT(env, env != NULL && env->dbenv != NULL); + dbenv = env->dbenv; + + if (FLD_ISSET(dbenv->verbose, DB_VERB_FILEOPS | DB_VERB_FILEOPS_ALL)) + __db_msg(env, DB_STR_A("0125", "fileops: mmap %s", + "%s"), path); + + DB_ASSERT(env, F_ISSET(fhp, DB_FH_OPENED) && fhp->fd != -1); + + /* + * If it's read-only, it's private, and if it's not, it's shared. + * Don't bother with an additional parameter. + */ + flags = is_rdonly ? MAP_PRIVATE : MAP_SHARED; + +#ifdef MAP_FILE + /* + * Historically, MAP_FILE was required for mapping regular files, + * even though it was the default. Some systems have it, some + * don't, some that have it set it to 0. + */ + flags |= MAP_FILE; +#endif + + /* + * I know of no systems that implement the flag to tell the system + * that the region contains semaphores, but it's not an unreasonable + * thing to do, and has been part of the design since forever. I + * don't think anyone will object, but don't set it for read-only + * files, it doesn't make sense. + */ +#ifdef MAP_HASSEMAPHORE + if (is_region && !is_rdonly) + flags |= MAP_HASSEMAPHORE; +#else + COMPQUIET(is_region, 0); +#endif + + /* + * FreeBSD: + * Causes data dirtied via this VM map to be flushed to physical media + * only when necessary (usually by the pager) rather then gratuitously. + * Typically this prevents the update daemons from flushing pages + * dirtied through such maps and thus allows efficient sharing of + * memory across unassociated processes using a file-backed shared + * memory map. + */ +#ifdef MAP_NOSYNC + flags |= MAP_NOSYNC; +#endif + + prot = PROT_READ | (is_rdonly ? 0 : PROT_WRITE); + + /* + * XXX + * Work around a bug in the VMS V7.1 mmap() implementation. To map + * a file into memory on VMS it needs to be opened in a certain way, + * originally. To get the file opened in that certain way, the VMS + * mmap() closes the file and re-opens it. When it does this, it + * doesn't flush any caches out to disk before closing. The problem + * this causes us is that when the memory cache doesn't get written + * out, the file isn't big enough to match the memory chunk and the + * mmap() call fails. This call to fsync() fixes the problem. DEC + * thinks this isn't a bug because of language in XPG5 discussing user + * responsibility for on-disk and in-memory synchronization. + */ +#ifdef VMS + if (__os_fsync(env, fhp) == -1) + return (__os_posix_err(__os_get_syserr())); +#endif + + /* MAP_FAILED was not defined in early mmap implementations. */ +#ifndef MAP_FAILED +#define MAP_FAILED -1 +#endif + if ((p = mmap(NULL, + len, prot, flags, fhp->fd, (off_t)0)) == (void *)MAP_FAILED) { + ret = __os_get_syserr(); + __db_syserr(env, ret, DB_STR("0126", "mmap")); + return (__os_posix_err(ret)); + } + + /* + * If it's a region, we want to make sure that the memory isn't paged. + * For example, Solaris will page large mpools because it thinks that + * I/O buffer memory is more important than we are. The mlock system + * call may or may not succeed (mlock is restricted to the super-user + * on some systems). Currently, the only other use of mmap in DB is + * to map read-only databases -- we don't want them paged, either, so + * the call isn't conditional. + */ + if (F_ISSET(env, ENV_LOCKDOWN)) { +#ifdef HAVE_MLOCK + ret = mlock(p, len) == 0 ? 0 : __os_get_syserr(); +#else + ret = DB_OPNOTSUP; +#endif + if (ret != 0) { + __db_syserr(env, ret, DB_STR("0127", "mlock")); + return (__os_posix_err(ret)); + } + } + + *addrp = p; + return (0); +} +#endif + +#ifdef HAVE_SHMGET +#ifndef SHM_R +#define SHM_R 0400 +#endif +#ifndef SHM_W +#define SHM_W 0200 +#endif + +/* + * __shm_mode -- + * Map the DbEnv::open method file mode permissions to shmget call + * permissions. + */ +static int +__shm_mode(env) + ENV *env; +{ + int mode; + + /* Default to r/w owner, r/w group. */ + if (env->db_mode == 0) + return (SHM_R | SHM_W | SHM_R >> 3 | SHM_W >> 3); + + mode = 0; + if (env->db_mode & S_IRUSR) + mode |= SHM_R; + if (env->db_mode & S_IWUSR) + mode |= SHM_W; + if (env->db_mode & S_IRGRP) + mode |= SHM_R >> 3; + if (env->db_mode & S_IWGRP) + mode |= SHM_W >> 3; + if (env->db_mode & S_IROTH) + mode |= SHM_R >> 6; + if (env->db_mode & S_IWOTH) + mode |= SHM_W >> 6; + return (mode); +} +#else +/* + * __no_system_mem -- + * No system memory environments error message. + */ +static int +__no_system_mem(env) + ENV *env; +{ + __db_errx(env, DB_STR("0128", + "architecture doesn't support environments in system memory")); + return (DB_OPNOTSUP); +} +#endif /* HAVE_SHMGET */ diff -r 000000000000 -r a1985f14b030 src/os/os_mkdir.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/os/os_mkdir.c Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,74 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 1997, 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + * $Id$ + */ + +#include "db_config.h" + +#include "db_int.h" + +/* + * __os_mkdir -- + * Create a directory. + * + * PUBLIC: int __os_mkdir __P((ENV *, const char *, int)); + */ +int +__os_mkdir(env, name, mode) + ENV *env; + const char *name; + int mode; +{ + DB_ENV *dbenv; + int ret; + + dbenv = env == NULL ? NULL : env->dbenv; + if (dbenv != NULL && + FLD_ISSET(dbenv->verbose, DB_VERB_FILEOPS | DB_VERB_FILEOPS_ALL)) + __db_msg(env, DB_STR_A("0129", "fileops: mkdir %s", + "%s"), name); + + /* Make the directory, with paranoid permissions. */ +#if defined(HAVE_VXWORKS) + RETRY_CHK((mkdir(CHAR_STAR_CAST name)), ret); +#else + RETRY_CHK((mkdir(name, DB_MODE_700)), ret); +#endif + if (ret != 0) + return (__os_posix_err(ret)); + + /* Set the absolute permissions, if specified. */ +#if !defined(HAVE_VXWORKS) + if (mode != 0) { + RETRY_CHK((chmod(name, mode)), ret); + if (ret != 0) + ret = __os_posix_err(ret); + } +#endif + return (ret); +} diff -r 000000000000 -r a1985f14b030 src/os/os_open.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/os/os_open.c Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,184 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 1997, 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + * $Id$ + */ + +#include "db_config.h" + +#include "db_int.h" + +/* + * __os_open -- + * Open a file descriptor (including page size and log size information). + * + * PUBLIC: int __os_open __P((ENV *, + * PUBLIC: const char *, u_int32_t, u_int32_t, int, DB_FH **)); + */ +int +__os_open(env, name, page_size, flags, mode, fhpp) + ENV *env; + const char *name; + u_int32_t page_size, flags; + int mode; + DB_FH **fhpp; +{ + DB_ENV *dbenv; + DB_FH *fhp; + int oflags, ret; + + COMPQUIET(page_size, 0); + + dbenv = env == NULL ? NULL : env->dbenv; + *fhpp = NULL; + oflags = 0; + + if (dbenv != NULL && + FLD_ISSET(dbenv->verbose, DB_VERB_FILEOPS | DB_VERB_FILEOPS_ALL)) + __db_msg(env, DB_STR_A("0152", + "fileops: open %s", "%s"), name); + +#undef OKFLAGS +#define OKFLAGS \ + (DB_OSO_ABSMODE | DB_OSO_CREATE | DB_OSO_DIRECT | DB_OSO_DSYNC |\ + DB_OSO_EXCL | DB_OSO_RDONLY | DB_OSO_REGION | DB_OSO_SEQ | \ + DB_OSO_TEMP | DB_OSO_TRUNC) + if ((ret = __db_fchk(env, "__os_open", flags, OKFLAGS)) != 0) + return (ret); + +#if defined(O_BINARY) + /* + * If there's a binary-mode open flag, set it, we never want any + * kind of translation. Some systems do translations by default, + * e.g., with Cygwin, the default mode for an open() is set by the + * mode of the mount that underlies the file. + */ + oflags |= O_BINARY; +#endif + + /* + * DB requires the POSIX 1003.1 semantic that two files opened at the + * same time with DB_OSO_CREATE/O_CREAT and DB_OSO_EXCL/O_EXCL flags + * set return an EEXIST failure in at least one. + */ + if (LF_ISSET(DB_OSO_CREATE)) + oflags |= O_CREAT; + + if (LF_ISSET(DB_OSO_EXCL)) + oflags |= O_EXCL; + +#ifdef HAVE_O_DIRECT + if (LF_ISSET(DB_OSO_DIRECT)) + oflags |= O_DIRECT; +#endif +#ifdef O_DSYNC + if (LF_ISSET(DB_OSO_DSYNC)) + oflags |= O_DSYNC; +#endif + + if (LF_ISSET(DB_OSO_RDONLY)) + oflags |= O_RDONLY; + else + oflags |= O_RDWR; + + if (LF_ISSET(DB_OSO_TRUNC)) + oflags |= O_TRUNC; + + /* + * Undocumented feature: allow applications to create intermediate + * directories whenever a file is opened. + */ + if (dbenv != NULL && + env->dir_mode != 0 && LF_ISSET(DB_OSO_CREATE) && + (ret = __db_mkpath(env, name)) != 0) + return (ret); + + /* Open the file. */ +#ifdef HAVE_QNX + if (LF_ISSET(DB_OSO_REGION)) + ret = __os_qnx_region_open(env, name, oflags, mode, &fhp); + else +#endif + ret = __os_openhandle(env, name, oflags, mode, &fhp); + if (ret != 0) + return (ret); + + if (LF_ISSET(DB_OSO_REGION)) + F_SET(fhp, DB_FH_REGION); +#ifdef HAVE_FCHMOD + /* + * If the code using Berkeley DB is a library, that code may not be able + * to control the application's umask value. Allow applications to set + * absolute file modes. We can't fix the race between file creation and + * the fchmod call -- we can't modify the process' umask here since the + * process may be multi-threaded and the umask value is per-process, not + * per-thread. + */ + if (LF_ISSET(DB_OSO_CREATE) && LF_ISSET(DB_OSO_ABSMODE)) + (void)fchmod(fhp->fd, mode); +#endif + +#ifdef O_DSYNC + /* + * If we can configure the file descriptor to flush on write, the + * file descriptor does not need to be explicitly sync'd. + */ + if (LF_ISSET(DB_OSO_DSYNC)) + F_SET(fhp, DB_FH_NOSYNC); +#endif + +#if defined(HAVE_DIRECTIO) && defined(DIRECTIO_ON) + /* + * The Solaris C library includes directio, but you have to set special + * compile flags to #define DIRECTIO_ON. Require both in order to call + * directio. + */ + if (LF_ISSET(DB_OSO_DIRECT)) + (void)directio(fhp->fd, DIRECTIO_ON); +#endif + + /* + * Delete any temporary file. + * + * !!! + * There's a race here, where we've created a file and we crash before + * we can unlink it. Temporary files aren't common in DB, regardless, + * it's not a security problem because the file is empty. There's no + * reasonable way to avoid the race (playing signal games isn't worth + * the portability nightmare), so we just live with it. + */ + if (LF_ISSET(DB_OSO_TEMP)) { +#if defined(HAVE_UNLINK_WITH_OPEN_FAILURE) || defined(CONFIG_TEST) + F_SET(fhp, DB_FH_UNLINK); +#else + (void)__os_unlink(env, name, 0); +#endif + } + + *fhpp = fhp; + return (0); +} diff -r 000000000000 -r a1985f14b030 src/os/os_path.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/os/os_path.c Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,49 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 1997, 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + * $Id$ + */ + +#include "db_config.h" + +#include "db_int.h" +/* + * __os_concat_path -- + * Concatenate two elements of a path. + * PUBLIC: int __os_concat_path __P((char *, + * PUBLIC: size_t, const char *, const char *)); + */ +int __os_concat_path(dest, destsize, path, file) + char *dest; + size_t destsize; + const char *path, *file; +{ + if ((size_t)snprintf(dest, destsize, + "%s%c%s", path, PATH_SEPARATOR[0], file) >= destsize) + return (EINVAL); + return (0); +} diff -r 000000000000 -r a1985f14b030 src/os/os_pid.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/os/os_pid.c Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,85 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 2001, 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + * $Id$ + */ + +#include "db_config.h" + +#include "db_int.h" + +/* + * __os_id -- + * Return the current process ID. + * + * PUBLIC: void __os_id __P((DB_ENV *, pid_t *, db_threadid_t*)); + */ +void +__os_id(dbenv, pidp, tidp) + DB_ENV *dbenv; + pid_t *pidp; + db_threadid_t *tidp; +{ + /* + * We can't depend on dbenv not being NULL, this routine is called + * from places where there's no DB_ENV handle. + * + * We cache the pid in the ENV handle, getting the process ID is a + * fairly slow call on lots of systems. + */ + if (pidp != NULL) { + if (dbenv == NULL) { +#if defined(HAVE_VXWORKS) + *pidp = taskIdSelf(); +#else + *pidp = getpid(); +#endif + } else + *pidp = dbenv->env->pid_cache; + } + +/* + * When building on MinGW, we define both HAVE_PTHREAD_SELF and DB_WIN32, + * and we are using pthreads instead of Windows threads implementation. + * So here, we need to check the thread implementations before checking + * the platform. + */ + if (tidp != NULL) { +#if defined(HAVE_PTHREAD_SELF) + *tidp = pthread_self(); +#elif defined(HAVE_MUTEX_UI_THREADS) + *tidp = thr_self(); +#elif defined(DB_WIN32) + *tidp = GetCurrentThreadId(); +#else + /* + * Default to just getpid. + */ + DB_THREADID_INIT(*tidp); +#endif + } +} diff -r 000000000000 -r a1985f14b030 src/os/os_rename.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/os/os_rename.c Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,75 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 1997, 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + * $Id$ + */ + +#include "db_config.h" + +#include "db_int.h" + +/* + * __os_rename -- + * Rename a file. + * + * PUBLIC: int __os_rename __P((ENV *, + * PUBLIC: const char *, const char *, u_int32_t)); + */ +int +__os_rename(env, oldname, newname, silent) + ENV *env; + const char *oldname, *newname; + u_int32_t silent; +{ + DB_ENV *dbenv; + int ret; + + dbenv = env == NULL ? NULL : env->dbenv; + if (dbenv != NULL && + FLD_ISSET(dbenv->verbose, DB_VERB_FILEOPS | DB_VERB_FILEOPS_ALL)) + __db_msg(env, DB_STR_A("0168", "fileops: rename %s to %s", + "%s %s"), oldname, newname); + + LAST_PANIC_CHECK_BEFORE_IO(env); + + if (DB_GLOBAL(j_rename) != NULL) + ret = DB_GLOBAL(j_rename)(oldname, newname); + else + RETRY_CHK((rename(oldname, newname)), ret); + + /* + * If "silent" is not set, then errors are OK and we should not output + * an error message. + */ + if (ret != 0) { + if (!silent) + __db_syserr(env, ret, DB_STR_A("0169", + "rename %s %s", "%s %s"), oldname, newname); + ret = __os_posix_err(ret); + } + return (ret); +} diff -r 000000000000 -r a1985f14b030 src/os/os_root.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/os/os_root.c Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,49 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 1999, 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + * $Id$ + */ + +#include "db_config.h" + +#include "db_int.h" + +/* + * __os_isroot -- + * Return if user has special permissions. + * + * PUBLIC: int __os_isroot __P((void)); + */ +int +__os_isroot() +{ +#ifdef HAVE_GETUID + return (getuid() == 0); +#else + return (0); +#endif +} diff -r 000000000000 -r a1985f14b030 src/os/os_rpath.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/os/os_rpath.c Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,58 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 1997, 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + * $Id$ + */ + +#include "db_config.h" + +#include "db_int.h" + +/* + * __db_rpath -- + * Return the last path separator in the path or NULL if none found. + * + * PUBLIC: char *__db_rpath __P((const char *)); + */ +char * +__db_rpath(path) + const char *path; +{ + const char *s, *last; + + s = path; + last = NULL; + if (PATH_SEPARATOR[1] != '\0') { + for (; s[0] != '\0'; ++s) + if (strchr(PATH_SEPARATOR, s[0]) != NULL) + last = s; + } else + for (; s[0] != '\0'; ++s) + if (s[0] == PATH_SEPARATOR[0]) + last = s; + return ((char *)last); +} diff -r 000000000000 -r a1985f14b030 src/os/os_rw.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/os/os_rw.c Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,313 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 1997, 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + * $Id$ + */ + +#include "db_config.h" + +#include "db_int.h" + +/* + * __os_io -- + * Do an I/O. + * + * PUBLIC: int __os_io __P((ENV *, int, DB_FH *, db_pgno_t, + * PUBLIC: u_int32_t, u_int32_t, u_int32_t, u_int8_t *, size_t *)); + */ +int +__os_io(env, op, fhp, pgno, pgsize, relative, io_len, buf, niop) + ENV *env; + int op; + DB_FH *fhp; + db_pgno_t pgno; + u_int32_t pgsize, relative, io_len; + u_int8_t *buf; + size_t *niop; +{ +#if defined(HAVE_PREAD) && defined(HAVE_PWRITE) + DB_ENV *dbenv; + off_t offset; + ssize_t nio; +#endif + int ret; + + /* + * Check for illegal usage. + * + * This routine is used in one of two ways: reading bytes from an + * absolute offset and reading a specific database page. All of + * our absolute offsets are known to fit into a u_int32_t, while + * our database pages might be at offsets larger than a u_int32_t. + */ + DB_ASSERT(env, F_ISSET(fhp, DB_FH_OPENED) && fhp->fd != -1); + DB_ASSERT(env, (pgno == 0 && pgsize == 0) || relative == 0); + +#if defined(HAVE_PREAD) && defined(HAVE_PWRITE) + dbenv = env == NULL ? NULL : env->dbenv; + + if ((offset = relative) == 0) + offset = (off_t)pgno * pgsize; + switch (op) { + case DB_IO_READ: + if (DB_GLOBAL(j_read) != NULL) + goto slow; +#if defined(HAVE_STATISTICS) + ++fhp->read_count; +#endif + if (dbenv != NULL && + FLD_ISSET(dbenv->verbose, DB_VERB_FILEOPS_ALL)) + __db_msg(env, DB_STR_A("0130", + "fileops: read %s: %lu bytes at offset %lu", + "%s %lu %lu"), fhp->name, (u_long)io_len, + (u_long)offset); + + LAST_PANIC_CHECK_BEFORE_IO(env); + nio = DB_GLOBAL(j_pread) != NULL ? + DB_GLOBAL(j_pread)(fhp->fd, buf, io_len, offset) : + pread(fhp->fd, buf, io_len, offset); + break; + case DB_IO_WRITE: + if (DB_GLOBAL(j_write) != NULL) + goto slow; +#ifdef HAVE_FILESYSTEM_NOTZERO + if (__os_fs_notzero()) + goto slow; +#endif +#if defined(HAVE_STATISTICS) + ++fhp->write_count; +#endif + if (dbenv != NULL && + FLD_ISSET(dbenv->verbose, DB_VERB_FILEOPS_ALL)) + __db_msg(env, DB_STR_A("0131", + "fileops: write %s: %lu bytes at offset %lu", + "%s %lu %lu"), fhp->name, (u_long)io_len, + (u_long)offset); + + LAST_PANIC_CHECK_BEFORE_IO(env); + nio = DB_GLOBAL(j_pwrite) != NULL ? + DB_GLOBAL(j_pwrite)(fhp->fd, buf, io_len, offset) : + pwrite(fhp->fd, buf, io_len, offset); + break; + default: + return (EINVAL); + } + if (nio == (ssize_t)io_len) { + *niop = io_len; + return (0); + } +slow: +#endif + MUTEX_LOCK(env, fhp->mtx_fh); + + if ((ret = __os_seek(env, fhp, pgno, pgsize, relative)) != 0) + goto err; + switch (op) { + case DB_IO_READ: + ret = __os_read(env, fhp, buf, io_len, niop); + break; + case DB_IO_WRITE: + ret = __os_write(env, fhp, buf, io_len, niop); + break; + default: + ret = EINVAL; + break; + } + +err: MUTEX_UNLOCK(env, fhp->mtx_fh); + + return (ret); + +} + +/* + * __os_read -- + * Read from a file handle. + * + * PUBLIC: int __os_read __P((ENV *, DB_FH *, void *, size_t, size_t *)); + */ +int +__os_read(env, fhp, addr, len, nrp) + ENV *env; + DB_FH *fhp; + void *addr; + size_t len; + size_t *nrp; +{ + DB_ENV *dbenv; + size_t offset; + ssize_t nr; + int ret; + u_int8_t *taddr; + + dbenv = env == NULL ? NULL : env->dbenv; + ret = 0; + + DB_ASSERT(env, F_ISSET(fhp, DB_FH_OPENED) && fhp->fd != -1); + +#if defined(HAVE_STATISTICS) + ++fhp->read_count; +#endif + if (dbenv != NULL && FLD_ISSET(dbenv->verbose, DB_VERB_FILEOPS_ALL)) + __db_msg(env, DB_STR_A("0132", + "fileops: read %s: %lu bytes", "%s %lu"), + fhp->name, (u_long)len); + + if (DB_GLOBAL(j_read) != NULL) { + *nrp = len; + LAST_PANIC_CHECK_BEFORE_IO(env); + if (DB_GLOBAL(j_read)(fhp->fd, addr, len) != (ssize_t)len) { + ret = __os_get_syserr(); + __db_syserr(env, ret, DB_STR_A("0133", + "read: %#lx, %lu", "%#lx %lu"), + P_TO_ULONG(addr), (u_long)len); + ret = __os_posix_err(ret); + } + return (ret); + } + + for (taddr = addr, offset = 0; + offset < len; taddr += nr, offset += (u_int32_t)nr) { + LAST_PANIC_CHECK_BEFORE_IO(env); + RETRY_CHK(((nr = read(fhp->fd, + CHAR_STAR_CAST taddr, len - offset)) < 0 ? 1 : 0), ret); + if (nr == 0 || ret != 0) + break; + } + *nrp = (size_t)(taddr - (u_int8_t *)addr); + if (ret != 0) { + __db_syserr(env, ret, DB_STR_A("0134", + "read: %#lx, %lu", "%#lx %lu"), + P_TO_ULONG(taddr), (u_long)len - offset); + ret = __os_posix_err(ret); + } + return (ret); +} + +/* + * __os_write -- + * Write to a file handle. + * + * PUBLIC: int __os_write __P((ENV *, DB_FH *, void *, size_t, size_t *)); + */ +int +__os_write(env, fhp, addr, len, nwp) + ENV *env; + DB_FH *fhp; + void *addr; + size_t len; + size_t *nwp; +{ + DB_ASSERT(env, F_ISSET(fhp, DB_FH_OPENED) && fhp->fd != -1); + +#ifdef HAVE_FILESYSTEM_NOTZERO + /* Zero-fill as necessary. */ + if (__os_fs_notzero()) { + int ret; + if ((ret = __db_zero_fill(env, fhp)) != 0) + return (ret); + } +#endif + return (__os_physwrite(env, fhp, addr, len, nwp)); +} + +/* + * __os_physwrite -- + * Physical write to a file handle. + * + * PUBLIC: int __os_physwrite + * PUBLIC: __P((ENV *, DB_FH *, void *, size_t, size_t *)); + */ +int +__os_physwrite(env, fhp, addr, len, nwp) + ENV *env; + DB_FH *fhp; + void *addr; + size_t len; + size_t *nwp; +{ + DB_ENV *dbenv; + size_t offset; + ssize_t nw; + int ret; + u_int8_t *taddr; + + dbenv = env == NULL ? NULL : env->dbenv; + ret = 0; + +#if defined(HAVE_STATISTICS) + ++fhp->write_count; +#endif + if (dbenv != NULL && FLD_ISSET(dbenv->verbose, DB_VERB_FILEOPS_ALL)) + __db_msg(env, DB_STR_A("0135", + "fileops: write %s: %lu bytes", "%s %lu"), + fhp->name, (u_long)len); + +#if defined(HAVE_FILESYSTEM_NOTZERO) && defined(DIAGNOSTIC) + if (__os_fs_notzero()) { + struct stat sb; + off_t cur_off; + + DB_ASSERT(env, fstat(fhp->fd, &sb) != -1 && + (cur_off = lseek(fhp->fd, (off_t)0, SEEK_CUR)) != -1 && + cur_off <= sb.st_size); + } +#endif + if (DB_GLOBAL(j_write) != NULL) { + *nwp = len; + LAST_PANIC_CHECK_BEFORE_IO(env); + if (DB_GLOBAL(j_write)(fhp->fd, addr, len) != (ssize_t)len) { + ret = __os_get_syserr(); + __db_syserr(env, ret, DB_STR_A("0136", + "write: %#lx, %lu", "%#lx %lu"), + P_TO_ULONG(addr), (u_long)len); + ret = __os_posix_err(ret); + + DB_EVENT(env, DB_EVENT_WRITE_FAILED, NULL); + } + return (ret); + } + + for (taddr = addr, offset = 0; + offset < len; taddr += nw, offset += (u_int32_t)nw) { + LAST_PANIC_CHECK_BEFORE_IO(env); + RETRY_CHK(((nw = write(fhp->fd, + CHAR_STAR_CAST taddr, len - offset)) < 0 ? 1 : 0), ret); + if (ret != 0) + break; + } + *nwp = len; + if (ret != 0) { + __db_syserr(env, ret, DB_STR_A("0137", + "write: %#lx, %lu", "%#lx %lu"), + P_TO_ULONG(taddr), (u_long)len - offset); + ret = __os_posix_err(ret); + + DB_EVENT(env, DB_EVENT_WRITE_FAILED, NULL); + } + return (ret); +} diff -r 000000000000 -r a1985f14b030 src/os/os_seek.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/os/os_seek.c Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,88 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 1997, 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + * $Id$ + */ + +#include "db_config.h" + +#include "db_int.h" + +/* + * __os_seek -- + * Seek to a page/byte offset in the file. + * + * PUBLIC: int __os_seek __P((ENV *, + * PUBLIC: DB_FH *, db_pgno_t, u_int32_t, off_t)); + */ +int +__os_seek(env, fhp, pgno, pgsize, relative) + ENV *env; + DB_FH *fhp; + db_pgno_t pgno; + u_int32_t pgsize; + off_t relative; +{ + DB_ENV *dbenv; + off_t offset; + int ret; + + dbenv = env == NULL ? NULL : env->dbenv; + + DB_ASSERT(env, F_ISSET(fhp, DB_FH_OPENED) && fhp->fd != -1); + +#if defined(HAVE_STATISTICS) + ++fhp->seek_count; +#endif + + offset = (off_t)pgsize * pgno + relative; + + if (dbenv != NULL && FLD_ISSET(dbenv->verbose, DB_VERB_FILEOPS_ALL)) + __db_msg(env, DB_STR_A("0170", + "fileops: seek %s to %lu", "%s %lu"), + fhp->name, (u_long)offset); + + if (DB_GLOBAL(j_seek) != NULL) + ret = DB_GLOBAL(j_seek)(fhp->fd, offset, SEEK_SET); + else + RETRY_CHK((lseek( + fhp->fd, offset, SEEK_SET) == -1 ? 1 : 0), ret); + + if (ret == 0) { + fhp->pgsize = pgsize; + fhp->pgno = pgno; + fhp->offset = relative; + } else { + __db_syserr(env, ret, DB_STR_A("0171", + "seek: %lu: (%lu * %lu) + %lu", "%lu %lu %lu %lu"), + (u_long)offset, (u_long)pgno, (u_long)pgsize, + (u_long)relative); + ret = __os_posix_err(ret); + } + + return (ret); +} diff -r 000000000000 -r a1985f14b030 src/os/os_stack.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/os/os_stack.c Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,67 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 2001, 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + * $Id$ + */ + +#include "db_config.h" + +#include "db_int.h" +#if defined(HAVE_SYSTEM_INCLUDE_FILES) && defined(HAVE_BACKTRACE) && \ + defined(HAVE_BACKTRACE_SYMBOLS) && defined(HAVE_EXECINFO_H) +#include +#endif + +/* + * __os_stack -- + * Output a stack trace to the message file handle. + * + * PUBLIC: void __os_stack __P((ENV *)); + */ +void +__os_stack(env) + ENV *env; +{ +#if defined(HAVE_BACKTRACE) && defined(HAVE_BACKTRACE_SYMBOLS) + void *array[200]; + size_t i, size; + char **strings; + + /* + * Solaris and the GNU C library support this interface. Solaris + * has additional interfaces (printstack and walkcontext), I don't + * know if they offer any additional value or not. + */ + size = backtrace(array, sizeof(array) / sizeof(array[0])); + strings = backtrace_symbols(array, size); + + for (i = 0; i < size; ++i) + __db_errx(env, "%s", strings[i]); + free(strings); +#endif + COMPQUIET(env, NULL); +} diff -r 000000000000 -r a1985f14b030 src/os/os_stat.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/os/os_stat.c Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,130 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 1997, 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + * $Id$ + */ + +#include "db_config.h" + +#include "db_int.h" + +/* + * __os_exists -- + * Return if the file exists. + * + * PUBLIC: int __os_exists __P((ENV *, const char *, int *)); + */ +int +__os_exists(env, path, isdirp) + ENV *env; + const char *path; + int *isdirp; +{ + DB_ENV *dbenv; + struct stat sb; + int ret; + + dbenv = env == NULL ? NULL : env->dbenv; + + if (dbenv != NULL && + FLD_ISSET(dbenv->verbose, DB_VERB_FILEOPS | DB_VERB_FILEOPS_ALL)) + __db_msg(env, DB_STR_A("0165", + "fileops: stat %s", "%s"), path); + + if (DB_GLOBAL(j_exists) != NULL) + return (DB_GLOBAL(j_exists)(path, isdirp)); + + RETRY_CHK((stat(CHAR_STAR_CAST path, &sb)), ret); + if (ret != 0) + return (__os_posix_err(ret)); + +#if !defined(S_ISDIR) || defined(STAT_MACROS_BROKEN) +#undef S_ISDIR +#ifdef _S_IFDIR +#define S_ISDIR(m) (_S_IFDIR & (m)) +#else +#define S_ISDIR(m) (((m) & 0170000) == 0040000) +#endif +#endif + if (isdirp != NULL) + *isdirp = S_ISDIR(sb.st_mode); + + return (0); +} + +/* + * __os_ioinfo -- + * Return file size and I/O size; abstracted to make it easier + * to replace. + * + * PUBLIC: int __os_ioinfo __P((ENV *, const char *, + * PUBLIC: DB_FH *, u_int32_t *, u_int32_t *, u_int32_t *)); + */ +int +__os_ioinfo(env, path, fhp, mbytesp, bytesp, iosizep) + ENV *env; + const char *path; + DB_FH *fhp; + u_int32_t *mbytesp, *bytesp, *iosizep; +{ + struct stat sb; + int ret; + + if (DB_GLOBAL(j_ioinfo) != NULL) + return (DB_GLOBAL(j_ioinfo)(path, + fhp->fd, mbytesp, bytesp, iosizep)); + + DB_ASSERT(env, F_ISSET(fhp, DB_FH_OPENED) && fhp->fd != -1); + + RETRY_CHK((fstat(fhp->fd, &sb)), ret); + if (ret != 0) { + __db_syserr(env, ret, DB_STR("0166", "fstat")); + return (__os_posix_err(ret)); + } + + /* Return the size of the file. */ + if (mbytesp != NULL) + *mbytesp = (u_int32_t)(sb.st_size / MEGABYTE); + if (bytesp != NULL) + *bytesp = (u_int32_t)(sb.st_size % MEGABYTE); + + /* + * Return the underlying filesystem I/O size, if available. + * + * XXX + * Check for a 0 size -- the HP MPE/iX architecture has st_blksize, + * but it's always 0. + */ +#ifdef HAVE_STRUCT_STAT_ST_BLKSIZE + if (iosizep != NULL && (*iosizep = sb.st_blksize) == 0) + *iosizep = DB_DEF_IOSIZE; +#else + if (iosizep != NULL) + *iosizep = DB_DEF_IOSIZE; +#endif + return (0); +} diff -r 000000000000 -r a1985f14b030 src/os/os_tmpdir.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/os/os_tmpdir.c Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,163 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 1998, 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + * $Id$ + */ + +#include "db_config.h" + +#include "db_int.h" + +#ifdef HAVE_SYSTEM_INCLUDE_FILES +#ifdef macintosh +#include +#endif +#endif + +/* + * __os_tmpdir -- + * Set the temporary directory path. + * + * The order of items in the list structure and the order of checks in + * the environment are documented. + * + * PUBLIC: int __os_tmpdir __P((ENV *, u_int32_t)); + */ +int +__os_tmpdir(env, flags) + ENV *env; + u_int32_t flags; +{ + DB_ENV *dbenv; + int isdir, ret; + char *tdir, tdir_buf[DB_MAXPATHLEN]; + + dbenv = env->dbenv; + + /* Use the environment if it's permitted and initialized. */ + if (LF_ISSET(DB_USE_ENVIRON) || + (LF_ISSET(DB_USE_ENVIRON_ROOT) && __os_isroot())) { + /* POSIX: TMPDIR */ + tdir = tdir_buf; + if ((ret = __os_getenv( + env, "TMPDIR", &tdir, sizeof(tdir_buf))) != 0) + return (ret); + if (tdir != NULL && tdir[0] != '\0') + goto found; + + /* + * Windows: TEMP, TMP + */ + tdir = tdir_buf; + if ((ret = __os_getenv( + env, "TEMP", &tdir, sizeof(tdir_buf))) != 0) + return (ret); + if (tdir != NULL && tdir[0] != '\0') + goto found; + + tdir = tdir_buf; + if ((ret = __os_getenv( + env, "TMP", &tdir, sizeof(tdir_buf))) != 0) + return (ret); + if (tdir != NULL && tdir[0] != '\0') + goto found; + + /* Macintosh */ + tdir = tdir_buf; + if ((ret = __os_getenv( + env, "TempFolder", &tdir, sizeof(tdir_buf))) != 0) + return (ret); + + if (tdir != NULL && tdir[0] != '\0') +found: return (__os_strdup(env, tdir, &dbenv->db_tmp_dir)); + } + +#ifdef macintosh + /* Get the path to the temporary folder. */ + {FSSpec spec; + + if (!Special2FSSpec(kTemporaryFolderType, + kOnSystemDisk, 0, &spec)) + return (__os_strdup(env, + FSp2FullPath(&spec), &dbenv->db_tmp_dir)); + } +#endif +#ifdef DB_WIN32 + /* Get the path to the temporary directory. */ + { + _TCHAR tpath[DB_MAXPATHLEN + 1]; + char *path, *eos; + + if (GetTempPath(DB_MAXPATHLEN, tpath) > 2) { + FROM_TSTRING(env, tpath, path, ret); + if (ret != 0) + return (ret); + + eos = path + strlen(path) - 1; + if (*eos == '\\' || *eos == '/') + *eos = '\0'; + if (__os_exists(env, path, &isdir) == 0 && isdir) { + ret = __os_strdup(env, + path, &dbenv->db_tmp_dir); + FREE_STRING(env, path); + return (ret); + } + FREE_STRING(env, path); + } + } +#endif + + /* + * Step through the static list looking for a possibility. + * + * We don't use the obvious data structure because some C compilers + * (and I use the phrase loosely) don't like static data arrays. + */ +#define DB_TEMP_DIRECTORY(n) { \ + char *__p = n; \ + if (__os_exists(env, __p, &isdir) == 0 && isdir != 0) \ + return (__os_strdup(env, __p, &dbenv->db_tmp_dir)); \ + } +#ifdef DB_WIN32 + DB_TEMP_DIRECTORY("/temp"); + DB_TEMP_DIRECTORY("C:/temp"); + DB_TEMP_DIRECTORY("C:/tmp"); +#else + DB_TEMP_DIRECTORY("/var/tmp"); + DB_TEMP_DIRECTORY("/usr/tmp"); + DB_TEMP_DIRECTORY("/tmp"); +#if defined(ANDROID) || defined(DB_ANDROID) + DB_TEMP_DIRECTORY("/cache"); +#endif +#endif + + /* + * If we don't have any other place to store temporary files, store + * them in the current directory. + */ + return (__os_strdup(env, "", &dbenv->db_tmp_dir)); +} diff -r 000000000000 -r a1985f14b030 src/os/os_truncate.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/os/os_truncate.c Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,85 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 2004, 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + * $Id$ + */ + +#include "db_config.h" + +#include "db_int.h" + +/* + * __os_truncate -- + * Truncate the file. + * + * PUBLIC: int __os_truncate __P((ENV *, DB_FH *, db_pgno_t, u_int32_t)); + */ +int +__os_truncate(env, fhp, pgno, pgsize) + ENV *env; + DB_FH *fhp; + db_pgno_t pgno; + u_int32_t pgsize; +{ + DB_ENV *dbenv; + off_t offset; + int ret; + + dbenv = env == NULL ? NULL : env->dbenv; + + /* + * Truncate a file so that "pgno" is discarded from the end of the + * file. + */ + offset = (off_t)pgsize * pgno; + + if (dbenv != NULL && + FLD_ISSET(dbenv->verbose, DB_VERB_FILEOPS | DB_VERB_FILEOPS_ALL)) + __db_msg(env, DB_STR_A("0141", + "fileops: truncate %s to %lu", "%s %lu"), + fhp->name, (u_long)offset); + + LAST_PANIC_CHECK_BEFORE_IO(env); + + if (DB_GLOBAL(j_ftruncate) != NULL) + ret = DB_GLOBAL(j_ftruncate)(fhp->fd, offset); + else { +#ifdef HAVE_FTRUNCATE + RETRY_CHK((ftruncate(fhp->fd, offset)), ret); +#else + ret = DB_OPNOTSUP; +#endif + } + + if (ret != 0) { + __db_syserr(env, ret, DB_STR_A("0142", + "ftruncate: %lu", "%lu"), (u_long)offset); + ret = __os_posix_err(ret); + } + + return (ret); +} diff -r 000000000000 -r a1985f14b030 src/os/os_uid.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/os/os_uid.c Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,77 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 2001, 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + * $Id$ + */ + +#include "db_config.h" + +#include "db_int.h" + +/* + * __os_unique_id -- + * Return a unique 32-bit value. + * + * PUBLIC: void __os_unique_id __P((ENV *, u_int32_t *)); + */ +void +__os_unique_id(env, idp) + ENV *env; + u_int32_t *idp; +{ + DB_ENV *dbenv; + db_timespec v; + pid_t pid; + u_int32_t id; + + *idp = 0; + + dbenv = env == NULL ? NULL : env->dbenv; + + /* + * Our randomized value is comprised of our process ID, the current + * time of day and a stack address, all XOR'd together. + */ + __os_id(dbenv, &pid, NULL); + __os_gettime(env, &v, 1); + + id = (u_int32_t)pid ^ + (u_int32_t)v.tv_sec ^ (u_int32_t)v.tv_nsec ^ P_TO_UINT32(&pid); + + /* + * We could try and find a reasonable random-number generator, but + * that's not all that easy to do. Seed and use srand()/rand(), if + * we can find them. + */ + if (DB_GLOBAL(uid_init) == 0) { + DB_GLOBAL(uid_init) = 1; + srand((u_int)id); + } + id ^= (u_int)rand(); + + *idp = id; +} diff -r 000000000000 -r a1985f14b030 src/os/os_unlink.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/os/os_unlink.c Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,102 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 1997, 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + * $Id$ + */ + +#include "db_config.h" + +#include "db_int.h" + +/* + * __os_unlink -- + * Remove a file. + * + * PUBLIC: int __os_unlink __P((ENV *, const char *, int)); + */ +int +__os_unlink(env, path, overwrite_test) + ENV *env; + const char *path; + int overwrite_test; +{ + DB_ENV *dbenv; + int ret, t_ret; + + dbenv = env == NULL ? NULL : env->dbenv; + + if (dbenv != NULL && + FLD_ISSET(dbenv->verbose, DB_VERB_FILEOPS | DB_VERB_FILEOPS_ALL)) + __db_msg(env, DB_STR_A("0160", "fileops: unlink %s", + "%s"), path); + + /* Optionally overwrite the contents of the file to enhance security. */ + if (dbenv != NULL && overwrite_test && F_ISSET(dbenv, DB_ENV_OVERWRITE)) + (void)__db_file_multi_write(env, path); + + LAST_PANIC_CHECK_BEFORE_IO(env); + + if (DB_GLOBAL(j_unlink) != NULL) + ret = DB_GLOBAL(j_unlink)(path); + else { + RETRY_CHK((unlink(CHAR_STAR_CAST path)), ret); +#ifdef HAVE_QNX + /* + * The file may be a region file created by shm_open, not a + * regular file. Try and delete using unlink, and if that + * fails for an unexpected reason, try a shared memory unlink. + */ + if (ret != 0 && __os_posix_err(ret) != ENOENT) + RETRY_CHK((shm_unlink(path)), ret); +#endif + } + + /* + * !!! + * The results of unlink are file system driver specific on VxWorks. + * In the case of removing a file that did not exist, some, at least, + * return an error, but with an errno of 0, not ENOENT. We do not + * have to test for that explicitly, the RETRY_CHK macro resets "ret" + * to be the errno, and so we'll just slide right on through. + * + * XXX + * We shouldn't be testing for an errno of ENOENT here, but ENOENT + * signals that a file is missing, and we attempt to unlink things + * (such as v. 2.x environment regions, in ENV->remove) that we + * are expecting not to be there. Reporting errors in these cases + * is annoying. + */ + if (ret != 0) { + t_ret = __os_posix_err(ret); + if (t_ret != ENOENT) + __db_syserr(env, ret, DB_STR_A("0161", + "unlink: %s", "%s"), path); + ret = t_ret; + } + + return (ret); +} diff -r 000000000000 -r a1985f14b030 src/os/os_yield.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/os/os_yield.c Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,117 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 1997, 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + * $Id$ + */ + +#include "db_config.h" + +#include "db_int.h" + +#if defined(HAVE_SYSTEM_INCLUDE_FILES) && defined(HAVE_SCHED_YIELD) +#include +#endif + +static void __os_sleep __P((ENV *, u_long, u_long)); + +/* + * __os_yield -- + * Yield the processor, optionally pausing until running again. + * + * PUBLIC: void __os_yield __P((ENV *, u_long, u_long)); + */ +void +__os_yield(env, secs, usecs) + ENV *env; + u_long secs, usecs; /* Seconds and microseconds. */ +{ + /* + * Don't require the values be normalized (some operating systems + * return an error if the usecs argument to select is too large). + */ + for (; usecs >= US_PER_SEC; usecs -= US_PER_SEC) + ++secs; + + if (DB_GLOBAL(j_yield) != NULL) { + (void)DB_GLOBAL(j_yield)(secs, usecs); + return; + } + + /* + * Yield the processor so other processes or threads can run. Use + * the local yield call if not pausing, otherwise call the select + * function. + */ + if (secs != 0 || usecs != 0) + __os_sleep(env, secs, usecs); + else { +#if defined(HAVE_MUTEX_UI_THREADS) + thr_yield(); +#elif defined(HAVE_PTHREAD_YIELD) + pthread_yield(); +#elif defined(HAVE_SCHED_YIELD) + (void)sched_yield(); +#elif defined(HAVE_YIELD) + yield(); +#else + __os_sleep(env, 0, 0); +#endif + } +} + +/* + * __os_sleep -- + * Pause the thread of control. + */ +static void +__os_sleep(env, secs, usecs) + ENV *env; + u_long secs, usecs; /* Seconds and microseconds. */ +{ + struct timeval t; + int ret; + + /* + * Sheer raving paranoia -- don't select for 0 time, in case some + * implementation doesn't yield the processor in that case. + */ + t.tv_sec = (long)secs; + t.tv_usec = (long)usecs + 1; + + /* + * We don't catch interrupts and restart the system call here, unlike + * other Berkeley DB system calls. This may be a user attempting to + * interrupt a sleeping DB utility (for example, db_checkpoint), and + * we want the utility to see the signal and quit. This assumes it's + * always OK for DB to sleep for less time than originally scheduled. + */ + if (select(0, NULL, NULL, NULL, &t) == -1) { + ret = __os_get_syserr(); + if (__os_posix_err(ret) != EINTR) + __db_syserr(env, ret, DB_STR("0167", "select")); + } +} diff -r 000000000000 -r a1985f14b030 src/os_windows/ce_ctime.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/os_windows/ce_ctime.c Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,109 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 2001, 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + * $Id$ + */ + +#include "db_config.h" + +#include "db_int.h" + +static void __os_windows_ct_numb __P((char *, int)); + +/* + * __os_ctime -- + * Format a time-stamp. + */ +char * +__os_ctime(tod, time_buf) + const time_t *tod; + char *time_buf; +{ + char *ncp; + __int64 i64_tod; + struct _FILETIME file_tod, file_loc; + struct _SYSTEMTIME sys_loc; +static const __int64 SECS_BETWEEN_EPOCHS = 11644473600; +static const __int64 SECS_TO_100NS = 10000000; /* 10^7 */ + + strcpy(time_buf, "Thu Jan 01 00:00:00 1970"); + time_buf[CTIME_BUFLEN - 1] = '\0'; + + /* Convert the tod to a SYSTEM_TIME struct */ + i64_tod = *tod; + i64_tod = (i64_tod + SECS_BETWEEN_EPOCHS)*SECS_TO_100NS; + memcpy(&file_tod, &i64_tod, sizeof(file_tod)); + FileTimeToLocalFileTime(&file_tod, &file_loc); + FileTimeToSystemTime(&file_loc, &sys_loc); + + /* + * Convert the _SYSTEMTIME to the correct format in time_buf. + * Based closely on the os_brew/ctime.c implementation. + * + * wWeekDay : Day of the week 0-6 (0=Monday, 6=Sunday) + */ + ncp = &"MonTueWedThuFriSatSun"[sys_loc.wDayOfWeek*3]; + time_buf[0] = *ncp++; + time_buf[1] = *ncp++; + time_buf[2] = *ncp; + ncp = &"JanFebMarAprMayJunJulAugSepOctNovDec"[(sys_loc.wMonth - 1) * 3]; + time_buf[4] = *ncp++; + time_buf[5] = *ncp++; + time_buf[6] = *ncp; + + __os_windows_ct_numb(time_buf + 8, sys_loc.wDay); + /* Add 100 to keep the leading zero. */ + __os_windows_ct_numb(time_buf + 11, sys_loc.wHour + 100); + __os_windows_ct_numb(time_buf + 14, sys_loc.wMinute + 100); + __os_windows_ct_numb(time_buf + 17, sys_loc.wSecond + 100); + + if (sys_loc.wYear < 100) { /* 9 99 */ + time_buf[20] = ' '; + time_buf[21] = ' '; + __os_windows_ct_numb(time_buf + 22, sys_loc.wYear); + } else { /* 99 1999 */ + __os_windows_ct_numb(time_buf + 20, sys_loc.wYear / 100); + __os_windows_ct_numb(time_buf + 22, sys_loc.wYear % 100 + 100); + } + + return (time_buf); +} + +/* + * __os_windows_ct_numb -- + * Append ASCII representations for two digits to a string. + */ +static void +__os_windows_ct_numb(cp, n) + char *cp; + int n; +{ + cp[0] = ' '; + if (n >= 10) + cp[0] = (n / 10) % 10 + '0'; + cp[1] = n % 10 + '0'; +} diff -r 000000000000 -r a1985f14b030 src/os_windows/os_abs.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/os_windows/os_abs.c Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,55 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 1997, 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + * $Id$ + */ + +#include "db_config.h" + +#include "db_int.h" + +/* + * __os_abspath -- + * Return if a path is an absolute path. + */ +int +__os_abspath(path) + const char *path; +{ + /* + * !!! + * Check for drive specifications, e.g., "C:". In addition, the path + * separator used by the win32 DB (PATH_SEPARATOR) is \; look for both + * / and \ since these are user-input paths. + */ + if (strlen(path) == 0) + return (0); + + if (strlen(path) >= 3 && isalpha(path[0]) && path[1] == ':') + path += 2; + return (path[0] == '/' || path[0] == '\\'); +} diff -r 000000000000 -r a1985f14b030 src/os_windows/os_clock.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/os_windows/os_clock.c Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,101 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 2001, 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + * $Id$ + */ + +#include "db_config.h" + +#include "db_int.h" + +/* + * __os_gettime -- + * Return the current time-of-day clock in seconds and nanoseconds. + */ +void +__os_gettime(env, tp, monotonic) + ENV *env; + db_timespec *tp; + int monotonic; +{ + if (monotonic) { + /* + * The elapsed time is stored as a DWORD value, so time wraps + * around to zero if the system runs for 49.7 days. Initialize + * a base value with 50 days worth of seconds, and add 50 more + * days every time the counter wraps. That ensures we always + * move forward. + * + * It's possible this code could race, but the danger is we + * would increment base_seconds more than once per wrap and + * eventually overflow, which is a pretty remote possibility. + */ +#define TIMER_WRAP_SECONDS (50 * 24 * 60 * 60) + static DWORD last_ticks; + static time_t base_seconds; + DWORD ticks; + + ticks = GetTickCount(); + if (ticks < last_ticks) + base_seconds += TIMER_WRAP_SECONDS; + last_ticks = ticks; + tp->tv_sec = base_seconds + (u_int32_t)(ticks / 1000); + tp->tv_nsec = (u_int32_t)((ticks % 1000) * NS_PER_MS); + } else { +#ifdef DB_WINCE + FILETIME ft; + LARGE_INTEGER large_int; + LONGLONG ns_since_epoch, utc1970; + SYSTEMTIME st; + + (void)GetSystemTime(&st); + (void)SystemTimeToFileTime(&st, &ft); + + /* + * A FILETIME expresses time as 100 nanosecond chunks from + * Jan 1, 1601; convert to a timespec where the time is + * is expressed in seconds and nanoseconds from Jan 1, 1970. + * + * UTC_1970 is the number of 100-nano-second chunks from + * 1601 to 1970. + */ +#define NS100_PER_SEC (NS_PER_SEC / 100) +#define UTC_1970 (((LONGLONG)27111902 << 32) + (LONGLONG)3577643008) + memcpy(&large_int, &ft, sizeof(large_int)); + utc1970 = UTC_1970; + ns_since_epoch = (large_int.QuadPart - utc1970); + tp->tv_sec = (time_t)(ns_since_epoch / NS100_PER_SEC); + tp->tv_nsec = (long)(ns_since_epoch % NS100_PER_SEC); +#else + struct _timeb now; + + _ftime(&now); + tp->tv_sec = now.time; + tp->tv_nsec = now.millitm * NS_PER_MS; +#endif + } +} diff -r 000000000000 -r a1985f14b030 src/os_windows/os_config.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/os_windows/os_config.c Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,155 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 1999, 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + * $Id$ + */ + +#include "db_config.h" + +#include "db_int.h" + +/* + * __os_is_winnt -- + * Return 1 if Windows/NT, otherwise 0. + * + * PUBLIC: int __os_is_winnt __P((void)); + */ +int +__os_is_winnt() +{ +#ifdef DB_WINCE + return (1); +#else + static int __os_type = -1; + + /* + * The value of __os_type is computed only once, and cached to + * avoid the overhead of repeated calls to GetVersion(). + */ + if (__os_type == -1) { + if ((GetVersion() & 0x80000000) == 0) + __os_type = 1; + else + __os_type = 0; + } + return (__os_type); +#endif +} + +/* + * __os_fs_notzero -- + * Return 1 if allocated filesystem blocks are not zeroed. + */ +int +__os_fs_notzero() +{ +#ifdef DB_WINCE + return (1); +#else + static int __os_notzero = -1; + OSVERSIONINFO osvi; + + /* + * Windows/NT zero-fills pages that were never explicitly written to + * the file. Note however that this is *NOT* documented. In fact, the + * Win32 documentation makes it clear that there are no guarantees that + * uninitialized bytes will be zeroed: + * + * If the file is extended, the contents of the file between the old + * EOF position and the new position are not defined. + * + * Experiments confirm that NT/2K/XP all zero fill for both NTFS and + * FAT32. Cygwin also relies on this behavior. This is the relevant + * comment from Cygwin: + * + * Oops, this is the bug case - Win95 uses whatever is on the disk + * instead of some known (safe) value, so we must seek back and fill + * in the gap with zeros. - DJ + * Note: this bug doesn't happen on NT4, even though the + * documentation for WriteFile() says that it *may* happen on any OS. + * + * We're making a bet, here, but we made it a long time ago and haven't + * yet seen any evidence that it was wrong. + * + * Windows 95/98 and On-Time give random garbage, and that breaks + * Berkeley DB. + * + * The value of __os_notzero is computed only once, and cached to + * avoid the overhead of repeated calls to GetVersion(). + */ + if (__os_notzero == -1) { + if (__os_is_winnt()) { + osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); + GetVersionEx(&osvi); + if (_tcscmp(osvi.szCSDVersion, _T("RTTarget-32")) == 0) + __os_notzero = 1; /* On-Time */ + else + __os_notzero = 0; /* Windows/NT */ + } else + __os_notzero = 1; /* Not Windows/NT */ + } + return (__os_notzero); +#endif +} + +/* + * __os_support_direct_io -- + * Check to see if we support direct I/O. + */ +int +__os_support_direct_io() +{ + return (1); +} + +/* + * __os_support_db_register -- + * Return 1 if the system supports DB_REGISTER. + */ +int +__os_support_db_register() +{ +#ifdef DB_WINCE + return (0); +#else + return (__os_is_winnt()); +#endif +} + +/* + * __os_support_replication -- + * Return 1 if the system supports replication. + */ +int +__os_support_replication() +{ +#ifdef DB_WINCE + return (0); +#else + return (__os_is_winnt()); +#endif +} diff -r 000000000000 -r a1985f14b030 src/os_windows/os_cpu.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/os_windows/os_cpu.c Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,49 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 1997, 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + * $Id$ + */ + +#include "db_config.h" + +#include "db_int.h" + +/* + * __os_cpu_count -- + * Return the number of CPUs. + * + * PUBLIC: u_int32_t __os_cpu_count __P((void)); + */ +u_int32_t +__os_cpu_count() +{ + SYSTEM_INFO SystemInfo; + + GetSystemInfo(&SystemInfo); + + return ((u_int32_t)SystemInfo.dwNumberOfProcessors); +} diff -r 000000000000 -r a1985f14b030 src/os_windows/os_dir.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/os_windows/os_dir.c Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,144 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 1997, 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + * $Id$ + */ + +#include "db_config.h" + +#include "db_int.h" + +/* + * __os_dirlist -- + * Return a list of the files in a directory. + */ +int +__os_dirlist(env, dir, returndir, namesp, cntp) + ENV *env; + const char *dir; + int returndir, *cntp; + char ***namesp; +{ + HANDLE dirhandle; + WIN32_FIND_DATA fdata; + int arraysz, cnt, ret; + char **names, *onename; + _TCHAR tfilespec[DB_MAXPATHLEN + 1]; + _TCHAR *tdir; + + *namesp = NULL; + *cntp = 0; + + TO_TSTRING(env, dir, tdir, ret); + if (ret != 0) + return (ret); + + (void)_sntprintf(tfilespec, DB_MAXPATHLEN, + _T("%s%hc*"), tdir, PATH_SEPARATOR[0]); + + /* + * On WinCE, FindFirstFile will return INVALID_HANDLE_VALUE when + * the searched directory is empty, and set last error to + * ERROR_NO_MORE_FILES, on Windows it will return "." instead. + */ + if ((dirhandle = + FindFirstFile(tfilespec, &fdata)) == INVALID_HANDLE_VALUE) { + if (GetLastError() == ERROR_NO_MORE_FILES) + return (0); + return (__os_posix_err(__os_get_syserr())); + } + + names = NULL; + arraysz = cnt = ret = 0; + for (;;) { + if (returndir || + (fdata.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0) { + if (fdata.cFileName[0] == _T('.') && + (fdata.cFileName[1] == _T('\0') || + (fdata.cFileName[1] == _T('.') && + fdata.cFileName[2] == _T('\0')))) + goto next; + if (cnt >= arraysz) { + arraysz += 100; + if ((ret = __os_realloc(env, + arraysz * sizeof(names[0]), &names)) != 0) + goto err; + } + /* + * FROM_TSTRING doesn't necessarily allocate new + * memory, so we must do that explicitly. + * Unfortunately, when compiled with UNICODE, we'll + * copy twice. + */ + FROM_TSTRING(env, fdata.cFileName, onename, ret); + if (ret != 0) + goto err; + ret = __os_strdup(env, onename, &names[cnt]); + FREE_STRING(env, onename); + if (ret != 0) + goto err; + cnt++; + } +next: + if (!FindNextFile(dirhandle, &fdata)) { + if (GetLastError() == ERROR_NO_MORE_FILES) + break; + else { + ret = __os_posix_err(__os_get_syserr()); + goto err; + } + } + } + +err: if (!FindClose(dirhandle) && ret == 0) + ret = __os_posix_err(__os_get_syserr()); + + if (ret == 0) { + *namesp = names; + *cntp = cnt; + } else if (names != NULL) + __os_dirfree(env, names, cnt); + + FREE_STRING(env, tdir); + + return (ret); +} + +/* + * __os_dirfree -- + * Free the list of files. + */ +void +__os_dirfree(env, names, cnt) + ENV *env; + char **names; + int cnt; +{ + while (cnt > 0) + __os_free(env, names[--cnt]); + __os_free(env, names); +} diff -r 000000000000 -r a1985f14b030 src/os_windows/os_errno.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/os_windows/os_errno.c Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,450 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 1999, 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + * $Id$ + */ + +#include "db_config.h" + +#include "db_int.h" + +/* + * __os_get_errno_ret_zero -- + * Return the last system error, including an error of zero. + */ +int +__os_get_errno_ret_zero() +{ + /* This routine must be able to return the same value repeatedly. */ + return (errno); +} + +/* + * We've seen cases where system calls failed but errno was never set. For + * that reason, __os_get_errno() and __os_get_syserr set errno to EAGAIN if + * it's not already set, to work around the problem. For obvious reasons, + * we can only call this function if we know an error has occurred, that + * is, we can't test the return for a non-zero value after the get call. + * + * __os_get_errno -- + * Return the last ANSI C "errno" value or EAGAIN if the last error + * is zero. + */ +int +__os_get_errno() +{ + /* This routine must be able to return the same value repeatedly. */ + if (errno == 0) + __os_set_errno(EAGAIN); + return (errno); +} + +#ifdef HAVE_REPLICATION_THREADS +/* + * __os_get_neterr -- + * Return the last networking error or EAGAIN if the last error is zero. + * + * PUBLIC: #ifdef HAVE_REPLICATION_THREADS + * PUBLIC: int __os_get_neterr __P((void)); + * PUBLIC: #endif + */ +int +__os_get_neterr() +{ + int err; + + /* This routine must be able to return the same value repeatedly. */ + err = WSAGetLastError(); + if (err == 0) + WSASetLastError(err = ERROR_RETRY); + return (err); +} +#endif + +/* + * __os_get_syserr -- + * Return the last system error or EAGAIN if the last error is zero. + */ +int +__os_get_syserr() +{ + int err; + + /* This routine must be able to return the same value repeatedly. */ + err = GetLastError(); + if (err == 0) + SetLastError(err = ERROR_RETRY); + return (err); +} + +/* + * __os_set_errno -- + * Set the value of errno. + */ +void +__os_set_errno(evalue) + int evalue; +{ + /* + * This routine is called by the compatibility interfaces (DB 1.85, + * dbm and hsearch). Force values > 0, that is, not one of DB 2.X + * and later's public error returns. If something bad has happened, + * default to EFAULT -- a nasty return. Otherwise, default to EINVAL. + * As the compatibility APIs aren't included on Windows, the Windows + * version of this routine doesn't need this behavior. + */ + errno = + evalue >= 0 ? evalue : (evalue == DB_RUNRECOVERY ? EFAULT : EINVAL); +} + +/* + * __os_strerror -- + * Return a string associated with the system error. + */ +char * +__os_strerror(error, buf, len) + int error; + char *buf; + size_t len; +{ +#ifdef DB_WINCE +#define MAX_TMPBUF_LEN 512 + _TCHAR tbuf[MAX_TMPBUF_LEN]; + size_t maxlen; + + DB_ASSERT(NULL, error != 0); + + memset(tbuf, 0, sizeof(_TCHAR)*MAX_TMPBUF_LEN); + maxlen = (len > MAX_TMPBUF_LEN ? MAX_TMPBUF_LEN : len); + FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, 0, (DWORD)error, + 0, tbuf, maxlen-1, NULL); + + if (WideCharToMultiByte(CP_UTF8, 0, tbuf, -1, + buf, len, 0, NULL) == 0) + strncpy(buf, DB_STR("0035", + "Error message translation failed."), len); +#else + DB_ASSERT(NULL, error != 0); + /* + * Explicitly call FormatMessageA, since we want to receive a char + * string back, not a tchar string. + */ + FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM, + 0, (DWORD)error, 0, buf, (DWORD)(len - 1), NULL); + buf[len - 1] = '\0'; +#endif + + return (buf); +} + +/* + * __os_posix_err -- + * Convert a system error to a POSIX error. + */ +int +__os_posix_err(error) + int error; +{ + /* Handle calls on successful returns. */ + if (error == 0) + return (0); + + /* + * Translate the Windows error codes we care about. + */ + switch (error) { + case ERROR_INVALID_PARAMETER: + return (EINVAL); + + case ERROR_FILE_NOT_FOUND: + case ERROR_INVALID_DRIVE: + case ERROR_PATH_NOT_FOUND: + return (ENOENT); + + case ERROR_NO_MORE_FILES: + case ERROR_TOO_MANY_OPEN_FILES: + return (EMFILE); + + case ERROR_ACCESS_DENIED: + return (EPERM); + + case ERROR_INVALID_HANDLE: + return (EBADF); + + case ERROR_NOT_ENOUGH_MEMORY: + return (ENOMEM); + + case ERROR_DISK_FULL: + return (ENOSPC); + + case ERROR_ARENA_TRASHED: + case ERROR_BAD_COMMAND: + case ERROR_BAD_ENVIRONMENT: + case ERROR_BAD_FORMAT: + case ERROR_GEN_FAILURE: + case ERROR_INVALID_ACCESS: + case ERROR_INVALID_BLOCK: + case ERROR_INVALID_DATA: + case ERROR_READ_FAULT: + case ERROR_WRITE_FAULT: + return (EFAULT); + + case ERROR_ALREADY_EXISTS: + case ERROR_FILE_EXISTS: + return (EEXIST); + + case ERROR_NOT_SAME_DEVICE: + return (EXDEV); + + case ERROR_WRITE_PROTECT: + return (EACCES); + + case ERROR_LOCK_FAILED: + case ERROR_LOCK_VIOLATION: + case ERROR_NOT_READY: + case ERROR_SHARING_VIOLATION: + return (EBUSY); + + case ERROR_RETRY: + return (EINTR); + } + + /* + * Translate the Windows socket error codes. + */ + switch (error) { + case WSAEADDRINUSE: +#ifdef EADDRINUSE + return (EADDRINUSE); +#else + break; +#endif + case WSAEADDRNOTAVAIL: +#ifdef EADDRNOTAVAIL + return (EADDRNOTAVAIL); +#else + break; +#endif + case WSAEAFNOSUPPORT: +#ifdef EAFNOSUPPORT + return (EAFNOSUPPORT); +#else + break; +#endif + case WSAEALREADY: +#ifdef EALREADY + return (EALREADY); +#else + break; +#endif + case WSAEBADF: + return (EBADF); + case WSAECONNABORTED: +#ifdef ECONNABORTED + return (ECONNABORTED); +#else + break; +#endif + case WSAECONNREFUSED: +#ifdef ECONNREFUSED + return (ECONNREFUSED); +#else + break; +#endif + case WSAECONNRESET: +#ifdef ECONNRESET + return (ECONNRESET); +#else + break; +#endif + case WSAEDESTADDRREQ: +#ifdef EDESTADDRREQ + return (EDESTADDRREQ); +#else + break; +#endif + case WSAEFAULT: + return (EFAULT); + case WSAEHOSTDOWN: +#ifdef EHOSTDOWN + return (EHOSTDOWN); +#else + break; +#endif + case WSAEHOSTUNREACH: +#ifdef EHOSTUNREACH + return (EHOSTUNREACH); +#else + break; +#endif + case WSAEINPROGRESS: +#ifdef EINPROGRESS + return (EINPROGRESS); +#else + break; +#endif + case WSAEINTR: + return (EINTR); + case WSAEINVAL: + return (EINVAL); + case WSAEISCONN: +#ifdef EISCONN + return (EISCONN); +#else + break; +#endif + case WSAELOOP: +#ifdef ELOOP + return (ELOOP); +#else + break; +#endif + case WSAEMFILE: + return (EMFILE); + case WSAEMSGSIZE: +#ifdef EMSGSIZE + return (EMSGSIZE); +#else + break; +#endif + case WSAENAMETOOLONG: + return (ENAMETOOLONG); + case WSAENETDOWN: +#ifdef ENETDOWN + return (ENETDOWN); +#else + break; +#endif + case WSAENETRESET: +#ifdef ENETRESET + return (ENETRESET); +#else + break; +#endif + case WSAENETUNREACH: +#ifdef ENETUNREACH + return (ENETUNREACH); +#else + break; +#endif + case WSAENOBUFS: +#ifdef ENOBUFS + return (ENOBUFS); +#else + break; +#endif + case WSAENOPROTOOPT: +#ifdef ENOPROTOOPT + return (ENOPROTOOPT); +#else + break; +#endif + case WSAENOTCONN: +#ifdef ENOTCONN + return (ENOTCONN); +#else + break; +#endif + case WSANOTINITIALISED: + return (EAGAIN); + case WSAENOTSOCK: +#ifdef ENOTSOCK + return (ENOTSOCK); +#else + break; +#endif + case WSAEOPNOTSUPP: + return (DB_OPNOTSUP); + case WSAEPFNOSUPPORT: +#ifdef EPFNOSUPPORT + return (EPFNOSUPPORT); +#else + break; +#endif + case WSAEPROTONOSUPPORT: +#ifdef EPROTONOSUPPORT + return (EPROTONOSUPPORT); +#else + break; +#endif + case WSAEPROTOTYPE: +#ifdef EPROTOTYPE + return (EPROTOTYPE); +#else + break; +#endif + case WSAESHUTDOWN: +#ifdef ESHUTDOWN + return (ESHUTDOWN); +#else + break; +#endif + case WSAESOCKTNOSUPPORT: +#ifdef ESOCKTNOSUPPORT + return (ESOCKTNOSUPPORT); +#else + break; +#endif + case WSAETIMEDOUT: +#ifdef ETIMEDOUT + return (ETIMEDOUT); +#else + break; +#endif + case WSAETOOMANYREFS: +#ifdef ETOOMANYREFS + return (ETOOMANYREFS); +#else + break; +#endif + case WSAEWOULDBLOCK: +#ifdef EWOULDBLOCK + return (EWOULDBLOCK); +#else + return (EAGAIN); +#endif + case WSAHOST_NOT_FOUND: +#ifdef EHOSTUNREACH + return (EHOSTUNREACH); +#else + break; +#endif + case WSASYSNOTREADY: + return (EAGAIN); + case WSATRY_AGAIN: + return (EAGAIN); + case WSAVERNOTSUPPORTED: + return (DB_OPNOTSUP); + case WSAEACCES: + return (EACCES); + } + + /* + * EFAULT is the default if we don't have a translation. + */ + return (EFAULT); +} diff -r 000000000000 -r a1985f14b030 src/os_windows/os_fid.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/os_windows/os_fid.c Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,151 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 1996, 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + * $Id$ + */ + +#include "db_config.h" + +#include "db_int.h" + +/* + * __os_fileid -- + * Return a unique identifier for a file. + */ +int +__os_fileid(env, fname, unique_okay, fidp) + ENV *env; + const char *fname; + int unique_okay; + u_int8_t *fidp; +{ + pid_t pid; + size_t i; + u_int32_t tmp; + u_int8_t *p; + int ret; + + /* + * The documentation for GetFileInformationByHandle() states that the + * inode-type numbers are not constant between processes. Actually, + * they are, they're the NTFS MFT indexes. So, this works on NTFS, + * but perhaps not on other platforms, and perhaps not over a network. + * Can't think of a better solution right now. + */ + DB_FH *fhp; + BY_HANDLE_FILE_INFORMATION fi; + BOOL retval = FALSE; + + DB_ASSERT(env, fname != NULL); + + /* Clear the buffer. */ + memset(fidp, 0, DB_FILE_ID_LEN); + + /* + * First we open the file, because we're not given a handle to it. + * If we can't open it, we're in trouble. + */ + if ((ret = __os_open(env, fname, 0, + DB_OSO_RDONLY, DB_MODE_400, &fhp)) != 0) + return (ret); + + /* File open, get its info */ + if ((retval = GetFileInformationByHandle(fhp->handle, &fi)) == FALSE) + ret = __os_get_syserr(); + (void)__os_closehandle(env, fhp); + + if (retval == FALSE) + return (__os_posix_err(ret)); + + /* + * We want the three 32-bit words which tell us the volume ID and + * the file ID. We make a crude attempt to copy the bytes over to + * the callers buffer. + * + * We don't worry about byte sexing or the actual variable sizes. + * + * When this routine is called from the DB access methods, it's only + * called once -- whatever ID is generated when a database is created + * is stored in the database file's metadata, and that is what is + * saved in the mpool region's information to uniquely identify the + * file. + * + * When called from the mpool layer this routine will be called each + * time a new thread of control wants to share the file, which makes + * things tougher. As far as byte sexing goes, since the mpool region + * lives on a single host, there's no issue of that -- the entire + * region is byte sex dependent. As far as variable sizes go, we make + * the simplifying assumption that 32-bit and 64-bit processes will + * get the same 32-bit values if we truncate any returned 64-bit value + * to a 32-bit value. + */ + tmp = (u_int32_t)fi.nFileIndexLow; + for (p = (u_int8_t *)&tmp, i = sizeof(u_int32_t); i > 0; --i) + *fidp++ = *p++; + tmp = (u_int32_t)fi.nFileIndexHigh; + for (p = (u_int8_t *)&tmp, i = sizeof(u_int32_t); i > 0; --i) + *fidp++ = *p++; + + if (unique_okay) { + /* Add in 32-bits of (hopefully) unique number. */ + __os_unique_id(env, &tmp); + for (p = (u_int8_t *)&tmp, i = sizeof(u_int32_t); i > 0; --i) + *fidp++ = *p++; + + /* + * Initialize/increment the serial number we use to help + * avoid fileid collisions. Note we don't bother with + * locking; it's unpleasant to do from down in here, and + * if we race on this no real harm will be done, since the + * finished fileid has so many other components. + * + * We use the bottom 32-bits of the process ID, hoping they + * are more random than the top 32-bits (should we be on a + * machine with 64-bit process IDs). + * + * We increment by 100000 on each call as a simple way of + * randomizing; simply incrementing seems potentially less + * useful if pids are also simply incremented, since this + * is process-local and we may be one of a set of processes + * starting up. 100000 pushes us out of pid space on most + * 32-bit platforms, and has few interesting properties in + * base 2. + */ + if (DB_GLOBAL(fid_serial) == 0) { + __os_id(env->dbenv, &pid, NULL); + DB_GLOBAL(fid_serial) = (u_int32_t)pid; + } else + DB_GLOBAL(fid_serial) += 100000; + + } else { + tmp = (u_int32_t)fi.dwVolumeSerialNumber; + for (p = (u_int8_t *)&tmp, i = sizeof(u_int32_t); i > 0; --i) + *fidp++ = *p++; + } + + return (0); +} diff -r 000000000000 -r a1985f14b030 src/os_windows/os_flock.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/os_windows/os_flock.c Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,112 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 1997, 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + * $Id$ + */ + +#include "db_config.h" + +#include "db_int.h" + +/* + * __os_fdlock -- + * Acquire/release a lock on a byte in a file. + */ +int +__os_fdlock(env, fhp, offset, acquire, nowait) + ENV *env; + DB_FH *fhp; + int acquire, nowait; + off_t offset; +{ +#ifdef DB_WINCE + /* + * This functionality is not supported by WinCE, so just fail. + * + * Should only happen if an app attempts to open an environment + * with the DB_REGISTER flag. + */ + __db_errx(env, DB_STR("0019", + "fdlock API not implemented for WinCE, DB_REGISTER " + "environment flag not supported.")); + return (EFAULT); +#else + DWORD low, high; + DB_ENV *dbenv; + OVERLAPPED over; + int ret; + + dbenv = env == NULL ? NULL : env->dbenv; + + DB_ASSERT(env, + F_ISSET(fhp, DB_FH_OPENED) && fhp->handle != INVALID_HANDLE_VALUE); + + if (dbenv != NULL && FLD_ISSET(dbenv->verbose, DB_VERB_FILEOPS_ALL)) + __db_msg(env, DB_STR_A("0020", + "fileops: flock %s %s offset %lu", "%s %s %lu"), fhp->name, + acquire ? DB_STR_P("acquire"): DB_STR_P("release"), + (u_long)offset); + + /* + * Windows file locking interferes with read/write operations, so we + * map the ranges to an area past the end of the file. + */ + DB_ASSERT(env, offset < (u_int64_t)INT64_MAX); + offset = UINT64_MAX - offset; + low = (DWORD)offset; + high = (DWORD)(offset >> 32); + + if (acquire) { + if (nowait) + RETRY_CHK_EINTR_ONLY( + !LockFile(fhp->handle, low, high, 1, 0), ret); + else if (__os_is_winnt()) { + memset(&over, 0, sizeof(over)); + over.Offset = low; + over.OffsetHigh = high; + RETRY_CHK_EINTR_ONLY( + !LockFileEx(fhp->handle, LOCKFILE_EXCLUSIVE_LOCK, + 0, 1, 0, &over), + ret); + } else { + /* Windows 9x/ME doesn't support a blocking call. */ + for (;;) { + RETRY_CHK_EINTR_ONLY( + !LockFile(fhp->handle, low, high, 1, 0), + ret); + if (__os_posix_err(ret) != EAGAIN) + break; + __os_yield(env, 1, 0); + } + } + } else + RETRY_CHK_EINTR_ONLY( + !UnlockFile(fhp->handle, low, high, 1, 0), ret); + + return (__os_posix_err(ret)); +#endif +} diff -r 000000000000 -r a1985f14b030 src/os_windows/os_fsync.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/os_windows/os_fsync.c Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,66 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 1997, 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + * $Id$ + */ + +#include "db_config.h" + +#include "db_int.h" + +/* + * __os_fsync -- + * Flush a file descriptor. + */ +int +__os_fsync(env, fhp) + ENV *env; + DB_FH *fhp; +{ + DB_ENV *dbenv; + int ret; + + dbenv = env == NULL ? NULL : env->dbenv; + + /* + * Do nothing if the file descriptor has been marked as not requiring + * any sync to disk. + */ + if (F_ISSET(fhp, DB_FH_NOSYNC)) + return (0); + + if (dbenv != NULL && FLD_ISSET(dbenv->verbose, DB_VERB_FILEOPS_ALL)) + __db_msg(env, DB_STR_A("0023", + "fileops: flush %s", "%s"), fhp->name); + + RETRY_CHK((!FlushFileBuffers(fhp->handle)), ret); + if (ret != 0) { + __db_syserr(env, ret, DB_STR("0024", "FlushFileBuffers")); + ret = __os_posix_err(ret); + } + return (ret); +} diff -r 000000000000 -r a1985f14b030 src/os_windows/os_getenv.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/os_windows/os_getenv.c Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,125 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 1997, 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + * $Id$ + */ + +#include "db_config.h" + +#include "db_int.h" + +/* + * __os_getenv -- + * Retrieve an environment variable. + */ +int +__os_getenv(env, name, bpp, buflen) + ENV *env; + const char *name; + char **bpp; + size_t buflen; +{ +#ifdef DB_WINCE + COMPQUIET(name, NULL); + /* WinCE does not have a getenv implementation. */ + return (0); +#else + _TCHAR *tname, tbuf[1024]; + int ret; + char *p; + + /* + * If there's a value and the buffer is large enough: + * copy value into the pointer, return 0 + * If there's a value and the buffer is too short: + * set pointer to NULL, return EINVAL + * If there's no value: + * set pointer to NULL, return 0 + */ + if ((p = getenv(name)) != NULL) { + if (strlen(p) < buflen) { + (void)strcpy(*bpp, p); + return (0); + } + goto small_buf; + } + + TO_TSTRING(env, name, tname, ret); + if (ret != 0) + return (ret); + /* + * The declared size of the tbuf buffer limits the maximum environment + * variable size in Berkeley DB on Windows. If that's too small, or if + * we need to get rid of large allocations on the BDB stack, we should + * malloc the tbuf memory. + */ + ret = GetEnvironmentVariable(tname, tbuf, sizeof(tbuf)); + FREE_STRING(env, tname); + + /* + * If GetEnvironmentVariable succeeds, the return value is the number + * of characters stored in the buffer pointed to by lpBuffer, not + * including the terminating null character. If the buffer is not + * large enough to hold the data, the return value is the buffer size, + * in characters, required to hold the string and its terminating null + * character. If GetEnvironmentVariable fails, the return value is + * zero. If the specified environment variable was not found in the + * environment block, GetLastError returns ERROR_ENVVAR_NOT_FOUND. + */ + if (ret == 0) { + if ((ret = __os_get_syserr()) == ERROR_ENVVAR_NOT_FOUND) { + *bpp = NULL; + return (0); + } + __db_syserr(env, ret, DB_STR("0026", + "GetEnvironmentVariable")); + return (__os_posix_err(ret)); + } + if (ret > (int)sizeof(tbuf)) + goto small_buf; + + FROM_TSTRING(env, tbuf, p, ret); + if (ret != 0) + return (ret); + if (strlen(p) < buflen) + (void)strcpy(*bpp, p); + else + *bpp = NULL; + FREE_STRING(env, p); + if (*bpp == NULL) + goto small_buf; + + return (0); + +small_buf: + *bpp = NULL; + __db_errx(env, DB_STR_A("0027", + "%s: buffer too small to hold environment variable %s", "%s %s"), + name, p); + return (EINVAL); +#endif +} diff -r 000000000000 -r a1985f14b030 src/os_windows/os_handle.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/os_windows/os_handle.c Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,189 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 1998, 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + * $Id$ + */ + +#include "db_config.h" + +#include "db_int.h" + +/* + * __os_openhandle -- + * Open a file, using POSIX 1003.1 open flags. + */ +int +__os_openhandle(env, name, flags, mode, fhpp) + ENV *env; + const char *name; + int flags, mode; + DB_FH **fhpp; +{ +#ifdef DB_WINCE + /* + * __os_openhandle API is not implemented on WinCE. + * It is not currently called from within the Berkeley DB library, + * so don't log the failure via the __db_err mechanism. + */ + return (EFAULT); +#else + DB_FH *fhp; + int ret, nrepeat, retries; + + /* + * Allocate the file handle and copy the file name. We generally only + * use the name for verbose or error messages, but on systems where we + * can't unlink temporary files immediately, we use the name to unlink + * the temporary file when the file handle is closed. + * + * Lock the ENV handle and insert the new file handle on the list. + */ + if ((ret = __os_calloc(env, 1, sizeof(DB_FH), &fhp)) != 0) + return (ret); + if ((ret = __os_strdup(env, name, &fhp->name)) != 0) + goto err; + if (env != NULL) { + MUTEX_LOCK(env, env->mtx_env); + TAILQ_INSERT_TAIL(&env->fdlist, fhp, q); + MUTEX_UNLOCK(env, env->mtx_env); + F_SET(fhp, DB_FH_ENVLINK); + } + + retries = 0; + for (nrepeat = 1; nrepeat < 4; ++nrepeat) { + fhp->fd = _open(name, flags, mode); + + if (fhp->fd != -1) { + ret = 0; + break; + } + + switch (ret = __os_posix_err(__os_get_syserr())) { + case EMFILE: + case ENFILE: + case ENOSPC: + /* + * If it's a "temporary" error, we retry up to 3 times, + * waiting up to 12 seconds. While it's not a problem + * if we can't open a database, an inability to open a + * log file is cause for serious dismay. + */ + __os_yield(env, nrepeat * 2, 0); + break; + case EAGAIN: + case EBUSY: + case EINTR: + /* + * If an EAGAIN, EBUSY or EINTR, retry immediately for + * DB_RETRY times. + */ + if (++retries < DB_RETRY) + --nrepeat; + break; + default: + /* Open is silent on error. */ + goto err; + } + } + + if (ret == 0) { + F_SET(fhp, DB_FH_OPENED); + *fhpp = fhp; + return (0); + } + +err: (void)__os_closehandle(env, fhp); + return (ret); +#endif +} + +/* + * __os_closehandle -- + * Close a file. + */ +int +__os_closehandle(env, fhp) + ENV *env; + DB_FH *fhp; +{ + DB_ENV *dbenv; + int ret, t_ret; + + ret = 0; + + if (env != NULL) { + dbenv = env->dbenv; + if (fhp->name != NULL && FLD_ISSET( + dbenv->verbose, DB_VERB_FILEOPS | DB_VERB_FILEOPS_ALL)) + __db_msg(env, DB_STR_A("0031", + "fileops: %s: close", "%s"), fhp->name); + + if (F_ISSET(fhp, DB_FH_ENVLINK)) { + /* + * Lock the ENV handle and remove this file + * handle from the list. + */ + MUTEX_LOCK(env, env->mtx_env); + TAILQ_REMOVE(&env->fdlist, fhp, q); + MUTEX_UNLOCK(env, env->mtx_env); + } + } + + /* Discard any underlying system file reference. */ + if (F_ISSET(fhp, DB_FH_OPENED)) { + if (fhp->handle != INVALID_HANDLE_VALUE) + RETRY_CHK((!CloseHandle(fhp->handle)), ret); + else +#ifdef DB_WINCE + ret = EFAULT; +#else + RETRY_CHK((_close(fhp->fd)), ret); +#endif + + if (fhp->trunc_handle != INVALID_HANDLE_VALUE) { + RETRY_CHK((!CloseHandle(fhp->trunc_handle)), t_ret); + if (t_ret != 0 && ret == 0) + ret = t_ret; + } + + if (ret != 0) { + __db_syserr(env, ret, DB_STR("0032", + "CloseHandle")); + ret = __os_posix_err(ret); + } + } + + /* Unlink the file if we haven't already done so. */ + if (F_ISSET(fhp, DB_FH_UNLINK)) + (void)__os_unlink(env, fhp->name, 0); + + if (fhp->name != NULL) + __os_free(env, fhp->name); + __os_free(env, fhp); + + return (ret); +} diff -r 000000000000 -r a1985f14b030 src/os_windows/os_map.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/os_windows/os_map.c Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,419 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 1996, 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + * $Id$ + */ + +#include "db_config.h" + +#include "db_int.h" + +static int __os_map + __P((ENV *, char *, REGINFO *, DB_FH *, size_t, int, int, int, void **)); +static int __os_unique_name __P((_TCHAR *, HANDLE, _TCHAR *, size_t)); + +/* + * __os_attach -- + * Create/join a shared memory region. + */ +int +__os_attach(env, infop, rp) + ENV *env; + REGINFO *infop; + REGION *rp; +{ + int ret; + int is_sparse; +#ifndef DB_WINCE + DWORD dw; +#endif + + infop->fhp = NULL; + /* + * On Windows/9X, files that are opened by multiple processes do not + * share data correctly. For this reason, we require that DB_PRIVATE + * be specified on that platform. + */ + if (!F_ISSET(env, ENV_PRIVATE) && __os_is_winnt() == 0) { + __db_err(env, EINVAL, DB_STR("0006", + "Windows 9X systems must specify DB_PRIVATE")); + return (EINVAL); + } + + /* + * Try to open/create the file. We DO NOT need to ensure that multiple + * threads/processes attempting to simultaneously create the region are + * properly ordered, our caller has already taken care of that. + */ + if ((ret = __os_open(env, infop->name, 0, DB_OSO_REGION | + (F_ISSET(infop, REGION_CREATE_OK) ? DB_OSO_CREATE : 0), + env->db_mode, &infop->fhp)) != 0) { + __db_err(env, ret, "%s", infop->name); + return (ret); + } + + is_sparse = 0; +#ifndef DB_WINCE + /* + * Sparse file only works for NTFS filesystem. If we failed to set it, + * just ignore the error and use the normal method. + */ + if (!F_ISSET(env, ENV_SYSTEM_MEM) && (DeviceIoControl( + infop->fhp->handle, FSCTL_SET_SPARSE, NULL, 0, NULL, 0, + &dw, NULL))) + is_sparse = 1; +#endif + + /* + * Map the file in. If we're creating an in-system-memory region, + * specify a segment ID (which is never used again) so that the + * calling code writes out the REGENV_REF structure to the primary + * environment file. + */ + ret = __os_map(env, infop->name, infop, infop->fhp, rp->max, + 1, F_ISSET(env, ENV_SYSTEM_MEM), 0, &infop->addr); + if (ret == 0 && F_ISSET(env, ENV_SYSTEM_MEM)) + rp->segid = 1; + + if (ret != 0) { + (void)__os_closehandle(env, infop->fhp); + infop->fhp = NULL; + return (ret); + } + + /* + * If we are using sparse file, we don't need to keep the file handle + * for writing or extending. + */ + if (is_sparse && infop->fhp != NULL) { + ret = __os_closehandle(env, infop->fhp); + infop->fhp = NULL; + } + return (ret); +} + +/* + * __os_detach -- + * Detach from a shared memory region. + */ +int +__os_detach(env, infop, destroy) + ENV *env; + REGINFO *infop; + int destroy; +{ + DB_ENV *dbenv; + int ret, t_ret; + + dbenv = env->dbenv; + + if (infop->wnt_handle != NULL) { + (void)CloseHandle(infop->wnt_handle); + infop->wnt_handle = NULL; + } + if (infop->fhp != NULL) { + ret = __os_closehandle(env, infop->fhp); + infop->fhp = NULL; + if (ret != 0) + return (ret); + } + + ret = !UnmapViewOfFile(infop->addr) ? __os_get_syserr() : 0; + if (ret != 0) { + __db_syserr(env, ret, DB_STR("0007", "UnmapViewOfFile")); + ret = __os_posix_err(ret); + } + + if (!F_ISSET(env, ENV_SYSTEM_MEM) && destroy && + (t_ret = __os_unlink(env, infop->name, 1)) != 0 && ret == 0) + ret = t_ret; + + return (ret); +} + +/* + * __os_mapfile -- + * Map in a shared memory file. + */ +int +__os_mapfile(env, path, fhp, len, is_rdonly, addr) + ENV *env; + char *path; + DB_FH *fhp; + int is_rdonly; + size_t len; + void **addr; +{ +#ifdef DB_WINCE + /* + * Windows CE has special requirements for file mapping to work. + * * The input handle needs to be opened using CreateFileForMapping + * * Concurrent access via a non mapped file is not supported. + * So we disable support for memory mapping files on Windows CE. It is + * currently only used as an optimization in mpool for small read only + * databases. + */ + return (EFAULT); +#else + DB_ENV *dbenv; + + dbenv = env == NULL ? NULL : env->dbenv; + + if (dbenv != NULL && + FLD_ISSET(dbenv->verbose, DB_VERB_FILEOPS | DB_VERB_FILEOPS_ALL)) + __db_msg(env, DB_STR_A("0008", "fileops: mmap %s", "%s"), path); + return (__os_map(env, path, NULL, fhp, len, 0, 0, is_rdonly, addr)); +#endif +} + +/* + * __os_unmapfile -- + * Unmap the shared memory file. + */ +int +__os_unmapfile(env, addr, len) + ENV *env; + void *addr; + size_t len; +{ + DB_ENV *dbenv; + + dbenv = env == NULL ? NULL : env->dbenv; + + if (dbenv != NULL && + FLD_ISSET(dbenv->verbose, DB_VERB_FILEOPS | DB_VERB_FILEOPS_ALL)) + __db_msg(env, DB_STR("0009", "fileops: munmap")); + + return (!UnmapViewOfFile(addr) ? __os_posix_err(__os_get_syserr()) : 0); +} + +/* + * __os_unique_name -- + * Create a unique identifying name from a pathname (may be absolute or + * relative) and/or a file descriptor. + * + * The name returned must be unique (different files map to different + * names), and repeatable (same files, map to same names). It's not + * so easy to do by name. Should handle not only: + * + * foo.bar == ./foo.bar == c:/whatever_path/foo.bar + * + * but also understand that: + * + * foo.bar == Foo.Bar (FAT file system) + * foo.bar != Foo.Bar (NTFS) + * + * The best solution is to use the file index, found in the file + * information structure (similar to UNIX inode #). + * + * When a file is deleted, its file index may be reused, + * but if the unique name has not gone from its namespace, + * we may get a conflict. So to ensure some tie in to the + * original pathname, we also use the creation time and the + * file basename. This is not a perfect system, but it + * should work for all but anamolous test cases. + * + */ +static int +__os_unique_name(orig_path, hfile, result_path, result_path_len) + _TCHAR *orig_path, *result_path; + HANDLE hfile; + size_t result_path_len; +{ + BY_HANDLE_FILE_INFORMATION fileinfo; + _TCHAR *basename, *p; + + /* + * In Windows, pathname components are delimited by '/' or '\', and + * if neither is present, we need to strip off leading drive letter + * (e.g. c:foo.txt). + */ + basename = _tcsrchr(orig_path, '/'); + p = _tcsrchr(orig_path, '\\'); + if (basename == NULL || (p != NULL && p > basename)) + basename = p; + if (basename == NULL) + basename = _tcsrchr(orig_path, ':'); + + if (basename == NULL) + basename = orig_path; + else + basename++; + + if (!GetFileInformationByHandle(hfile, &fileinfo)) + return (__os_posix_err(__os_get_syserr())); + + (void)_sntprintf(result_path, result_path_len, + _T("__db_shmem.%8.8lx.%8.8lx.%8.8lx.%8.8lx.%8.8lx.%s"), + fileinfo.dwVolumeSerialNumber, + fileinfo.nFileIndexHigh, + fileinfo.nFileIndexLow, + fileinfo.ftCreationTime.dwHighDateTime, + fileinfo.ftCreationTime.dwHighDateTime, + basename); + + return (0); +} + +/* + * __os_map -- + * The mmap(2) function for Windows. + */ +static int +__os_map(env, path, infop, fhp, len, is_region, is_system, is_rdonly, addr) + ENV *env; + REGINFO *infop; + char *path; + DB_FH *fhp; + int is_region, is_system, is_rdonly; + size_t len; + void **addr; +{ + HANDLE hMemory; + int ret, use_pagefile; + _TCHAR *tpath, shmem_name[DB_MAXPATHLEN]; + void *pMemory; + unsigned __int64 len64; + + ret = 0; + if (infop != NULL) + infop->wnt_handle = NULL; + + /* + * On 64 bit systems, len is already a 64 bit value. + * On 32 bit systems len is a 32 bit value. + * Always convert to a 64 bit value, so that the high order + * DWORD can be simply extracted on 64 bit platforms. + */ + len64 = len; + + use_pagefile = is_region && is_system; + + /* + * If creating a region in system space, get a matching name in the + * paging file namespace. + */ + if (use_pagefile) { +#ifdef DB_WINCE + __db_errx(env, DB_STR("0010", + "Unable to memory map regions using system " + "memory on WinCE.")); + return (EFAULT); +#endif + TO_TSTRING(env, path, tpath, ret); + if (ret != 0) + return (ret); + ret = __os_unique_name(tpath, fhp->handle, + shmem_name, sizeof(shmem_name)); + FREE_STRING(env, tpath); + if (ret != 0) + return (ret); + } + + /* + * XXX + * DB: We have not implemented copy-on-write here. + * + * If this is an region in system memory, we try to open it using the + * OpenFileMapping() first, and only call CreateFileMapping() if we're + * really creating the section. There are two reasons: + * + * 1) We only create the mapping if we have newly created the region. + * This avoids a long-running problem caused by Windows reference + * counting, where regions that are closed by all processes are + * deleted. It turns out that just checking for a zeroed region + * is not good enough. See [#4882] and [#7127] for the details. + * + * 2) CreateFileMapping seems to mess up making the commit charge to + * the process. It thinks, incorrectly, that when we want to join a + * previously existing section, that it should make a commit charge + * for the whole section. In fact, there is no new committed memory + * whatever. The call can fail if there is insufficient memory free + * to handle the erroneous commit charge. So, we find that the + * bogus commit is not made if we call OpenFileMapping. + */ + hMemory = NULL; + if (use_pagefile) { +#ifndef DB_WINCE + hMemory = OpenFileMapping( + is_rdonly ? FILE_MAP_READ : FILE_MAP_ALL_ACCESS, + 0, shmem_name); + + if (hMemory == NULL && F_ISSET(infop, REGION_CREATE_OK)) + hMemory = CreateFileMapping((HANDLE)-1, 0, + is_rdonly ? PAGE_READONLY : PAGE_READWRITE, + (DWORD)(len64 >> 32), (DWORD)len64, shmem_name); +#endif + } else { + hMemory = CreateFileMapping(fhp->handle, 0, + is_rdonly ? PAGE_READONLY : PAGE_READWRITE, + (DWORD)(len64 >> 32), (DWORD)len64, NULL); +#ifdef DB_WINCE + /* + * WinCE automatically closes the handle passed in. + * Ensure DB does not attempt to close the handle again. + */ + fhp->handle = INVALID_HANDLE_VALUE; + F_CLR(fhp, DB_FH_OPENED); +#endif + } + + if (hMemory == NULL) { + ret = __os_get_syserr(); + __db_syserr(env, ret, DB_STR("0011", "OpenFileMapping")); + return (__env_panic(env, __os_posix_err(ret))); + } + + pMemory = MapViewOfFile(hMemory, + (is_rdonly ? FILE_MAP_READ : FILE_MAP_ALL_ACCESS), 0, 0, len); + if (pMemory == NULL) { + ret = __os_get_syserr(); + __db_syserr(env, ret, DB_STR("0012", "MapViewOfFile")); + return (__env_panic(env, __os_posix_err(ret))); + } + + /* + * XXX + * It turns out that the kernel object underlying the named section + * is reference counted, but that the call to MapViewOfFile() above + * does NOT increment the reference count! So, if we close the handle + * here, the kernel deletes the object from the kernel namespace. + * When a second process comes along to join the region, the kernel + * happily creates a new object with the same name, but completely + * different identity. The two processes then have distinct isolated + * mapped sections, not at all what was wanted. Not closing the handle + * here fixes this problem. We carry the handle around in the region + * structure so we can close it when unmap is called. + */ + if (use_pagefile && infop != NULL) + infop->wnt_handle = hMemory; + else + CloseHandle(hMemory); + + *addr = pMemory; + return (ret); +} diff -r 000000000000 -r a1985f14b030 src/os_windows/os_mkdir.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/os_windows/os_mkdir.c Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,66 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 1997, 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + * $Id$ + */ + +#include "db_config.h" + +#include "db_int.h" + +/* + * __os_mkdir -- + * Create a directory. + */ +int +__os_mkdir(env, name, mode) + ENV *env; + const char *name; + int mode; +{ + DB_ENV *dbenv; + _TCHAR *tname; + int ret; + + dbenv = env == NULL ? NULL : env->dbenv; + + if (dbenv != NULL && + FLD_ISSET(dbenv->verbose, DB_VERB_FILEOPS | DB_VERB_FILEOPS_ALL)) + __db_msg(env, DB_STR_A("0013", "fileops: mkdir %s", + "%s"), name); + + /* Make the directory, with paranoid permissions. */ + TO_TSTRING(env, name, tname, ret); + if (ret != 0) + return (ret); + RETRY_CHK(!CreateDirectory(tname, NULL), ret); + FREE_STRING(env, tname); + if (ret != 0) + return (__os_posix_err(ret)); + + return (ret); +} diff -r 000000000000 -r a1985f14b030 src/os_windows/os_open.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/os_windows/os_open.c Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,280 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 1997, 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + * $Id$ + */ + +#include "db_config.h" + +#include "db_int.h" + +/* + * __os_open -- + * Open a file descriptor (including page size and log size information). + */ +int +__os_open(env, name, page_size, flags, mode, fhpp) + ENV *env; + const char *name; + u_int32_t page_size, flags; + int mode; + DB_FH **fhpp; +{ + DB_ENV *dbenv; + DB_FH *fhp; +#ifndef DB_WINCE + DWORD cluster_size, sector_size, free_clusters, total_clusters; + _TCHAR *drive, dbuf[4]; /* */ + +#endif + int access, attr, createflag, nrepeat, ret, share; + _TCHAR *tname; + + dbenv = env == NULL ? NULL : env->dbenv; + *fhpp = NULL; + tname = NULL; + + if (dbenv != NULL && + FLD_ISSET(dbenv->verbose, DB_VERB_FILEOPS | DB_VERB_FILEOPS_ALL)) + __db_msg(env, DB_STR_A("0025", "fileops: open %s", + "%s"), name); + +#undef OKFLAGS +#define OKFLAGS \ + (DB_OSO_ABSMODE | DB_OSO_CREATE | DB_OSO_DIRECT | DB_OSO_DSYNC |\ + DB_OSO_EXCL | DB_OSO_RDONLY | DB_OSO_REGION | DB_OSO_SEQ | \ + DB_OSO_TEMP | DB_OSO_TRUNC) + if ((ret = __db_fchk(env, "__os_open", flags, OKFLAGS)) != 0) + return (ret); + + TO_TSTRING(env, name, tname, ret); + if (ret != 0) + goto err; + + /* + * Allocate the file handle and copy the file name. We generally only + * use the name for verbose or error messages, but on systems where we + * can't unlink temporary files immediately, we use the name to unlink + * the temporary file when the file handle is closed. + * + * Lock the ENV handle and insert the new file handle on the list. + */ + if ((ret = __os_calloc(env, 1, sizeof(DB_FH), &fhp)) != 0) + return (ret); + if ((ret = __os_strdup(env, name, &fhp->name)) != 0) + goto err; + if (env != NULL) { + MUTEX_LOCK(env, env->mtx_env); + TAILQ_INSERT_TAIL(&env->fdlist, fhp, q); + MUTEX_UNLOCK(env, env->mtx_env); + F_SET(fhp, DB_FH_ENVLINK); + } + + /* + * Otherwise, use the Windows/32 CreateFile interface so that we can + * play magic games with files to get data flush effects similar to + * the POSIX O_DSYNC flag. + * + * !!! + * We currently ignore the 'mode' argument. It would be possible + * to construct a set of security attributes that we could pass to + * CreateFile that would accurately represents the mode. In worst + * case, this would require looking up user and all group names and + * creating an entry for each. Alternatively, we could call the + * _chmod (partial emulation) function after file creation, although + * this leaves us with an obvious race. However, these efforts are + * largely meaningless on FAT, the most common file system, which + * only has a "readable" and "writable" flag, applying to all users. + */ + access = GENERIC_READ; + if (!LF_ISSET(DB_OSO_RDONLY)) + access |= GENERIC_WRITE; + +#ifdef DB_WINCE + /* + * WinCE translates these flags into share flags for + * CreateFileForMapping. + * Also WinCE does not support the FILE_SHARE_DELETE flag. + */ + if (LF_ISSET(DB_OSO_REGION)) + share = GENERIC_READ | GENERIC_WRITE; + else + share = FILE_SHARE_READ | FILE_SHARE_WRITE; +#else + share = FILE_SHARE_READ | FILE_SHARE_WRITE; + if (__os_is_winnt()) + share |= FILE_SHARE_DELETE; +#endif + attr = FILE_ATTRIBUTE_NORMAL; + + /* + * Reproduce POSIX 1003.1 semantics: if O_CREATE and O_EXCL are both + * specified, fail, returning EEXIST, unless we create the file. + */ + if (LF_ISSET(DB_OSO_CREATE) && LF_ISSET(DB_OSO_EXCL)) + createflag = CREATE_NEW; /* create only if !exist*/ + else if (!LF_ISSET(DB_OSO_CREATE) && LF_ISSET(DB_OSO_TRUNC)) + createflag = TRUNCATE_EXISTING; /* truncate, fail if !exist */ + else if (LF_ISSET(DB_OSO_TRUNC)) + createflag = CREATE_ALWAYS; /* create and truncate */ + else if (LF_ISSET(DB_OSO_CREATE)) + createflag = OPEN_ALWAYS; /* open or create */ + else + createflag = OPEN_EXISTING; /* open only if existing */ + + if (LF_ISSET(DB_OSO_DSYNC)) { + F_SET(fhp, DB_FH_NOSYNC); + attr |= FILE_FLAG_WRITE_THROUGH; + } + +#ifndef DB_WINCE + if (LF_ISSET(DB_OSO_SEQ)) + attr |= FILE_FLAG_SEQUENTIAL_SCAN; + else + attr |= FILE_FLAG_RANDOM_ACCESS; +#endif + + if (LF_ISSET(DB_OSO_TEMP)) + attr |= FILE_FLAG_DELETE_ON_CLOSE; + + /* + * We can turn filesystem buffering off if the page size is a + * multiple of the disk's sector size. To find the sector size, + * we call GetDiskFreeSpace, which expects a drive name like "d:\\" + * or NULL for the current disk (i.e., a relative path). + * + * WinCE only has GetDiskFreeSpaceEx which does not + * return the sector size. + */ +#ifndef DB_WINCE + if (LF_ISSET(DB_OSO_DIRECT) && page_size != 0 && name[0] != '\0') { + if (name[1] == ':') { + drive = dbuf; + _sntprintf(dbuf, sizeof(dbuf), _T("%c:\\"), tname[0]); + } else + drive = NULL; + + /* + * We ignore all results except sectorsize, but some versions + * of Windows require that the parameters are non-NULL. + */ + if (GetDiskFreeSpace(drive, &cluster_size, + §or_size, &free_clusters, &total_clusters) && + page_size % sector_size == 0) + attr |= FILE_FLAG_NO_BUFFERING; + } +#endif + + fhp->handle = fhp->trunc_handle = INVALID_HANDLE_VALUE; + for (nrepeat = 1;; ++nrepeat) { + if (fhp->handle == INVALID_HANDLE_VALUE) { +#ifdef DB_WINCE + if (LF_ISSET(DB_OSO_REGION)) + fhp->handle = CreateFileForMapping(tname, + access, share, NULL, createflag, attr, 0); + else +#endif + fhp->handle = CreateFile(tname, + access, share, NULL, createflag, attr, 0); + } + +#ifdef HAVE_FTRUNCATE + /* + * Older versions of WinCE may not support truncate, if so, the + * HAVE_FTRUNCATE macro should be #undef'ed, and we + * don't need to open this second handle. + * + * WinCE dose not support opening a second handle on the same + * file via CreateFileForMapping, but this dose not matter + * since we are not truncating region files but database files. + * + * But some older versions of WinCE even + * dose not allow a second handle opened via CreateFile. If + * this is the case, users will need to #undef the + * HAVE_FTRUNCATE macro in build_wince/db_config.h. + */ + + /* + * Windows does not provide truncate directly. There is no + * safe way to use a handle for truncate concurrently with + * reads or writes. To deal with this, we open a second handle + * used just for truncating. + */ + if (fhp->handle != INVALID_HANDLE_VALUE && + !LF_ISSET(DB_OSO_RDONLY | DB_OSO_TEMP) && + fhp->trunc_handle == INVALID_HANDLE_VALUE +#ifdef DB_WINCE + /* Do not open trunc handle for region files. */ + && (!LF_ISSET(DB_OSO_REGION)) +#endif + ) + fhp->trunc_handle = CreateFile( + tname, access, share, NULL, OPEN_EXISTING, attr, 0); +#endif + +#ifndef HAVE_FTRUNCATE + if (fhp->handle == INVALID_HANDLE_VALUE) +#else + if (fhp->handle == INVALID_HANDLE_VALUE || + (!LF_ISSET(DB_OSO_RDONLY | DB_OSO_TEMP) && + fhp->trunc_handle == INVALID_HANDLE_VALUE +#ifdef DB_WINCE + /* Do not open trunc handle for region files. */ + && (!LF_ISSET(DB_OSO_REGION)) +#endif + )) +#endif + { + /* + * If it's a "temporary" error, we retry up to 3 times, + * waiting up to 12 seconds. While it's not a problem + * if we can't open a database, an inability to open a + * log file is cause for serious dismay. + */ + ret = __os_posix_err(__os_get_syserr()); + if ((ret != ENFILE && ret != EMFILE && ret != ENOSPC) || + nrepeat > 3) + goto err; + + __os_yield(env, nrepeat * 2, 0); + } else + break; + } + + FREE_STRING(env, tname); + + if (LF_ISSET(DB_OSO_REGION)) + F_SET(fhp, DB_FH_REGION); + F_SET(fhp, DB_FH_OPENED); + *fhpp = fhp; + return (0); + +err: FREE_STRING(env, tname); + if (fhp != NULL) + (void)__os_closehandle(env, fhp); + return (ret); +} diff -r 000000000000 -r a1985f14b030 src/os_windows/os_rename.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/os_windows/os_rename.c Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,104 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 1997, 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + * $Id$ + */ + +#include "db_config.h" + +#include "db_int.h" + +/* + * __os_rename -- + * Rename a file. + */ +int +__os_rename(env, oldname, newname, silent) + ENV *env; + const char *oldname, *newname; + u_int32_t silent; +{ + DB_ENV *dbenv; + _TCHAR *toldname, *tnewname; + int ret; + + dbenv = env == NULL ? NULL : env->dbenv; + + if (dbenv != NULL && + FLD_ISSET(dbenv->verbose, DB_VERB_FILEOPS | DB_VERB_FILEOPS_ALL)) + __db_msg(env, DB_STR_A("0036", "fileops: rename %s to %s", + "%s %s"), oldname, newname); + + TO_TSTRING(env, oldname, toldname, ret); + if (ret != 0) + return (ret); + TO_TSTRING(env, newname, tnewname, ret); + if (ret != 0) { + FREE_STRING(env, toldname); + return (ret); + } + + LAST_PANIC_CHECK_BEFORE_IO(env); + + if (!MoveFile(toldname, tnewname)) + ret = __os_get_syserr(); + + if (__os_posix_err(ret) == EEXIST) { + ret = 0; +#ifndef DB_WINCE + if (__os_is_winnt()) { + if (!MoveFileEx( + toldname, tnewname, MOVEFILE_REPLACE_EXISTING)) + ret = __os_get_syserr(); + } else +#endif + { + /* + * There is no MoveFileEx for Win9x/Me/CE, so we have to + * do the best we can. Note that the MoveFile call + * above would have succeeded if oldname and newname + * refer to the same file, so we don't need to check + * that here. + */ + (void)DeleteFile(tnewname); + if (!MoveFile(toldname, tnewname)) + ret = __os_get_syserr(); + } + } + + FREE_STRING(env, tnewname); + FREE_STRING(env, toldname); + + if (ret != 0) { + if (silent == 0) + __db_syserr(env, ret, DB_STR_A("0037", + "MoveFileEx %s %s", "%s %s"), oldname, newname); + ret = __os_posix_err(ret); + } + + return (ret); +} diff -r 000000000000 -r a1985f14b030 src/os_windows/os_rw.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/os_windows/os_rw.c Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,240 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 1997, 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + * $Id$ + */ + +#include "db_config.h" + +#include "db_int.h" + +/* + * __os_io -- + * Do an I/O. + */ +int +__os_io(env, op, fhp, pgno, pgsize, relative, io_len, buf, niop) + ENV *env; + int op; + DB_FH *fhp; + db_pgno_t pgno; + u_int32_t pgsize, relative, io_len; + u_int8_t *buf; + size_t *niop; +{ + int ret; + +#ifndef DB_WINCE + if (__os_is_winnt()) { + DB_ENV *dbenv; + DWORD nbytes; + OVERLAPPED over; + ULONG64 off; + dbenv = env == NULL ? NULL : env->dbenv; + if ((off = relative) == 0) + off = (ULONG64)pgsize * pgno; + over.Offset = (DWORD)(off & 0xffffffff); + over.OffsetHigh = (DWORD)(off >> 32); + over.hEvent = 0; /* we don't want asynchronous notifications */ + + if (dbenv != NULL && + FLD_ISSET(dbenv->verbose, DB_VERB_FILEOPS_ALL)) + __db_msg(env, DB_STR_A("0014", + "fileops: %s %s: %lu bytes at offset %lu", + "%s %s %lu %lu"), op == DB_IO_READ ? + DB_STR_P("read") : DB_STR_P("write"), + fhp->name, (u_long)io_len, (u_long)off); + + LAST_PANIC_CHECK_BEFORE_IO(env); + + switch (op) { + case DB_IO_READ: +#if defined(HAVE_STATISTICS) + ++fhp->read_count; +#endif + if (!ReadFile(fhp->handle, + buf, (DWORD)io_len, &nbytes, &over)) + goto slow; + break; + case DB_IO_WRITE: +#ifdef HAVE_FILESYSTEM_NOTZERO + if (__os_fs_notzero()) + goto slow; +#endif +#if defined(HAVE_STATISTICS) + ++fhp->write_count; +#endif + if (!WriteFile(fhp->handle, + buf, (DWORD)io_len, &nbytes, &over)) + goto slow; + break; + } + if (nbytes == io_len) { + *niop = (size_t)nbytes; + return (0); + } + } + +slow: +#endif + MUTEX_LOCK(env, fhp->mtx_fh); + + if ((ret = __os_seek(env, fhp, pgno, pgsize, relative)) != 0) + goto err; + + switch (op) { + case DB_IO_READ: + ret = __os_read(env, fhp, buf, io_len, niop); + break; + case DB_IO_WRITE: + ret = __os_write(env, fhp, buf, io_len, niop); + break; + } + +err: MUTEX_UNLOCK(env, fhp->mtx_fh); + + return (ret); +} + +/* + * __os_read -- + * Read from a file handle. + */ +int +__os_read(env, fhp, addr, len, nrp) + ENV *env; + DB_FH *fhp; + void *addr; + size_t len; + size_t *nrp; +{ + DB_ENV *dbenv; + DWORD count; + size_t offset, nr; + u_int8_t *taddr; + int ret; + + dbenv = env == NULL ? NULL : env->dbenv; + ret = 0; + +#if defined(HAVE_STATISTICS) + ++fhp->read_count; +#endif + if (dbenv != NULL && FLD_ISSET(dbenv->verbose, DB_VERB_FILEOPS_ALL)) + __db_msg(env, DB_STR_A("0015", "fileops: read %s: %lu bytes", + "%s %lu"), fhp->name, (u_long)len); + + for (taddr = addr, + offset = 0; offset < len; taddr += nr, offset += nr) { + LAST_PANIC_CHECK_BEFORE_IO(env); + RETRY_CHK((!ReadFile(fhp->handle, + taddr, (DWORD)(len - offset), &count, NULL)), ret); + if (count == 0 || ret != 0) + break; + nr = (size_t)count; + } + *nrp = taddr - (u_int8_t *)addr; + if (ret != 0) { + __db_syserr(env, ret, DB_STR_A("0016", + "read: 0x%lx, %lu", "%lx %lu"), + P_TO_ULONG(taddr), (u_long)len - offset); + ret = __os_posix_err(ret); + } + return (ret); +} + +/* + * __os_write -- + * Write to a file handle. + */ +int +__os_write(env, fhp, addr, len, nwp) + ENV *env; + DB_FH *fhp; + void *addr; + size_t len; + size_t *nwp; +{ + int ret; + +#ifdef HAVE_FILESYSTEM_NOTZERO + /* Zero-fill as necessary. */ + if (__os_fs_notzero() && + (ret = __db_zero_fill(env, fhp)) != 0) + return (ret); +#endif + return (__os_physwrite(env, fhp, addr, len, nwp)); +} + +/* + * __os_physwrite -- + * Physical write to a file handle. + */ +int +__os_physwrite(env, fhp, addr, len, nwp) + ENV *env; + DB_FH *fhp; + void *addr; + size_t len; + size_t *nwp; +{ + DB_ENV *dbenv; + DWORD count; + size_t offset, nw; + u_int8_t *taddr; + int ret; + + dbenv = env == NULL ? NULL : env->dbenv; + ret = 0; + +#if defined(HAVE_STATISTICS) + ++fhp->write_count; +#endif + if (dbenv != NULL && FLD_ISSET(dbenv->verbose, DB_VERB_FILEOPS_ALL)) + __db_msg(env, DB_STR_A("0017", "fileops: write %s: %lu bytes", + "%s %lu"), fhp->name, (u_long)len); + + for (taddr = addr, + offset = 0; offset < len; taddr += nw, offset += nw) { + LAST_PANIC_CHECK_BEFORE_IO(env); + RETRY_CHK((!WriteFile(fhp->handle, + taddr, (DWORD)(len - offset), &count, NULL)), ret); + if (ret != 0) + break; + nw = (size_t)count; + } + *nwp = len; + if (ret != 0) { + __db_syserr(env, ret, DB_STR_A("0018", + "write: %#lx, %lu", "%#lx %lu"), + P_TO_ULONG(taddr), (u_long)len - offset); + ret = __os_posix_err(ret); + + DB_EVENT(env, DB_EVENT_WRITE_FAILED, NULL); + } + return (ret); +} diff -r 000000000000 -r a1985f14b030 src/os_windows/os_seek.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/os_windows/os_seek.c Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,89 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 1997, 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + * $Id$ + */ + +#include "db_config.h" + +#include "db_int.h" + +/* + * __os_seek -- + * Seek to a page/byte offset in the file. + */ +int +__os_seek(env, fhp, pgno, pgsize, relative) + ENV *env; + DB_FH *fhp; + db_pgno_t pgno; + u_int32_t pgsize; + off_t relative; +{ + /* Yes, this really is how Microsoft designed their API. */ + union { + __int64 bigint; + struct { + unsigned long low; + long high; + }; + } offbytes; + DB_ENV *dbenv; + off_t offset; + int ret; + + dbenv = env == NULL ? NULL : env->dbenv; + +#if defined(HAVE_STATISTICS) + ++fhp->seek_count; +#endif + + offset = (off_t)pgsize * pgno + relative; + + if (dbenv != NULL && FLD_ISSET(dbenv->verbose, DB_VERB_FILEOPS_ALL)) + __db_msg(env, DB_STR_A("0038", + "fileops: seek %s to %lu", "%s %lu"), + fhp->name, (u_long)offset); + + offbytes.bigint = offset; + ret = (SetFilePointer(fhp->handle, offbytes.low, + &offbytes.high, FILE_BEGIN) == (DWORD)-1) ? __os_get_syserr() : 0; + + if (ret == 0) { + fhp->pgsize = pgsize; + fhp->pgno = pgno; + fhp->offset = relative; + } else { + __db_syserr(env, ret, DB_STR_A("0039", + "seek: %lu: (%lu * %lu) + %lu", "%lu %lu %lu %lu"), + (u_long)offset, (u_long)pgno, + (u_long)pgsize, (u_long)relative); + ret = __os_posix_err(ret); + } + + return (ret); +} diff -r 000000000000 -r a1985f14b030 src/os_windows/os_stat.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/os_windows/os_stat.c Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,253 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 1997, 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + * $Id$ + */ + +#include "db_config.h" + +#include "db_int.h" + +/* + * Raw data reads must be done in multiples of the disk sector size. Currently + * the sector size is either 512 bytes or 4096 bytes. So we set the + * MAX_SECTOR_SIZE to 4096. + */ +#define MAX_SECTOR_SIZE 4096 + +/* + * Find the cluster size of the file system that would contain the given path. + * If the value can't be determined, an error is returned. + */ +int +__os_get_cluster_size(path, psize) + const char *path; + u_int32_t *psize; +{ + +#if (WINVER < 0x500) || defined(DB_WINCE) + /* + * WinCE and versions of Windows earlier than Windows NT don't have + * the APIs required to retrieve the cluster size. + */ + *psize = DB_DEF_IOSIZE; + return (0); +#else + BYTE clustershift, sectorshift, *pcluster; + char buffer[MAX_SECTOR_SIZE]; + DWORD flags, infolen, length, mcl, name_size; + HANDLE vhandle; + int ret; + NTFS_VOLUME_DATA_BUFFER ntfsinfo; + size_t name_len; + TCHAR *env_path, name_buffer[MAX_PATH + 1], root_path[MAX_PATH + 1]; + WORD *psector; + + if (path == NULL || psize == NULL) { + return (EINVAL); + } + + name_size = MAX_PATH + 1; + *psize = 0; + + TO_TSTRING(NULL, path, env_path, ret); + if (ret != 0) + return (ret); + /* Retrieve the volume root path where the input path resides. */ + if (!GetVolumePathName(env_path, root_path, name_size)) { + FREE_STRING(NULL, env_path); + return (__os_posix_err(__os_get_syserr())); + } + FREE_STRING(NULL, env_path); + + /* Get the volume GUID name from the root path. */ + if (!GetVolumeNameForVolumeMountPoint( + root_path, name_buffer, name_size)) + return (__os_posix_err(__os_get_syserr())); + + /* Delete the last trail "\" in the GUID name. */ + name_len = _tcsclen(name_buffer); + if (name_len > 0) + name_buffer[name_len - 1] = _T('\0'); + + /* Create a handle to the volume. */ + vhandle = CreateFile(name_buffer, FILE_READ_ATTRIBUTES | FILE_READ_DATA, + FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL, NULL); + + /* If open failed, return error */ + if (vhandle == INVALID_HANDLE_VALUE) + return (__os_posix_err(__os_get_syserr())); + + /* Get the volume information through the root path. */ + if (!GetVolumeInformation(root_path, NULL, name_size, NULL, &mcl, + &flags, name_buffer, name_size)) { + ret = __os_posix_err(__os_get_syserr()); + CloseHandle(vhandle); + return (ret); + } + + ret = 0; + if (_tcscmp(name_buffer, _T("NTFS")) == 0) { + /* + * If this is NTFS file system, use FSCTL_GET_NTFS_VOLUME_DATA + * to get the cluster size. + */ + if (DeviceIoControl( + vhandle, /* volume handle */ + FSCTL_GET_NTFS_VOLUME_DATA, /* Control Code */ + NULL, /* not use */ + 0, /* not use */ + &ntfsinfo, /* output buffer */ + sizeof(NTFS_VOLUME_DATA_BUFFER),/* output buffer length */ + &infolen, /* number of returned bytes */ + NULL)) /* ignore here */ + *psize = ntfsinfo.BytesPerCluster; + else + ret = __os_posix_err(__os_get_syserr()); + } else if (_tcscmp(name_buffer, _T("exFAT")) == 0) { + /* + * If this is exFAT file system, read the information of sector + * and cluster from the BPB on sector 0 + * +6C H: BYTE SectorSizeShift + * +6D H: BYTE ClusterShift + */ + if (ReadFile(vhandle, buffer, MAX_SECTOR_SIZE, &length, NULL)) { + sectorshift = *(BYTE *)(&buffer[0x6C]); + clustershift = *(BYTE *)(&buffer[0x6D]); + *psize = 1 << sectorshift; + *psize = (*psize) << clustershift; + } + else + ret = __os_posix_err(__os_get_syserr()); + } else if (_tcscmp(name_buffer, _T("FAT")) == 0 || + _tcscmp(name_buffer, _T("FAT32")) == 0) { + /* + * If this is FAT or FAT32 file system, read the information of + * sector and cluster from the BPB on sector 0. + * +0B H: WORD Bytes per Sector. + * +0D H: BYTE Sectors Per Cluster. + */ + if (ReadFile(vhandle, buffer, MAX_SECTOR_SIZE, &length, NULL)) { + psector = (WORD *)(&buffer[0x0B]); + pcluster = (BYTE *)(&buffer[0x0D]); + *psize = (*psector) * (*pcluster); + } + else + ret = __os_posix_err(__os_get_syserr()); + } + + CloseHandle(vhandle); + return (ret); +#endif +} + +/* + * __os_exists -- + * Return if the file exists. + */ +int +__os_exists(env, path, isdirp) + ENV *env; + const char *path; + int *isdirp; +{ + DB_ENV *dbenv; + DWORD attrs; + _TCHAR *tpath; + int ret; + + dbenv = env == NULL ? NULL : env->dbenv; + + TO_TSTRING(env, path, tpath, ret); + if (ret != 0) + return (ret); + + if (dbenv != NULL && + FLD_ISSET(dbenv->verbose, DB_VERB_FILEOPS | DB_VERB_FILEOPS_ALL)) + __db_msg(env, DB_STR_A("0033", "fileops: stat %s", + "%s"), path); + + RETRY_CHK( + ((attrs = GetFileAttributes(tpath)) == (DWORD)-1 ? 1 : 0), ret); + if (ret == 0) { + if (isdirp != NULL) + *isdirp = (attrs & FILE_ATTRIBUTE_DIRECTORY); + } else + ret = __os_posix_err(ret); + + FREE_STRING(env, tpath); + return (ret); +} + +/* + * __os_ioinfo -- + * Return file size and I/O size; abstracted to make it easier + * to replace. + */ +int +__os_ioinfo(env, path, fhp, mbytesp, bytesp, iosizep) + ENV *env; + const char *path; + DB_FH *fhp; + u_int32_t *mbytesp, *bytesp, *iosizep; +{ + int ret; + BY_HANDLE_FILE_INFORMATION bhfi; + unsigned __int64 filesize; + u_int32_t io_sz; + + RETRY_CHK((!GetFileInformationByHandle(fhp->handle, &bhfi)), ret); + if (ret != 0) { + __db_syserr(env, ret, DB_STR("0034", + "GetFileInformationByHandle")); + return (__os_posix_err(ret)); + } + + filesize = ((unsigned __int64)bhfi.nFileSizeHigh << 32) + + bhfi.nFileSizeLow; + + /* Return the size of the file. */ + if (mbytesp != NULL) + *mbytesp = (u_int32_t)(filesize / MEGABYTE); + if (bytesp != NULL) + *bytesp = (u_int32_t)(filesize % MEGABYTE); + + if (iosizep != NULL) { + /* + * Attempt to retrieve a file system cluster size, if the + * call succeeds, and the value returned is reasonable, + * use it as the default page size. Otherwise use a + * reasonable default value. + */ + if (__os_get_cluster_size(path, &io_sz) != 0 || io_sz < 1025) + *iosizep = DB_DEF_IOSIZE; + else + *iosizep = io_sz; + } + return (0); +} diff -r 000000000000 -r a1985f14b030 src/os_windows/os_truncate.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/os_windows/os_truncate.c Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,121 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 2004, 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + * $Id$ + */ + +#include "db_config.h" + +#include "db_int.h" + +/* + * __os_truncate -- + * Truncate the file. + */ +int +__os_truncate(env, fhp, pgno, pgsize) + ENV *env; + DB_FH *fhp; + db_pgno_t pgno; + u_int32_t pgsize; +{ + /* Yes, this really is how Microsoft have designed their API */ + union { + __int64 bigint; + struct { + unsigned long low; + long high; + }; + } off; + DB_ENV *dbenv; + off_t offset; + int ret; + + dbenv = env == NULL ? NULL : env->dbenv; + offset = (off_t)pgsize * pgno; + ret = 0; + + if (dbenv != NULL && + FLD_ISSET(dbenv->verbose, DB_VERB_FILEOPS | DB_VERB_FILEOPS_ALL)) + __db_msg(env, DB_STR_A("0021", "fileops: truncate %s to %lu", + "%s %lu"), fhp->name, (u_long)offset); + +#ifdef HAVE_FILESYSTEM_NOTZERO + /* + * If the filesystem doesn't zero fill, it isn't safe to extend the + * file, or we end up with junk blocks. Just return in that case. + */ + if (__os_fs_notzero()) { + off_t stat_offset; + u_int32_t mbytes, bytes; + + /* Stat the file. */ + if ((ret = + __os_ioinfo(env, NULL, fhp, &mbytes, &bytes, NULL)) != 0) + return (ret); + stat_offset = (off_t)mbytes * MEGABYTE + bytes; + + if (offset > stat_offset) + return (0); + } +#endif + + LAST_PANIC_CHECK_BEFORE_IO(env); + + /* + * Windows doesn't provide truncate directly. Instead, it has + * SetEndOfFile, which truncates to the current position. To + * deal with that, we open a duplicate file handle for truncating. + * + * We want to retry the truncate call, which involves a SetFilePointer + * and a SetEndOfFile, but there are several complications: + * + * 1) since the Windows API deals in 32-bit values, it's possible that + * the return from SetFilePointer (the low 32-bits) is + * INVALID_SET_FILE_POINTER even when the call has succeeded. So we + * have to also check whether GetLastError() returns NO_ERROR. + * + * 2) when it returns, SetFilePointer overwrites the high bits of the + * offset, so if we need to retry, we have to reset the offset each + * time. + * + * We can't switch to SetFilePointerEx, which knows about 64-bit + * offsets, because it isn't supported on Win9x/ME. + */ + RETRY_CHK((off.bigint = (__int64)pgsize * pgno, + (SetFilePointer(fhp->trunc_handle, off.low, &off.high, FILE_BEGIN) + == INVALID_SET_FILE_POINTER && GetLastError() != NO_ERROR) || + !SetEndOfFile(fhp->trunc_handle)), ret); + + if (ret != 0) { + __db_syserr(env, ret, DB_STR_A("0022", "SetFilePointer: %lu", + "%lu"), pgno * pgsize); + ret = __os_posix_err(ret); + } + + return (ret); +} diff -r 000000000000 -r a1985f14b030 src/os_windows/os_unlink.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/os_windows/os_unlink.c Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,145 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 1997, 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + * $Id$ + */ + +#include "db_config.h" + +#include "db_int.h" + +/* + * __os_unlink -- + * Remove a file. + */ +int +__os_unlink(env, path, overwrite_test) + ENV *env; + const char *path; + int overwrite_test; +{ + DB_ENV *dbenv; + HANDLE h; + _TCHAR *tpath, *orig_tpath, buf[DB_MAXPATHLEN]; + u_int32_t id; + int ret, t_ret; + + dbenv = env == NULL ? NULL : env->dbenv; + + if (dbenv != NULL && + FLD_ISSET(dbenv->verbose, DB_VERB_FILEOPS | DB_VERB_FILEOPS_ALL)) + __db_msg(env, DB_STR_A("0028", "fileops: unlink %s", + "%s"), path); + + /* Optionally overwrite the contents of the file to enhance security. */ + if (dbenv != NULL && overwrite_test && F_ISSET(dbenv, DB_ENV_OVERWRITE)) + (void)__db_file_multi_write(env, path); + + TO_TSTRING(env, path, tpath, ret); + if (ret != 0) + return (ret); + orig_tpath = tpath; + + LAST_PANIC_CHECK_BEFORE_IO(env); + + /* + * Windows NT and its descendants allow removal of open files, but the + * DeleteFile Win32 system call isn't equivalent to a POSIX unlink. + * Firstly, it only succeeds if FILE_SHARE_DELETE is set when the file + * is opened. Secondly, it leaves the file in a "zombie" state, where + * it can't be opened again, but a new file with the same name can't be + * created either. + * + * Since we depend on being able to recreate files (during recovery, + * say), we have to first rename the file, and then delete it. It + * still hangs around, but with a name we don't care about. The rename + * will fail if the file doesn't exist, which isn't a problem, but if + * it fails for some other reason, we need to know about it or a + * subsequent open may fail for no apparent reason. + */ + if (__os_is_winnt()) { + __os_unique_id(env, &id); + _sntprintf(buf, DB_MAXPATHLEN, _T("%s.del.%010u"), tpath, id); + if (MoveFile(tpath, buf)) + tpath = buf; + else { + ret = __os_get_syserr(); + if (__os_posix_err(ret) != ENOENT) + /* + * System doesn't always return ENOENT when + * file is missing. So we need a double check + * here. Set the return value to ENOENT when + * file doesn't exist. + */ + if (__os_exists(env, path, NULL) == 0) + __db_err(env, ret, DB_STR_A("0029", + "MoveFile: " + "rename %s to temporary file", + "%s"), path); + else + ret = ENOENT; + } + + /* + * Try removing the file using the delete-on-close flag. This + * plays nicer with files that are still open than DeleteFile. + */ + h = CreateFile(tpath, 0, + FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, + NULL, OPEN_EXISTING, FILE_FLAG_DELETE_ON_CLOSE, 0); + if (h != INVALID_HANDLE_VALUE) { + (void)CloseHandle (h); + if (GetFileAttributes(tpath) == INVALID_FILE_ATTRIBUTES) + goto skipdel; + } + } + + RETRY_CHK((!DeleteFile(tpath)), ret); + +skipdel: + FREE_STRING(env, orig_tpath); + + /* + * XXX + * We shouldn't be testing for an errno of ENOENT here, but ENOENT + * signals that a file is missing, and we attempt to unlink things + * (such as v. 2.x environment regions, in ENV->remove) that we + * are expecting not to be there. Reporting errors in these cases + * is annoying. + */ + if ((ret != 0) && (t_ret = __os_posix_err(ret)) != ENOENT) { + /* Double check if the file exists. */ + if (__os_exists(env, path, NULL) == 0) { + __db_syserr(env, ret, DB_STR_A("0030", + "DeleteFile: %s", "%s"), path); + ret = t_ret; + } else + ret = ENOENT; + } + + return (ret); +} diff -r 000000000000 -r a1985f14b030 src/os_windows/os_yield.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/os_windows/os_yield.c Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,57 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 1997, 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + * $Id$ + */ + +#include "db_config.h" + +#include "db_int.h" + +/* + * __os_yield -- + * Yield the processor, optionally pausing until running again. + */ +void +__os_yield(env, secs, usecs) + ENV *env; + u_long secs, usecs; /* Seconds and microseconds. */ +{ + COMPQUIET(env, NULL); + + /* Don't require the values be normalized. */ + for (; usecs >= US_PER_SEC; usecs -= US_PER_SEC) + ++secs; + + /* + * Yield the processor so other processes or threads can run. + * + * Sheer raving paranoia -- don't sleep for 0 time, in case some + * implementation doesn't yield the processor in that case. + */ + Sleep(secs * MS_PER_SEC + (usecs / US_PER_MS) + 1); +} diff -r 000000000000 -r a1985f14b030 src/qam/qam_stub.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/qam/qam_stub.c Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,361 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 1996, 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + * $Id$ + */ + +#ifndef HAVE_QUEUE +#include "db_config.h" + +#include "db_int.h" +#include "dbinc/db_page.h" +#include "dbinc/qam.h" + +/* + * If the library wasn't compiled with the Queue access method, various + * routines aren't available. Stub them here, returning an appropriate + * error. + */ + +/* + * __db_no_queue_am -- + * Error when a Berkeley DB build doesn't include the access method. + * + * PUBLIC: int __db_no_queue_am __P((ENV *)); + */ +int +__db_no_queue_am(env) + ENV *env; +{ + __db_errx(env, DB_STR("1145", + "library build did not include support for the Queue access method")); + return (DB_OPNOTSUP); +} + +int +__db_prqueue(dbp, flags) + DB *dbp; + u_int32_t flags; +{ + COMPQUIET(flags, 0); + return (__db_no_queue_am(dbp->env)); +} + +int +__qam_31_qammeta(dbp, real_name, buf) + DB *dbp; + char *real_name; + u_int8_t *buf; +{ + COMPQUIET(real_name, NULL); + COMPQUIET(buf, NULL); + return (__db_no_queue_am(dbp->env)); +} + +int +__qam_32_qammeta(dbp, real_name, buf) + DB *dbp; + char *real_name; + u_int8_t *buf; +{ + COMPQUIET(real_name, NULL); + COMPQUIET(buf, NULL); + return (__db_no_queue_am(dbp->env)); +} + +int +__qam_append(dbc, key, data) + DBC *dbc; + DBT *key, *data; +{ + COMPQUIET(key, NULL); + COMPQUIET(data, NULL); + return (__db_no_queue_am(dbc->env)); +} + +int +__qamc_dup(orig_dbc, new_dbc) + DBC *orig_dbc, *new_dbc; +{ + COMPQUIET(new_dbc, NULL); + return (__db_no_queue_am(orig_dbc->env)); +} + +int +__qamc_init(dbc) + DBC *dbc; +{ + return (__db_no_queue_am(dbc->env)); +} + +int +__qam_db_close(dbp, flags) + DB *dbp; + u_int32_t flags; +{ + COMPQUIET(dbp, NULL); + COMPQUIET(flags, 0); + return (0); +} + +int +__qam_db_create(dbp) + DB *dbp; +{ + COMPQUIET(dbp, NULL); + return (0); +} + +int +__qam_extent_names(env, name, namelistp) + ENV *env; + char *name; + char ***namelistp; +{ + COMPQUIET(name, NULL); + COMPQUIET(namelistp, NULL); + return (__db_no_queue_am(env)); +} + +int +__qam_gen_filelist(dbp, ip, filelistp) + DB *dbp; + DB_THREAD_INFO *ip; + QUEUE_FILELIST **filelistp; +{ + COMPQUIET(ip, NULL); + COMPQUIET(filelistp, NULL); + return (__db_no_queue_am(dbp->env)); +} + +int +__qam_init_print(env, dtabp) + ENV *env; + DB_DISTAB *dtabp; +{ + COMPQUIET(env, NULL); + COMPQUIET(dtabp, NULL); + return (0); +} + +int +__qam_init_recover(env, dtabp) + ENV *env; + DB_DISTAB *dtabp; +{ + COMPQUIET(env, NULL); + COMPQUIET(dtabp, NULL); + return (0); +} + +int +__qam_metachk(dbp, name, qmeta) + DB *dbp; + const char *name; + QMETA *qmeta; +{ + COMPQUIET(name, NULL); + COMPQUIET(qmeta, NULL); + return (__db_no_queue_am(dbp->env)); +} + +int +__qam_mswap(env, pg) + ENV *env; + PAGE *pg; +{ + COMPQUIET(pg, NULL); + return (__db_no_queue_am(env)); +} + +int +__qam_new_file(dbp, ip, txn, fhp, name) + DB *dbp; + DB_THREAD_INFO *ip; + DB_TXN *txn; + DB_FH *fhp; + const char *name; +{ + COMPQUIET(ip, NULL); + COMPQUIET(txn, NULL); + COMPQUIET(fhp, NULL); + COMPQUIET(name, NULL); + return (__db_no_queue_am(dbp->env)); +} + +int +__qam_open(dbp, ip, txn, name, base_pgno, mode, flags) + DB *dbp; + DB_THREAD_INFO *ip; + DB_TXN *txn; + const char *name; + db_pgno_t base_pgno; + int mode; + u_int32_t flags; +{ + COMPQUIET(ip, NULL); + COMPQUIET(txn, NULL); + COMPQUIET(name, NULL); + COMPQUIET(base_pgno, 0); + COMPQUIET(mode, 0); + COMPQUIET(flags, 0); + return (__db_no_queue_am(dbp->env)); +} + +int +__qam_pgin_out(env, pg, pp, cookie) + ENV *env; + db_pgno_t pg; + void *pp; + DBT *cookie; +{ + COMPQUIET(pg, 0); + COMPQUIET(pp, NULL); + COMPQUIET(cookie, NULL); + return (__db_no_queue_am(env)); +} + +int +__qam_salvage(dbp, vdp, pgno, h, handle, callback, flags) + DB *dbp; + VRFY_DBINFO *vdp; + db_pgno_t pgno; + PAGE *h; + void *handle; + int (*callback) __P((void *, const void *)); + u_int32_t flags; +{ + COMPQUIET(vdp, NULL); + COMPQUIET(pgno, 0); + COMPQUIET(h, NULL); + COMPQUIET(handle, NULL); + COMPQUIET(callback, NULL); + COMPQUIET(flags, 0); + return (__db_no_queue_am(dbp->env)); +} + +int +__qam_set_ext_data(dbp, name) + DB *dbp; + const char *name; +{ + COMPQUIET(name, NULL); + return (__db_no_queue_am(dbp->env)); +} + +int +__qam_stat(dbc, spp, flags) + DBC *dbc; + void *spp; + u_int32_t flags; +{ + COMPQUIET(spp, NULL); + COMPQUIET(flags, 0); + return (__db_no_queue_am(dbc->env)); +} + +int +__qam_stat_print(dbc, flags) + DBC *dbc; + u_int32_t flags; +{ + COMPQUIET(flags, 0); + return (__db_no_queue_am(dbc->env)); +} + +int +__qam_sync(dbp) + DB *dbp; +{ + return (__db_no_queue_am(dbp->env)); +} + +int +__qam_truncate(dbc, countp) + DBC *dbc; + u_int32_t *countp; +{ + COMPQUIET(countp, NULL); + return (__db_no_queue_am(dbc->env)); +} + +int +__qam_vrfy_data(dbp, vdp, h, pgno, flags) + DB *dbp; + VRFY_DBINFO *vdp; + QPAGE *h; + db_pgno_t pgno; + u_int32_t flags; +{ + COMPQUIET(vdp, NULL); + COMPQUIET(h, NULL); + COMPQUIET(pgno, 0); + COMPQUIET(flags, 0); + return (__db_no_queue_am(dbp->env)); +} + +int +__qam_vrfy_meta(dbp, vdp, meta, pgno, flags) + DB *dbp; + VRFY_DBINFO *vdp; + QMETA *meta; + db_pgno_t pgno; + u_int32_t flags; +{ + COMPQUIET(vdp, NULL); + COMPQUIET(meta, NULL); + COMPQUIET(pgno, 0); + COMPQUIET(flags, 0); + return (__db_no_queue_am(dbp->env)); +} + +int +__qam_vrfy_structure(dbp, vdp, flags) + DB *dbp; + VRFY_DBINFO *vdp; + u_int32_t flags; +{ + COMPQUIET(vdp, NULL); + COMPQUIET(flags, 0); + return (__db_no_queue_am(dbp->env)); +} + +int +__qam_vrfy_walkqueue(dbp, vdp, handle, callback, flags) + DB *dbp; + VRFY_DBINFO *vdp; + void *handle; + int (*callback) __P((void *, const void *)); + u_int32_t flags; +{ + COMPQUIET(vdp, NULL); + COMPQUIET(handle, NULL); + COMPQUIET(callback, NULL); + COMPQUIET(flags, 0); + return (__db_no_queue_am(dbp->env)); +} +#endif /* !HAVE_QUEUE */ diff -r 000000000000 -r a1985f14b030 src/rep/rep_stub.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/rep/rep_stub.c Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,447 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 1996, 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + * $Id$ + */ + +#ifndef HAVE_REPLICATION +#include "db_config.h" + +#include "db_int.h" +#include "dbinc/db_page.h" +#include "dbinc/db_am.h" + +/* + * If the library wasn't compiled with replication support, various routines + * aren't available. Stub them here, returning an appropriate error. + */ +static int __db_norep __P((ENV *)); + +/* + * __db_norep -- + * Error when a Berkeley DB build doesn't include replication support. + */ +static int +__db_norep(env) + ENV *env; +{ + __db_errx(env, DB_STR("3581", + "library build did not include support for replication")); + return (DB_OPNOTSUP); +} + +int +__db_rep_enter(dbp, checkgen, checklock, return_now) + DB *dbp; + int checkgen, checklock, return_now; +{ + COMPQUIET(checkgen, 0); + COMPQUIET(checklock, 0); + COMPQUIET(return_now, 0); + return (__db_norep(dbp->env)); +} + +int +__env_rep_enter(env, checklock) + ENV *env; + int checklock; +{ + COMPQUIET(checklock, 0); + return (__db_norep(env)); +} + +int +__env_db_rep_exit(env) + ENV *env; +{ + return (__db_norep(env)); +} + +int +__op_rep_enter(env, local_nowait, obey_user) + ENV *env; + int local_nowait, obey_user; +{ + COMPQUIET(local_nowait, 0); + COMPQUIET(obey_user, 0); + return (__db_norep(env)); +} + +int +__op_rep_exit(env) + ENV *env; +{ + return (__db_norep(env)); +} + +int +__archive_rep_enter(env) + ENV *env; +{ + COMPQUIET(env, NULL); + return (0); +} + +int +__archive_rep_exit(env) + ENV *env; +{ + COMPQUIET(env, NULL); + return (0); +} + +int +__rep_bulk_message(env, bulkp, repth, lsnp, dbt, flags) + ENV *env; + REP_BULK *bulkp; + REP_THROTTLE *repth; + DB_LSN *lsnp; + const DBT *dbt; + u_int32_t flags; +{ + COMPQUIET(bulkp, NULL); + COMPQUIET(repth, NULL); + COMPQUIET(lsnp, NULL); + COMPQUIET(dbt, NULL); + COMPQUIET(flags, 0); + return (__db_norep(env)); +} + +int +__rep_env_refresh(env) + ENV *env; +{ + COMPQUIET(env, NULL); + return (0); +} + +int +__rep_elect_pp(dbenv, nsites, nvotes, flags) + DB_ENV *dbenv; + u_int32_t nsites, nvotes; + u_int32_t flags; +{ + COMPQUIET(nsites, 0); + COMPQUIET(nvotes, 0); + COMPQUIET(flags, 0); + return (__db_norep(dbenv->env)); +} + +int +__rep_flush(dbenv) + DB_ENV *dbenv; +{ + return (__db_norep(dbenv->env)); +} + +int +__rep_lease_check(env, refresh) + ENV *env; + int refresh; +{ + COMPQUIET(refresh, 0); + return (__db_norep(env)); +} + +int +__rep_lease_expire(env) + ENV *env; +{ + return (__db_norep(env)); +} + +void +__rep_msg(env, msg) + const ENV *env; + const char *msg; +{ + COMPQUIET(env, NULL); + COMPQUIET(msg, NULL); + return; +} + +int +__rep_get_clockskew(dbenv, fast_clockp, slow_clockp) + DB_ENV *dbenv; + u_int32_t *fast_clockp, *slow_clockp; +{ + COMPQUIET(fast_clockp, NULL); + COMPQUIET(slow_clockp, NULL); + return (__db_norep(dbenv->env)); +} + +int +__rep_set_clockskew(dbenv, fast_clock, slow_clock) + DB_ENV *dbenv; + u_int32_t fast_clock, slow_clock; +{ + COMPQUIET(fast_clock, 0); + COMPQUIET(slow_clock, 0); + return (__db_norep(dbenv->env)); +} + +int +__rep_set_nsites_pp(dbenv, n) + DB_ENV *dbenv; + u_int32_t n; +{ + COMPQUIET(n, 0); + return (__db_norep(dbenv->env)); +} + +int +__rep_get_nsites(dbenv, n) + DB_ENV *dbenv; + u_int32_t *n; +{ + COMPQUIET(n, NULL); + return (__db_norep(dbenv->env)); +} + +int +__rep_set_priority(dbenv, priority) + DB_ENV *dbenv; + u_int32_t priority; +{ + COMPQUIET(priority, 0); + return (__db_norep(dbenv->env)); +} + +int +__rep_get_priority(dbenv, priority) + DB_ENV *dbenv; + u_int32_t *priority; +{ + COMPQUIET(priority, NULL); + return (__db_norep(dbenv->env)); +} + +int +__rep_set_timeout(dbenv, which, timeout) + DB_ENV *dbenv; + int which; + db_timeout_t timeout; +{ + COMPQUIET(which, 0); + COMPQUIET(timeout, 0); + return (__db_norep(dbenv->env)); +} + +int +__rep_get_timeout(dbenv, which, timeout) + DB_ENV *dbenv; + int which; + db_timeout_t *timeout; +{ + COMPQUIET(which, 0); + COMPQUIET(timeout, NULL); + return (__db_norep(dbenv->env)); +} + +int +__rep_get_config(dbenv, which, onp) + DB_ENV *dbenv; + u_int32_t which; + int *onp; +{ + COMPQUIET(which, 0); + COMPQUIET(onp, NULL); + return (__db_norep(dbenv->env)); +} + +int +__rep_set_config(dbenv, which, on) + DB_ENV *dbenv; + u_int32_t which; + int on; +{ + COMPQUIET(which, 0); + COMPQUIET(on, 0); + return (__db_norep(dbenv->env)); +} + +int +__rep_get_limit(dbenv, gbytesp, bytesp) + DB_ENV *dbenv; + u_int32_t *gbytesp, *bytesp; +{ + COMPQUIET(gbytesp, NULL); + COMPQUIET(bytesp, NULL); + return (__db_norep(dbenv->env)); +} + +int +__rep_open(env) + ENV *env; +{ + COMPQUIET(env, NULL); + return (0); +} + +int +__rep_preclose(env) + ENV *env; +{ + return (__db_norep(env)); +} + +int +__rep_process_message_pp(dbenv, control, rec, eid, ret_lsnp) + DB_ENV *dbenv; + DBT *control, *rec; + int eid; + DB_LSN *ret_lsnp; +{ + COMPQUIET(control, NULL); + COMPQUIET(rec, NULL); + COMPQUIET(eid, 0); + COMPQUIET(ret_lsnp, NULL); + return (__db_norep(dbenv->env)); +} + +int +__rep_send_message(env, eid, rtype, lsnp, dbtp, logflags, repflags) + ENV *env; + int eid; + u_int32_t rtype; + DB_LSN *lsnp; + const DBT *dbtp; + u_int32_t logflags, repflags; +{ + COMPQUIET(eid, 0); + COMPQUIET(rtype, 0); + COMPQUIET(lsnp, NULL); + COMPQUIET(dbtp, NULL); + COMPQUIET(logflags, 0); + COMPQUIET(repflags, 0); + return (__db_norep(env)); +} + +int +__rep_set_limit(dbenv, gbytes, bytes) + DB_ENV *dbenv; + u_int32_t gbytes, bytes; +{ + COMPQUIET(gbytes, 0); + COMPQUIET(bytes, 0); + return (__db_norep(dbenv->env)); +} + +int +__rep_set_transport_pp(dbenv, eid, f_send) + DB_ENV *dbenv; + int eid; + int (*f_send) __P((DB_ENV *, const DBT *, const DBT *, const DB_LSN *, + int, u_int32_t)); +{ + COMPQUIET(eid, 0); + COMPQUIET(f_send, NULL); + return (__db_norep(dbenv->env)); +} + +int +__rep_set_request(dbenv, min, max) + DB_ENV *dbenv; + u_int32_t min, max; +{ + COMPQUIET(min, 0); + COMPQUIET(max, 0); + return (__db_norep(dbenv->env)); +} + +int +__rep_get_request(dbenv, minp, maxp) + DB_ENV *dbenv; + u_int32_t *minp, *maxp; +{ + COMPQUIET(minp, NULL); + COMPQUIET(maxp, NULL); + return (__db_norep(dbenv->env)); +} + +int +__rep_start_pp(dbenv, dbt, flags) + DB_ENV *dbenv; + DBT *dbt; + u_int32_t flags; +{ + COMPQUIET(dbt, NULL); + COMPQUIET(flags, 0); + return (__db_norep(dbenv->env)); +} + +int +__rep_stat_pp(dbenv, statp, flags) + DB_ENV *dbenv; + DB_REP_STAT **statp; + u_int32_t flags; +{ + COMPQUIET(statp, NULL); + COMPQUIET(flags, 0); + return (__db_norep(dbenv->env)); +} + +int +__rep_stat_print_pp(dbenv, flags) + DB_ENV *dbenv; + u_int32_t flags; +{ + COMPQUIET(flags, 0); + return (__db_norep(dbenv->env)); +} + +int +__rep_stat_print(env, flags) + ENV *env; + u_int32_t flags; +{ + COMPQUIET(flags, 0); + return (__db_norep(env)); +} + +int +__rep_sync(dbenv, flags) + DB_ENV *dbenv; + u_int32_t flags; +{ + COMPQUIET(flags, 0); + return (__db_norep(dbenv->env)); +} + +int +__rep_txn_applied(env, ip, commit_info, timeout) + ENV *env; + DB_THREAD_INFO *ip; + DB_COMMIT_INFO *commit_info; + db_timeout_t timeout; +{ + COMPQUIET(ip, 0); + COMPQUIET(commit_info, NULL); + COMPQUIET(timeout, 0); + return (__db_norep(env)); +} +#endif /* !HAVE_REPLICATION */ diff -r 000000000000 -r a1985f14b030 src/repmgr/repmgr_stub.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/repmgr/repmgr_stub.c Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,284 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 1996, 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + * $Id$ + */ + +#ifndef HAVE_REPLICATION_THREADS +#include "db_config.h" + +#include "db_int.h" + +/* + * If the library wasn't compiled with replication support, various routines + * aren't available. Stub them here, returning an appropriate error. + */ +static int __db_norepmgr __P((DB_ENV *)); + +/* + * __db_norepmgr -- + * Error when a Berkeley DB build doesn't include replication mgr support. + */ +static int +__db_norepmgr(dbenv) + DB_ENV *dbenv; +{ + __db_errx(dbenv->env, DB_STR("3628", + "library build did not include support for the Replication Manager")); + return (DB_OPNOTSUP); +} + +/* + * PUBLIC: #ifndef HAVE_REPLICATION_THREADS + * PUBLIC: int __repmgr_close __P((ENV *)); + * PUBLIC: #endif + */ +int +__repmgr_close(env) + ENV *env; +{ + COMPQUIET(env, NULL); + return (0); +} + +/* + * PUBLIC: #ifndef HAVE_REPLICATION_THREADS + * PUBLIC: int __repmgr_get_ack_policy __P((DB_ENV *, int *)); + * PUBLIC: #endif + */ +int +__repmgr_get_ack_policy(dbenv, policy) + DB_ENV *dbenv; + int *policy; +{ + COMPQUIET(policy, NULL); + return (__db_norepmgr(dbenv)); +} + +/* + * PUBLIC: #ifndef HAVE_REPLICATION_THREADS + * PUBLIC: int __repmgr_set_ack_policy __P((DB_ENV *, int)); + * PUBLIC: #endif + */ +int +__repmgr_set_ack_policy(dbenv, policy) + DB_ENV *dbenv; + int policy; +{ + COMPQUIET(policy, 0); + return (__db_norepmgr(dbenv)); +} + +/* + * PUBLIC: #ifndef HAVE_REPLICATION_THREADS + * PUBLIC: int __repmgr_site + * PUBLIC: __P((DB_ENV *, const char *, u_int, DB_SITE **, u_int32_t)); + * PUBLIC: #endif + */ +int +__repmgr_site(dbenv, host, port, dbsitep, flags) + DB_ENV *dbenv; + const char *host; + u_int port; + DB_SITE **dbsitep; + u_int32_t flags; +{ + COMPQUIET(host, NULL); + COMPQUIET(port, 0); + COMPQUIET(dbsitep, NULL); + COMPQUIET(flags, 0); + return (__db_norepmgr(dbenv)); +} + +/* + * PUBLIC: #ifndef HAVE_REPLICATION_THREADS + * PUBLIC: int __repmgr_site_by_eid __P((DB_ENV *, int, DB_SITE **)); + * PUBLIC: #endif + */ +int +__repmgr_site_by_eid(dbenv, eid, dbsitep) + DB_ENV *dbenv; + int eid; + DB_SITE **dbsitep; +{ + COMPQUIET(eid, 0); + COMPQUIET(dbsitep, NULL); + return (__db_norepmgr(dbenv)); +} + +/* + * PUBLIC: #ifndef HAVE_REPLICATION_THREADS + * PUBLIC: int __repmgr_local_site + * PUBLIC: __P((DB_ENV *, DB_SITE **)); + * PUBLIC: #endif + */ +int +__repmgr_local_site(dbenv, dbsitep) + DB_ENV *dbenv; + DB_SITE **dbsitep; +{ + COMPQUIET(dbsitep, NULL); + return (__db_norepmgr(dbenv)); +} + +/* + * PUBLIC: #ifndef HAVE_REPLICATION_THREADS + * PUBLIC: int __repmgr_site_list __P((DB_ENV *, u_int *, DB_REPMGR_SITE **)); + * PUBLIC: #endif + */ +int +__repmgr_site_list(dbenv, countp, listp) + DB_ENV *dbenv; + u_int *countp; + DB_REPMGR_SITE **listp; +{ + COMPQUIET(countp, NULL); + COMPQUIET(listp, NULL); + return (__db_norepmgr(dbenv)); +} + +/* + * PUBLIC: #ifndef HAVE_REPLICATION_THREADS + * PUBLIC: int __repmgr_start __P((DB_ENV *, int, u_int32_t)); + * PUBLIC: #endif + */ +int +__repmgr_start(dbenv, nthreads, flags) + DB_ENV *dbenv; + int nthreads; + u_int32_t flags; +{ + COMPQUIET(nthreads, 0); + COMPQUIET(flags, 0); + return (__db_norepmgr(dbenv)); +} + +/* + * PUBLIC: #ifndef HAVE_REPLICATION_THREADS + * PUBLIC: int __repmgr_stat_pp __P((DB_ENV *, DB_REPMGR_STAT **, u_int32_t)); + * PUBLIC: #endif + */ +int +__repmgr_stat_pp(dbenv, statp, flags) + DB_ENV *dbenv; + DB_REPMGR_STAT **statp; + u_int32_t flags; +{ + COMPQUIET(statp, NULL); + COMPQUIET(flags, 0); + return (__db_norepmgr(dbenv)); +} + +/* + * PUBLIC: #ifndef HAVE_REPLICATION_THREADS + * PUBLIC: int __repmgr_stat_print_pp __P((DB_ENV *, u_int32_t)); + * PUBLIC: #endif + */ +int +__repmgr_stat_print_pp(dbenv, flags) + DB_ENV *dbenv; + u_int32_t flags; +{ + COMPQUIET(flags, 0); + return (__db_norepmgr(dbenv)); +} + +/* + * PUBLIC: #ifndef HAVE_REPLICATION_THREADS + * PUBLIC: int __repmgr_handle_event __P((ENV *, u_int32_t, void *)); + * PUBLIC: #endif + */ +int +__repmgr_handle_event(env, event, info) + ENV *env; + u_int32_t event; + void *info; +{ + COMPQUIET(env, NULL); + COMPQUIET(event, 0); + COMPQUIET(info, NULL); + + /* + * It's not an error for this function to be called. Replication calls + * this to let repmgr handle events. If repmgr isn't part of the build, + * all replication events should be forwarded to the application. + */ + return (DB_EVENT_NOT_HANDLED); +} + +/* + * PUBLIC: #ifndef HAVE_REPLICATION_THREADS + * PUBLIC: int __repmgr_channel __P((DB_ENV *, int, DB_CHANNEL **, u_int32_t)); + * PUBLIC: #endif + */ +int +__repmgr_channel(dbenv, eid, dbchannelp, flags) + DB_ENV *dbenv; + int eid; + DB_CHANNEL **dbchannelp; + u_int32_t flags; +{ + COMPQUIET(eid, 0); + COMPQUIET(dbchannelp, NULL); + COMPQUIET(flags, 0); + return (__db_norepmgr(dbenv)); +} + +/* + * PUBLIC: #ifndef HAVE_REPLICATION_THREADS + * PUBLIC: int __repmgr_set_msg_dispatch __P((DB_ENV *, + * PUBLIC: void (*)(DB_ENV *, DB_CHANNEL *, DBT *, u_int32_t, u_int32_t), + * PUBLIC: u_int32_t)); + * PUBLIC: #endif + */ +int +__repmgr_set_msg_dispatch(dbenv, dispatch, flags) + DB_ENV *dbenv; + void (*dispatch) __P((DB_ENV *, + DB_CHANNEL *, DBT *, u_int32_t, u_int32_t)); + u_int32_t flags; +{ + COMPQUIET(dispatch, NULL); + COMPQUIET(flags, 0); + return (__db_norepmgr(dbenv)); +} + +/* + * PUBLIC: #ifndef HAVE_REPLICATION_THREADS + * PUBLIC: int __repmgr_init_recover __P((ENV *, DB_DISTAB *)); + * PUBLIC: #endif + */ +int +__repmgr_init_recover(env, dtabp) + ENV *env; + DB_DISTAB *dtabp; +{ + COMPQUIET(env, NULL); + COMPQUIET(dtabp, NULL); + return (0); +} +#endif /* !HAVE_REPLICATION_THREADS */ diff -r 000000000000 -r a1985f14b030 src/windows_incl/clib_port.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/windows_incl/clib_port.h Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,304 @@ +/* DO NOT EDIT: automatically built from dist/clib_port.in. + * + * Copyright (c) 2006, 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +/* + * Minimum/maximum values for various types. + */ +#ifndef UINT16_MAX /* Maximum 16-bit unsigned. */ +#define UINT16_MAX 65535 +#endif +#ifndef UINT32_MAX /* Maximum 32-bit unsigned. */ +#define UINT32_MAX 4294967295U +#endif + +#ifndef INT_MAX +#if SIZEOF_INT == 4 +#define INT_MAX 2147483647 +#endif +#if SIZEOF_INT == 8 +#define INT_MAX 9223372036854775807 +#endif +#endif + +#ifndef INT_MIN /* minimum (signed) int value */ +#define INT_MIN (-INT_MAX-1) +#endif + +#ifndef UINT_MAX /* maximum (signed) int value */ +#if SIZEOF_INT == 4 +#define UINT_MAX 4294967295U +#endif +#if SIZEOF_INT == 8 +#define UINT_MAX 18446744073709551615U +#endif +#endif + +#ifndef LONG_MAX /* maximum (signed) long value */ +#if SIZEOF_LONG == 4 +#define LONG_MAX 2147483647 +#endif +#if SIZEOF_LONG == 8 +#define LONG_MAX 9223372036854775807L +#endif +#endif + +#ifndef LONG_MIN /* minimum (signed) long value */ +#define LONG_MIN (-LONG_MAX-1) +#endif + +#ifndef ULONG_MAX /* maximum (unsigned) long value */ +#if SIZEOF_LONG == 4 +#define ULONG_MAX 4294967295U +#endif +#if SIZEOF_LONG == 8 +#define ULONG_MAX 18446744073709551615UL +#endif +#endif + +#if defined(HAVE_64BIT_TYPES) +/* + * Override the system's 64-bit min/max constants. AIX's 32-bit compiler can + * handle 64-bit values, but the system's constants don't include the LL/ULL + * suffix, and so can't be compiled using the 32-bit compiler. + */ +#undef INT64_MAX +#undef INT64_MIN +#undef UINT64_MAX + +#ifdef DB_WIN32 +#define INT64_MAX _I64_MAX +#define INT64_MIN _I64_MIN +#define UINT64_MAX _UI64_MAX +#else +#define INT64_MAX 9223372036854775807LL +#define INT64_MIN (-INT64_MAX-1) +#define UINT64_MAX 18446744073709551615ULL +#endif /* DB_WIN32 */ + +#define INT64_FMT "%I64d" +#define UINT64_FMT "%I64u" +#endif /* HAVE_64BIT_TYPES */ + +/* + * Exit success/failure macros. + */ +#ifndef HAVE_EXIT_SUCCESS +#define EXIT_FAILURE 1 +#define EXIT_SUCCESS 0 +#endif + +/* + * File modes. + */ +#ifdef DB_WIN32 +#ifndef S_IREAD /* WinCE doesn't have S_IREAD. */ +#define S_IREAD 0 +#endif +#ifndef S_IWRITE /* WinCE doesn't have S_IWRITE. */ +#define S_IWRITE 0 +#endif +#ifndef S_IRUSR +#define S_IRUSR S_IREAD /* R for owner */ +#endif +#ifndef S_IWUSR +#define S_IWUSR S_IWRITE /* W for owner */ +#endif +#ifndef S_IXUSR +#define S_IXUSR 0 /* X for owner */ +#endif +#ifndef S_IRGRP +#define S_IRGRP 0 /* R for group */ +#endif +#ifndef S_IWGRP +#define S_IWGRP 0 /* W for group */ +#endif +#ifndef S_IXGRP +#define S_IXGRP 0 /* X for group */ +#endif +#ifndef S_IROTH +#define S_IROTH 0 /* R for other */ +#endif +#ifndef S_IWOTH +#define S_IWOTH 0 /* W for other */ +#endif +#ifndef S_IXOTH +#define S_IXOTH 0 /* X for other */ +#endif +#else /* !DB_WIN32 */ +#ifndef S_IRUSR +#define S_IRUSR 0000400 /* R for owner */ +#endif +#ifndef S_IWUSR +#define S_IWUSR 0000200 /* W for owner */ +#endif +#ifndef S_IXUSR +#define S_IXUSR 0000100 /* X for owner */ +#endif +#ifndef S_IRGRP +#define S_IRGRP 0000040 /* R for group */ +#endif +#ifndef S_IWGRP +#define S_IWGRP 0000020 /* W for group */ +#endif +#ifndef S_IXGRP +#define S_IXGRP 0000010 /* X for group */ +#endif +#ifndef S_IROTH +#define S_IROTH 0000004 /* R for other */ +#endif +#ifndef S_IWOTH +#define S_IWOTH 0000002 /* W for other */ +#endif +#ifndef S_IXOTH +#define S_IXOTH 0000001 /* X for other */ +#endif +#endif /* !DB_WIN32 */ + +/* + * Don't step on the namespace. Other libraries may have their own + * implementations of these functions, we don't want to use their + * implementations or force them to use ours based on the load order. + */ +#ifndef HAVE_ATOI +#define atoi __db_Catoi +#endif +#ifndef HAVE_ATOL +#define atol __db_Catol +#endif +#ifndef HAVE_BSEARCH +#define bsearch __db_Cbsearch +#endif +#ifndef HAVE_FCLOSE +#define fclose __db_Cfclose +#endif +#ifndef HAVE_FGETC +#define fgetc __db_Cfgetc +#endif +#ifndef HAVE_FGETS +#define fgets __db_Cfgets +#endif +#ifndef HAVE_FOPEN +#define fopen __db_Cfopen +#endif +#ifndef HAVE_FWRITE +#define fwrite __db_Cfwrite +#endif +#ifndef HAVE_GETADDRINFO +#define freeaddrinfo(a) __db_Cfreeaddrinfo(a) +#define getaddrinfo(a, b, c, d) __db_Cgetaddrinfo(a, b, c, d) +#endif +#ifndef HAVE_GETCWD +#define getcwd __db_Cgetcwd +#endif +#ifndef HAVE_GETOPT +#define getopt __db_Cgetopt +#define optarg __db_Coptarg +#define opterr __db_Copterr +#define optind __db_Coptind +#define optopt __db_Coptopt +#define optreset __db_Coptreset +#endif +#ifndef HAVE_ISALPHA +#define isalpha __db_Cisalpha +#endif +#ifndef HAVE_ISDIGIT +#define isdigit __db_Cisdigit +#endif +#ifndef HAVE_ISPRINT +#define isprint __db_Cisprint +#endif +#ifndef HAVE_ISSPACE +#define isspace __db_Cisspace +#endif +#ifndef HAVE_LOCALTIME +#define localtime __db_Clocaltime +#endif +#ifndef HAVE_MEMCMP +#define memcmp __db_Cmemcmp +#endif +#ifndef HAVE_MEMCPY +#define memcpy __db_Cmemcpy +#endif +#ifndef HAVE_MEMMOVE +#define memmove __db_Cmemmove +#endif +#ifndef HAVE_PRINTF +#define printf __db_Cprintf +#define fprintf __db_Cfprintf +#endif +#ifndef HAVE_QSORT +#define qsort __db_Cqsort +#endif +#ifndef HAVE_RAISE +#define raise __db_Craise +#endif +#ifndef HAVE_RAND +#define rand __db_Crand +#define srand __db_Csrand +#endif +#ifndef HAVE_SNPRINTF +#define snprintf __db_Csnprintf +#endif +#ifndef HAVE_STRCASECMP +#define strcasecmp __db_Cstrcasecmp +#define strncasecmp __db_Cstrncasecmp +#endif +#ifndef HAVE_STRCAT +#define strcat __db_Cstrcat +#endif +#ifndef HAVE_STRCHR +#define strchr __db_Cstrchr +#endif +#ifndef HAVE_STRDUP +#define strdup __db_Cstrdup +#endif +#ifndef HAVE_STRERROR +#define strerror __db_Cstrerror +#endif +#ifndef HAVE_STRNCAT +#define strncat __db_Cstrncat +#endif +#ifndef HAVE_STRNCMP +#define strncmp __db_Cstrncmp +#endif +#ifndef HAVE_STRRCHR +#define strrchr __db_Cstrrchr +#endif +#ifndef HAVE_STRSEP +#define strsep __db_Cstrsep +#endif +#ifndef HAVE_STRTOL +#define strtol __db_Cstrtol +#endif +#ifndef HAVE_STRTOUL +#define strtoul __db_Cstrtoul +#endif +#ifndef HAVE_TIME +#define time __db_Ctime +#endif +#ifndef HAVE_VSNPRINTF +#define vsnprintf __db_Cvsnprintf +#endif diff -r 000000000000 -r a1985f14b030 src/windows_incl/db.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/windows_incl/db.h Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,3221 @@ +/* DO NOT EDIT: automatically built by dist/s_windows. */ +/* + * See the file LICENSE for redistribution information. + * + * Copyright (c) 1996, 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + * $Id$ + * + * db.h include file layout: + * General. + * Database Environment. + * Locking subsystem. + * Logging subsystem. + * Shared buffer cache (mpool) subsystem. + * Transaction subsystem. + * Access methods. + * Access method cursors. + * Dbm/Ndbm, Hsearch historic interfaces. + */ + +#ifndef _DB_H_ +#define _DB_H_ + +#ifndef __NO_SYSTEM_INCLUDES +#include +#include +#include +#endif + +/* + * Turn off inappropriate compiler warnings + */ +#ifdef _MSC_VER +/* + * This warning is explicitly disabled in Visual C++ by default. + * It is necessary to explicitly enable the /Wall flag to generate this + * warning. + * Since this is a shared include file it should compile without warnings + * at the highest warning level, so third party applications can use + * higher warning levels cleanly. + * + * 4820: 'bytes' bytes padding added after member 'member' + * The type and order of elements caused the compiler to + * add padding to the end of a struct. + */ +#pragma warning(push) +#pragma warning(disable: 4820) +#endif /* _MSC_VER */ +#if defined(__cplusplus) +extern "C" { +#endif + + +#undef __P +#define __P(protos) protos + +/* + * Berkeley DB version information. + */ +#define DB_VERSION_FAMILY 11 +#define DB_VERSION_RELEASE 2 +#define DB_VERSION_MAJOR 5 +#define DB_VERSION_MINOR 4 +#define DB_VERSION_PATCH 0 +#define DB_VERSION_STRING "Berkeley DB 5.4.0: (May 7, 2012)" +#define DB_VERSION_FULL_STRING "Berkeley DB 11g Release 2, library version 11.2.5.4.0: (May 7, 2012)" + +/* + * !!! + * Berkeley DB uses specifically sized types. If they're not provided by + * the system, typedef them here. + * + * We protect them against multiple inclusion using __BIT_TYPES_DEFINED__, + * as does BIND and Kerberos, since we don't know for sure what #include + * files the user is using. + * + * !!! + * We also provide the standard u_int, u_long etc., if they're not provided + * by the system. + */ +#ifndef __BIT_TYPES_DEFINED__ +#define __BIT_TYPES_DEFINED__ +typedef unsigned char u_int8_t; +typedef short int16_t; +typedef unsigned short u_int16_t; +typedef int int32_t; +typedef unsigned int u_int32_t; +typedef __int64 int64_t; +typedef unsigned __int64 u_int64_t; +#endif + +#ifndef _WINSOCKAPI_ +typedef unsigned char u_char; +typedef unsigned int u_int; +typedef unsigned long u_long; +#endif +typedef unsigned short u_short; + +/* + * Missing ANSI types. + * + * uintmax_t -- + * Largest unsigned type, used to align structures in memory. We don't store + * floating point types in structures, so integral types should be sufficient + * (and we don't have to worry about systems that store floats in other than + * power-of-2 numbers of bytes). Additionally this fixes compilers that rewrite + * structure assignments and ANSI C memcpy calls to be in-line instructions + * that happen to require alignment. + * + * uintptr_t -- + * Unsigned type that's the same size as a pointer. There are places where + * DB modifies pointers by discarding the bottom bits to guarantee alignment. + * We can't use uintmax_t, it may be larger than the pointer, and compilers + * get upset about that. So far we haven't run on any machine where there's + * no unsigned type the same size as a pointer -- here's hoping. + */ +#if defined(_MSC_VER) && _MSC_VER < 1300 +typedef u_int32_t uintmax_t; +#else +typedef u_int64_t uintmax_t; +#endif +#ifdef _WIN64 +typedef u_int64_t uintptr_t; +#else +typedef u_int32_t uintptr_t; +#endif + +/* + * Windows defines off_t to long (i.e., 32 bits). We need to pass 64-bit + * file offsets, so we declare our own. + */ +#define off_t __db_off_t +typedef int64_t off_t; +typedef int32_t pid_t; +#ifdef HAVE_MIXED_SIZE_ADDRESSING +typedef u_int32_t db_size_t; +#else +typedef size_t db_size_t; +#endif +#ifdef _WIN64 +typedef int64_t ssize_t; +#else +typedef int32_t ssize_t; +#endif +#ifdef HAVE_MIXED_SIZE_ADDRESSING +typedef int32_t db_ssize_t; +#else +typedef ssize_t db_ssize_t; +#endif + +/* + * Sequences are only available on machines with 64-bit integral types. + */ +typedef int64_t db_seq_t; + +/* Thread and process identification. */ +typedef u_int32_t db_threadid_t; + +/* Basic types that are exported or quasi-exported. */ +typedef u_int32_t db_pgno_t; /* Page number type. */ +typedef u_int16_t db_indx_t; /* Page offset type. */ +#define DB_MAX_PAGES 0xffffffff /* >= # of pages in a file */ + +typedef u_int32_t db_recno_t; /* Record number type. */ +#define DB_MAX_RECORDS 0xffffffff /* >= # of records in a tree */ + +typedef u_int32_t db_timeout_t; /* Type of a timeout. */ + +/* + * Region offsets are the difference between a pointer in a region and the + * region's base address. With private environments, both addresses are the + * result of calling malloc, and we can't assume anything about what malloc + * will return, so region offsets have to be able to hold differences between + * arbitrary pointers. + */ +typedef db_size_t roff_t; + +/* + * Forward structure declarations, so we can declare pointers and + * applications can get type checking. + */ +struct __channel; typedef struct __channel CHANNEL; +struct __db; typedef struct __db DB; +struct __db_bt_stat; typedef struct __db_bt_stat DB_BTREE_STAT; +struct __db_channel; typedef struct __db_channel DB_CHANNEL; +struct __db_cipher; typedef struct __db_cipher DB_CIPHER; +struct __db_compact; typedef struct __db_compact DB_COMPACT; +struct __db_dbt; typedef struct __db_dbt DBT; +struct __db_distab; typedef struct __db_distab DB_DISTAB; +struct __db_env; typedef struct __db_env DB_ENV; +struct __db_h_stat; typedef struct __db_h_stat DB_HASH_STAT; +struct __db_heap_rid; typedef struct __db_heap_rid DB_HEAP_RID; +struct __db_heap_stat; typedef struct __db_heap_stat DB_HEAP_STAT; +struct __db_ilock; typedef struct __db_ilock DB_LOCK_ILOCK; +struct __db_lock_hstat; typedef struct __db_lock_hstat DB_LOCK_HSTAT; +struct __db_lock_pstat; typedef struct __db_lock_pstat DB_LOCK_PSTAT; +struct __db_lock_stat; typedef struct __db_lock_stat DB_LOCK_STAT; +struct __db_lock_u; typedef struct __db_lock_u DB_LOCK; +struct __db_locker; typedef struct __db_locker DB_LOCKER; +struct __db_lockreq; typedef struct __db_lockreq DB_LOCKREQ; +struct __db_locktab; typedef struct __db_locktab DB_LOCKTAB; +struct __db_log; typedef struct __db_log DB_LOG; +struct __db_log_cursor; typedef struct __db_log_cursor DB_LOGC; +struct __db_log_stat; typedef struct __db_log_stat DB_LOG_STAT; +struct __db_lsn; typedef struct __db_lsn DB_LSN; +struct __db_mpool; typedef struct __db_mpool DB_MPOOL; +struct __db_mpool_fstat;typedef struct __db_mpool_fstat DB_MPOOL_FSTAT; +struct __db_mpool_stat; typedef struct __db_mpool_stat DB_MPOOL_STAT; +struct __db_mpoolfile; typedef struct __db_mpoolfile DB_MPOOLFILE; +struct __db_mutex_stat; typedef struct __db_mutex_stat DB_MUTEX_STAT; +struct __db_mutex_t; typedef struct __db_mutex_t DB_MUTEX; +struct __db_mutexmgr; typedef struct __db_mutexmgr DB_MUTEXMGR; +struct __db_preplist; typedef struct __db_preplist DB_PREPLIST; +struct __db_qam_stat; typedef struct __db_qam_stat DB_QUEUE_STAT; +struct __db_rep; typedef struct __db_rep DB_REP; +struct __db_rep_stat; typedef struct __db_rep_stat DB_REP_STAT; +struct __db_repmgr_conn_err; + typedef struct __db_repmgr_conn_err DB_REPMGR_CONN_ERR; +struct __db_repmgr_site;typedef struct __db_repmgr_site DB_REPMGR_SITE; +struct __db_repmgr_stat;typedef struct __db_repmgr_stat DB_REPMGR_STAT; +struct __db_seq_record; typedef struct __db_seq_record DB_SEQ_RECORD; +struct __db_seq_stat; typedef struct __db_seq_stat DB_SEQUENCE_STAT; +struct __db_site; typedef struct __db_site DB_SITE; +struct __db_sequence; typedef struct __db_sequence DB_SEQUENCE; +struct __db_thread_info;typedef struct __db_thread_info DB_THREAD_INFO; +struct __db_txn; typedef struct __db_txn DB_TXN; +struct __db_txn_active; typedef struct __db_txn_active DB_TXN_ACTIVE; +struct __db_txn_stat; typedef struct __db_txn_stat DB_TXN_STAT; +struct __db_txn_token; typedef struct __db_txn_token DB_TXN_TOKEN; +struct __db_txnmgr; typedef struct __db_txnmgr DB_TXNMGR; +struct __dbc; typedef struct __dbc DBC; +struct __dbc_internal; typedef struct __dbc_internal DBC_INTERNAL; +struct __env; typedef struct __env ENV; +struct __fh_t; typedef struct __fh_t DB_FH; +struct __fname; typedef struct __fname FNAME; +struct __key_range; typedef struct __key_range DB_KEY_RANGE; +struct __mpoolfile; typedef struct __mpoolfile MPOOLFILE; +struct __db_logvrfy_config; +typedef struct __db_logvrfy_config DB_LOG_VERIFY_CONFIG; + +/* + * The Berkeley DB API flags are automatically-generated -- the following flag + * names are no longer used, but remain for compatibility reasons. + */ +#define DB_DEGREE_2 DB_READ_COMMITTED +#define DB_DIRTY_READ DB_READ_UNCOMMITTED +#define DB_JOINENV 0x0 + +/* Key/data structure -- a Data-Base Thang. */ +struct __db_dbt { + void *data; /* Key/data */ + u_int32_t size; /* key/data length */ + + u_int32_t ulen; /* RO: length of user buffer. */ + u_int32_t dlen; /* RO: get/put record length. */ + u_int32_t doff; /* RO: get/put record offset. */ + + void *app_data; + +#define DB_DBT_APPMALLOC 0x001 /* Callback allocated memory. */ +#define DB_DBT_BULK 0x002 /* Internal: Insert if duplicate. */ +#define DB_DBT_DUPOK 0x004 /* Internal: Insert if duplicate. */ +#define DB_DBT_ISSET 0x008 /* Lower level calls set value. */ +#define DB_DBT_MALLOC 0x010 /* Return in malloc'd memory. */ +#define DB_DBT_MULTIPLE 0x020 /* References multiple records. */ +#define DB_DBT_PARTIAL 0x040 /* Partial put/get. */ +#define DB_DBT_REALLOC 0x080 /* Return in realloc'd memory. */ +#define DB_DBT_READONLY 0x100 /* Readonly, don't update. */ +#define DB_DBT_STREAMING 0x200 /* Internal: DBT is being streamed. */ +#define DB_DBT_USERCOPY 0x400 /* Use the user-supplied callback. */ +#define DB_DBT_USERMEM 0x800 /* Return in user's memory. */ + u_int32_t flags; +}; + +/******************************************************* + * Mutexes. + *******************************************************/ +/* + * When mixed size addressing is supported mutexes need to be the same size + * independent of the process address size is. + */ +#ifdef HAVE_MIXED_SIZE_ADDRESSING +typedef db_size_t db_mutex_t; +#else +typedef uintptr_t db_mutex_t; +#endif + +struct __db_mutex_stat { /* SHARED */ + /* The following fields are maintained in the region's copy. */ + u_int32_t st_mutex_align; /* Mutex alignment */ + u_int32_t st_mutex_tas_spins; /* Mutex test-and-set spins */ + u_int32_t st_mutex_init; /* Initial mutex count */ + u_int32_t st_mutex_cnt; /* Mutex count */ + u_int32_t st_mutex_max; /* Mutex max */ + u_int32_t st_mutex_free; /* Available mutexes */ + u_int32_t st_mutex_inuse; /* Mutexes in use */ + u_int32_t st_mutex_inuse_max; /* Maximum mutexes ever in use */ + + /* The following fields are filled-in from other places. */ +#ifndef __TEST_DB_NO_STATISTICS + uintmax_t st_region_wait; /* Region lock granted after wait. */ + uintmax_t st_region_nowait; /* Region lock granted without wait. */ + roff_t st_regsize; /* Region size. */ + roff_t st_regmax; /* Region max. */ +#endif +}; + +/* This is the length of the buffer passed to DB_ENV->thread_id_string() */ +#define DB_THREADID_STRLEN 128 + +/******************************************************* + * Locking. + *******************************************************/ +#define DB_LOCKVERSION 1 + +#define DB_FILE_ID_LEN 20 /* Unique file ID length. */ + +/* + * Deadlock detector modes; used in the DB_ENV structure to configure the + * locking subsystem. + */ +#define DB_LOCK_NORUN 0 +#define DB_LOCK_DEFAULT 1 /* Default policy. */ +#define DB_LOCK_EXPIRE 2 /* Only expire locks, no detection. */ +#define DB_LOCK_MAXLOCKS 3 /* Select locker with max locks. */ +#define DB_LOCK_MAXWRITE 4 /* Select locker with max writelocks. */ +#define DB_LOCK_MINLOCKS 5 /* Select locker with min locks. */ +#define DB_LOCK_MINWRITE 6 /* Select locker with min writelocks. */ +#define DB_LOCK_OLDEST 7 /* Select oldest locker. */ +#define DB_LOCK_RANDOM 8 /* Select random locker. */ +#define DB_LOCK_YOUNGEST 9 /* Select youngest locker. */ + +/* + * Simple R/W lock modes and for multi-granularity intention locking. + * + * !!! + * These values are NOT random, as they are used as an index into the lock + * conflicts arrays, i.e., DB_LOCK_IWRITE must be == 3, and DB_LOCK_IREAD + * must be == 4. + */ +typedef enum { + DB_LOCK_NG=0, /* Not granted. */ + DB_LOCK_READ=1, /* Shared/read. */ + DB_LOCK_WRITE=2, /* Exclusive/write. */ + DB_LOCK_WAIT=3, /* Wait for event */ + DB_LOCK_IWRITE=4, /* Intent exclusive/write. */ + DB_LOCK_IREAD=5, /* Intent to share/read. */ + DB_LOCK_IWR=6, /* Intent to read and write. */ + DB_LOCK_READ_UNCOMMITTED=7, /* Degree 1 isolation. */ + DB_LOCK_WWRITE=8 /* Was Written. */ +} db_lockmode_t; + +/* + * Request types. + */ +typedef enum { + DB_LOCK_DUMP=0, /* Display held locks. */ + DB_LOCK_GET=1, /* Get the lock. */ + DB_LOCK_GET_TIMEOUT=2, /* Get lock with a timeout. */ + DB_LOCK_INHERIT=3, /* Pass locks to parent. */ + DB_LOCK_PUT=4, /* Release the lock. */ + DB_LOCK_PUT_ALL=5, /* Release locker's locks. */ + DB_LOCK_PUT_OBJ=6, /* Release locker's locks on obj. */ + DB_LOCK_PUT_READ=7, /* Release locker's read locks. */ + DB_LOCK_TIMEOUT=8, /* Force a txn to timeout. */ + DB_LOCK_TRADE=9, /* Trade locker ids on a lock. */ + DB_LOCK_UPGRADE_WRITE=10 /* Upgrade writes for dirty reads. */ +} db_lockop_t; + +/* + * Status of a lock. + */ +typedef enum { + DB_LSTAT_ABORTED=1, /* Lock belongs to an aborted txn. */ + DB_LSTAT_EXPIRED=2, /* Lock has expired. */ + DB_LSTAT_FREE=3, /* Lock is unallocated. */ + DB_LSTAT_HELD=4, /* Lock is currently held. */ + DB_LSTAT_PENDING=5, /* Lock was waiting and has been + * promoted; waiting for the owner + * to run and upgrade it to held. */ + DB_LSTAT_WAITING=6 /* Lock is on the wait queue. */ +}db_status_t; + +/* Lock statistics structure. */ +struct __db_lock_stat { /* SHARED */ + u_int32_t st_id; /* Last allocated locker ID. */ + u_int32_t st_cur_maxid; /* Current maximum unused ID. */ + u_int32_t st_initlocks; /* Initial number of locks in table. */ + u_int32_t st_initlockers; /* Initial num of lockers in table. */ + u_int32_t st_initobjects; /* Initial num of objects in table. */ + u_int32_t st_locks; /* Current number of locks in table. */ + u_int32_t st_lockers; /* Current num of lockers in table. */ + u_int32_t st_objects; /* Current num of objects in table. */ + u_int32_t st_maxlocks; /* Maximum number of locks in table. */ + u_int32_t st_maxlockers; /* Maximum num of lockers in table. */ + u_int32_t st_maxobjects; /* Maximum num of objects in table. */ + u_int32_t st_partitions; /* number of partitions. */ + u_int32_t st_tablesize; /* Size of object hash table. */ + int32_t st_nmodes; /* Number of lock modes. */ + u_int32_t st_nlockers; /* Current number of lockers. */ +#ifndef __TEST_DB_NO_STATISTICS + u_int32_t st_nlocks; /* Current number of locks. */ + u_int32_t st_maxnlocks; /* Maximum number of locks so far. */ + u_int32_t st_maxhlocks; /* Maximum number of locks in any bucket. */ + uintmax_t st_locksteals; /* Number of lock steals so far. */ + uintmax_t st_maxlsteals; /* Maximum number steals in any partition. */ + u_int32_t st_maxnlockers; /* Maximum number of lockers so far. */ + u_int32_t st_nobjects; /* Current number of objects. */ + u_int32_t st_maxnobjects; /* Maximum number of objects so far. */ + u_int32_t st_maxhobjects; /* Maximum number of objectsin any bucket. */ + uintmax_t st_objectsteals; /* Number of objects steals so far. */ + uintmax_t st_maxosteals; /* Maximum number of steals in any partition. */ + uintmax_t st_nrequests; /* Number of lock gets. */ + uintmax_t st_nreleases; /* Number of lock puts. */ + uintmax_t st_nupgrade; /* Number of lock upgrades. */ + uintmax_t st_ndowngrade; /* Number of lock downgrades. */ + uintmax_t st_lock_wait; /* Lock conflicts w/ subsequent wait */ + uintmax_t st_lock_nowait; /* Lock conflicts w/o subsequent wait */ + uintmax_t st_ndeadlocks; /* Number of lock deadlocks. */ + db_timeout_t st_locktimeout; /* Lock timeout. */ + uintmax_t st_nlocktimeouts; /* Number of lock timeouts. */ + db_timeout_t st_txntimeout; /* Transaction timeout. */ + uintmax_t st_ntxntimeouts; /* Number of transaction timeouts. */ + uintmax_t st_part_wait; /* Partition lock granted after wait. */ + uintmax_t st_part_nowait; /* Partition lock granted without wait. */ + uintmax_t st_part_max_wait; /* Max partition lock granted after wait. */ + uintmax_t st_part_max_nowait; /* Max partition lock granted without wait. */ + uintmax_t st_objs_wait; /* Object lock granted after wait. */ + uintmax_t st_objs_nowait; /* Object lock granted without wait. */ + uintmax_t st_lockers_wait; /* Locker lock granted after wait. */ + uintmax_t st_lockers_nowait; /* Locker lock granted without wait. */ + uintmax_t st_region_wait; /* Region lock granted after wait. */ + uintmax_t st_region_nowait; /* Region lock granted without wait. */ + u_int32_t st_hash_len; /* Max length of bucket. */ + roff_t st_regsize; /* Region size. */ +#endif +}; + +struct __db_lock_hstat { /* SHARED */ + uintmax_t st_nrequests; /* Number of lock gets. */ + uintmax_t st_nreleases; /* Number of lock puts. */ + uintmax_t st_nupgrade; /* Number of lock upgrades. */ + uintmax_t st_ndowngrade; /* Number of lock downgrades. */ + u_int32_t st_nlocks; /* Current number of locks. */ + u_int32_t st_maxnlocks; /* Maximum number of locks so far. */ + u_int32_t st_nobjects; /* Current number of objects. */ + u_int32_t st_maxnobjects; /* Maximum number of objects so far. */ + uintmax_t st_lock_wait; /* Lock conflicts w/ subsequent wait */ + uintmax_t st_lock_nowait; /* Lock conflicts w/o subsequent wait */ + uintmax_t st_nlocktimeouts; /* Number of lock timeouts. */ + uintmax_t st_ntxntimeouts; /* Number of transaction timeouts. */ + u_int32_t st_hash_len; /* Max length of bucket. */ +}; + +struct __db_lock_pstat { /* SHARED */ + u_int32_t st_nlocks; /* Current number of locks. */ + u_int32_t st_maxnlocks; /* Maximum number of locks so far. */ + u_int32_t st_nobjects; /* Current number of objects. */ + u_int32_t st_maxnobjects; /* Maximum number of objects so far. */ + uintmax_t st_locksteals; /* Number of lock steals so far. */ + uintmax_t st_objectsteals; /* Number of objects steals so far. */ +}; + +/* + * DB_LOCK_ILOCK -- + * Internal DB access method lock. + */ +struct __db_ilock { /* SHARED */ + db_pgno_t pgno; /* Page being locked. */ + u_int8_t fileid[DB_FILE_ID_LEN];/* File id. */ +#define DB_HANDLE_LOCK 1 +#define DB_RECORD_LOCK 2 +#define DB_PAGE_LOCK 3 +#define DB_DATABASE_LOCK 4 + u_int32_t type; /* Type of lock. */ +}; + +/* + * DB_LOCK -- + * The structure is allocated by the caller and filled in during a + * lock_get request (or a lock_vec/DB_LOCK_GET). + */ +struct __db_lock_u { /* SHARED */ + roff_t off; /* Offset of the lock in the region */ + u_int32_t ndx; /* Index of the object referenced by + * this lock; used for locking. */ + u_int32_t gen; /* Generation number of this lock. */ + db_lockmode_t mode; /* mode of this lock. */ +}; + +/* Lock request structure. */ +struct __db_lockreq { + db_lockop_t op; /* Operation. */ + db_lockmode_t mode; /* Requested mode. */ + db_timeout_t timeout; /* Time to expire lock. */ + DBT *obj; /* Object being locked. */ + DB_LOCK lock; /* Lock returned. */ +}; + +/******************************************************* + * Logging. + *******************************************************/ +#define DB_LOGVERSION 20 /* Current log version. */ +#define DB_LOGVERSION_LATCHING 15 /* Log version using latching: db-4.8 */ +#define DB_LOGCHKSUM 12 /* Check sum headers: db-4.5 */ +#define DB_LOGOLDVER 8 /* Oldest version supported: db-4.2 */ +#define DB_LOGMAGIC 0x040988 + +/* + * A DB_LSN has two parts, a fileid which identifies a specific file, and an + * offset within that file. The fileid is an unsigned 4-byte quantity that + * uniquely identifies a file within the log directory -- currently a simple + * counter inside the log. The offset is also an unsigned 4-byte value. The + * log manager guarantees the offset is never more than 4 bytes by switching + * to a new log file before the maximum length imposed by an unsigned 4-byte + * offset is reached. + */ +struct __db_lsn { /* SHARED */ + u_int32_t file; /* File ID. */ + u_int32_t offset; /* File offset. */ +}; + +/* + * Application-specified log record types start at DB_user_BEGIN, and must not + * equal or exceed DB_debug_FLAG. + * + * DB_debug_FLAG is the high-bit of the u_int32_t that specifies a log record + * type. If the flag is set, it's a log record that was logged for debugging + * purposes only, even if it reflects a database change -- the change was part + * of a non-durable transaction. + */ +#define DB_user_BEGIN 10000 +#define DB_debug_FLAG 0x80000000 + +/* + * DB_LOGC -- + * Log cursor. + */ +struct __db_log_cursor { + ENV *env; /* Environment */ + + DB_FH *fhp; /* File handle. */ + DB_LSN lsn; /* Cursor: LSN */ + u_int32_t len; /* Cursor: record length */ + u_int32_t prev; /* Cursor: previous record's offset */ + + DBT dbt; /* Return DBT. */ + DB_LSN p_lsn; /* Persist LSN. */ + u_int32_t p_version; /* Persist version. */ + + u_int8_t *bp; /* Allocated read buffer. */ + u_int32_t bp_size; /* Read buffer length in bytes. */ + u_int32_t bp_rlen; /* Read buffer valid data length. */ + DB_LSN bp_lsn; /* Read buffer first byte LSN. */ + + u_int32_t bp_maxrec; /* Max record length in the log file. */ + + /* DB_LOGC PUBLIC HANDLE LIST BEGIN */ + int (*close) __P((DB_LOGC *, u_int32_t)); + int (*get) __P((DB_LOGC *, DB_LSN *, DBT *, u_int32_t)); + int (*version) __P((DB_LOGC *, u_int32_t *, u_int32_t)); + /* DB_LOGC PUBLIC HANDLE LIST END */ + +#define DB_LOG_DISK 0x01 /* Log record came from disk. */ +#define DB_LOG_LOCKED 0x02 /* Log region already locked */ +#define DB_LOG_SILENT_ERR 0x04 /* Turn-off error messages. */ + u_int32_t flags; +}; + +/* Log statistics structure. */ +struct __db_log_stat { /* SHARED */ + u_int32_t st_magic; /* Log file magic number. */ + u_int32_t st_version; /* Log file version number. */ + int32_t st_mode; /* Log file permissions mode. */ + u_int32_t st_lg_bsize; /* Log buffer size. */ + u_int32_t st_lg_size; /* Log file size. */ + u_int32_t st_wc_bytes; /* Bytes to log since checkpoint. */ + u_int32_t st_wc_mbytes; /* Megabytes to log since checkpoint. */ + u_int32_t st_fileid_init; /* Initial allocation for fileids. */ +#ifndef __TEST_DB_NO_STATISTICS + u_int32_t st_nfileid; /* Current number of fileids. */ + u_int32_t st_maxnfileid; /* Maximum number of fileids used. */ + uintmax_t st_record; /* Records entered into the log. */ + u_int32_t st_w_bytes; /* Bytes to log. */ + u_int32_t st_w_mbytes; /* Megabytes to log. */ + uintmax_t st_wcount; /* Total I/O writes to the log. */ + uintmax_t st_wcount_fill; /* Overflow writes to the log. */ + uintmax_t st_rcount; /* Total I/O reads from the log. */ + uintmax_t st_scount; /* Total syncs to the log. */ + uintmax_t st_region_wait; /* Region lock granted after wait. */ + uintmax_t st_region_nowait; /* Region lock granted without wait. */ + u_int32_t st_cur_file; /* Current log file number. */ + u_int32_t st_cur_offset; /* Current log file offset. */ + u_int32_t st_disk_file; /* Known on disk log file number. */ + u_int32_t st_disk_offset; /* Known on disk log file offset. */ + u_int32_t st_maxcommitperflush; /* Max number of commits in a flush. */ + u_int32_t st_mincommitperflush; /* Min number of commits in a flush. */ + roff_t st_regsize; /* Region size. */ +#endif +}; + +/* + * We need to record the first log record of a transaction. For user + * defined logging this macro returns the place to put that information, + * if it is need in rlsnp, otherwise it leaves it unchanged. We also + * need to track the last record of the transaction, this returns the + * place to put that info. + */ +#define DB_SET_TXN_LSNP(txn, blsnp, llsnp) \ + ((txn)->set_txn_lsnp(txn, blsnp, llsnp)) + +/* + * Definition of the structure which specifies marshalling of log records. + */ +typedef enum { + LOGREC_Done, + LOGREC_ARG, + LOGREC_HDR, + LOGREC_DATA, + LOGREC_DB, + LOGREC_DBOP, + LOGREC_DBT, + LOGREC_LOCKS, + LOGREC_OP, + LOGREC_PGDBT, + LOGREC_PGDDBT, + LOGREC_PGLIST, + LOGREC_POINTER, + LOGREC_TIME +} log_rec_type_t; + +typedef const struct __log_rec_spec { + log_rec_type_t type; + u_int32_t offset; + const char *name; + const char fmt[4]; +} DB_LOG_RECSPEC; + +/* + * Size of a DBT in a log record. + */ +#define LOG_DBT_SIZE(dbt) \ + (sizeof(u_int32_t) + ((dbt) == NULL ? 0 : (dbt)->size)) + +/******************************************************* + * Shared buffer cache (mpool). + *******************************************************/ +/* Priority values for DB_MPOOLFILE->{put,set_priority}. */ +typedef enum { + DB_PRIORITY_UNCHANGED=0, + DB_PRIORITY_VERY_LOW=1, + DB_PRIORITY_LOW=2, + DB_PRIORITY_DEFAULT=3, + DB_PRIORITY_HIGH=4, + DB_PRIORITY_VERY_HIGH=5 +} DB_CACHE_PRIORITY; + +/* Per-process DB_MPOOLFILE information. */ +struct __db_mpoolfile { + DB_FH *fhp; /* Underlying file handle. */ + + /* + * !!! + * The ref, pinref and q fields are protected by the region lock. + */ + u_int32_t ref; /* Reference count. */ + + u_int32_t pinref; /* Pinned block reference count. */ + + /* + * !!! + * Explicit representations of structures from queue.h. + * TAILQ_ENTRY(__db_mpoolfile) q; + */ + struct { + struct __db_mpoolfile *tqe_next; + struct __db_mpoolfile **tqe_prev; + } q; /* Linked list of DB_MPOOLFILE's. */ + + /* + * !!! + * The rest of the fields (with the exception of the MP_FLUSH flag) + * are not thread-protected, even when they may be modified at any + * time by the application. The reason is the DB_MPOOLFILE handle + * is single-threaded from the viewpoint of the application, and so + * the only fields needing to be thread-protected are those accessed + * by checkpoint or sync threads when using DB_MPOOLFILE structures + * to flush buffers from the cache. + */ + ENV *env; /* Environment */ + MPOOLFILE *mfp; /* Underlying MPOOLFILE. */ + + u_int32_t clear_len; /* Cleared length on created pages. */ + u_int8_t /* Unique file ID. */ + fileid[DB_FILE_ID_LEN]; + int ftype; /* File type. */ + int32_t lsn_offset; /* LSN offset in page. */ + u_int32_t gbytes, bytes; /* Maximum file size. */ + DBT *pgcookie; /* Byte-string passed to pgin/pgout. */ + int32_t priority; /* Cache priority. */ + + void *addr; /* Address of mmap'd region. */ + size_t len; /* Length of mmap'd region. */ + + u_int32_t config_flags; /* Flags to DB_MPOOLFILE->set_flags. */ + + /* DB_MPOOLFILE PUBLIC HANDLE LIST BEGIN */ + int (*close) __P((DB_MPOOLFILE *, u_int32_t)); + int (*get) + __P((DB_MPOOLFILE *, db_pgno_t *, DB_TXN *, u_int32_t, void *)); + int (*get_clear_len) __P((DB_MPOOLFILE *, u_int32_t *)); + int (*get_fileid) __P((DB_MPOOLFILE *, u_int8_t *)); + int (*get_flags) __P((DB_MPOOLFILE *, u_int32_t *)); + int (*get_ftype) __P((DB_MPOOLFILE *, int *)); + int (*get_last_pgno) __P((DB_MPOOLFILE *, db_pgno_t *)); + int (*get_lsn_offset) __P((DB_MPOOLFILE *, int32_t *)); + int (*get_maxsize) __P((DB_MPOOLFILE *, u_int32_t *, u_int32_t *)); + int (*get_pgcookie) __P((DB_MPOOLFILE *, DBT *)); + int (*get_priority) __P((DB_MPOOLFILE *, DB_CACHE_PRIORITY *)); + int (*open) __P((DB_MPOOLFILE *, const char *, u_int32_t, int, size_t)); + int (*put) __P((DB_MPOOLFILE *, void *, DB_CACHE_PRIORITY, u_int32_t)); + int (*set_clear_len) __P((DB_MPOOLFILE *, u_int32_t)); + int (*set_fileid) __P((DB_MPOOLFILE *, u_int8_t *)); + int (*set_flags) __P((DB_MPOOLFILE *, u_int32_t, int)); + int (*set_ftype) __P((DB_MPOOLFILE *, int)); + int (*set_lsn_offset) __P((DB_MPOOLFILE *, int32_t)); + int (*set_maxsize) __P((DB_MPOOLFILE *, u_int32_t, u_int32_t)); + int (*set_pgcookie) __P((DB_MPOOLFILE *, DBT *)); + int (*set_priority) __P((DB_MPOOLFILE *, DB_CACHE_PRIORITY)); + int (*sync) __P((DB_MPOOLFILE *)); + /* DB_MPOOLFILE PUBLIC HANDLE LIST END */ + + /* + * MP_FILEID_SET, MP_OPEN_CALLED and MP_READONLY do not need to be + * thread protected because they are initialized before the file is + * linked onto the per-process lists, and never modified. + * + * MP_FLUSH is thread protected because it is potentially read/set by + * multiple threads of control. + */ +#define MP_FILEID_SET 0x001 /* Application supplied a file ID. */ +#define MP_FLUSH 0x002 /* Was used to flush a buffer. */ +#define MP_FOR_FLUSH 0x004 /* Was opened to flush a buffer. */ +#define MP_MULTIVERSION 0x008 /* Opened for multiversion access. */ +#define MP_OPEN_CALLED 0x010 /* File opened. */ +#define MP_READONLY 0x020 /* File is readonly. */ +#define MP_DUMMY 0x040 /* File is dummy for __memp_fput. */ + u_int32_t flags; +}; + +/* Mpool statistics structure. */ +struct __db_mpool_stat { /* SHARED */ + u_int32_t st_gbytes; /* Total cache size: GB. */ + u_int32_t st_bytes; /* Total cache size: B. */ + u_int32_t st_ncache; /* Number of cache regions. */ + u_int32_t st_max_ncache; /* Maximum number of regions. */ + db_size_t st_mmapsize; /* Maximum file size for mmap. */ + int32_t st_maxopenfd; /* Maximum number of open fd's. */ + int32_t st_maxwrite; /* Maximum buffers to write. */ + db_timeout_t st_maxwrite_sleep; /* Sleep after writing max buffers. */ + u_int32_t st_pages; /* Total number of pages. */ +#ifndef __TEST_DB_NO_STATISTICS + u_int32_t st_map; /* Pages from mapped files. */ + uintmax_t st_cache_hit; /* Pages found in the cache. */ + uintmax_t st_cache_miss; /* Pages not found in the cache. */ + uintmax_t st_page_create; /* Pages created in the cache. */ + uintmax_t st_page_in; /* Pages read in. */ + uintmax_t st_page_out; /* Pages written out. */ + uintmax_t st_ro_evict; /* Clean pages forced from the cache. */ + uintmax_t st_rw_evict; /* Dirty pages forced from the cache. */ + uintmax_t st_page_trickle; /* Pages written by memp_trickle. */ + u_int32_t st_page_clean; /* Clean pages. */ + u_int32_t st_page_dirty; /* Dirty pages. */ + u_int32_t st_hash_buckets; /* Number of hash buckets. */ + u_int32_t st_hash_mutexes; /* Number of hash bucket mutexes. */ + u_int32_t st_pagesize; /* Assumed page size. */ + u_int32_t st_hash_searches; /* Total hash chain searches. */ + u_int32_t st_hash_longest; /* Longest hash chain searched. */ + uintmax_t st_hash_examined; /* Total hash entries searched. */ + uintmax_t st_hash_nowait; /* Hash lock granted with nowait. */ + uintmax_t st_hash_wait; /* Hash lock granted after wait. */ + uintmax_t st_hash_max_nowait; /* Max hash lock granted with nowait. */ + uintmax_t st_hash_max_wait; /* Max hash lock granted after wait. */ + uintmax_t st_region_nowait; /* Region lock granted with nowait. */ + uintmax_t st_region_wait; /* Region lock granted after wait. */ + uintmax_t st_mvcc_frozen; /* Buffers frozen. */ + uintmax_t st_mvcc_thawed; /* Buffers thawed. */ + uintmax_t st_mvcc_freed; /* Frozen buffers freed. */ + uintmax_t st_alloc; /* Number of page allocations. */ + uintmax_t st_alloc_buckets; /* Buckets checked during allocation. */ + uintmax_t st_alloc_max_buckets;/* Max checked during allocation. */ + uintmax_t st_alloc_pages; /* Pages checked during allocation. */ + uintmax_t st_alloc_max_pages; /* Max checked during allocation. */ + uintmax_t st_io_wait; /* Thread waited on buffer I/O. */ + uintmax_t st_sync_interrupted; /* Number of times sync interrupted. */ + uintmax_t st_oddfsize_detect; /* Odd file size detected. */ + uintmax_t st_oddfsize_resolve; /* Odd file size resolved. */ + roff_t st_regsize; /* Region size. */ + roff_t st_regmax; /* Region max. */ +#endif +}; + +/* + * Mpool file statistics structure. + * The first fields in this structure must mirror the __db_mpool_fstat_int + * structure, since content is mem copied between the two. + */ +struct __db_mpool_fstat { + u_int32_t st_pagesize; /* Page size. */ +#ifndef __TEST_DB_NO_STATISTICS + u_int32_t st_map; /* Pages from mapped files. */ + uintmax_t st_cache_hit; /* Pages found in the cache. */ + uintmax_t st_cache_miss; /* Pages not found in the cache. */ + uintmax_t st_page_create; /* Pages created in the cache. */ + uintmax_t st_page_in; /* Pages read in. */ + uintmax_t st_page_out; /* Pages written out. */ + uintmax_t st_backup_spins; /* Number of spins during a copy. */ +#endif + char *file_name; /* File name. */ +}; + +/******************************************************* + * Transactions and recovery. + *******************************************************/ +#define DB_TXNVERSION 1 + +typedef enum { + DB_TXN_ABORT=0, /* Public. */ + DB_TXN_APPLY=1, /* Public. */ + DB_TXN_BACKWARD_ROLL=3, /* Public. */ + DB_TXN_FORWARD_ROLL=4, /* Public. */ + DB_TXN_OPENFILES=5, /* Internal. */ + DB_TXN_POPENFILES=6, /* Internal. */ + DB_TXN_PRINT=7, /* Public. */ + DB_TXN_LOG_VERIFY=8 /* Internal. */ +} db_recops; + +/* + * BACKWARD_ALLOC is used during the forward pass to pick up any aborted + * allocations for files that were created during the forward pass. + * The main difference between _ALLOC and _ROLL is that the entry for + * the file not exist during the rollforward pass. + */ +#define DB_UNDO(op) ((op) == DB_TXN_ABORT || (op) == DB_TXN_BACKWARD_ROLL) +#define DB_REDO(op) ((op) == DB_TXN_FORWARD_ROLL || (op) == DB_TXN_APPLY) + +struct __db_txn { + DB_TXNMGR *mgrp; /* Pointer to transaction manager. */ + DB_TXN *parent; /* Pointer to transaction's parent. */ + DB_LOCKER *locker; /* Locker for this txn. */ + DB_THREAD_INFO *thread_info; /* Pointer to thread information. */ + + char *name; /* Transaction name. */ + + void *td; /* Detail structure within region. */ + db_timeout_t lock_timeout; /* Timeout for locks for this txn. */ + void *txn_list; /* Undo information for parent. */ + + /* + * !!! + * Explicit representations of structures from queue.h. + * TAILQ_ENTRY(__db_txn) links; + */ + struct { + struct __db_txn *tqe_next; + struct __db_txn **tqe_prev; + } links; /* Links transactions off manager. */ + + /* + * !!! + * Explicit representations of structures from shqueue.h. + * SH_TAILQ_ENTRY xa_links; + * These links link together transactions that are active in + * the same thread of control. + */ + struct { + db_ssize_t stqe_next; + db_ssize_t stqe_prev; + } xa_links; /* Links XA transactions. */ + + /* + * !!! + * Explicit representations of structures from queue.h. + * TAILQ_HEAD(__events, __txn_event) events; + */ + struct { + struct __txn_event *tqh_first; + struct __txn_event **tqh_last; + } events; /* Links deferred events. */ + + /* + * !!! + * Explicit representations of structures from queue.h. + * STAILQ_HEAD(__logrec, __txn_logrec) logs; + */ + struct { + struct __txn_logrec *stqh_first; + struct __txn_logrec **stqh_last; + } logs; /* Links in memory log records. */ + + /* + * !!! + * Explicit representations of structures from queue.h. + * TAILQ_ENTRY(__db_txn) klinks; + */ + struct { + struct __db_txn *tqe_next; + struct __db_txn **tqe_prev; + } klinks; /* Links of children in parent. */ + + /* + * !!! + * Explicit representations of structures from queue.h. + * TAILQ_HEAD(__kids, __db_txn) kids; + */ + struct __kids { + struct __db_txn *tqh_first; + struct __db_txn **tqh_last; + } kids; + + /* + * !!! + * Explicit representations of structures from queue.h. + * TAILQ_HEAD(__my_cursors, __dbc) my_cursors; + */ + struct __my_cursors { + struct __dbc *tqh_first; + struct __dbc **tqh_last; + } my_cursors; + u_int32_t cursors; /* Number of cursors open for txn */ + u_int32_t txnid; /* Unique transaction id. */ + + void *api_internal; /* C++ API private. */ + + /* + * !!! + * Explicit representations of structures from queue.h. + * TAILQ_HEAD(__femfs, MPOOLFILE) femfs; + * + * These are DBs involved in file extension in this transaction. + */ + struct __femfs { + DB *tqh_first; + DB **tqh_last; + } femfs; + + DB_TXN_TOKEN *token_buffer; /* User's commit token buffer. */ + void *xml_internal; /* XML API private. */ + + /* DB_TXN PUBLIC HANDLE LIST BEGIN */ + int (*abort) __P((DB_TXN *)); + int (*commit) __P((DB_TXN *, u_int32_t)); + int (*discard) __P((DB_TXN *, u_int32_t)); + int (*get_name) __P((DB_TXN *, const char **)); + int (*get_priority) __P((DB_TXN *, u_int32_t *)); + u_int32_t (*id) __P((DB_TXN *)); + int (*prepare) __P((DB_TXN *, u_int8_t *)); + int (*set_commit_token) __P((DB_TXN *, DB_TXN_TOKEN *)); + int (*set_name) __P((DB_TXN *, const char *)); + int (*set_priority) __P((DB_TXN *, u_int32_t)); + int (*set_timeout) __P((DB_TXN *, db_timeout_t, u_int32_t)); + /* DB_TXN PUBLIC HANDLE LIST END */ + + /* DB_TXN PRIVATE HANDLE LIST BEGIN */ + void (*set_txn_lsnp) __P((DB_TXN *txn, DB_LSN **, DB_LSN **)); + /* DB_TXN PRIVATE HANDLE LIST END */ + +#define TXN_XA_THREAD_NOTA 0 +#define TXN_XA_THREAD_ASSOCIATED 1 +#define TXN_XA_THREAD_SUSPENDED 2 +#define TXN_XA_THREAD_UNASSOCIATED 3 + u_int32_t xa_thr_status; + +#define TXN_CHILDCOMMIT 0x00001 /* Txn has committed. */ +#define TXN_COMPENSATE 0x00002 /* Compensating transaction. */ +#define TXN_DEADLOCK 0x00004 /* Txn has deadlocked. */ +#define TXN_FAMILY 0x00008 /* Cursors/children are independent. */ +#define TXN_IGNORE_LEASE 0x00010 /* Skip lease check at commit time. */ +#define TXN_INFAMILY 0x00020 /* Part of a transaction family. */ +#define TXN_LOCKTIMEOUT 0x00040 /* Txn has a lock timeout. */ +#define TXN_MALLOC 0x00080 /* Structure allocated by TXN system. */ +#define TXN_NOSYNC 0x00100 /* Do not sync on prepare and commit. */ +#define TXN_NOWAIT 0x00200 /* Do not wait on locks. */ +#define TXN_PRIVATE 0x00400 /* Txn owned by cursor. */ +#define TXN_READONLY 0x00800 /* CDS group handle. */ +#define TXN_READ_COMMITTED 0x01000 /* Txn has degree 2 isolation. */ +#define TXN_READ_UNCOMMITTED 0x02000 /* Txn has degree 1 isolation. */ +#define TXN_RESTORED 0x04000 /* Txn has been restored. */ +#define TXN_SNAPSHOT 0x08000 /* Snapshot Isolation. */ +#define TXN_SYNC 0x10000 /* Write and sync on prepare/commit. */ +#define TXN_WRITE_NOSYNC 0x20000 /* Write only on prepare/commit. */ +#define TXN_BULK 0x40000 /* Enable bulk loading optimization. */ + u_int32_t flags; +}; + +#define TXN_SYNC_FLAGS (TXN_SYNC | TXN_NOSYNC | TXN_WRITE_NOSYNC) + +/* + * Structure used for two phase commit interface. + * We set the size of our global transaction id (gid) to be 128 in order + * to match that defined by the XA X/Open standard. + */ +#define DB_GID_SIZE 128 +struct __db_preplist { + DB_TXN *txn; + u_int8_t gid[DB_GID_SIZE]; +}; + +/* Transaction statistics structure. */ +struct __db_txn_active { + u_int32_t txnid; /* Transaction ID */ + u_int32_t parentid; /* Transaction ID of parent */ + pid_t pid; /* Process owning txn ID */ + db_threadid_t tid; /* Thread owning txn ID */ + + DB_LSN lsn; /* LSN when transaction began */ + + DB_LSN read_lsn; /* Read LSN for MVCC */ + u_int32_t mvcc_ref; /* MVCC reference count */ + + u_int32_t priority; /* Deadlock resolution priority */ + +#define TXN_ABORTED 1 +#define TXN_COMMITTED 2 +#define TXN_NEED_ABORT 3 +#define TXN_PREPARED 4 +#define TXN_RUNNING 5 + u_int32_t status; /* Status of the transaction */ + +#define TXN_XA_ACTIVE 1 +#define TXN_XA_DEADLOCKED 2 +#define TXN_XA_IDLE 3 +#define TXN_XA_PREPARED 4 +#define TXN_XA_ROLLEDBACK 5 + u_int32_t xa_status; /* XA status */ + + u_int8_t gid[DB_GID_SIZE]; /* Global transaction ID */ + char name[51]; /* 50 bytes of name, nul termination */ +}; + +struct __db_txn_stat { + u_int32_t st_nrestores; /* number of restored transactions + after recovery. */ +#ifndef __TEST_DB_NO_STATISTICS + DB_LSN st_last_ckp; /* lsn of the last checkpoint */ + time_t st_time_ckp; /* time of last checkpoint */ + u_int32_t st_last_txnid; /* last transaction id given out */ + u_int32_t st_inittxns; /* inital txns allocated */ + u_int32_t st_maxtxns; /* maximum txns possible */ + uintmax_t st_naborts; /* number of aborted transactions */ + uintmax_t st_nbegins; /* number of begun transactions */ + uintmax_t st_ncommits; /* number of committed transactions */ + u_int32_t st_nactive; /* number of active transactions */ + u_int32_t st_nsnapshot; /* number of snapshot transactions */ + u_int32_t st_maxnactive; /* maximum active transactions */ + u_int32_t st_maxnsnapshot; /* maximum snapshot transactions */ + uintmax_t st_region_wait; /* Region lock granted after wait. */ + uintmax_t st_region_nowait; /* Region lock granted without wait. */ + roff_t st_regsize; /* Region size. */ + DB_TXN_ACTIVE *st_txnarray; /* array of active transactions */ +#endif +}; + +#define DB_TXN_TOKEN_SIZE 20 +struct __db_txn_token { + u_int8_t buf[DB_TXN_TOKEN_SIZE]; +}; + +/******************************************************* + * Replication. + *******************************************************/ +/* Special, out-of-band environment IDs. */ +#define DB_EID_BROADCAST -1 +#define DB_EID_INVALID -2 +#define DB_EID_MASTER -3 + +#define DB_REP_DEFAULT_PRIORITY 100 + +/* Acknowledgement policies; 0 reserved as OOB. */ +#define DB_REPMGR_ACKS_ALL 1 +#define DB_REPMGR_ACKS_ALL_AVAILABLE 2 +#define DB_REPMGR_ACKS_ALL_PEERS 3 +#define DB_REPMGR_ACKS_NONE 4 +#define DB_REPMGR_ACKS_ONE 5 +#define DB_REPMGR_ACKS_ONE_PEER 6 +#define DB_REPMGR_ACKS_QUORUM 7 + +/* Replication timeout configuration values. */ +#define DB_REP_ACK_TIMEOUT 1 /* RepMgr acknowledgements. */ +#define DB_REP_CHECKPOINT_DELAY 2 /* Master checkpoint delay. */ +#define DB_REP_CONNECTION_RETRY 3 /* RepMgr connections. */ +#define DB_REP_ELECTION_RETRY 4 /* RepMgr elect retries. */ +#define DB_REP_ELECTION_TIMEOUT 5 /* Rep normal elections. */ +#define DB_REP_FULL_ELECTION_TIMEOUT 6 /* Rep full elections. */ +#define DB_REP_HEARTBEAT_MONITOR 7 /* RepMgr client HB monitor. */ +#define DB_REP_HEARTBEAT_SEND 8 /* RepMgr master send freq. */ +#define DB_REP_LEASE_TIMEOUT 9 /* Master leases. */ + +/* + * Event notification types. (Tcl testing interface currently assumes there are + * no more than 32 of these.) + */ +#define DB_EVENT_PANIC 0 +#define DB_EVENT_REG_ALIVE 1 +#define DB_EVENT_REG_PANIC 2 +#define DB_EVENT_REP_CLIENT 3 +#define DB_EVENT_REP_CONNECT_BROKEN 4 +#define DB_EVENT_REP_CONNECT_ESTD 5 +#define DB_EVENT_REP_CONNECT_TRY_FAILED 6 +#define DB_EVENT_REP_DUPMASTER 7 +#define DB_EVENT_REP_ELECTED 8 +#define DB_EVENT_REP_ELECTION_FAILED 9 +#define DB_EVENT_REP_INIT_DONE 10 +#define DB_EVENT_REP_JOIN_FAILURE 11 +#define DB_EVENT_REP_LOCAL_SITE_REMOVED 12 +#define DB_EVENT_REP_MASTER 13 +#define DB_EVENT_REP_MASTER_FAILURE 14 +#define DB_EVENT_REP_NEWMASTER 15 +#define DB_EVENT_REP_PERM_FAILED 16 +#define DB_EVENT_REP_SITE_ADDED 17 +#define DB_EVENT_REP_SITE_REMOVED 18 +#define DB_EVENT_REP_STARTUPDONE 19 +#define DB_EVENT_REP_WOULD_ROLLBACK 20 /* Undocumented; C API only. */ +#define DB_EVENT_WRITE_FAILED 21 +#define DB_EVENT_NO_SUCH_EVENT 0xffffffff /* OOB sentinel value */ + +/* Replication Manager site status. */ +struct __db_repmgr_site { + int eid; + char *host; + u_int port; + +#define DB_REPMGR_CONNECTED 1 +#define DB_REPMGR_DISCONNECTED 2 + u_int32_t status; + +#define DB_REPMGR_ISPEER 0x01 + u_int32_t flags; +}; + +/* Replication statistics. */ +struct __db_rep_stat { /* SHARED */ + /* !!! + * Many replication statistics fields cannot be protected by a mutex + * without an unacceptable performance penalty, since most message + * processing is done without the need to hold a region-wide lock. + * Fields whose comments end with a '+' may be updated without holding + * the replication or log mutexes (as appropriate), and thus may be + * off somewhat (or, on unreasonable architectures under unlucky + * circumstances, garbaged). + */ + u_int32_t st_startup_complete; /* Site completed client sync-up. */ +#ifndef __TEST_DB_NO_STATISTICS + uintmax_t st_log_queued; /* Log records currently queued.+ */ + u_int32_t st_status; /* Current replication status. */ + DB_LSN st_next_lsn; /* Next LSN to use or expect. */ + DB_LSN st_waiting_lsn; /* LSN we're awaiting, if any. */ + DB_LSN st_max_perm_lsn; /* Maximum permanent LSN. */ + db_pgno_t st_next_pg; /* Next pg we expect. */ + db_pgno_t st_waiting_pg; /* pg we're awaiting, if any. */ + + u_int32_t st_dupmasters; /* # of times a duplicate master + condition was detected.+ */ + db_ssize_t st_env_id; /* Current environment ID. */ + u_int32_t st_env_priority; /* Current environment priority. */ + uintmax_t st_bulk_fills; /* Bulk buffer fills. */ + uintmax_t st_bulk_overflows; /* Bulk buffer overflows. */ + uintmax_t st_bulk_records; /* Bulk records stored. */ + uintmax_t st_bulk_transfers; /* Transfers of bulk buffers. */ + uintmax_t st_client_rerequests;/* Number of forced rerequests. */ + uintmax_t st_client_svc_req; /* Number of client service requests + received by this client. */ + uintmax_t st_client_svc_miss; /* Number of client service requests + missing on this client. */ + u_int32_t st_gen; /* Current generation number. */ + u_int32_t st_egen; /* Current election gen number. */ + uintmax_t st_lease_chk; /* Lease validity checks. */ + uintmax_t st_lease_chk_misses; /* Lease checks invalid. */ + uintmax_t st_lease_chk_refresh; /* Lease refresh attempts. */ + uintmax_t st_lease_sends; /* Lease messages sent live. */ + + uintmax_t st_log_duplicated; /* Log records received multiply.+ */ + uintmax_t st_log_queued_max; /* Max. log records queued at once.+ */ + uintmax_t st_log_queued_total; /* Total # of log recs. ever queued.+ */ + uintmax_t st_log_records; /* Log records received and put.+ */ + uintmax_t st_log_requested; /* Log recs. missed and requested.+ */ + db_ssize_t st_master; /* Env. ID of the current master. */ + uintmax_t st_master_changes; /* # of times we've switched masters. */ + uintmax_t st_msgs_badgen; /* Messages with a bad generation #.+ */ + uintmax_t st_msgs_processed; /* Messages received and processed.+ */ + uintmax_t st_msgs_recover; /* Messages ignored because this site + was a client in recovery.+ */ + uintmax_t st_msgs_send_failures;/* # of failed message sends.+ */ + uintmax_t st_msgs_sent; /* # of successful message sends.+ */ + uintmax_t st_newsites; /* # of NEWSITE msgs. received.+ */ + u_int32_t st_nsites; /* Current number of sites we will + assume during elections. */ + uintmax_t st_nthrottles; /* # of times we were throttled. */ + uintmax_t st_outdated; /* # of times we detected and returned + an OUTDATED condition.+ */ + uintmax_t st_pg_duplicated; /* Pages received multiply.+ */ + uintmax_t st_pg_records; /* Pages received and stored.+ */ + uintmax_t st_pg_requested; /* Pages missed and requested.+ */ + uintmax_t st_txns_applied; /* # of transactions applied.+ */ + uintmax_t st_startsync_delayed;/* # of STARTSYNC msgs delayed.+ */ + + /* Elections generally. */ + uintmax_t st_elections; /* # of elections held.+ */ + uintmax_t st_elections_won; /* # of elections won by this site.+ */ + + /* Statistics about an in-progress election. */ + db_ssize_t st_election_cur_winner; /* Current front-runner. */ + u_int32_t st_election_gen; /* Election generation number. */ + u_int32_t st_election_datagen; /* Election data generation number. */ + DB_LSN st_election_lsn; /* Max. LSN of current winner. */ + u_int32_t st_election_nsites; /* # of "registered voters". */ + u_int32_t st_election_nvotes; /* # of "registered voters" needed. */ + u_int32_t st_election_priority; /* Current election priority. */ + int32_t st_election_status; /* Current election status. */ + u_int32_t st_election_tiebreaker;/* Election tiebreaker value. */ + u_int32_t st_election_votes; /* Votes received in this round. */ + u_int32_t st_election_sec; /* Last election time seconds. */ + u_int32_t st_election_usec; /* Last election time useconds. */ + u_int32_t st_max_lease_sec; /* Maximum lease timestamp seconds. */ + u_int32_t st_max_lease_usec; /* Maximum lease timestamp useconds. */ + + /* Undocumented statistics only used by the test system. */ +#ifdef CONFIG_TEST + u_int32_t st_filefail_cleanups; /* # of FILE_FAIL cleanups done. */ +#endif +#endif +}; + +/* Replication Manager statistics. */ +struct __db_repmgr_stat { /* SHARED */ + uintmax_t st_perm_failed; /* # of insufficiently ack'ed msgs. */ + uintmax_t st_msgs_queued; /* # msgs queued for network delay. */ + uintmax_t st_msgs_dropped; /* # msgs discarded due to excessive + queue length. */ + uintmax_t st_connection_drop; /* Existing connections dropped. */ + uintmax_t st_connect_fail; /* Failed new connection attempts. */ + uintmax_t st_elect_threads; /* # of active election threads. */ + uintmax_t st_max_elect_threads; /* Max concurrent e-threads ever. */ +}; + +/* Replication Manager connection error. */ +struct __db_repmgr_conn_err { + int eid; /* Replication Environment ID. */ + int error; /* System networking error code. */ +}; + +/******************************************************* + * Sequences. + *******************************************************/ +/* + * The storage record for a sequence. + */ +struct __db_seq_record { + u_int32_t seq_version; /* Version size/number. */ + u_int32_t flags; /* DB_SEQ_XXX Flags. */ + db_seq_t seq_value; /* Current value. */ + db_seq_t seq_max; /* Max permitted. */ + db_seq_t seq_min; /* Min permitted. */ +}; + +/* + * Handle for a sequence object. + */ +struct __db_sequence { + DB *seq_dbp; /* DB handle for this sequence. */ + db_mutex_t mtx_seq; /* Mutex if sequence is threaded. */ + DB_SEQ_RECORD *seq_rp; /* Pointer to current data. */ + DB_SEQ_RECORD seq_record; /* Data from DB_SEQUENCE. */ + int32_t seq_cache_size; /* Number of values cached. */ + db_seq_t seq_last_value; /* Last value cached. */ + db_seq_t seq_prev_value; /* Last value returned. */ + DBT seq_key; /* DBT pointing to sequence key. */ + DBT seq_data; /* DBT pointing to seq_record. */ + + /* API-private structure: used by C++ and Java. */ + void *api_internal; + + /* DB_SEQUENCE PUBLIC HANDLE LIST BEGIN */ + int (*close) __P((DB_SEQUENCE *, u_int32_t)); + int (*get) __P((DB_SEQUENCE *, + DB_TXN *, int32_t, db_seq_t *, u_int32_t)); + int (*get_cachesize) __P((DB_SEQUENCE *, int32_t *)); + int (*get_db) __P((DB_SEQUENCE *, DB **)); + int (*get_flags) __P((DB_SEQUENCE *, u_int32_t *)); + int (*get_key) __P((DB_SEQUENCE *, DBT *)); + int (*get_range) __P((DB_SEQUENCE *, + db_seq_t *, db_seq_t *)); + int (*initial_value) __P((DB_SEQUENCE *, db_seq_t)); + int (*open) __P((DB_SEQUENCE *, + DB_TXN *, DBT *, u_int32_t)); + int (*remove) __P((DB_SEQUENCE *, DB_TXN *, u_int32_t)); + int (*set_cachesize) __P((DB_SEQUENCE *, int32_t)); + int (*set_flags) __P((DB_SEQUENCE *, u_int32_t)); + int (*set_range) __P((DB_SEQUENCE *, db_seq_t, db_seq_t)); + int (*stat) __P((DB_SEQUENCE *, + DB_SEQUENCE_STAT **, u_int32_t)); + int (*stat_print) __P((DB_SEQUENCE *, u_int32_t)); + /* DB_SEQUENCE PUBLIC HANDLE LIST END */ +}; + +struct __db_seq_stat { /* SHARED */ + uintmax_t st_wait; /* Sequence lock granted w/o wait. */ + uintmax_t st_nowait; /* Sequence lock granted after wait. */ + db_seq_t st_current; /* Current value in db. */ + db_seq_t st_value; /* Current cached value. */ + db_seq_t st_last_value; /* Last cached value. */ + db_seq_t st_min; /* Minimum value. */ + db_seq_t st_max; /* Maximum value. */ + int32_t st_cache_size; /* Cache size. */ + u_int32_t st_flags; /* Flag value. */ +}; + +/******************************************************* + * Access methods. + *******************************************************/ +/* + * Any new methods need to retain the original numbering. The type + * is written in a log record so must be maintained. + */ +typedef enum { + DB_BTREE=1, + DB_HASH=2, + DB_HEAP=6, + DB_RECNO=3, + DB_QUEUE=4, + DB_UNKNOWN=5 /* Figure it out on open. */ +} DBTYPE; + +#define DB_RENAMEMAGIC 0x030800 /* File has been renamed. */ + +#define DB_BTREEVERSION 9 /* Current btree version. */ +#define DB_BTREEOLDVER 8 /* Oldest btree version supported. */ +#define DB_BTREEMAGIC 0x053162 + +#define DB_HASHVERSION 9 /* Current hash version. */ +#define DB_HASHOLDVER 7 /* Oldest hash version supported. */ +#define DB_HASHMAGIC 0x061561 + +#define DB_HEAPVERSION 1 /* Current heap version. */ +#define DB_HEAPOLDVER 1 /* Oldest heap version supported. */ +#define DB_HEAPMAGIC 0x074582 + +#define DB_QAMVERSION 4 /* Current queue version. */ +#define DB_QAMOLDVER 3 /* Oldest queue version supported. */ +#define DB_QAMMAGIC 0x042253 + +#define DB_SEQUENCE_VERSION 2 /* Current sequence version. */ +#define DB_SEQUENCE_OLDVER 1 /* Oldest sequence version supported. */ + +/* + * DB access method and cursor operation values. Each value is an operation + * code to which additional bit flags are added. + */ +#define DB_AFTER 1 /* Dbc.put */ +#define DB_APPEND 2 /* Db.put */ +#define DB_BEFORE 3 /* Dbc.put */ +#define DB_CONSUME 4 /* Db.get */ +#define DB_CONSUME_WAIT 5 /* Db.get */ +#define DB_CURRENT 6 /* Dbc.get, Dbc.put, DbLogc.get */ +#define DB_FIRST 7 /* Dbc.get, DbLogc->get */ +#define DB_GET_BOTH 8 /* Db.get, Dbc.get */ +#define DB_GET_BOTHC 9 /* Dbc.get (internal) */ +#define DB_GET_BOTH_RANGE 10 /* Db.get, Dbc.get */ +#define DB_GET_RECNO 11 /* Dbc.get */ +#define DB_JOIN_ITEM 12 /* Dbc.get; don't do primary lookup */ +#define DB_KEYFIRST 13 /* Dbc.put */ +#define DB_KEYLAST 14 /* Dbc.put */ +#define DB_LAST 15 /* Dbc.get, DbLogc->get */ +#define DB_NEXT 16 /* Dbc.get, DbLogc->get */ +#define DB_NEXT_DUP 17 /* Dbc.get */ +#define DB_NEXT_NODUP 18 /* Dbc.get */ +#define DB_NODUPDATA 19 /* Db.put, Dbc.put */ +#define DB_NOOVERWRITE 20 /* Db.put */ +#define DB_OVERWRITE_DUP 21 /* Dbc.put, Db.put; no DB_KEYEXIST */ +#define DB_POSITION 22 /* Dbc.dup */ +#define DB_PREV 23 /* Dbc.get, DbLogc->get */ +#define DB_PREV_DUP 24 /* Dbc.get */ +#define DB_PREV_NODUP 25 /* Dbc.get */ +#define DB_SET 26 /* Dbc.get, DbLogc->get */ +#define DB_SET_RANGE 27 /* Dbc.get */ +#define DB_SET_RECNO 28 /* Db.get, Dbc.get */ +#define DB_UPDATE_SECONDARY 29 /* Dbc.get, Dbc.del (internal) */ +#define DB_SET_LTE 30 /* Dbc.get (internal) */ +#define DB_GET_BOTH_LTE 31 /* Dbc.get (internal) */ + +/* This has to change when the max opcode hits 255. */ +#define DB_OPFLAGS_MASK 0x000000ff /* Mask for operations flags. */ + +/* + * DB (user visible) error return codes. + * + * !!! + * We don't want our error returns to conflict with other packages where + * possible, so pick a base error value that's hopefully not common. We + * document that we own the error name space from -30,800 to -30,999. + */ +/* DB (public) error return codes. */ +#define DB_BUFFER_SMALL (-30999)/* User memory too small for return. */ +#define DB_DONOTINDEX (-30998)/* "Null" return from 2ndary callbk. */ +#define DB_FOREIGN_CONFLICT (-30997)/* A foreign db constraint triggered. */ +#define DB_HEAP_FULL (-30996)/* No free space in a heap file. */ +#define DB_KEYEMPTY (-30995)/* Key/data deleted or never created. */ +#define DB_KEYEXIST (-30994)/* The key/data pair already exists. */ +#define DB_LOCK_DEADLOCK (-30993)/* Deadlock. */ +#define DB_LOCK_NOTGRANTED (-30992)/* Lock unavailable. */ +#define DB_LOG_BUFFER_FULL (-30991)/* In-memory log buffer full. */ +#define DB_LOG_VERIFY_BAD (-30990)/* Log verification failed. */ +#define DB_NOSERVER (-30989)/* Server panic return. */ +#define DB_NOTFOUND (-30988)/* Key/data pair not found (EOF). */ +#define DB_OLD_VERSION (-30987)/* Out-of-date version. */ +#define DB_PAGE_NOTFOUND (-30986)/* Requested page not found. */ +#define DB_REP_DUPMASTER (-30985)/* There are two masters. */ +#define DB_REP_HANDLE_DEAD (-30984)/* Rolled back a commit. */ +#define DB_REP_HOLDELECTION (-30983)/* Time to hold an election. */ +#define DB_REP_IGNORE (-30982)/* This msg should be ignored.*/ +#define DB_REP_ISPERM (-30981)/* Cached not written perm written.*/ +#define DB_REP_JOIN_FAILURE (-30980)/* Unable to join replication group. */ +#define DB_REP_LEASE_EXPIRED (-30979)/* Master lease has expired. */ +#define DB_REP_LOCKOUT (-30978)/* API/Replication lockout now. */ +#define DB_REP_NEWSITE (-30977)/* New site entered system. */ +#define DB_REP_NOTPERM (-30976)/* Permanent log record not written. */ +#define DB_REP_UNAVAIL (-30975)/* Site cannot currently be reached. */ +#define DB_REP_WOULDROLLBACK (-30974)/* UNDOC: rollback inhibited by app. */ +#define DB_RUNRECOVERY (-30973)/* Panic return. */ +#define DB_SECONDARY_BAD (-30972)/* Secondary index corrupt. */ +#define DB_TIMEOUT (-30971)/* Timed out on read consistency. */ +#define DB_VERIFY_BAD (-30970)/* Verify failed; bad format. */ +#define DB_VERSION_MISMATCH (-30969)/* Environment version mismatch. */ + +/* DB (private) error return codes. */ +#define DB_ALREADY_ABORTED (-30899) +#define DB_CHKSUM_FAIL (-30898)/* Checksum failed. */ +#define DB_DELETED (-30897)/* Recovery file marked deleted. */ +#define DB_EVENT_NOT_HANDLED (-30896)/* Forward event to application. */ +#define DB_NEEDSPLIT (-30895)/* Page needs to be split. */ +#define DB_REP_BULKOVF (-30894)/* Rep bulk buffer overflow. */ +#define DB_REP_LOGREADY (-30893)/* Rep log ready for recovery. */ +#define DB_REP_NEWMASTER (-30892)/* We have learned of a new master. */ +#define DB_REP_PAGEDONE (-30891)/* This page was already done. */ +#define DB_SURPRISE_KID (-30890)/* Child commit where parent + didn't know it was a parent. */ +#define DB_SWAPBYTES (-30889)/* Database needs byte swapping. */ +#define DB_TXN_CKP (-30888)/* Encountered ckp record in log. */ +#define DB_VERIFY_FATAL (-30887)/* DB->verify cannot proceed. */ + +/* Database handle. */ +struct __db { + /******************************************************* + * Public: owned by the application. + *******************************************************/ + u_int32_t pgsize; /* Database logical page size. */ + DB_CACHE_PRIORITY priority; /* Database priority in cache. */ + + /* Callbacks. */ + int (*db_append_recno) __P((DB *, DBT *, db_recno_t)); + void (*db_feedback) __P((DB *, int, int)); + int (*dup_compare) __P((DB *, const DBT *, const DBT *)); + + void *app_private; /* Application-private handle. */ + + /******************************************************* + * Private: owned by DB. + *******************************************************/ + DB_ENV *dbenv; /* Backing public environment. */ + ENV *env; /* Backing private environment. */ + + DBTYPE type; /* DB access method type. */ + + DB_MPOOLFILE *mpf; /* Backing buffer pool. */ + + db_mutex_t mutex; /* Synchronization for free threading */ + + char *fname, *dname; /* File/database passed to DB->open. */ + const char *dirname; /* Directory of DB file. */ + u_int32_t open_flags; /* Flags passed to DB->open. */ + + u_int8_t fileid[DB_FILE_ID_LEN];/* File's unique ID for locking. */ + + u_int32_t adj_fileid; /* File's unique ID for curs. adj. */ + +#define DB_LOGFILEID_INVALID -1 + FNAME *log_filename; /* File's naming info for logging. */ + + db_pgno_t meta_pgno; /* Meta page number */ + DB_LOCKER *locker; /* Locker for handle locking. */ + DB_LOCKER *cur_locker; /* Current handle lock holder. */ + DB_TXN *cur_txn; /* Opening transaction. */ + DB_LOCKER *associate_locker; /* Locker for DB->associate call. */ + DB_LOCK handle_lock; /* Lock held on this handle. */ + + time_t timestamp; /* Handle timestamp for replication. */ + u_int32_t fid_gen; /* Rep generation number for fids. */ + + /* + * Returned data memory for DB->get() and friends. + */ + DBT my_rskey; /* Secondary key. */ + DBT my_rkey; /* [Primary] key. */ + DBT my_rdata; /* Data. */ + + /* + * !!! + * Some applications use DB but implement their own locking outside of + * DB. If they're using fcntl(2) locking on the underlying database + * file, and we open and close a file descriptor for that file, we will + * discard their locks. The DB_FCNTL_LOCKING flag to DB->open is an + * undocumented interface to support this usage which leaves any file + * descriptors we open until DB->close. This will only work with the + * DB->open interface and simple caches, e.g., creating a transaction + * thread may open/close file descriptors this flag doesn't protect. + * Locking with fcntl(2) on a file that you don't own is a very, very + * unsafe thing to do. 'Nuff said. + */ + DB_FH *saved_open_fhp; /* Saved file handle. */ + + /* + * Linked list of DBP's, linked from the ENV, used to keep track + * of all open db handles for cursor adjustment. + * + * !!! + * Explicit representations of structures from queue.h. + * TAILQ_ENTRY(__db) dblistlinks; + */ + struct { + struct __db *tqe_next; + struct __db **tqe_prev; + } dblistlinks; + + /* + * Cursor queues. + * + * !!! + * Explicit representations of structures from queue.h. + * TAILQ_HEAD(__cq_fq, __dbc) free_queue; + * TAILQ_HEAD(__cq_aq, __dbc) active_queue; + * TAILQ_HEAD(__cq_jq, __dbc) join_queue; + */ + struct __cq_fq { + struct __dbc *tqh_first; + struct __dbc **tqh_last; + } free_queue; + struct __cq_aq { + struct __dbc *tqh_first; + struct __dbc **tqh_last; + } active_queue; + struct __cq_jq { + struct __dbc *tqh_first; + struct __dbc **tqh_last; + } join_queue; + + /* + * Secondary index support. + * + * Linked list of secondary indices -- set in the primary. + * + * !!! + * Explicit representations of structures from queue.h. + * LIST_HEAD(s_secondaries, __db); + */ + struct { + struct __db *lh_first; + } s_secondaries; + + /* + * List entries for secondaries, and reference count of how many + * threads are updating this secondary (see Dbc.put). + * + * !!! + * Note that these are synchronized by the primary's mutex, but + * filled in in the secondaries. + * + * !!! + * Explicit representations of structures from queue.h. + * LIST_ENTRY(__db) s_links; + */ + struct { + struct __db *le_next; + struct __db **le_prev; + } s_links; + u_int32_t s_refcnt; + + /* Secondary callback and free functions -- set in the secondary. */ + int (*s_callback) __P((DB *, const DBT *, const DBT *, DBT *)); + + /* Reference to primary -- set in the secondary. */ + DB *s_primary; + +#define DB_ASSOC_IMMUTABLE_KEY 0x00000001 /* Secondary key is immutable. */ +#define DB_ASSOC_CREATE 0x00000002 /* Secondary db populated on open. */ + + /* Flags passed to associate -- set in the secondary. */ + u_int32_t s_assoc_flags; + + /* + * Foreign key support. + * + * Linked list of primary dbs -- set in the foreign db + * + * !!! + * Explicit representations of structures from queue.h. + * LIST_HEAD(f_primaries, __db); + */ + struct { + struct __db_foreign_info *lh_first; + } f_primaries; + + /* + * !!! + * Explicit representations of structures from queue.h. + * TAILQ_ENTRY(__db) felink; + * + * Links in a list of DBs involved in file extension + * during a transaction. These are to be used only while the + * metadata is locked. + */ + struct { + struct __db *tqe_next; + struct __db **tqe_prev; + } felink; + + /* Reference to foreign -- set in the secondary. */ + DB *s_foreign; + + /* API-private structure: used by DB 1.85, C++, Java, Perl and Tcl */ + void *api_internal; + + /* Subsystem-private structure. */ + void *bt_internal; /* Btree/Recno access method. */ + void *h_internal; /* Hash access method. */ + void *heap_internal; /* Heap access method. */ + void *p_internal; /* Partition informaiton. */ + void *q_internal; /* Queue access method. */ + + /* DB PUBLIC HANDLE LIST BEGIN */ + int (*associate) __P((DB *, DB_TXN *, DB *, + int (*)(DB *, const DBT *, const DBT *, DBT *), u_int32_t)); + int (*associate_foreign) __P((DB *, DB *, + int (*)(DB *, const DBT *, DBT *, const DBT *, int *), + u_int32_t)); + int (*close) __P((DB *, u_int32_t)); + int (*compact) __P((DB *, + DB_TXN *, DBT *, DBT *, DB_COMPACT *, u_int32_t, DBT *)); + int (*cursor) __P((DB *, DB_TXN *, DBC **, u_int32_t)); + int (*del) __P((DB *, DB_TXN *, DBT *, u_int32_t)); + void (*err) __P((DB *, int, const char *, ...)); + void (*errx) __P((DB *, const char *, ...)); + int (*exists) __P((DB *, DB_TXN *, DBT *, u_int32_t)); + int (*fd) __P((DB *, int *)); + int (*get) __P((DB *, DB_TXN *, DBT *, DBT *, u_int32_t)); + int (*get_alloc) __P((DB *, void *(**)(size_t), + void *(**)(void *, size_t), void (**)(void *))); + int (*get_append_recno) __P((DB *, int (**)(DB *, DBT *, db_recno_t))); + int (*get_assoc_flags) __P((DB *, u_int32_t *)); + int (*get_bt_compare) + __P((DB *, int (**)(DB *, const DBT *, const DBT *))); + int (*get_bt_compress) __P((DB *, + int (**)(DB *, + const DBT *, const DBT *, const DBT *, const DBT *, DBT *), + int (**)(DB *, const DBT *, const DBT *, DBT *, DBT *, DBT *))); + int (*get_bt_minkey) __P((DB *, u_int32_t *)); + int (*get_bt_prefix) + __P((DB *, size_t (**)(DB *, const DBT *, const DBT *))); + int (*get_byteswapped) __P((DB *, int *)); + int (*get_cachesize) __P((DB *, u_int32_t *, u_int32_t *, int *)); + int (*get_create_dir) __P((DB *, const char **)); + int (*get_dbname) __P((DB *, const char **, const char **)); + int (*get_dup_compare) + __P((DB *, int (**)(DB *, const DBT *, const DBT *))); + int (*get_encrypt_flags) __P((DB *, u_int32_t *)); + DB_ENV *(*get_env) __P((DB *)); + void (*get_errcall) __P((DB *, + void (**)(const DB_ENV *, const char *, const char *))); + void (*get_errfile) __P((DB *, FILE **)); + void (*get_errpfx) __P((DB *, const char **)); + int (*get_feedback) __P((DB *, void (**)(DB *, int, int))); + int (*get_flags) __P((DB *, u_int32_t *)); + int (*get_h_compare) + __P((DB *, int (**)(DB *, const DBT *, const DBT *))); + int (*get_h_ffactor) __P((DB *, u_int32_t *)); + int (*get_h_hash) + __P((DB *, u_int32_t (**)(DB *, const void *, u_int32_t))); + int (*get_h_nelem) __P((DB *, u_int32_t *)); + int (*get_heapsize) __P((DB *, u_int32_t *, u_int32_t *)); + int (*get_heap_regionsize) __P((DB *, u_int32_t *)); + int (*get_lk_exclusive) __P((DB *, int *, int *)); + int (*get_lorder) __P((DB *, int *)); + DB_MPOOLFILE *(*get_mpf) __P((DB *)); + void (*get_msgcall) __P((DB *, + void (**)(const DB_ENV *, const char *))); + void (*get_msgfile) __P((DB *, FILE **)); + int (*get_multiple) __P((DB *)); + int (*get_open_flags) __P((DB *, u_int32_t *)); + int (*get_pagesize) __P((DB *, u_int32_t *)); + int (*get_partition_callback) __P((DB *, + u_int32_t *, u_int32_t (**)(DB *, DBT *key))); + int (*get_partition_dirs) __P((DB *, const char ***)); + int (*get_partition_keys) __P((DB *, u_int32_t *, DBT **)); + int (*get_priority) __P((DB *, DB_CACHE_PRIORITY *)); + int (*get_q_extentsize) __P((DB *, u_int32_t *)); + int (*get_re_delim) __P((DB *, int *)); + int (*get_re_len) __P((DB *, u_int32_t *)); + int (*get_re_pad) __P((DB *, int *)); + int (*get_re_source) __P((DB *, const char **)); + int (*get_transactional) __P((DB *)); + int (*get_type) __P((DB *, DBTYPE *)); + int (*join) __P((DB *, DBC **, DBC **, u_int32_t)); + int (*key_range) + __P((DB *, DB_TXN *, DBT *, DB_KEY_RANGE *, u_int32_t)); + int (*open) __P((DB *, + DB_TXN *, const char *, const char *, DBTYPE, u_int32_t, int)); + int (*pget) __P((DB *, DB_TXN *, DBT *, DBT *, DBT *, u_int32_t)); + int (*put) __P((DB *, DB_TXN *, DBT *, DBT *, u_int32_t)); + int (*remove) __P((DB *, const char *, const char *, u_int32_t)); + int (*rename) __P((DB *, + const char *, const char *, const char *, u_int32_t)); + int (*set_alloc) __P((DB *, void *(*)(size_t), + void *(*)(void *, size_t), void (*)(void *))); + int (*set_append_recno) __P((DB *, int (*)(DB *, DBT *, db_recno_t))); + int (*set_bt_compare) + __P((DB *, int (*)(DB *, const DBT *, const DBT *))); + int (*set_bt_compress) __P((DB *, + int (*)(DB *, const DBT *, const DBT *, const DBT *, const DBT *, DBT *), + int (*)(DB *, const DBT *, const DBT *, DBT *, DBT *, DBT *))); + int (*set_bt_minkey) __P((DB *, u_int32_t)); + int (*set_bt_prefix) + __P((DB *, size_t (*)(DB *, const DBT *, const DBT *))); + int (*set_cachesize) __P((DB *, u_int32_t, u_int32_t, int)); + int (*set_create_dir) __P((DB *, const char *)); + int (*set_dup_compare) + __P((DB *, int (*)(DB *, const DBT *, const DBT *))); + int (*set_encrypt) __P((DB *, const char *, u_int32_t)); + void (*set_errcall) __P((DB *, + void (*)(const DB_ENV *, const char *, const char *))); + void (*set_errfile) __P((DB *, FILE *)); + void (*set_errpfx) __P((DB *, const char *)); + int (*set_feedback) __P((DB *, void (*)(DB *, int, int))); + int (*set_flags) __P((DB *, u_int32_t)); + int (*set_h_compare) + __P((DB *, int (*)(DB *, const DBT *, const DBT *))); + int (*set_h_ffactor) __P((DB *, u_int32_t)); + int (*set_h_hash) + __P((DB *, u_int32_t (*)(DB *, const void *, u_int32_t))); + int (*set_h_nelem) __P((DB *, u_int32_t)); + int (*set_heapsize) __P((DB *, u_int32_t, u_int32_t, u_int32_t)); + int (*set_heap_regionsize) __P((DB *, u_int32_t)); + int (*set_lk_exclusive) __P((DB *, int)); + int (*set_lorder) __P((DB *, int)); + void (*set_msgcall) __P((DB *, void (*)(const DB_ENV *, const char *))); + void (*set_msgfile) __P((DB *, FILE *)); + int (*set_pagesize) __P((DB *, u_int32_t)); + int (*set_paniccall) __P((DB *, void (*)(DB_ENV *, int))); + int (*set_partition) __P((DB *, + u_int32_t, DBT *, u_int32_t (*)(DB *, DBT *key))); + int (*set_partition_dirs) __P((DB *, const char **)); + int (*set_priority) __P((DB *, DB_CACHE_PRIORITY)); + int (*set_q_extentsize) __P((DB *, u_int32_t)); + int (*set_re_delim) __P((DB *, int)); + int (*set_re_len) __P((DB *, u_int32_t)); + int (*set_re_pad) __P((DB *, int)); + int (*set_re_source) __P((DB *, const char *)); + int (*sort_multiple) __P((DB *, DBT *, DBT *, u_int32_t)); + int (*stat) __P((DB *, DB_TXN *, void *, u_int32_t)); + int (*stat_print) __P((DB *, u_int32_t)); + int (*sync) __P((DB *, u_int32_t)); + int (*truncate) __P((DB *, DB_TXN *, u_int32_t *, u_int32_t)); + int (*upgrade) __P((DB *, const char *, u_int32_t)); + int (*verify) + __P((DB *, const char *, const char *, FILE *, u_int32_t)); + /* DB PUBLIC HANDLE LIST END */ + + /* DB PRIVATE HANDLE LIST BEGIN */ + int (*dump) __P((DB *, const char *, + int (*)(void *, const void *), void *, int, int)); + int (*db_am_remove) __P((DB *, DB_THREAD_INFO *, + DB_TXN *, const char *, const char *, u_int32_t)); + int (*db_am_rename) __P((DB *, DB_THREAD_INFO *, + DB_TXN *, const char *, const char *, const char *)); + /* DB PRIVATE HANDLE LIST END */ + + /* + * Never called; these are a place to save function pointers + * so that we can undo an associate. + */ + int (*stored_get) __P((DB *, DB_TXN *, DBT *, DBT *, u_int32_t)); + int (*stored_close) __P((DB *, u_int32_t)); + + /* Alternative handle close function, used by C++ API. */ + int (*alt_close) __P((DB *, u_int32_t)); + +#define DB_OK_BTREE 0x01 +#define DB_OK_HASH 0x02 +#define DB_OK_HEAP 0x04 +#define DB_OK_QUEUE 0x08 +#define DB_OK_RECNO 0x10 + u_int32_t am_ok; /* Legal AM choices. */ + + /* + * This field really ought to be an AM_FLAG, but we have + * have run out of bits. If/when we decide to split up + * the flags, we can incorporate it. + */ + int preserve_fid; /* Do not free fileid on close. */ + +#define DB_AM_CHKSUM 0x00000001 /* Checksumming */ +#define DB_AM_COMPENSATE 0x00000002 /* Created by compensating txn */ +#define DB_AM_COMPRESS 0x00000004 /* Compressed BTree */ +#define DB_AM_CREATED 0x00000008 /* Database was created upon open */ +#define DB_AM_CREATED_MSTR 0x00000010 /* Encompassing file was created */ +#define DB_AM_DBM_ERROR 0x00000020 /* Error in DBM/NDBM database */ +#define DB_AM_DELIMITER 0x00000040 /* Variable length delimiter set */ +#define DB_AM_DISCARD 0x00000080 /* Discard any cached pages */ +#define DB_AM_DUP 0x00000100 /* DB_DUP */ +#define DB_AM_DUPSORT 0x00000200 /* DB_DUPSORT */ +#define DB_AM_ENCRYPT 0x00000400 /* Encryption */ +#define DB_AM_FIXEDLEN 0x00000800 /* Fixed-length records */ +#define DB_AM_INMEM 0x00001000 /* In-memory; no sync on close */ +#define DB_AM_INORDER 0x00002000 /* DB_INORDER */ +#define DB_AM_IN_RENAME 0x00004000 /* File is being renamed */ +#define DB_AM_NOT_DURABLE 0x00008000 /* Do not log changes */ +#define DB_AM_OPEN_CALLED 0x00010000 /* DB->open called */ +#define DB_AM_PAD 0x00020000 /* Fixed-length record pad */ +#define DB_AM_PARTDB 0x00040000 /* Handle for a database partition */ +#define DB_AM_PGDEF 0x00080000 /* Page size was defaulted */ +#define DB_AM_RDONLY 0x00100000 /* Database is readonly */ +#define DB_AM_READ_UNCOMMITTED 0x00200000 /* Support degree 1 isolation */ +#define DB_AM_RECNUM 0x00400000 /* DB_RECNUM */ +#define DB_AM_RECOVER 0x00800000 /* DB opened by recovery routine */ +#define DB_AM_RENUMBER 0x01000000 /* DB_RENUMBER */ +#define DB_AM_REVSPLITOFF 0x02000000 /* DB_REVSPLITOFF */ +#define DB_AM_SECONDARY 0x04000000 /* Database is a secondary index */ +#define DB_AM_SNAPSHOT 0x08000000 /* DB_SNAPSHOT */ +#define DB_AM_SUBDB 0x10000000 /* Subdatabases supported */ +#define DB_AM_SWAP 0x20000000 /* Pages need to be byte-swapped */ +#define DB_AM_TXN 0x40000000 /* Opened in a transaction */ +#define DB_AM_VERIFYING 0x80000000 /* DB handle is in the verifier */ + u_int32_t orig_flags; /* Flags at open, for refresh */ + u_int32_t flags; + +#define DB2_AM_EXCL 0x00000001 /* Exclusively lock the handle */ +#define DB2_AM_INTEXCL 0x00000002 /* Internal exclusive lock. */ +#define DB2_AM_NOWAIT 0x00000004 /* Do not wait for handle lock */ + u_int32_t orig_flags2; /* Second flags word; for refresh */ + u_int32_t flags2; /* Second flags word */ +}; + +/* + * Macros for bulk operations. These are only intended for the C API. + * For C++, use DbMultiple*Iterator or DbMultiple*Builder. + * + * Bulk operations store multiple entries into a single DBT structure. The + * following macros assist with creating and reading these Multiple DBTs. + * + * The basic layout for single data items is: + * + * ------------------------------------------------------------------------- + * | data1 | ... | dataN | ..... |-1 | dNLen | dNOff | ... | d1Len | d1Off | + * ------------------------------------------------------------------------- + * + * For the DB_MULTIPLE_KEY* macros, the items are in key/data pairs, so data1 + * would be a key, and data2 its corresponding value (N is always even). + * + * For the DB_MULTIPLE_RECNO* macros, the record number is stored along with + * the len/off pair in the "header" section, and the list is zero terminated + * (since -1 is a valid record number): + * + * -------------------------------------------------------------------------- + * | d1 |..| dN |..| 0 | dNLen | dNOff | recnoN |..| d1Len | d1Off | recno1 | + * -------------------------------------------------------------------------- + */ +#define DB_MULTIPLE_INIT(pointer, dbt) \ + (pointer = (u_int8_t *)(dbt)->data + \ + (dbt)->ulen - sizeof(u_int32_t)) + +#define DB_MULTIPLE_NEXT(pointer, dbt, retdata, retdlen) \ + do { \ + u_int32_t *__p = (u_int32_t *)(pointer); \ + if (*__p == (u_int32_t)-1) { \ + retdata = NULL; \ + pointer = NULL; \ + break; \ + } \ + retdata = (u_int8_t *)(dbt)->data + *__p--; \ + retdlen = *__p--; \ + pointer = __p; \ + if (retdlen == 0 && retdata == (u_int8_t *)(dbt)->data) \ + retdata = NULL; \ + } while (0) + +#define DB_MULTIPLE_KEY_NEXT(pointer, dbt, retkey, retklen, retdata, retdlen) \ + do { \ + u_int32_t *__p = (u_int32_t *)(pointer); \ + if (*__p == (u_int32_t)-1) { \ + retdata = NULL; \ + retkey = NULL; \ + pointer = NULL; \ + break; \ + } \ + retkey = (u_int8_t *)(dbt)->data + *__p--; \ + retklen = *__p--; \ + retdata = (u_int8_t *)(dbt)->data + *__p--; \ + retdlen = *__p--; \ + pointer = __p; \ + } while (0) + +#define DB_MULTIPLE_RECNO_NEXT(pointer, dbt, recno, retdata, retdlen) \ + do { \ + u_int32_t *__p = (u_int32_t *)(pointer); \ + if (*__p == (u_int32_t)0) { \ + recno = 0; \ + retdata = NULL; \ + pointer = NULL; \ + break; \ + } \ + recno = *__p--; \ + retdata = (u_int8_t *)(dbt)->data + *__p--; \ + retdlen = *__p--; \ + pointer = __p; \ + } while (0) + +#define DB_MULTIPLE_WRITE_INIT(pointer, dbt) \ + do { \ + (dbt)->flags |= DB_DBT_BULK; \ + pointer = (u_int8_t *)(dbt)->data + \ + (dbt)->ulen - sizeof(u_int32_t); \ + *(u_int32_t *)(pointer) = (u_int32_t)-1; \ + } while (0) + +#define DB_MULTIPLE_RESERVE_NEXT(pointer, dbt, writedata, writedlen) \ + do { \ + u_int32_t *__p = (u_int32_t *)(pointer); \ + u_int32_t __off = ((pointer) == (u_int8_t *)(dbt)->data +\ + (dbt)->ulen - sizeof(u_int32_t)) ? 0 : __p[1] + __p[2];\ + if ((u_int8_t *)(dbt)->data + __off + (writedlen) > \ + (u_int8_t *)(__p - 2)) \ + writedata = NULL; \ + else { \ + writedata = (u_int8_t *)(dbt)->data + __off; \ + __p[0] = __off; \ + __p[-1] = (u_int32_t)(writedlen); \ + __p[-2] = (u_int32_t)-1; \ + pointer = __p - 2; \ + } \ + } while (0) + +#define DB_MULTIPLE_WRITE_NEXT(pointer, dbt, writedata, writedlen) \ + do { \ + void *__destd; \ + DB_MULTIPLE_RESERVE_NEXT((pointer), (dbt), \ + __destd, (writedlen)); \ + if (__destd == NULL) \ + pointer = NULL; \ + else \ + memcpy(__destd, (writedata), (writedlen)); \ + } while (0) + +#define DB_MULTIPLE_KEY_RESERVE_NEXT(pointer, dbt, writekey, writeklen, writedata, writedlen) \ + do { \ + u_int32_t *__p = (u_int32_t *)(pointer); \ + u_int32_t __off = ((pointer) == (u_int8_t *)(dbt)->data +\ + (dbt)->ulen - sizeof(u_int32_t)) ? 0 : __p[1] + __p[2];\ + if ((u_int8_t *)(dbt)->data + __off + (writeklen) + \ + (writedlen) > (u_int8_t *)(__p - 4)) { \ + writekey = NULL; \ + writedata = NULL; \ + } else { \ + writekey = (u_int8_t *)(dbt)->data + __off; \ + __p[0] = __off; \ + __p[-1] = (u_int32_t)(writeklen); \ + __p -= 2; \ + __off += (u_int32_t)(writeklen); \ + writedata = (u_int8_t *)(dbt)->data + __off; \ + __p[0] = __off; \ + __p[-1] = (u_int32_t)(writedlen); \ + __p[-2] = (u_int32_t)-1; \ + pointer = __p - 2; \ + } \ + } while (0) + +#define DB_MULTIPLE_KEY_WRITE_NEXT(pointer, dbt, writekey, writeklen, writedata, writedlen) \ + do { \ + void *__destk, *__destd; \ + DB_MULTIPLE_KEY_RESERVE_NEXT((pointer), (dbt), \ + __destk, (writeklen), __destd, (writedlen)); \ + if (__destk == NULL) \ + pointer = NULL; \ + else { \ + memcpy(__destk, (writekey), (writeklen)); \ + if (__destd != NULL) \ + memcpy(__destd, (writedata), (writedlen));\ + } \ + } while (0) + +#define DB_MULTIPLE_RECNO_WRITE_INIT(pointer, dbt) \ + do { \ + (dbt)->flags |= DB_DBT_BULK; \ + pointer = (u_int8_t *)(dbt)->data + \ + (dbt)->ulen - sizeof(u_int32_t); \ + *(u_int32_t *)(pointer) = 0; \ + } while (0) + +#define DB_MULTIPLE_RECNO_RESERVE_NEXT(pointer, dbt, recno, writedata, writedlen) \ + do { \ + u_int32_t *__p = (u_int32_t *)(pointer); \ + u_int32_t __off = ((pointer) == (u_int8_t *)(dbt)->data +\ + (dbt)->ulen - sizeof(u_int32_t)) ? 0 : __p[1] + __p[2]; \ + if (((u_int8_t *)(dbt)->data + __off) + (writedlen) > \ + (u_int8_t *)(__p - 3)) \ + writedata = NULL; \ + else { \ + writedata = (u_int8_t *)(dbt)->data + __off; \ + __p[0] = (u_int32_t)(recno); \ + __p[-1] = __off; \ + __p[-2] = (u_int32_t)(writedlen); \ + __p[-3] = 0; \ + pointer = __p - 3; \ + } \ + } while (0) + +#define DB_MULTIPLE_RECNO_WRITE_NEXT(pointer, dbt, recno, writedata, writedlen)\ + do { \ + void *__destd; \ + DB_MULTIPLE_RECNO_RESERVE_NEXT((pointer), (dbt), \ + (recno), __destd, (writedlen)); \ + if (__destd == NULL) \ + pointer = NULL; \ + else if ((writedlen) != 0) \ + memcpy(__destd, (writedata), (writedlen)); \ + } while (0) + +struct __db_heap_rid { + db_pgno_t pgno; /* Page number. */ + db_indx_t indx; /* Index in the offset table. */ +}; +#define DB_HEAP_RID_SZ (sizeof(db_pgno_t) + sizeof(db_indx_t)) + +/******************************************************* + * Access method cursors. + *******************************************************/ +struct __dbc { + DB *dbp; /* Backing database */ + DB_ENV *dbenv; /* Backing environment */ + ENV *env; /* Backing environment */ + + DB_THREAD_INFO *thread_info; /* Thread that owns this cursor. */ + DB_TXN *txn; /* Associated transaction. */ + DB_CACHE_PRIORITY priority; /* Priority in cache. */ + + /* + * Active/free cursor queues. + * + * !!! + * Explicit representations of structures from queue.h. + * TAILQ_ENTRY(__dbc) links; + */ + struct { + DBC *tqe_next; + DBC **tqe_prev; + } links; + + /* + * Cursor queue of the owning transaction. + * + * !!! + * Explicit representations of structures from queue.h. + * TAILQ_ENTRY(__dbc) txn_cursors; + */ + struct { + DBC *tqe_next; /* next element */ + DBC **tqe_prev; /* address of previous next element */ + } txn_cursors; + + /* + * The DBT *'s below are used by the cursor routines to return + * data to the user when DBT flags indicate that DB should manage + * the returned memory. They point at a DBT containing the buffer + * and length that will be used, and "belonging" to the handle that + * should "own" this memory. This may be a "my_*" field of this + * cursor--the default--or it may be the corresponding field of + * another cursor, a DB handle, a join cursor, etc. In general, it + * will be whatever handle the user originally used for the current + * DB interface call. + */ + DBT *rskey; /* Returned secondary key. */ + DBT *rkey; /* Returned [primary] key. */ + DBT *rdata; /* Returned data. */ + + DBT my_rskey; /* Space for returned secondary key. */ + DBT my_rkey; /* Space for returned [primary] key. */ + DBT my_rdata; /* Space for returned data. */ + + DB_LOCKER *lref; /* Reference to default locker. */ + DB_LOCKER *locker; /* Locker for this operation. */ + DBT lock_dbt; /* DBT referencing lock. */ + DB_LOCK_ILOCK lock; /* Object to be locked. */ + DB_LOCK mylock; /* CDB lock held on this cursor. */ + + DBTYPE dbtype; /* Cursor type. */ + + DBC_INTERNAL *internal; /* Access method private. */ + + /* DBC PUBLIC HANDLE LIST BEGIN */ + int (*close) __P((DBC *)); + int (*cmp) __P((DBC *, DBC *, int *, u_int32_t)); + int (*count) __P((DBC *, db_recno_t *, u_int32_t)); + int (*del) __P((DBC *, u_int32_t)); + int (*dup) __P((DBC *, DBC **, u_int32_t)); + int (*get) __P((DBC *, DBT *, DBT *, u_int32_t)); + int (*get_priority) __P((DBC *, DB_CACHE_PRIORITY *)); + int (*pget) __P((DBC *, DBT *, DBT *, DBT *, u_int32_t)); + int (*put) __P((DBC *, DBT *, DBT *, u_int32_t)); + int (*set_priority) __P((DBC *, DB_CACHE_PRIORITY)); + /* DBC PUBLIC HANDLE LIST END */ + + /* The following are the method names deprecated in the 4.6 release. */ + int (*c_close) __P((DBC *)); + int (*c_count) __P((DBC *, db_recno_t *, u_int32_t)); + int (*c_del) __P((DBC *, u_int32_t)); + int (*c_dup) __P((DBC *, DBC **, u_int32_t)); + int (*c_get) __P((DBC *, DBT *, DBT *, u_int32_t)); + int (*c_pget) __P((DBC *, DBT *, DBT *, DBT *, u_int32_t)); + int (*c_put) __P((DBC *, DBT *, DBT *, u_int32_t)); + + /* DBC PRIVATE HANDLE LIST BEGIN */ + int (*am_bulk) __P((DBC *, DBT *, u_int32_t)); + int (*am_close) __P((DBC *, db_pgno_t, int *)); + int (*am_del) __P((DBC *, u_int32_t)); + int (*am_destroy) __P((DBC *)); + int (*am_get) __P((DBC *, DBT *, DBT *, u_int32_t, db_pgno_t *)); + int (*am_put) __P((DBC *, DBT *, DBT *, u_int32_t, db_pgno_t *)); + int (*am_writelock) __P((DBC *)); + /* DBC PRIVATE HANDLE LIST END */ + +/* + * DBC_DONTLOCK and DBC_RECOVER are used during recovery and transaction + * abort. If a transaction is being aborted or recovered then DBC_RECOVER + * will be set and locking and logging will be disabled on this cursor. If + * we are performing a compensating transaction (e.g. free page processing) + * then DB_DONTLOCK will be set to inhibit locking, but logging will still + * be required. DB_DONTLOCK is also used if the whole database is locked. + */ +#define DBC_ACTIVE 0x00001 /* Cursor in use. */ +#define DBC_BULK 0x00002 /* Bulk update cursor. */ +#define DBC_DONTLOCK 0x00004 /* Don't lock on this cursor. */ +#define DBC_DOWNREV 0x00008 /* Down rev replication master. */ +#define DBC_DUPLICATE 0x00010 /* Create a duplicate cursor. */ +#define DBC_ERROR 0x00020 /* Error in this request. */ +#define DBC_FAMILY 0x00040 /* Part of a locker family. */ +#define DBC_FROM_DB_GET 0x00080 /* Called from the DB->get() method. */ +#define DBC_MULTIPLE 0x00100 /* Return Multiple data. */ +#define DBC_MULTIPLE_KEY 0x00200 /* Return Multiple keys and data. */ +#define DBC_OPD 0x00400 /* Cursor references off-page dups. */ +#define DBC_OWN_LID 0x00800 /* Free lock id on destroy. */ +#define DBC_PARTITIONED 0x01000 /* Cursor for a partitioned db. */ +#define DBC_READ_COMMITTED 0x02000 /* Cursor has degree 2 isolation. */ +#define DBC_READ_UNCOMMITTED 0x04000 /* Cursor has degree 1 isolation. */ +#define DBC_RECOVER 0x08000 /* Recovery cursor; don't log/lock. */ +#define DBC_RMW 0x10000 /* Acquire write flag in read op. */ +#define DBC_TRANSIENT 0x20000 /* Cursor is transient. */ +#define DBC_WAS_READ_COMMITTED 0x40000 /* Cursor holds a read commited lock. */ +#define DBC_WRITECURSOR 0x80000 /* Cursor may be used to write (CDB). */ +#define DBC_WRITER 0x100000 /* Cursor immediately writing (CDB). */ + u_int32_t flags; +}; + +/* Key range statistics structure */ +struct __key_range { + double less; + double equal; + double greater; +}; + +/* Btree/Recno statistics structure. */ +struct __db_bt_stat { /* SHARED */ + u_int32_t bt_magic; /* Magic number. */ + u_int32_t bt_version; /* Version number. */ + u_int32_t bt_metaflags; /* Metadata flags. */ + u_int32_t bt_nkeys; /* Number of unique keys. */ + u_int32_t bt_ndata; /* Number of data items. */ + u_int32_t bt_pagecnt; /* Page count. */ + u_int32_t bt_pagesize; /* Page size. */ + u_int32_t bt_minkey; /* Minkey value. */ + u_int32_t bt_re_len; /* Fixed-length record length. */ + u_int32_t bt_re_pad; /* Fixed-length record pad. */ + u_int32_t bt_levels; /* Tree levels. */ + u_int32_t bt_int_pg; /* Internal pages. */ + u_int32_t bt_leaf_pg; /* Leaf pages. */ + u_int32_t bt_dup_pg; /* Duplicate pages. */ + u_int32_t bt_over_pg; /* Overflow pages. */ + u_int32_t bt_empty_pg; /* Empty pages. */ + u_int32_t bt_free; /* Pages on the free list. */ + uintmax_t bt_int_pgfree; /* Bytes free in internal pages. */ + uintmax_t bt_leaf_pgfree; /* Bytes free in leaf pages. */ + uintmax_t bt_dup_pgfree; /* Bytes free in duplicate pages. */ + uintmax_t bt_over_pgfree; /* Bytes free in overflow pages. */ +}; + +struct __db_compact { + /* Input Parameters. */ + u_int32_t compact_fillpercent; /* Desired fillfactor: 1-100 */ + db_timeout_t compact_timeout; /* Lock timeout. */ + u_int32_t compact_pages; /* Max pages to process. */ + /* Output Stats. */ + u_int32_t compact_empty_buckets; /* Empty hash buckets found. */ + u_int32_t compact_pages_free; /* Number of pages freed. */ + u_int32_t compact_pages_examine; /* Number of pages examine. */ + u_int32_t compact_levels; /* Number of levels removed. */ + u_int32_t compact_deadlock; /* Number of deadlocks. */ + db_pgno_t compact_pages_truncated; /* Pages truncated to OS. */ + /* Internal. */ + db_pgno_t compact_truncate; /* Page number for truncation */ +}; + +/* Hash statistics structure. */ +struct __db_h_stat { /* SHARED */ + u_int32_t hash_magic; /* Magic number. */ + u_int32_t hash_version; /* Version number. */ + u_int32_t hash_metaflags; /* Metadata flags. */ + u_int32_t hash_nkeys; /* Number of unique keys. */ + u_int32_t hash_ndata; /* Number of data items. */ + u_int32_t hash_pagecnt; /* Page count. */ + u_int32_t hash_pagesize; /* Page size. */ + u_int32_t hash_ffactor; /* Fill factor specified at create. */ + u_int32_t hash_buckets; /* Number of hash buckets. */ + u_int32_t hash_free; /* Pages on the free list. */ + uintmax_t hash_bfree; /* Bytes free on bucket pages. */ + u_int32_t hash_bigpages; /* Number of big key/data pages. */ + uintmax_t hash_big_bfree; /* Bytes free on big item pages. */ + u_int32_t hash_overflows; /* Number of overflow pages. */ + uintmax_t hash_ovfl_free; /* Bytes free on ovfl pages. */ + u_int32_t hash_dup; /* Number of dup pages. */ + uintmax_t hash_dup_free; /* Bytes free on duplicate pages. */ +}; + +/* Heap statistics structure. */ +struct __db_heap_stat { /* SHARED */ + u_int32_t heap_magic; /* Magic number. */ + u_int32_t heap_version; /* Version number. */ + u_int32_t heap_metaflags; /* Metadata flags. */ + u_int32_t heap_nrecs; /* Number of records. */ + u_int32_t heap_pagecnt; /* Page count. */ + u_int32_t heap_pagesize; /* Page size. */ + u_int32_t heap_nregions; /* Number of regions. */ + u_int32_t heap_regionsize; /* Number of pages in a region. */ +}; + +/* Queue statistics structure. */ +struct __db_qam_stat { /* SHARED */ + u_int32_t qs_magic; /* Magic number. */ + u_int32_t qs_version; /* Version number. */ + u_int32_t qs_metaflags; /* Metadata flags. */ + u_int32_t qs_nkeys; /* Number of unique keys. */ + u_int32_t qs_ndata; /* Number of data items. */ + u_int32_t qs_pagesize; /* Page size. */ + u_int32_t qs_extentsize; /* Pages per extent. */ + u_int32_t qs_pages; /* Data pages. */ + u_int32_t qs_re_len; /* Fixed-length record length. */ + u_int32_t qs_re_pad; /* Fixed-length record pad. */ + u_int32_t qs_pgfree; /* Bytes free in data pages. */ + u_int32_t qs_first_recno; /* First not deleted record. */ + u_int32_t qs_cur_recno; /* Next available record number. */ +}; + +/******************************************************* + * Environment. + *******************************************************/ +#define DB_REGION_MAGIC 0x120897 /* Environment magic number. */ + +/* + * Database environment structure. + * + * This is the public database environment handle. The private environment + * handle is the ENV structure. The user owns this structure, the library + * owns the ENV structure. The reason there are two structures is because + * the user's configuration outlives any particular DB_ENV->open call, and + * separate structures allows us to easily discard internal information without + * discarding the user's configuration. + * + * Fields in the DB_ENV structure should normally be set only by application + * DB_ENV handle methods. + */ + +/* + * Memory configuration types. + */ +typedef enum { + DB_MEM_LOCK=1, + DB_MEM_LOCKOBJECT=2, + DB_MEM_LOCKER=3, + DB_MEM_LOGID=4, + DB_MEM_TRANSACTION=5, + DB_MEM_THREAD=6 +} DB_MEM_CONFIG; + +/* + * Backup configuration types. + */ +typedef enum { + DB_BACKUP_READ_COUNT = 1, + DB_BACKUP_READ_SLEEP = 2, + DB_BACKUP_SIZE = 3, + DB_BACKUP_WRITE_DIRECT = 4 +} DB_BACKUP_CONFIG; + +struct __db_env { + ENV *env; /* Linked ENV structure */ + + /* + * The DB_ENV structure can be used concurrently, so field access is + * protected. + */ + db_mutex_t mtx_db_env; /* DB_ENV structure mutex */ + + /* Error message callback */ + void (*db_errcall) __P((const DB_ENV *, const char *, const char *)); + FILE *db_errfile; /* Error message file stream */ + const char *db_errpfx; /* Error message prefix */ + + /* Other message callback */ + void (*db_msgcall) __P((const DB_ENV *, const char *)); + FILE *db_msgfile; /* Other message file stream */ + + /* Other application callback functions */ + int (*app_dispatch) __P((DB_ENV *, DBT *, DB_LSN *, db_recops)); + void (*db_event_func) __P((DB_ENV *, u_int32_t, void *)); + void (*db_feedback) __P((DB_ENV *, int, int)); + void (*db_free) __P((void *)); + void (*db_paniccall) __P((DB_ENV *, int)); + void *(*db_malloc) __P((size_t)); + void *(*db_realloc) __P((void *, size_t)); + int (*is_alive) __P((DB_ENV *, pid_t, db_threadid_t, u_int32_t)); + void (*thread_id) __P((DB_ENV *, pid_t *, db_threadid_t *)); + char *(*thread_id_string) __P((DB_ENV *, pid_t, db_threadid_t, char *)); + + /* Application specified paths */ + char *db_log_dir; /* Database log file directory */ + char *db_md_dir; /* Persistent metadata directory */ + char *db_tmp_dir; /* Database tmp file directory */ + + char *db_create_dir; /* Create directory for data files */ + char **db_data_dir; /* Database data file directories */ + int data_cnt; /* Database data file slots */ + int data_next; /* Next database data file slot */ + + char *intermediate_dir_mode; /* Intermediate directory perms */ + + long shm_key; /* shmget key */ + + char *passwd; /* Cryptography support */ + size_t passwd_len; + + /* Private handle references */ + void *app_private; /* Application-private handle */ + void *api1_internal; /* C++, Perl API private */ + void *api2_internal; /* Java API private */ + + u_int32_t verbose; /* DB_VERB_XXX flags */ + + /* Mutex configuration */ + u_int32_t mutex_align; /* Mutex alignment */ + u_int32_t mutex_cnt; /* Number of mutexes to configure */ + u_int32_t mutex_inc; /* Number of mutexes to add */ + u_int32_t mutex_max; /* Max number of mutexes */ + u_int32_t mutex_tas_spins;/* Test-and-set spin count */ + + /* Locking configuration */ + u_int8_t *lk_conflicts; /* Two dimensional conflict matrix */ + int lk_modes; /* Number of lock modes in table */ + u_int32_t lk_detect; /* Deadlock detect on all conflicts */ + u_int32_t lk_max; /* Maximum number of locks */ + u_int32_t lk_max_lockers;/* Maximum number of lockers */ + u_int32_t lk_max_objects;/* Maximum number of locked objects */ + u_int32_t lk_init; /* Initial number of locks */ + u_int32_t lk_init_lockers;/* Initial number of lockers */ + u_int32_t lk_init_objects;/* Initial number of locked objects */ + u_int32_t lk_partitions ;/* Number of object partitions */ + db_timeout_t lk_timeout; /* Lock timeout period */ + /* Used during initialization */ + u_int32_t locker_t_size; /* Locker hash table size. */ + u_int32_t object_t_size; /* Object hash table size. */ + + /* Logging configuration */ + u_int32_t lg_bsize; /* Buffer size */ + u_int32_t lg_fileid_init; /* Initial allocation for fname structs */ + int lg_filemode; /* Log file permission mode */ + u_int32_t lg_regionmax; /* Region size */ + u_int32_t lg_size; /* Log file size */ + u_int32_t lg_flags; /* Log configuration */ + + /* Memory pool configuration */ + u_int32_t mp_gbytes; /* Cache size: GB */ + u_int32_t mp_bytes; /* Cache size: bytes */ + u_int32_t mp_max_gbytes; /* Maximum cache size: GB */ + u_int32_t mp_max_bytes; /* Maximum cache size: bytes */ + size_t mp_mmapsize; /* Maximum file size for mmap */ + int mp_maxopenfd; /* Maximum open file descriptors */ + int mp_maxwrite; /* Maximum buffers to write */ + u_int mp_ncache; /* Initial number of cache regions */ + u_int32_t mp_pagesize; /* Average page size */ + u_int32_t mp_tablesize; /* Approximate hash table size */ + u_int32_t mp_mtxcount; /* Number of mutexs */ + /* Sleep after writing max buffers */ + db_timeout_t mp_maxwrite_sleep; + + /* Transaction configuration */ + u_int32_t tx_init; /* Initial number of transactions */ + u_int32_t tx_max; /* Maximum number of transactions */ + time_t tx_timestamp; /* Recover to specific timestamp */ + db_timeout_t tx_timeout; /* Timeout for transactions */ + + /* Thread tracking configuration */ + u_int32_t thr_init; /* Thread count */ + u_int32_t thr_max; /* Thread max */ + roff_t memory_max; /* Maximum region memory */ + + /* + * The following fields are not strictly user-owned, but they outlive + * the ENV structure, and so are stored here. + */ + DB_FH *registry; /* DB_REGISTER file handle */ + u_int32_t registry_off; /* + * Offset of our slot. We can't use + * off_t because its size depends on + * build settings. + */ + db_timeout_t envreg_timeout; /* DB_REGISTER wait timeout */ + +#define DB_ENV_AUTO_COMMIT 0x00000001 /* DB_AUTO_COMMIT */ +#define DB_ENV_CDB_ALLDB 0x00000002 /* CDB environment wide locking */ +#define DB_ENV_FAILCHK 0x00000004 /* Failchk is running */ +#define DB_ENV_DIRECT_DB 0x00000008 /* DB_DIRECT_DB set */ +#define DB_ENV_DSYNC_DB 0x00000010 /* DB_DSYNC_DB set */ +#define DB_ENV_DATABASE_LOCKING 0x00000020 /* Try database-level locking */ +#define DB_ENV_MULTIVERSION 0x00000040 /* DB_MULTIVERSION set */ +#define DB_ENV_NOLOCKING 0x00000080 /* DB_NOLOCKING set */ +#define DB_ENV_NOMMAP 0x00000100 /* DB_NOMMAP set */ +#define DB_ENV_NOPANIC 0x00000200 /* Okay if panic set */ +#define DB_ENV_OVERWRITE 0x00000400 /* DB_OVERWRITE set */ +#define DB_ENV_REGION_INIT 0x00000800 /* DB_REGION_INIT set */ +#define DB_ENV_TIME_NOTGRANTED 0x00001000 /* DB_TIME_NOTGRANTED set */ +#define DB_ENV_TXN_NOSYNC 0x00002000 /* DB_TXN_NOSYNC set */ +#define DB_ENV_TXN_NOWAIT 0x00004000 /* DB_TXN_NOWAIT set */ +#define DB_ENV_TXN_SNAPSHOT 0x00008000 /* DB_TXN_SNAPSHOT set */ +#define DB_ENV_TXN_WRITE_NOSYNC 0x00010000 /* DB_TXN_WRITE_NOSYNC set */ +#define DB_ENV_YIELDCPU 0x00020000 /* DB_YIELDCPU set */ +#define DB_ENV_HOTBACKUP 0x00040000 /* DB_HOTBACKUP_IN_PROGRESS set */ +#define DB_ENV_NOFLUSH 0x00080000 /* DB_NOFLUSH set */ + u_int32_t flags; + + /* DB_ENV PUBLIC HANDLE LIST BEGIN */ + int (*add_data_dir) __P((DB_ENV *, const char *)); + int (*backup) __P((DB_ENV *, const char *, u_int32_t)); + int (*cdsgroup_begin) __P((DB_ENV *, DB_TXN **)); + int (*close) __P((DB_ENV *, u_int32_t)); + int (*dbbackup) __P((DB_ENV *, const char *, const char *, u_int32_t)); + int (*dbremove) __P((DB_ENV *, + DB_TXN *, const char *, const char *, u_int32_t)); + int (*dbrename) __P((DB_ENV *, + DB_TXN *, const char *, const char *, const char *, u_int32_t)); + void (*err) __P((const DB_ENV *, int, const char *, ...)); + void (*errx) __P((const DB_ENV *, const char *, ...)); + int (*failchk) __P((DB_ENV *, u_int32_t)); + int (*fileid_reset) __P((DB_ENV *, const char *, u_int32_t)); + int (*get_alloc) __P((DB_ENV *, void *(**)(size_t), + void *(**)(void *, size_t), void (**)(void *))); + int (*get_app_dispatch) + __P((DB_ENV *, int (**)(DB_ENV *, DBT *, DB_LSN *, db_recops))); + int (*get_cache_max) __P((DB_ENV *, u_int32_t *, u_int32_t *)); + int (*get_cachesize) __P((DB_ENV *, u_int32_t *, u_int32_t *, int *)); + int (*get_create_dir) __P((DB_ENV *, const char **)); + int (*get_data_dirs) __P((DB_ENV *, const char ***)); + int (*get_data_len) __P((DB_ENV *, u_int32_t *)); + int (*get_backup_callbacks) __P((DB_ENV *, + int (**)(DB_ENV *, const char *, const char *, void **), + int (**)(DB_ENV *, u_int32_t, u_int32_t, u_int32_t, u_int8_t *, void *), + int (**)(DB_ENV *, const char *, void *))); + int (*get_backup_config) __P((DB_ENV *, DB_BACKUP_CONFIG, u_int32_t *)); + int (*get_encrypt_flags) __P((DB_ENV *, u_int32_t *)); + void (*get_errcall) __P((DB_ENV *, + void (**)(const DB_ENV *, const char *, const char *))); + void (*get_errfile) __P((DB_ENV *, FILE **)); + void (*get_errpfx) __P((DB_ENV *, const char **)); + int (*get_flags) __P((DB_ENV *, u_int32_t *)); + int (*get_feedback) __P((DB_ENV *, void (**)(DB_ENV *, int, int))); + int (*get_home) __P((DB_ENV *, const char **)); + int (*get_intermediate_dir_mode) __P((DB_ENV *, const char **)); + int (*get_isalive) __P((DB_ENV *, + int (**)(DB_ENV *, pid_t, db_threadid_t, u_int32_t))); + int (*get_lg_bsize) __P((DB_ENV *, u_int32_t *)); + int (*get_lg_dir) __P((DB_ENV *, const char **)); + int (*get_lg_filemode) __P((DB_ENV *, int *)); + int (*get_lg_max) __P((DB_ENV *, u_int32_t *)); + int (*get_lg_regionmax) __P((DB_ENV *, u_int32_t *)); + int (*get_lk_conflicts) __P((DB_ENV *, const u_int8_t **, int *)); + int (*get_lk_detect) __P((DB_ENV *, u_int32_t *)); + int (*get_lk_max_lockers) __P((DB_ENV *, u_int32_t *)); + int (*get_lk_max_locks) __P((DB_ENV *, u_int32_t *)); + int (*get_lk_max_objects) __P((DB_ENV *, u_int32_t *)); + int (*get_lk_partitions) __P((DB_ENV *, u_int32_t *)); + int (*get_lk_priority) __P((DB_ENV *, u_int32_t, u_int32_t *)); + int (*get_lk_tablesize) __P((DB_ENV *, u_int32_t *)); + int (*get_memory_init) __P((DB_ENV *, DB_MEM_CONFIG, u_int32_t *)); + int (*get_memory_max) __P((DB_ENV *, u_int32_t *, u_int32_t *)); + int (*get_metadata_dir) __P((DB_ENV *, const char **)); + int (*get_mp_max_openfd) __P((DB_ENV *, int *)); + int (*get_mp_max_write) __P((DB_ENV *, int *, db_timeout_t *)); + int (*get_mp_mmapsize) __P((DB_ENV *, size_t *)); + int (*get_mp_mtxcount) __P((DB_ENV *, u_int32_t *)); + int (*get_mp_pagesize) __P((DB_ENV *, u_int32_t *)); + int (*get_mp_tablesize) __P((DB_ENV *, u_int32_t *)); + void (*get_msgcall) + __P((DB_ENV *, void (**)(const DB_ENV *, const char *))); + void (*get_msgfile) __P((DB_ENV *, FILE **)); + int (*get_open_flags) __P((DB_ENV *, u_int32_t *)); + int (*get_shm_key) __P((DB_ENV *, long *)); + int (*get_thread_count) __P((DB_ENV *, u_int32_t *)); + int (*get_thread_id_fn) + __P((DB_ENV *, void (**)(DB_ENV *, pid_t *, db_threadid_t *))); + int (*get_thread_id_string_fn) __P((DB_ENV *, + char *(**)(DB_ENV *, pid_t, db_threadid_t, char *))); + int (*get_timeout) __P((DB_ENV *, db_timeout_t *, u_int32_t)); + int (*get_tmp_dir) __P((DB_ENV *, const char **)); + int (*get_tx_max) __P((DB_ENV *, u_int32_t *)); + int (*get_tx_timestamp) __P((DB_ENV *, time_t *)); + int (*get_verbose) __P((DB_ENV *, u_int32_t, int *)); + int (*is_bigendian) __P((void)); + int (*lock_detect) __P((DB_ENV *, u_int32_t, u_int32_t, int *)); + int (*lock_get) __P((DB_ENV *, + u_int32_t, u_int32_t, DBT *, db_lockmode_t, DB_LOCK *)); + int (*lock_id) __P((DB_ENV *, u_int32_t *)); + int (*lock_id_free) __P((DB_ENV *, u_int32_t)); + int (*lock_put) __P((DB_ENV *, DB_LOCK *)); + int (*lock_stat) __P((DB_ENV *, DB_LOCK_STAT **, u_int32_t)); + int (*lock_stat_print) __P((DB_ENV *, u_int32_t)); + int (*lock_vec) __P((DB_ENV *, + u_int32_t, u_int32_t, DB_LOCKREQ *, int, DB_LOCKREQ **)); + int (*log_archive) __P((DB_ENV *, char **[], u_int32_t)); + int (*log_cursor) __P((DB_ENV *, DB_LOGC **, u_int32_t)); + int (*log_file) __P((DB_ENV *, const DB_LSN *, char *, size_t)); + int (*log_flush) __P((DB_ENV *, const DB_LSN *)); + int (*log_get_config) __P((DB_ENV *, u_int32_t, int *)); + int (*log_printf) __P((DB_ENV *, DB_TXN *, const char *, ...)); + int (*log_put) __P((DB_ENV *, DB_LSN *, const DBT *, u_int32_t)); + int (*log_put_record) __P((DB_ENV *, DB *, DB_TXN *, DB_LSN *, + u_int32_t, u_int32_t, u_int32_t, u_int32_t, + DB_LOG_RECSPEC *, ...)); + int (*log_read_record) __P((DB_ENV *, DB **, + void *, void *, DB_LOG_RECSPEC *, u_int32_t, void **)); + int (*log_set_config) __P((DB_ENV *, u_int32_t, int)); + int (*log_stat) __P((DB_ENV *, DB_LOG_STAT **, u_int32_t)); + int (*log_stat_print) __P((DB_ENV *, u_int32_t)); + int (*log_verify) __P((DB_ENV *, const DB_LOG_VERIFY_CONFIG *)); + int (*lsn_reset) __P((DB_ENV *, const char *, u_int32_t)); + int (*memp_fcreate) __P((DB_ENV *, DB_MPOOLFILE **, u_int32_t)); + int (*memp_register) __P((DB_ENV *, int, int (*)(DB_ENV *, db_pgno_t, + void *, DBT *), int (*)(DB_ENV *, db_pgno_t, void *, DBT *))); + int (*memp_stat) __P((DB_ENV *, + DB_MPOOL_STAT **, DB_MPOOL_FSTAT ***, u_int32_t)); + int (*memp_stat_print) __P((DB_ENV *, u_int32_t)); + int (*memp_sync) __P((DB_ENV *, DB_LSN *)); + int (*memp_trickle) __P((DB_ENV *, int, int *)); + int (*mutex_alloc) __P((DB_ENV *, u_int32_t, db_mutex_t *)); + int (*mutex_free) __P((DB_ENV *, db_mutex_t)); + int (*mutex_get_align) __P((DB_ENV *, u_int32_t *)); + int (*mutex_get_increment) __P((DB_ENV *, u_int32_t *)); + int (*mutex_get_init) __P((DB_ENV *, u_int32_t *)); + int (*mutex_get_max) __P((DB_ENV *, u_int32_t *)); + int (*mutex_get_tas_spins) __P((DB_ENV *, u_int32_t *)); + int (*mutex_lock) __P((DB_ENV *, db_mutex_t)); + int (*mutex_set_align) __P((DB_ENV *, u_int32_t)); + int (*mutex_set_increment) __P((DB_ENV *, u_int32_t)); + int (*mutex_set_init) __P((DB_ENV *, u_int32_t)); + int (*mutex_set_max) __P((DB_ENV *, u_int32_t)); + int (*mutex_set_tas_spins) __P((DB_ENV *, u_int32_t)); + int (*mutex_stat) __P((DB_ENV *, DB_MUTEX_STAT **, u_int32_t)); + int (*mutex_stat_print) __P((DB_ENV *, u_int32_t)); + int (*mutex_unlock) __P((DB_ENV *, db_mutex_t)); + int (*open) __P((DB_ENV *, const char *, u_int32_t, int)); + int (*remove) __P((DB_ENV *, const char *, u_int32_t)); + int (*rep_elect) __P((DB_ENV *, u_int32_t, u_int32_t, u_int32_t)); + int (*rep_flush) __P((DB_ENV *)); + int (*rep_get_clockskew) __P((DB_ENV *, u_int32_t *, u_int32_t *)); + int (*rep_get_config) __P((DB_ENV *, u_int32_t, int *)); + int (*rep_get_limit) __P((DB_ENV *, u_int32_t *, u_int32_t *)); + int (*rep_get_nsites) __P((DB_ENV *, u_int32_t *)); + int (*rep_get_priority) __P((DB_ENV *, u_int32_t *)); + int (*rep_get_request) __P((DB_ENV *, u_int32_t *, u_int32_t *)); + int (*rep_get_timeout) __P((DB_ENV *, int, u_int32_t *)); + int (*rep_process_message) + __P((DB_ENV *, DBT *, DBT *, int, DB_LSN *)); + int (*rep_set_clockskew) __P((DB_ENV *, u_int32_t, u_int32_t)); + int (*rep_set_config) __P((DB_ENV *, u_int32_t, int)); + int (*rep_set_limit) __P((DB_ENV *, u_int32_t, u_int32_t)); + int (*rep_set_nsites) __P((DB_ENV *, u_int32_t)); + int (*rep_set_priority) __P((DB_ENV *, u_int32_t)); + int (*rep_set_request) __P((DB_ENV *, u_int32_t, u_int32_t)); + int (*rep_set_timeout) __P((DB_ENV *, int, db_timeout_t)); + int (*rep_set_transport) __P((DB_ENV *, int, int (*)(DB_ENV *, + const DBT *, const DBT *, const DB_LSN *, int, u_int32_t))); + int (*rep_start) __P((DB_ENV *, DBT *, u_int32_t)); + int (*rep_stat) __P((DB_ENV *, DB_REP_STAT **, u_int32_t)); + int (*rep_stat_print) __P((DB_ENV *, u_int32_t)); + int (*rep_sync) __P((DB_ENV *, u_int32_t)); + int (*repmgr_channel) __P((DB_ENV *, int, DB_CHANNEL **, u_int32_t)); + int (*repmgr_get_ack_policy) __P((DB_ENV *, int *)); + int (*repmgr_local_site) __P((DB_ENV *, DB_SITE **)); + int (*repmgr_msg_dispatch) __P((DB_ENV *, + void (*)(DB_ENV *, DB_CHANNEL *, DBT *, u_int32_t, u_int32_t), + u_int32_t)); + int (*repmgr_set_ack_policy) __P((DB_ENV *, int)); + int (*repmgr_site) + __P((DB_ENV *, const char *, u_int, DB_SITE**, u_int32_t)); + int (*repmgr_site_by_eid) __P((DB_ENV *, int, DB_SITE**)); + int (*repmgr_site_list) __P((DB_ENV *, u_int *, DB_REPMGR_SITE **)); + int (*repmgr_start) __P((DB_ENV *, int, u_int32_t)); + int (*repmgr_stat) __P((DB_ENV *, DB_REPMGR_STAT **, u_int32_t)); + int (*repmgr_stat_print) __P((DB_ENV *, u_int32_t)); + int (*set_alloc) __P((DB_ENV *, void *(*)(size_t), + void *(*)(void *, size_t), void (*)(void *))); + int (*set_app_dispatch) + __P((DB_ENV *, int (*)(DB_ENV *, DBT *, DB_LSN *, db_recops))); + int (*set_cache_max) __P((DB_ENV *, u_int32_t, u_int32_t)); + int (*set_cachesize) __P((DB_ENV *, u_int32_t, u_int32_t, int)); + int (*set_create_dir) __P((DB_ENV *, const char *)); + int (*set_data_dir) __P((DB_ENV *, const char *)); + int (*set_data_len) __P((DB_ENV *, u_int32_t)); + int (*set_backup_callbacks) __P((DB_ENV *, + int (*)(DB_ENV *, const char *, const char *, void **), + int (*)(DB_ENV *, u_int32_t, + u_int32_t, u_int32_t, u_int8_t *, void *), + int (*)(DB_ENV *, const char *, void *))); + int (*set_backup_config) __P((DB_ENV *, DB_BACKUP_CONFIG, u_int32_t)); + int (*set_encrypt) __P((DB_ENV *, const char *, u_int32_t)); + void (*set_errcall) __P((DB_ENV *, + void (*)(const DB_ENV *, const char *, const char *))); + void (*set_errfile) __P((DB_ENV *, FILE *)); + void (*set_errpfx) __P((DB_ENV *, const char *)); + int (*set_event_notify) + __P((DB_ENV *, void (*)(DB_ENV *, u_int32_t, void *))); + int (*set_feedback) __P((DB_ENV *, void (*)(DB_ENV *, int, int))); + int (*set_flags) __P((DB_ENV *, u_int32_t, int)); + int (*set_intermediate_dir_mode) __P((DB_ENV *, const char *)); + int (*set_isalive) __P((DB_ENV *, + int (*)(DB_ENV *, pid_t, db_threadid_t, u_int32_t))); + int (*set_lg_bsize) __P((DB_ENV *, u_int32_t)); + int (*set_lg_dir) __P((DB_ENV *, const char *)); + int (*set_lg_filemode) __P((DB_ENV *, int)); + int (*set_lg_max) __P((DB_ENV *, u_int32_t)); + int (*set_lg_regionmax) __P((DB_ENV *, u_int32_t)); + int (*set_lk_conflicts) __P((DB_ENV *, u_int8_t *, int)); + int (*set_lk_detect) __P((DB_ENV *, u_int32_t)); + int (*set_lk_max_lockers) __P((DB_ENV *, u_int32_t)); + int (*set_lk_max_locks) __P((DB_ENV *, u_int32_t)); + int (*set_lk_max_objects) __P((DB_ENV *, u_int32_t)); + int (*set_lk_partitions) __P((DB_ENV *, u_int32_t)); + int (*set_lk_priority) __P((DB_ENV *, u_int32_t, u_int32_t)); + int (*set_lk_tablesize) __P((DB_ENV *, u_int32_t)); + int (*set_memory_init) __P((DB_ENV *, DB_MEM_CONFIG, u_int32_t)); + int (*set_memory_max) __P((DB_ENV *, u_int32_t, u_int32_t)); + int (*set_metadata_dir) __P((DB_ENV *, const char *)); + int (*set_mp_max_openfd) __P((DB_ENV *, int)); + int (*set_mp_max_write) __P((DB_ENV *, int, db_timeout_t)); + int (*set_mp_mmapsize) __P((DB_ENV *, size_t)); + int (*set_mp_mtxcount) __P((DB_ENV *, u_int32_t)); + int (*set_mp_pagesize) __P((DB_ENV *, u_int32_t)); + int (*set_mp_tablesize) __P((DB_ENV *, u_int32_t)); + void (*set_msgcall) + __P((DB_ENV *, void (*)(const DB_ENV *, const char *))); + void (*set_msgfile) __P((DB_ENV *, FILE *)); + int (*set_paniccall) __P((DB_ENV *, void (*)(DB_ENV *, int))); + int (*set_shm_key) __P((DB_ENV *, long)); + int (*set_thread_count) __P((DB_ENV *, u_int32_t)); + int (*set_thread_id) + __P((DB_ENV *, void (*)(DB_ENV *, pid_t *, db_threadid_t *))); + int (*set_thread_id_string) __P((DB_ENV *, + char *(*)(DB_ENV *, pid_t, db_threadid_t, char *))); + int (*set_timeout) __P((DB_ENV *, db_timeout_t, u_int32_t)); + int (*set_tmp_dir) __P((DB_ENV *, const char *)); + int (*set_tx_max) __P((DB_ENV *, u_int32_t)); + int (*set_tx_timestamp) __P((DB_ENV *, time_t *)); + int (*set_verbose) __P((DB_ENV *, u_int32_t, int)); + int (*txn_applied) __P((DB_ENV *, + DB_TXN_TOKEN *, db_timeout_t, u_int32_t)); + int (*stat_print) __P((DB_ENV *, u_int32_t)); + int (*txn_begin) __P((DB_ENV *, DB_TXN *, DB_TXN **, u_int32_t)); + int (*txn_checkpoint) __P((DB_ENV *, u_int32_t, u_int32_t, u_int32_t)); + int (*txn_recover) __P((DB_ENV *, + DB_PREPLIST *, long, long *, u_int32_t)); + int (*txn_stat) __P((DB_ENV *, DB_TXN_STAT **, u_int32_t)); + int (*txn_stat_print) __P((DB_ENV *, u_int32_t)); + /* DB_ENV PUBLIC HANDLE LIST END */ + + /* DB_ENV PRIVATE HANDLE LIST BEGIN */ + int (*prdbt) __P((DBT *, int, + const char *, void *, int (*)(void *, const void *), int, int)); + /* DB_ENV PRIVATE HANDLE LIST END */ +}; + +/* + * Dispatch structure for recovery, log verification and print routines. Since + * internal and external routines take different arguments (ENV versus DB_ENV), + * we need something more elaborate than a single pointer and size. + */ +struct __db_distab { + int (**int_dispatch) __P((ENV *, DBT *, DB_LSN *, db_recops, void *)); + size_t int_size; + int (**ext_dispatch) __P((DB_ENV *, DBT *, DB_LSN *, db_recops)); + size_t ext_size; +}; + +/* + * Log verification configuration structure. + */ +struct __db_logvrfy_config { + int continue_after_fail, verbose; + u_int32_t cachesize; + const char *temp_envhome; + const char *dbfile, *dbname; + DB_LSN start_lsn, end_lsn; + time_t start_time, end_time; +}; + +struct __db_channel { + CHANNEL *channel; /* Pointer to internal state details. */ + int eid; /* Env. ID passed in constructor. */ + db_timeout_t timeout; + + /* DB_CHANNEL PUBLIC HANDLE LIST BEGIN */ + int (*close) __P((DB_CHANNEL *, u_int32_t)); + int (*send_msg) __P((DB_CHANNEL *, DBT *, u_int32_t, u_int32_t)); + int (*send_request) __P((DB_CHANNEL *, + DBT *, u_int32_t, DBT *, db_timeout_t, u_int32_t)); + int (*set_timeout) __P((DB_CHANNEL *, db_timeout_t)); + /* DB_CHANNEL PUBLIC HANDLE LIST END */ +}; + +struct __db_site { + ENV *env; + int eid; + const char *host; + u_int port; + u_int32_t flags; + + /* DB_SITE PUBLIC HANDLE LIST BEGIN */ + int (*get_address) __P((DB_SITE *, const char **, u_int *)); + int (*get_config) __P((DB_SITE *, u_int32_t, u_int32_t *)); + int (*get_eid) __P((DB_SITE *, int *)); + int (*set_config) __P((DB_SITE *, u_int32_t, u_int32_t)); + int (*remove) __P((DB_SITE *)); + int (*close) __P((DB_SITE *)); + /* DB_SITE PUBLIC HANDLE LIST END */ +}; + +#if DB_DBM_HSEARCH != 0 +/******************************************************* + * Dbm/Ndbm historic interfaces. + *******************************************************/ +typedef struct __db DBM; + +#define DBM_INSERT 0 /* Flags to dbm_store(). */ +#define DBM_REPLACE 1 + +/* + * The DB support for ndbm(3) always appends this suffix to the + * file name to avoid overwriting the user's original database. + */ +#define DBM_SUFFIX ".db" + +#if defined(_XPG4_2) +typedef struct { + char *dptr; + size_t dsize; +} datum; +#else +typedef struct { + char *dptr; + int dsize; +} datum; +#endif + +/* + * Translate NDBM calls into DB calls so that DB doesn't step on the + * application's name space. + */ +#define dbm_clearerr(a) __db_ndbm_clearerr(a) +#define dbm_close(a) __db_ndbm_close(a) +#define dbm_delete(a, b) __db_ndbm_delete(a, b) +#define dbm_dirfno(a) __db_ndbm_dirfno(a) +#define dbm_error(a) __db_ndbm_error(a) +#define dbm_fetch(a, b) __db_ndbm_fetch(a, b) +#define dbm_firstkey(a) __db_ndbm_firstkey(a) +#define dbm_nextkey(a) __db_ndbm_nextkey(a) +#define dbm_open(a, b, c) __db_ndbm_open(a, b, c) +#define dbm_pagfno(a) __db_ndbm_pagfno(a) +#define dbm_rdonly(a) __db_ndbm_rdonly(a) +#define dbm_store(a, b, c, d) \ + __db_ndbm_store(a, b, c, d) + +/* + * Translate DBM calls into DB calls so that DB doesn't step on the + * application's name space. + * + * The global variables dbrdonly, dirf and pagf were not retained when 4BSD + * replaced the dbm interface with ndbm, and are not supported here. + */ +#define dbminit(a) __db_dbm_init(a) +#define dbmclose __db_dbm_close +#if !defined(__cplusplus) +#define delete(a) __db_dbm_delete(a) +#endif +#define fetch(a) __db_dbm_fetch(a) +#define firstkey __db_dbm_firstkey +#define nextkey(a) __db_dbm_nextkey(a) +#define store(a, b) __db_dbm_store(a, b) + +/******************************************************* + * Hsearch historic interface. + *******************************************************/ +typedef enum { + FIND, ENTER +} ACTION; + +typedef struct entry { + char *key; + char *data; +} ENTRY; + +#define hcreate(a) __db_hcreate(a) +#define hdestroy __db_hdestroy +#define hsearch(a, b) __db_hsearch(a, b) + +#endif /* DB_DBM_HSEARCH */ + +#if defined(__cplusplus) +} +#endif + +/* Restore default compiler warnings */ +#ifdef _MSC_VER +#pragma warning(pop) +#endif +#endif /* !_DB_H_ */ +/* DO NOT EDIT: automatically built by dist/s_include. + * + * Copyright (c) 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ +#define DB_AGGRESSIVE 0x00000001 +#define DB_ARCH_ABS 0x00000001 +#define DB_ARCH_DATA 0x00000002 +#define DB_ARCH_LOG 0x00000004 +#define DB_ARCH_REMOVE 0x00000008 +#define DB_AUTO_COMMIT 0x00000100 +#define DB_BACKUP_CLEAN 0x00000002 +#define DB_BACKUP_FILES 0x00000008 +#define DB_BACKUP_NO_LOGS 0x00000010 +#define DB_BACKUP_SINGLE_DIR 0x00000020 +#define DB_BACKUP_UPDATE 0x00000040 +#define DB_BOOTSTRAP_HELPER 0x00000001 +#define DB_CDB_ALLDB 0x00000040 +#define DB_CHKSUM 0x00000008 +#define DB_CKP_INTERNAL 0x00000002 +#define DB_CREATE 0x00000001 +#define DB_CURSOR_BULK 0x00000001 +#define DB_CURSOR_TRANSIENT 0x00000008 +#define DB_CXX_NO_EXCEPTIONS 0x00000002 +#define DB_DATABASE_LOCKING 0x00000080 +#define DB_DIRECT 0x00000020 +#define DB_DIRECT_DB 0x00000200 +#define DB_DSYNC_DB 0x00000400 +#define DB_DUP 0x00000010 +#define DB_DUPSORT 0x00000002 +#define DB_DURABLE_UNKNOWN 0x00000040 +#define DB_ENCRYPT 0x00000001 +#define DB_ENCRYPT_AES 0x00000001 +#define DB_EXCL 0x00000004 +#define DB_EXTENT 0x00000100 +#define DB_FAILCHK 0x00000010 +#define DB_FAILCHK_ISALIVE 0x00000040 +#define DB_FAST_STAT 0x00000001 +#define DB_FCNTL_LOCKING 0x00000800 +#define DB_FLUSH 0x00000002 +#define DB_FORCE 0x00000001 +#define DB_FORCESYNC 0x00000001 +#define DB_FOREIGN_ABORT 0x00000001 +#define DB_FOREIGN_CASCADE 0x00000002 +#define DB_FOREIGN_NULLIFY 0x00000004 +#define DB_FREELIST_ONLY 0x00000001 +#define DB_FREE_SPACE 0x00000002 +#define DB_GROUP_CREATOR 0x00000002 +#define DB_HOTBACKUP_IN_PROGRESS 0x00000800 +#define DB_IGNORE_LEASE 0x00001000 +#define DB_IMMUTABLE_KEY 0x00000002 +#define DB_INIT_CDB 0x00000080 +#define DB_INIT_LOCK 0x00000100 +#define DB_INIT_LOG 0x00000200 +#define DB_INIT_MPOOL 0x00000400 +#define DB_INIT_MUTEX 0x00000800 +#define DB_INIT_REP 0x00001000 +#define DB_INIT_TXN 0x00002000 +#define DB_INORDER 0x00000020 +#define DB_INTERNAL_PERSISTENT_DB 0x00001000 +#define DB_INTERNAL_TEMPORARY_DB 0x00002000 +#define DB_JOIN_NOSORT 0x00000001 +#define DB_LEGACY 0x00000004 +#define DB_LOCAL_SITE 0x00000008 +#define DB_LOCKDOWN 0x00004000 +#define DB_LOCK_CHECK 0x00000001 +#define DB_LOCK_IGNORE_REC 0x00000002 +#define DB_LOCK_NOWAIT 0x00000004 +#define DB_LOCK_RECORD 0x00000008 +#define DB_LOCK_SET_TIMEOUT 0x00000010 +#define DB_LOCK_SWITCH 0x00000020 +#define DB_LOCK_UPGRADE 0x00000040 +#define DB_LOG_AUTO_REMOVE 0x00000001 +#define DB_LOG_CHKPNT 0x00000001 +#define DB_LOG_COMMIT 0x00000004 +#define DB_LOG_DIRECT 0x00000002 +#define DB_LOG_DSYNC 0x00000004 +#define DB_LOG_IN_MEMORY 0x00000008 +#define DB_LOG_NOCOPY 0x00000008 +#define DB_LOG_NOT_DURABLE 0x00000010 +#define DB_LOG_NO_DATA 0x00000002 +#define DB_LOG_VERIFY_CAF 0x00000001 +#define DB_LOG_VERIFY_DBFILE 0x00000002 +#define DB_LOG_VERIFY_ERR 0x00000004 +#define DB_LOG_VERIFY_FORWARD 0x00000008 +#define DB_LOG_VERIFY_INTERR 0x00000010 +#define DB_LOG_VERIFY_PARTIAL 0x00000020 +#define DB_LOG_VERIFY_VERBOSE 0x00000040 +#define DB_LOG_VERIFY_WARNING 0x00000080 +#define DB_LOG_WRNOSYNC 0x00000020 +#define DB_LOG_ZERO 0x00000010 +#define DB_MPOOL_CREATE 0x00000001 +#define DB_MPOOL_DIRTY 0x00000002 +#define DB_MPOOL_DISCARD 0x00000001 +#define DB_MPOOL_EDIT 0x00000004 +#define DB_MPOOL_FREE 0x00000008 +#define DB_MPOOL_LAST 0x00000010 +#define DB_MPOOL_NEW 0x00000020 +#define DB_MPOOL_NOFILE 0x00000001 +#define DB_MPOOL_NOLOCK 0x00000004 +#define DB_MPOOL_TRY 0x00000040 +#define DB_MPOOL_UNLINK 0x00000002 +#define DB_MULTIPLE 0x00000800 +#define DB_MULTIPLE_KEY 0x00004000 +#define DB_MULTIVERSION 0x00000008 +#define DB_MUTEX_ALLOCATED 0x00000001 +#define DB_MUTEX_LOCKED 0x00000002 +#define DB_MUTEX_LOGICAL_LOCK 0x00000004 +#define DB_MUTEX_PROCESS_ONLY 0x00000008 +#define DB_MUTEX_SELF_BLOCK 0x00000010 +#define DB_MUTEX_SHARED 0x00000020 +#define DB_NOERROR 0x00004000 +#define DB_NOFLUSH 0x00001000 +#define DB_NOLOCKING 0x00002000 +#define DB_NOMMAP 0x00000010 +#define DB_NOORDERCHK 0x00000002 +#define DB_NOPANIC 0x00004000 +#define DB_NOSYNC 0x00000001 +#define DB_NO_AUTO_COMMIT 0x00008000 +#define DB_NO_CHECKPOINT 0x00008000 +#define DB_ODDFILESIZE 0x00000080 +#define DB_ORDERCHKONLY 0x00000004 +#define DB_OVERWRITE 0x00008000 +#define DB_PANIC_ENVIRONMENT 0x00010000 +#define DB_PRINTABLE 0x00000008 +#define DB_PRIVATE 0x00010000 +#define DB_PR_PAGE 0x00000010 +#define DB_PR_RECOVERYTEST 0x00000020 +#define DB_RDONLY 0x00000400 +#define DB_RDWRMASTER 0x00010000 +#define DB_READ_COMMITTED 0x00000400 +#define DB_READ_UNCOMMITTED 0x00000200 +#define DB_RECNUM 0x00000040 +#define DB_RECOVER 0x00000002 +#define DB_RECOVER_FATAL 0x00020000 +#define DB_REGION_INIT 0x00020000 +#define DB_REGISTER 0x00040000 +#define DB_RENUMBER 0x00000080 +#define DB_REPMGR_CONF_2SITE_STRICT 0x00000001 +#define DB_REPMGR_CONF_ELECTIONS 0x00000002 +#define DB_REPMGR_NEED_RESPONSE 0x00000001 +#define DB_REPMGR_PEER 0x00000010 +#define DB_REP_ANYWHERE 0x00000001 +#define DB_REP_CLIENT 0x00000001 +#define DB_REP_CONF_AUTOINIT 0x00000004 +#define DB_REP_CONF_AUTOROLLBACK 0x00000008 +#define DB_REP_CONF_BULK 0x00000010 +#define DB_REP_CONF_DELAYCLIENT 0x00000020 +#define DB_REP_CONF_INMEM 0x00000040 +#define DB_REP_CONF_LEASE 0x00000080 +#define DB_REP_CONF_NOWAIT 0x00000100 +#define DB_REP_ELECTION 0x00000004 +#define DB_REP_MASTER 0x00000002 +#define DB_REP_NOBUFFER 0x00000002 +#define DB_REP_PERMANENT 0x00000004 +#define DB_REP_REREQUEST 0x00000008 +#define DB_REVSPLITOFF 0x00000100 +#define DB_RMW 0x00002000 +#define DB_SALVAGE 0x00000040 +#define DB_SA_SKIPFIRSTKEY 0x00000080 +#define DB_SA_UNKNOWNKEY 0x00000100 +#define DB_SEQ_DEC 0x00000001 +#define DB_SEQ_INC 0x00000002 +#define DB_SEQ_RANGE_SET 0x00000004 +#define DB_SEQ_WRAP 0x00000008 +#define DB_SEQ_WRAPPED 0x00000010 +#define DB_SET_LOCK_TIMEOUT 0x00000001 +#define DB_SET_REG_TIMEOUT 0x00000004 +#define DB_SET_TXN_NOW 0x00000008 +#define DB_SET_TXN_TIMEOUT 0x00000002 +#define DB_SHALLOW_DUP 0x00000100 +#define DB_SNAPSHOT 0x00000200 +#define DB_STAT_ALL 0x00000004 +#define DB_STAT_ALLOC 0x00000008 +#define DB_STAT_CLEAR 0x00000001 +#define DB_STAT_LOCK_CONF 0x00000010 +#define DB_STAT_LOCK_LOCKERS 0x00000020 +#define DB_STAT_LOCK_OBJECTS 0x00000040 +#define DB_STAT_LOCK_PARAMS 0x00000080 +#define DB_STAT_MEMP_HASH 0x00000010 +#define DB_STAT_MEMP_NOERROR 0x00000020 +#define DB_STAT_SUBSYSTEM 0x00000002 +#define DB_STAT_SUMMARY 0x00000010 +#define DB_ST_DUPOK 0x00000200 +#define DB_ST_DUPSET 0x00000400 +#define DB_ST_DUPSORT 0x00000800 +#define DB_ST_IS_RECNO 0x00001000 +#define DB_ST_OVFL_LEAF 0x00002000 +#define DB_ST_RECNUM 0x00004000 +#define DB_ST_RELEN 0x00008000 +#define DB_ST_TOPLEVEL 0x00010000 +#define DB_SYSTEM_MEM 0x00080000 +#define DB_THREAD 0x00000020 +#define DB_TIME_NOTGRANTED 0x00040000 +#define DB_TRUNCATE 0x00020000 +#define DB_TXN_BULK 0x00000010 +#define DB_TXN_FAMILY 0x00000040 +#define DB_TXN_NOSYNC 0x00000001 +#define DB_TXN_NOT_DURABLE 0x00000004 +#define DB_TXN_NOWAIT 0x00000002 +#define DB_TXN_SNAPSHOT 0x00000004 +#define DB_TXN_SYNC 0x00000008 +#define DB_TXN_WAIT 0x00000080 +#define DB_TXN_WRITE_NOSYNC 0x00000020 +#define DB_UNREF 0x00020000 +#define DB_UPGRADE 0x00000001 +#define DB_USE_ENVIRON 0x00000004 +#define DB_USE_ENVIRON_ROOT 0x00000008 +#define DB_VERB_BACKUP 0x00000001 +#define DB_VERB_DEADLOCK 0x00000002 +#define DB_VERB_FILEOPS 0x00000004 +#define DB_VERB_FILEOPS_ALL 0x00000008 +#define DB_VERB_RECOVERY 0x00000010 +#define DB_VERB_REGISTER 0x00000020 +#define DB_VERB_REPLICATION 0x00000040 +#define DB_VERB_REPMGR_CONNFAIL 0x00000080 +#define DB_VERB_REPMGR_MISC 0x00000100 +#define DB_VERB_REP_ELECT 0x00000200 +#define DB_VERB_REP_LEASE 0x00000400 +#define DB_VERB_REP_MISC 0x00000800 +#define DB_VERB_REP_MSGS 0x00001000 +#define DB_VERB_REP_SYNC 0x00002000 +#define DB_VERB_REP_SYSTEM 0x00004000 +#define DB_VERB_REP_TEST 0x00008000 +#define DB_VERB_WAITSFOR 0x00010000 +#define DB_VERIFY 0x00000002 +#define DB_VERIFY_PARTITION 0x00040000 +#define DB_WRITECURSOR 0x00000010 +#define DB_WRITELOCK 0x00000020 +#define DB_WRITEOPEN 0x00040000 +#define DB_XA_CREATE 0x00000001 +#define DB_YIELDCPU 0x00080000 + +/* DO NOT EDIT: automatically built by dist/s_include. + * + * Copyright (c) 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ +#ifndef _DB_EXT_PROT_IN_ +#define _DB_EXT_PROT_IN_ + +#if defined(__cplusplus) +extern "C" { +#endif + +int db_copy __P((DB_ENV *, const char *, const char *, const char *)); +int db_create __P((DB **, DB_ENV *, u_int32_t)); +char *db_strerror __P((int)); +int db_env_set_func_assert __P((void (*)(const char *, const char *, int))); +int db_env_set_func_close __P((int (*)(int))); +int db_env_set_func_dirfree __P((void (*)(char **, int))); +int db_env_set_func_dirlist __P((int (*)(const char *, char ***, int *))); +int db_env_set_func_exists __P((int (*)(const char *, int *))); +int db_env_set_func_free __P((void (*)(void *))); +int db_env_set_func_fsync __P((int (*)(int))); +int db_env_set_func_ftruncate __P((int (*)(int, off_t))); +int db_env_set_func_ioinfo __P((int (*)(const char *, int, u_int32_t *, u_int32_t *, u_int32_t *))); +int db_env_set_func_malloc __P((void *(*)(size_t))); +int db_env_set_func_file_map __P((int (*)(DB_ENV *, char *, size_t, int, void **), int (*)(DB_ENV *, void *))); +int db_env_set_func_region_map __P((int (*)(DB_ENV *, char *, size_t, int *, void **), int (*)(DB_ENV *, void *))); +int db_env_set_func_pread __P((ssize_t (*)(int, void *, size_t, off_t))); +int db_env_set_func_pwrite __P((ssize_t (*)(int, const void *, size_t, off_t))); +int db_env_set_func_open __P((int (*)(const char *, int, ...))); +int db_env_set_func_read __P((ssize_t (*)(int, void *, size_t))); +int db_env_set_func_realloc __P((void *(*)(void *, size_t))); +int db_env_set_func_rename __P((int (*)(const char *, const char *))); +int db_env_set_func_seek __P((int (*)(int, off_t, int))); +int db_env_set_func_unlink __P((int (*)(const char *))); +int db_env_set_func_write __P((ssize_t (*)(int, const void *, size_t))); +int db_env_set_func_yield __P((int (*)(u_long, u_long))); +int db_env_create __P((DB_ENV **, u_int32_t)); +char *db_version __P((int *, int *, int *)); +char *db_full_version __P((int *, int *, int *, int *, int *)); +int log_compare __P((const DB_LSN *, const DB_LSN *)); +#if defined(DB_WIN32) && !defined(DB_WINCE) +int db_env_set_win_security __P((SECURITY_ATTRIBUTES *sa)); +#endif +int db_sequence_create __P((DB_SEQUENCE **, DB *, u_int32_t)); +#if DB_DBM_HSEARCH != 0 +int __db_ndbm_clearerr __P((DBM *)); +void __db_ndbm_close __P((DBM *)); +int __db_ndbm_delete __P((DBM *, datum)); +int __db_ndbm_dirfno __P((DBM *)); +int __db_ndbm_error __P((DBM *)); +datum __db_ndbm_fetch __P((DBM *, datum)); +datum __db_ndbm_firstkey __P((DBM *)); +datum __db_ndbm_nextkey __P((DBM *)); +DBM *__db_ndbm_open __P((const char *, int, int)); +int __db_ndbm_pagfno __P((DBM *)); +int __db_ndbm_rdonly __P((DBM *)); +int __db_ndbm_store __P((DBM *, datum, datum, int)); +int __db_dbm_close __P((void)); +int __db_dbm_delete __P((datum)); +datum __db_dbm_fetch __P((datum)); +datum __db_dbm_firstkey __P((void)); +int __db_dbm_init __P((char *)); +datum __db_dbm_nextkey __P((datum)); +int __db_dbm_store __P((datum, datum)); +#endif +#if DB_DBM_HSEARCH != 0 +int __db_hcreate __P((size_t)); +ENTRY *__db_hsearch __P((ENTRY, ACTION)); +void __db_hdestroy __P((void)); +#endif + +#if defined(__cplusplus) +} +#endif +#endif /* !_DB_EXT_PROT_IN_ */ diff -r 000000000000 -r a1985f14b030 src/windows_incl/db_config.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/windows_incl/db_config.h Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,706 @@ +/* DO NOT EDIT: automatically built by dist/s_windows. */ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 1996, 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + * $Id$ + */ + +/* Define to 1 if you want to build a version for running the test suite. */ +/* #undef CONFIG_TEST */ + +/* Defined to a size to limit the stack size of Berkeley DB threads. */ +/* #undef DB_STACKSIZE */ + +/* We use DB_WIN32 much as one would use _WIN32 -- to specify that we're using + an operating system environment that supports Win32 calls and semantics. We + don't use _WIN32 because Cygwin/GCC also defines _WIN32, even though + Cygwin/GCC closely emulates the Unix environment. */ +#define DB_WIN32 1 + +/* Define to 1 if you want a debugging version. */ +#if defined(_DEBUG) +#if !defined(DEBUG) +#define DEBUG 1 +#endif +#endif + +/* Define to 1 if you want a version that logs read operations. */ +/* #undef DEBUG_ROP */ + +/* Define to 1 if you want a version that logs write operations. */ +/* #undef DEBUG_WOP */ + +/* Define to 1 if you want a version with run-time diagnostic checking. */ +/* #undef DIAGNOSTIC */ + +/* Define to 1 if building only the most basic features. */ +#define HAVE_RDS_BUILD 1 + +/* Define to 1 if 64-bit types are available. */ +#define HAVE_64BIT_TYPES 1 + +/* Define to 1 if you have the `abort' function. */ +#define HAVE_ABORT 1 + +/* Define to 1 if you have the `atoi' function. */ +#define HAVE_ATOI 1 + +/* Define to 1 if you have the `atol' function. */ +#define HAVE_ATOL 1 + +/* Define to 1 if platform reads and writes files atomically. */ +/* #undef HAVE_ATOMICFILEREAD */ + +/* Define to 1 to use Solaris library routes for atomic operations. */ +/* #undef HAVE_ATOMIC_SOLARIS */ + +/* Define to 1 to use native atomic operations. */ +#define HAVE_ATOMIC_SUPPORT 1 + +/* Define to 1 to use GCC and x86 or x86_64 assemlby language atomic + operations. */ +/* #undef HAVE_ATOMIC_X86_GCC_ASSEMBLY */ + +/* Define to 1 if you have the `backtrace' function. */ +/* Define to 1 if you have the `backtrace' function. */ +/* #undef HAVE_BACKTRACE */ + +/* Define to 1 if you have the `backtrace_symbols' function. */ +/* #undef HAVE_BACKTRACE_SYMBOLS */ + +/* Define to 1 if you have the `bsearch' function. */ +#define HAVE_BSEARCH 1 + +/* Define to 1 if you have the `clock_gettime' function. */ +/* #undef HAVE_CLOCK_GETTIME */ + +/* Define to 1 if clock_gettime supports CLOCK_MONOTONIC. */ +/* #undef HAVE_CLOCK_MONOTONIC */ + +/* Define to 1 if building compression support. */ +#if !defined(HAVE_SMALLBUILD) && !defined(HAVE_RDS_BUILD) +#define HAVE_COMPRESSION 1 +#endif + +/* Define to 1 if Berkeley DB release includes strong cryptography. */ +#if !defined(HAVE_SMALLBUILD) && !defined(HAVE_RDS_BUILD) +#define HAVE_CRYPTO 1 +#endif + +/* Define to 1 if using Intel IPP for cryptography. */ +/* #undef HAVE_CRYPTO_IPP */ + +/* Define to 1 if you have the `ctime_r' function. */ +/* #undef HAVE_CTIME_R */ + +/* Define to 1 if ctime_r takes a buffer length as a third argument. */ +/* #undef HAVE_CTIME_R_3ARG */ + +/* Define to 1 if building the DBM API. */ +#define HAVE_DBM 1 + +/* Define to 1 if you have the `directio' function. */ +/* #undef HAVE_DIRECTIO */ + +/* Define to 1 if you have the header file, and it defines `DIR'. + */ +/* #undef HAVE_DIRENT_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_DLFCN_H */ + +/* Define to 1 to use dtrace for performance event tracing. */ +/* #undef HAVE_DTRACE */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_EXECINFO_H */ + +/* Define to 1 if you have EXIT_SUCCESS/EXIT_FAILURE #defines. */ +#define HAVE_EXIT_SUCCESS 1 + +/* Define to 1 if you have the `fchmod' function. */ +/* #undef HAVE_FCHMOD */ + +/* Define to 1 if you have the `fclose' function. */ +#define HAVE_FCLOSE 1 + +/* Define to 1 if you have the `fcntl' function. */ +/* #undef HAVE_FCNTL */ + +/* Define to 1 if fcntl/F_SETFD denies child access to file descriptors. */ +/* #undef HAVE_FCNTL_F_SETFD */ + +/* Define to 1 if you have the `fdatasync' function. */ +/* #undef HAVE_FDATASYNC */ + +/* Define to 1 if you have the `fgetc' function. */ +#define HAVE_FGETC 1 + +/* Define to 1 if you have the `fgets' function. */ +#define HAVE_FGETS 1 + +/* Define to 1 if allocated filesystem blocks are not zeroed. */ +#define HAVE_FILESYSTEM_NOTZERO 1 + +/* Define to 1 if you have the `fopen' function. */ +#define HAVE_FOPEN 1 + +/* Define to 1 if you have the `ftruncate' function. */ +#define HAVE_FTRUNCATE 1 + +/* Define to 1 if you have the `fwrite' function. */ +#define HAVE_FWRITE 1 + +/* Define to 1 if you have the `getaddrinfo' function. */ +#define HAVE_GETADDRINFO 1 + +/* Define to 1 if you have the `getcwd' function. */ +#define HAVE_GETCWD 1 + +/* Define to 1 if you have the `getenv' function. */ +#define HAVE_GETENV 1 + +/* Define to 1 if you have the `getgid' function. */ +/* #undef HAVE_GETGID */ + +/* Define to 1 if you have the `getopt' function. */ +/* + * Windows does not have the getopt function, but as Berkeley DB example + * programs require getopt, we handle it outside of this configuration. + */ +#define HAVE_GETOPT 1 + +/* Define to 1 if getopt supports the optreset variable. */ +#define HAVE_GETOPT_OPTRESET 1 + +/* Define to 1 if you have the `getrusage' function. */ +/* #undef HAVE_GETRUSAGE */ + +/* Define to 1 if you have the `gettimeofday' function. */ +/* #undef HAVE_GETTIMEOFDAY */ + +/* Define to 1 if you have the `getuid' function. */ +/* #undef HAVE_GETUID */ + +/* Define to 1 if building Hash access method. */ +#if !defined(HAVE_SMALLBUILD) && !defined(HAVE_RDS_BUILD) +#define HAVE_HASH 1 +#endif + +/* Define to 1 if building Heap access method. */ +#if !defined(HAVE_SMALLBUILD) && !defined(HAVE_RDS_BUILD) +#define HAVE_HEAP 1 +#endif + +/* Define to 1 if you have the `hstrerror' function. */ +/* #undef HAVE_HSTRERROR */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_INTTYPES_H */ + +/* Define to 1 if you have the `isalpha' function. */ +/* #undef HAVE_ISALPHA */ + +/* Define to 1 if you have the `isdigit' function. */ +#define HAVE_ISDIGIT 1 + +/* Define to 1 if you have the `isprint' function. */ +#define HAVE_ISPRINT 1 + +/* Define to 1 if you have localization function to support globalization. */ +/* #undef HAVE_LOCALIZATION */ + +/* Define to 1 if you have the `localtime' function. */ +#define HAVE_LOCALTIME 1 + +/* Define to 1 to enable log checksums. */ +/* #undef HAVE_LOG_CHECKSUM */ + +/* Define to 1 if you have the `isspace' function. */ +#define HAVE_ISSPACE 1 + +/* Define to 1 if you have the `memcmp' function. */ +#define HAVE_MEMCMP 1 + +/* Define to 1 if you have the `memcpy' function. */ +#define HAVE_MEMCPY 1 + +/* Define to 1 if you have the `memmove' function. */ +#define HAVE_MEMMOVE 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_MEMORY_H 1 + +/* Define to 1 if you have the `mlock' function. */ +/* #undef HAVE_MLOCK */ + +/* Define to 1 if you have the `mmap' function. */ +/* #undef HAVE_MMAP */ + +/* Define to 1 where mmap() incrementally extends the accessible mapping as + the underlying file grows. */ +/* #undef HAVE_MMAP_EXTEND */ + +/* Define to 1 if you have the `mprotect' function. */ +/* #undef HAVE_MPROTECT */ + +/* Define to 1 if you have the `munlock' function. */ +/* #undef HAVE_MUNLOCK */ + +/* Define to 1 if you have the `munmap' function. */ +/* #undef HAVE_MUNMAP */ + +/* Define to 1 to use the GCC compiler and 68K assembly language mutexes. */ +/* #undef HAVE_MUTEX_68K_GCC_ASSEMBLY */ + +/* Define to 1 to use the AIX _check_lock mutexes. */ +/* #undef HAVE_MUTEX_AIX_CHECK_LOCK */ + +/* Define to 1 to use the GCC compiler and Alpha assembly language mutexes. */ +/* #undef HAVE_MUTEX_ALPHA_GCC_ASSEMBLY */ + +/* Define to 1 to use the GCC compiler and ARM assembly language mutexes. */ +/* #undef HAVE_MUTEX_ARM_GCC_ASSEMBLY */ + +/* Define to 1 to use the Apple/Darwin _spin_lock_try mutexes. */ +/* #undef HAVE_MUTEX_DARWIN_SPIN_LOCK_TRY */ + +/* Define to 1 to use the UNIX fcntl system call mutexes. */ +/* #undef HAVE_MUTEX_FCNTL */ + +/* Define to 1 to use the GCC compiler and PaRisc assembly language mutexes. + */ +/* #undef HAVE_MUTEX_HPPA_GCC_ASSEMBLY */ + +/* Define to 1 to use the msem_XXX mutexes on HP-UX. */ +/* #undef HAVE_MUTEX_HPPA_MSEM_INIT */ + +/* Define to 1 to use test-and-set mutexes with blocking mutexes. */ +/* #undef HAVE_MUTEX_HYBRID */ + +/* Define to 1 to use the GCC compiler and IA64 assembly language mutexes. */ +/* #undef HAVE_MUTEX_IA64_GCC_ASSEMBLY */ + +/* Define to 1 to use the GCC compiler and MIPS assembly language mutexes. */ +/* #undef HAVE_MUTEX_MIPS_GCC_ASSEMBLY */ + +/* Define to 1 to use the msem_XXX mutexes on systems other than HP-UX. */ +/* #undef HAVE_MUTEX_MSEM_INIT */ + +/* Define to 1 to use the GCC compiler and PowerPC assembly language mutexes. + */ +/* #undef HAVE_MUTEX_PPC_GCC_ASSEMBLY */ + +/* Define to 1 to use POSIX 1003.1 pthread_XXX mutexes. */ +/* #undef HAVE_MUTEX_PTHREADS */ + +/* Define to 1 to use Reliant UNIX initspin mutexes. */ +/* #undef HAVE_MUTEX_RELIANTUNIX_INITSPIN */ + +/* Define to 1 to use the IBM C compiler and S/390 assembly language mutexes. + */ +/* #undef HAVE_MUTEX_S390_CC_ASSEMBLY */ + +/* Define to 1 to use the GCC compiler and S/390 assembly language mutexes. */ +/* #undef HAVE_MUTEX_S390_GCC_ASSEMBLY */ + +/* Define to 1 to use the SCO compiler and x86 assembly language mutexes. */ +/* #undef HAVE_MUTEX_SCO_X86_CC_ASSEMBLY */ + +/* Define to 1 to use the obsolete POSIX 1003.1 sema_XXX mutexes. */ +/* #undef HAVE_MUTEX_SEMA_INIT */ + +/* Define to 1 to use the SGI XXX_lock mutexes. */ +/* #undef HAVE_MUTEX_SGI_INIT_LOCK */ + +/* Define to 1 to use the Solaris _lock_XXX mutexes. */ +/* #undef HAVE_MUTEX_SOLARIS_LOCK_TRY */ + +/* Define to 1 to use the Solaris lwp threads mutexes. */ +/* #undef HAVE_MUTEX_SOLARIS_LWP */ + +/* Define to 1 to use the GCC compiler and Sparc assembly language mutexes. */ +/* #undef HAVE_MUTEX_SPARC_GCC_ASSEMBLY */ + +/* Define to 1 if the Berkeley DB library should support mutexes. */ +#define HAVE_MUTEX_SUPPORT 1 + +/* Define to 1 if mutexes hold system resources. */ +/* #undef HAVE_MUTEX_SYSTEM_RESOURCES */ + +/* Define to 1 to configure mutexes intra-process only. */ +/* #undef HAVE_MUTEX_THREAD_ONLY */ + +/* Define to 1 to use the CC compiler and Tru64 assembly language mutexes. */ +/* #undef HAVE_MUTEX_TRU64_CC_ASSEMBLY */ + +/* Define to 1 to use the UNIX International mutexes. */ +/* #undef HAVE_MUTEX_UI_THREADS */ + +/* Define to 1 to use the UTS compiler and assembly language mutexes. */ +/* #undef HAVE_MUTEX_UTS_CC_ASSEMBLY */ + +/* Define to 1 to use VMS mutexes. */ +/* #undef HAVE_MUTEX_VMS */ + +/* Define to 1 to use VxWorks mutexes. */ +/* #undef HAVE_MUTEX_VXWORKS */ + +/* Define to 1 to use the MSVC compiler and Windows mutexes. */ +#define HAVE_MUTEX_WIN32 1 + +/* Define to 1 to use the GCC compiler and Windows mutexes. */ +/* #undef HAVE_MUTEX_WIN32_GCC */ + +/* Define to 1 to use the GCC compiler and 64-bit x86 assembly language + mutexes. */ +/* #undef HAVE_MUTEX_X86_64_GCC_ASSEMBLY */ + +/* Define to 1 to use the GCC compiler and 32-bit x86 assembly language + mutexes. */ +/* #undef HAVE_MUTEX_X86_GCC_ASSEMBLY */ + +/* Define to 1 if you have the header file, and it defines `DIR'. */ +/* #undef HAVE_NDIR_H */ + +/* Define to 1 if you have the O_DIRECT flag. */ +/* #undef HAVE_O_DIRECT */ + +/* Define to 1 if building partitioned database support. */ +#if !defined(HAVE_SMALLBUILD) && !defined(HAVE_RDS_BUILD) +#define HAVE_PARTITION 1 +#endif + +/* Define to 1 to enable some kind of performance event monitoring. */ +/* #undef HAVE_PERFMON */ + +/* Define to 1 to enable performance event monitoring of *_stat() statistics. + */ +/* #undef HAVE_PERFMON_STATISTICS */ + +/* Define to 1 if you have the `pread' function. */ +/* #undef HAVE_PREAD */ + +/* Define to 1 if you have the `printf' function. */ +#define HAVE_PRINTF 1 + +/* Define to 1 if you have the `pstat_getdynamic' function. */ +/* #undef HAVE_PSTAT_GETDYNAMIC */ + +/* Define to 1 if it is OK to initialize an already initialized + pthread_cond_t. */ +/* #undef HAVE_PTHREAD_COND_REINIT_OKAY */ + +/* Define to 1 if it is OK to initialize an already initialized + pthread_rwlock_t. */ +/* #undef HAVE_PTHREAD_RWLOCK_REINIT_OKAY */ + +/* Define to 1 if you have the `pthread_self' function. */ +/* #undef HAVE_PTHREAD_SELF */ + +/* Define to 1 if you have the `pthread_yield' function. */ +/* #undef HAVE_PTHREAD_YIELD */ + +/* Define to 1 if you have the `pwrite' function. */ +/* #undef HAVE_PWRITE */ + +/* Define to 1 if building on QNX. */ +/* #undef HAVE_QNX */ + +/* Define to 1 if you have the `qsort' function. */ +#define HAVE_QSORT 1 + +/* Define to 1 if building Queue access method. */ +#if !defined(HAVE_SMALLBUILD) && !defined(HAVE_RDS_BUILD) +#define HAVE_QUEUE 1 +#endif + +/* Define to 1 if you have the `raise' function. */ +#define HAVE_RAISE 1 + +/* Define to 1 if you have the `rand' function. */ +#define HAVE_RAND 1 + +/* Define to 1 if you have the `random' function. */ +/* #undef HAVE_RANDOM */ + +/* Define to 1 if building replication support. */ +#if !defined(HAVE_SMALLBUILD) && !defined(HAVE_RDS_BUILD) +#define HAVE_REPLICATION 1 +#endif + +/* Define to 1 if building the Berkeley DB replication framework. */ +#if !defined(HAVE_SMALLBUILD) && !defined(HAVE_RDS_BUILD) +#define HAVE_REPLICATION_THREADS 1 +#endif + +/* Define to 1 if you have the `sched_yield' function. */ +/* #undef HAVE_SCHED_YIELD */ + +/* Define to 1 if you have the `select' function. */ +/* #undef HAVE_SELECT */ + +/* Define to 1 if you have the `setgid' function. */ +/* #undef HAVE_SETGID */ + +/* Define to 1 if you have the `setuid' function. */ +#define HAVE_SETUID 1 + +/* Define to 1 to configure Berkeley DB to use shared, read/write latches. */ +#define HAVE_SHARED_LATCHES 1 + +/* Define to 1 if shmctl/SHM_LOCK locks down shared memory segments. */ +/* #undef HAVE_SHMCTL_SHM_LOCK */ + +/* Define to 1 if you have the `shmget' function. */ +/* #undef HAVE_SHMGET */ + +/* Define to 1 if you have the `sigaction' function. */ +/* #undef HAVE_SIGACTION */ + +/* Define to 1 if thread identifier type db_threadid_t is integral. */ +#define HAVE_SIMPLE_THREAD_TYPE 1 + +/* Define to 1 if you have the `snprintf' function. */ +#define HAVE_SNPRINTF 1 + +/* Define to 1 if you have the `stat' function. */ +#define HAVE_STAT 1 + +/* Define to 1 if building statistics support. */ +#define HAVE_STATISTICS 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_STDINT_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_STDLIB_H 1 + +/* Define to 1 if you have the `strcasecmp' function. */ +#define HAVE_STRCASECMP 1 + +/* Define to 1 if you have the `strcat' function. */ +#define HAVE_STRCAT 1 + +/* Define to 1 if you have the `strchr' function. */ +#define HAVE_STRCHR 1 + +/* Define to 1 if you have the `strdup' function. */ +#define HAVE_STRDUP 1 + +/* Define to 1 if you have the `strerror' function. */ +#define HAVE_STRERROR 1 + +/* Define to 1 if you have the `strftime' function. */ +#define HAVE_STRFTIME 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STRINGS_H 1 + +/* Define to 1 if you have the header file. */ +#define HAVE_STRING_H 1 + +/* Define to 1 if building without output message content. */ +#ifdef HAVE_SMALLBUILD +#define HAVE_STRIPPED_MESSAGES 1 +#endif + +/* Define to 1 if you have the `strncat' function. */ +#define HAVE_STRNCAT 1 + +/* Define to 1 if you have the `strncmp' function. */ +#define HAVE_STRNCMP 1 + +/* Define to 1 if you have the `strrchr' function. */ +#define HAVE_STRRCHR 1 + +/* Define to 1 if you have the `strsep' function. */ +/* #undef HAVE_STRSEP */ + +/* Define to 1 if you have the `strtol' function. */ +#define HAVE_STRTOL 1 + +/* Define to 1 if you have the `strtoul' function. */ +#define HAVE_STRTOUL 1 + +/* Define to 1 if `st_blksize' is member of `struct stat'. */ +/* #undef HAVE_STRUCT_STAT_ST_BLKSIZE */ + +/* Define to 1 if you have the `sysconf' function. */ +/* #undef HAVE_SYSCONF */ + +/* Define to 1 if port includes files in the Berkeley DB source code. */ +/* #undef HAVE_SYSTEM_INCLUDE_FILES */ + +/* Define to 1 if you have the header file, and it defines `DIR'. + */ +/* #undef HAVE_SYS_DIR_H */ + +/* Define to 1 if you have the header file, and it defines `DIR'. + */ +/* #undef HAVE_SYS_NDIR_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SYS_SDT_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SYS_SELECT_H */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SYS_SOCKET_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_STAT_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_SYS_TIME_H */ + +/* Define to 1 if you have the header file. */ +#define HAVE_SYS_TYPES_H 1 + +/* Define to 1 if you have the `time' function. */ +#define HAVE_TIME 1 + +/* Define to 1 if building in transaction support. */ +/* #undef HAVE_TRANSACTIONS */ + +/* Define to 1 if you have the header file. */ +/* #undef HAVE_UNISTD_H */ + +/* Define to 1 if unlink of file with open file descriptors will fail. */ +/* #undef HAVE_UNLINK_WITH_OPEN_FAILURE */ + +/* Define to 1 if port includes historic database upgrade support. */ +#define HAVE_UPGRADE_SUPPORT 1 + +/* Define to 1 if building access method verification support. */ +#if !defined(HAVE_SMALLBUILD) && !defined(HAVE_RDS_BUILD) +#define HAVE_VERIFY 1 +#endif + +/* Define to 1 if you have the `vsnprintf' function. */ +#define HAVE_VSNPRINTF 1 + +/* Define to 1 if building VxWorks. */ +/* #undef HAVE_VXWORKS */ + +/* Define to 1 if you have the `yield' function. */ +/* #undef HAVE_YIELD */ + +/* Define to 1 if you have the `_fstati64' function. */ +#define HAVE__FSTATI64 1 + +/* Define to the sub-directory in which libtool stores uninstalled libraries. */ +/* #undef LT_OBJDIR */ + +/* Define to the address where bug reports for this package should be sent. */ +#define PACKAGE_BUGREPORT "Oracle Technology Network Berkeley DB forum" + +/* Define to the full name of this package. */ +#define PACKAGE_NAME "Berkeley DB" + +/* Define to the full name and version of this package. */ +#define PACKAGE_STRING "Berkeley DB 5.4.0" + +/* Define to the one symbol short name of this package. */ +#define PACKAGE_TARNAME "db-5.4.0" + +/* Define to the home page for this package. */ +#define PACKAGE_URL "http://www.oracle.com/technology/software/products/berkeley-db/index.html" + +/* Define to the version of this package. */ +#define PACKAGE_VERSION "5.4.0" + +/* The size of a `char', as computed by sizeof. */ +/* #undef SIZEOF_CHAR */ + +/* The size of a `char *', as computed by sizeof. */ +#if defined(_WIN64) +#define SIZEOF_CHAR_P 8 +#else +#define SIZEOF_CHAR_P 4 +#endif + +/* The size of a `int', as computed by sizeof. */ +/* #undef SIZEOF_INT */ + +/* The size of a `long', as computed by sizeof. */ +/* #undef SIZEOF_LONG */ + +/* The size of a `long long', as computed by sizeof. */ +/* #undef SIZEOF_LONG_LONG */ + +/* The size of a `short', as computed by sizeof. */ +/* #undef SIZEOF_SHORT */ + +/* The size of a `size_t', as computed by sizeof. */ +/* #undef SIZEOF_SIZE_T */ + +/* The size of a `unsigned char', as computed by sizeof. */ +/* #undef SIZEOF_UNSIGNED_CHAR */ + +/* The size of a `unsigned int', as computed by sizeof. */ +/* #undef SIZEOF_UNSIGNED_INT */ + +/* The size of a `unsigned long', as computed by sizeof. */ +/* #undef SIZEOF_UNSIGNED_LONG */ + +/* The size of a `unsigned long long', as computed by sizeof. */ +/* #undef SIZEOF_UNSIGNED_LONG_LONG */ + +/* The size of a `unsigned short', as computed by sizeof. */ +/* #undef SIZEOF_UNSIGNED_SHORT */ + +/* Define to 1 if the `S_IS*' macros in do not work properly. */ +/* #undef STAT_MACROS_BROKEN */ + +/* Define to 1 if you have the ANSI C header files. */ +#define STDC_HEADERS 1 + +/* Define to 1 if you can safely include both and . */ +/* #undef TIME_WITH_SYS_TIME */ + +/* Define to 1 to mask harmless uninitialized memory read/writes. */ +/* #undef UMRW */ + +/* Number of bits in a file offset, on hosts where this is settable. */ +/* #undef _FILE_OFFSET_BITS */ + +/* Define for large files, on AIX-style hosts. */ +/* #undef _LARGE_FILES */ + +/* Define to empty if `const' does not conform to ANSI C. */ +/* #undef const */ + +/* Define to `__inline__' or `__inline' if that's what the C compiler + calls it, or to nothing if 'inline' is not supported under any name. */ +#ifndef __cplusplus +#define inline __inline +#endif + +/* type to use in place of socklen_t if not defined */ +/* #undef socklen_t */ diff -r 000000000000 -r a1985f14b030 src/windows_incl/db_int.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/windows_incl/db_int.h Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,1185 @@ +/* DO NOT EDIT: automatically built by dist/s_windows. */ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 1996, 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + * $Id$ + */ + +#ifndef _DB_INT_H_ +#define _DB_INT_H_ + +/******************************************************* + * Berkeley DB ANSI/POSIX include files. + *******************************************************/ +#ifdef HAVE_SYSTEM_INCLUDE_FILES +#include +#ifdef DIAG_MVCC +#include +#endif +#include + +#if defined(HAVE_REPLICATION_THREADS) +#ifdef HAVE_SYS_SELECT_H +#include +#endif +#ifdef HAVE_VXWORKS +#include +#endif +#endif + +#if TIME_WITH_SYS_TIME +#include +#include +#else +#if HAVE_SYS_TIME_H +#include +#else +#include +#endif +#endif + +#ifdef HAVE_VXWORKS +#include +#else +#include +#endif + +#if defined(HAVE_REPLICATION_THREADS) +#ifdef HAVE_SYS_SOCKET_H +#include +#endif +#include +#include +#include +#endif + +#if defined(STDC_HEADERS) || defined(__cplusplus) +#include +#else +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#endif /* !HAVE_SYSTEM_INCLUDE_FILES */ + +#ifdef DB_WIN32 +#include "dbinc/win_db.h" +#endif + +#ifdef HAVE_DBM +#undef DB_DBM_HSEARCH +#define DB_DBM_HSEARCH 1 +#endif + +#include "db.h" +#include "clib_port.h" + +#include "dbinc/queue.h" +#include "dbinc/shqueue.h" +#include "dbinc/perfmon.h" + +#if defined(__cplusplus) +extern "C" { +#endif + +/* + * The Windows compiler needs to be told about structures that are available + * outside a dll. + */ +#if defined(DB_WIN32) && defined(_MSC_VER) && \ + !defined(DB_CREATE_DLL) && !defined(_LIB) +#define __DB_IMPORT __declspec(dllimport) +#else +#define __DB_IMPORT +#endif + +/******************************************************* + * Forward structure declarations. + *******************************************************/ +struct __db_commit_info; typedef struct __db_commit_info DB_COMMIT_INFO; +struct __db_reginfo_t; typedef struct __db_reginfo_t REGINFO; +struct __db_txnhead; typedef struct __db_txnhead DB_TXNHEAD; +struct __db_txnlist; typedef struct __db_txnlist DB_TXNLIST; +struct __vrfy_childinfo;typedef struct __vrfy_childinfo VRFY_CHILDINFO; +struct __vrfy_dbinfo; typedef struct __vrfy_dbinfo VRFY_DBINFO; +struct __vrfy_pageinfo; typedef struct __vrfy_pageinfo VRFY_PAGEINFO; + +struct __db_log_verify_info; +struct __txn_verify_info; +struct __lv_filereg_info; +struct __lv_ckp_info; +struct __lv_timestamp_info; +typedef struct __db_log_verify_info DB_LOG_VRFY_INFO; +typedef struct __txn_verify_info VRFY_TXN_INFO; +typedef struct __lv_filereg_info VRFY_FILEREG_INFO; +typedef struct __lv_filelife VRFY_FILELIFE; +typedef struct __lv_ckp_info VRFY_CKP_INFO; +typedef struct __lv_timestamp_info VRFY_TIMESTAMP_INFO; + +/* + * TXNINFO_HANDLER -- + * Callback function pointer type for __iterate_txninfo. + */ +typedef int (*TXNINFO_HANDLER) __P((DB_LOG_VRFY_INFO *, VRFY_TXN_INFO *, void *)); + +typedef SH_TAILQ_HEAD(__hash_head) DB_HASHTAB; + +/******************************************************* + * General purpose constants and macros. + *******************************************************/ +#undef FALSE +#define FALSE 0 +#undef TRUE +#define TRUE (!FALSE) + +#define MEGABYTE 1048576 +#define GIGABYTE 1073741824 + +#define NS_PER_MS 1000000 /* Nanoseconds in a millisecond */ +#define NS_PER_US 1000 /* Nanoseconds in a microsecond */ +#define NS_PER_SEC 1000000000 /* Nanoseconds in a second */ +#define US_PER_MS 1000 /* Microseconds in a millisecond */ +#define US_PER_SEC 1000000 /* Microseconds in a second */ +#define MS_PER_SEC 1000 /* Milliseconds in a second */ + +#define RECNO_OOB 0 /* Illegal record number. */ + +/* + * Define a macro which has no runtime effect, yet avoids triggering empty + * statement compiler warnings. Use it as the text of conditionally-null macros. + */ +#define NOP_STATEMENT do { } while (0) + +/* Test for a power-of-two (tests true for zero, which doesn't matter here). */ +#define POWER_OF_TWO(x) (((x) & ((x) - 1)) == 0) + +/* Test for valid page sizes. */ +#define DB_MIN_PGSIZE 0x000200 /* Minimum page size (512). */ +#define DB_MAX_PGSIZE 0x010000 /* Maximum page size (65536). */ +#define IS_VALID_PAGESIZE(x) \ + (POWER_OF_TWO(x) && (x) >= DB_MIN_PGSIZE && ((x) <= DB_MAX_PGSIZE)) + +/* Minimum number of pages cached, by default. */ +#define DB_MINPAGECACHE 16 + +/* + * If we are unable to determine the underlying filesystem block size, use + * 8K on the grounds that most OS's use less than 8K for a VM page size. + */ +#define DB_DEF_IOSIZE (8 * 1024) + +/* Align an integer to a specific boundary. */ +#undef DB_ALIGN +#define DB_ALIGN(v, bound) \ + (((v) + (bound) - 1) & ~(((uintmax_t)(bound)) - 1)) + +/* Increment a pointer to a specific boundary. */ +#undef ALIGNP_INC +#define ALIGNP_INC(p, bound) \ + (void *)(((uintptr_t)(p) + (bound) - 1) & ~(((uintptr_t)(bound)) - 1)) + +/* + * DB_ALIGN8 adjusts structure alignments to make sure shared structures have + * fixed size and filed offset on both 32bit and 64bit platforms when + * HAVE_MIXED_SIZE_ADDRESSING is defined. + */ +#ifdef HAVE_MIXED_SIZE_ADDRESSING +#define DB_ALIGN8 __declspec(align(8)) +#else +#define DB_ALIGN8 +#endif + +/* + * Berkeley DB uses the va_copy macro from C99, not all compilers include + * it, so add a dumb implementation compatible with pre C99 implementations. + */ +#ifndef va_copy +#define va_copy(d, s) ((d) = (s)) +#endif + +/* + * Print an address as a u_long (a u_long is the largest type we can print + * portably). Most 64-bit systems have made longs 64-bits, so this should + * work. + */ +#define P_TO_ULONG(p) ((u_long)(uintptr_t)(p)) + +/* + * Convert a pointer to an integral value. + * + * The (u_int16_t)(uintptr_t) cast avoids warnings: the (uintptr_t) cast + * converts the value to an integral type, and the (u_int16_t) cast converts + * it to a small integral type so we don't get complaints when we assign the + * final result to an integral type smaller than uintptr_t. + */ +#define P_TO_UINT32(p) ((u_int32_t)(uintptr_t)(p)) +#define P_TO_UINT16(p) ((u_int16_t)(uintptr_t)(p)) +#define P_TO_ROFF(p) ((roff_t)(uintptr_t)(p)) + +/* The converse of P_TO_ROFF() above. */ +#define ROFF_TO_P(roff) ((void *)(uintptr_t)(roff)) + +/* + * There are several on-page structures that are declared to have a number of + * fields followed by a variable length array of items. The structure size + * without including the variable length array or the address of the first of + * those elements can be found using SSZ. + * + * This macro can also be used to find the offset of a structure element in a + * structure. This is used in various places to copy structure elements from + * unaligned memory references, e.g., pointers into a packed page. + * + * There are two versions because compilers object if you take the address of + * an array. + */ +#undef SSZ +#define SSZ(name, field) P_TO_UINT16(&(((name *)0)->field)) + +#undef SSZA +#define SSZA(name, field) P_TO_UINT16(&(((name *)0)->field[0])) + +/* Structure used to print flag values. */ +typedef struct __fn { + u_int32_t mask; /* Flag value. */ + const char *name; /* Flag name. */ +} FN; + +/* Set, clear and test flags. */ +#define FLD_CLR(fld, f) (fld) &= ~(f) +#define FLD_ISSET(fld, f) ((fld) & (f)) +#define FLD_SET(fld, f) (fld) |= (f) +#define F_CLR(p, f) (p)->flags &= ~(f) +#define F_ISSET(p, f) ((p)->flags & (f)) +#define F_SET(p, f) (p)->flags |= (f) +#define F2_CLR(p, f) ((p)->flags2 &= ~(f)) +#define F2_ISSET(p, f) ((p)->flags2 & (f)) +#define F2_SET(p, f) ((p)->flags2 |= (f)) +#define LF_CLR(f) ((flags) &= ~(f)) +#define LF_ISSET(f) ((flags) & (f)) +#define LF_SET(f) ((flags) |= (f)) + +/* + * Calculate a percentage. The values can overflow 32-bit integer arithmetic + * so we use floating point. + * + * When calculating a bytes-vs-page size percentage, we're getting the inverse + * of the percentage in all cases, that is, we want 100 minus the percentage we + * calculate. + */ +#define DB_PCT(v, total) \ + ((int)((total) == 0 ? 0 : ((double)(v) * 100) / (total))) +#define DB_PCT_PG(v, total, pgsize) \ + ((int)((total) == 0 ? 0 : \ + 100 - ((double)(v) * 100) / (((double)total) * (pgsize)))) + +/* + * Statistics update shared memory and so are expensive -- don't update the + * values unless we're going to display the results. + * When performance monitoring is enabled, the changed value can be published + * (via DTrace or SystemTap) along with another associated value or two. + */ +#undef STAT +#ifdef HAVE_STATISTICS +#define STAT(x) x +#define STAT_ADJUST(env, cat, subcat, val, amount, id) \ + do { \ + (val) += (amount); \ + STAT_PERFMON2((env), cat, subcat, (val), (id)); \ + } while (0) +#define STAT_ADJUST_VERB(env, cat, subcat, val, amount, id1, id2) \ + do { \ + (val) += (amount); \ + STAT_PERFMON3((env), cat, subcat, (val), (id1), (id2)); \ + } while (0) +#define STAT_INC(env, cat, subcat, val, id) \ + STAT_ADJUST(env, cat, subcat, (val), 1, (id)) +#define STAT_INC_VERB(env, cat, subcat, val, id1, id2) \ + STAT_ADJUST_VERB((env), cat, subcat, (val), 1, (id1), (id2)) +/* + * STAT_DEC() subtracts one rather than adding (-1) with STAT_ADJUST(); the + * latter might generate a compilation warning for an unsigned value. + */ +#define STAT_DEC(env, cat, subcat, val, id) \ + do { \ + (val)--; \ + STAT_PERFMON2((env), cat, subcat, (val), (id)); \ + } while (0) +/* N.B.: Add a verbose version of STAT_DEC() when needed. */ + +#define STAT_SET(env, cat, subcat, val, newval, id) \ + do { \ + (val) = (newval); \ + STAT_PERFMON2((env), cat, subcat, (val), (id)); \ + } while (0) +#define STAT_SET_VERB(env, cat, subcat, val, newval, id1, id2) \ + do { \ + (val) = (newval); \ + STAT_PERFMON3((env), cat, subcat, (val), (id1), (id2)); \ + } while (0) +#else +#define STAT(x) NOP_STATEMENT +#define STAT_ADJUST(env, cat, subcat, val, amt, id) NOP_STATEMENT +#define STAT_ADJUST_VERB(env, cat, subcat, val, amt, id1, id2) NOP_STATEMENT +#define STAT_INC(env, cat, subcat, val, id) NOP_STATEMENT +#define STAT_INC_VERB(env, cat, subcat, val, id1, id2) NOP_STATEMENT +#define STAT_DEC(env, cat, subcat, val, id) NOP_STATEMENT +#define STAT_SET(env, cat, subcat, val, newval, id) NOP_STATEMENT +#define STAT_SET_VERB(env, cat, subcat, val, newval, id1, id2) NOP_STATEMENT +#endif + +#if defined HAVE_SIMPLE_THREAD_TYPE +#define DB_THREADID_INIT(t) COMPQUIET((t), 0) +#else +#define DB_THREADID_INIT(t) memset(&(t), 0, sizeof(t)) +#endif + +/* + * These macros are used when an error condition is first noticed. They allow + * one to be notified (via e.g. DTrace, SystemTap, ...) when an error occurs + * deep inside DB, rather than when it is returned back through the API. + * + * The second actual argument to these is the second part of the error or + * warning event name. They work when 'errcode' is a symbolic name e.g. + * EINVAL or DB_LOCK_DEALOCK, not a variable. Noticing system call failures + * would be handled by tracing on syscall exit; when e.g., it returns < 0. + */ +#define ERR_ORIGIN(env, errcode) \ + (PERFMON0(env, error, errcode), errcode) + +#define ERR_ORIGIN_MSG(env, errcode, msg) \ + (PERFMON1(env, error, errcode, msg), errcode) + +#define WARNING_ORIGIN(env, errcode) \ + (PERFMON0(env, warning, errcode), errcode) + +/* + * Structure used for callback message aggregation. + * + * Display values in XXX_stat_print calls. + */ +typedef struct __db_msgbuf { + char *buf; /* Heap allocated buffer. */ + char *cur; /* Current end of message. */ + size_t len; /* Allocated length of buffer. */ +} DB_MSGBUF; +#define DB_MSGBUF_INIT(a) do { \ + (a)->buf = (a)->cur = NULL; \ + (a)->len = 0; \ +} while (0) +#define DB_MSGBUF_FLUSH(env, a) do { \ + if ((a)->buf != NULL) { \ + if ((a)->cur != (a)->buf) \ + __db_msg(env, "%s", (a)->buf); \ + __os_free(env, (a)->buf); \ + DB_MSGBUF_INIT(a); \ + } \ +} while (0) +#define DB_MSGBUF_REP_FLUSH(env, a, diag_msg, regular_msg) do { \ + if ((a)->buf != NULL) { \ + if ((a)->cur != (a)->buf && diag_msg) \ + __db_repmsg(env, "%s", (a)->buf); \ + if (regular_msg) \ + DB_MSGBUF_FLUSH(env, a); \ + else { \ + __os_free(env, (a)->buf); \ + DB_MSGBUF_INIT(a); \ + } \ + } \ +} while (0) +#define STAT_FMT(msg, fmt, type, v) do { \ + DB_MSGBUF __mb; \ + DB_MSGBUF_INIT(&__mb); \ + __db_msgadd(env, &__mb, fmt, (type)(v)); \ + __db_msgadd(env, &__mb, "\t%s", msg); \ + DB_MSGBUF_FLUSH(env, &__mb); \ +} while (0) +#define STAT_HEX(msg, v) \ + __db_msg(env, "%#lx\t%s", (u_long)(v), msg) +#define STAT_ISSET(msg, p) \ + __db_msg(env, "%sSet\t%s", (p) == NULL ? "!" : " ", msg) +#define STAT_LONG(msg, v) \ + __db_msg(env, "%ld\t%s", (long)(v), msg) +#define STAT_LSN(msg, lsnp) \ + __db_msg(env, "%lu/%lu\t%s", \ + (u_long)(lsnp)->file, (u_long)(lsnp)->offset, msg) +#define STAT_POINTER(msg, v) \ + __db_msg(env, "%#lx\t%s", P_TO_ULONG(v), msg) +#define STAT_STRING(msg, p) do { \ + const char *__p = p; /* p may be a function call. */ \ + __db_msg(env, "%s\t%s", __p == NULL ? "!Set" : __p, msg); \ +} while (0) +#define STAT_ULONG(msg, v) \ + __db_msg(env, "%lu\t%s", (u_long)(v), msg) + +/* + * The following macros are used to control how error and message strings are + * output by Berkeley DB. There are essentially three different controls + * available: + * - Default behavior is to output error strings with its unique identifier. + * - If HAVE_STRIPPED_MESSAGES is enabled, a unique identifier along with any + * parameters to the error string will be output. + * - If HAVE_LOCALIZATION is defined, and the '_()' macro is implemented, a + * gettext or ICU style translation will be done. + * + * Each new string that will be output should be wrapped in a DB_STR* macro. + * There are three versions of this macro for different scenarions: + * - DB_STR for strings that need an identifier, and don't have any argument. + * - DB_STR_A for strings that need an identifier, and have argument(s). + * - DB_STR_P for strings that don't need an identifier, and don't have + * arguments. + * + * Error message IDs are automatically assigned by dist/s_message_id script. + */ +#ifdef HAVE_LOCALIZATION +#define _(msg) msg /* Replace with localization function. */ +#else +#define _(msg) msg +#endif + +#ifdef HAVE_STRIPPED_MESSAGES +#define DB_STR_C(msg, fmt) fmt +#else +#define DB_STR_C(msg, fmt) _(msg) +#endif + +#define DB_MSGID(id) "BDB" id + +#define DB_STR(id, msg) DB_MSGID(id) " " DB_STR_C(msg, "") + +#define DB_STR_A(id, msg, fmt) DB_MSGID(id) " " DB_STR_C(msg, fmt) + +#define DB_STR_P(msg) _(msg) + +/* + * There are quite a few places in Berkeley DB where we want to initialize + * a DBT from a string or other random pointer type, using a length typed + * to size_t in most cases. This macro avoids a lot of casting. The macro + * comes in two flavors because we often want to clear the DBT first. + */ +#define DB_SET_DBT(dbt, d, s) do { \ + (dbt).data = (void *)(d); \ + (dbt).size = (u_int32_t)(s); \ +} while (0) +#define DB_INIT_DBT(dbt, d, s) do { \ + memset(&(dbt), 0, sizeof(dbt)); \ + DB_SET_DBT(dbt, d, s); \ +} while (0) + +/******************************************************* + * API return values + *******************************************************/ +/* + * Return values that are OK for each different call. Most calls have a + * standard 'return of 0 is only OK value', but some, like db->get have + * DB_NOTFOUND as a return value, but it really isn't an error. + */ +#define DB_RETOK_STD(ret) ((ret) == 0) +#define DB_RETOK_DBCDEL(ret) ((ret) == 0 || (ret) == DB_KEYEMPTY || \ + (ret) == DB_NOTFOUND) +#define DB_RETOK_DBCGET(ret) ((ret) == 0 || (ret) == DB_KEYEMPTY || \ + (ret) == DB_NOTFOUND) +#define DB_RETOK_DBCPUT(ret) ((ret) == 0 || (ret) == DB_KEYEXIST || \ + (ret) == DB_NOTFOUND) +#define DB_RETOK_DBDEL(ret) DB_RETOK_DBCDEL(ret) +#define DB_RETOK_DBGET(ret) DB_RETOK_DBCGET(ret) +#define DB_RETOK_DBPUT(ret) ((ret) == 0 || (ret) == DB_KEYEXIST) +#define DB_RETOK_EXISTS(ret) DB_RETOK_DBCGET(ret) +#define DB_RETOK_LGGET(ret) ((ret) == 0 || (ret) == DB_NOTFOUND) +#define DB_RETOK_MPGET(ret) ((ret) == 0 || (ret) == DB_PAGE_NOTFOUND) +#define DB_RETOK_REPPMSG(ret) ((ret) == 0 || \ + (ret) == DB_REP_IGNORE || \ + (ret) == DB_REP_ISPERM || \ + (ret) == DB_REP_NEWMASTER || \ + (ret) == DB_REP_NEWSITE || \ + (ret) == DB_REP_NOTPERM || \ + (ret) == DB_REP_WOULDROLLBACK) +#define DB_RETOK_REPMGR_LOCALSITE(ret) ((ret) == 0 || (ret) == DB_NOTFOUND) +#define DB_RETOK_REPMGR_START(ret) ((ret) == 0 || (ret) == DB_REP_IGNORE) +#define DB_RETOK_TXNAPPLIED(ret) ((ret) == 0 || \ + (ret) == DB_NOTFOUND || \ + (ret) == DB_TIMEOUT || \ + (ret) == DB_KEYEMPTY) + +/* Find a reasonable operation-not-supported error. */ +#ifdef EOPNOTSUPP +#define DB_OPNOTSUP EOPNOTSUPP +#else +#ifdef ENOTSUP +#define DB_OPNOTSUP ENOTSUP +#else +#define DB_OPNOTSUP EINVAL +#endif +#endif + +/******************************************************* + * Files. + *******************************************************/ +/* + * We use 1024 as the maximum path length. It's too hard to figure out what + * the real path length is, as it was traditionally stored in , + * and that file isn't always available. + */ +#define DB_MAXPATHLEN 1024 + +#define PATH_DOT "." /* Current working directory. */ + /* Path separator character(s). */ +#define PATH_SEPARATOR "\\/:" + +/******************************************************* + * Environment. + *******************************************************/ +/* Type passed to __db_appname(). */ +typedef enum { + DB_APP_NONE=0, /* No type (region). */ + DB_APP_DATA, /* Data file. */ + DB_APP_LOG, /* Log file. */ + DB_APP_META, /* Persistent metadata file. */ + DB_APP_RECOVER, /* We are in recovery. */ + DB_APP_TMP /* Temporary file. */ +} APPNAME; + +/* + * A set of macros to check if various functionality has been configured. + * + * ALIVE_ON The is_alive function is configured. + * CDB_LOCKING CDB product locking. + * CRYPTO_ON Security has been configured. + * LOCKING_ON Locking has been configured. + * LOGGING_ON Logging has been configured. + * MUTEX_ON Mutexes have been configured. + * MPOOL_ON Memory pool has been configured. + * REP_ON Replication has been configured. + * TXN_ON Transactions have been configured. + * + * REP_ON is more complex than most: if the BDB library was compiled without + * replication support, ENV->rep_handle will be NULL; if the BDB library has + * replication support, but it was not configured, the region reference will + * be NULL. + */ +#define ALIVE_ON(env) ((env)->dbenv->is_alive != NULL) +#define CDB_LOCKING(env) F_ISSET(env, ENV_CDB) +#define CRYPTO_ON(env) ((env)->crypto_handle != NULL) +#define LOCKING_ON(env) ((env)->lk_handle != NULL) +#define LOGGING_ON(env) ((env)->lg_handle != NULL) +#define MPOOL_ON(env) ((env)->mp_handle != NULL) +#define MUTEX_ON(env) ((env)->mutex_handle != NULL) +#define REP_ON(env) \ + ((env)->rep_handle != NULL && (env)->rep_handle->region != NULL) +#define TXN_ON(env) ((env)->tx_handle != NULL) + +/* + * STD_LOCKING Standard locking, that is, locking was configured and CDB + * was not. We do not do locking in off-page duplicate trees, + * so we check for that in the cursor first. + */ +#define STD_LOCKING(dbc) \ + (!F_ISSET(dbc, DBC_OPD) && \ + !CDB_LOCKING((dbc)->env) && LOCKING_ON((dbc)->env)) + +/* + * IS_RECOVERING: The system is running recovery. + */ +#define IS_RECOVERING(env) \ + (LOGGING_ON(env) && F_ISSET((env)->lg_handle, DBLOG_RECOVER)) + +/* Initialization methods are often illegal before/after open is called. */ +#define ENV_ILLEGAL_AFTER_OPEN(env, name) \ + if (F_ISSET((env), ENV_OPEN_CALLED)) \ + return (__db_mi_open(env, name, 1)); +#define ENV_ILLEGAL_BEFORE_OPEN(env, name) \ + if (!F_ISSET((env), ENV_OPEN_CALLED)) \ + return (__db_mi_open(env, name, 0)); + +/* We're not actually user hostile, honest. */ +#define ENV_REQUIRES_CONFIG(env, handle, i, flags) \ + if (handle == NULL) \ + return (__env_not_config(env, i, flags)); +#define ENV_REQUIRES_CONFIG_XX(env, handle, i, flags) \ + if ((env)->handle->region == NULL) \ + return (__env_not_config(env, i, flags)); +#define ENV_NOT_CONFIGURED(env, handle, i, flags) \ + if (F_ISSET((env), ENV_OPEN_CALLED)) \ + ENV_REQUIRES_CONFIG(env, handle, i, flags) + +#define ENV_ENTER_RET(env, ip, ret) do { \ + ret = 0; \ + PANIC_CHECK_RET(env, ret); \ + if (ret == 0) { \ + if ((env)->thr_hashtab == NULL) \ + ip = NULL; \ + else \ + ret = __env_set_state(env, &(ip), THREAD_ACTIVE);\ + } \ +} while (0) + +#define ENV_ENTER(env, ip) do { \ + int __ret; \ + ip = NULL; \ + ENV_ENTER_RET(env, ip, __ret); \ + if (__ret != 0) \ + return (__ret); \ +} while (0) + +#define FAILCHK_THREAD(env, ip) do { \ + if ((ip) != NULL) \ + (ip)->dbth_state = THREAD_FAILCHK; \ +} while (0) + +#define ENV_GET_THREAD_INFO(env, ip) ENV_ENTER(env, ip) + +#ifdef DIAGNOSTIC +#define ENV_LEAVE(env, ip) do { \ + if ((ip) != NULL) { \ + DB_ASSERT(env, ((ip)->dbth_state == THREAD_ACTIVE || \ + (ip)->dbth_state == THREAD_FAILCHK)); \ + (ip)->dbth_state = THREAD_OUT; \ + } \ +} while (0) +#else +#define ENV_LEAVE(env, ip) do { \ + if ((ip) != NULL) \ + (ip)->dbth_state = THREAD_OUT; \ +} while (0) +#endif +#ifdef DIAGNOSTIC +#define CHECK_THREAD(env) do { \ + if ((env)->thr_hashtab != NULL) \ + (void)__env_set_state(env, NULL, THREAD_VERIFY); \ +} while (0) +#ifdef HAVE_STATISTICS +#define CHECK_MTX_THREAD(env, mtx) do { \ + if (mtx->alloc_id != MTX_MUTEX_REGION && \ + mtx->alloc_id != MTX_ENV_REGION && \ + mtx->alloc_id != MTX_APPLICATION) \ + CHECK_THREAD(env); \ +} while (0) +#else +#define CHECK_MTX_THREAD(env, mtx) NOP_STATEMENT +#endif +#else +#define CHECK_THREAD(env) NOP_STATEMENT +#define CHECK_MTX_THREAD(env, mtx) NOP_STATEMENT +#endif + +typedef enum { + THREAD_SLOT_NOT_IN_USE=0, + THREAD_OUT, + THREAD_ACTIVE, + THREAD_BLOCKED, + THREAD_BLOCKED_DEAD, + THREAD_FAILCHK, + THREAD_VERIFY +} DB_THREAD_STATE; + +typedef struct __pin_list { + roff_t b_ref; /* offset to buffer. */ + int region; /* region containing buffer. */ +} PIN_LIST; +#define PINMAX 4 + +struct __db_thread_info { /* SHARED */ + pid_t dbth_pid; + db_threadid_t dbth_tid; + DB_THREAD_STATE dbth_state; + SH_TAILQ_ENTRY dbth_links; + /* + * The next field contains the (process local) reference to the XA + * transaction currently associated with this thread of control. + */ + SH_TAILQ_HEAD(__dbth_xatxn) dbth_xatxn; + u_int32_t dbth_xa_status; + /* + * The following fields track which buffers this thread of + * control has pinned in the mpool buffer cache. + */ + u_int16_t dbth_pincount; /* Number of pins for this thread. */ + u_int16_t dbth_pinmax; /* Number of slots allocated. */ + roff_t dbth_pinlist; /* List of pins. */ + PIN_LIST dbth_pinarray[PINMAX]; /* Initial array of slots. */ +#ifdef DIAGNOSTIC + roff_t dbth_locker; /* Current locker for this thread. */ + u_int32_t dbth_check_off; /* Count of number of LOCK_OFF calls. */ +#endif +}; +#ifdef DIAGNOSTIC +#define LOCK_CHECK_OFF(ip) if ((ip) != NULL) \ + (ip)->dbth_check_off++ + +#define LOCK_CHECK_ON(ip) if ((ip) != NULL) \ + (ip)->dbth_check_off-- + +#define LOCK_CHECK(dbc, pgno, mode, type) \ + DB_ASSERT((dbc)->dbp->env, (dbc)->locker == NULL || \ + __db_haslock((dbc)->dbp->env, \ + (dbc)->locker, (dbc)->dbp->mpf, pgno, mode, type) == 0) +#else +#define LOCK_CHECK_OFF(ip) NOP_STATEMENT +#define LOCK_CHECK_ON(ip) NOP_STATEMENT +#define LOCK_CHECK(dbc, pgno, mode) NOP_STATEMENT +#endif + +typedef struct __env_thread_info { + u_int32_t thr_count; + u_int32_t thr_init; + u_int32_t thr_max; + u_int32_t thr_nbucket; + roff_t thr_hashoff; +} THREAD_INFO; + +#define DB_EVENT(env, e, einfo) do { \ + DB_ENV *__dbenv = (env)->dbenv; \ + if (__dbenv->db_event_func != NULL) \ + __dbenv->db_event_func(__dbenv, e, einfo); \ +} while (0) + +typedef struct __flag_map { + u_int32_t inflag, outflag; +} FLAG_MAP; + +typedef struct __db_backup_handle { + int (*open) __P((DB_ENV *, const char *, const char *, void **)); + int (*write) __P((DB_ENV *, + u_int32_t, u_int32_t, u_int32_t, u_int8_t *, void *)); + int (*close) __P((DB_ENV *, const char *, void *)); + u_int32_t size; + u_int32_t read_count; + u_int32_t read_sleep; +#define BACKUP_WRITE_DIRECT 0x0001 + int flags; +} DB_BACKUP; + +/* + * Internal database environment structure. + * + * This is the private database environment handle. The public environment + * handle is the DB_ENV structure. The library owns this structure, the user + * owns the DB_ENV structure. The reason there are two structures is because + * the user's configuration outlives any particular DB_ENV->open call, and + * separate structures allows us to easily discard internal information without + * discarding the user's configuration. + */ +struct __env { + DB_ENV *dbenv; /* Linked DB_ENV structure */ + + /* + * The ENV structure can be used concurrently, so field access is + * protected. + */ + db_mutex_t mtx_env; /* ENV structure mutex */ + + /* + * Some fields are included in the ENV structure rather than in the + * DB_ENV structure because they are only set as arguments to the + * DB_ENV->open method. In other words, because of the historic API, + * not for any rational reason. + * + * Arguments to DB_ENV->open. + */ + char *db_home; /* Database home */ + u_int32_t open_flags; /* Flags */ + int db_mode; /* Default open permissions */ + + pid_t pid_cache; /* Cached process ID */ + + DB_FH *lockfhp; /* fcntl(2) locking file handle */ + + DB_LOCKER *env_lref; /* Locker in non-threaded handles */ + + DB_DISTAB recover_dtab; /* Dispatch table for recover funcs */ + + int dir_mode; /* Intermediate directory perms. */ + +#define ENV_DEF_DATA_LEN 100 + u_int32_t data_len; /* Data length in __db_prbytes. */ + + /* Thread tracking */ + u_int32_t thr_nbucket; /* Number of hash buckets */ + DB_HASHTAB *thr_hashtab; /* Hash table of DB_THREAD_INFO */ + + /* + * List of open DB handles for this ENV, used for cursor + * adjustment. Must be protected for multi-threaded support. + */ + db_mutex_t mtx_dblist; + int db_ref; /* DB handle reference count */ + TAILQ_HEAD(__dblist, __db) dblist; + + /* + * List of open file handles for this ENV. Must be protected + * for multi-threaded support. + */ + TAILQ_HEAD(__fdlist, __fh_t) fdlist; + + db_mutex_t mtx_mt; /* Mersenne Twister mutex */ + int mti; /* Mersenne Twister index */ + u_long *mt; /* Mersenne Twister state vector */ + + DB_CIPHER *crypto_handle; /* Crypto handle */ + DB_LOCKTAB *lk_handle; /* Lock handle */ + DB_LOG *lg_handle; /* Log handle */ + DB_MPOOL *mp_handle; /* Mpool handle */ + DB_MUTEXMGR *mutex_handle; /* Mutex handle */ + DB_REP *rep_handle; /* Replication handle */ + DB_TXNMGR *tx_handle; /* Txn handle */ + + DB_BACKUP *backup_handle; /* database copy configuration. */ + + /* + * XA support. + */ + int xa_rmid; /* XA Resource Manager ID */ + int xa_ref; /* XA Reference count */ + TAILQ_ENTRY(__env) links; /* XA environments */ + + /* Application callback to copy data to/from a custom data source */ +#define DB_USERCOPY_GETDATA 0x0001 +#define DB_USERCOPY_SETDATA 0x0002 + int (*dbt_usercopy) + __P((DBT *, u_int32_t, void *, u_int32_t, u_int32_t)); + + int (*log_verify_wrap) __P((ENV *, const char *, u_int32_t, + const char *, const char *, time_t, time_t, u_int32_t, u_int32_t, + u_int32_t, u_int32_t, int, int)); + + REGINFO *reginfo; /* REGINFO structure reference */ + +#define DB_TEST_ELECTINIT 1 /* after __rep_elect_init */ +#define DB_TEST_ELECTVOTE1 2 /* after sending VOTE1 */ +#define DB_TEST_NO_PAGES 3 /* before sending PAGE */ +#define DB_TEST_POSTDESTROY 4 /* after destroy op */ +#define DB_TEST_POSTLOG 5 /* after logging all pages */ +#define DB_TEST_POSTLOGMETA 6 /* after logging meta in btree */ +#define DB_TEST_POSTOPEN 7 /* after __os_open */ +#define DB_TEST_POSTSYNC 8 /* after syncing the log */ +#define DB_TEST_PREDESTROY 9 /* before destroy op */ +#define DB_TEST_PREOPEN 10 /* before __os_open */ +#define DB_TEST_REPMGR_PERM 11 /* repmgr perm/archiving tests */ +#define DB_TEST_SUBDB_LOCKS 12 /* subdb locking tests */ + int test_abort; /* Abort value for testing */ + int test_check; /* Checkpoint value for testing */ + int test_copy; /* Copy value for testing */ + +#define ENV_CDB 0x00000001 /* DB_INIT_CDB */ +#define ENV_DBLOCAL 0x00000002 /* Environment for a private DB */ +#define ENV_LITTLEENDIAN 0x00000004 /* Little endian system. */ +#define ENV_LOCKDOWN 0x00000008 /* DB_LOCKDOWN set */ +#define ENV_NO_OUTPUT_SET 0x00000010 /* No output channel set */ +#define ENV_OPEN_CALLED 0x00000020 /* DB_ENV->open called */ +#define ENV_PRIVATE 0x00000040 /* DB_PRIVATE set */ +#define ENV_RECOVER_FATAL 0x00000080 /* Doing fatal recovery in env */ +#define ENV_REF_COUNTED 0x00000100 /* Region references this handle */ +#define ENV_SYSTEM_MEM 0x00000200 /* DB_SYSTEM_MEM set */ +#define ENV_THREAD 0x00000400 /* DB_THREAD set */ +#define ENV_FORCE_TXN_BULK 0x00000800 /* Txns use bulk mode-for testing */ + u_int32_t flags; +}; + +/******************************************************* + * Database Access Methods. + *******************************************************/ +/* + * DB_IS_THREADED -- + * The database handle is free-threaded (was opened with DB_THREAD). + */ +#define DB_IS_THREADED(dbp) \ + ((dbp)->mutex != MUTEX_INVALID) + +/* Initialization methods are often illegal before/after open is called. */ +#define DB_ILLEGAL_AFTER_OPEN(dbp, name) \ + if (F_ISSET((dbp), DB_AM_OPEN_CALLED)) \ + return (__db_mi_open((dbp)->env, name, 1)); +#define DB_ILLEGAL_BEFORE_OPEN(dbp, name) \ + if (!F_ISSET((dbp), DB_AM_OPEN_CALLED)) \ + return (__db_mi_open((dbp)->env, name, 0)); +/* Some initialization methods are illegal if environment isn't local. */ +#define DB_ILLEGAL_IN_ENV(dbp, name) \ + if (!F_ISSET((dbp)->env, ENV_DBLOCAL)) \ + return (__db_mi_env((dbp)->env, name)); +#define DB_ILLEGAL_METHOD(dbp, flags) { \ + int __ret; \ + if ((__ret = __dbh_am_chk(dbp, flags)) != 0) \ + return (__ret); \ +} + +/* + * Common DBC->internal fields. Each access method adds additional fields + * to this list, but the initial fields are common. + */ +#define __DBC_INTERNAL \ + DBC *opd; /* Off-page duplicate cursor. */\ + DBC *pdbc; /* Pointer to parent cursor. */ \ + \ + void *page; /* Referenced page. */ \ + u_int32_t part; /* Partition number. */ \ + db_pgno_t root; /* Tree root. */ \ + db_pgno_t pgno; /* Referenced page number. */ \ + db_indx_t indx; /* Referenced key item index. */\ + \ + /* Streaming -- cache last position. */ \ + db_pgno_t stream_start_pgno; /* Last start pgno. */ \ + u_int32_t stream_off; /* Current offset. */ \ + db_pgno_t stream_curr_pgno; /* Current overflow page. */ \ + \ + DB_LOCK lock; /* Cursor lock. */ \ + db_lockmode_t lock_mode; /* Lock mode. */ + +struct __dbc_internal { + __DBC_INTERNAL +}; + +/* Actions that __db_master_update can take. */ +typedef enum { MU_REMOVE, MU_RENAME, MU_OPEN, MU_MOVE } mu_action; + +/* + * Access-method-common macro for determining whether a cursor + * has been initialized. + */ +#ifdef HAVE_PARTITION +#define IS_INITIALIZED(dbc) (DB_IS_PARTITIONED((dbc)->dbp) ? \ + ((PART_CURSOR *)(dbc)->internal)->sub_cursor != NULL && \ + ((PART_CURSOR *)(dbc)->internal)->sub_cursor-> \ + internal->pgno != PGNO_INVALID : \ + (dbc)->internal->pgno != PGNO_INVALID) +#else +#define IS_INITIALIZED(dbc) ((dbc)->internal->pgno != PGNO_INVALID) +#endif + +/* Free the callback-allocated buffer, if necessary, hanging off of a DBT. */ +#define FREE_IF_NEEDED(env, dbt) \ + if (F_ISSET((dbt), DB_DBT_APPMALLOC)) { \ + __os_ufree((env), (dbt)->data); \ + F_CLR((dbt), DB_DBT_APPMALLOC); \ + } + +/* + * Use memory belonging to object "owner" to return the results of + * any no-DBT-flag get ops on cursor "dbc". + */ +#define SET_RET_MEM(dbc, owner) \ + do { \ + (dbc)->rskey = &(owner)->my_rskey; \ + (dbc)->rkey = &(owner)->my_rkey; \ + (dbc)->rdata = &(owner)->my_rdata; \ + } while (0) + +/* Use the return-data memory src is currently set to use in dest as well. */ +#define COPY_RET_MEM(src, dest) \ + do { \ + (dest)->rskey = (src)->rskey; \ + (dest)->rkey = (src)->rkey; \ + (dest)->rdata = (src)->rdata; \ + } while (0) + +/* Reset the returned-memory pointers to their defaults. */ +#define RESET_RET_MEM(dbc) \ + do { \ + (dbc)->rskey = &(dbc)->my_rskey; \ + (dbc)->rkey = &(dbc)->my_rkey; \ + (dbc)->rdata = &(dbc)->my_rdata; \ + } while (0) + +#define COMPACT_TRUNCATE(c_data) do { \ + if (c_data->compact_truncate > 1) \ + c_data->compact_truncate--; \ +} while (0) + +/******************************************************* + * Mpool. + *******************************************************/ +/* + * File types for DB access methods. Negative numbers are reserved to DB. + */ +#define DB_FTYPE_SET -1 /* Call pgin/pgout functions. */ +#define DB_FTYPE_NOTSET 0 /* Don't call... */ +#define DB_LSN_OFF_NOTSET -1 /* Not yet set. */ +#define DB_CLEARLEN_NOTSET UINT32_MAX /* Not yet set. */ + +/* Structure used as the DB pgin/pgout pgcookie. */ +typedef struct __dbpginfo { + u_int32_t db_pagesize; /* Underlying page size. */ + u_int32_t flags; /* Some DB_AM flags needed. */ + DBTYPE type; /* DB type */ +} DB_PGINFO; + +/******************************************************* + * Log. + *******************************************************/ +/* Initialize an LSN to 'zero'. */ +#define ZERO_LSN(LSN) do { \ + (LSN).file = 0; \ + (LSN).offset = 0; \ +} while (0) +#define IS_ZERO_LSN(LSN) ((LSN).file == 0 && (LSN).offset == 0) + +#define IS_INIT_LSN(LSN) ((LSN).file == 1 && (LSN).offset == 0) +#define INIT_LSN(LSN) do { \ + (LSN).file = 1; \ + (LSN).offset = 0; \ +} while (0) + +#define MAX_LSN(LSN) do { \ + (LSN).file = UINT32_MAX; \ + (LSN).offset = UINT32_MAX; \ +} while (0) +#define IS_MAX_LSN(LSN) \ + ((LSN).file == UINT32_MAX && (LSN).offset == UINT32_MAX) + +/* If logging is turned off, smash the lsn. */ +#define LSN_NOT_LOGGED(LSN) do { \ + (LSN).file = 0; \ + (LSN).offset = 1; \ +} while (0) +#define IS_NOT_LOGGED_LSN(LSN) \ + ((LSN).file == 0 && (LSN).offset == 1) + +/* + * LOG_COMPARE -- compare two LSNs. + */ + +#define LOG_COMPARE(lsn0, lsn1) \ + ((lsn0)->file != (lsn1)->file ? \ + ((lsn0)->file < (lsn1)->file ? -1 : 1) : \ + ((lsn0)->offset != (lsn1)->offset ? \ + ((lsn0)->offset < (lsn1)->offset ? -1 : 1) : 0)) + +/******************************************************* + * Txn. + *******************************************************/ +#define DB_NONBLOCK(C) ((C)->txn != NULL && F_ISSET((C)->txn, TXN_NOWAIT)) +#define NOWAIT_FLAG(txn) \ + ((txn) != NULL && F_ISSET((txn), TXN_NOWAIT) ? DB_LOCK_NOWAIT : 0) +#define IS_REAL_TXN(txn) \ + ((txn) != NULL && !F_ISSET(txn, TXN_FAMILY)) +#define IS_SUBTRANSACTION(txn) \ + ((txn) != NULL && (txn)->parent != NULL) + +/* Checks for existence of an XA transaction in access method interfaces. */ +#define XA_CHECK_TXN(ip, txn) \ + if ((ip) != NULL && (txn) == NULL) { \ + (txn) = SH_TAILQ_FIRST(&(ip)->dbth_xatxn, __db_txn); \ + DB_ASSERT(env, txn == NULL || \ + txn->xa_thr_status == TXN_XA_THREAD_ASSOCIATED); \ + } + +/* Ensure that there is no XA transaction active. */ +#define XA_NO_TXN(ip, retval) { \ + DB_TXN *__txn; \ + retval = 0; \ + if ((ip) != NULL) { \ + __txn = SH_TAILQ_FIRST(&(ip)->dbth_xatxn, __db_txn); \ + if (__txn != NULL && \ + __txn->xa_thr_status == TXN_XA_THREAD_ASSOCIATED) \ + retval = EINVAL; \ + } \ +} + +/******************************************************* + * Crypto. + *******************************************************/ +#define DB_IV_BYTES 16 /* Bytes per IV */ +#define DB_MAC_KEY 20 /* Bytes per MAC checksum */ + +/******************************************************* + * Compression + *******************************************************/ +#define CMP_INT_SPARE_VAL 0xFC /* Smallest byte value that the integer + compression algorithm doesn't use */ + +#if defined(__cplusplus) +} +#endif + +/******************************************************* + * Remaining general DB includes. + *******************************************************/ + + +#include "dbinc/globals.h" +#include "dbinc/clock.h" +#include "dbinc/debug.h" +#include "dbinc/region.h" +#include "dbinc_auto/env_ext.h" +#include "dbinc/mutex.h" +#ifdef HAVE_REPLICATION_THREADS +#include "dbinc/repmgr.h" +#endif +#include "dbinc/rep.h" +#include "dbinc/os.h" +#include "dbinc_auto/clib_ext.h" +#include "dbinc_auto/common_ext.h" + +/******************************************************* + * Remaining Log. + * These need to be defined after the general includes + * because they need rep.h from above. + *******************************************************/ +/* + * Test if the environment is currently logging changes. If we're in recovery + * or we're a replication client, we don't need to log changes because they're + * already in the log, even though we have a fully functional log system. + */ +#define DBENV_LOGGING(env) \ + (LOGGING_ON(env) && !IS_REP_CLIENT(env) && (!IS_RECOVERING(env))) + +/* + * Test if we need to log a change. By default, we don't log operations without + * associated transactions, unless DIAGNOSTIC, DEBUG_ROP or DEBUG_WOP are on. + * This is because we want to get log records for read/write operations, and, if + * we are trying to debug something, more information is always better. + * + * The DBC_RECOVER flag is set when we're in abort, as well as during recovery; + * thus DBC_LOGGING may be false for a particular dbc even when DBENV_LOGGING + * is true. + * + * We explicitly use LOGGING_ON/IS_REP_CLIENT here because we don't want to pull + * in the log headers, which IS_RECOVERING (and thus DBENV_LOGGING) rely on, and + * because DBC_RECOVER should be set anytime IS_RECOVERING would be true. + * + * If we're not in recovery (master - doing an abort or a client applying + * a txn), then a client's only path through here is on an internal + * operation, and a master's only path through here is a transactional + * operation. Detect if either is not the case. + */ +#if defined(DIAGNOSTIC) || defined(DEBUG_ROP) || defined(DEBUG_WOP) +#define DBC_LOGGING(dbc) __dbc_logging(dbc) +#else +#define DBC_LOGGING(dbc) \ + ((dbc)->txn != NULL && LOGGING_ON((dbc)->env) && \ + !F_ISSET((dbc), DBC_RECOVER) && !IS_REP_CLIENT((dbc)->env)) +#endif + +#endif /* !_DB_INT_H_ */ diff -r 000000000000 -r a1985f14b030 util/db_dump.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/util/db_dump.c Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,556 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 1996, 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + * $Id$ + */ + +#include "db_config.h" + +#include "db_int.h" +#include "dbinc/db_page.h" +#include "dbinc/db_am.h" + +#ifndef lint +static const char copyright[] = + "Copyright (c) 1996, 2012 Oracle and/or its affiliates. All rights reserved.\n"; +#endif + +int db_init __P((DB_ENV *, char *, int, u_int32_t, int *)); +int dump_sub __P((DB_ENV *, DB *, char *, int, int)); +int main __P((int, char *[])); +int show_subs __P((DB *)); +int usage __P((void)); +int version_check __P((void)); + +const char *progname; + +int +main(argc, argv) + int argc; + char *argv[]; +{ + extern char *optarg; + extern int optind; + DB_ENV *dbenv; + DB *dbp; + db_pgno_t first, last; + u_int32_t cache; + int ch; + int exitval, keyflag, lflag, mflag, nflag, pflag, sflag, private; + int ret, Rflag, rflag, resize; + char *data_len, *dbname, *dopt, *filename, *home, *passwd; + + if ((progname = __db_rpath(argv[0])) == NULL) + progname = argv[0]; + else + ++progname; + + if ((ret = version_check()) != 0) + return (ret); + + dbenv = NULL; + dbp = NULL; + exitval = lflag = mflag = nflag = pflag = rflag = Rflag = sflag = 0; + first = last = PGNO_INVALID; + keyflag = 0; + cache = MEGABYTE; + private = 0; + data_len = dbname = dopt = filename = home = passwd = NULL; + while ((ch = getopt(argc, argv, "d:D:f:F:h:klL:m:NpP:rRs:V")) != EOF) + switch (ch) { + case 'd': + dopt = optarg; + break; + case 'D': + data_len = optarg; + break; + case 'f': + if (freopen(optarg, "w", stdout) == NULL) { + fprintf(stderr, DB_STR_A("5108", + "%s: %s: reopen: %s\n", "%s %s %s\n"), + progname, optarg, strerror(errno)); + return (EXIT_FAILURE); + } + break; + case 'F': + first = (db_pgno_t)strtoul(optarg, NULL, 10); + break; + case 'h': + home = optarg; + break; + case 'k': + keyflag = 1; + break; + case 'l': + lflag = 1; + break; + case 'L': + last = (db_pgno_t)strtoul(optarg, NULL, 10); + break; + case 'm': + mflag = 1; + dbname = optarg; + break; + case 'N': + nflag = 1; + break; + case 'P': + if (passwd != NULL) { + fprintf(stderr, DB_STR("5130", + "Password may not be specified twice")); + free(passwd); + return (EXIT_FAILURE); + } + passwd = strdup(optarg); + memset(optarg, 0, strlen(optarg)); + if (passwd == NULL) { + fprintf(stderr, DB_STR_A("5109", + "%s: strdup: %s\n", "%s %s\n"), + progname, strerror(errno)); + return (EXIT_FAILURE); + } + break; + case 'p': + pflag = 1; + break; + case 's': + sflag = 1; + dbname = optarg; + break; + case 'R': + Rflag = 1; + /* DB_AGGRESSIVE requires DB_SALVAGE */ + /* FALLTHROUGH */ + case 'r': + rflag = 1; + break; + case 'V': + printf("%s\n", db_version(NULL, NULL, NULL)); + return (EXIT_SUCCESS); + case '?': + default: + return (usage()); + } + argc -= optind; + argv += optind; + + /* + * A file name must be specified, unless we're looking for an in-memory + * db, in which case it must not. + */ + if (argc == 0 && mflag) + filename = NULL; + else if (argc == 1 && !mflag) + filename = argv[0]; + else + return (usage()); + + if (dopt != NULL && pflag) { + fprintf(stderr, DB_STR_A("5110", + "%s: the -d and -p options may not both be specified\n", + "%s\n"), progname); + return (EXIT_FAILURE); + } + if (lflag && sflag) { + fprintf(stderr, DB_STR_A("5111", + "%s: the -l and -s options may not both be specified\n", + "%s\n"), progname); + return (EXIT_FAILURE); + } + if ((lflag || sflag) && mflag) { + fprintf(stderr, DB_STR_A("5112", + "%s: the -m option may not be specified with -l or -s\n", + "%s\n"), progname); + return (EXIT_FAILURE); + } + + if (keyflag && rflag) { + fprintf(stderr, DB_STR_A("5113", + "%s: the -k and -r or -R options may not both be specified\n", + "%s\n"), progname); + return (EXIT_FAILURE); + } + + if (sflag && rflag) { + fprintf(stderr, DB_STR_A("5114", + "%s: the -r or R options may not be specified with -s\n", + "%s\n"), progname); + return (EXIT_FAILURE); + } + + /* Handle possible interruptions. */ + __db_util_siginit(); + + /* + * Create an environment object and initialize it for error + * reporting. + */ +retry: if ((ret = db_env_create(&dbenv, 0)) != 0) { + fprintf(stderr, + "%s: db_env_create: %s\n", progname, db_strerror(ret)); + goto err; + } + + dbenv->set_errfile(dbenv, stderr); + dbenv->set_errpfx(dbenv, progname); + if (data_len != NULL) + (void)dbenv->set_data_len(dbenv, (u_int32_t)atol(data_len)); + + if (nflag) { + if ((ret = dbenv->set_flags(dbenv, DB_NOLOCKING, 1)) != 0) { + dbenv->err(dbenv, ret, "set_flags: DB_NOLOCKING"); + goto err; + } + if ((ret = dbenv->set_flags(dbenv, DB_NOPANIC, 1)) != 0) { + dbenv->err(dbenv, ret, "set_flags: DB_NOPANIC"); + goto err; + } + } + if (passwd != NULL && (ret = dbenv->set_encrypt(dbenv, + passwd, DB_ENCRYPT_AES)) != 0) { + dbenv->err(dbenv, ret, "set_passwd"); + goto err; + } + + /* Initialize the environment. */ + if (db_init(dbenv, home, rflag, cache, &private) != 0) + goto err; + + /* Create the DB object and open the file. */ + if ((ret = db_create(&dbp, dbenv, 0)) != 0) { + dbenv->err(dbenv, ret, "db_create"); + goto err; + } + +#if 0 + Set application-specific btree compression functions here. For example: + if ((ret = dbp->set_bt_compress( + dbp, local_compress_func, local_decompress_func)) != 0) { + dbp->err(dbp, ret, "DB->set_bt_compress"); + goto err; + } +#endif + + /* + * If we're salvaging, don't do an open; it might not be safe. + * Dispatch now into the salvager. + */ + if (rflag) { + /* The verify method is a destructor. */ + ret = dbp->verify(dbp, filename, dbname, stdout, + DB_SALVAGE | + (Rflag ? DB_AGGRESSIVE : 0) | + (pflag ? DB_PRINTABLE : 0)); + dbp = NULL; + if (ret != 0) + goto err; + goto done; + } + + if ((ret = dbp->open(dbp, NULL, + filename, dbname, DB_UNKNOWN, DB_RDWRMASTER|DB_RDONLY, 0)) != 0) { + dbp->err(dbp, ret, DB_STR_A("5115", "open: %s", "%s"), + filename == NULL ? dbname : filename); + goto err; + } + if (private != 0) { + if ((ret = __db_util_cache(dbp, &cache, &resize)) != 0) + goto err; + if (resize) { + (void)dbp->close(dbp, 0); + dbp = NULL; + + (void)dbenv->close(dbenv, 0); + dbenv = NULL; + goto retry; + } + } + + if (dopt != NULL) { + if ((ret = + __db_dumptree(dbp, NULL, dopt, NULL, first, last)) != 0) { + dbp->err(dbp, ret, "__db_dumptree: %s", filename); + goto err; + } + } else if (lflag) { + if (dbp->get_multiple(dbp)) { + if (show_subs(dbp)) + goto err; + } else { + dbp->errx(dbp, DB_STR_A("5116", + "%s: does not contain multiple databases", "%s"), + filename); + goto err; + } + } else { + if (dbname == NULL && dbp->get_multiple(dbp)) { + if (dump_sub(dbenv, dbp, filename, pflag, keyflag)) + goto err; + } else + if (dbp->dump(dbp, NULL, + __db_pr_callback, stdout, pflag, keyflag)) + goto err; + } + + if (0) { +err: exitval = 1; + } +done: if (dbp != NULL && (ret = dbp->close(dbp, 0)) != 0) { + exitval = 1; + dbenv->err(dbenv, ret, DB_STR("5117", "close")); + } + if (dbenv != NULL && (ret = dbenv->close(dbenv, 0)) != 0) { + exitval = 1; + fprintf(stderr, + "%s: dbenv->close: %s\n", progname, db_strerror(ret)); + } + + if (passwd != NULL) + free(passwd); + + /* Resend any caught signal. */ + __db_util_sigresend(); + + return (exitval == 0 ? EXIT_SUCCESS : EXIT_FAILURE); +} + +/* + * db_init -- + * Initialize the environment. + */ +int +db_init(dbenv, home, is_salvage, cache, is_privatep) + DB_ENV *dbenv; + char *home; + int is_salvage; + u_int32_t cache; + int *is_privatep; +{ + int ret; + + /* + * Try and use the underlying environment when opening a database. + * We wish to use the buffer pool so our information is as up-to-date + * as possible, even if the mpool cache hasn't been flushed. + * + * If we are not doing a salvage, we want to join the environment; + * if a locking system is present, this will let us use it and be + * safe to run concurrently with other threads of control. (We never + * need to use transactions explicitly, as we're read-only.) Note + * that in CDB, too, this will configure our environment + * appropriately, and our cursors will (correctly) do locking as CDB + * read cursors. + * + * If we are doing a salvage, the verification code will protest + * if we initialize transactions, logging, or locking; do an + * explicit DB_INIT_MPOOL to try to join any existing environment + * before we create our own. + */ + *is_privatep = 0; + if ((ret = dbenv->open(dbenv, home, + DB_USE_ENVIRON | (is_salvage ? DB_INIT_MPOOL : 0), 0)) == 0) + return (0); + if (ret == DB_VERSION_MISMATCH) + goto err; + + /* + * An environment is required because we may be trying to look at + * databases in directories other than the current one. We could + * avoid using an environment iff the -h option wasn't specified, + * but that seems like more work than it's worth. + * + * No environment exists (or, at least no environment that includes + * an mpool region exists). Create one, but make it private so that + * no files are actually created. + */ + *is_privatep = 1; + if ((ret = dbenv->set_cachesize(dbenv, 0, cache, 1)) == 0 && + (ret = dbenv->open(dbenv, home, + DB_CREATE | DB_INIT_MPOOL | DB_PRIVATE | DB_USE_ENVIRON, 0)) == 0) + return (0); + + /* An environment is required. */ +err: dbenv->err(dbenv, ret, "DB_ENV->open"); + return (1); +} + +/* + * dump_sub -- + * Dump out the records for a DB containing subdatabases. + */ +int +dump_sub(dbenv, parent_dbp, parent_name, pflag, keyflag) + DB_ENV *dbenv; + DB *parent_dbp; + char *parent_name; + int pflag, keyflag; +{ + DB *dbp; + DBC *dbcp; + DBT key, data; + int ret; + char *subdb; + + /* + * Get a cursor and step through the database, dumping out each + * subdatabase. + */ + if ((ret = parent_dbp->cursor(parent_dbp, NULL, &dbcp, 0)) != 0) { + dbenv->err(dbenv, ret, "DB->cursor"); + return (1); + } + + memset(&key, 0, sizeof(key)); + memset(&data, 0, sizeof(data)); + while ((ret = dbcp->get(dbcp, &key, &data, + DB_IGNORE_LEASE | DB_NEXT)) == 0) { + /* Nul terminate the subdatabase name. */ + if ((subdb = malloc(key.size + 1)) == NULL) { + dbenv->err(dbenv, ENOMEM, NULL); + return (1); + } + memcpy(subdb, key.data, key.size); + subdb[key.size] = '\0'; + + /* Create the DB object and open the file. */ + if ((ret = db_create(&dbp, dbenv, 0)) != 0) { + dbenv->err(dbenv, ret, "db_create"); + free(subdb); + return (1); + } + +#if 0 + Set application-specific btree compression functions here. + For example: + + if ((ret = dbp->set_bt_compress( + dbp, local_compress_func, local_decompress_func)) != 0) { + dbp->err(dbp, ret, "DB->set_bt_compress"); + goto err; + } +#endif + + if ((ret = dbp->open(dbp, NULL, + parent_name, subdb, DB_UNKNOWN, DB_RDONLY, 0)) != 0) + dbp->err(dbp, ret, + "DB->open: %s:%s", parent_name, subdb); + if (ret == 0 && dbp->dump( + dbp, subdb, __db_pr_callback, stdout, pflag, keyflag)) + ret = 1; + (void)dbp->close(dbp, 0); + free(subdb); + if (ret != 0) + return (1); + } + if (ret != DB_NOTFOUND) { + parent_dbp->err(parent_dbp, ret, "DBcursor->get"); + return (1); + } + + if ((ret = dbcp->close(dbcp)) != 0) { + parent_dbp->err(parent_dbp, ret, "DBcursor->close"); + return (1); + } + + return (0); +} + +/* + * show_subs -- + * Display the subdatabases for a database. + */ +int +show_subs(dbp) + DB *dbp; +{ + DBC *dbcp; + DBT key, data; + int ret; + + /* + * Get a cursor and step through the database, printing out the key + * of each key/data pair. + */ + if ((ret = dbp->cursor(dbp, NULL, &dbcp, 0)) != 0) { + dbp->err(dbp, ret, "DB->cursor"); + return (1); + } + + memset(&key, 0, sizeof(key)); + memset(&data, 0, sizeof(data)); + while ((ret = dbcp->get(dbcp, &key, &data, + DB_IGNORE_LEASE | DB_NEXT)) == 0) { + if ((ret = dbp->dbenv->prdbt( + &key, 1, NULL, stdout, __db_pr_callback, 0, 0)) != 0) { + dbp->errx(dbp, NULL); + return (1); + } + } + if (ret != DB_NOTFOUND) { + dbp->err(dbp, ret, "DBcursor->get"); + return (1); + } + + if ((ret = dbcp->close(dbcp)) != 0) { + dbp->err(dbp, ret, "DBcursor->close"); + return (1); + } + return (0); +} + +/* + * usage -- + * Display the usage message. + */ +int +usage() +{ + (void)fprintf(stderr, "usage: %s [-klNprRV]\n\t%s\n", + progname, + "[-d ahr] [-f output] [-h home] [-P password] [-s database] db_file"); + (void)fprintf(stderr, "usage: %s [-kNpV] %s\n", + progname, "[-d ahr] [-f output] [-h home] -m database"); + return (EXIT_FAILURE); +} + +int +version_check() +{ + int v_major, v_minor, v_patch; + + /* Make sure we're loaded with the right version of the DB library. */ + (void)db_version(&v_major, &v_minor, &v_patch); + if (v_major != DB_VERSION_MAJOR || v_minor != DB_VERSION_MINOR) { + fprintf(stderr, DB_STR_A("5118", + "%s: version %d.%d doesn't match library version %d.%d\n", + "%s %d %d %d %d\n"), progname, + DB_VERSION_MAJOR, DB_VERSION_MINOR, + v_major, v_minor); + return (EXIT_FAILURE); + } + return (0); +} diff -r 000000000000 -r a1985f14b030 util/db_load.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/util/db_load.c Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,1420 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 1996, 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + * $Id$ + */ + +#include "db_config.h" + +#include "db_int.h" +#include "dbinc/db_page.h" +#include "dbinc/db_am.h" + +#ifndef lint +static const char copyright[] = + "Copyright (c) 1996, 2012 Oracle and/or its affiliates. All rights reserved.\n"; +#endif + +typedef struct { /* XXX: Globals. */ + const char *progname; /* Program name. */ + char *hdrbuf; /* Input file header. */ + u_long lineno; /* Input file line number. */ + u_long origline; /* Original file line number. */ + int endodata; /* Reached the end of a database. */ + int endofile; /* Reached the end of the input. */ + int version; /* Input version. */ + char *home; /* Env home. */ + char *passwd; /* Env passwd. */ + int private; /* Private env. */ + u_int32_t cache; /* Env cache size. */ +} LDG; + +int badend __P((DB_ENV *)); +void badnum __P((DB_ENV *)); +int configure __P((DB_ENV *, DB *, char **, char **, int *)); +int convprintable __P((DB_ENV *, char *, char **)); +int db_init __P((DB_ENV *, char *, u_int32_t, int *)); +int dbt_rdump __P((DB_ENV *, DBT *)); +int dbt_rprint __P((DB_ENV *, DBT *)); +int dbt_rrecno __P((DB_ENV *, DBT *, int)); +int dbt_to_recno __P((DB_ENV *, DBT *, db_recno_t *)); +int env_create __P((DB_ENV **, LDG *)); +void free_keys __P((DBT *part_keys)); +int load __P((DB_ENV *, char *, DBTYPE, char **, u_int, LDG *, int *)); +int main __P((int, char *[])); +int rheader __P((DB_ENV *, DB *, DBTYPE *, char **, int *, int *, DBT **)); +int usage __P((void)); +int version_check __P((void)); + +const char *progname; + +#define G(f) ((LDG *)dbenv->app_private)->f + + /* Flags to the load function. */ +#define LDF_NOHEADER 0x01 /* No dump header. */ +#define LDF_NOOVERWRITE 0x02 /* Don't overwrite existing rows. */ +#define LDF_PASSWORD 0x04 /* Encrypt created databases. */ + +int +main(argc, argv) + int argc; + char *argv[]; +{ + enum { NOTSET, STANDARD_LOAD } mode; + extern char *optarg; + extern int optind; + DBTYPE dbtype; + DB_ENV *dbenv; + LDG ldg; + u_int ldf; + int ch, existed, exitval, ret; + char **clist, **clp; + + if ((progname = __db_rpath(argv[0])) == NULL) + progname = argv[0]; + else + ++progname; + + clist = NULL; + ldg.progname = progname; + ldg.lineno = 0; + ldg.endodata = ldg.endofile = 0; + ldg.version = 1; + ldg.cache = MEGABYTE; + ldg.hdrbuf = NULL; + ldg.home = NULL; + ldg.passwd = NULL; + + if ((exitval = version_check()) != 0) + goto done; + + mode = NOTSET; + ldf = 0; + exitval = existed = 0; + dbtype = DB_UNKNOWN; + + /* Allocate enough room for configuration arguments. */ + if ((clp = clist = + (char **)calloc((size_t)argc + 1, sizeof(char *))) == NULL) { + fprintf(stderr, "%s: %s\n", ldg.progname, strerror(ENOMEM)); + exitval = 1; + goto done; + } + + /* + * There are two modes for db_load: -r and everything else. The -r + * option zeroes out the database LSN's or resets the file ID, it + * doesn't really "load" a new database. The functionality is in + * db_load because we don't have a better place to put it, and we + * don't want to create a new utility for just that functionality. + */ + while ((ch = getopt(argc, argv, "c:f:h:nP:Tt:V")) != EOF) + switch (ch) { + case 'c': + if (mode != NOTSET && mode != STANDARD_LOAD) { + exitval = usage(); + goto done; + } + mode = STANDARD_LOAD; + + *clp++ = optarg; + break; + case 'f': + if (mode != NOTSET && mode != STANDARD_LOAD) { + exitval = usage(); + goto done; + } + mode = STANDARD_LOAD; + + if (freopen(optarg, "r", stdin) == NULL) { + fprintf(stderr, DB_STR_A("5072", + "%s: %s: reopen: %s\n", "%s %s %s\n"), + ldg.progname, optarg, strerror(errno)); + exitval = usage(); + goto done; + } + break; + case 'h': + ldg.home = optarg; + break; + case 'n': + if (mode != NOTSET && mode != STANDARD_LOAD) { + exitval = usage(); + goto done; + } + mode = STANDARD_LOAD; + + ldf |= LDF_NOOVERWRITE; + break; + case 'P': + ldg.passwd = strdup(optarg); + memset(optarg, 0, strlen(optarg)); + if (ldg.passwd == NULL) { + fprintf(stderr, DB_STR_A("5073", + "%s: strdup: %s\n", "%s %s\n"), + ldg.progname, strerror(errno)); + exitval = usage(); + goto done; + } + ldf |= LDF_PASSWORD; + break; + case 'T': + if (mode != NOTSET && mode != STANDARD_LOAD) { + exitval = usage(); + goto done; + } + mode = STANDARD_LOAD; + + ldf |= LDF_NOHEADER; + break; + case 't': + if (mode != NOTSET && mode != STANDARD_LOAD) { + exitval = usage(); + goto done; + } + mode = STANDARD_LOAD; + + if (strcmp(optarg, "btree") == 0) { + dbtype = DB_BTREE; + break; + } + if (strcmp(optarg, "hash") == 0) { + dbtype = DB_HASH; + break; + } + if (strcmp(optarg, "recno") == 0) { + dbtype = DB_RECNO; + break; + } + if (strcmp(optarg, "queue") == 0) { + dbtype = DB_QUEUE; + break; + } + exitval = usage(); + goto done; + case 'V': + printf("%s\n", db_version(NULL, NULL, NULL)); + exitval = (EXIT_SUCCESS); + goto done; + case '?': + default: + exitval = usage(); + goto done; + } + argc -= optind; + argv += optind; + + if (argc != 1) { + exitval = usage(); + goto done; + } + + /* Handle possible interruptions. */ + __db_util_siginit(); + + /* + * Create an environment object initialized for error reporting, and + * then open it. + */ + if (env_create(&dbenv, &ldg) != 0) + goto err; + + /* If we're resetting the LSNs, that's an entirely separate path. */ + switch (mode) { + case NOTSET: + case STANDARD_LOAD: + while (!ldg.endofile) + if (load(dbenv, argv[0], dbtype, clist, ldf, + &ldg, &existed) != 0) + goto err; + break; + } + + if (0) { +err: exitval = 1; + } + if ((ret = dbenv->close(dbenv, 0)) != 0) { + exitval = 1; + fprintf(stderr, + "%s: dbenv->close: %s\n", ldg.progname, db_strerror(ret)); + } + + /* Resend any caught signal. */ + __db_util_sigresend(); + +done: + if (clist != NULL) + free(clist); + if (ldg.passwd != NULL) + free(ldg.passwd); + + /* + * Return 0 on success, 1 if keys existed already, and 2 on failure. + * + * Technically, this is wrong, because exit of anything other than + * 0 is implementation-defined by the ANSI C standard. I don't see + * any good solutions that don't involve API changes. + */ + return (exitval == 0 ? (existed == 0 ? 0 : 1) : 2); +} + +/* + * load -- + * Load a database. + */ +int +load(dbenv, name, argtype, clist, flags, ldg, existedp) + DB_ENV *dbenv; + char *name, **clist; + DBTYPE argtype; + u_int flags; + LDG *ldg; + int *existedp; +{ + DB *dbp; + DBC *dbc; + DBT key, rkey, data, *part_keys, *readp, *writep; + DBTYPE dbtype; + DB_HEAP_RID rid; + DB_TXN *ctxn, *txn; + db_recno_t recno, datarecno; + u_int32_t put_flags; + int ascii_recno, checkprint, hexkeys, keyflag, keys, resize, ret, rval; + char *subdb; + + put_flags = LF_ISSET(LDF_NOOVERWRITE) ? DB_NOOVERWRITE : 0; + G(endodata) = 0; + + dbc = NULL; + subdb = NULL; + ctxn = txn = NULL; + part_keys = NULL; + memset(&key, 0, sizeof(DBT)); + memset(&data, 0, sizeof(DBT)); + memset(&rkey, 0, sizeof(DBT)); + +retry_db: + dbtype = DB_UNKNOWN; + keys = -1; + hexkeys = -1; + keyflag = -1; + + /* Create the DB object. */ + if ((ret = db_create(&dbp, dbenv, 0)) != 0) { + dbenv->err(dbenv, ret, "db_create"); + goto err; + } + + /* Read the header -- if there's no header, we expect flat text. */ + if (LF_ISSET(LDF_NOHEADER)) { + checkprint = 1; + dbtype = argtype; + } else { + if (rheader(dbenv, + dbp, &dbtype, &subdb, &checkprint, &keys, &part_keys) != 0) + goto err; + if (G(endofile)) + goto done; + } + + /* + * Apply command-line configuration changes. (We apply command-line + * configuration changes to all databases that are loaded, e.g., all + * subdatabases.) + */ + if (configure(dbenv, dbp, clist, &subdb, &keyflag)) + goto err; + + if (keys != 1) { + if (keyflag == 1) { + dbp->err(dbp, EINVAL, DB_STR("5074", + "No keys specified in file")); + goto err; + } + } + else if (keyflag == 0) { + dbp->err(dbp, EINVAL, DB_STR("5075", + "Keys specified in file")); + goto err; + } + else + keyflag = 1; + + if (dbtype == DB_BTREE || dbtype == DB_HASH) { + if (keyflag == 0) + dbp->err(dbp, + EINVAL, DB_STR("5076", + "Btree and Hash must specify keys")); + else + keyflag = 1; + } + + if (dbtype == DB_HEAP && keyflag == 1) { + dbp->err(dbp, + EINVAL, DB_STR("5127", "Heap must not specify keys")); + goto err; + } + + if (argtype != DB_UNKNOWN) { + if (dbtype == DB_HEAP) { + dbenv->errx(dbenv, DB_STR("5128", + "improper database type conversion specified")); + goto err; + } + + if (dbtype == DB_RECNO || dbtype == DB_QUEUE) + if (keyflag != 1 && argtype != DB_RECNO && + argtype != DB_QUEUE) { + dbenv->errx(dbenv, DB_STR("5077", + "improper database type conversion specified")); + goto err; + } + dbtype = argtype; + } + + if (dbtype == DB_UNKNOWN) { + dbenv->errx(dbenv, DB_STR("5078", + "no database type specified")); + goto err; + } + + if (dbtype == DB_HEAP) + put_flags = DB_APPEND; + + if (keyflag == -1) + keyflag = 0; + + /* + * Recno keys have only been printed in hexadecimal starting + * with db_dump format version 3 (DB 3.2). + * + * !!! + * Note that version is set in rheader(), which must be called before + * this assignment. + */ + hexkeys = (G(version) >= 3 && keyflag == 1 && checkprint == 0); + + if (keyflag == 1 && (dbtype == DB_RECNO || dbtype == DB_QUEUE)) + ascii_recno = 1; + else + ascii_recno = 0; + + /* If configured with a password, encrypt databases we create. */ + if (LF_ISSET(LDF_PASSWORD) && + (ret = dbp->set_flags(dbp, DB_ENCRYPT)) != 0) { + dbp->err(dbp, ret, "DB->set_flags: DB_ENCRYPT"); + goto err; + } + +#if 0 + Set application-specific btree comparison, compression, or hash + functions here. For example: + + if ((ret = dbp->set_bt_compare(dbp, local_comparison_func)) != 0) { + dbp->err(dbp, ret, "DB->set_bt_compare"); + goto err; + } + if ((ret = dbp->set_bt_compress(dbp, local_compress_func, + local_decompress_func)) != 0) { + dbp->err(dbp, ret, "DB->set_bt_compress"); + goto err; + } + if ((ret = dbp->set_h_hash(dbp, local_hash_func)) != 0) { + dbp->err(dbp, ret, "DB->set_h_hash"); + goto err; + } +#endif + + /* Open the DB file. */ + if ((ret = dbp->open(dbp, NULL, name, subdb, dbtype, + DB_CREATE | (TXN_ON(dbenv->env) ? DB_AUTO_COMMIT : 0), + DB_MODE_666)) != 0) { + dbp->err(dbp, ret, "DB->open: %s", name); + goto err; + } + if (ldg->private != 0) { + if ((ret = __db_util_cache(dbp, &ldg->cache, &resize)) != 0) + goto err; + if (resize) { + if ((ret = dbp->close(dbp, 0)) != 0) + goto err; + dbp = NULL; + if ((ret = dbenv->close(dbenv, 0)) != 0) + goto err; + if ((ret = env_create(&dbenv, ldg)) != 0) + goto err; + goto retry_db; + } + } + + /* Initialize the key/data pair. */ + readp = writep = &key; + if (dbtype == DB_RECNO || dbtype == DB_QUEUE) { + key.size = sizeof(recno); + if (keyflag) { + key.data = &datarecno; + if (checkprint) { + readp = &rkey; + goto key_data; + } + } else + key.data = &recno; + } else if (dbtype == DB_HEAP) { + key.size = sizeof(DB_HEAP_RID); + key.data = &rid; + } else +key_data: if ((readp->data = malloc(readp->ulen = 1024)) == NULL) { + dbenv->err(dbenv, ENOMEM, NULL); + goto err; + } + if ((data.data = malloc(data.ulen = 1024)) == NULL) { + dbenv->err(dbenv, ENOMEM, NULL); + goto err; + } + + if (put_flags == 0 && (ret = dbp->cursor(dbp, + txn, &dbc, DB_CURSOR_BULK)) != 0) + goto err; + + /* Get each key/data pair and add them to the database. */ + for (recno = 1; !__db_util_interrupted(); ++recno) { + if (!keyflag) { + if (checkprint) { + if (dbt_rprint(dbenv, &data)) + goto err; + } else { + if (dbt_rdump(dbenv, &data)) + goto err; + } + } else { + if (checkprint) { + if (dbt_rprint(dbenv, readp)) + goto err; + if (ascii_recno && + dbt_to_recno(dbenv, readp, &datarecno) != 0) + goto err; + + if (!G(endodata) && dbt_rprint(dbenv, &data)) + goto odd_count; + } else { + if (ascii_recno) { + if (dbt_rrecno(dbenv, readp, hexkeys)) + goto err; + } else + if (dbt_rdump(dbenv, readp)) + goto err; + + if (!G(endodata) && dbt_rdump(dbenv, &data)) { +odd_count: dbenv->errx(dbenv, DB_STR("5079", + "odd number of key/data pairs")); + goto err; + } + } + } + if (G(endodata)) + break; + + switch (ret = ((put_flags == 0) ? + dbc->put(dbc, writep, &data, DB_KEYLAST) : + dbp->put(dbp, ctxn, writep, &data, put_flags))) { + case 0: + break; + case DB_KEYEXIST: + *existedp = 1; + dbenv->errx(dbenv, DB_STR_A("5080", + "%s: line %d: key already exists, not loaded:", + "%s %d"), name, + !keyflag ? recno : recno * 2 - 1); + + (void)dbenv->prdbt(&key, + checkprint, 0, stderr, __db_pr_callback, 0, 0); + break; + default: + dbenv->err(dbenv, ret, NULL); + goto err; + } + } +done: rval = 0; + if (dbc != NULL && (ret = dbc->close(dbc)) != 0) { + dbc = NULL; + goto err; + } + + if (0) { +err: rval = 1; + if (dbc != NULL) + (void)dbc->close(dbc); + } + + /* Close the database. */ + if (dbp != NULL && (ret = dbp->close(dbp, 0)) != 0) { + dbenv->err(dbenv, ret, "DB->close"); + rval = 1; + } + + if (G(hdrbuf) != NULL) + free(G(hdrbuf)); + G(hdrbuf) = NULL; + /* Free allocated memory. */ + if (subdb != NULL) + free(subdb); + if (dbtype != DB_HEAP && + dbtype != DB_RECNO && dbtype != DB_QUEUE && key.data != NULL) + free(key.data); + if (rkey.data != NULL) + free(rkey.data); + free(data.data); + free_keys(part_keys); + return (rval); +} + +/* + * env_create -- + * Create the environment and initialize it for error reporting. + */ +int +env_create(dbenvp, ldg) + DB_ENV **dbenvp; + LDG *ldg; +{ + DB_ENV *dbenv; + int ret; + + if ((ret = db_env_create(dbenvp, 0)) != 0) { + fprintf(stderr, "%s: db_env_create: %s\n", + ldg->progname, db_strerror(ret)); + return (ret); + } + dbenv = *dbenvp; + dbenv->set_errfile(dbenv, stderr); + dbenv->set_errpfx(dbenv, ldg->progname); + if (ldg->passwd != NULL && (ret = dbenv->set_encrypt(dbenv, + ldg->passwd, DB_ENCRYPT_AES)) != 0) { + dbenv->err(dbenv, ret, "set_passwd"); + return (ret); + } + if ((ret = db_init(dbenv, ldg->home, ldg->cache, &ldg->private)) != 0) + return (ret); + dbenv->app_private = ldg; + + return (0); +} + +/* + * db_init -- + * Initialize the environment. + */ +int +db_init(dbenv, home, cache, is_private) + DB_ENV *dbenv; + char *home; + u_int32_t cache; + int *is_private; +{ + u_int32_t flags; + int ret; + + *is_private = 0; + /* We may be loading into a live environment. Try and join. */ + flags = DB_USE_ENVIRON | + DB_INIT_LOCK | DB_INIT_LOG | DB_INIT_MPOOL | DB_INIT_TXN; + if ((ret = dbenv->open(dbenv, home, flags, 0)) == 0) + return (0); + if (ret == DB_VERSION_MISMATCH) + goto err; + + /* + * We're trying to load a database. + * + * An environment is required because we may be trying to look at + * databases in directories other than the current one. We could + * avoid using an environment iff the -h option wasn't specified, + * but that seems like more work than it's worth. + * + * No environment exists (or, at least no environment that includes + * an mpool region exists). Create one, but make it private so that + * no files are actually created. + */ + LF_CLR(DB_INIT_LOCK | DB_INIT_LOG | DB_INIT_TXN); + LF_SET(DB_CREATE | DB_PRIVATE); + *is_private = 1; + if ((ret = dbenv->set_cachesize(dbenv, 0, cache, 1)) != 0) { + dbenv->err(dbenv, ret, "set_cachesize"); + return (1); + } + if ((ret = dbenv->open(dbenv, home, flags, 0)) == 0) + return (0); + + /* An environment is required. */ +err: dbenv->err(dbenv, ret, "DB_ENV->open"); + return (1); +} + +#define FLAG(name, value, keyword, flag) \ + if (strcmp(name, keyword) == 0) { \ + switch (*value) { \ + case '1': \ + if ((ret = dbp->set_flags(dbp, flag)) != 0) { \ + dbp->err(dbp, ret, "%s: set_flags: %s", \ + G(progname), name); \ + goto err; \ + } \ + break; \ + case '0': \ + break; \ + default: \ + badnum(dbenv); \ + goto err; \ + } \ + continue; \ + } +#define NUMBER(name, value, keyword, func, t) \ + if (strcmp(name, keyword) == 0) { \ + if ((ret = __db_getlong(dbenv, \ + NULL, value, 0, LONG_MAX, &val)) != 0 || \ + (ret = dbp->func(dbp, (t)val)) != 0) \ + goto nameerr; \ + continue; \ + } +#define STRING(name, value, keyword, func) \ + if (strcmp(name, keyword) == 0) { \ + if ((ret = dbp->func(dbp, value[0])) != 0) \ + goto nameerr; \ + continue; \ + } + +/* + * The code to check a command-line or input header argument against a list + * of configuration options. It's #defined because it's used in two places + * and the two places have gotten out of sync more than once. + */ +#define CONFIGURATION_LIST_COMPARE \ + NUMBER(name, value, "bt_minkey", set_bt_minkey, u_int32_t); \ + FLAG(name, value, "chksum", DB_CHKSUM); \ + NUMBER(name, value, "db_lorder", set_lorder, int); \ + NUMBER(name, value, "db_pagesize", set_pagesize, u_int32_t); \ + FLAG(name, value, "duplicates", DB_DUP); \ + FLAG(name, value, "dupsort", DB_DUPSORT); \ + NUMBER(name, value, "re_len", set_re_len, u_int32_t); \ + STRING(name, value, "re_pad", set_re_pad); \ + FLAG(name, value, "recnum", DB_RECNUM); \ + FLAG(name, value, "renumber", DB_RENUMBER); + +/* + * configure -- + * Handle command-line configuration options. + */ +int +configure(dbenv, dbp, clp, subdbp, keysp) + DB_ENV *dbenv; + DB *dbp; + char **clp, **subdbp; + int *keysp; +{ + long val; + int ret, savech; + char *name, *value; + u_int32_t heap_bytes, heap_gbytes; + + heap_bytes = heap_gbytes = 0; + + for (; (name = *clp) != NULL; *--value = savech, ++clp) { + if ((value = strchr(name, '=')) == NULL) { + dbp->errx(dbp, DB_STR("5081", + "command-line configuration uses name=value format")); + return (1); + } + savech = *value; + *value++ = '\0'; + + if (strcmp(name, "database") == 0 || + strcmp(name, "subdatabase") == 0) { + if (*subdbp != NULL) + free(*subdbp); + if ((*subdbp = strdup(value)) == NULL) { + dbp->err(dbp, ENOMEM, NULL); + return (1); + } + continue; + } + if (strcmp(name, "keys") == 0) { + if (strcmp(value, "1") == 0) + *keysp = 1; + else if (strcmp(value, "0") == 0) + *keysp = 0; + else { + badnum(dbenv); + return (1); + } + continue; + } + + CONFIGURATION_LIST_COMPARE; + + dbp->errx(dbp, DB_STR_A("5082", + "unknown command-line configuration keyword \"%s\"", + "%s"), name); + return (1); + } + return (0); + +nameerr: + dbp->err(dbp, ret, "%s: %s=%s", G(progname), name, value); +err: return (1); +} + +/* + * rheader -- + * Read the header message. + */ +int +rheader(dbenv, dbp, dbtypep, subdbp, checkprintp, keysp, part_keyp) + DB_ENV *dbenv; + DB *dbp; + DBTYPE *dbtypep; + char **subdbp; + int *checkprintp, *keysp; + DBT **part_keyp; +{ + DBT *keys, *kp; + size_t buflen, linelen, start; + long val; + int ch, first, hdr, ret; + char *buf, *name, *p, *value; + u_int32_t heap_bytes, heap_gbytes, i, nparts; + + *dbtypep = DB_UNKNOWN; + *checkprintp = 0; + name = NULL; + *part_keyp = NULL; + keys = NULL; + heap_bytes = heap_gbytes = 0; + + /* + * We start with a smallish buffer; most headers are small. + * We may need to realloc it for a large subdatabase name. + */ + buflen = 4096; + if (G(hdrbuf) == NULL) { + hdr = 0; + if ((buf = malloc(buflen)) == NULL) + goto memerr; + G(hdrbuf) = buf; + G(origline) = G(lineno); + } else { + hdr = 1; + buf = G(hdrbuf); + G(lineno) = G(origline); + } + + start = 0; + for (first = 1;; first = 0) { + ++G(lineno); + + /* Read a line, which may be of arbitrary length, into buf. */ + linelen = 0; + buf = &G(hdrbuf)[start]; + if (hdr == 0) { + for (;;) { + if ((ch = getchar()) == EOF) { + if (!first || ferror(stdin)) + goto badfmt; + G(endofile) = 1; + break; + } + + /* + * If the buffer is too small, double it. + */ + if (linelen + start == buflen) { + G(hdrbuf) = + realloc(G(hdrbuf), buflen *= 2); + if (G(hdrbuf) == NULL) + goto memerr; + buf = &G(hdrbuf)[start]; + } + + if (ch == '\n') + break; + + buf[linelen++] = ch; + } + if (G(endofile) == 1) + break; + buf[linelen++] = '\0'; + } else + linelen = strlen(buf) + 1; + start += linelen; + + if (name != NULL) { + free(name); + name = NULL; + } + /* If we don't see the expected information, it's an error. */ + if ((name = strdup(buf)) == NULL) + goto memerr; + if ((p = strchr(name, '=')) == NULL) + goto badfmt; + *p++ = '\0'; + + value = p--; + + if (name[0] == '\0') + goto badfmt; + + /* + * The only values that may be zero-length are database names. + * In the original Berkeley DB code it was possible to create + * zero-length database names, and the db_load code was then + * changed to allow such databases to be be dumped and loaded. + * [#8204] + */ + if (strcmp(name, "database") == 0 || + strcmp(name, "subdatabase") == 0) { + if ((ret = convprintable(dbenv, value, subdbp)) != 0) { + dbp->err(dbp, ret, DB_STR("5083", + "error reading db name")); + goto err; + } + continue; + } + + /* No other values may be zero-length. */ + if (value[0] == '\0') + goto badfmt; + + if (strcmp(name, "HEADER") == 0) + break; + if (strcmp(name, "VERSION") == 0) { + /* + * Version 1 didn't have a "VERSION" header line. We + * only support versions 1, 2, and 3 of the dump format. + */ + G(version) = atoi(value); + + if (G(version) > 3) { + dbp->errx(dbp, DB_STR_A("5084", + "line %lu: VERSION %d is unsupported", + "%lu %d"), G(lineno), G(version)); + goto err; + } + continue; + } + if (strcmp(name, "format") == 0) { + if (strcmp(value, "bytevalue") == 0) { + *checkprintp = 0; + continue; + } + if (strcmp(value, "print") == 0) { + *checkprintp = 1; + continue; + } + goto badfmt; + } + if (strcmp(name, "type") == 0) { + if (strcmp(value, "btree") == 0) { + *dbtypep = DB_BTREE; + continue; + } + if (strcmp(value, "hash") == 0) { + *dbtypep = DB_HASH; + continue; + } + if (strcmp(value, "heap") == 0) { + *dbtypep = DB_HEAP; + continue; + } + if (strcmp(value, "recno") == 0) { + *dbtypep = DB_RECNO; + continue; + } + if (strcmp(value, "queue") == 0) { + *dbtypep = DB_QUEUE; + continue; + } + dbp->errx(dbp, DB_STR_A("5085", + "line %lu: unknown type", "%lu"), G(lineno)); + goto err; + } + if (strcmp(name, "keys") == 0) { + if (strcmp(value, "1") == 0) + *keysp = 1; + else if (strcmp(value, "0") == 0) + *keysp = 0; + else { + badnum(dbenv); + goto err; + } + continue; + } + if (strcmp(name, "nparts") == 0) { + if ((ret = __db_getlong(dbenv, + NULL, value, 0, LONG_MAX, &val)) != 0) { + badnum(dbenv); + goto err; + } + nparts = (u_int32_t) val; + if ((keys = + malloc(nparts * sizeof(DBT))) == NULL) { + dbenv->err(dbenv, ENOMEM, NULL); + goto err; + } + keys[nparts - 1].data = NULL; + kp = keys; + for (i = 1; i < nparts; kp++, i++) { + if ((kp->data = + malloc(kp->ulen = 1024)) == NULL) { + dbenv->err(dbenv, ENOMEM, NULL); + goto err; + } + if (*checkprintp) { + if (dbt_rprint(dbenv, kp)) + goto err; + } else { + if (dbt_rdump(dbenv, kp)) + goto err; + } + } + if ((ret = dbp->set_partition( + dbp, nparts, keys, NULL)) != 0) + goto err; + + *part_keyp = keys; + + continue; + } + + CONFIGURATION_LIST_COMPARE; + + /* Have to special case heap size, because we need 2 values. */ + if (strcmp(name, "heap_bytes") == 0) { + if ((ret = __db_getlong(dbenv, + NULL, value, 0, LONG_MAX, &val)) != 0) + goto nameerr; + heap_bytes = (u_int32_t)val; + } + if (strcmp(name, "heap_gbytes") == 0) { + if ((ret = __db_getlong(dbenv, + NULL, value, 0, LONG_MAX, &val)) != 0) + goto nameerr; + heap_gbytes = (u_int32_t)val; + } + + dbp->errx(dbp, DB_STR_A("5086", + "unknown input-file header configuration keyword \"%s\"", + "%s"), name); + goto err; + } + ret = 0; + + + if (0) { +nameerr: dbp->err(dbp, ret, "%s: %s=%s", G(progname), name, value); + ret = 1; + } + if (0) { +badfmt: dbp->errx(dbp, DB_STR_A("5087", + "line %lu: unexpected format", "%lu"), G(lineno)); + ret = 1; + } + if (0) { +memerr: dbp->errx(dbp, DB_STR("5088", + "unable to allocate memory")); +err: ret = 1; + } + if (name != NULL) + free(name); + if (ret != 0) { + *part_keyp = NULL; + free_keys(keys); + } + return (ret); +} + +void free_keys(part_keys) + DBT *part_keys; +{ + DBT *kp; + if (part_keys != NULL) { + for (kp = part_keys; kp->data != NULL; kp++) + free(kp->data); + free(part_keys); + } +} + +/* + * Macro to convert a pair of hex bytes to a decimal value. + * + * !!! + * Note that this macro is side-effect safe. This was done deliberately, + * callers depend on it. + */ +#define DIGITIZE(store, v1, v2) { \ + char _v1, _v2; \ + _v1 = (v1); \ + _v2 = (v2); \ + if ((_v1) > 'f' || (_v2) > 'f') \ + return (badend(dbenv)); \ + (store) = \ + ((_v1) == '0' ? 0 : \ + ((_v1) == '1' ? 1 : \ + ((_v1) == '2' ? 2 : \ + ((_v1) == '3' ? 3 : \ + ((_v1) == '4' ? 4 : \ + ((_v1) == '5' ? 5 : \ + ((_v1) == '6' ? 6 : \ + ((_v1) == '7' ? 7 : \ + ((_v1) == '8' ? 8 : \ + ((_v1) == '9' ? 9 : \ + ((_v1) == 'a' ? 10 : \ + ((_v1) == 'b' ? 11 : \ + ((_v1) == 'c' ? 12 : \ + ((_v1) == 'd' ? 13 : \ + ((_v1) == 'e' ? 14 : 15))))))))))))))) << 4 | \ + ((_v2) == '0' ? 0 : \ + ((_v2) == '1' ? 1 : \ + ((_v2) == '2' ? 2 : \ + ((_v2) == '3' ? 3 : \ + ((_v2) == '4' ? 4 : \ + ((_v2) == '5' ? 5 : \ + ((_v2) == '6' ? 6 : \ + ((_v2) == '7' ? 7 : \ + ((_v2) == '8' ? 8 : \ + ((_v2) == '9' ? 9 : \ + ((_v2) == 'a' ? 10 : \ + ((_v2) == 'b' ? 11 : \ + ((_v2) == 'c' ? 12 : \ + ((_v2) == 'd' ? 13 : \ + ((_v2) == 'e' ? 14 : 15))))))))))))))); \ +} + +/* + * convprintable -- + * Convert a printable-encoded string into a newly allocated string. + * + * In an ideal world, this would probably share code with dbt_rprint but + * that's set up to read character-by-character (to avoid large memory + * allocations that aren't likely to be a problem here), and this has fewer + * special cases to deal with. + * + * Note that despite the printable encoding, the char * interface to this + * function (which is, not coincidentally, also used for database naming) + * means that outstr cannot contain any nuls. + */ +int +convprintable(dbenv, instr, outstrp) + DB_ENV *dbenv; + char *instr, **outstrp; +{ + char *outstr; + + /* + * Just malloc a string big enough for the whole input string; + * the output string will be smaller (or of equal length). + * + * Note that we may be passed a zero-length string and need to + * be able to duplicate it. + */ + if ((outstr = malloc(strlen(instr) + 1)) == NULL) + return (ENOMEM); + + *outstrp = outstr; + + for ( ; *instr != '\0'; instr++) + if (*instr == '\\') { + if (*++instr == '\\') { + *outstr++ = '\\'; + continue; + } + DIGITIZE(*outstr++, *instr, *++instr); + } else + *outstr++ = *instr; + + *outstr = '\0'; + + return (0); +} + +/* + * dbt_rprint -- + * Read a printable line into a DBT structure. + */ +int +dbt_rprint(dbenv, dbtp) + DB_ENV *dbenv; + DBT *dbtp; +{ + u_int32_t len; + u_int8_t *p; + int c1, c2, escape, first; + char buf[32]; + + ++G(lineno); + + first = 1; + escape = 0; + for (p = dbtp->data, len = 0; (c1 = getchar()) != '\n';) { + if (c1 == EOF) { + if (len == 0) { + G(endofile) = G(endodata) = 1; + return (0); + } + return (badend(dbenv)); + } + if (first) { + first = 0; + if (G(version) > 1) { + if (c1 != ' ') { + buf[0] = c1; + if (fgets(buf + 1, + sizeof(buf) - 1, stdin) == NULL || + strcmp(buf, "DATA=END\n") != 0) + return (badend(dbenv)); + G(endodata) = 1; + return (0); + } + continue; + } + } + if (escape) { + if (c1 != '\\') { + if ((c2 = getchar()) == EOF) + return (badend(dbenv)); + DIGITIZE(c1, c1, c2); + } + escape = 0; + } else + if (c1 == '\\') { + escape = 1; + continue; + } + if (len >= dbtp->ulen - 10) { + dbtp->ulen *= 2; + if ((dbtp->data = + realloc(dbtp->data, dbtp->ulen)) == NULL) { + dbenv->err(dbenv, ENOMEM, NULL); + return (1); + } + p = (u_int8_t *)dbtp->data + len; + } + ++len; + *p++ = c1; + } + dbtp->size = len; + + return (0); +} + +/* + * dbt_rdump -- + * Read a byte dump line into a DBT structure. + */ +int +dbt_rdump(dbenv, dbtp) + DB_ENV *dbenv; + DBT *dbtp; +{ + u_int32_t len; + u_int8_t *p; + int c1, c2, first; + char buf[32]; + + ++G(lineno); + + first = 1; + for (p = dbtp->data, len = 0; (c1 = getchar()) != '\n';) { + if (c1 == EOF) { + if (len == 0) { + G(endofile) = G(endodata) = 1; + return (0); + } + return (badend(dbenv)); + } + if (first) { + first = 0; + if (G(version) > 1) { + if (c1 != ' ') { + buf[0] = c1; + if (fgets(buf + 1, + sizeof(buf) - 1, stdin) == NULL || + strcmp(buf, "DATA=END\n") != 0) + return (badend(dbenv)); + G(endodata) = 1; + return (0); + } + continue; + } + } + if ((c2 = getchar()) == EOF) + return (badend(dbenv)); + if (len >= dbtp->ulen - 10) { + dbtp->ulen *= 2; + if ((dbtp->data = + realloc(dbtp->data, dbtp->ulen)) == NULL) { + dbenv->err(dbenv, ENOMEM, NULL); + return (1); + } + p = (u_int8_t *)dbtp->data + len; + } + ++len; + DIGITIZE(*p++, c1, c2); + } + dbtp->size = len; + + return (0); +} + +/* + * dbt_rrecno -- + * Read a record number dump line into a DBT structure. + */ +int +dbt_rrecno(dbenv, dbtp, ishex) + DB_ENV *dbenv; + DBT *dbtp; + int ishex; +{ + char buf[32], *p, *q; + u_long recno; + + ++G(lineno); + + if (fgets(buf, sizeof(buf), stdin) == NULL) { + G(endofile) = G(endodata) = 1; + return (0); + } + + if (strcmp(buf, "DATA=END\n") == 0) { + G(endodata) = 1; + return (0); + } + + if (buf[0] != ' ') + goto err; + + /* + * If we're expecting a hex key, do an in-place conversion + * of hex to straight ASCII before calling __db_getulong(). + */ + if (ishex) { + for (p = q = buf + 1; *q != '\0' && *q != '\n';) { + /* + * 0-9 in hex are 0x30-0x39, so this is easy. + * We should alternate between 3's and [0-9], and + * if the [0-9] are something unexpected, + * __db_getulong will fail, so we only need to catch + * end-of-string conditions. + */ + if (*q++ != '3') + goto err; + if (*q == '\n' || *q == '\0') + goto err; + *p++ = *q++; + } + *p = '\0'; + } + + if (__db_getulong(dbenv, G(progname), buf + 1, 0, 0, &recno)) + goto err; + + *((db_recno_t *)dbtp->data) = recno; + dbtp->size = sizeof(db_recno_t); + return (0); + +err: return (badend(dbenv)); +} + +int +dbt_to_recno(dbenv, dbt, recnop) + DB_ENV *dbenv; + DBT *dbt; + db_recno_t *recnop; +{ + char buf[32]; /* Large enough for 2^64. */ + + memcpy(buf, dbt->data, dbt->size); + buf[dbt->size] = '\0'; + + return (__db_getulong(dbenv, G(progname), buf, 0, 0, (u_long *)recnop)); +} + +/* + * badnum -- + * Display the bad number message. + */ +void +badnum(dbenv) + DB_ENV *dbenv; +{ + dbenv->errx(dbenv, DB_STR("5089", + "boolean name=value pairs require a value of 0 or 1")); +} + +/* + * badend -- + * Display the bad end to input message. + */ +int +badend(dbenv) + DB_ENV *dbenv; +{ + dbenv->errx(dbenv, DB_STR("5090", + "unexpected end of input data or key/data pair")); + return (1); +} + +/* + * usage -- + * Display the usage message. + */ +int +usage() +{ + (void)fprintf(stderr, "usage: %s %s\n\t%s\n", progname, + "[-nTV] [-c name=value] [-f file]", + "[-h home] [-P password] [-t btree | hash | recno | queue] db_file"); + (void)fprintf(stderr, "usage: %s %s\n", + progname, "-r lsn | fileid [-h home] [-P password] db_file"); + return (EXIT_FAILURE); +} + +int +version_check() +{ + int v_major, v_minor, v_patch; + + /* Make sure we're loaded with the right version of the DB library. */ + (void)db_version(&v_major, &v_minor, &v_patch); + if (v_major != DB_VERSION_MAJOR || v_minor != DB_VERSION_MINOR) { + fprintf(stderr, DB_STR_A("5091", + "%s: version %d.%d doesn't match library version %d.%d\n", + "%s %d %d %d %d\n"), progname, DB_VERSION_MAJOR, + DB_VERSION_MINOR, v_major, v_minor); + return (EXIT_FAILURE); + } + return (0); +} diff -r 000000000000 -r a1985f14b030 util/db_stat.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/util/db_stat.c Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,488 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 1996, 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + * $Id$ + */ + +#include "db_config.h" + +#include "db_int.h" + +#ifndef lint +static const char copyright[] = + "Copyright (c) 1996, 2012 Oracle and/or its affiliates. All rights reserved.\n"; +#endif + +typedef enum { T_NOTSET, T_DB, + T_ENV, T_LOCK, T_LOG, T_MPOOL, T_MUTEX, T_REP, T_TXN } test_t; + +int db_init __P((DB_ENV *, char *, test_t, u_int32_t, int *)); +int main __P((int, char *[])); +int usage __P((void)); +int version_check __P((void)); + +const char *progname; + +int +main(argc, argv) + int argc; + char *argv[]; +{ + extern char *optarg; + extern int optind; + DB_ENV *dbenv; + DB *dbp; + test_t ttype; + u_int32_t cache, flags; + int ch, exitval; + int nflag, private, resize, ret; + char *db, *home, *p, *passwd, *subdb; + + if ((progname = __db_rpath(argv[0])) == NULL) + progname = argv[0]; + else + ++progname; + + if ((ret = version_check()) != 0) + return (ret); + + dbenv = NULL; + dbp = NULL; + ttype = T_NOTSET; + cache = MEGABYTE; + exitval = flags = nflag = private = 0; + db = home = passwd = subdb = NULL; + + while ((ch = getopt(argc, + argv, "aC:cd:Eefgh:L:lM:mNP:R:rs:tVxX:Z")) != EOF) + switch (ch) { + case 'a': + LF_SET(DB_STAT_ALLOC); + break; + case 'C': case 'c': + if (ttype != T_NOTSET && ttype != T_LOCK) + goto argcombo; + ttype = T_LOCK; + if (ch != 'c') + for (p = optarg; *p; ++p) + switch (*p) { + case 'A': + LF_SET(DB_STAT_ALL); + break; + case 'c': + LF_SET(DB_STAT_LOCK_CONF); + break; + case 'l': + LF_SET(DB_STAT_LOCK_LOCKERS); + break; + case 'm': /* Backward compatible. */ + break; + case 'o': + LF_SET(DB_STAT_LOCK_OBJECTS); + break; + case 'p': + LF_SET(DB_STAT_LOCK_PARAMS); + break; + default: + return (usage()); + } + break; + case 'd': + if (ttype != T_NOTSET && ttype != T_DB) + goto argcombo; + ttype = T_DB; + db = optarg; + break; + case 'E': case 'e': + if (ttype != T_NOTSET && ttype != T_ENV) + goto argcombo; + ttype = T_ENV; + LF_SET(DB_STAT_SUBSYSTEM); + if (ch == 'E') + LF_SET(DB_STAT_ALL); + break; + case 'f': + if (ttype != T_NOTSET && ttype != T_DB) + goto argcombo; + ttype = T_DB; + LF_SET(DB_FAST_STAT); + break; + case 'h': + home = optarg; + break; + case 'L': case 'l': + if (ttype != T_NOTSET && ttype != T_LOG) + goto argcombo; + ttype = T_LOG; + if (ch != 'l') + for (p = optarg; *p; ++p) + switch (*p) { + case 'A': + LF_SET(DB_STAT_ALL); + break; + default: + return (usage()); + } + break; + case 'M': case 'm': + if (ttype != T_NOTSET && ttype != T_MPOOL) + goto argcombo; + ttype = T_MPOOL; + if (ch != 'm') + for (p = optarg; *p; ++p) + switch (*p) { + case 'A': + LF_SET(DB_STAT_ALL); + break; + case 'h': + LF_SET(DB_STAT_MEMP_HASH); + break; + case 'm': /* Backward compatible. */ + break; + default: + return (usage()); + } + break; + case 'N': + nflag = 1; + break; + case 'P': + if (passwd != NULL) { + fprintf(stderr, DB_STR("5139", + "Password may not be specified twice")); + free(passwd); + return (EXIT_FAILURE); + } + passwd = strdup(optarg); + memset(optarg, 0, strlen(optarg)); + if (passwd == NULL) { + fprintf(stderr, DB_STR_A("5005", + "%s: strdup: %s\n", "%s %s\n"), + progname, strerror(errno)); + return (EXIT_FAILURE); + } + break; + case 'R': case 'r': + if (ttype != T_NOTSET && ttype != T_REP) + goto argcombo; + ttype = T_REP; + if (ch != 'r') + for (p = optarg; *p; ++p) + switch (*p) { + case 'A': + LF_SET(DB_STAT_ALL); + break; + default: + return (usage()); + } + break; + case 's': + if (ttype != T_NOTSET && ttype != T_DB) + goto argcombo; + ttype = T_DB; + subdb = optarg; + break; + case 't': + if (ttype != T_NOTSET) { +argcombo: fprintf(stderr, DB_STR_A("5006", + "%s: illegal option combination\n", + "%s\n"), progname); + return (usage()); + } + ttype = T_TXN; + break; + case 'V': + printf("%s\n", db_version(NULL, NULL, NULL)); + return (EXIT_SUCCESS); + case 'X': case 'x': + if (ttype != T_NOTSET && ttype != T_MUTEX) + goto argcombo; + ttype = T_MUTEX; + if (ch != 'x') + for (p = optarg; *p; ++p) + switch (*p) { + case 'A': + LF_SET(DB_STAT_ALL); + break; + default: + return (usage()); + } + break; + case 'Z': + LF_SET(DB_STAT_CLEAR); + break; + case '?': + default: + return (usage()); + } + argc -= optind; + argv += optind; + + switch (ttype) { + case T_DB: + if (db == NULL) + return (usage()); + break; + case T_ENV: + case T_LOCK: + case T_LOG: + case T_MPOOL: + case T_MUTEX: + case T_REP: + case T_TXN: + break; + case T_NOTSET: + return (usage()); + } + + if (LF_ISSET(DB_STAT_ALL | DB_STAT_ALLOC) == DB_STAT_ALLOC) + return (usage()); + + /* Handle possible interruptions. */ + __db_util_siginit(); + + /* + * Create an environment object and initialize it for error + * reporting. + */ +retry: if ((ret = db_env_create(&dbenv, 0)) != 0) { + fprintf(stderr, + "%s: db_env_create: %s\n", progname, db_strerror(ret)); + goto err; + } + + dbenv->set_errfile(dbenv, stderr); + dbenv->set_errpfx(dbenv, progname); + + if (nflag) { + if ((ret = dbenv->set_flags(dbenv, DB_NOLOCKING, 1)) != 0) { + dbenv->err(dbenv, ret, "set_flags: DB_NOLOCKING"); + goto err; + } + if ((ret = dbenv->set_flags(dbenv, DB_NOPANIC, 1)) != 0) { + dbenv->err(dbenv, ret, "set_flags: DB_NOPANIC"); + goto err; + } + } + + if (passwd != NULL && + (ret = dbenv->set_encrypt(dbenv, passwd, DB_ENCRYPT_AES)) != 0) { + dbenv->err(dbenv, ret, "set_passwd"); + goto err; + } + + /* Initialize the environment. */ + if (db_init(dbenv, home, ttype, cache, &private) != 0) + goto err; + + switch (ttype) { + case T_DB: + /* Create the DB object and open the file. */ + if ((ret = db_create(&dbp, dbenv, 0)) != 0) { + dbenv->err(dbenv, ret, "db_create"); + goto err; + } + + /* + * We open the database for writing so we can update the cached + * statistics, but it's OK to fail, we can open read-only and + * proceed. + * + * Turn off error messages for now -- we can't open lots of + * databases read-write (for example, master databases and + * hash databases for which we don't know the hash function). + */ + dbenv->set_errfile(dbenv, NULL); + ret = dbp->open(dbp, NULL, db, subdb, DB_UNKNOWN, 0, 0); + dbenv->set_errfile(dbenv, stderr); + if (ret != 0) { + /* Handles cannot be reused after a failed DB->open. */ + (void)dbp->close(dbp, 0); + if ((ret = db_create(&dbp, dbenv, 0)) != 0) { + dbenv->err(dbenv, ret, "db_create"); + goto err; + } + + if ((ret = dbp->open(dbp, + NULL, db, subdb, DB_UNKNOWN, DB_RDONLY, 0)) != 0) { + dbenv->err(dbenv, ret, "DB->open: %s", db); + goto err; + } + } + + /* Check if cache is too small for this DB's pagesize. */ + if (private) { + if ((ret = __db_util_cache(dbp, &cache, &resize)) != 0) + goto err; + if (resize) { + (void)dbp->close(dbp, DB_NOSYNC); + dbp = NULL; + + (void)dbenv->close(dbenv, 0); + dbenv = NULL; + goto retry; + } + } + + if (dbp->stat_print(dbp, flags)) + goto err; + break; + case T_ENV: + if (dbenv->stat_print(dbenv, flags)) + goto err; + break; + case T_MPOOL: + if (dbenv->memp_stat_print(dbenv, flags)) + goto err; + break; + case T_LOCK: + case T_LOG: + case T_MUTEX: + case T_REP: + case T_TXN: + dbenv->errx(dbenv, "This build does not support that subsystem"); + break; + case T_NOTSET: + dbenv->errx(dbenv, DB_STR("5007", + "Unknown statistics flag")); + goto err; + } + + if (0) { +err: exitval = 1; + } + if (dbp != NULL && (ret = dbp->close(dbp, DB_NOSYNC)) != 0) { + exitval = 1; + dbenv->err(dbenv, ret, DB_STR("5008", "close")); + } + if (dbenv != NULL && (ret = dbenv->close(dbenv, 0)) != 0) { + exitval = 1; + fprintf(stderr, + "%s: dbenv->close: %s\n", progname, db_strerror(ret)); + } + + if (passwd != NULL) + free(passwd); + + /* Resend any caught signal. */ + __db_util_sigresend(); + + return (exitval == 0 ? EXIT_SUCCESS : EXIT_FAILURE); +} + +/* + * db_init -- + * Initialize the environment. + */ +int +db_init(dbenv, home, ttype, cache, is_private) + DB_ENV *dbenv; + char *home; + test_t ttype; + u_int32_t cache; + int *is_private; +{ + u_int32_t oflags; + int ret; + + /* + * If our environment open fails, and we're trying to look at a + * shared region, it's a hard failure. + * + * We will probably just drop core if the environment we join does + * not include a memory pool. This is probably acceptable; trying + * to use an existing environment that does not contain a memory + * pool to look at a database can be safely construed as operator + * error, I think. + */ + *is_private = 0; + if ((ret = dbenv->open(dbenv, home, DB_USE_ENVIRON, 0)) == 0) + return (0); + if (ret == DB_VERSION_MISMATCH) + goto err; + if (ttype != T_DB && ttype != T_LOG) { + dbenv->err(dbenv, ret, "DB_ENV->open%s%s", + home == NULL ? "" : ": ", home == NULL ? "" : home); + return (1); + } + + /* + * We're looking at a database or set of log files and no environment + * exists. Create one, but make it private so no files are actually + * created. Declare a reasonably large cache so that we don't fail + * when reporting statistics on large databases. + * + * An environment is required to look at databases because we may be + * trying to look at databases in directories other than the current + * one. + */ + if ((ret = dbenv->set_cachesize(dbenv, 0, cache, 1)) != 0) { + dbenv->err(dbenv, ret, "set_cachesize"); + return (1); + } + *is_private = 1; + oflags = DB_CREATE | DB_PRIVATE | DB_USE_ENVIRON; + if (ttype == T_DB) + oflags |= DB_INIT_MPOOL; + if (ttype == T_LOG) + oflags |= DB_INIT_LOG; + if ((ret = dbenv->open(dbenv, home, oflags, 0)) == 0) + return (0); + + /* An environment is required. */ +err: dbenv->err(dbenv, ret, "DB_ENV->open"); + return (1); +} + +int +usage() +{ + fprintf(stderr, "usage: %s %s\n", progname, + "-d file [-fN] [-h home] [-P password] [-s database]"); + fprintf(stderr, "usage: %s %s\n\t%s\n", progname, + "[-cEelmrtVx] [-C Aclop]", + "[-h home] [-L A] [-M A] [-P password] [-R A] [-X A] [-aNZ]"); + return (EXIT_FAILURE); +} + +int +version_check() +{ + int v_major, v_minor, v_patch; + + /* Make sure we're loaded with the right version of the DB library. */ + (void)db_version(&v_major, &v_minor, &v_patch); + if (v_major != DB_VERSION_MAJOR || v_minor != DB_VERSION_MINOR) { + fprintf(stderr, DB_STR_A("5009", + "%s: version %d.%d doesn't match library version %d.%d\n", + "%s %d %d %d %d\n"), progname, + DB_VERSION_MAJOR, DB_VERSION_MINOR, + v_major, v_minor); + return (EXIT_FAILURE); + } + return (0); +} diff -r 000000000000 -r a1985f14b030 util/db_verify.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/util/db_verify.c Fri May 11 10:42:02 2012 +0100 @@ -0,0 +1,311 @@ +/*- + * See the file LICENSE for redistribution information. + * + * Copyright (c) 1996, 2012 Oracle and/or its affiliates. All rights reserved. + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code 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 General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + * $Id$ + */ + +#include "db_config.h" + +#include "db_int.h" + +#ifndef lint +static const char copyright[] = + "Copyright (c) 1996, 2012 Oracle and/or its affiliates. All rights reserved.\n"; +#endif + +int main __P((int, char *[])); +int usage __P((void)); +int version_check __P((void)); + +const char *progname; + +int +main(argc, argv) + int argc; + char *argv[]; +{ + extern char *optarg; + extern int optind; + DB *dbp, *dbp1; + DB_ENV *dbenv; + u_int32_t flags, cache; + int ch, exitval, mflag, nflag, private; + int quiet, resize, ret; + char *dname, *fname, *home, *passwd; + + if ((progname = __db_rpath(argv[0])) == NULL) + progname = argv[0]; + else + ++progname; + + if ((ret = version_check()) != 0) + return (ret); + + dbenv = NULL; + dbp = NULL; + cache = MEGABYTE; + exitval = mflag = nflag = quiet = 0; + flags = 0; + home = passwd = NULL; + while ((ch = getopt(argc, argv, "h:mNoP:quV")) != EOF) + switch (ch) { + case 'h': + home = optarg; + break; + case 'm': + mflag = 1; + break; + case 'N': + nflag = 1; + break; + case 'P': + if (passwd != NULL) { + fprintf(stderr, DB_STR("5132", + "Password may not be specified twice")); + free(passwd); + return (EXIT_FAILURE); + } + passwd = strdup(optarg); + memset(optarg, 0, strlen(optarg)); + if (passwd == NULL) { + fprintf(stderr, "%s: strdup: %s\n", + progname, strerror(errno)); + return (EXIT_FAILURE); + } + break; + case 'o': + LF_SET(DB_NOORDERCHK); + break; + case 'q': + quiet = 1; + break; + case 'u': /* Undocumented. */ + LF_SET(DB_UNREF); + break; + case 'V': + printf("%s\n", db_version(NULL, NULL, NULL)); + return (EXIT_SUCCESS); + case '?': + default: + return (usage()); + } + argc -= optind; + argv += optind; + + if (argc <= 0) + return (usage()); + + if (mflag) { + dname = argv[0]; + fname = NULL; + } else { + fname = argv[0]; + dname = NULL; + } + + /* Handle possible interruptions. */ + __db_util_siginit(); + + /* + * Create an environment object and initialize it for error + * reporting. + */ +retry: if ((ret = db_env_create(&dbenv, 0)) != 0) { + fprintf(stderr, + "%s: db_env_create: %s\n", progname, db_strerror(ret)); + goto err; + } + + if (!quiet) { + dbenv->set_errfile(dbenv, stderr); + dbenv->set_errpfx(dbenv, progname); + } + + if (nflag) { + if ((ret = dbenv->set_flags(dbenv, DB_NOLOCKING, 1)) != 0) { + dbenv->err(dbenv, ret, "set_flags: DB_NOLOCKING"); + goto err; + } + if ((ret = dbenv->set_flags(dbenv, DB_NOPANIC, 1)) != 0) { + dbenv->err(dbenv, ret, "set_flags: DB_NOPANIC"); + goto err; + } + } + + if (passwd != NULL && + (ret = dbenv->set_encrypt(dbenv, passwd, DB_ENCRYPT_AES)) != 0) { + dbenv->err(dbenv, ret, "set_passwd"); + goto err; + } + /* + * Attach to an mpool if it exists, but if that fails, attach to a + * private region. In the latter case, declare a reasonably large + * cache so that we don't fail when verifying large databases. + */ + private = 0; + if ((ret = + dbenv->open(dbenv, home, DB_INIT_MPOOL | DB_USE_ENVIRON, 0)) != 0) { + if (ret != DB_VERSION_MISMATCH) { + if ((ret = + dbenv->set_cachesize(dbenv, 0, cache, 1)) != 0) { + dbenv->err(dbenv, ret, "set_cachesize"); + goto err; + } + private = 1; + ret = dbenv->open(dbenv, home, DB_CREATE | + DB_INIT_MPOOL | DB_PRIVATE | DB_USE_ENVIRON, 0); + } + if (ret != 0) { + dbenv->err(dbenv, ret, "DB_ENV->open"); + goto err; + } + } + + /* + * Find out if we have a transactional environment so that we can + * make sure that we don't open the verify database with logging + * enabled. + */ + for (; !__db_util_interrupted() && argv[0] != NULL; ++argv) { + if ((ret = db_create(&dbp, dbenv, 0)) != 0) { + dbenv->err(dbenv, ret, "%s: db_create", progname); + goto err; + } + + if (TXN_ON(dbenv->env) && + (ret = dbp->set_flags(dbp, DB_TXN_NOT_DURABLE)) != 0) { + dbenv->err( + dbenv, ret, "%s: db_set_flags", progname); + goto err; + } + + /* + * We create a 2nd dbp to this database to get its pagesize + * because the dbp we're using for verify cannot be opened. + * + * If the database is corrupted, we may not be able to open + * it, of course. In that case, just continue, using the + * cache size we have. + */ + if (private) { + if ((ret = db_create(&dbp1, dbenv, 0)) != 0) { + dbenv->err( + dbenv, ret, "%s: db_create", progname); + goto err; + } + + if (TXN_ON(dbenv->env) && (ret = + dbp1->set_flags(dbp1, DB_TXN_NOT_DURABLE)) != 0) { + dbenv->err( + dbenv, ret, "%s: db_set_flags", progname); + goto err; + } + + ret = dbp1->open(dbp1, + NULL, fname, dname, DB_UNKNOWN, DB_RDONLY, 0); + + /* + * If we get here, we can check the cache/page. + * !!! + * If we have to retry with an env with a larger + * cache, we jump out of this loop. However, we + * will still be working on the same argv when we + * get back into the for-loop. + */ + if (ret == 0) { + if (__db_util_cache( + dbp1, &cache, &resize) == 0 && resize) { + (void)dbp1->close(dbp1, 0); + (void)dbp->close(dbp, 0); + dbp = NULL; + + (void)dbenv->close(dbenv, 0); + dbenv = NULL; + goto retry; + } + } + (void)dbp1->close(dbp1, 0); + } + + /* The verify method is a destructor. */ + ret = dbp->verify(dbp, fname, dname, NULL, flags); + dbp = NULL; + if (ret != 0) + exitval = 1; + if (!quiet) + printf(DB_STR_A("5105", "Verification of %s %s.\n", + "%s %s\n"), argv[0], ret == 0 ? + DB_STR_P("succeeded") : DB_STR_P("failed")); + } + + if (0) { +err: exitval = 1; + } + + if (dbp != NULL && (ret = dbp->close(dbp, 0)) != 0) { + exitval = 1; + dbenv->err(dbenv, ret, DB_STR("5106", "close")); + } + if (dbenv != NULL && (ret = dbenv->close(dbenv, 0)) != 0) { + exitval = 1; + fprintf(stderr, + "%s: dbenv->close: %s\n", progname, db_strerror(ret)); + } + + if (passwd != NULL) + free(passwd); + + /* Resend any caught signal. */ + __db_util_sigresend(); + + return (exitval == 0 ? EXIT_SUCCESS : EXIT_FAILURE); +} + +int +usage() +{ + fprintf(stderr, "usage: %s %s\n", progname, + "[-NoqV] [-h home] [-P password] db_file ..."); + return (EXIT_FAILURE); +} + +int +version_check() +{ + int v_major, v_minor, v_patch; + + /* Make sure we're loaded with the right version of the DB library. */ + (void)db_version(&v_major, &v_minor, &v_patch); + if (v_major != DB_VERSION_MAJOR || v_minor != DB_VERSION_MINOR) { + fprintf(stderr, DB_STR_A("5107", + "%s: version %d.%d doesn't match library version %d.%d\n", + "%s %d %d %d %d\n"), progname, DB_VERSION_MAJOR, + DB_VERSION_MINOR, v_major, v_minor); + return (EXIT_FAILURE); + } + return (0); +}