Import BSDDB 4.7.25 (as of svn r89086)

This commit is contained in:
Zachary Ware
2017-09-04 13:40:25 -05:00
parent 4b29e0458f
commit 8f590873d0
4781 changed files with 2241032 additions and 6 deletions

Binary file not shown.

View File

@@ -0,0 +1,356 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>Cursor Example</title>
<link rel="stylesheet" href="gettingStarted.css" type="text/css" />
<meta name="generator" content="DocBook XSL Stylesheets V1.62.4" />
<link rel="home" href="index.html" title="Getting Started with Berkeley DB" />
<link rel="up" href="Cursors.html" title="Chapter 4. Using Cursors" />
<link rel="previous" href="ReplacingEntryWCursor.html" title="Replacing Records Using Cursors" />
<link rel="next" href="indexes.html" title="Chapter 5. Secondary Databases" />
</head>
<body>
<div class="navheader">
<table width="100%" summary="Navigation header">
<tr>
<th colspan="3" align="center">Cursor Example</th>
</tr>
<tr>
<td width="20%" align="left"><a accesskey="p" href="ReplacingEntryWCursor.html">Prev</a> </td>
<th width="60%" align="center">Chapter 4. Using Cursors</th>
<td width="20%" align="right"> <a accesskey="n" href="indexes.html">Next</a></td>
</tr>
</table>
<hr />
</div>
<div class="sect1" lang="en" xml:lang="en">
<div class="titlepage">
<div>
<div>
<h2 class="title" style="clear: both"><a id="CoreCursorUsage"></a>Cursor Example</h2>
</div>
</div>
<div></div>
</div>
<p>
In
<a href="DbUsage.html">Database Usage Example</a>
we wrote an
application that loaded two databases with
vendor and inventory information. In this example, we will write an
application to display all of the items in the inventory database. As a
part of showing any given inventory item, we will look up the vendor who
can provide the item and show the vendor's contact information.
</p>
<p>
Specifically, the <tt class="classname">example_database_read</tt>
application does the following:
</p>
<div class="orderedlist">
<ol type="1">
<li>
<p>
Opens the the inventory and vendor databases
that were created by our <tt class="classname">example_database_load</tt>
application. See
<a href="DbUsage.html#exampledbload">example_database_load</a>
for information on how that
application creates the databases and writes data to them.
</p>
</li>
<li>
<p>Obtains a cursor from the inventory database.</p>
</li>
<li>
<p>
Steps through the inventory database, displaying
each record as it goes.
</p>
</li>
<li>
<p>
Gets the name of the vendor for that inventory item from the
inventory record.
</p>
</li>
<li>
<p>
Uses the vendor name to look up the vendor record in the vendor
database.
</p>
</li>
<li>
<p>Displays the vendor record.</p>
</li>
</ol>
</div>
<p>
Remember that you can find the complete implementation of this application
in:
</p>
<pre class="programlisting"><span class="emphasis"><em>DB_INSTALL</em></span>/examples_c/getting_started</pre>
<p>
where <tt class="literal"><span class="emphasis"><em>DB_INSTALL</em></span></tt> is the location where you
placed your DB distribution.
</p>
<div class="example">
<a id="CoreEIR"></a>
<p class="title">
<b>Example 4.1 example_database_read</b>
</p>
<p>
To begin, we include the necessary header files and perform our
forward declarations.
</p>
<a id="c_cursor10"></a>
<pre class="programlisting">/* File: example_database_read.c */
/* gettingstarted_common.h includes db.h for us */
#include "gettingstarted_common.h"
/* Forward declarations */
char * show_inventory_item(void *);
int show_all_records(STOCK_DBS *);
int show_records(STOCK_DBS *, char *);
int show_vendor_record(char *, DB *); </pre>
<p>
Next we write our <tt class="function">main()</tt> function. Note that it is
somewhat unnecessarily complicated here because we will be extending it
in the next chapter to perform inventory item lookups.
</p>
<a id="c_cursor11"></a>
<pre class="programlisting">/*
* Displays all inventory items and the associated vendor record.
*/
int
main(int argc, char *argv[])
{
STOCK_DBS my_stock;
int ret;
/* Initialize the STOCK_DBS struct */
initialize_stockdbs(&amp;my_stock);
/*
* Parse the command line arguments here and determine
* the location of the database files. This step is
* omitted for brevity.
*/
/*
* Identify the files that will hold our databases
* This function uses information obtained from the
* command line to identify the directory in which
* the database files reside.
*/
set_db_filenames(&amp;my_stock);
/* Open all databases */
ret = databases_setup(&amp;my_stock, "example_database_read", stderr);
if (ret != 0) {
fprintf(stderr, "Error opening databases\n");
databases_close(&amp;my_stock);
return (ret);
}
ret = show_all_records(&amp;my_stock);
/* close our databases */
databases_close(&amp;my_stock);
return (ret);
} </pre>
<p>
Next we need to write the <tt class="function">show_all_records()</tt>
function. This
function takes a <tt class="literal">STOCK_DBS</tt> structure and displays all
of the inventory records found in the inventory database. Once it shows
the inventory record, it retrieves the vendor's name from that record
and uses it to look up and display the appropriate vendor record:
</p>
<a id="c_cursor12"></a>
<pre class="programlisting">int show_all_records(STOCK_DBS *my_stock)
{
DBC *cursorp;
DBT key, data;
char *the_vendor;
int exit_value, ret;
/* Initialize our DBTs. */
memset(&amp;key, 0, sizeof(DBT));
memset(&amp;data, 0, sizeof(DBT));
/* Get a cursor to the itemname db */
my_stock-&gt;inventory_dbp-&gt;cursor(my_stock-&gt;inventory_dbp, NULL,
&amp;cursorp, 0);
/*
* Iterate over the inventory database, from the first record
* to the last, displaying each in turn.
*/
exit_value = 0;
while ((ret =
cursorp-&gt;get(cursorp, &amp;key, &amp;data, DB_NEXT))
== 0)
{
the_vendor = show_inventory_item(data.data);
ret = show_vendor_record(the_vendor, my_stock-&gt;vendor_dbp);
if (ret) {
exit_value = ret;
break;
}
}
/* Close the cursor */
cursorp-&gt;close(cursorp);
return(exit_value);
} </pre>
<p>
The <tt class="function">show_inventory_item()</tt> simply extracts the
inventory information from the record data and displays it. It then
returns the vendor's name. Note that in order to extract the inventory
information, we have to unpack it from the data buffer. How we do this
is entirely dependent on how we packed the buffer in the first
place. For more information, see the
<tt class="function">load_inventory_database()</tt> function implementation
in
<span><a href="DbUsage.html#exampledbload">example_database_load</a>.</span>
</p>
<a id="c_cursor13"></a>
<pre class="programlisting">/*
* Shows an inventory item.
*/
char *
show_inventory_item(void *vBuf)
{
float price;
int buf_pos, quantity;
char *category, *name, *sku, *vendor_name;
char *buf = (char *)vBuf;
/* Get the price. */
price = *((float *)buf);
buf_pos = sizeof(float);
/* Get the quantity. */
quantity = *((int *)(buf + buf_pos));
buf_pos += sizeof(int);
/* Get the inventory item's name */
name = buf + buf_pos;
buf_pos += strlen(name) + 1;
/* Get the inventory item's sku */
sku = buf + buf_pos;
buf_pos += strlen(sku) + 1;
/*
* Get the category (fruits, vegetables, desserts) that this
* item belongs to.
*/
category = buf + buf_pos;
buf_pos += strlen(category) + 1;
/* Get the vendor's name */
vendor_name = buf + buf_pos;
/* Display all this information */
printf("name: %s\n", name);
printf("\tSKU: %s\n", sku);
printf("\tCategory: %s\n", category);
printf("\tPrice: %.2f\n", price);
printf("\tQuantity: %i\n", quantity);
printf("\tVendor:\n");
/* Return the vendor's name */
return(vendor_name);
} </pre>
<p>
Having returned the vendor's name, we can now use it to look up and
display the appropriate vendor record. In this case we do not need to use a
cursor to display the vendor record. Using a cursor here complicates our
code slightly for no good gain. Instead, we simply perform a
<tt class="function">get()</tt> directly against the vendor database.
</p>
<a id="c_cursor14"></a>
<pre class="programlisting">/*
* Shows a vendor record. Each vendor record is an instance of
* a vendor structure. See load_vendor_database() in
* example_database_load for how this structure was originally
* put into the database.
*/
int
show_vendor_record(char *vendor_name, DB *vendor_dbp)
{
DBT key, data;
VENDOR my_vendor;
int ret;
/* Zero our DBTs */
memset(&amp;key, 0, sizeof(DBT));
memset(&amp;data, 0, sizeof(DBT));
/* Set the search key to the vendor's name */
key.data = vendor_name;
key.size = strlen(vendor_name) + 1;
/*
* Make sure we use the memory we set aside for the VENDOR
* structure rather than the memory that DB allocates.
* Some systems may require structures to be aligned in memory
* in a specific way, and DB may not get it right.
*/
data.data = &amp;my_vendor;
data.ulen = sizeof(VENDOR);
data.flags = DB_DBT_USERMEM;
/* Get the record */
ret = vendor_dbp-&gt;get(vendor_dbp, 0, &amp;key, &amp;data, 0);
if (ret != 0) {
vendor_dbp-&gt;err(vendor_dbp, ret, "Error searching for vendor: '%s'",
vendor_name);
return(ret);
} else {
printf("\t\t%s\n", my_vendor.name);
printf("\t\t%s\n", my_vendor.street);
printf("\t\t%s, %s\n", my_vendor.city, my_vendor.state);
printf("\t\t%s\n\n", my_vendor.zipcode);
printf("\t\t%s\n\n", my_vendor.phone_number);
printf("\t\tContact: %s\n", my_vendor.sales_rep);
printf("\t\t%s\n", my_vendor.sales_rep_phone);
}
return(0);
} </pre>
</div>
<p>
That completes the implementation of
<tt class="classname">example_database_read()</tt>. In the next chapter, we
will extend this application to make use of a secondary database so that
we can query the inventory database for a specific inventory item.
</p>
</div>
<div class="navfooter">
<hr />
<table width="100%" summary="Navigation footer">
<tr>
<td width="40%" align="left"><a accesskey="p" href="ReplacingEntryWCursor.html">Prev</a> </td>
<td width="20%" align="center">
<a accesskey="u" href="Cursors.html">Up</a>
</td>
<td width="40%" align="right"> <a accesskey="n" href="indexes.html">Next</a></td>
</tr>
<tr>
<td width="40%" align="left" valign="top">Replacing Records Using Cursors </td>
<td width="20%" align="center">
<a accesskey="h" href="index.html">Home</a>
</td>
<td width="40%" align="right" valign="top"> Chapter 5. Secondary Databases</td>
</tr>
</table>
</div>
</body>
</html>

149
docs/gsg/C/CoreDBAdmin.html Normal file
View File

@@ -0,0 +1,149 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>Administrative Methods</title>
<link rel="stylesheet" href="gettingStarted.css" type="text/css" />
<meta name="generator" content="DocBook XSL Stylesheets V1.62.4" />
<link rel="home" href="index.html" title="Getting Started with Berkeley DB" />
<link rel="up" href="DB.html" title="Chapter 2. Databases" />
<link rel="previous" href="DBOpenFlags.html" title="Database Open Flags" />
<link rel="next" href="dbErrorReporting.html" title="Error Reporting Functions" />
</head>
<body>
<div class="navheader">
<table width="100%" summary="Navigation header">
<tr>
<th colspan="3" align="center">Administrative Methods</th>
</tr>
<tr>
<td width="20%" align="left"><a accesskey="p" href="DBOpenFlags.html">Prev</a> </td>
<th width="60%" align="center">Chapter 2. Databases</th>
<td width="20%" align="right"> <a accesskey="n" href="dbErrorReporting.html">Next</a></td>
</tr>
</table>
<hr />
</div>
<div class="sect1" lang="en" xml:lang="en">
<div class="titlepage">
<div>
<div>
<h2 class="title" style="clear: both"><a id="CoreDBAdmin"></a>Administrative Methods</h2>
</div>
</div>
<div></div>
</div>
<p>
The following
<tt class="classname">DB</tt>
methods may be useful to you when managing DB databases:
</p>
<div class="itemizedlist">
<ul type="disc">
<li>
<p>
<tt class="methodname">DB-&gt;get_open_flags()</tt>
</p>
<p>
Returns the current open flags. It is an error to use this method on
an unopened database.
</p>
<a id="c_db5"></a>
<pre class="programlisting">#include &lt;db.h&gt;
...
DB *dbp;
u_int32_t open_flags;
/* Database open and subsequent operations omitted for clarity */
dbp-&gt;get_open_flags(dbp, &amp;open_flags); </pre>
</li>
<li>
<p>
<tt class="methodname">DB-&gt;remove()</tt>
</p>
<p>
Removes the specified database. If no value is given for the
<i class="parameter"><tt>database</tt></i> parameter, then the entire file
referenced by this method is removed.
</p>
<p>
Never remove a database that has handles opened for it. Never remove a file that
contains databases with opened handles.
</p>
<a id="c_db6"></a>
<pre class="programlisting">#include &lt;db.h&gt;
...
DB *dbp;
/* Database handle creation omitted for clarity */
dbp-&gt;remove(dbp, /* Database pointer */
"mydb.db", /* Database file to remove */
NULL, /* Database to remove. This is
* NULL so the entire file is
* removed. */
0); /* Flags. None used. */</pre>
</li>
<li>
<p>
<tt class="methodname">DB-&gt;rename()</tt>
</p>
<p>
Renames the specified database. If no value is given for the
<i class="parameter"><tt>database</tt></i> parameter, then the entire file
referenced by this method is renamed.
</p>
<p>
Never rename a database that has handles opened for it. Never rename a file that
contains databases with opened handles.
</p>
<a id="c_db7"></a>
<pre class="programlisting">#include &lt;db.h&gt;
...
DB *dbp;
/* Database handle creation omitted for clarity */
dbp-&gt;rename(dbp, /* Database pointer */
"mydb.db", /* Database file to rename */
NULL, /* Database to rename. This is
* NULL so the entire file is
* renamed. */
"newdb.db", /* New database file name */
0); /* Flags. None used. */</pre>
</li>
</ul>
</div>
<span>
</span>
</div>
<div class="navfooter">
<hr />
<table width="100%" summary="Navigation footer">
<tr>
<td width="40%" align="left"><a accesskey="p" href="DBOpenFlags.html">Prev</a> </td>
<td width="20%" align="center">
<a accesskey="u" href="DB.html">Up</a>
</td>
<td width="40%" align="right"> <a accesskey="n" href="dbErrorReporting.html">Next</a></td>
</tr>
<tr>
<td width="40%" align="left" valign="top">Database Open Flags </td>
<td width="20%" align="center">
<a accesskey="h" href="index.html">Home</a>
</td>
<td width="40%" align="right" valign="top"> Error Reporting Functions</td>
</tr>
</table>
</div>
</body>
</html>

299
docs/gsg/C/CoreDbUsage.html Normal file
View File

@@ -0,0 +1,299 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>Database Example</title>
<link rel="stylesheet" href="gettingStarted.css" type="text/css" />
<meta name="generator" content="DocBook XSL Stylesheets V1.62.4" />
<link rel="home" href="index.html" title="Getting Started with Berkeley DB" />
<link rel="up" href="DB.html" title="Chapter 2. Databases" />
<link rel="previous" href="CoreEnvUsage.html" title="Managing Databases in Environments" />
<link rel="next" href="DBEntry.html" title="Chapter 3. Database Records" />
</head>
<body>
<div class="navheader">
<table width="100%" summary="Navigation header">
<tr>
<th colspan="3" align="center">Database Example</th>
</tr>
<tr>
<td width="20%" align="left"><a accesskey="p" href="CoreEnvUsage.html">Prev</a> </td>
<th width="60%" align="center">Chapter 2. Databases</th>
<td width="20%" align="right"> <a accesskey="n" href="DBEntry.html">Next</a></td>
</tr>
</table>
<hr />
</div>
<div class="sect1" lang="en" xml:lang="en">
<div class="titlepage">
<div>
<div>
<h2 class="title" style="clear: both"><a id="CoreDbUsage"></a>Database Example</h2>
</div>
</div>
<div></div>
</div>
<p>
Throughout this book we will build a couple of applications that load
and retrieve inventory data from DB databases. While we are not yet ready to
begin reading from or writing to our databases, we can at least create
some important structures and functions that we will use to manage our
databases.
</p>
<p>
Note that subsequent examples in this book will build on this code to
perform the more interesting work of writing to and reading from the
databases.
</p>
<p>
Note that you can find the complete implementation of these functions
in:
</p>
<pre class="programlisting"><span class="emphasis"><em>DB_INSTALL</em></span>/examples_c/getting_started</pre>
<p>
where <tt class="literal"><span class="emphasis"><em>DB_INSTALL</em></span></tt> is the location where you
placed your DB distribution.
</p>
<div class="example">
<a id="stock-db"></a>
<p class="title">
<b>Example 2.1 The stock_db Structure</b>
</p>
<p>
To begin, we create a structure that we will use to hold all our
database pointers and database names:
</p>
<a id="c_db11"></a>
<pre class="programlisting">/* File: gettingstarted_common.h */
#include &lt;db.h&gt;
typedef struct stock_dbs {
DB *inventory_dbp; /* Database containing inventory information */
DB *vendor_dbp; /* Database containing vendor information */
char *db_home_dir; /* Directory containing the database files */
char *inventory_db_name; /* Name of the inventory database */
char *vendor_db_name; /* Name of the vendor database */
} STOCK_DBS;
/* Function prototypes */
int databases_setup(STOCK_DBS *, const char *, FILE *);
int databases_close(STOCK_DBS *);
void initialize_stockdbs(STOCK_DBS *);
int open_database(DB **, const char *, const char *,
FILE *);
void set_db_filenames(STOCK_DBS *my_stock); </pre>
</div>
<div class="example">
<a id="stock-db-functions"></a>
<p class="title">
<b>Example 2.2 The stock_db Utility Functions</b>
</p>
<p>
Before continuing, we want some utility functions that we use to
make sure the stock_db structure is in a sane state before using it.
One is a simple function that initializes all the structure's
pointers to a useful default.The second is more interesting
in that it is used to place a
common path on all our database names so that we can explicitly
identify where all the database files should reside.
</p>
<a id="c_db12"></a>
<pre class="programlisting">/* File: gettingstarted_common.c */
#include "gettingstarted_common.h"
/* Initializes the STOCK_DBS struct.*/
void
initialize_stockdbs(STOCK_DBS *my_stock)
{
my_stock-&gt;db_home_dir = DEFAULT_HOMEDIR;
my_stock-&gt;inventory_dbp = NULL;
my_stock-&gt;vendor_dbp = NULL;
my_stock-&gt;inventory_db_name = NULL;
my_stock-&gt;vendor_db_name = NULL;
}
/* Identify all the files that will hold our databases. */
void
set_db_filenames(STOCK_DBS *my_stock)
{
size_t size;
/* Create the Inventory DB file name */
size = strlen(my_stock-&gt;db_home_dir) + strlen(INVENTORYDB) + 1;
my_stock-&gt;inventory_db_name = malloc(size);
snprintf(my_stock-&gt;inventory_db_name, size, "%s%s",
my_stock-&gt;db_home_dir, INVENTORYDB);
/* Create the Vendor DB file name */
size = strlen(my_stock-&gt;db_home_dir) + strlen(VENDORDB) + 1;
my_stock-&gt;vendor_db_name = malloc(size);
snprintf(my_stock-&gt;vendor_db_name, size, "%s%s",
my_stock-&gt;db_home_dir, VENDORDB);
} </pre>
</div>
<div class="example">
<a id="open-db"></a>
<p class="title">
<b>Example 2.3 open_database() Function</b>
</p>
<p>
We are opening multiple databases, and we are
opening those databases using identical flags and error reporting
settings. It is therefore worthwhile to create a function that
performs this operation for us:
</p>
<a id="c_db13"></a>
<pre class="programlisting">/* File: gettingstarted_common.c */
/* Opens a database */
int
open_database(DB **dbpp, /* The DB handle that we are opening */
const char *file_name, /* The file in which the db lives */
const char *program_name, /* Name of the program calling this
* function */
FILE *error_file_pointer) /* File where we want error messages sent */
{
DB *dbp; /* For convenience */
u_int32_t open_flags;
int ret;
/* Initialize the DB handle */
ret = db_create(&amp;dbp, NULL, 0);
if (ret != 0) {
fprintf(error_file_pointer, "%s: %s\n", program_name,
db_strerror(ret));
return(ret);
}
/* Point to the memory malloc'd by db_create() */
*dbpp = dbp;
/* Set up error handling for this database */
dbp-&gt;set_errfile(dbp, error_file_pointer);
dbp-&gt;set_errpfx(dbp, program_name);
/* Set the open flags */
open_flags = DB_CREATE;
/* Now open the database */
ret = dbp-&gt;open(dbp, /* Pointer to the database */
NULL, /* Txn pointer */
file_name, /* File name */
NULL, /* Logical db name (unneeded) */
DB_BTREE, /* Database type (using btree) */
open_flags, /* Open flags */
0); /* File mode. Using defaults */
if (ret != 0) {
dbp-&gt;err(dbp, ret, "Database '%s' open failed.", file_name);
return(ret);
}
return (0);
}</pre>
</div>
<div class="example">
<a id="databasesetup"></a>
<p class="title">
<b>Example 2.4 The databases_setup() Function</b>
</p>
<p>
Now that we have our <tt class="function">open_database()</tt> function,
we can use it to open a database. We now create a simple function
that will open all our databases for us.
</p>
<a id="c_db14"></a>
<pre class="programlisting">/* opens all databases */
int
databases_setup(STOCK_DBS *my_stock, const char *program_name,
FILE *error_file_pointer)
{
int ret;
/* Open the vendor database */
ret = open_database(&amp;(my_stock-&gt;vendor_dbp),
my_stock-&gt;vendor_db_name,
program_name, error_file_pointer);
if (ret != 0)
/*
* Error reporting is handled in open_database() so just return
* the return code here.
*/
return (ret);
/* Open the inventory database */
ret = open_database(&amp;(my_stock-&gt;inventory_dbp),
my_stock-&gt;inventory_db_name,
program_name, error_file_pointer);
if (ret != 0)
/*
* Error reporting is handled in open_database() so just return
* the return code here.
*/
return (ret);
printf("databases opened successfully\n");
return (0);
}</pre>
</div>
<div class="example">
<a id="database_close"></a>
<p class="title">
<b>Example 2.5 The databases_close() Function</b>
</p>
<p>
Finally, it is useful to have a function that can close all our databases for us:
</p>
<a id="c_db15"></a>
<pre class="programlisting">/* Closes all the databases. */
int
databases_close(STOCK_DBS *my_stock)
{
int ret;
/*
* Note that closing a database automatically flushes its cached data
* to disk, so no sync is required here.
*/
if (my_stock-&gt;inventory_dbp != NULL) {
ret = my_stock-&gt;inventory_dbp-&gt;close(my_stock-&gt;inventory_dbp, 0);
if (ret != 0)
fprintf(stderr, "Inventory database close failed: %s\n",
db_strerror(ret));
}
if (my_stock-&gt;vendor_dbp != NULL) {
ret = my_stock-&gt;vendor_dbp-&gt;close(my_stock-&gt;vendor_dbp, 0);
if (ret != 0)
fprintf(stderr, "Vendor database close failed: %s\n",
db_strerror(ret));
}
printf("databases closed.\n");
return (0);
} </pre>
</div>
</div>
<div class="navfooter">
<hr />
<table width="100%" summary="Navigation footer">
<tr>
<td width="40%" align="left"><a accesskey="p" href="CoreEnvUsage.html">Prev</a> </td>
<td width="20%" align="center">
<a accesskey="u" href="DB.html">Up</a>
</td>
<td width="40%" align="right"> <a accesskey="n" href="DBEntry.html">Next</a></td>
</tr>
<tr>
<td width="40%" align="left" valign="top">Managing Databases in Environments </td>
<td width="20%" align="center">
<a accesskey="h" href="index.html">Home</a>
</td>
<td width="40%" align="right" valign="top"> Chapter 3. Database Records</td>
</tr>
</table>
</div>
</body>
</html>

View File

@@ -0,0 +1,166 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>Managing Databases in Environments</title>
<link rel="stylesheet" href="gettingStarted.css" type="text/css" />
<meta name="generator" content="DocBook XSL Stylesheets V1.62.4" />
<link rel="home" href="index.html" title="Getting Started with Berkeley DB" />
<link rel="up" href="DB.html" title="Chapter 2. Databases" />
<link rel="previous" href="dbErrorReporting.html" title="Error Reporting Functions" />
<link rel="next" href="CoreDbUsage.html" title="Database Example" />
</head>
<body>
<div class="navheader">
<table width="100%" summary="Navigation header">
<tr>
<th colspan="3" align="center">Managing Databases in Environments</th>
</tr>
<tr>
<td width="20%" align="left"><a accesskey="p" href="dbErrorReporting.html">Prev</a> </td>
<th width="60%" align="center">Chapter 2. Databases</th>
<td width="20%" align="right"> <a accesskey="n" href="CoreDbUsage.html">Next</a></td>
</tr>
</table>
<hr />
</div>
<div class="sect1" lang="en" xml:lang="en">
<div class="titlepage">
<div>
<div>
<h2 class="title" style="clear: both"><a id="CoreEnvUsage"></a>Managing Databases in Environments</h2>
</div>
</div>
<div></div>
</div>
<p>
In
<span>
<a href="environments.html">Environments</a>,
</span>
we introduced
environments. While environments are not used in the example built in this book,
they are so commonly used for a wide class of DB applications that it is
necessary to show their basic usage, if only from a completeness perspective.
</p>
<p>
To use an environment, you must first
<span>
create the environment handle using <tt class="classname"></tt>, and then
</span>
open it. At open time, you must identify the directory in
which it resides. This directory must exist prior to the open attempt.
You can also identify open properties, such as whether the environment can be
created if it does not already exist.
</p>
<p>
You will also need to initialize the in-memory cache when you open your environment.
</p>
<p>
For example, to
<span>create an environment handle and</span>
open an environment:
</p>
<a id="c_env1"></a>
<pre class="programlisting">#include &lt;db.h&gt;
...
DB_ENV *myEnv; /* Env structure handle */
DB *dbp; /* DB structure handle */
u_int32_t db_flags; /* database open flags */
u_int32_t env_flags; /* env open flags */
int ret; /* function return value */
/*
Create an environment object and initialize it for error
reporting.
*/
ret = db_env_create(&amp;myEnv, 0);
if (ret != 0) {
fprintf(stderr, "Error creating env handle: %s\n", db_strerror(ret));
return -1;
}
/* Open the environment. */
env_flags = DB_CREATE | /* If the environment does not exist,
* create it. */
DB_INIT_MPOOL; /* Initialize the in-memory cache. */
ret = myEnv-&gt;open(myEnv, /* DB_ENV ptr */
"/export1/testEnv", /* env home directory */
env_flags, /* Open flags */
0); /* File mode (default) */
if (ret != 0) {
fprintf(stderr, "Environment open failed: %s", db_strerror(ret));
return -1;
} </pre>
<p>
Once an environment is opened, you can open databases in it. Note that by default databases
are stored in the environment's home directory, or relative to that directory if you
provide any sort of a path in the database's file name:
</p>
<a id="c_env2"></a>
<pre class="programlisting">/*
* Initialize the DB structure. Pass the pointer
* to the environment in which this DB is opened.
*/
ret = db_create(&amp;dbp, myEnv, 0);
if (ret != 0) {
/* Error handling goes here */
}
/* Database open flags */
db_flags = DB_CREATE; /* If the database does not exist,
* create it.*/
/* open the database */
ret = dbp-&gt;open(dbp, /* DB structure pointer */
NULL, /* Transaction pointer */
"my_db.db", /* On-disk file that holds the database. */
NULL, /* Optional logical database name */
DB_BTREE, /* Database access method */
db_flags, /* Open flags */
0); /* File mode (using defaults) */
if (ret != 0) {
/* Error handling goes here */
}</pre>
<p>
When you are done with an environment, you must close it. Before you close an environment,
make sure you close any opened databases.
</p>
<a id="c_env3"></a>
<pre class="programlisting">/*
* Close the database and environment
*/
if (dbp != NULL) {
dbp-&gt;close(dbp, 0);
}
if (myEnv != NULL) {
myEnv-&gt;close(myEnv, 0);
} </pre>
</div>
<div class="navfooter">
<hr />
<table width="100%" summary="Navigation footer">
<tr>
<td width="40%" align="left"><a accesskey="p" href="dbErrorReporting.html">Prev</a> </td>
<td width="20%" align="center">
<a accesskey="u" href="DB.html">Up</a>
</td>
<td width="40%" align="right"> <a accesskey="n" href="CoreDbUsage.html">Next</a></td>
</tr>
<tr>
<td width="40%" align="left" valign="top">Error Reporting Functions </td>
<td width="20%" align="center">
<a accesskey="h" href="index.html">Home</a>
</td>
<td width="40%" align="right" valign="top"> Database Example</td>
</tr>
</table>
</div>
</body>
</html>

180
docs/gsg/C/Cursors.html Normal file
View File

@@ -0,0 +1,180 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>Chapter 4. Using Cursors</title>
<link rel="stylesheet" href="gettingStarted.css" type="text/css" />
<meta name="generator" content="DocBook XSL Stylesheets V1.62.4" />
<link rel="home" href="index.html" title="Getting Started with Berkeley DB" />
<link rel="up" href="index.html" title="Getting Started with Berkeley DB" />
<link rel="previous" href="DbUsage.html" title="Database Usage Example" />
<link rel="next" href="Positioning.html" title="Getting Records Using the Cursor" />
</head>
<body>
<div class="navheader">
<table width="100%" summary="Navigation header">
<tr>
<th colspan="3" align="center">Chapter 4. Using Cursors</th>
</tr>
<tr>
<td width="20%" align="left"><a accesskey="p" href="DbUsage.html">Prev</a> </td>
<th width="60%" align="center"> </th>
<td width="20%" align="right"> <a accesskey="n" href="Positioning.html">Next</a></td>
</tr>
</table>
<hr />
</div>
<div class="chapter" lang="en" xml:lang="en">
<div class="titlepage">
<div>
<div>
<h2 class="title"><a id="Cursors"></a>Chapter 4. Using Cursors</h2>
</div>
</div>
<div></div>
</div>
<div class="toc">
<p>
<b>Table of Contents</b>
</p>
<dl>
<dt>
<span class="sect1">
<a href="Cursors.html#openCursor">Opening and Closing Cursors</a>
</span>
</dt>
<dt>
<span class="sect1">
<a href="Positioning.html">Getting Records Using the Cursor</a>
</span>
</dt>
<dd>
<dl>
<dt>
<span class="sect2">
<a href="Positioning.html#cursorsearch">Searching for Records</a>
</span>
</dt>
<dt>
<span class="sect2">
<a href="Positioning.html#getdups">Working with Duplicate Records</a>
</span>
</dt>
</dl>
</dd>
<dt>
<span class="sect1">
<a href="PutEntryWCursor.html">Putting Records Using Cursors</a>
</span>
</dt>
<dt>
<span class="sect1">
<a href="DeleteEntryWCursor.html">Deleting Records Using Cursors</a>
</span>
</dt>
<dt>
<span class="sect1">
<a href="ReplacingEntryWCursor.html">Replacing Records Using Cursors</a>
</span>
</dt>
<dt>
<span class="sect1">
<a href="CoreCursorUsage.html">Cursor Example</a>
</span>
</dt>
</dl>
</div>
<p>
Cursors provide a mechanism by which you can iterate over the records in a
database. Using cursors, you can get, put, and delete database records. If
a database allows duplicate records, then cursors are
<span>the easiest way that you can access anything
other than the first record for a given key.</span>
</p>
<p>
This chapter introduces cursors. It explains how to open and close them, how
to use them to modify databases, and how to use them with duplicate records.
</p>
<div class="sect1" lang="en" xml:lang="en">
<div class="titlepage">
<div>
<div>
<h2 class="title" style="clear: both"><a id="openCursor"></a>Opening and Closing Cursors</h2>
</div>
</div>
<div></div>
</div>
<p>
Cursors are managed using the
<span><tt class="classname">DBC</tt> structure.</span>
To use a cursor, you must open it using the
<tt class="methodname">DB-&gt;cursor()</tt>
method.
</p>
<p>For example:</p>
<a id="c_cursor1"></a>
<pre class="programlisting">#include &lt;db.h&gt;
...
DB *my_database;
DBC *cursorp;
/* Database open omitted for clarity */
/* Get a cursor */
my_database-&gt;cursor(my_database, NULL, &amp;cursorp, 0); </pre>
<p>
When you are done with the cursor, you should close it. To close a
cursor, call the
<tt class="methodname">DBC-&gt;close()</tt>
method. Note that closing your database while cursors are still opened
within the scope of the DB handle, especially if those cursors are
writing to the database, can have unpredictable results. Always
close your cursors before closing your database.
</p>
<a id="c_cursor2"></a>
<pre class="programlisting">#include &lt;db.h&gt;
...
DB *my_database;
DBC *cursorp;
/* Database and cursor open omitted for clarity */
if (cursorp != NULL)
cursorp-&gt;close(cursorp);
if (my_database != NULL)
my_database-&gt;close(my_database, 0); </pre>
</div>
</div>
<div class="navfooter">
<hr />
<table width="100%" summary="Navigation footer">
<tr>
<td width="40%" align="left"><a accesskey="p" href="DbUsage.html">Prev</a> </td>
<td width="20%" align="center">
<a accesskey="u" href="index.html">Up</a>
</td>
<td width="40%" align="right"> <a accesskey="n" href="Positioning.html">Next</a></td>
</tr>
<tr>
<td width="40%" align="left" valign="top">Database Usage Example </td>
<td width="20%" align="center">
<a accesskey="h" href="index.html">Home</a>
</td>
<td width="40%" align="right" valign="top"> Getting Records Using the Cursor</td>
</tr>
</table>
</div>
</body>
</html>

191
docs/gsg/C/DB.html Normal file
View File

@@ -0,0 +1,191 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>Chapter 2. Databases</title>
<link rel="stylesheet" href="gettingStarted.css" type="text/css" />
<meta name="generator" content="DocBook XSL Stylesheets V1.62.4" />
<link rel="home" href="index.html" title="Getting Started with Berkeley DB" />
<link rel="up" href="index.html" title="Getting Started with Berkeley DB" />
<link rel="previous" href="gettingit.html" title="Getting and Using DB " />
<link rel="next" href="coredbclose.html" title="Closing Databases" />
</head>
<body>
<div class="navheader">
<table width="100%" summary="Navigation header">
<tr>
<th colspan="3" align="center">Chapter 2. Databases</th>
</tr>
<tr>
<td width="20%" align="left"><a accesskey="p" href="gettingit.html">Prev</a> </td>
<th width="60%" align="center"> </th>
<td width="20%" align="right"> <a accesskey="n" href="coredbclose.html">Next</a></td>
</tr>
</table>
<hr />
</div>
<div class="chapter" lang="en" xml:lang="en">
<div class="titlepage">
<div>
<div>
<h2 class="title"><a id="DB"></a>Chapter 2. Databases</h2>
</div>
</div>
<div></div>
</div>
<div class="toc">
<p>
<b>Table of Contents</b>
</p>
<dl>
<dt>
<span class="sect1">
<a href="DB.html#DBOpen">Opening Databases</a>
</span>
</dt>
<dt>
<span class="sect1">
<a href="coredbclose.html">Closing Databases</a>
</span>
</dt>
<dt>
<span class="sect1">
<a href="DBOpenFlags.html">Database Open Flags</a>
</span>
</dt>
<dt>
<span class="sect1">
<a href="CoreDBAdmin.html">Administrative Methods</a>
</span>
</dt>
<dt>
<span class="sect1">
<a href="dbErrorReporting.html">Error Reporting Functions</a>
</span>
</dt>
<dt>
<span class="sect1">
<a href="CoreEnvUsage.html">Managing Databases in Environments</a>
</span>
</dt>
<dt>
<span class="sect1">
<a href="CoreDbUsage.html">Database Example</a>
</span>
</dt>
</dl>
</div>
<p>In Berkeley DB, a database is a collection of <span class="emphasis"><em>records</em></span>. Records,
in turn, consist of key/data pairings.
</p>
<p>
Conceptually, you can think of a
<span>database</span>
as containing a two-column table where column 1 contains a key and column 2
contains data. Both the key and the data are managed using
<tt class="classname">DBT</tt>
<span>structures</span>
(see <a href="DBEntry.html">Database Records</a> for details on this
<span>structure</span>).
So, fundamentally, using a DB
<span>database</span>
involves putting, getting, and deleting database records, which in turns involves efficiently
managing information
<span>contained in </span>
<tt class="classname">DBT</tt>
<span>structures.</span>
The next several chapters of this book are dedicated to those activities.
</p>
<div class="sect1" lang="en" xml:lang="en">
<div class="titlepage">
<div>
<div>
<h2 class="title" style="clear: both"><a id="DBOpen"></a>Opening Databases</h2>
</div>
</div>
<div></div>
</div>
<p>
To open a database, you must first use the <tt class="function">db_create()</tt> function to
initialize a <tt class="classname">DB</tt> handle.
Once you have initialized the <tt class="classname">DB</tt>
handle, you use its <tt class="methodname">open()</tt> method to open the database.
</p>
<p>
Note that by default, DB does not create databases if they do not already exist.
To override this behavior, specify the
<a href="DBOpenFlags.html" title="Database Open Flags"><tt class="literal">DB_CREATE</tt></a> flag on the
<tt class="methodname">open()</tt> method.
</p>
<p>
The following code fragment illustrates a database open:
</p>
<a id="c_db1"></a>
<pre class="programlisting">#include &lt;db.h&gt;
...
DB *dbp; /* DB structure handle */
u_int32_t flags; /* database open flags */
int ret; /* function return value */
/* Initialize the structure. This
* database is not opened in an environment,
* so the environment pointer is NULL. */
ret = db_create(&amp;dbp, NULL, 0);
if (ret != 0) {
/* Error handling goes here */
}
/* Database open flags */
flags = DB_CREATE; /* If the database does not exist,
* create it.*/
/* open the database */
ret = dbp-&gt;open(dbp, /* DB structure pointer */
NULL, /* Transaction pointer */
"my_db.db", /* On-disk file that holds the database. */
NULL, /* Optional logical database name */
DB_BTREE, /* Database access method */
flags, /* Open flags */
0); /* File mode (using defaults) */
if (ret != 0) {
/* Error handling goes here */
}</pre>
</div>
</div>
<div class="navfooter">
<hr />
<table width="100%" summary="Navigation footer">
<tr>
<td width="40%" align="left"><a accesskey="p" href="gettingit.html">Prev</a> </td>
<td width="20%" align="center">
<a accesskey="u" href="index.html">Up</a>
</td>
<td width="40%" align="right"> <a accesskey="n" href="coredbclose.html">Next</a></td>
</tr>
<tr>
<td width="40%" align="left" valign="top">Getting and Using DB  </td>
<td width="20%" align="center">
<a accesskey="h" href="index.html">Home</a>
</td>
<td width="40%" align="right" valign="top"> Closing Databases</td>
</tr>
</table>
</div>
</body>
</html>

230
docs/gsg/C/DBEntry.html Normal file
View File

@@ -0,0 +1,230 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>Chapter 3. Database Records</title>
<link rel="stylesheet" href="gettingStarted.css" type="text/css" />
<meta name="generator" content="DocBook XSL Stylesheets V1.62.4" />
<link rel="home" href="index.html" title="Getting Started with Berkeley DB" />
<link rel="up" href="index.html" title="Getting Started with Berkeley DB" />
<link rel="previous" href="CoreDbUsage.html" title="Database Example" />
<link rel="next" href="usingDbt.html" title="Reading and Writing Database Records" />
</head>
<body>
<div class="navheader">
<table width="100%" summary="Navigation header">
<tr>
<th colspan="3" align="center">Chapter 3. Database Records</th>
</tr>
<tr>
<td width="20%" align="left"><a accesskey="p" href="CoreDbUsage.html">Prev</a> </td>
<th width="60%" align="center"> </th>
<td width="20%" align="right"> <a accesskey="n" href="usingDbt.html">Next</a></td>
</tr>
</table>
<hr />
</div>
<div class="chapter" lang="en" xml:lang="en">
<div class="titlepage">
<div>
<div>
<h2 class="title"><a id="DBEntry"></a>Chapter 3. Database Records</h2>
</div>
</div>
<div></div>
</div>
<div class="toc">
<p>
<b>Table of Contents</b>
</p>
<dl>
<dt>
<span class="sect1">
<a href="DBEntry.html#usingDbEntry">Using Database Records</a>
</span>
</dt>
<dt>
<span class="sect1">
<a href="usingDbt.html">Reading and Writing Database Records</a>
</span>
</dt>
<dd>
<dl>
<dt>
<span class="sect2">
<a href="usingDbt.html#databaseWrite">Writing Records to the Database</a>
</span>
</dt>
<dt>
<span class="sect2">
<a href="usingDbt.html#CoreDatabaseRead">Getting Records from the Database</a>
</span>
</dt>
<dt>
<span class="sect2">
<a href="usingDbt.html#recordDelete">Deleting Records</a>
</span>
</dt>
<dt>
<span class="sect2">
<a href="usingDbt.html#datapersist">Data Persistence</a>
</span>
</dt>
</dl>
</dd>
<dt>
<span class="sect1">
<a href="cstructs.html">Using C Structures with DB</a>
</span>
</dt>
<dd>
<dl>
<dt>
<span class="sect2">
<a href="cstructs.html#cstructdynamic">C Structures with Pointers</a>
</span>
</dt>
</dl>
</dd>
<dt>
<span class="sect1">
<a href="DbUsage.html">Database Usage Example</a>
</span>
</dt>
</dl>
</div>
<p>
DB records contain two parts — a key and some data. Both the key
and its corresponding data are
encapsulated in
<span><tt class="classname">DBT</tt> structures.</span>
Therefore, to access a DB record, you need two such
<span>structures,</span>
one for the key and
one for the data.
</p>
<p>
<tt class="classname">DBT</tt> structures provide a <tt class="literal">void *</tt>
field that you use to point to your data, and another field that identifies
the data length. They can therefore be used to store anything from simple
primitive data to complex structures so long as the information you want to
store resides in a single contiguous block of memory.
</p>
<p>
This chapter describes
<tt class="classname">DBT</tt>
usage. It also
introduces storing and retrieving key/value pairs from a database.
</p>
<div class="sect1" lang="en" xml:lang="en">
<div class="titlepage">
<div>
<div>
<h2 class="title" style="clear: both"><a id="usingDbEntry"></a>Using Database Records</h2>
</div>
</div>
<div></div>
</div>
<p>
Each database record is comprised of two
<span><tt class="classname">DBT</tt> structures</span>
— one for the key and another for the data.
</p>
<p>
To store a database record where the key and/or the data are primitive
data (<tt class="literal">int</tt>, <tt class="literal">float</tt>, and so forth),
or where the key and/or the data contain an array, we need only to point
to the memory location where that data resides and identify its
length. For example:
</p>
<a id="c_dbt1"></a>
<pre class="programlisting">#include &lt;db.h&gt;
#include &lt;string.h&gt;
...
DBT key, data;
float money = 122.45;
char *description = "Grocery bill.";
/* Zero out the DBTs before using them. */
memset(&amp;key, 0, sizeof(DBT));
memset(&amp;data, 0, sizeof(DBT));
key.data = &amp;money;
key.size = sizeof(float);
data.data = description;
data.size = strlen(description) + 1; </pre>
<p>
To retrieve the record, simply assign the <tt class="literal">void *</tt> returned in the
<tt class="methodname">DBT</tt>
to the appropriate variable.
</p>
<p>
Note that in the following example we do not allow DB to assign the
memory for the retrieval of the money value. The reason why is that some
systems may require float values to have a specific alignment, and the
memory as returned by DB
may not be properly aligned (the same problem may exist for structures
on some systems). We tell DB to use our memory instead of its
own by specifying the <tt class="literal">DB_DBT_USERMEM</tt> flag. Be aware that
when we do this, we must also identify how much user memory is available
through the use of the <tt class="literal">ulen</tt> field.
</p>
<a id="c_dbt2"></a>
<pre class="programlisting">#include &lt;db.h&gt;
#include &lt;string.h&gt;
...
float money;
DBT key, data;
char *description;
/* Initialize the DBTs */
memset(&amp;key, 0, sizeof(DBT));
memset(&amp;data, 0, sizeof(DBT));
key.data = &amp;money;
key.ulen = sizeof(float);
key.flags = DB_DBT_USERMEM;
/* Database retrieval code goes here */
/*
* Money is set into the memory that we supplied.
*/
description = data.data;</pre>
</div>
</div>
<div class="navfooter">
<hr />
<table width="100%" summary="Navigation footer">
<tr>
<td width="40%" align="left"><a accesskey="p" href="CoreDbUsage.html">Prev</a> </td>
<td width="20%" align="center">
<a accesskey="u" href="index.html">Up</a>
</td>
<td width="40%" align="right"> <a accesskey="n" href="usingDbt.html">Next</a></td>
</tr>
<tr>
<td width="40%" align="left" valign="top">Database Example </td>
<td width="20%" align="center">
<a accesskey="h" href="index.html">Home</a>
</td>
<td width="40%" align="right" valign="top"> Reading and Writing Database Records</td>
</tr>
</table>
</div>
</body>
</html>

118
docs/gsg/C/DBOpenFlags.html Normal file
View File

@@ -0,0 +1,118 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>Database Open Flags</title>
<link rel="stylesheet" href="gettingStarted.css" type="text/css" />
<meta name="generator" content="DocBook XSL Stylesheets V1.62.4" />
<link rel="home" href="index.html" title="Getting Started with Berkeley DB" />
<link rel="up" href="DB.html" title="Chapter 2. Databases" />
<link rel="previous" href="coredbclose.html" title="Closing Databases" />
<link rel="next" href="CoreDBAdmin.html" title="Administrative Methods" />
</head>
<body>
<div class="navheader">
<table width="100%" summary="Navigation header">
<tr>
<th colspan="3" align="center">Database Open Flags</th>
</tr>
<tr>
<td width="20%" align="left"><a accesskey="p" href="coredbclose.html">Prev</a> </td>
<th width="60%" align="center">Chapter 2. Databases</th>
<td width="20%" align="right"> <a accesskey="n" href="CoreDBAdmin.html">Next</a></td>
</tr>
</table>
<hr />
</div>
<div class="sect1" lang="en" xml:lang="en">
<div class="titlepage">
<div>
<div>
<h2 class="title" style="clear: both"><a id="DBOpenFlags"></a>Database Open Flags</h2>
</div>
</div>
<div></div>
</div>
<p>
The following are the flags that you may want to use at database open time.
Note that this list is not exhaustive — it includes only those flags likely
to be of interest for introductory, single-threaded
database applications. For a complete list of the flags available to you, see the
<i class="citetitle">Berkeley DB C API guide.</i>
</p>
<div class="note" style="margin-left: 0.5in; margin-right: 0.5in;">
<h3 class="title">Note</h3>
<p>
To specify more than one flag on the call to
<span><tt class="methodname">DB-&gt;open()</tt>,</span>
you must bitwise inclusively OR them together:
</p>
<a id="c_db3"></a>
<pre class="programlisting">u_int32_t open_flags = DB_CREATE | DB_EXCL;</pre>
</div>
<div class="itemizedlist">
<ul type="disc">
<li>
<p>
<tt class="literal">DB_CREATE</tt>
</p>
<p>
If the database does not currently exist, create it. By default, the database open
fails if the database does not already exist.
</p>
</li>
<li>
<p>
<tt class="literal">DB_EXCL</tt>
</p>
<p>
Exclusive database creation. Causes the database open to fail if the database
already exists. This flag is only meaningful when used with
<tt class="literal">DB_CREATE</tt>.
</p>
</li>
<li>
<p>
<tt class="literal">DB_RDONLY</tt>
</p>
<p>
Open the database for read operations only. Causes any subsequent database write
operations to fail.
</p>
</li>
<li>
<p>
<tt class="literal">DB_TRUNCATE</tt>
</p>
<p>
Physically truncate (empty) the on-disk file that contains the database.
Causes DB to delete all databases physically contained in that file.
</p>
</li>
</ul>
</div>
</div>
<div class="navfooter">
<hr />
<table width="100%" summary="Navigation footer">
<tr>
<td width="40%" align="left"><a accesskey="p" href="coredbclose.html">Prev</a> </td>
<td width="20%" align="center">
<a accesskey="u" href="DB.html">Up</a>
</td>
<td width="40%" align="right"> <a accesskey="n" href="CoreDBAdmin.html">Next</a></td>
</tr>
<tr>
<td width="40%" align="left" valign="top">Closing Databases </td>
<td width="20%" align="center">
<a accesskey="h" href="index.html">Home</a>
</td>
<td width="40%" align="right" valign="top"> Administrative Methods</td>
</tr>
</table>
</div>
</body>
</html>

478
docs/gsg/C/DbUsage.html Normal file
View File

@@ -0,0 +1,478 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>Database Usage Example</title>
<link rel="stylesheet" href="gettingStarted.css" type="text/css" />
<meta name="generator" content="DocBook XSL Stylesheets V1.62.4" />
<link rel="home" href="index.html" title="Getting Started with Berkeley DB" />
<link rel="up" href="DBEntry.html" title="Chapter 3. Database Records" />
<link rel="previous" href="cstructs.html" title="Using C Structures with DB" />
<link rel="next" href="Cursors.html" title="Chapter 4. Using Cursors" />
</head>
<body>
<div class="navheader">
<table width="100%" summary="Navigation header">
<tr>
<th colspan="3" align="center">Database Usage Example</th>
</tr>
<tr>
<td width="20%" align="left"><a accesskey="p" href="cstructs.html">Prev</a> </td>
<th width="60%" align="center">Chapter 3. Database Records</th>
<td width="20%" align="right"> <a accesskey="n" href="Cursors.html">Next</a></td>
</tr>
</table>
<hr />
</div>
<div class="sect1" lang="en" xml:lang="en">
<div class="titlepage">
<div>
<div>
<h2 class="title" style="clear: both"><a id="DbUsage"></a>Database Usage Example</h2>
</div>
</div>
<div></div>
</div>
<p>
In <a href="CoreDbUsage.html">Database Example</a> we created several
functions that will open and close the databases that we will use for
our inventory application. We now make use of those functions to load inventory data into
the two databases that we use for this application.
</p>
<p>
Again, remember that you can find the complete implementation for these functions
in:
</p>
<pre class="programlisting"><span class="emphasis"><em>DB_INSTALL</em></span>/examples_c/getting_started</pre>
<p>
where <tt class="literal"><span class="emphasis"><em>DB_INSTALL</em></span></tt> is the location where you
placed your DB distribution.
</p>
<div class="example">
<a id="VENDORStruct"></a>
<p class="title">
<b>Example 3.1 VENDOR Structure</b>
</p>
<p>
We want to store data related to an inventory system. There are two
types of information that we want to manage: inventory data and related
vendor contact information. To manage this information, we could
create a structure for each type of data, but to illustrate
storing mixed data without a structure we refrain from creating one
for the inventory data.
</p>
<p>
For the vendor data, we add the VENDOR structure to the same file as holds
our STOCK_DBS structure. Note that the VENDOR structure uses
fixed-length fields. This is not necessary and in fact could
represent a waste of resources if the number of vendors stored in
our database scales to very large numbers. However, for simplicity we use
fixed-length fields anyway, especially
given that our sample data contains so few vendor records.
</p>
<p>
Note that for the inventory data, we will store the data by
marshaling it into a buffer, described below.
</p>
<a id="c_dbt10"></a>
<pre class="programlisting">/* File: gettingstarted_common.h */
#include &lt;db.h&gt;
...
<b class="userinput"><tt>typedef struct vendor {
char name[MAXFIELD]; /* Vendor name */
char street[MAXFIELD]; /* Street name and number */
char city[MAXFIELD]; /* City */
char state[3]; /* Two-digit US state code */
char zipcode[6]; /* US zipcode */
char phone_number[13]; /* Vendor phone number */
char sales_rep[MAXFIELD]; /* Name of sales representative */
char sales_rep_phone[MAXFIELD]; /* Sales rep's phone number */
} VENDOR;</tt></b> </pre>
</div>
<div class="example">
<a id="exampledbload"></a>
<p class="title">
<b>Example 3.2 example_database_load</b>
</p>
<p>
Our initial sample application will load database information from
several flat files. To save space, we won't show all the details of
this example program. However, as always you can find the complete
implementation for this program here:
</p>
<pre class="programlisting"><span class="emphasis"><em>DB_INSTALL</em></span>/examples_c/getting_started</pre>
<p>
where <tt class="literal"><span class="emphasis"><em>DB_INSTALL</em></span></tt> is the location where you
placed your DB distribution.
</p>
<p>
We begin with the normal include directives and forward declarations:
</p>
<a id="c_dbt11"></a>
<pre class="programlisting">/* example_database_load.c */
#include "gettingstarted_common.h"
/* Forward declarations */
int load_vendors_database(STOCK_DBS, char *);
int pack_string(char *, char *, int);
int load_inventory_database(STOCK_DBS, char *); </pre>
<p>
Next we begin our <tt class="function">main()</tt> function with the variable
declarations and command line parsing that is normal for most command
line applications:
</p>
<a id="c_dbt12"></a>
<pre class="programlisting">/*
* Loads the contents of vendors.txt and inventory.txt into
* Berkeley DB databases.
*/
int
main(int argc, char *argv[])
{
STOCK_DBS my_stock;
int ret, size;
char *basename, *inventory_file, *vendor_file;
/* Initialize the STOCK_DBS struct */
initialize_stockdbs(&amp;my_stock);
/*
* Initialize the base path. This path is used to
* identify the location of the flat-text data
* input files.
*/
basename = "./";
/*
* Parse the command line arguments here and determine
* the location of the flat text files containing the
* inventory data here. This step is omitted for clarity.
*/
/*
* Identify the files that will hold our databases
* This function uses information obtained from the
* command line to identify the directory in which
* the database files reside.
*/
set_db_filenames(&amp;my_stock);
/* Find our input files */
size = strlen(basename) + strlen(INVENTORY_FILE) + 1;
inventory_file = malloc(size);
snprintf(inventory_file, size, "%s%s", basename, INVENTORY_FILE);
size = strlen(basename) + strlen(VENDORS_FILE) + 1;
vendor_file = malloc(size);
snprintf(vendor_file, size, "%s%s", basename, VENDORS_FILE);
/* Open all databases */
ret = databases_setup(&amp;my_stock, "example_database_load", stderr);
if (ret != 0) {
fprintf(stderr, "Error opening databases\n");
databases_close(&amp;my_stock);
return (ret);
}
ret = load_vendors_database(my_stock, vendor_file);
if (!ret) {
fprintf(stderr, "Error loading vendors database.\n");
databases_close(&amp;my_stock);
return (ret);
}
ret = load_inventory_database(my_stock, inventory_file);
if (!ret) {
fprintf(stderr, "Error loading inventory database.\n");
databases_close(&amp;my_stock);
return (ret);
}
/* close our environment and databases */
databases_close(&amp;my_stock);
printf("Done loading databases.\n");
return (0);
}</pre>
<p>
Notice that there is not a lot to this function because we have pushed
off all the database activity to other places. In particular our
databases are all opened and configured in
<tt class="function">databases_setup()</tt> which we implemented in
<a href="CoreDbUsage.html#databasesetup">The databases_setup() Function</a>.
</p>
<p>
Next we show the implementation of
<tt class="function">load_vendors_database()</tt>. We load this data by
scanning (line by line) the contents of the
<tt class="filename">vendors.txt</tt> into a VENDOR structure. Once we have a
line scanned into the structure, we can store that structure into our
vendors database.
</p>
<p>
Note that we use the vendor's name as the key here. In doing so, we
assume that the vendor's name is unique in our database. If it was not,
we would either have to select a different key, or architect our
application such that it could cope with multiple vendor records with
the same name.
</p>
<a id="c_dbt13"></a>
<pre class="programlisting">/*
* Loads the contents of the vendors.txt file into
* a database.
*/
int
load_vendors_database(STOCK_DBS my_stock, char *vendor_file)
{
DBT key, data;
FILE *ifp;
VENDOR my_vendor;
char buf[MAXLINE];
/* Open the vendor file for read access */
ifp = fopen(vendor_file, "r");
if (ifp == NULL) {
fprintf(stderr, "Error opening file '%s'\n", vendor_file);
return(-1);
}
/* Iterate over the vendor file */
while(fgets(buf, MAXLINE, ifp) != NULL) {
/* zero out the structure */
memset(&amp;my_vendor, 0, sizeof(VENDOR));
/* Zero out the DBTs */
memset(&amp;key, 0, sizeof(DBT));
memset(&amp;data, 0, sizeof(DBT));
/*
* Scan the line into the structure.
* Convenient, but not particularly safe.
* In a real program, there would be a lot more
* defensive code here.
*/
sscanf(buf,
"%20[^#]#%20[^#]#%20[^#]#%3[^#]#%6[^#]#%13[^#]#%20[^#]#%20[^\n]",
my_vendor.name, my_vendor.street,
my_vendor.city, my_vendor.state,
my_vendor.zipcode, my_vendor.phone_number,
my_vendor.sales_rep, my_vendor.sales_rep_phone);
/*
* Now that we have our structure we can load it
* into the database.
*/
/* Set up the database record's key */
key.data = my_vendor.name;
key.size = strlen(my_vendor.name) + 1;
/* Set up the database record's data */
data.data = &amp;my_vendor;
data.size = sizeof(my_vendor);
/*
* Note that given the way we built our struct, there are extra
* bytes in it. Essentially we're using fixed-width fields with
* the unused portion of some fields padded with zeros. This
* is the easiest thing to do, but it does result in a bloated
* database. Look at load_inventory_data() for an example of how
* to avoid this.
*/
/* Put the data into the database.
* Omitting error handling for clarity.
*/
my_stock.vendor_dbp-&gt;put(my_stock.vendor_dbp, 0, &amp;key, &amp;data, 0);
} /* end vendors database while loop */
/* Close the vendor.txt file */
fclose(ifp);
return(0);
} </pre>
<p>
Finally, we need to write the
<tt class="function">load_inventory_database()</tt> function. We made this function a
bit more complicated than is necessary by avoiding the use of a
structure to manage the data. Instead, we manually pack all our inventory
data into a single block of memory, and store that data in the
database.
</p>
<p>
While this complicates our code somewhat, this approach allows us to
use the smallest amount of space possible for the data that we want to
store. The result is that our cache can be smaller than it might
otherwise be and our database will take less space on disk than if we used
a structure with fixed-length fields.
</p>
<p>
For a trivial dataset such as what we use for these examples, these
resource savings are negligible. But if we were storing hundreds of
millions of records, then the cost savings may become significant.
</p>
<p>
Before we actually implement our inventory loading function, it is useful
to create a simple utility function that copies a character array into a
buffer at a designated offset:
</p>
<a id="c_dbt14"></a>
<pre class="programlisting">/*
* Simple little convenience function that takes a buffer, a string,
* and an offset and copies that string into the buffer at the
* appropriate location. Used to ensure that all our strings
* are contained in a single contiguous chunk of memory.
*/
int
pack_string(char *buffer, char *string, int start_pos)
{
int string_size = strlen(string) + 1;
memcpy(buffer+start_pos, string, string_size);
return(start_pos + string_size);
} </pre>
<p>
That done, we can now load the inventory database:
</p>
<a id="c_dbt15"></a>
<pre class="programlisting">/*
* Loads the contents of the inventory.txt file into
* a database.
*/
int
load_inventory_database(STOCK_DBS my_stock, char *inventory_file)
{
DBT key, data;
char buf[MAXLINE];
void *databuf;
int bufLen, dataLen;
FILE *ifp;
/*
* Rather than lining everything up nicely in a struct, we're being
* deliberately a bit sloppy here. This function illustrates how to
* store mixed data that might be obtained from various locations
* in your application.
*/
float price;
int quantity;
char category[MAXFIELD], name[MAXFIELD];
char vendor[MAXFIELD], sku[MAXFIELD];
/* Load the inventory database */
ifp = fopen(inventory_file, "r");
if (ifp == NULL) {
fprintf(stderr, "Error opening file '%s'\n", inventory_file);
return(-1);
}
/* Get our buffer. MAXDATABUF is some suitably large number */
databuf = malloc(MAXDATABUF);
/*
* Read the inventory.txt file line by line, saving each line off to the
* database as we go.
*/
while(fgets(buf, MAXLINE, ifp) != NULL) {
/*
* Scan the line into the appropriate buffers and variables.
* Convenient, but not particularly safe. In a real
* program, there would be a lot more defensive code here.
*/
sscanf(buf,
"%20[^#]#%20[^#]#%f#%i#%20[^#]#%20[^\n]",
name, sku, &amp;price, &amp;quantity, category, vendor);
/*
* Now pack it into a single contiguous memory location for
* storage.
*/
memset(databuf, 0, MAXDATABUF);
bufLen = 0;
dataLen = 0;
/*
* We first store the fixed-length elements. This makes our code to
* retrieve this data from the database a little bit easier.
*/
/* First discover how long the data element is. */
dataLen = sizeof(float);
/* Then copy it to our buffer */
memcpy(databuf, &amp;price, dataLen);
/*
* Then figure out how much data is actually in our buffer.
* We repeat this pattern for all the data we want to store.
*/
bufLen += dataLen;
/* Rinse, lather, repeat. */
dataLen = sizeof(int);
memcpy(databuf + bufLen, &amp;quantity, dataLen);
bufLen += dataLen;
bufLen = pack_string(databuf, name, bufLen);
bufLen = pack_string(databuf, sku, bufLen);
bufLen = pack_string(databuf, category, bufLen);
bufLen = pack_string(databuf, vendor, bufLen);
/*
* Now actually save the contents of the buffer off
* to our database.
*/
/* Zero out the DBTs */
memset(&amp;key, 0, sizeof(DBT));
memset(&amp;data, 0, sizeof(DBT));
/*
* The key is the item's SKU. This is a unique value, so we need not
* support duplicates for this database.
*/
key.data = sku;
key.size = strlen(sku) + 1;
/* The data is the information that we packed into databuf. */
data.data = databuf;
data.size = bufLen;
/* Put the data into the database */
my_stock.vendor_dbp-&gt;put(my_stock.inventory_dbp, 0, &amp;key, &amp;data, 0);
} /* end vendors database while loop */
/* Cleanup */
fclose(ifp);
if (databuf != NULL)
free(databuf);
return(0);
} </pre>
<p>
In the next chapter we provide an example that shows how to read
the inventory and vendor databases.
</p>
</div>
</div>
<div class="navfooter">
<hr />
<table width="100%" summary="Navigation footer">
<tr>
<td width="40%" align="left"><a accesskey="p" href="cstructs.html">Prev</a> </td>
<td width="20%" align="center">
<a accesskey="u" href="DBEntry.html">Up</a>
</td>
<td width="40%" align="right"> <a accesskey="n" href="Cursors.html">Next</a></td>
</tr>
<tr>
<td width="40%" align="left" valign="top">Using C Structures with DB </td>
<td width="20%" align="center">
<a accesskey="h" href="index.html">Home</a>
</td>
<td width="40%" align="right" valign="top"> Chapter 4. Using Cursors</td>
</tr>
</table>
</div>
</body>
</html>

View File

@@ -0,0 +1,109 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>Deleting Records Using Cursors</title>
<link rel="stylesheet" href="gettingStarted.css" type="text/css" />
<meta name="generator" content="DocBook XSL Stylesheets V1.62.4" />
<link rel="home" href="index.html" title="Getting Started with Berkeley DB" />
<link rel="up" href="Cursors.html" title="Chapter 4. Using Cursors" />
<link rel="previous" href="PutEntryWCursor.html" title="Putting Records Using Cursors" />
<link rel="next" href="ReplacingEntryWCursor.html" title="Replacing Records Using Cursors" />
</head>
<body>
<div class="navheader">
<table width="100%" summary="Navigation header">
<tr>
<th colspan="3" align="center">Deleting Records Using Cursors</th>
</tr>
<tr>
<td width="20%" align="left"><a accesskey="p" href="PutEntryWCursor.html">Prev</a> </td>
<th width="60%" align="center">Chapter 4. Using Cursors</th>
<td width="20%" align="right"> <a accesskey="n" href="ReplacingEntryWCursor.html">Next</a></td>
</tr>
</table>
<hr />
</div>
<div class="sect1" lang="en" xml:lang="en">
<div class="titlepage">
<div>
<div>
<h2 class="title" style="clear: both"><a id="DeleteEntryWCursor"></a>Deleting Records Using Cursors</h2>
</div>
</div>
<div></div>
</div>
<p>
To delete a record using a cursor, simply position the cursor to the
record that you want to delete and then call
<span>
<span><tt class="methodname">DBC-&gt;del()</tt>.</span>
</span>
</p>
<p>For example:</p>
<a id="c_cursor8"></a>
<pre class="programlisting">#include &lt;db.h&gt;
#include &lt;string.h&gt;
...
DB *dbp;
DBC *cursorp;
DBT key, data;
char *key1str = "My first string";
int ret;
/* Database open omitted */
/* Initialize our DBTs. */
memset(&amp;key, 0, sizeof(DBT));
memset(&amp;data, 0, sizeof(DBT));
/* Set up our DBTs */
key.data = key1str;
key.size = strlen(key1str) + 1;
/* Get the cursor */
dbp-&gt;cursor(dbp, NULL, &amp;cursorp, 0);
/* Iterate over the database, deleting each record in turn. */
while ((ret = cursorp-&gt;get(cursorp, &amp;key,
&amp;data, DB_SET)) == 0) {
cursorp-&gt;del(cursorp, 0);
}
/* Cursors must be closed */
if (cursorp != NULL)
cursorp-&gt;close(cursorp);
if (dbp != NULL)
dbp-&gt;close(dbp, 0);</pre>
</div>
<div class="navfooter">
<hr />
<table width="100%" summary="Navigation footer">
<tr>
<td width="40%" align="left"><a accesskey="p" href="PutEntryWCursor.html">Prev</a> </td>
<td width="20%" align="center">
<a accesskey="u" href="Cursors.html">Up</a>
</td>
<td width="40%" align="right"> <a accesskey="n" href="ReplacingEntryWCursor.html">Next</a></td>
</tr>
<tr>
<td width="40%" align="left" valign="top">Putting Records Using Cursors </td>
<td width="20%" align="center">
<a accesskey="h" href="index.html">Home</a>
</td>
<td width="40%" align="right" valign="top"> Replacing Records Using Cursors</td>
</tr>
</table>
</div>
</body>
</html>

573
docs/gsg/C/Positioning.html Normal file
View File

@@ -0,0 +1,573 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>Getting Records Using the Cursor</title>
<link rel="stylesheet" href="gettingStarted.css" type="text/css" />
<meta name="generator" content="DocBook XSL Stylesheets V1.62.4" />
<link rel="home" href="index.html" title="Getting Started with Berkeley DB" />
<link rel="up" href="Cursors.html" title="Chapter 4. Using Cursors" />
<link rel="previous" href="Cursors.html" title="Chapter 4. Using Cursors" />
<link rel="next" href="PutEntryWCursor.html" title="Putting Records Using Cursors" />
</head>
<body>
<div class="navheader">
<table width="100%" summary="Navigation header">
<tr>
<th colspan="3" align="center">Getting Records Using the Cursor</th>
</tr>
<tr>
<td width="20%" align="left"><a accesskey="p" href="Cursors.html">Prev</a> </td>
<th width="60%" align="center">Chapter 4. Using Cursors</th>
<td width="20%" align="right"> <a accesskey="n" href="PutEntryWCursor.html">Next</a></td>
</tr>
</table>
<hr />
</div>
<div class="sect1" lang="en" xml:lang="en">
<div class="titlepage">
<div>
<div>
<h2 class="title" style="clear: both"><a id="Positioning"></a>Getting Records Using the Cursor</h2>
</div>
</div>
<div></div>
</div>
<p>
To iterate over database records, from the first record to
the last, simply open the cursor and then use the
<tt class="methodname">DBC-&gt;get()</tt>
method.
<span>Note that you need to supply the
<tt class="literal">DB_NEXT</tt> flag to this method.</span>
For example:
</p>
<a id="c_cursor3"></a>
<pre class="programlisting">#include &lt;db.h&gt;
#include &lt;string.h&gt;
...
DB *my_database;
DBC *cursorp;
DBT key, data;
int ret;
/* Database open omitted for clarity */
/* Get a cursor */
my_database-&gt;cursor(my_database, NULL, &amp;cursorp, 0);
/* Initialize our DBTs. */
memset(&amp;key, 0, sizeof(DBT));
memset(&amp;data, 0, sizeof(DBT));
/* Iterate over the database, retrieving each record in turn. */
while ((ret = cursorp-&gt;get(cursorp, &amp;key, &amp;data, DB_NEXT)) == 0) {
/* Do interesting things with the DBTs here. */
}
if (ret != DB_NOTFOUND) {
/* Error handling goes here */
}
/* Cursors must be closed */
if (cursorp != NULL)
cursorp-&gt;close(cursorp);
if (my_database != NULL)
my_database-&gt;close(my_database, 0);</pre>
<p>
To iterate over the database from the last record to the first, use
<tt class="literal">DB_PREV</tt> instead of <tt class="literal">DB_NEXT</tt>:
</p>
<a id="c_cursor4"></a>
<pre class="programlisting">#include &lt;db.h&gt;
#include &lt;string.h&gt;
...
DB *my_database;
DBC *cursorp;
DBT key, data;
int ret;
/* Database open omitted for clarity */
/* Get a cursor */
my_database-&gt;cursor(my_database, NULL, &amp;cursorp, 0);
/* Initialize our DBTs. */
memset(&amp;key, 0, sizeof(DBT));
memset(&amp;data, 0, sizeof(DBT));
/* Iterate over the database, retrieving each record in turn. */
while ((ret = cursorp-&gt;get(cursorp, &amp;key,
&amp;data, DB_PREV)) == 0) {
/* Do interesting things with the DBTs here. */
}
if (ret != DB_NOTFOUND) {
/* Error handling goes here */
}
// Cursors must be closed
if (cursorp != NULL)
cursorp-&gt;close(cursorp);
if (my_database != NULL)
my_database-&gt;close(my_database, 0);</pre>
<div class="sect2" lang="en" xml:lang="en">
<div class="titlepage">
<div>
<div>
<h3 class="title"><a id="cursorsearch"></a>Searching for Records</h3>
</div>
</div>
<div></div>
</div>
<p>
You can use cursors to search for database records. You can search based
on just a key, or you can search based on both the key and the data.
You can also perform partial matches if your database supports sorted
duplicate sets. In all cases, the key and data parameters of these
methods are filled with the key and data values of the database record
to which the cursor is positioned as a result of the search.
</p>
<p>
Also, if the search fails, then cursor's state is left unchanged
and
<tt class="literal">DB_NOTFOUND</tt>
is returned.
</p>
<p>
To use a cursor to search for a record, use
<span>DBT-&gt;get()<tt class="methodname"></tt>.</span>
When you use this method, you can provide the following flags:
</p>
<div class="note" style="margin-left: 0.5in; margin-right: 0.5in;">
<h3 class="title">Note</h3>
<p>
Notice in the following list that the cursor flags use the
keyword <tt class="literal">SET</tt> when the cursor examines just the key
portion of the records (in this case, the cursor is set to the
record whose key matches the value provided to the cursor).
Moreover, when the cursor uses the keyword <tt class="literal">GET</tt>,
then the cursor is positioned to both the key
<span class="emphasis"><em>and</em></span> the data values provided to the cursor.
</p>
<p>
Regardless of the keyword you use to get a record with a cursor, the
cursor's key and data
<span><tt class="classname">DBT</tt>s</span>
are filled with the data retrieved from the record to which the
cursor is positioned.
</p>
</div>
<div class="itemizedlist">
<ul type="disc">
<li>
<p>
<tt class="literal">DB_SET</tt>
</p>
<p>
Moves the cursor to the first record in the database with
the specified key.
</p>
</li>
<li>
<p>
<tt class="literal">DB_SET_RANGE</tt>
</p>
<p>
<span>Identical to
<tt class="literal">DB_SET</tt>
unless you are using the BTree access. In this case, the cursor
moves</span>
to the first record in the database whose
key is greater than or equal to the specified key. This comparison
is determined by the
<span>comparison function</span>
that you provide for the database. If no
<span>comparison function</span>
is provided, then the default
lexicographical sorting is used.
</p>
<p>
For example, suppose you have database records that use the
following
<span>strings</span>
as keys:
</p>
<pre class="programlisting">Alabama
Alaska
Arizona</pre>
<p>
Then providing a search key of <tt class="literal">Alaska</tt> moves the
cursor to the second key noted above. Providing a key of
<tt class="literal">Al</tt> moves the cursor to the first key (<tt class="literal">Alabama</tt>), providing
a search key of <tt class="literal">Alas</tt> moves the cursor to the second key
(<tt class="literal">Alaska</tt>), and providing a key of <tt class="literal">Ar</tt> moves the
cursor to the last key (<tt class="literal">Arizona</tt>).
</p>
</li>
<li>
<p>
<tt class="literal">DB_GET_BOTH</tt>
</p>
<p>
Moves the cursor to the first record in the database that uses
the specified key and data.
</p>
</li>
<li>
<p>
<tt class="literal">DB_GET_BOTH_RANGE</tt>
</p>
<p>
Moves the cursor to the first record in the database whose key matches the specified
key and whose data is
greater than or equal to the specified data. If the database supports
duplicate records, then on matching the key, the cursor is moved to
the duplicate record with the smallest data that is greater than or
equal to the specified data.
</p>
<p>
For example,
<span>suppose your database uses BTree
and it has </span>
database records that use the following key/data pairs:
</p>
<pre class="programlisting">Alabama/Athens
Alabama/Florence
Alaska/Anchorage
Alaska/Fairbanks
Arizona/Avondale
Arizona/Florence </pre>
<p>then providing:</p>
<div class="informaltable">
<table border="1" width="80%">
<colgroup>
<col />
<col />
<col />
</colgroup>
<thead>
<tr>
<th>a search key of ...</th>
<th>and a search data of ...</th>
<th>moves the cursor to ...</th>
</tr>
</thead>
<tbody>
<tr>
<td>Alaska</td>
<td>Fa</td>
<td>Alaska/Fairbanks</td>
</tr>
<tr>
<td>Arizona</td>
<td>Fl</td>
<td>Arizona/Florence</td>
</tr>
<tr>
<td>Alaska</td>
<td>An</td>
<td>Alaska/Anchorage</td>
</tr>
</tbody>
</table>
</div>
</li>
</ul>
</div>
<p>
For example, assuming a database containing sorted duplicate records of
U.S. States/U.S Cities key/data pairs (both as
<span>strings),</span>
then the following code fragment can be used to position the cursor
to any record in the database and print its key/data values:
</p>
<a id="c_cursor5"></a>
<pre class="programlisting">#include &lt;db.h&gt;
#include &lt;string.h&gt;
...
DBC *cursorp;
DBT key, data;
DB *dbp;
int ret;
char *search_data = "Fa";
char *search_key = "Alaska";
/* database open omitted for clarity */
/* Get a cursor */
dbp-&gt;cursor(dbp, NULL, &amp;cursorp, 0);
/* Set up our DBTs */
key.data = search_key;
key.size = strlen(search_key) + 1;
data.data = search_data;
data.size = strlen(search_data) + 1;
/*
* Position the cursor to the first record in the database whose
* key matches the search key and whose data begins with the
* search data.
*/
ret = cursorp-&gt;get(cursorp, &amp;key, &amp;data, DB_GET_BOTH_RANGE);
if (!ret) {
/* Do something with the data */
} else {
/* Error handling goes here */
}
/* Close the cursor */
if (cursorp != NULL)
cursorp-&gt;close(cursorp);
/* Close the database */
if (dbp != NULL)
dbp-&gt;close(dbp, 0); </pre>
</div>
<div class="sect2" lang="en" xml:lang="en">
<div class="titlepage">
<div>
<div>
<h3 class="title"><a id="getdups"></a>Working with Duplicate Records</h3>
</div>
</div>
<div></div>
</div>
<p>
A record is a duplicate of another record if the two records share the
same key. For duplicate records, only the data portion of the record is unique.
</p>
<p>
Duplicate records are supported only for the BTree or Hash access methods.
For information on configuring your database to use duplicate records,
see <a href="btree.html#duplicateRecords">Allowing Duplicate Records</a>.
</p>
<p>
If your database supports duplicate records, then it can potentially
contain multiple records that share the same key.
<span>By default, normal database
get operations will only return the first such record in a set
of duplicate records. Typically, subsequent duplicate records are
accessed using a cursor.
</span>
The following
<span><tt class="methodname">DBC-&gt;get()</tt> flags</span>
are interesting when working with databases that support duplicate records:
</p>
<div class="itemizedlist">
<ul type="disc">
<li>
<p>
<span>
<tt class="literal">DB_NEXT</tt>,
<tt class="literal">DB_PREV</tt>
</span>
</p>
<p>
Shows the next/previous record in the database, regardless of
whether it is a duplicate of the current record. For an example of
using these methods, see <a href="Positioning.html">Getting Records Using the Cursor</a>.
</p>
</li>
<li>
<p>
<tt class="literal">DB_GET_BOTH_RANGE</tt>
</p>
<p>
Useful for seeking the cursor to a specific record, regardless of
whether it is a duplicate record. See <a href="Positioning.html#cursorsearch">Searching for Records</a> for more
information.
</p>
</li>
<li>
<p>
<span>
<tt class="literal">DB_NEXT_NODUP</tt>,
<tt class="literal">DB_PREV_NODUP</tt>
</span>
</p>
<p>
Gets the next/previous non-duplicate record in the database. This
allows you to skip over all the duplicates in a set of duplicate
records. If you call
<span>
<tt class="methodname">DBC-&gt;get()</tt>
with <tt class="literal">DB_PREV_NODUP</tt>,
</span>
then the cursor is positioned to the last record for the previous
key in the database. For example, if you have the following records
in your database:
</p>
<pre class="programlisting">Alabama/Athens
Alabama/Florence
Alaska/Anchorage
Alaska/Fairbanks
Arizona/Avondale
Arizona/Florence</pre>
<p>
and your cursor is positioned to <tt class="literal">Alaska/Fairbanks</tt>,
and you then call
<span>
<tt class="methodname">DBC-&gt;get()</tt>
with <tt class="literal">DB_PREV_NODUP</tt>,
</span>
then the cursor is positioned to Alabama/Florence. Similarly, if
you call
<span>
<tt class="methodname">DBC-&gt;get()</tt>
with <tt class="literal">DB_NEXT_NODUP</tt>,
</span>
then the cursor is positioned to the first record corresponding to
the next key in the database.
</p>
<p>
If there is no next/previous key in the database, then
<tt class="literal">DB_NOTFOUND</tt>
is returned, and the cursor is left unchanged.
</p>
</li>
<li>
<p>
<tt class="literal">DB_NEXT_DUP</tt>
</p>
<p>
Gets the
<span>next</span>
record that shares the current key. If the
cursor is positioned at the last record in the duplicate set and
you call
<span>
<tt class="methodname">DBC-&gt;get()</tt>
with <tt class="literal">DB_NEXT_DUP</tt>,
</span>
then
<tt class="literal">DB_NOTFOUND</tt>
is returned and the cursor is left unchanged.
</p>
</li>
</ul>
</div>
<p>
For example, the following code fragment positions a cursor to a key
<span>and displays it and all its
duplicates.</span>
</p>
<a id="c_cursor6"></a>
<pre class="programlisting">#include &lt;db.h&gt;
#include &lt;string.h&gt;
...
DB *dbp;
DBC *cursorp;
DBT key, data;
int ret;
char *search_key = "Al";
/* database open omitted for clarity */
/* Get a cursor */
dbp-&gt;cursor(dbp, NULL, &amp;cursorp, 0);
/* Set up our DBTs */
key.data = search_key;
key.size = strlen(search_key) + 1;
/*
* Position the cursor to the first record in the database whose
* key and data begin with the correct strings.
*/
ret = cursorp-&gt;get(cursorp, &amp;key, &amp;data, DB_SET);
while (ret != DB_NOTFOUND) {
printf("key: %s, data: %s\n", (char *)key.data, (char *)data.data);
ret = cursorp-&gt;get(cursorp, &amp;key, &amp;data, DB_NEXT_DUP);
}
/* Close the cursor */
if (cursorp != NULL)
cursorp-&gt;close(cursorp);
/* Close the database */
if (dbp != NULL)
dbp-&gt;close(dbp, 0); </pre>
</div>
</div>
<div class="navfooter">
<hr />
<table width="100%" summary="Navigation footer">
<tr>
<td width="40%" align="left"><a accesskey="p" href="Cursors.html">Prev</a> </td>
<td width="20%" align="center">
<a accesskey="u" href="Cursors.html">Up</a>
</td>
<td width="40%" align="right"> <a accesskey="n" href="PutEntryWCursor.html">Next</a></td>
</tr>
<tr>
<td width="40%" align="left" valign="top">Chapter 4. Using Cursors </td>
<td width="20%" align="center">
<a accesskey="h" href="index.html">Home</a>
</td>
<td width="40%" align="right" valign="top"> Putting Records Using Cursors</td>
</tr>
</table>
</div>
</body>
</html>

View File

@@ -0,0 +1,221 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>Putting Records Using Cursors</title>
<link rel="stylesheet" href="gettingStarted.css" type="text/css" />
<meta name="generator" content="DocBook XSL Stylesheets V1.62.4" />
<link rel="home" href="index.html" title="Getting Started with Berkeley DB" />
<link rel="up" href="Cursors.html" title="Chapter 4. Using Cursors" />
<link rel="previous" href="Positioning.html" title="Getting Records Using the Cursor" />
<link rel="next" href="DeleteEntryWCursor.html" title="Deleting Records Using Cursors" />
</head>
<body>
<div class="navheader">
<table width="100%" summary="Navigation header">
<tr>
<th colspan="3" align="center">Putting Records Using Cursors</th>
</tr>
<tr>
<td width="20%" align="left"><a accesskey="p" href="Positioning.html">Prev</a> </td>
<th width="60%" align="center">Chapter 4. Using Cursors</th>
<td width="20%" align="right"> <a accesskey="n" href="DeleteEntryWCursor.html">Next</a></td>
</tr>
</table>
<hr />
</div>
<div class="sect1" lang="en" xml:lang="en">
<div class="titlepage">
<div>
<div>
<h2 class="title" style="clear: both"><a id="PutEntryWCursor"></a>Putting Records Using Cursors</h2>
</div>
</div>
<div></div>
</div>
<p>
You can use cursors to put records into the database. DB's behavior
when putting records into the database differs depending on the flags
that you use when writing the record, on the access method that you are
using, and on whether your database supports sorted duplicates.
</p>
<p>
Note that when putting records to the database using a cursor, the
cursor is positioned at the record you inserted.
</p>
<p>
You use
<tt class="methodname">DBC-&gt;put()</tt>
to put (write) records to the database. You can use the following flags
with this method:
</p>
<div class="itemizedlist">
<ul type="disc">
<li>
<p>
<tt class="literal">DB_NODUPDATA</tt>
</p>
<p>
If the provided key already exists
in the database, then this method returns
<tt class="literal">DB_KEYEXIST</tt>.
</p>
<p>
If the key does not exist, then the order that the record is put into the database
is determined by the
<span>
insertion order in use by the database. If a comparison
function has been provided to the database, the record is
inserted in its sorted location. Otherwise (assuming BTree),
lexicographical sorting is used, with
shorter items collating before longer items.
</span>
</p>
<p>
This flag can only be used for the BTree and Hash access methods,
and only if the database has been configured to support sorted
duplicate data items (<tt class="literal">DB_DUPSORT</tt> was specified at
database creation time).
</p>
<p>
This flag cannot be used with the Queue or Recno access methods.
</p>
<p>
For more information on duplicate records, see
<a href="btree.html#duplicateRecords">Allowing Duplicate Records</a>.
</p>
</li>
<li>
<p>
<tt class="literal">DB_KEYFIRST</tt>
</p>
<p>
For databases that do not support duplicates, this method behaves
<span>
exactly the same as if a default insertion was performed.
</span>
If the database supports duplicate records,
<span>
and a duplicate sort function has been specified, the
inserted data item is added in its sorted location. If
the key already exists in the database and no duplicate
sort function has been specified, the inserted data item
is added as the first of the data items for that key.
</span>
</p>
</li>
<li>
<p>
<tt class="literal">DB_KEYLAST</tt>
</p>
<p>
Behaves exactly as if
<tt class="literal">DB_KEYFIRST</tt>
was used, except that if the key already exists in the database and no
duplicate sort function has been specified, the
inserted data item is added as the last of the data
items for that key.
</p>
</li>
</ul>
</div>
<p>For example:</p>
<a id="c_cursor7"></a>
<pre class="programlisting">#include &lt;db.h&gt;
#include &lt;string.h&gt;
...
DB *dbp;
DBC *cursorp;
DBT data1, data2, data3;
DBT key1, key2;
char *key1str = "My first string";
char *data1str = "My first data";
char *key2str = "A second string";
char *data2str = "My second data";
char *data3str = "My third data";
int ret;
/* Set up our DBTs */
key1.data = key1str;
key1.size = strlen(key1str) + 1;
data1.data = data1str;
data1.size = strlen(data1str) + 1;
key2.data = key2str;
key2.size = strlen(key2str) + 1;
data2.data = data2str;
data2.size = strlen(data2str) + 1;
data3.data = data3str;
data3.size = strlen(data3str) + 1;
/* Database open omitted */
/* Get the cursor */
dbp-&gt;cursor(dbp, NULL, &amp;cursorp, 0);
/*
* Assuming an empty database, this first put places
* "My first string"/"My first data" in the first
* position in the database
*/
ret = cursorp-&gt;put(cursorp, &amp;key1,
&amp;data1, DB_KEYFIRST);
/*
* This put places "A second string"/"My second data" in the
* the database according to its key sorts against the key
* used for the currently existing database record. Most likely
* this record would appear first in the database.
*/
ret = cursorp-&gt;put(cursorp, &amp;key2,
&amp;data2, DB_KEYFIRST); /* Added according to sort order */
/*
* If duplicates are not allowed, the currently existing record that
* uses "key2" is overwritten with the data provided on this put.
* That is, the record "A second string"/"My second data" becomes
* "A second string"/"My third data"
*
* If duplicates are allowed, then "My third data" is placed in the
* duplicates list according to how it sorts against "My second data".
*/
ret = cursorp-&gt;put(cursorp, &amp;key2,
&amp;data3, DB_KEYFIRST); /* If duplicates are not allowed, record
* is overwritten with new data. Otherwise,
* the record is added to the beginning of
* the duplicates list.
*/ </pre>
</div>
<div class="navfooter">
<hr />
<table width="100%" summary="Navigation footer">
<tr>
<td width="40%" align="left"><a accesskey="p" href="Positioning.html">Prev</a> </td>
<td width="20%" align="center">
<a accesskey="u" href="Cursors.html">Up</a>
</td>
<td width="40%" align="right"> <a accesskey="n" href="DeleteEntryWCursor.html">Next</a></td>
</tr>
<tr>
<td width="40%" align="left" valign="top">Getting Records Using the Cursor </td>
<td width="20%" align="center">
<a accesskey="h" href="index.html">Home</a>
</td>
<td width="40%" align="right" valign="top"> Deleting Records Using Cursors</td>
</tr>
</table>
</div>
</body>
</html>

View File

@@ -0,0 +1,137 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>Replacing Records Using Cursors</title>
<link rel="stylesheet" href="gettingStarted.css" type="text/css" />
<meta name="generator" content="DocBook XSL Stylesheets V1.62.4" />
<link rel="home" href="index.html" title="Getting Started with Berkeley DB" />
<link rel="up" href="Cursors.html" title="Chapter 4. Using Cursors" />
<link rel="previous" href="DeleteEntryWCursor.html" title="Deleting Records Using Cursors" />
<link rel="next" href="CoreCursorUsage.html" title="Cursor Example" />
</head>
<body>
<div class="navheader">
<table width="100%" summary="Navigation header">
<tr>
<th colspan="3" align="center">Replacing Records Using Cursors</th>
</tr>
<tr>
<td width="20%" align="left"><a accesskey="p" href="DeleteEntryWCursor.html">Prev</a> </td>
<th width="60%" align="center">Chapter 4. Using Cursors</th>
<td width="20%" align="right"> <a accesskey="n" href="CoreCursorUsage.html">Next</a></td>
</tr>
</table>
<hr />
</div>
<div class="sect1" lang="en" xml:lang="en">
<div class="titlepage">
<div>
<div>
<h2 class="title" style="clear: both"><a id="ReplacingEntryWCursor"></a>Replacing Records Using Cursors</h2>
</div>
</div>
<div></div>
</div>
<p>
You replace the data for a database record by using
<span>
<tt class="methodname">DBC-&gt;put()</tt>
with the <tt class="literal">DB_CURRENT</tt> flag.
</span>
</p>
<a id="c_cursor9"></a>
<pre class="programlisting">#include &lt;db.h&gt;
#include &lt;string.h&gt;
...
DB *dbp;
DBC *cursorp;
DBT key, data;
char *key1str = "My first string";
char *replacement_data = "replace me";
int ret;
/* Initialize our DBTs. */
memset(&amp;key, 0, sizeof(DBT));
memset(&amp;data, 0, sizeof(DBT));
/* Set up our DBTs */
key.data = key1str;
key.size = strlen(key1str) + 1;
/* Database open omitted */
/* Get the cursor */
dbp-&gt;cursor(dbp, NULL, &amp;cursorp, 0);
/* Position the cursor */
ret = cursorp-&gt;get(cursorp, &amp;key, &amp;data, DB_SET);
if (ret == 0) {
data.data = replacement_data;
data.size = strlen(replacement_data) + 1;
cursorp-&gt;put(cursorp, &amp;key, &amp;data, DB_CURRENT);
}
/* Cursors must be closed */
if (cursorp != NULL)
cursorp-&gt;close(cursorp);
if (dbp != NULL)
dbp-&gt;close(dbp, 0);</pre>
<p>
Note that you cannot change a record's key using this method; the key
parameter is always ignored when you replace a record.
</p>
<p>
When replacing the data portion of a record, if you are replacing a
record that is a member of a sorted duplicates set, then the replacement
will be successful only if the new record sorts identically to the old
record. This means that if you are replacing a record that is a member
of a sorted duplicates set, and if you are using the default
lexicographic sort, then the replacement will fail due to violating the
sort order. However, if you
provide a custom sort routine that, for example, sorts based on just a
few bytes out of the data item, then potentially you can perform
a direct replacement and still not violate the restrictions described
here.
</p>
<p>
<span>Under these circumstances, if</span>
you want to replace the data contained by a duplicate record,
<span>
and you are not using a custom sort routine, then
</span>
delete the record and create a new record with the desired key and data.
</p>
</div>
<div class="navfooter">
<hr />
<table width="100%" summary="Navigation footer">
<tr>
<td width="40%" align="left"><a accesskey="p" href="DeleteEntryWCursor.html">Prev</a> </td>
<td width="20%" align="center">
<a accesskey="u" href="Cursors.html">Up</a>
</td>
<td width="40%" align="right"> <a accesskey="n" href="CoreCursorUsage.html">Next</a></td>
</tr>
<tr>
<td width="40%" align="left" valign="top">Deleting Records Using Cursors </td>
<td width="20%" align="center">
<a accesskey="h" href="index.html">Home</a>
</td>
<td width="40%" align="right" valign="top"> Cursor Example</td>
</tr>
</table>
</div>
</body>
</html>

View File

@@ -0,0 +1,281 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>Access Methods</title>
<link rel="stylesheet" href="gettingStarted.css" type="text/css" />
<meta name="generator" content="DocBook XSL Stylesheets V1.62.4" />
<link rel="home" href="index.html" title="Getting Started with Berkeley DB" />
<link rel="up" href="introduction.html" title="Chapter 1. Introduction to Berkeley DB " />
<link rel="previous" href="concepts.html" title="Berkeley DB Concepts" />
<link rel="next" href="databaseLimits.html" title="Database Limits and Portability" />
</head>
<body>
<div class="navheader">
<table width="100%" summary="Navigation header">
<tr>
<th colspan="3" align="center">Access Methods</th>
</tr>
<tr>
<td width="20%" align="left"><a accesskey="p" href="concepts.html">Prev</a> </td>
<th width="60%" align="center">Chapter 1. Introduction to Berkeley DB </th>
<td width="20%" align="right"> <a accesskey="n" href="databaseLimits.html">Next</a></td>
</tr>
</table>
<hr />
</div>
<div class="sect1" lang="en" xml:lang="en">
<div class="titlepage">
<div>
<div>
<h2 class="title" style="clear: both"><a id="accessmethods"></a>Access Methods</h2>
</div>
</div>
<div></div>
</div>
<p>
While this manual will focus primarily on the BTree access method, it is
still useful to briefly describe all of the access methods that DB
makes available.
</p>
<p>
Note that an access method can be selected only when the database is
created. Once selected, actual API usage is generally
identical across all access methods. That is, while some
exceptions exist, mechanically you interact with the library in the same
way regardless of which access method you have selected.
</p>
<p>
The access method that you should choose is gated first by what you want
to use as a key, and then secondly by the performance that you see
for a given access method.
</p>
<p>
The following are the available access methods:
</p>
<div class="informaltable">
<table border="1" width="80%">
<colgroup>
<col align="left" />
<col align="left" />
</colgroup>
<thead>
<tr>
<th align="center">Access Method</th>
<th align="center">Description</th>
</tr>
</thead>
<tbody>
<tr>
<td align="left">BTree</td>
<td align="left" valign="top">
<p>
Data is stored in a sorted, balanced tree structure.
Both the key and the data for BTree records can be
arbitrarily complex. That is, they can contain single values
such as an integer or a string, or complex types such as a
structure. Also, although not the default
behavior, it is possible for two records to
use keys that compare as equals. When this occurs, the
records are considered to be duplicates of one another.
</p>
</td>
</tr>
<tr>
<td align="left">Hash</td>
<td align="left" valign="top">
<p>
Data is stored in an extended linear hash table. Like
BTree, the key and the data used for Hash records can be of
arbitrarily complex data. Also, like BTree, duplicate
records are optionally supported.
</p>
</td>
</tr>
<tr>
<td align="left">Queue</td>
<td align="left" valign="top">
<p>
Data is stored in a queue as fixed-length records. Each
record uses a logical record number as its key. This access
method is designed for fast inserts at the tail of the
queue, and it has a special operation that deletes and
returns a record from the head of the queue.
</p>
<p>
This access method is unusual in that it provides record
level locking. This can provide
beneficial performance improvements in applications
requiring concurrent access to the queue.
</p>
</td>
</tr>
<tr>
<td align="left">Recno</td>
<td align="left" valign="top">
<p>
Data is stored in either fixed or variable-length records.
Like Queue, Recno records use logical record numbers as keys.
</p>
</td>
</tr>
</tbody>
</table>
</div>
<div class="sect2" lang="en" xml:lang="en">
<div class="titlepage">
<div>
<div>
<h3 class="title"><a id="selectAM"></a>Selecting Access Methods</h3>
</div>
</div>
<div></div>
</div>
<p>
To select an access method, you should first consider what you want
to use as a key for you database records. If you want to use
arbitrary data (even strings), then you should use either BTree or
Hash. If you want to use logical record numbers (essentially
integers) then you should use Queue or Recno.
</p>
<p>
Once you have made this decision, you must choose between either
BTree or Hash, or Queue or Recno. This decision is described next.
</p>
</div>
<div class="sect2" lang="en" xml:lang="en">
<div class="titlepage">
<div>
<div>
<h3 class="title"><a id="BTreeVSHash"></a>Choosing between BTree and Hash</h3>
</div>
</div>
<div></div>
</div>
<p>
For small working datasets that fit entirely in memory, there is no
difference between BTree and Hash. Both will perform just as well
as the other. In this situation, you might just as well use BTree,
if for no other reason than the majority of DB applications use
BTree.
</p>
<p>
Note that the main concern here is your
working dataset, not your entire dataset. Many applications maintain
large amounts of information but only need to access some small
portion of that data with any frequency. So what you want to
consider is the data that you will routinely use, not the sum total
of all the data managed by your application.
</p>
<p>
However, as your working dataset grows to the point
where you cannot fit it all into memory, then you need to take more
care when choosing your access method. Specifically, choose:
</p>
<div class="itemizedlist">
<ul type="disc">
<li>
<p>
BTree if your keys have some locality of reference. That is,
if they sort well and you can expect that a query for a
given key will likely be followed by a query for one of its
neighbors.
</p>
</li>
<li>
<p>
Hash if your dataset is extremely large. For any given
access method, DB must maintain a certain amount of internal
information. However, the amount of information that DB
must maintain for BTree is much greater than for Hash. The
result is that as your dataset grows, this internal
information can dominate the cache to the point where there
is relatively little space left for application data.
As a result, BTree can be forced to perform disk I/O much more
frequently than would Hash given the same amount of data.
</p>
<p>
Moreover, if your dataset becomes so large that DB will
almost certainly have to perform disk I/O to satisfy a
random request, then Hash will definitely out perform BTree
because it has fewer internal records to search through than
does BTree.
</p>
</li>
</ul>
</div>
</div>
<div class="sect2" lang="en" xml:lang="en">
<div class="titlepage">
<div>
<div>
<h3 class="title"><a id="QueueVSRecno"></a>Choosing between Queue and Recno</h3>
</div>
</div>
<div></div>
</div>
<p>
Queue or Recno are used when the application wants to use logical
record numbers for the primary database key. Logical record numbers
are essentially integers that uniquely identify the database
record. They can be either mutable or fixed, where a mutable record
number is one that might change as database records are stored or
deleted. Fixed logical record numbers never change regardless of
what database operations are performed.
</p>
<p>
When deciding between Queue and Recno, choose:
</p>
<div class="itemizedlist">
<ul type="disc">
<li>
<p>
Queue if your application requires high degrees of
concurrency. Queue provides record-level locking (as opposed
to the page-level locking that the other access methods
use), and this can result in significantly faster throughput
for highly concurrent applications.
</p>
<p>
Note, however, that Queue provides support only for fixed
length records. So if the size of the data that you want to
store varies widely from record to record, you should
probably choose an access method other than Queue.
</p>
</li>
<li>
<p>
Recno if you want mutable record numbers. Queue is only
capable of providing fixed record numbers. Also, Recno
provides support for databases whose permanent storage is a
flat text file. This is useful for applications looking for
fast, temporary storage while the data is being read or
modified.
</p>
</li>
</ul>
</div>
</div>
</div>
<div class="navfooter">
<hr />
<table width="100%" summary="Navigation footer">
<tr>
<td width="40%" align="left"><a accesskey="p" href="concepts.html">Prev</a> </td>
<td width="20%" align="center">
<a accesskey="u" href="introduction.html">Up</a>
</td>
<td width="40%" align="right"> <a accesskey="n" href="databaseLimits.html">Next</a></td>
</tr>
<tr>
<td width="40%" align="left" valign="top">Berkeley DB Concepts </td>
<td width="20%" align="center">
<a accesskey="h" href="index.html">Home</a>
</td>
<td width="40%" align="right" valign="top"> Database Limits and Portability</td>
</tr>
</table>
</div>
</body>
</html>

572
docs/gsg/C/btree.html Normal file
View File

@@ -0,0 +1,572 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>BTree Configuration</title>
<link rel="stylesheet" href="gettingStarted.css" type="text/css" />
<meta name="generator" content="DocBook XSL Stylesheets V1.62.4" />
<link rel="home" href="index.html" title="Getting Started with Berkeley DB" />
<link rel="up" href="dbconfig.html" title="Chapter 6. Database Configuration" />
<link rel="previous" href="cachesize.html" title="Selecting the Cache Size" />
</head>
<body>
<div class="navheader">
<table width="100%" summary="Navigation header">
<tr>
<th colspan="3" align="center">BTree Configuration</th>
</tr>
<tr>
<td width="20%" align="left"><a accesskey="p" href="cachesize.html">Prev</a> </td>
<th width="60%" align="center">Chapter 6. Database Configuration</th>
<td width="20%" align="right"> </td>
</tr>
</table>
<hr />
</div>
<div class="sect1" lang="en" xml:lang="en">
<div class="titlepage">
<div>
<div>
<h2 class="title" style="clear: both"><a id="btree"></a>BTree Configuration</h2>
</div>
</div>
<div></div>
</div>
<p>
In going through the previous chapters in this book, you may notice that
we touch on some topics that are specific to BTree, but we do not cover
those topics in any real detail. In this section, we will discuss
configuration issues that are unique to BTree.
</p>
<p>
Specifically, in this section we describe:
</p>
<div class="itemizedlist">
<ul type="disc">
<li>
<p>
Allowing duplicate records.
</p>
</li>
<li>
<p>
Setting comparator callbacks.
</p>
</li>
</ul>
</div>
<div class="sect2" lang="en" xml:lang="en">
<div class="titlepage">
<div>
<div>
<h3 class="title"><a id="duplicateRecords"></a>Allowing Duplicate Records</h3>
</div>
</div>
<div></div>
</div>
<p>
BTree databases can contain duplicate records. One record is
considered to be a duplicate of another when both records use keys
that compare as equal to one another.
</p>
<p>
By default, keys are compared using a lexicographical comparison,
with shorter keys collating higher than longer keys.
You can override this default using the
<tt class="methodname">DB-&gt;set_bt_compare()</tt>
method. See the next section for details.
</p>
<p>
By default, DB databases do not allow duplicate records. As a
result, any attempt to write a record that uses a key equal to a
previously existing record results in the previously existing record
being overwritten by the new record.
</p>
<p>
Allowing duplicate records is useful if you have a database that
contains records keyed by a commonly occurring piece of information.
It is frequently necessary to allow duplicate records for secondary
databases.
</p>
<p>
For example, suppose your primary database contained records related
to automobiles. You might in this case want to be able to find all
the automobiles in the database that are of a particular color, so
you would index on the color of the automobile. However, for any
given color there will probably be multiple automobiles. Since the
index is the secondary key, this means that multiple secondary
database records will share the same key, and so the secondary
database must support duplicate records.
</p>
<div class="sect3" lang="en" xml:lang="en">
<div class="titlepage">
<div>
<div>
<h4 class="title"><a id="sorteddups"></a>Sorted Duplicates</h4>
</div>
</div>
<div></div>
</div>
<p>
Duplicate records can be stored in sorted or unsorted order.
You can cause DB to automatically sort your duplicate
records by
<span>
specifying the <tt class="literal">DB_DUPSORT</tt> flag at
database creation time.
</span>
</p>
<p>
If sorted duplicates are supported, then the
<span>
sorting function specified on
<tt class="methodname">DB-&gt;set_dup_compare()</tt>
</span>
is used to determine the location of the duplicate record in its
duplicate set. If no such function is provided, then the default
lexicographical comparison is used.
</p>
</div>
<div class="sect3" lang="en" xml:lang="en">
<div class="titlepage">
<div>
<div>
<h4 class="title"><a id="nosorteddups"></a>Unsorted Duplicates</h4>
</div>
</div>
<div></div>
</div>
<p>
For performance reasons, BTrees should always contain sorted
records. (BTrees containing unsorted entries must potentially
spend a great deal more time locating an entry than does a BTree
that contains sorted entries). That said, DB provides support
for suppressing automatic sorting of duplicate records because it may be that
your application is inserting records that are already in a
sorted order.
</p>
<p>
That is, if the database is configured to support unsorted
duplicates, then the assumption is that your application
will manually perform the sorting. In this event,
expect to pay a significant performance penalty. Any time you
place records into the database in a sort order not know to
DB, you will pay a performance penalty
</p>
<p>
That said, this is how DB behaves when inserting records
into a database that supports non-sorted duplicates:
</p>
<div class="itemizedlist">
<ul type="disc">
<li>
<p>
If your application simply adds a duplicate record using
<span><tt class="methodname">DB-&gt;put()</tt>,</span>
then the record is inserted at the end of its sorted duplicate set.
</p>
</li>
<li>
<p>
If a cursor is used to put the duplicate record to the database,
then the new record is placed in the duplicate set according to the
flags that are provided on the
<tt class="methodname">DBC-&gt;put()</tt>
method. The relevant flags are:
</p>
<div class="itemizedlist">
<ul type="circle">
<li>
<p>
<tt class="literal">DB_AFTER</tt>
</p>
<p>
The data
<span>
provided on the call to
<tt class="methodname">DBC-&gt;put()</tt>
</span>
is placed into the database
as a duplicate record. The key used for this operation is
the key used for the record to which the cursor currently
refers. Any key provided on the call
<span>
to
<tt class="methodname">DBC-&gt;put()</tt>
</span>
is therefore ignored.
</p>
<p>
The duplicate record is inserted into the database
immediately after the cursor's current position in the
database.
</p>
<p>
This flag is ignored if sorted duplicates are supported for
the database.
</p>
</li>
<li>
<p>
<tt class="literal">DB_BEFORE</tt>
</p>
<p>
Behaves the same as
<tt class="literal">DB_AFTER</tt>
except that the new record is inserted immediately before
the cursor's current location in the database.
</p>
</li>
<li>
<p>
<tt class="literal">DB_KEYFIRST</tt>
</p>
<p>
If the key
<span>
provided on the call to
<tt class="methodname">DBC-&gt;put()</tt>
</span>
already exists in the
database, and the database is configured to use duplicates
without sorting, then the new record is inserted as the first entry
in the appropriate duplicates list.
</p>
</li>
<li>
<p>
<tt class="literal">DB_KEYLAST</tt>
</p>
<p>
Behaves identically to
<tt class="literal">DB_KEYFIRST</tt>
except that the new duplicate record is inserted as the last
record in the duplicates list.
</p>
</li>
</ul>
</div>
</li>
</ul>
</div>
</div>
<div class="sect3" lang="en" xml:lang="en">
<div class="titlepage">
<div>
<div>
<h4 class="title"><a id="specifyingDups"></a>Configuring a Database to Support Duplicates</h4>
</div>
</div>
<div></div>
</div>
<p>
Duplicates support can only be configured
at database creation time. You do this by specifying the appropriate
<span>
flags to
<tt class="methodname">DB-&gt;set_flags()</tt>
</span>
before the database is opened for the first time.
</p>
<p>
The
<span>flags</span>
that you can use are:
</p>
<div class="itemizedlist">
<ul type="disc">
<li>
<p>
<tt class="literal">DB_DUP</tt>
</p>
<p>
The database supports non-sorted duplicate records.
</p>
</li>
<li>
<p>
<tt class="literal">DB_DUPSORT</tt>
</p>
<p>
The database supports sorted duplicate records.
</p>
</li>
</ul>
</div>
<p>
The following code fragment illustrates how to configure a database
to support sorted duplicate records:
</p>
<a id="c_btree_dupsort"></a>
<pre class="programlisting">#include &lt;db.h&gt;
...
DB *dbp;
FILE *error_file_pointer;
int ret;
char *program_name = "my_prog";
char *file_name = "mydb.db";
/* Variable assignments omitted for brevity */
/* Initialize the DB handle */
ret = db_create(&amp;dbp, NULL, 0);
if (ret != 0) {
fprintf(error_file_pointer, "%s: %s\n", program_name,
db_strerror(ret));
return(ret);
}
/* Set up error handling for this database */
dbp-&gt;set_errfile(dbp, error_file_pointer);
dbp-&gt;set_errpfx(dbp, program_name);
/*
* Configure the database for sorted duplicates
*/
ret = dbp-&gt;set_flags(dbp, DB_DUPSORT);
if (ret != 0) {
dbp-&gt;err(dbp, ret, "Attempt to set DUPSORT flag failed.");
dbp-&gt;close(dbp, 0);
return(ret);
}
/* Now open the database */
ret = dbp-&gt;open(dbp, /* Pointer to the database */
NULL, /* Txn pointer */
file_name, /* File name */
NULL, /* Logical db name (unneeded) */
DB_BTREE, /* Database type (using btree) */
DB_CREATE, /* Open flags */
0); /* File mode. Using defaults */
if (ret != 0) {
dbp-&gt;err(dbp, ret, "Database '%s' open failed.", file_name);
dbp-&gt;close(dbp, 0);
return(ret);
} </pre>
</div>
</div>
<div class="sect2" lang="en" xml:lang="en">
<div class="titlepage">
<div>
<div>
<h3 class="title"><a id="comparators"></a>Setting Comparison Functions</h3>
</div>
</div>
<div></div>
</div>
<p>
By default, DB uses a lexicographical comparison function where
shorter records collate before longer records. For the majority of
cases, this comparison works well and you do not need to manage
it in any way.
</p>
<p>
However, in some situations your application's performance can
benefit from setting a custom comparison routine. You can do this
either for database keys, or for the data if your
database supports sorted duplicate records.
</p>
<p>
Some of the reasons why you may want to provide a custom sorting
function are:
</p>
<div class="itemizedlist">
<ul type="disc">
<li>
<p>
Your database is keyed using strings and you want to provide
some sort of language-sensitive ordering to that data. Doing
so can help increase the locality of reference that allows
your database to perform at its best.
</p>
</li>
<li>
<p>
You are using a little-endian system (such as x86) and you
are using integers as your database's keys. Berkeley DB
stores keys as byte strings and little-endian integers
do not sort well when viewed as byte strings. There are
several solutions to this problem, one being to provide a
custom comparison function. See
<a href="http://www.oracle.com/technology/documentation/berkeley-db/db/ref/am_misc/faq.html" target="_top">http://www.oracle.com/technology/documentation/berkeley-db/db/ref/am_misc/faq.html</a>
for more information.
</p>
</li>
<li>
<p>
You you do not want the entire key to participate in the
comparison, for whatever reason. In
this case, you may want to provide a custom comparison
function so that only the relevant bytes are examined.
</p>
</li>
</ul>
</div>
<div class="sect3" lang="en" xml:lang="en">
<div class="titlepage">
<div>
<div>
<h4 class="title"><a id="creatingComparisonFunctions"></a>
<span>Creating Comparison Functions</span>
</h4>
</div>
</div>
<div></div>
</div>
<p>
You set a BTree's key
<span>
comparison function
</span>
using
<span><tt class="methodname">DB-&gt;set_bt_compare()</tt>.</span>
You can also set a BTree's duplicate data comparison function using
<span><tt class="methodname">DB-&gt;set_dup_compare()</tt>.</span>
</p>
<p>
<span>
You cannot use these methods after the database has been opened.
Also, if
</span>
the database already exists when it is opened, the
<span>
function
</span>
provided to these methods must be the same as
that historically used to create the database or corruption can
occur.
</p>
<p>
The value that you provide to the <tt class="methodname">set_bt_compare()</tt> method
is a pointer to a function that has the following signature:
</p>
<pre class="programlisting">int (*function)(DB *db, const DBT *key1, const DBT *key2)</pre>
<p>
This function must return an integer value less than, equal to,
or greater than 0. If key1 is considered to be greater than
key2, then the function must return a value that is greater than
0. If the two are equal, then the function must return 0, and if
the first key is less than the second then the function must return
a negative value.
</p>
<p>
The function that you provide to <tt class="methodname">set_dup_compare()</tt>
works in exactly the same way, except that the
<tt class="literal">DBT</tt>
parameters hold record data items instead of keys.
</p>
<p>
For example, an example routine that is used to sort integer
keys in the database is:
<span>
</span>
</p>
<a id="c_btree1"></a>
<pre class="programlisting">int
compare_int(DB *dbp, const DBT *a, const DBT *b)
{
int ai, bi;
/*
* Returns:
* &lt; 0 if a &lt; b
* = 0 if a = b
* &gt; 0 if a &gt; b
*/
memcpy(&amp;ai, a-&gt;data, sizeof(int));
memcpy(&amp;bi, b-&gt;data, sizeof(int));
return (ai - bi);
} </pre>
<p>
Note that the data must first be copied into memory that is
appropriately aligned, as Berkeley DB does not guarantee any kind of
alignment of the underlying data, including for comparison routines.
When writing comparison routines, remember that databases created on
machines of different architectures may have different integer byte
orders, for which your code may need to compensate.
</p>
<p>
To cause DB to use this comparison function:
</p>
<a id="c_btree2"></a>
<pre class="programlisting">#include &lt;db.h&gt;
#include &lt;string.h&gt;
...
DB *dbp;
int ret;
/* Create a database */
ret = db_create(&amp;dbp, NULL, 0);
if (ret != 0) {
fprintf(stderr, "%s: %s\n", "my_program",
db_strerror(ret));
return(-1);
}
/* Set up the btree comparison function for this database */
dbp-&gt;set_bt_compare(dbp, compare_int);
/* Database open call follows sometime after this. */ </pre>
</div>
</div>
</div>
<div class="navfooter">
<hr />
<table width="100%" summary="Navigation footer">
<tr>
<td width="40%" align="left"><a accesskey="p" href="cachesize.html">Prev</a> </td>
<td width="20%" align="center">
<a accesskey="u" href="dbconfig.html">Up</a>
</td>
<td width="40%" align="right"> </td>
</tr>
<tr>
<td width="40%" align="left" valign="top">Selecting the Cache Size </td>
<td width="20%" align="center">
<a accesskey="h" href="index.html">Home</a>
</td>
<td width="40%" align="right" valign="top"> </td>
</tr>
</table>
</div>
</body>
</html>

98
docs/gsg/C/cachesize.html Normal file
View File

@@ -0,0 +1,98 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>Selecting the Cache Size</title>
<link rel="stylesheet" href="gettingStarted.css" type="text/css" />
<meta name="generator" content="DocBook XSL Stylesheets V1.62.4" />
<link rel="home" href="index.html" title="Getting Started with Berkeley DB" />
<link rel="up" href="dbconfig.html" title="Chapter 6. Database Configuration" />
<link rel="previous" href="dbconfig.html" title="Chapter 6. Database Configuration" />
<link rel="next" href="btree.html" title="BTree Configuration" />
</head>
<body>
<div class="navheader">
<table width="100%" summary="Navigation header">
<tr>
<th colspan="3" align="center">Selecting the Cache Size</th>
</tr>
<tr>
<td width="20%" align="left"><a accesskey="p" href="dbconfig.html">Prev</a> </td>
<th width="60%" align="center">Chapter 6. Database Configuration</th>
<td width="20%" align="right"> <a accesskey="n" href="btree.html">Next</a></td>
</tr>
</table>
<hr />
</div>
<div class="sect1" lang="en" xml:lang="en">
<div class="titlepage">
<div>
<div>
<h2 class="title" style="clear: both"><a id="cachesize"></a>Selecting the Cache Size</h2>
</div>
</div>
<div></div>
</div>
<p>
Cache size is important to your application because if it is set to too
small of a value, your application's performance will suffer from too
much disk I/O. On the other hand, if your cache is too large, then your
application will use more memory than it actually needs.
Moreover, if your application uses too much memory, then on most
operating systems this can result in your application being swapped out
of memory, resulting in extremely poor performance.
</p>
<p>
You select your cache size using either
<span>
<tt class="methodname">DB-&gt;set_cachesize()</tt>, or
<tt class="methodname">DB_ENV-&gt;set_cachesize()</tt>,
</span>
depending on whether you are using a database environment or not. You
cache size must be a power of 2, but it is otherwise limited only by
available memory and performance considerations.
</p>
<p>
Selecting a cache size is something of an art, but fortunately you
can change it any time, so it can be easily tuned to your
application's changing data requirements. The best way to
determine how large your cache needs to be is to put your
application into a production environment and watch to see how much
disk I/O is occurring. If your application is going to disk quite a
lot to retrieve database records, then you should increase the size
of your cache (provided that you have enough memory to do so).
</p>
<p>
You can use the <tt class="literal">db_stat</tt> command line utility with the
<tt class="literal">-m</tt> option to gauge the effectiveness of your cache.
In particular, the number of pages found in the cache is shown, along
with a percentage value. The closer to 100% that you can get, the
better. If this value drops too low, and you are experiencing
performance problems, then you should consider increasing the size of
your cache, assuming you have memory to support it.
</p>
</div>
<div class="navfooter">
<hr />
<table width="100%" summary="Navigation footer">
<tr>
<td width="40%" align="left"><a accesskey="p" href="dbconfig.html">Prev</a> </td>
<td width="20%" align="center">
<a accesskey="u" href="dbconfig.html">Up</a>
</td>
<td width="40%" align="right"> <a accesskey="n" href="btree.html">Next</a></td>
</tr>
<tr>
<td width="40%" align="left" valign="top">Chapter 6. Database Configuration </td>
<td width="20%" align="center">
<a accesskey="h" href="index.html">Home</a>
</td>
<td width="40%" align="right" valign="top"> BTree Configuration</td>
</tr>
</table>
</div>
</body>
</html>

168
docs/gsg/C/concepts.html Normal file
View File

@@ -0,0 +1,168 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>Berkeley DB Concepts</title>
<link rel="stylesheet" href="gettingStarted.css" type="text/css" />
<meta name="generator" content="DocBook XSL Stylesheets V1.62.4" />
<link rel="home" href="index.html" title="Getting Started with Berkeley DB" />
<link rel="up" href="introduction.html" title="Chapter 1. Introduction to Berkeley DB " />
<link rel="previous" href="introduction.html" title="Chapter 1. Introduction to Berkeley DB " />
<link rel="next" href="accessmethods.html" title="Access Methods" />
</head>
<body>
<div class="navheader">
<table width="100%" summary="Navigation header">
<tr>
<th colspan="3" align="center">Berkeley DB Concepts</th>
</tr>
<tr>
<td width="20%" align="left"><a accesskey="p" href="introduction.html">Prev</a> </td>
<th width="60%" align="center">Chapter 1. Introduction to Berkeley DB </th>
<td width="20%" align="right"> <a accesskey="n" href="accessmethods.html">Next</a></td>
</tr>
</table>
<hr />
</div>
<div class="sect1" lang="en" xml:lang="en">
<div class="titlepage">
<div>
<div>
<h2 class="title" style="clear: both"><a id="concepts"></a>Berkeley DB Concepts</h2>
</div>
</div>
<div></div>
</div>
<p>
Before continuing, it is useful to describe some of the larger concepts
that you will encounter when building a DB application.
</p>
<p>
Conceptually, DB databases contain <span class="emphasis"><em>records</em></span>.
Logically each record represents a single entry in the database.
Each such record contains two pieces of information: a key and a data.
This manual will on occasion describe a <span class="emphasis"><em>a record's
key</em></span> or a <span class="emphasis"><em>record's data</em></span> when it is
necessary to speak to one or the other portion of a database
record.
</p>
<p>
Because of the key/data pairing used for DB databases, they are
sometimes thought of as a two-column table. However, data (and
sometimes keys, depending on the access method) can hold arbitrarily
complex data. Frequently, C structures and other such mechanisms are
stored in the record. This effectively turns a 2-column table
into a table with <span class="emphasis"><em>n</em></span> columns, where
<span class="emphasis"><em>n-1</em></span> of those columns are provided by the structure's
fields.
</p>
<p>
Note that a DB database is very much like a table in a relational
database system in that most DB applications use more than one
database (just as most relational databases use more than one table).
</p>
<p>
Unlike relational systems, however, a DB database contains a single
collection of records organized according to a given access method
(BTree, Queue, Hash, and so forth). In a relational database system,
the underlying access method is generally hidden from you.
</p>
<p>
In any case, frequently DB
applications are designed so that a single database stores a specific
type of data (just as in a relational database system, a single table
holds entries containing a specific set of fields). Because most applications
are required to manage multiple kinds of data, a DB application will
often use multiple databases.
</p>
<p>
For example, consider an accounting application. This kind of an
application may manage data based on bank accounts, checking
accounts, stocks, bonds, loans, and so forth. An accounting application
will also have to manage information about people, banking institutions,
customer accounts, and so on. In a traditional relational database, all
of these different kinds of information would be stored and managed
using a (probably very) complex series of tables. In a DB
application, all of this information would instead be divided out and
managed using multiple databases.
</p>
<p>
DB applications can efficiently use multiple databases using an
optional mechanism called an <span class="emphasis"><em>environment</em></span>.
For more information, see <a href="environments.html">Environments</a>.
</p>
<p>
You interact with most DB APIs using special structures that
contain pointers to functions. These callbacks are
called <span class="emphasis"><em>methods</em></span> because they look so much like a
method on a C++ class. The variable that you use to access these
methods is often referred to as a
<span class="emphasis"><em>handle</em></span>. For example, to use a database you will
obtain a handle to that database.
</p>
<p>
Retrieving a record from a database is sometimes called
<span class="emphasis"><em>getting the record</em></span> because the method that you use
to retrieve the records is called <tt class="methodname">get()</tt>.
Similarly, storing database records is sometimes called
<span class="emphasis"><em>putting the record</em></span> because you use the
<tt class="methodname">put()</tt> method to do this.
</p>
<p>
When you store, or put, a record to a database using its handle, the
record is stored according to whatever sort order is in use by the
database. Sorting is mostly performed based on the key, but sometimes
the data is considered too. If you put a record using a key that already
exists in the database, then the existing record is replaced with the
new data. However, if the database supports
duplicate records (that is, records with identical keys but
different data), then that new record is stored as a duplicate record and
any existing records are not overwritten.
</p>
<p>
If a database supports duplicate records, then you can use a database
handle to retrieve only the first record in a set of duplicate records.
</p>
<p>
In addition to using a database handle, you can also read and write data using a
special mechanism called a <span class="emphasis"><em>cursor</em></span>. Cursors are
essentially iterators that you can use to walk over the records in a
database. You can use cursors to iterate over a database from the first
record to the last, and from the last to the first. You can also use
cursors to seek to a record. In the event that a database supports
duplicate records, cursors are the only way you can access all the
records in a set of duplicates.
</p>
<p>
Finally, DB provides a special kind of a database called a
<span class="emphasis"><em>secondary database</em></span>. Secondary databases serve as an
index into normal databases (called primary database to distinguish them
from secondaries). Secondary databases are interesting because DB
records can hold complex data types, but seeking to a given record is
performed only based on that record's key. If you wanted to be able to
seek to a record based on some piece of information that is not the key,
then you enable this through the use of secondary databases.
</p>
</div>
<div class="navfooter">
<hr />
<table width="100%" summary="Navigation footer">
<tr>
<td width="40%" align="left"><a accesskey="p" href="introduction.html">Prev</a> </td>
<td width="20%" align="center">
<a accesskey="u" href="introduction.html">Up</a>
</td>
<td width="40%" align="right"> <a accesskey="n" href="accessmethods.html">Next</a></td>
</tr>
<tr>
<td width="40%" align="left" valign="top">Chapter 1. Introduction to Berkeley DB  </td>
<td width="20%" align="center">
<a accesskey="h" href="index.html">Home</a>
</td>
<td width="40%" align="right" valign="top"> Access Methods</td>
</tr>
</table>
</div>
</body>
</html>

106
docs/gsg/C/coredbclose.html Normal file
View File

@@ -0,0 +1,106 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>Closing Databases</title>
<link rel="stylesheet" href="gettingStarted.css" type="text/css" />
<meta name="generator" content="DocBook XSL Stylesheets V1.62.4" />
<link rel="home" href="index.html" title="Getting Started with Berkeley DB" />
<link rel="up" href="DB.html" title="Chapter 2. Databases" />
<link rel="previous" href="DB.html" title="Chapter 2. Databases" />
<link rel="next" href="DBOpenFlags.html" title="Database Open Flags" />
</head>
<body>
<div class="navheader">
<table width="100%" summary="Navigation header">
<tr>
<th colspan="3" align="center">Closing Databases</th>
</tr>
<tr>
<td width="20%" align="left"><a accesskey="p" href="DB.html">Prev</a> </td>
<th width="60%" align="center">Chapter 2. Databases</th>
<td width="20%" align="right"> <a accesskey="n" href="DBOpenFlags.html">Next</a></td>
</tr>
</table>
<hr />
</div>
<div class="sect1" lang="en" xml:lang="en">
<div class="titlepage">
<div>
<div>
<h2 class="title" style="clear: both"><a id="coredbclose"></a>Closing Databases</h2>
</div>
</div>
<div></div>
</div>
<p>
Once you are done using the database, you must close it. You use the
<tt class="methodname">DB-&gt;close()</tt>
method to do this.
</p>
<p>
Closing a database causes it to become unusable until it is opened
again. Note that you should make sure that any open cursors are closed
before closing your database. Active cursors during a database
close can cause unexpected results, especially if any of those cursors are
writing to the database. You should always make sure that all your
database accesses have completed before closing your database.
</p>
<p>
Cursors are described in <a href="Cursors.html">Using Cursors</a> later in this manual.
</p>
<p>
Be aware that when you close the last open handle
for a database, then by default its cache is flushed to disk.
This means that any information that has
been modified in the cache is guaranteed to be written to disk when the
last handle is closed. You can manually perform this operation using
the
<tt class="methodname">DB-&gt;sync()</tt>
method, but for normal shutdown operations it is not necessary.
For more information about syncing your cache, see
<a href="usingDbt.html#datapersist">Data Persistence</a>.
</p>
<p>The following code fragment illustrates a database close:</p>
<a id="c_db2"></a>
<pre class="programlisting">#include &lt;db.h&gt;
...
DB *dbp; /* DB struct handle */
...
/*
* Database open and access operations
* happen here.
*/
...
/* When we're done with the database, close it. */
if (dbp != NULL)
dbp-&gt;close(dbp, 0); </pre>
</div>
<div class="navfooter">
<hr />
<table width="100%" summary="Navigation footer">
<tr>
<td width="40%" align="left"><a accesskey="p" href="DB.html">Prev</a> </td>
<td width="20%" align="center">
<a accesskey="u" href="DB.html">Up</a>
</td>
<td width="40%" align="right"> <a accesskey="n" href="DBOpenFlags.html">Next</a></td>
</tr>
<tr>
<td width="40%" align="left" valign="top">Chapter 2. Databases </td>
<td width="20%" align="center">
<a accesskey="h" href="index.html">Home</a>
</td>
<td width="40%" align="right" valign="top"> Database Open Flags</td>
</tr>
</table>
</div>
</body>
</html>

View File

@@ -0,0 +1,700 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>Secondary Database Example</title>
<link rel="stylesheet" href="gettingStarted.css" type="text/css" />
<meta name="generator" content="DocBook XSL Stylesheets V1.62.4" />
<link rel="home" href="index.html" title="Getting Started with Berkeley DB" />
<link rel="up" href="indexes.html" title="Chapter 5. Secondary Databases" />
<link rel="previous" href="joins.html" title="Database Joins" />
<link rel="next" href="dbconfig.html" title="Chapter 6. Database Configuration" />
</head>
<body>
<div class="navheader">
<table width="100%" summary="Navigation header">
<tr>
<th colspan="3" align="center">Secondary Database Example</th>
</tr>
<tr>
<td width="20%" align="left"><a accesskey="p" href="joins.html">Prev</a> </td>
<th width="60%" align="center">Chapter 5. Secondary Databases</th>
<td width="20%" align="right"> <a accesskey="n" href="dbconfig.html">Next</a></td>
</tr>
</table>
<hr />
</div>
<div class="sect1" lang="en" xml:lang="en">
<div class="titlepage">
<div>
<div>
<h2 class="title" style="clear: both"><a id="coreindexusage"></a>Secondary Database Example</h2>
</div>
</div>
<div></div>
</div>
<p>
In previous chapters in this book, we built applications that load
and display several DB databases. In this example, we will extend those
examples to use secondary databases. Specifically:
</p>
<div class="itemizedlist">
<ul type="disc">
<li>
<p>
In
<a href="DbUsage.html">Database Usage Example</a>
we built an application that can open and load data into several databases.
In <a href="coreindexusage.html#edlWIndexes">Secondary Databases with example_database_load</a> we will extend
that application to also open a secondary database for the purpose
of indexing inventory item names.
</p>
</li>
<li>
<p>
In <a href="CoreCursorUsage.html">Cursor Example</a> we
built an application to display our inventory database (and related
vendor information). In
<a href="coreindexusage.html#edrWIndexes">Secondary Databases with example_database_read</a>
we will extend that application to
show inventory records based on the index we cause to be loaded using
<tt class="function">example_database_load</tt>.
</p>
</li>
</ul>
</div>
<div class="sect2" lang="en" xml:lang="en">
<div class="titlepage">
<div>
<div>
<h3 class="title"><a id="edlWIndexes"></a>Secondary Databases with example_database_load</h3>
</div>
</div>
<div></div>
</div>
<p>
<tt class="function">example_database_load</tt> uses several utility
functions to open and close its databases. In order to cause
<tt class="function">example_database_load</tt> to maintain an index of
inventory item names, all we really need to do is update the utility
functions to:
</p>
<div class="orderedlist">
<ol type="1">
<li>
<p>
Create a new database to be used as a secondary database.
</p>
</li>
<li>
<p>
Associate our new database to the inventory primary
database.
</p>
</li>
<li>
<p>
Close the secondary database when we close the rest of our
databases.
</p>
</li>
</ol>
</div>
<p>
We also need a function that can create our secondary keys for us.
</p>
<p>
Because DB maintains secondary databases for us; once this work
is done we need not make any other changes to <tt class="function">example_database_load</tt>.
<span>Therefore, we can limit
all our work to the code found in <tt class="filename">gettingstarted_common.h</tt>
and <tt class="filename">gettingstarted_common.c</tt>.
</span>
</p>
<p>
Remember that you can find the complete implementation of these functions
in:
</p>
<pre class="programlisting"><span class="emphasis"><em>DB_INSTALL</em></span>/examples_c/getting_started</pre>
<p>
where <tt class="literal"><span class="emphasis"><em>DB_INSTALL</em></span></tt> is the location where you
placed your DB distribution.
</p>
<p>
To begin, we need to update the <tt class="literal">stock_dbs</tt>
structure to accommodate the additional database. We defined this
structure in <tt class="filename">gettingstarted_common.h</tt>. We can
limit our update to this file to just that structure definition:
</p>
<p>
Remember that new code is in <b class="userinput"><tt>bold</tt></b>.
</p>
<a id="c_index10"></a>
<pre class="programlisting">/* file: gettingstarted_common.h */
#include &lt;db.h&gt;
typedef struct stock_dbs {
DB *inventory_dbp; /* Database containing inventory information */
DB *vendor_dbp; /* Database containing vendor information */
<b class="userinput"><tt>DB *itemname_sdbp; /* Index based on the item name index */</tt></b>
char *db_home_dir; /* Directory containing the database files */
<b class="userinput"><tt>char *itemname_db_name; /* Itemname secondary database */</tt></b>
char *inventory_db_name; /* Name of the inventory database */
char *vendor_db_name; /* Name of the vendor database */
} STOCK_DBS;
/* Function prototypes */
int databases_setup(STOCK_DBS *, const char *, FILE *);
int databases_close(STOCK_DBS *);
void initialize_stockdbs(STOCK_DBS *);
int open_database(DB **, const char *, const char *, FILE *, <b class="userinput"><tt>int</tt></b>);
void set_db_filenames(STOCK_DBS *my_stock);
</pre>
<p>
Because we updated our stock_dbs structure, we need to update our
stock_dbs utility functions
(<a href="CoreDbUsage.html#stock-db-functions">The stock_db Utility Functions</a>)
accordingly. The updates are trivial and so we won't show them here
in the interest of space. You can find their complete implementation
in the <tt class="filename">gettingstarted_common.c</tt> file
accompanying this example in your DB distribution.
</p>
<p>
More importantly, however, we need to go to
<tt class="filename">gettingstarted_common.c</tt>
and create our secondary key extractor function. When we
store our inventory items, we place the item name in the buffer
immediately after a <tt class="literal">float</tt> and an
<tt class="literal">int</tt>, so retrieving the string from the buffer is
fairly easy to do:
</p>
<a id="c_index11"></a>
<pre class="programlisting">/* file: gettingstarted_common.c */
#include "gettingstarted_common.h"
<b class="userinput"><tt>/*
* Used to extract an inventory item's name from an
* inventory database record. This function is used to create
* keys for secondary database records.
*/
int
get_item_name(DB *dbp, const DBT *pkey, const DBT *pdata, DBT *skey)
{
int offset;
/*
* First, obtain the buffer location where we placed the
* item's name. In this example, the item's name is located
* in the primary data. It is the first string in the
* buffer after the price (a float) and the quantity (an int).
*
* See load_inventory_database() in example_database_load.c
* for how we marshalled the inventory information into the
* data DBT.
*/
offset = sizeof(float) + sizeof(int);
/* Check to make sure there's data */
if (pdata-&gt;size &lt; offset)
return (-1); /* Returning non-zero means that the
* secondary record is not created/updated.
*/
/* Now set the secondary key's data to be the item name */
memset(skey, 0, sizeof(DBT));
skey-&gt;data = pdata-&gt;data + offset;
skey-&gt;size = strlen(skey-&gt;data) + 1;
return (0);
}</tt></b> </pre>
<p>
Having completed that function, we need to update
<tt class="function">set_db_filenames()</tt> and
<tt class="function">initialize_stockdbs()</tt> to handle the
new secondary databases that our application will now use.
These functions were originally introduced in
<a href="CoreDbUsage.html#stock-db-functions">The stock_db Utility Functions</a>.
</p>
<a id="c_index11.1"></a>
<pre class="programlisting">
/* Initializes the STOCK_DBS struct.*/
void
initialize_stockdbs(STOCK_DBS *my_stock)
{
my_stock-&gt;db_home_dir = DEFAULT_HOMEDIR;
my_stock-&gt;inventory_dbp = NULL;
my_stock-&gt;vendor_dbp = NULL;
<b class="userinput"><tt>my_stock-&gt;itemname_sdbp = NULL;</tt></b>
my_stock-&gt;inventory_db_name = NULL;
my_stock-&gt;vendor_db_name = NULL;
<b class="userinput"><tt>my_stock-&gt;itemname_db_name = NULL;</tt></b>
}
/* Identify all the files that will hold our databases. */
void
set_db_filenames(STOCK_DBS *my_stock)
{
size_t size;
/* Create the Inventory DB file name */
size = strlen(my_stock-&gt;db_home_dir) + strlen(INVENTORYDB) + 1;
my_stock-&gt;inventory_db_name = malloc(size);
snprintf(my_stock-&gt;inventory_db_name, size, "%s%s",
my_stock-&gt;db_home_dir, INVENTORYDB);
/* Create the Vendor DB file name */
size = strlen(my_stock-&gt;db_home_dir) + strlen(VENDORDB) + 1;
my_stock-&gt;vendor_db_name = malloc(size);
snprintf(my_stock-&gt;vendor_db_name, size, "%s%s",
my_stock-&gt;db_home_dir, VENDORDB);
<b class="userinput"><tt>/* Create the itemname DB file name */
size = strlen(my_stock-&gt;db_home_dir) + strlen(ITEMNAMEDB) + 1;
my_stock-&gt;itemname_db_name = malloc(size);
snprintf(my_stock-&gt;itemname_db_name, size, "%s%s",
my_stock-&gt;db_home_dir, ITEMNAMEDB);</tt></b>
} </pre>
<p>
We also need to update the
<tt class="function">open_database()</tt> (as described in
<a href="CoreDbUsage.html#open-db">open_database() Function</a>)
to take special actions if we are
opening a secondary database. Unlike our primary databases, we want to
support sorted duplicates for our secondary database. This is because we
are indexing based on an item's name, and item names are
shared by multiple inventory records. As a result every key the secondary
database (an item name) will be used by multiple records (pointers to
records in our primary database). We allow this by configuring our
secondary database to support duplicate records. Further, because
BTrees perform best when their records are sorted, we go ahead and
configure our secondary database for sorted duplicates.
</p>
<p>
To do this, we add a parameter to the function that indicates whether we are
opening a secondary database, and we add in the few lines of code
necessary to set the sorted duplicates flags.
</p>
<a id="c_index12"></a>
<pre class="programlisting">/* Opens a database */
int
open_database(DB **dbpp, /* The DB handle that we are opening */
const char *file_name, /* The file in which the db lives */
const char *program_name, /* Name of the program calling this
* function */
FILE *error_file_pointer,
<b class="userinput"><tt>int is_secondary</tt></b>)
{
DB *dbp; /* For convenience */
u_int32_t open_flags;
int ret;
/* Initialize the DB handle */
ret = db_create(&amp;dbp, NULL, 0);
if (ret != 0) {
fprintf(error_file_pointer, "%s: %s\n", program_name,
db_strerror(ret));
return (ret);
}
/* Point to the memory malloc'd by db_create() */
*dbpp = dbp;
/* Set up error handling for this database */
dbp-&gt;set_errfile(dbp, error_file_pointer);
dbp-&gt;set_errpfx(dbp, program_name);
<b class="userinput"><tt>/*
* If this is a secondary database, then we want to allow
* sorted duplicates.
*/
if (is_secondary) {
ret = dbp-&gt;set_flags(dbp, DB_DUPSORT);
if (ret != 0) {
dbp-&gt;err(dbp, ret, "Attempt to set DUPSORT flag failed.",
file_name);
return (ret);
}
}</tt></b>
/* Set the open flags */
open_flags = DB_CREATE;
/* Now open the database */
ret = dbp-&gt;open(dbp, /* Pointer to the database */
NULL, /* Txn pointer */
file_name, /* File name */
NULL, /* Logical db name (unneeded) */
DB_BTREE, /* Database type (using btree) */
open_flags, /* Open flags */
0); /* File mode. Using defaults */
if (ret != 0) {
dbp-&gt;err(dbp, ret, "Database '%s' open failed.", file_name);
return (ret);
}
return (ret);
} </pre>
<p>
That done, we can now update <tt class="function">databases_setup()</tt>
(see <a href="CoreDbUsage.html#databasesetup">The databases_setup() Function</a>) to create
and open our secondary database. To do this, we have to add a flag to
each call to <tt class="function">open_database()</tt> that indicates whether
the database is a secondary. We also have to associate our secondary
database with the inventory database (the primary).
</p>
<p>
Note that we do not anywhere in this example show the definition of
<tt class="literal">PRIMARY_DB</tt> and <tt class="literal">SECONDARY_DB</tt>. See
<tt class="filename">gettingstarted_common.h</tt> in your DB examples
directory for those definitions (they are just <tt class="literal">0</tt> and
<tt class="literal">1</tt>, respectively).
</p>
<a id="c_index13"></a>
<pre class="programlisting">/* opens all databases */
int
databases_setup(STOCK_DBS *my_stock, const char *program_name,
FILE *error_file_pointer)
{
int ret;
/* Open the vendor database */
ret = open_database(&amp;(my_stock-&gt;vendor_dbp),
my_stock-&gt;vendor_db_name,
program_name, error_file_pointer,
<b class="userinput"><tt>PRIMARY_DB</tt></b>);
if (ret != 0)
/*
* Error reporting is handled in open_database() so just return
* the return code here.
*/
return (ret);
/* Open the inventory database */
ret = open_database(&amp;(my_stock-&gt;inventory_dbp),
my_stock-&gt;inventory_db_name,
program_name, error_file_pointer,
<b class="userinput"><tt>PRIMARY_DB</tt></b>);
if (ret != 0)
/*
* Error reporting is handled in open_database() so just return
* the return code here.
*/
return (ret);
<b class="userinput"><tt>/*
* Open the itemname secondary database. This is used to
* index the product names found in the inventory
* database.
*/
ret = open_database(&amp;(my_stock-&gt;itemname_sdbp),
my_stock-&gt;itemname_db_name,
program_name, error_file_pointer,
SECONDARY_DB);
if (ret != 0)
/*
* Error reporting is handled in open_database() so just return
* the return code here.
*/
return (ret);
/*
* Associate the itemname db with its primary db
* (inventory db).
*/
my_stock-&gt;inventory_dbp-&gt;associate(
my_stock-&gt;inventory_dbp, /* Primary db */
NULL, /* txn id */
my_stock-&gt;itemname_sdbp, /* Secondary db */
get_item_name, /* Secondary key extractor */
0); /* Flags */
</tt></b>
printf("databases opened successfully\n");
return (0);
}</pre>
<p>
Finally, we need to update <tt class="function">databases_close()</tt>
(<a href="CoreDbUsage.html#database_close">The databases_close() Function</a>)
to close our
new secondary database. Note that we are careful to close the secondary
before the primary, even though the database close routine is single
threaded.
</p>
<a id="c_index14"></a>
<pre class="programlisting">/* Closes all the databases and secondary databases. */
int
databases_close(STOCK_DBS *my_stock)
{
int ret;
/*
* Note that closing a database automatically flushes its cached data
* to disk, so no sync is required here.
*/
<b class="userinput"><tt>if (my_stock-&gt;itemname_sdbp != NULL) {
ret = my_stock-&gt;itemname_sdbp-&gt;close(my_stock-&gt;itemname_sdbp, 0);
if (ret != 0)
fprintf(stderr, "Itemname database close failed: %s\n",
db_strerror(ret));
}</tt></b>
if (my_stock-&gt;inventory_dbp != NULL) {
ret = my_stock-&gt;inventory_dbp-&gt;close(my_stock-&gt;inventory_dbp, 0);
if (ret != 0)
fprintf(stderr, "Inventory database close failed: %s\n",
db_strerror(ret));
}
if (my_stock-&gt;vendor_dbp != NULL) {
ret = my_stock-&gt;vendor_dbp-&gt;close(my_stock-&gt;vendor_dbp, 0);
if (ret != 0)
fprintf(stderr, "Vendor database close failed: %s\n",
db_strerror(ret));
}
printf("databases closed.\n");
return (0);
} </pre>
<p>
And the implementation changes slightly to take advantage of the new
boolean. Note that to save space, we just show the constructor where the
code actually changes:
</p>
<p>
That completes our update to <tt class="function">example_database_load</tt>.
Now when this program is called, it will automatically index inventory
items based on their names. We can then query for those items using the
new index. We show how to do that in the next section.
</p>
</div>
<div class="sect2" lang="en" xml:lang="en">
<div class="titlepage">
<div>
<div>
<h3 class="title"><a id="edrWIndexes"></a>Secondary Databases with example_database_read</h3>
</div>
</div>
<div></div>
</div>
<p>
In <a href="CoreCursorUsage.html">Cursor Example</a> we
wrote an application that displays every inventory item in the
Inventory database. In this section, we will update that example to
allow us to search for and display an inventory item given a
specific name. To do this, we will make use of the secondary
database that <tt class="function">example_database_load</tt> now
creates.
</p>
<p>
Because we manage all our database open and close activities in
<tt class="function">databases_setup()</tt> and
<tt class="function">databases_close()</tt>,
the update to <tt class="function">example_database_read</tt> is
relatively modest. We need only add a command line parameter on
which we can specify the item name, and we will need a new function
in which we will perform the query and display the results.
</p>
<p>
To begin, we add a single forward declaration to the application,
and update our usage function slightly:
</p>
<a id="c_index15"></a>
<pre class="programlisting">/* File: example_database_read.c */
/* gettingstarted_common.h includes db.h for us */
#include "gettingstarted_common.h"
/* Forward declarations */
char * show_inventory_item(void *);
int show_all_records(STOCK_DBS *);
<b class="userinput"><tt>int show_records(STOCK_DBS *, char *);</tt></b>
int show_vendor_record(char *, DB *); </pre>
<p>
Next, we update <tt class="function">main()</tt> to
accept the new command line switch.
We also need a new variable to contain the item's name.
</p>
<a id="c_index16"></a>
<pre class="programlisting">/*
<b class="userinput"><tt> * Searches for a inventory item based on that item's name. The search is
* performed using the item name secondary database. Displays all
* inventory items that use the specified name, as well as the vendor
* associated with that inventory item.
*
* If no item name is provided, then all inventory items are displayed.</tt></b>
*/
int
main(int argc, char *argv[])
{
STOCK_DBS my_stock;
int ret;
<b class="userinput"><tt>char *itemname</tt></b>;
/* Initialize the STOCK_DBS struct */
initialize_stockdbs(&amp;my_stock);
<b class="userinput"><tt>itemname = NULL;</tt></b>
/*
* Parse the command line arguments here and determine
* the location of the database files <b class="userinput"><tt>as well as the
* inventory item we want displayed, if any.</tt></b> This step is
* omitted for brevity.
*/
/*
* Identify the files that will hold our databases
* This function uses information obtained from the
* command line to identify the directory in which
* the database files reside.
*/
set_db_filenames(&amp;my_stock);
/* Open all databases */
ret = databases_setup(&amp;my_stock, "example_database_read", stderr);
if (ret != 0) {
fprintf(stderr, "Error opening databases\n");
databases_close(&amp;my_stock);
return (ret);
}</pre>
<p>
The final update to the <tt class="function">main()</tt> entails a little bit
of logic to determine whether we want to display all available inventory
items, or just the ones that match a name provided on the
<tt class="literal">-i</tt> command line parameter.
</p>
<a id="c_index17"></a>
<pre class="programlisting"> /*
* Show either a single item or all items, depending
* on whether itemname is set to a value.
*/
<b class="userinput"><tt>if (itemname == NULL)
ret = show_all_records(&amp;my_stock);
else
ret = show_records(&amp;my_stock, itemname);</tt></b>
/* Close our databases */
databases_close(&amp;my_stock);
return (ret);
} </pre>
<p>
The only other thing that we need to add to the application is the
implementation of the
<tt class="function">show_records()</tt>
function.
</p>
<div class="note" style="margin-left: 0.5in; margin-right: 0.5in;">
<h3 class="title">Note</h3>
<p>
In the interest of space, we refrain from showing the other
functions used by this application. For their implementation, please
see <a href="CoreCursorUsage.html">Cursor Example</a>.
Alternatively, you can see the entire implementation of this
application
in:
</p>
<pre class="programlisting"><span class="emphasis"><em>DB_INSTALL</em></span>/examples_c/getting_started</pre>
<p>
where <tt class="literal"><span class="emphasis"><em>DB_INSTALL</em></span></tt> is the location where you
placed your DB distribution.
</p>
</div>
<a id="c_index18"></a>
<pre class="programlisting">/*
* Search for an inventory item given its name (using the inventory item
* secondary database) and display that record and any duplicates that may
* exist.
*/
int
show_records(STOCK_DBS *my_stock, char *itemname)
{
DBC *itemname_cursorp;
DBT key, data;
char *the_vendor;
int ret, exit_value;
/* Initialize our DBTs. */
memset(&amp;key, 0, sizeof(DBT));
memset(&amp;data, 0, sizeof(DBT));
/* Get a cursor to the itemname db */
my_stock-&gt;itemname_sdbp-&gt;cursor(my_stock-&gt;itemname_sdbp, 0,
&amp;itemname_cursorp, 0);
/*
* Get the search key. This is the name on the inventory
* record that we want to examine.
*/
key.data = itemname;
key.size = strlen(itemname) + 1;
/*
* Position our cursor to the first record in the secondary
* database that has the appropriate key.
*/
exit_value = 0;
ret = itemname_cursorp-&gt;get(itemname_cursorp, &amp;key, &amp;data, DB_SET);
if (!ret) {
do {
/*
* Show the inventory record and the vendor responsible
* for this inventory item.
*/
the_vendor = show_inventory_item(data.data);
ret = show_vendor_record(the_vendor, my_stock-&gt;vendor_dbp);
if (ret) {
exit_value = ret;
break;
}
/*
* Our secondary allows duplicates, so we need to loop over
* the next duplicate records and show them all. This is done
* because an inventory item's name is not a unique value.
*/
} while(itemname_cursorp-&gt;get(itemname_cursorp, &amp;key, &amp;data,
DB_NEXT_DUP) == 0);
} else {
printf("No records found for '%s'\n", itemname);
}
/* Close the cursor */
itemname_cursorp-&gt;close(itemname_cursorp);
return (exit_value);
} </pre>
<p>
This completes our update to
<tt class="classname">example_inventory_read</tt>. Using this update, you
can now search for and show all inventory items that match a particular
name. For example:
</p>
<pre class="programlisting"> example_inventory_read -i "Zulu Nut"</pre>
</div>
</div>
<div class="navfooter">
<hr />
<table width="100%" summary="Navigation footer">
<tr>
<td width="40%" align="left"><a accesskey="p" href="joins.html">Prev</a> </td>
<td width="20%" align="center">
<a accesskey="u" href="indexes.html">Up</a>
</td>
<td width="40%" align="right"> <a accesskey="n" href="dbconfig.html">Next</a></td>
</tr>
<tr>
<td width="40%" align="left" valign="top">Database Joins </td>
<td width="20%" align="center">
<a accesskey="h" href="index.html">Home</a>
</td>
<td width="40%" align="right" valign="top"> Chapter 6. Database Configuration</td>
</tr>
</table>
</div>
</body>
</html>

324
docs/gsg/C/cstructs.html Normal file
View File

@@ -0,0 +1,324 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>Using C Structures with DB</title>
<link rel="stylesheet" href="gettingStarted.css" type="text/css" />
<meta name="generator" content="DocBook XSL Stylesheets V1.62.4" />
<link rel="home" href="index.html" title="Getting Started with Berkeley DB" />
<link rel="up" href="DBEntry.html" title="Chapter 3. Database Records" />
<link rel="previous" href="usingDbt.html" title="Reading and Writing Database Records" />
<link rel="next" href="DbUsage.html" title="Database Usage Example" />
</head>
<body>
<div class="navheader">
<table width="100%" summary="Navigation header">
<tr>
<th colspan="3" align="center">Using C Structures with DB</th>
</tr>
<tr>
<td width="20%" align="left"><a accesskey="p" href="usingDbt.html">Prev</a> </td>
<th width="60%" align="center">Chapter 3. Database Records</th>
<td width="20%" align="right"> <a accesskey="n" href="DbUsage.html">Next</a></td>
</tr>
</table>
<hr />
</div>
<div class="sect1" lang="en" xml:lang="en">
<div class="titlepage">
<div>
<div>
<h2 class="title" style="clear: both"><a id="cstructs"></a>Using C Structures with DB</h2>
</div>
</div>
<div></div>
</div>
<p>
Storing data in structures is a handy way to pack varied types of
information into each database record. DB databases are sometimes
thought of as a two column table where column 1 is the key and column 2 is
the data. By using structures, you can effectively turn this table into
<span class="emphasis"><em>n</em></span> columns where <span class="emphasis"><em>n-1</em></span> columns
are contained in the structure.
</p>
<p>
So long as a C structure contains fields that are not pointers, you can safely
store and retrieve them in the same way as you would any primitive
datatype. The following code fragment illustrates this:
</p>
<a id="c_dbt6"></a>
<pre class="programlisting">#include &lt;db.h&gt;
#include &lt;string.h&gt;
typedef struct my_struct {
int id;
char familiar_name[MAXLINE]; /* Some suitably large value */
char surname[MAXLINE];
} MY_STRUCT;
...
DBT key, data;
DB *my_database;
MY_STRUCT user;
char *fname = "David";
char *sname = "Rider";
/* Database open omitted for clarity */
user.id = 1;
strncpy(user.familiar_name, fname, strlen(fname)+1);
strncpy(user.surname, sname, strlen(sname)+1);
/* Zero out the DBTs before using them. */
memset(&amp;key, 0, sizeof(DBT));
memset(&amp;data, 0, sizeof(DBT));
key.data = &amp;(user.id);
key.size = sizeof(int);
data.data = &amp;user;
data.size = sizeof(MY_STRUCT);
my_database-&gt;put(my_database, NULL, &amp;key, &amp;data, DB_NOOVERWRITE);</pre>
<p>
To retrieve the structure, make sure you supply your own
memory. The reason why is that like real numbers, some systems require
structures to be aligned in a specific way. Because it is possible that
the memory DB provides is not aligned properly, for safest result simply
use your own memory:
</p>
<a id="c_dbt7"></a>
<pre class="programlisting">#include &lt;db.h&gt;
#include &lt;string.h&gt;
...
DBT key, data;
DB *my_database;
MY_STRUCT user;
/* Database open omitted for clarity */
/* Zero out the DBTs before using them. */
memset(&amp;key, 0, sizeof(DBT));
memset(&amp;data, 0, sizeof(DBT));
/* Initialize the structure */
memset(&amp;user, 0, sizeof(MY_STRUCT));
user.id = 1;
key.data = &amp;user.id;
key.size = sizeof(int);
/* Use our memory to retrieve the structure */
data.data = &amp;user;
data.ulen = sizeof(MY_STRUCT);
data.flags = DB_DBT_USERMEM;
my_database-&gt;get(my_database, NULL, &amp;key, &amp;data, 0);
printf("Familiar name: %s\n", user.familiar_name);
printf("Surname: %s\n", user.surname); </pre>
<p>
Be aware that while this is the easiest way to manage structures stored
in DB databases, this approach does suffer from causing your
database to be larger than is strictly necessary. Each structure stored
in the database is of a fixed size, and you do not see any space savings
from storing a (for example) 5 character surname versus a 20 character
surname.
</p>
<p>
For a simple example such as this, the padding stored with each record
is probably not critical. However, if you are storing structures that
contain a very large number of character arrays, or if you are simply
storing millions of records, then you may want to avoid this approach.
The wasted space in each record will only serve to make your databases
larger than need be, which will in turn require a larger cache and more
disk I/O than you would ordinarily need.
</p>
<p>
An alternative approach is described next.
</p>
<div class="sect2" lang="en" xml:lang="en">
<div class="titlepage">
<div>
<div>
<h3 class="title"><a id="cstructdynamic"></a>C Structures with Pointers</h3>
</div>
</div>
<div></div>
</div>
<p>
It is often necessary in C structures
to use fields
that are pointers to
dynamically allocated memory. This is particularly
true if you want to store character strings (or any kind of an array for
that matter), and you want to avoid any overhead caused by
pre-designating the size of the array.
</p>
<p>
When storing structures
like these you need to make sure that all of
the data pointed to and contained by the structure
is lined up in a
single contiguous block of memory. Remember that DB stores data
located at a specific address and of a particular size. If your structure
includes fields
that are pointing to dynamically allocated memory, then
the data that you want to store can be located in different, not
necessarily contiguous, locations on the heap.
</p>
<p>
The easiest way to solve this problem is to pack your data
into a single memory location and then store the data in that location.
(This process is sometimes called <span class="emphasis"><em>marshalling the
data</em></span>.)
For example:
</p>
<a id="c_dbt8"></a>
<pre class="programlisting">#include &lt;db.h&gt;
#include &lt;string.h&gt;
#include &lt;stdlib.h&gt;
typedef struct my_struct {
int id;
char *familiar_name;
char *surname;
} MY_STRUCT;
...
DBT key, data;
DB *my_database;
MY_STRUCT user;
int buffsize, bufflen;
char fname[ ] = "Pete";
char sname[10];
char *databuff;
strncpy(sname, "Oar", strlen("Oar")+1);
/* Database open omitted for clarity */
user.id = 1;
user.familiar_name = fname;
user.surname = sname;
/* Some of the structure's data is on the stack, and
* some is on the heap. To store this structure's data, we
* need to marshall it -- pack it all into a single location
* in memory.
*/
/* Get the buffer */
buffsize = sizeof(int) +
(strlen(user.familiar_name) + strlen(user.surname) + 2);
databuff = malloc(buffsize);
memset(databuff, 0, buffsize);
/* copy everything to the buffer */
memcpy(databuff, &amp;(user.id), sizeof(int));
bufflen = sizeof(int);
memcpy(databuff + bufflen, user.familiar_name,
strlen(user.familiar_name) + 1);
bufflen += strlen(user.familiar_name) + 1;
memcpy(databuff + bufflen, user.surname,
strlen(user.surname) + 1);
bufflen += strlen(user.surname) + 1;
/* Now store it */
/* Zero out the DBTs before using them. */
memset(&amp;key, 0, sizeof(DBT));
memset(&amp;data, 0, sizeof(DBT));
key.data = &amp;(user.id);
key.size = sizeof(int);
data.data = databuff;
data.size = bufflen;
my_database-&gt;put(my_database, NULL, &amp;key, &amp;data, DB_NOOVERWRITE);
free(sname);
free(databuff);</pre>
<p>
To retrieve the stored structure:
</p>
<a id="c_dbt9"></a>
<pre class="programlisting">#include &lt;db.h&gt;
#include &lt;string.h&gt;
#include &lt;stdlib.h&gt;
typedef struct my_struct {
char *familiar_name;
char *surname;
int id;
} MY_STRUCT;
...
int id;
DBT key, data;
DB *my_database;
MY_STRUCT user;
char *buffer;
/* Database open omitted for clarity */
/* Zero out the DBTs before using them. */
memset(&amp;key, 0, sizeof(DBT));
memset(&amp;data, 0, sizeof(DBT));
id = 1;
key.data = &amp;id;
key.size = sizeof(int);
my_database-&gt;get(my_database, NULL, &amp;key, &amp;data, 0);
/*
* Some compilers won't allow pointer arithmetic on void *'s,
* so use a char * instead.
*/
buffer = data.data;
user.id = *((int *)data.data);
user.familiar_name = buffer + sizeof(int);
user.surname = buffer + sizeof(int) + strlen(user.familiar_name) + 1; </pre>
</div>
</div>
<div class="navfooter">
<hr />
<table width="100%" summary="Navigation footer">
<tr>
<td width="40%" align="left"><a accesskey="p" href="usingDbt.html">Prev</a> </td>
<td width="20%" align="center">
<a accesskey="u" href="DBEntry.html">Up</a>
</td>
<td width="40%" align="right"> <a accesskey="n" href="DbUsage.html">Next</a></td>
</tr>
<tr>
<td width="40%" align="left" valign="top">Reading and Writing Database Records </td>
<td width="20%" align="center">
<a accesskey="h" href="index.html">Home</a>
</td>
<td width="40%" align="right" valign="top"> Database Usage Example</td>
</tr>
</table>
</div>
</body>
</html>

View File

@@ -0,0 +1,81 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>Database Limits and Portability</title>
<link rel="stylesheet" href="gettingStarted.css" type="text/css" />
<meta name="generator" content="DocBook XSL Stylesheets V1.62.4" />
<link rel="home" href="index.html" title="Getting Started with Berkeley DB" />
<link rel="up" href="introduction.html" title="Chapter 1. Introduction to Berkeley DB " />
<link rel="previous" href="accessmethods.html" title="Access Methods" />
<link rel="next" href="environments.html" title="Environments" />
</head>
<body>
<div class="navheader">
<table width="100%" summary="Navigation header">
<tr>
<th colspan="3" align="center">Database Limits and Portability</th>
</tr>
<tr>
<td width="20%" align="left"><a accesskey="p" href="accessmethods.html">Prev</a> </td>
<th width="60%" align="center">Chapter 1. Introduction to Berkeley DB </th>
<td width="20%" align="right"> <a accesskey="n" href="environments.html">Next</a></td>
</tr>
</table>
<hr />
</div>
<div class="sect1" lang="en" xml:lang="en">
<div class="titlepage">
<div>
<div>
<h2 class="title" style="clear: both"><a id="databaseLimits"></a>Database Limits and Portability</h2>
</div>
</div>
<div></div>
</div>
<p>
Berkeley DB provides support for managing everything from very small
databases that fit entirely in memory, to extremely large databases
holding millions of records and terabytes of data. DB databases can
store up to 256 terabytes of data. Individual record keys or record
data can store up to 4 gigabytes of data.
</p>
<p>
DB's databases store data in a binary format that is portable across
platforms, even of differing endian-ness. Be aware, however, that
portability aside, some performance issues can crop up in the event that
you are using little endian architecture. See <a href="btree.html#comparators">Setting Comparison Functions</a>
for more information.
</p>
<p>
Also, DB's databases and data structures are designed for concurrent
access — they are thread-safe, and they share well across multiple
processes. That said, in order to allow multiple processes to share
databases and the cache, DB makes use of mechanisms that do not work
well on network-shared drives (NFS or Windows networks shares, for
example). For this reason, you cannot place your DB databases and
environments on network-mounted drives.
</p>
</div>
<div class="navfooter">
<hr />
<table width="100%" summary="Navigation footer">
<tr>
<td width="40%" align="left"><a accesskey="p" href="accessmethods.html">Prev</a> </td>
<td width="20%" align="center">
<a accesskey="u" href="introduction.html">Up</a>
</td>
<td width="40%" align="right"> <a accesskey="n" href="environments.html">Next</a></td>
</tr>
<tr>
<td width="40%" align="left" valign="top">Access Methods </td>
<td width="20%" align="center">
<a accesskey="h" href="index.html">Home</a>
</td>
<td width="40%" align="right" valign="top"> Environments</td>
</tr>
</table>
</div>
</body>
</html>

View File

@@ -0,0 +1,204 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>Error Reporting Functions</title>
<link rel="stylesheet" href="gettingStarted.css" type="text/css" />
<meta name="generator" content="DocBook XSL Stylesheets V1.62.4" />
<link rel="home" href="index.html" title="Getting Started with Berkeley DB" />
<link rel="up" href="DB.html" title="Chapter 2. Databases" />
<link rel="previous" href="CoreDBAdmin.html" title="Administrative Methods" />
<link rel="next" href="CoreEnvUsage.html" title="Managing Databases in Environments" />
</head>
<body>
<div class="navheader">
<table width="100%" summary="Navigation header">
<tr>
<th colspan="3" align="center">Error Reporting Functions</th>
</tr>
<tr>
<td width="20%" align="left"><a accesskey="p" href="CoreDBAdmin.html">Prev</a> </td>
<th width="60%" align="center">Chapter 2. Databases</th>
<td width="20%" align="right"> <a accesskey="n" href="CoreEnvUsage.html">Next</a></td>
</tr>
</table>
<hr />
</div>
<div class="sect1" lang="en" xml:lang="en">
<div class="titlepage">
<div>
<div>
<h2 class="title" style="clear: both"><a id="dbErrorReporting"></a>Error Reporting Functions</h2>
</div>
</div>
<div></div>
</div>
<p>
To simplify error reporting and handling, the
<span><tt class="classname">DB</tt> structure</span>
offers several useful methods.
</p>
<div class="itemizedlist">
<ul type="disc">
<li>
<p>
<tt class="methodname">set_errcall()</tt>
</p>
<p>
Defines the function that is called when an error message is
issued by DB. The error prefix and message are passed to
this callback. It is up to the application to display this
information correctly.
</p>
</li>
<li>
<p>
<tt class="methodname">set_errfile()</tt>
</p>
<p>
Sets the C library <tt class="literal">FILE *</tt> to be used for
displaying error messages issued by the DB library.
</p>
</li>
<li>
<p>
<tt class="methodname">set_errpfx()</tt>
</p>
<p>
Sets the prefix used for any error messages issued by the
DB library.
</p>
</li>
<li>
<p>
<tt class="methodname">err()</tt>
</p>
<p>
Issues an error message. The error message is sent to the
callback function as defined by <tt class="methodname">set_errcall</tt>.
If that method has not been used, then the error message is sent to the
file defined by
<span><tt class="methodname">set_errfile()</tt>.</span>
If none of these methods have been used, then the error message is sent to
standard error.
</p>
<p>
The error message consists of the prefix string
(as defined by <tt class="methodname">set_errpfx()</tt>),
an optional <tt class="literal">printf</tt>-style formatted message,
the error message, and a trailing newline.
</p>
</li>
<li>
<p>
<tt class="methodname">errx()</tt>
</p>
<p>
Behaves identically to <tt class="methodname">err()</tt> except
that the DB message text associated with the supplied error
value is not appended to the error string.
</p>
</li>
</ul>
</div>
<p>
In addition, you can use the <tt class="methodname">db_strerror()</tt>
function to directly return the error string that corresponds to a
particular error number.
</p>
<p>
For example, to send all error messages for a given database handle
to a callback for handling, first create your callback. Do something like this:
</p>
<a id="c_db8"></a>
<pre class="programlisting">/*
* Function called to handle any database error messages
* issued by DB.
*/
void
my_error_handler(const char *error_prefix, char *msg)
{
/*
* Put your code to handle the error prefix and error
* message here. Note that one or both of these parameters
* may be NULL depending on how the error message is issued
* and how the DB handle is configured.
*/
} </pre>
<p>
And then register the callback as follows:
</p>
<a id="c_db9"></a>
<pre class="programlisting">#include &lt;db.h&gt;
#include &lt;stdio.h&gt;
...
DB *dbp;
int ret;
/*
* Create a database and initialize it for error
* reporting.
*/
ret = db_create(&amp;dbp, NULL, 0);
if (ret != 0) {
fprintf(stderr, "%s: %s\n", "my_program",
db_strerror(ret));
return(ret);
}
/* Set up error handling for this database */
dbp-&gt;set_errcall(dbp, my_error_handler);
dbp-&gt;set_errpfx(dbp, "my_example_program"); </pre>
<p>
And to issue an error message:
</p>
<a id="c_db10"></a>
<pre class="programlisting">ret = dbp-&gt;open(dbp,
NULL,
"mydb.db",
NULL,
DB_BTREE,
DB_CREATE,
0);
if (ret != 0) {
dbp-&gt;err(dbp, ret,
"Database open failed: %s", "mydb.db");
return(ret);
}</pre>
<span>
</span>
</div>
<div class="navfooter">
<hr />
<table width="100%" summary="Navigation footer">
<tr>
<td width="40%" align="left"><a accesskey="p" href="CoreDBAdmin.html">Prev</a> </td>
<td width="20%" align="center">
<a accesskey="u" href="DB.html">Up</a>
</td>
<td width="40%" align="right"> <a accesskey="n" href="CoreEnvUsage.html">Next</a></td>
</tr>
<tr>
<td width="40%" align="left" valign="top">Administrative Methods </td>
<td width="20%" align="center">
<a accesskey="h" href="index.html">Home</a>
</td>
<td width="40%" align="right" valign="top"> Managing Databases in Environments</td>
</tr>
</table>
</div>
</body>
</html>

400
docs/gsg/C/dbconfig.html Normal file
View File

@@ -0,0 +1,400 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>Chapter 6. Database Configuration</title>
<link rel="stylesheet" href="gettingStarted.css" type="text/css" />
<meta name="generator" content="DocBook XSL Stylesheets V1.62.4" />
<link rel="home" href="index.html" title="Getting Started with Berkeley DB" />
<link rel="up" href="index.html" title="Getting Started with Berkeley DB" />
<link rel="previous" href="coreindexusage.html" title="Secondary Database Example" />
<link rel="next" href="cachesize.html" title="Selecting the Cache Size" />
</head>
<body>
<div class="navheader">
<table width="100%" summary="Navigation header">
<tr>
<th colspan="3" align="center">Chapter 6. Database Configuration</th>
</tr>
<tr>
<td width="20%" align="left"><a accesskey="p" href="coreindexusage.html">Prev</a> </td>
<th width="60%" align="center"> </th>
<td width="20%" align="right"> <a accesskey="n" href="cachesize.html">Next</a></td>
</tr>
</table>
<hr />
</div>
<div class="chapter" lang="en" xml:lang="en">
<div class="titlepage">
<div>
<div>
<h2 class="title"><a id="dbconfig"></a>Chapter 6. Database Configuration</h2>
</div>
</div>
<div></div>
</div>
<div class="toc">
<p>
<b>Table of Contents</b>
</p>
<dl>
<dt>
<span class="sect1">
<a href="dbconfig.html#pagesize">Setting the Page Size</a>
</span>
</dt>
<dd>
<dl>
<dt>
<span class="sect2">
<a href="dbconfig.html#overflowpages">Overflow Pages</a>
</span>
</dt>
<dt>
<span class="sect2">
<a href="dbconfig.html#Locking">Locking</a>
</span>
</dt>
<dt>
<span class="sect2">
<a href="dbconfig.html#IOEfficiency">IO Efficiency</a>
</span>
</dt>
<dt>
<span class="sect2">
<a href="dbconfig.html#pagesizeAdvice">Page Sizing Advice</a>
</span>
</dt>
</dl>
</dd>
<dt>
<span class="sect1">
<a href="cachesize.html">Selecting the Cache Size</a>
</span>
</dt>
<dt>
<span class="sect1">
<a href="btree.html">BTree Configuration</a>
</span>
</dt>
<dd>
<dl>
<dt>
<span class="sect2">
<a href="btree.html#duplicateRecords">Allowing Duplicate Records</a>
</span>
</dt>
<dt>
<span class="sect2">
<a href="btree.html#comparators">Setting Comparison Functions</a>
</span>
</dt>
</dl>
</dd>
</dl>
</div>
<p>
This chapter describes some of the database and cache configuration issues
that you need to consider when building your DB database.
In most cases, there is very little that you need to do in terms of
managing your databases. However, there are configuration issues that you
need to be concerned with, and these are largely dependent on the access
method that you are choosing for your database.
</p>
<p>
The examples and descriptions throughout this document have mostly focused
on the BTree access method. This is because the majority of DB
applications use BTree. For this reason, where configuration issues are
dependent on the type of access method in use, this chapter will focus on
BTree only. For configuration descriptions surrounding the other access
methods, see the <i class="citetitle">Berkeley DB Programmer's Reference Guide</i>.
</p>
<div class="sect1" lang="en" xml:lang="en">
<div class="titlepage">
<div>
<div>
<h2 class="title" style="clear: both"><a id="pagesize"></a>Setting the Page Size</h2>
</div>
</div>
<div></div>
</div>
<p>
Internally, DB stores database entries on pages. Page sizes are
important because they can affect your application's performance.
</p>
<p>
DB pages can be between 512 bytes and 64K bytes in size. The size
that you select must be a power of 2. You set your database's
page size using
<span><tt class="methodname">DB-&gt;set_pagesize()</tt>.</span>
</p>
<p>
Note that a database's page size can only be selected at database
creation time.
</p>
<p>
When selecting a page size, you should consider the following issues:
</p>
<div class="itemizedlist">
<ul type="disc">
<li>
<p>
Overflow pages.
</p>
</li>
<li>
<p>
Locking
</p>
</li>
<li>
<p>
Disk I/O.
</p>
</li>
</ul>
</div>
<p>
These topics are discussed next.
</p>
<div class="sect2" lang="en" xml:lang="en">
<div class="titlepage">
<div>
<div>
<h3 class="title"><a id="overflowpages"></a>Overflow Pages</h3>
</div>
</div>
<div></div>
</div>
<p>
Overflow pages are used to hold a key or data item
that cannot fit on a single page. You do not have to do anything to
cause overflow pages to be created, other than to store data that is
too large for your database's page size. Also, the only way you can
prevent overflow pages from being created is to be sure to select a
page size that is large enough to hold your database entries.
</p>
<p>
Because overflow pages exist outside of the normal database
structure, their use is expensive from a performance
perspective. If you select too small of a page size, then your
database will be forced to use an excessive number of overflow
pages. This will significantly harm your application's performance.
</p>
<p>
For this reason, you want to select a page size that is at
least large enough to hold multiple entries given the expected
average size of your database entries. In BTree's case, for best
results select a page size that can hold at least 4 such entries.
</p>
<p>
You can see how many overflow pages your database is using by
<span>
using the
<tt class="methodname">DB-&gt;stat()</tt>
method,
</span>
or by examining your database using the
<tt class="literal">db_stat</tt> command line utility.
</p>
</div>
<div class="sect2" lang="en" xml:lang="en">
<div class="titlepage">
<div>
<div>
<h3 class="title"><a id="Locking"></a>Locking</h3>
</div>
</div>
<div></div>
</div>
<p>
Locking and multi-threaded access to DB databases is built into
the product. However, in order to enable the locking subsystem and
in order to provide efficient sharing of the cache between
databases, you must use an <span class="emphasis"><em>environment</em></span>.
Environments and multi-threaded access are not fully described
in this manual (see the Berkeley DB Programmer's Reference Manual for
information), however, we provide some information on sizing your
pages in a multi-threaded/multi-process environment in the interest
of providing a complete discussion on the topic.
</p>
<p>
If your application is multi-threaded, or if your databases are
accessed by more than one process at a time, then page size can
influence your application's performance. The reason why is that
for most access methods (Queue is the exception), DB implements
page-level locking. This means that the finest locking granularity
is at the page, not at the record.
</p>
<p>
In most cases, database pages contain multiple database
records. Further, in order to provide safe access to multiple
threads or processes, DB performs locking on pages as entries on
those pages are read or written.
</p>
<p>
As the size of your page increases relative to the size of your
database entries, the number of entries that are held on any given
page also increase. The result is that the chances of two or more
readers and/or writers wanting to access entries on any given page
also increases.
</p>
<p>
When two or more threads and/or processes want to manage data on a
page, lock contention occurs. Lock contention is resolved by one
thread (or process) waiting for another thread to give up its lock.
It is this waiting activity that is harmful to your application's
performance.
</p>
<p>
It is possible to select a page size that is so large that your
application will spend excessive, and noticeable, amounts of time
resolving lock contention. Note that this scenario is particularly
likely to occur as the amount of concurrency built into your
application increases.
</p>
<p>
Oh the other hand, if you select too small of a page size, then that
that will only make your tree deeper, which can also cause
performance penalties. The trick, therefore, is to select a
reasonable page size (one that will hold a sizeable number of
records) and then reduce the page size if you notice lock
contention.
</p>
<p>
You can examine the number of lock conflicts and deadlocks occurring
in your application by examining your database environment lock
statistics. Either use the
<tt class="methodname">DB_ENV-&gt;lock_stat()</tt>
method, or use the <tt class="literal">db_stat</tt> command line utility.
The number of unavailable locks that your application waited for is
held in the lock statistic's <tt class="literal">st_lock_wait</tt> field.
</p>
</div>
<div class="sect2" lang="en" xml:lang="en">
<div class="titlepage">
<div>
<div>
<h3 class="title"><a id="IOEfficiency"></a>IO Efficiency</h3>
</div>
</div>
<div></div>
</div>
<p>
Page size can affect how efficient DB is at moving data to and
from disk. For some applications, especially those for which the
in-memory cache can not be large enough to hold the entire working
dataset, IO efficiency can significantly impact application performance.
</p>
<p>
Most operating systems use an internal block size to determine how much
data to move to and from disk for a single I/O operation. This block
size is usually equal to the filesystem's block size. For optimal
disk I/O efficiency, you should select a database page size that is
equal to the operating system's I/O block size.
</p>
<p>
Essentially, DB performs data transfers based on the database
page size. That is, it moves data to and from disk a page at a time.
For this reason, if the page size does not match the I/O block size,
then the operating system can introduce inefficiencies in how it
responds to DB's I/O requests.
</p>
<p>
For example, suppose your page size is smaller than your operating
system block size. In this case, when DB writes a page to disk
it is writing just a portion of a logical filesystem page. Any time
any application writes just a portion of a logical filesystem page, the
operating system brings in the real filesystem page, over writes
the portion of the page not written by the application, then writes
the filesystem page back to disk. The net result is significantly
more disk I/O than if the application had simply selected a page
size that was equal to the underlying filesystem block size.
</p>
<p>
Alternatively, if you select a page size that is larger than the
underlying filesystem block size, then the operating system may have
to read more data than is necessary to fulfill a read request.
Further, on some operating systems, requesting a single database
page may result in the operating system reading enough filesystem
blocks to satisfy the operating system's criteria for read-ahead. In
this case, the operating system will be reading significantly more
data from disk than is actually required to fulfill DB's read
request.
</p>
<div class="note" style="margin-left: 0.5in; margin-right: 0.5in;">
<h3 class="title">Note</h3>
<p>
While transactions are not discussed in this manual, a page size
other than your filesystem's block size can affect transactional
guarantees. The reason why is that page sizes larger than the
filesystem's block size causes DB to write pages in block
size increments. As a result, it is possible for a partial page
to be written as the result of a transactional commit. For more
information, see <a href="http://www.oracle.com/technology/documentation/berkeley-db/db/ref/transapp/reclimit.html" target="_top">http://www.oracle.com/technology/documentation/berkeley-db/db/ref/transapp/reclimit.html</a>.
</p>
</div>
</div>
<div class="sect2" lang="en" xml:lang="en">
<div class="titlepage">
<div>
<div>
<h3 class="title"><a id="pagesizeAdvice"></a>Page Sizing Advice</h3>
</div>
</div>
<div></div>
</div>
<p>
Page sizing can be confusing at first, so here are some general
guidelines that you can use to select your page size.
</p>
<p>
In general, and given no other considerations, a page size that is equal
to your filesystem block size is the ideal situation.
</p>
<p>
If your data is designed such that 4 database entries cannot fit on a
single page (assuming BTree), then grow your page size to accommodate
your data. Once you've abandoned matching your filesystem's block
size, the general rule is that larger page sizes are better.
</p>
<p>
The exception to this rule is if you have a great deal of
concurrency occurring in your application. In this case, the closer
you can match your page size to the ideal size needed for your
application's data, the better. Doing so will allow you to avoid
unnecessary contention for page locks.
</p>
</div>
</div>
</div>
<div class="navfooter">
<hr />
<table width="100%" summary="Navigation footer">
<tr>
<td width="40%" align="left"><a accesskey="p" href="coreindexusage.html">Prev</a> </td>
<td width="20%" align="center">
<a accesskey="u" href="index.html">Up</a>
</td>
<td width="40%" align="right"> <a accesskey="n" href="cachesize.html">Next</a></td>
</tr>
<tr>
<td width="40%" align="left" valign="top">Secondary Database Example </td>
<td width="20%" align="center">
<a accesskey="h" href="index.html">Home</a>
</td>
<td width="40%" align="right" valign="top"> Selecting the Cache Size</td>
</tr>
</table>
</div>
</body>
</html>

View File

@@ -0,0 +1,133 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>Environments</title>
<link rel="stylesheet" href="gettingStarted.css" type="text/css" />
<meta name="generator" content="DocBook XSL Stylesheets V1.62.4" />
<link rel="home" href="index.html" title="Getting Started with Berkeley DB" />
<link rel="up" href="introduction.html" title="Chapter 1. Introduction to Berkeley DB " />
<link rel="previous" href="databaseLimits.html" title="Database Limits and Portability" />
<link rel="next" href="returns.html" title="Error Returns" />
</head>
<body>
<div class="navheader">
<table width="100%" summary="Navigation header">
<tr>
<th colspan="3" align="center">Environments</th>
</tr>
<tr>
<td width="20%" align="left"><a accesskey="p" href="databaseLimits.html">Prev</a> </td>
<th width="60%" align="center">Chapter 1. Introduction to Berkeley DB </th>
<td width="20%" align="right"> <a accesskey="n" href="returns.html">Next</a></td>
</tr>
</table>
<hr />
</div>
<div class="sect1" lang="en" xml:lang="en">
<div class="titlepage">
<div>
<div>
<h2 class="title" style="clear: both"><a id="environments"></a>Environments</h2>
</div>
</div>
<div></div>
</div>
<p>
This manual is meant as an introduction to the Berkeley DB library.
Consequently, it describes how to build a very simple, single-threaded
application and so this manual omits a great many powerful
aspects of the DB database engine that are not required by simple
applications. One of these is important enough that it warrants a brief
overview here: environments.
</p>
<p>
While environments are frequently not used by applications running in
embedded environments where every byte counts, they will be used by
virtually any other DB application requiring anything other than
the bare minimum functionality.
</p>
<span>
<p>
An <span class="emphasis"><em>environment</em></span> is
essentially an encapsulation of one or more databases. You
open an environment and then you open databases in that environment.
When you do so, the databases are created/located in a location relative
to the environment's home directory.
</p>
<p>
Environments offer a great many features that a stand-alone DB
database cannot offer:
</p>
<div class="itemizedlist"><ul type="disc"><li><p>
Multi-database files.
</p><p>
It is possible in DB to contain multiple databases in a
single physical file on disk. This is desirable for those
application that open more than a few handful of databases.
However, in order to have more than one database contained in
a single physical file, your application
<span class="emphasis"><em>must</em></span> use an environment.
</p></li><li><p>
Multi-thread and multi-process support
</p><p>
When you use an environment, resources such as the in-memory
cache and locks can be shared by all of the databases opened in the
environment. The environment allows you to enable
subsystems that are designed to allow multiple threads and/or
processes to access DB databases. For example, you use an
environment to enable the concurrent data store (CDS), the
locking subsystem, and/or the shared memory buffer pool.
</p></li><li><p>
Transactional processing
</p><p>
DB offers a transactional subsystem that allows for full
ACID-protection of your database writes. You use environments to
enable the transactional subsystem, and then subsequently to obtain
transaction IDs.
</p></li><li><p>
High availability (replication) support
</p><p>
DB offers a replication subsystem that enables
single-master database replication with multiple read-only
copies of the replicated data. You use environments to enable
and then manage this subsystem.
</p></li><li><p>
Logging subsystem
</p><p>
DB offers write-ahead logging for applications that want to
obtain a high-degree of recoverability in the face of an
application or system crash. Once enabled, the logging subsystem
allows the application to perform two kinds of recovery
("normal" and "catastrophic") through the use of the information
contained in the log files.
</p></li></ul></div>
<p>
For more information on these topics, see the
<i class="citetitle">Berkeley DB Getting Started with Transaction Processing</i> guide and the
<i class="citetitle">Berkeley DB Getting Started with Replicated Applications</i> guide.
</p>
</span>
</div>
<div class="navfooter">
<hr />
<table width="100%" summary="Navigation footer">
<tr>
<td width="40%" align="left"><a accesskey="p" href="databaseLimits.html">Prev</a> </td>
<td width="20%" align="center">
<a accesskey="u" href="introduction.html">Up</a>
</td>
<td width="40%" align="right"> <a accesskey="n" href="returns.html">Next</a></td>
</tr>
<tr>
<td width="40%" align="left" valign="top">Database Limits and Portability </td>
<td width="20%" align="center">
<a accesskey="h" href="index.html">Home</a>
</td>
<td width="40%" align="right" valign="top"> Error Returns</td>
</tr>
</table>
</div>
</body>
</html>

View File

@@ -0,0 +1,41 @@
body { width: 45em;
margin-left: 3em;
font-family: Arial, Helvetica, sans-serif;
font-size: 11pt;
}
h2.title { margin-left: -1em;
font-family: Verdana, serif;
font-size: 16pt;
}
h3.title { font-family: Verdana, serif;
font-size: 14pt;
}
pre.programlisting {
font-family: monospace;
background-color: #eae8e9;
}
div.navheader { font-size: 9pt;
width: 60em;
margin-left: -2em;
}
div.navheader table tr td { font-size: 9pt; }
div.navfooter { font-size: 9pt;
width: 60em;
margin-left: -2em;
}
div.navfooter table tr td { font-size: 9pt; }
span.emphasis { font-style: italic; font-size: 9pt;}
div.appendix div.informaltable { font-size: 9pt; }
div.appendix div.informaltable td { vertical-align: top; }
div.appendix div.informaltable p { margin-top: .25em; }
div.appendix div.informaltable p { margin-bottom: .25em; }

77
docs/gsg/C/gettingit.html Normal file
View File

@@ -0,0 +1,77 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>Getting and Using DB </title>
<link rel="stylesheet" href="gettingStarted.css" type="text/css" />
<meta name="generator" content="DocBook XSL Stylesheets V1.62.4" />
<link rel="home" href="index.html" title="Getting Started with Berkeley DB" />
<link rel="up" href="introduction.html" title="Chapter 1. Introduction to Berkeley DB " />
<link rel="previous" href="returns.html" title="Error Returns" />
<link rel="next" href="DB.html" title="Chapter 2. Databases" />
</head>
<body>
<div class="navheader">
<table width="100%" summary="Navigation header">
<tr>
<th colspan="3" align="center">Getting and Using DB </th>
</tr>
<tr>
<td width="20%" align="left"><a accesskey="p" href="returns.html">Prev</a> </td>
<th width="60%" align="center">Chapter 1. Introduction to Berkeley DB </th>
<td width="20%" align="right"> <a accesskey="n" href="DB.html">Next</a></td>
</tr>
</table>
<hr />
</div>
<div class="sect1" lang="en" xml:lang="en">
<div class="titlepage">
<div>
<div>
<h2 class="title" style="clear: both"><a id="gettingit"></a>Getting and Using DB </h2>
</div>
</div>
<div></div>
</div>
<p>
You can obtain DB by visiting the Berkeley DB download page:
<a href="http://www.oracle.com/technology/software/products/berkeley-db/db/index.html" target="_top">http://www.oracle.com/technology/software/products/berkeley-db/db/index.html</a>.
</p>
<p>
To install DB, untar or unzip the distribution to the directory of
your choice. You will then need to build the product binaries.
For information on building DB, see
<span class="emphasis"><em>DB_INSTALL</em></span><tt class="literal">/docs/index.html</tt>,
where <span class="emphasis"><em>DB_INSTALL</em></span> is the directory where you unpacked
DB. On that page, you will find links to platform-specific build
instructions.
</p>
<p>
That page also contains links to more documentation for DB. In
particular, you will find links for the
<i class="citetitle">Berkeley DB Programmer's Reference Guide</i>
as well as the API reference documentation.
</p>
</div>
<div class="navfooter">
<hr />
<table width="100%" summary="Navigation footer">
<tr>
<td width="40%" align="left"><a accesskey="p" href="returns.html">Prev</a> </td>
<td width="20%" align="center">
<a accesskey="u" href="introduction.html">Up</a>
</td>
<td width="40%" align="right"> <a accesskey="n" href="DB.html">Next</a></td>
</tr>
<tr>
<td width="40%" align="left" valign="top">Error Returns </td>
<td width="20%" align="center">
<a accesskey="h" href="index.html">Home</a>
</td>
<td width="40%" align="right" valign="top"> Chapter 2. Databases</td>
</tr>
</table>
</div>
</body>
</html>

498
docs/gsg/C/index.html Normal file
View File

@@ -0,0 +1,498 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>Getting Started with Berkeley DB</title>
<link rel="stylesheet" href="gettingStarted.css" type="text/css" />
<meta name="generator" content="DocBook XSL Stylesheets V1.62.4" />
<link rel="home" href="index.html" title="Getting Started with Berkeley DB" />
<link rel="next" href="preface.html" title="Preface" />
</head>
<body>
<div class="navheader">
<table width="100%" summary="Navigation header">
<tr>
<th colspan="3" align="center">Getting Started with Berkeley DB</th>
</tr>
<tr>
<td width="20%" align="left"> </td>
<th width="60%" align="center"> </th>
<td width="20%" align="right"> <a accesskey="n" href="preface.html">Next</a></td>
</tr>
</table>
<hr />
</div>
<div class="book" lang="en" xml:lang="en">
<div class="titlepage">
<div>
<div>
<h1 class="title"><a id="id613728"></a>Getting Started with Berkeley DB</h1>
</div>
<div>
<div class="legalnotice">
<p class="legalnotice-title">
<b>Legal Notice</b>
</p>
<p>
This documentation is distributed under an open source license.
You may review the terms of this license at:
<a href="http://www.oracle.com/technology/software/products/berkeley-db/htdocs/oslicense.html" target="_top">http://www.oracle.com/technology/software/products/berkeley-db/htdocs/oslicense.html</a>
</p>
<p>
Oracle, Berkeley DB,
and
Sleepycat are trademarks or registered trademarks of
Oracle. All rights to these marks are reserved.
No third-party use is permitted without the
express prior written consent of Oracle.
</p>
<p>
To obtain a copy of this document's original source code, please
submit a request to the Oracle Technology Network forum at:
<a href="http://forums.oracle.com/forums/forum.jspa?forumID=271" target="_top">http://forums.oracle.com/forums/forum.jspa?forumID=271</a>
</p>
</div>
</div>
<div>
<p class="pubdate">4/25/2008</p>
</div>
</div>
<div></div>
<hr />
</div>
<div class="toc">
<p>
<b>Table of Contents</b>
</p>
<dl>
<dt>
<span class="preface">
<a href="preface.html">Preface</a>
</span>
</dt>
<dd>
<dl>
<dt>
<span class="sect1">
<a href="preface.html#conventions">Conventions Used in this Book</a>
</span>
</dt>
<dd>
<dl>
<dt>
<span class="sect2">
<a href="preface.html#moreinfo">For More Information</a>
</span>
</dt>
</dl>
</dd>
</dl>
</dd>
<dt>
<span class="chapter">
<a href="introduction.html">1. Introduction to Berkeley DB </a>
</span>
</dt>
<dd>
<dl>
<dt>
<span class="sect1">
<a href="introduction.html#aboutthismanual">About This Manual</a>
</span>
</dt>
<dt>
<span class="sect1">
<a href="concepts.html">Berkeley DB Concepts</a>
</span>
</dt>
<dt>
<span class="sect1">
<a href="accessmethods.html">Access Methods</a>
</span>
</dt>
<dd>
<dl>
<dt>
<span class="sect2">
<a href="accessmethods.html#selectAM">Selecting Access Methods</a>
</span>
</dt>
<dt>
<span class="sect2">
<a href="accessmethods.html#BTreeVSHash">Choosing between BTree and Hash</a>
</span>
</dt>
<dt>
<span class="sect2">
<a href="accessmethods.html#QueueVSRecno">Choosing between Queue and Recno</a>
</span>
</dt>
</dl>
</dd>
<dt>
<span class="sect1">
<a href="databaseLimits.html">Database Limits and Portability</a>
</span>
</dt>
<dt>
<span class="sect1">
<a href="environments.html">Environments</a>
</span>
</dt>
<dt>
<span class="sect1">
<a href="returns.html">Error Returns</a>
</span>
</dt>
<dt>
<span class="sect1">
<a href="gettingit.html">Getting and Using DB </a>
</span>
</dt>
</dl>
</dd>
<dt>
<span class="chapter">
<a href="DB.html">2. Databases</a>
</span>
</dt>
<dd>
<dl>
<dt>
<span class="sect1">
<a href="DB.html#DBOpen">Opening Databases</a>
</span>
</dt>
<dt>
<span class="sect1">
<a href="coredbclose.html">Closing Databases</a>
</span>
</dt>
<dt>
<span class="sect1">
<a href="DBOpenFlags.html">Database Open Flags</a>
</span>
</dt>
<dt>
<span class="sect1">
<a href="CoreDBAdmin.html">Administrative Methods</a>
</span>
</dt>
<dt>
<span class="sect1">
<a href="dbErrorReporting.html">Error Reporting Functions</a>
</span>
</dt>
<dt>
<span class="sect1">
<a href="CoreEnvUsage.html">Managing Databases in Environments</a>
</span>
</dt>
<dt>
<span class="sect1">
<a href="CoreDbUsage.html">Database Example</a>
</span>
</dt>
</dl>
</dd>
<dt>
<span class="chapter">
<a href="DBEntry.html">3. Database Records</a>
</span>
</dt>
<dd>
<dl>
<dt>
<span class="sect1">
<a href="DBEntry.html#usingDbEntry">Using Database Records</a>
</span>
</dt>
<dt>
<span class="sect1">
<a href="usingDbt.html">Reading and Writing Database Records</a>
</span>
</dt>
<dd>
<dl>
<dt>
<span class="sect2">
<a href="usingDbt.html#databaseWrite">Writing Records to the Database</a>
</span>
</dt>
<dt>
<span class="sect2">
<a href="usingDbt.html#CoreDatabaseRead">Getting Records from the Database</a>
</span>
</dt>
<dt>
<span class="sect2">
<a href="usingDbt.html#recordDelete">Deleting Records</a>
</span>
</dt>
<dt>
<span class="sect2">
<a href="usingDbt.html#datapersist">Data Persistence</a>
</span>
</dt>
</dl>
</dd>
<dt>
<span class="sect1">
<a href="cstructs.html">Using C Structures with DB</a>
</span>
</dt>
<dd>
<dl>
<dt>
<span class="sect2">
<a href="cstructs.html#cstructdynamic">C Structures with Pointers</a>
</span>
</dt>
</dl>
</dd>
<dt>
<span class="sect1">
<a href="DbUsage.html">Database Usage Example</a>
</span>
</dt>
</dl>
</dd>
<dt>
<span class="chapter">
<a href="Cursors.html">4. Using Cursors</a>
</span>
</dt>
<dd>
<dl>
<dt>
<span class="sect1">
<a href="Cursors.html#openCursor">Opening and Closing Cursors</a>
</span>
</dt>
<dt>
<span class="sect1">
<a href="Positioning.html">Getting Records Using the Cursor</a>
</span>
</dt>
<dd>
<dl>
<dt>
<span class="sect2">
<a href="Positioning.html#cursorsearch">Searching for Records</a>
</span>
</dt>
<dt>
<span class="sect2">
<a href="Positioning.html#getdups">Working with Duplicate Records</a>
</span>
</dt>
</dl>
</dd>
<dt>
<span class="sect1">
<a href="PutEntryWCursor.html">Putting Records Using Cursors</a>
</span>
</dt>
<dt>
<span class="sect1">
<a href="DeleteEntryWCursor.html">Deleting Records Using Cursors</a>
</span>
</dt>
<dt>
<span class="sect1">
<a href="ReplacingEntryWCursor.html">Replacing Records Using Cursors</a>
</span>
</dt>
<dt>
<span class="sect1">
<a href="CoreCursorUsage.html">Cursor Example</a>
</span>
</dt>
</dl>
</dd>
<dt>
<span class="chapter">
<a href="indexes.html">5. Secondary Databases</a>
</span>
</dt>
<dd>
<dl>
<dt>
<span class="sect1">
<a href="indexes.html#CoreDbAssociate">Opening and Closing Secondary Databases</a>
</span>
</dt>
<dt>
<span class="sect1">
<a href="keyCreator.html">Implementing Key
Extractors
</a>
</span>
</dt>
<dd>
<dl>
<dt>
<span class="sect2">
<a href="keyCreator.html#multikeys">Working with Multiple Keys</a>
</span>
</dt>
</dl>
</dd>
<dt>
<span class="sect1">
<a href="readSecondary.html">Reading Secondary Databases</a>
</span>
</dt>
<dt>
<span class="sect1">
<a href="secondaryDelete.html">Deleting Secondary Database Records</a>
</span>
</dt>
<dt>
<span class="sect1">
<a href="secondaryCursor.html">
Using Cursors with Secondary Databases
</a>
</span>
</dt>
<dt>
<span class="sect1">
<a href="joins.html">Database Joins</a>
</span>
</dt>
<dd>
<dl>
<dt>
<span class="sect2">
<a href="joins.html#joinUsage">Using Join Cursors</a>
</span>
</dt>
</dl>
</dd>
<dt>
<span class="sect1">
<a href="coreindexusage.html">Secondary Database Example</a>
</span>
</dt>
<dd>
<dl>
<dt>
<span class="sect2">
<a href="coreindexusage.html#edlWIndexes">Secondary Databases with example_database_load</a>
</span>
</dt>
<dt>
<span class="sect2">
<a href="coreindexusage.html#edrWIndexes">Secondary Databases with example_database_read</a>
</span>
</dt>
</dl>
</dd>
</dl>
</dd>
<dt>
<span class="chapter">
<a href="dbconfig.html">6. Database Configuration</a>
</span>
</dt>
<dd>
<dl>
<dt>
<span class="sect1">
<a href="dbconfig.html#pagesize">Setting the Page Size</a>
</span>
</dt>
<dd>
<dl>
<dt>
<span class="sect2">
<a href="dbconfig.html#overflowpages">Overflow Pages</a>
</span>
</dt>
<dt>
<span class="sect2">
<a href="dbconfig.html#Locking">Locking</a>
</span>
</dt>
<dt>
<span class="sect2">
<a href="dbconfig.html#IOEfficiency">IO Efficiency</a>
</span>
</dt>
<dt>
<span class="sect2">
<a href="dbconfig.html#pagesizeAdvice">Page Sizing Advice</a>
</span>
</dt>
</dl>
</dd>
<dt>
<span class="sect1">
<a href="cachesize.html">Selecting the Cache Size</a>
</span>
</dt>
<dt>
<span class="sect1">
<a href="btree.html">BTree Configuration</a>
</span>
</dt>
<dd>
<dl>
<dt>
<span class="sect2">
<a href="btree.html#duplicateRecords">Allowing Duplicate Records</a>
</span>
</dt>
<dt>
<span class="sect2">
<a href="btree.html#comparators">Setting Comparison Functions</a>
</span>
</dt>
</dl>
</dd>
</dl>
</dd>
</dl>
</div>
<div class="list-of-examples">
<p>
<b>List of Examples</b>
</p>
<dl>
<dt>2.1. <a href="CoreDbUsage.html#stock-db">The stock_db Structure</a></dt>
<dt>2.2. <a href="CoreDbUsage.html#stock-db-functions">The stock_db Utility Functions</a></dt>
<dt>2.3. <a href="CoreDbUsage.html#open-db">open_database() Function</a></dt>
<dt>2.4. <a href="CoreDbUsage.html#databasesetup">The databases_setup() Function</a></dt>
<dt>2.5. <a href="CoreDbUsage.html#database_close">The databases_close() Function</a></dt>
<dt>3.1. <a href="DbUsage.html#VENDORStruct">VENDOR Structure</a></dt>
<dt>3.2. <a href="DbUsage.html#exampledbload">example_database_load</a></dt>
<dt>4.1. <a href="CoreCursorUsage.html#CoreEIR">example_database_read</a></dt>
</dl>
</div>
</div>
<div class="navfooter">
<hr />
<table width="100%" summary="Navigation footer">
<tr>
<td width="40%" align="left"> </td>
<td width="20%" align="center"> </td>
<td width="40%" align="right"> <a accesskey="n" href="preface.html">Next</a></td>
</tr>
<tr>
<td width="40%" align="left" valign="top"> </td>
<td width="20%" align="center"> </td>
<td width="40%" align="right" valign="top"> Preface</td>
</tr>
</table>
</div>
</body>
</html>

360
docs/gsg/C/indexes.html Normal file
View File

@@ -0,0 +1,360 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>Chapter 5. Secondary Databases</title>
<link rel="stylesheet" href="gettingStarted.css" type="text/css" />
<meta name="generator" content="DocBook XSL Stylesheets V1.62.4" />
<link rel="home" href="index.html" title="Getting Started with Berkeley DB" />
<link rel="up" href="index.html" title="Getting Started with Berkeley DB" />
<link rel="previous" href="CoreCursorUsage.html" title="Cursor Example" />
<link rel="next" href="keyCreator.html" title="Implementing Key &#10; &#10; Extractors&#10; " />
</head>
<body>
<div class="navheader">
<table width="100%" summary="Navigation header">
<tr>
<th colspan="3" align="center">Chapter 5. Secondary Databases</th>
</tr>
<tr>
<td width="20%" align="left"><a accesskey="p" href="CoreCursorUsage.html">Prev</a> </td>
<th width="60%" align="center"> </th>
<td width="20%" align="right"> <a accesskey="n" href="keyCreator.html">Next</a></td>
</tr>
</table>
<hr />
</div>
<div class="chapter" lang="en" xml:lang="en">
<div class="titlepage">
<div>
<div>
<h2 class="title"><a id="indexes"></a>Chapter 5. Secondary Databases</h2>
</div>
</div>
<div></div>
</div>
<div class="toc">
<p>
<b>Table of Contents</b>
</p>
<dl>
<dt>
<span class="sect1">
<a href="indexes.html#CoreDbAssociate">Opening and Closing Secondary Databases</a>
</span>
</dt>
<dt>
<span class="sect1">
<a href="keyCreator.html">Implementing Key
Extractors
</a>
</span>
</dt>
<dd>
<dl>
<dt>
<span class="sect2">
<a href="keyCreator.html#multikeys">Working with Multiple Keys</a>
</span>
</dt>
</dl>
</dd>
<dt>
<span class="sect1">
<a href="readSecondary.html">Reading Secondary Databases</a>
</span>
</dt>
<dt>
<span class="sect1">
<a href="secondaryDelete.html">Deleting Secondary Database Records</a>
</span>
</dt>
<dt>
<span class="sect1">
<a href="secondaryCursor.html">
Using Cursors with Secondary Databases
</a>
</span>
</dt>
<dt>
<span class="sect1">
<a href="joins.html">Database Joins</a>
</span>
</dt>
<dd>
<dl>
<dt>
<span class="sect2">
<a href="joins.html#joinUsage">Using Join Cursors</a>
</span>
</dt>
</dl>
</dd>
<dt>
<span class="sect1">
<a href="coreindexusage.html">Secondary Database Example</a>
</span>
</dt>
<dd>
<dl>
<dt>
<span class="sect2">
<a href="coreindexusage.html#edlWIndexes">Secondary Databases with example_database_load</a>
</span>
</dt>
<dt>
<span class="sect2">
<a href="coreindexusage.html#edrWIndexes">Secondary Databases with example_database_read</a>
</span>
</dt>
</dl>
</dd>
</dl>
</div>
<p>
Usually you find database records by means of the record's key. However,
the key that you use for your record will not always contain the
information required to provide you with rapid access to the data that you
want to retrieve. For example, suppose your
<span>database</span>
contains records related to users. The key might be a string that is some
unique identifier for the person, such as a user ID. Each record's data,
however, would likely contain a complex object containing details about
people such as names, addresses, phone numbers, and so forth.
While your application may frequently want to query a person by user
ID (that is, by the information stored in the key), it may also on occasion
want to locate people by, say, their name.
</p>
<p>
Rather than iterate through all of the records in your database, examining
each in turn for a given person's name, you create indexes based on names
and then just search that index for the name that you want. You can do this
using secondary databases. In DB, the
<span>database</span>
that contains your data is called a
<span class="emphasis"><em>primary database</em></span>. A database that provides an
alternative set of keys to access that data is called a <span class="emphasis"><em>secondary
database</em></span><span>.</span> In a secondary database, the keys are your alternative
(or secondary) index, and the data corresponds to a primary record's key.
</p>
<p>
You create a secondary database by creating the database, opening it, and
then <span class="emphasis"><em>associating</em></span> the database with
the <span class="emphasis"><em>primary</em></span> database (that is, the database for which
you are creating the index). As a part of associating
the secondary database to the primary, you must provide a callback that is
used to create the secondary database keys. Typically this callback creates
a key based on data found in the primary database record's key or data.
</p>
<p>
Once opened, DB manages secondary databases for you. Adding or deleting
records in your primary database causes DB to update the secondary as
necessary. Further, changing a record's data in the primary database may cause
DB to modify a record in the secondary, depending on whether the change
forces a modification of a key in the secondary database.
</p>
<p>
Note that you can not write directly to a secondary database.
<span>Any attempt to write to a secondary database
results in a non-zero status return.</span>
To change the data referenced by a
<span>secondary</span>
record, modify the primary database instead. The exception to this rule is
that delete operations are allowed on the
<span>secondary database.</span>
See <a href="secondaryDelete.html">Deleting Secondary Database Records</a> for more
information.
</p>
<div class="note" style="margin-left: 0.5in; margin-right: 0.5in;">
<h3 class="title">Note</h3>
<p>
Secondary database records are updated/created by DB
only if the
<span>key creator callback function</span>
returns
<span><tt class="literal">0</tt>.</span>
If
<span>a value other than <tt class="literal">0</tt></span>
is returned, then DB will not add the key to the secondary database, and
in the event of a record update it will remove any existing key.
<span>Note that the callback can use either
<tt class="literal">DB_DONOTINDEX</tt> or some error code outside of DB's
name space to indicate that the entry should not be indexed.</span>
</p>
<p>
See <a href="keyCreator.html">Implementing Key
<span>Extractors</span>
</a> for more
<span>information.</span>
</p>
</div>
<p>
When you read a record from a secondary database, DB automatically
returns
<span>the data and optionally the key</span>
from the corresponding record in the primary database.
</p>
<div class="sect1" lang="en" xml:lang="en">
<div class="titlepage">
<div>
<div>
<h2 class="title" style="clear: both"><a id="CoreDbAssociate"></a>Opening and Closing Secondary Databases</h2>
</div>
</div>
<div></div>
</div>
<p>
You manage secondary database opens and closes in the same way as you
would any normal database. The only difference is that:
</p>
<div class="itemizedlist">
<ul type="disc">
<li>
<p>
You must associate the secondary to a primary database using
<span><tt class="methodname">DB-&gt;associate()</tt>.</span>
</p>
</li>
<li>
<p>
When closing your databases, it is a good idea to make sure you
close your secondaries before closing your primaries. This is
particularly true if your database closes are not single
threaded.
</p>
</li>
</ul>
</div>
<p>
When you associate a secondary to a primary database, you must provide a
callback that is used to generate the secondary's keys. These
callbacks are described in the next section.
</p>
<p>
For example, to open a secondary database and associate it to a primary
database:
</p>
<a id="c_index1"></a>
<pre class="programlisting">#include &lt;db.h&gt;
...
DB *dbp, *sdbp; /* Primary and secondary DB handles */
u_int32_t flags; /* Primary database open flags */
int ret; /* Function return value */
/* Primary */
ret = db_create(&amp;dbp, NULL, 0);
if (ret != 0) {
/* Error handling goes here */
}
/* Secondary */
ret = db_create(&amp;sdbp, NULL, 0);
if (ret != 0) {
/* Error handling goes here */
}
/* Usually we want to support duplicates for secondary databases */
ret = sdbp-&gt;set_flags(sdbp, DB_DUPSORT);
if (ret != 0) {
/* Error handling goes here */
}
/* Database open flags */
flags = DB_CREATE; /* If the database does not exist,
* create it.*/
/* open the primary database */
ret = dbp-&gt;open(dbp, /* DB structure pointer */
NULL, /* Transaction pointer */
"my_db.db", /* On-disk file that holds the database. */
NULL, /* Optional logical database name */
DB_BTREE, /* Database access method */
flags, /* Open flags */
0); /* File mode (using defaults) */
if (ret != 0) {
/* Error handling goes here */
}
/* open the secondary database */
ret = sdbp-&gt;open(sdbp, /* DB structure pointer */
NULL, /* Transaction pointer */
"my_secdb.db", /* On-disk file that holds the database. */
NULL, /* Optional logical database name */
DB_BTREE, /* Database access method */
flags, /* Open flags */
0); /* File mode (using defaults) */
if (ret != 0) {
/* Error handling goes here */
}
/* Now associate the secondary to the primary */
dbp-&gt;associate(dbp, /* Primary database */
NULL, /* TXN id */
sdbp, /* Secondary database */
get_sales_rep, /* Callback used for key creation. Not
* defined in this example. See the next
* section. */
0); /* Flags */</pre>
<p>
Closing the primary and secondary databases is accomplished exactly as you
would for any database:
</p>
<a id="c_index2"></a>
<pre class="programlisting">/* Close the secondary before the primary */
if (sdbp != NULL)
sdbp-&gt;close(sdbp, 0);
if (dbp != NULL)
dbp-&gt;close(dbp, 0); </pre>
</div>
</div>
<div class="navfooter">
<hr />
<table width="100%" summary="Navigation footer">
<tr>
<td width="40%" align="left"><a accesskey="p" href="CoreCursorUsage.html">Prev</a> </td>
<td width="20%" align="center">
<a accesskey="u" href="index.html">Up</a>
</td>
<td width="40%" align="right"> <a accesskey="n" href="keyCreator.html">Next</a></td>
</tr>
<tr>
<td width="40%" align="left" valign="top">Cursor Example </td>
<td width="20%" align="center">
<a accesskey="h" href="index.html">Home</a>
</td>
<td width="40%" align="right" valign="top"> Implementing Key
Extractors
</td>
</tr>
</table>
</div>
</body>
</html>

View File

@@ -0,0 +1,238 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>Chapter 1. Introduction to Berkeley DB </title>
<link rel="stylesheet" href="gettingStarted.css" type="text/css" />
<meta name="generator" content="DocBook XSL Stylesheets V1.62.4" />
<link rel="home" href="index.html" title="Getting Started with Berkeley DB" />
<link rel="up" href="index.html" title="Getting Started with Berkeley DB" />
<link rel="previous" href="preface.html" title="Preface" />
<link rel="next" href="concepts.html" title="Berkeley DB Concepts" />
</head>
<body>
<div class="navheader">
<table width="100%" summary="Navigation header">
<tr>
<th colspan="3" align="center">Chapter 1. Introduction to Berkeley DB </th>
</tr>
<tr>
<td width="20%" align="left"><a accesskey="p" href="preface.html">Prev</a> </td>
<th width="60%" align="center"> </th>
<td width="20%" align="right"> <a accesskey="n" href="concepts.html">Next</a></td>
</tr>
</table>
<hr />
</div>
<div class="chapter" lang="en" xml:lang="en">
<div class="titlepage">
<div>
<div>
<h2 class="title"><a id="introduction"></a>Chapter 1. Introduction to Berkeley DB </h2>
</div>
</div>
<div></div>
</div>
<div class="toc">
<p>
<b>Table of Contents</b>
</p>
<dl>
<dt>
<span class="sect1">
<a href="introduction.html#aboutthismanual">About This Manual</a>
</span>
</dt>
<dt>
<span class="sect1">
<a href="concepts.html">Berkeley DB Concepts</a>
</span>
</dt>
<dt>
<span class="sect1">
<a href="accessmethods.html">Access Methods</a>
</span>
</dt>
<dd>
<dl>
<dt>
<span class="sect2">
<a href="accessmethods.html#selectAM">Selecting Access Methods</a>
</span>
</dt>
<dt>
<span class="sect2">
<a href="accessmethods.html#BTreeVSHash">Choosing between BTree and Hash</a>
</span>
</dt>
<dt>
<span class="sect2">
<a href="accessmethods.html#QueueVSRecno">Choosing between Queue and Recno</a>
</span>
</dt>
</dl>
</dd>
<dt>
<span class="sect1">
<a href="databaseLimits.html">Database Limits and Portability</a>
</span>
</dt>
<dt>
<span class="sect1">
<a href="environments.html">Environments</a>
</span>
</dt>
<dt>
<span class="sect1">
<a href="returns.html">Error Returns</a>
</span>
</dt>
<dt>
<span class="sect1">
<a href="gettingit.html">Getting and Using DB </a>
</span>
</dt>
</dl>
</div>
<p>
Welcome to Berkeley DB (DB). DB is a general-purpose embedded
database engine that is capable of providing a wealth of data management services.
It is designed from the ground up for high-throughput applications requiring
in-process, bullet-proof management of mission-critical data. DB can
gracefully scale from managing a few bytes to terabytes of data. For the most
part, DB is limited only by your system's available physical resources.
</p>
<p>
You use DB through a series of Java APIs which give you the
ability to read and write your data, manage your database(s), and
perform other more advanced activities such as managing
transactions.
</p>
<p>
Because DB is an embedded database engine, it is extremely fast. You compile
and link it into your application in the same way as you would any
third-party library. This means that DB runs in the same process space
as does your application, allowing you to avoid the high cost of
interprocess communications incurred by stand-alone database servers.
</p>
<p>
To further improve performance, DB offers an in-memory cache designed to
provide rapid access to your most frequently used data. Once configured,
cache usage is transparent. It requires very little attention on the part
of the application developer.
</p>
<p>
Beyond raw speed, DB is also extremely configurable. It provides several
different ways of organizing your data in its databases. Known as
<span class="emphasis"><em>access methods</em></span>, each such data organization mechanism
provides different characteristics that are appropriate for different data
management profiles. (Note that this manual focuses almost entirely on the
BTree access method as this is the access method used by the vast majority
of DB applications).
</p>
<p>
To further improve its configurability, DB offers many different
subsystems, each of which can be used to extend DB's capabilities. For
example, many applications require write-protection of their data so
as to ensure that data is never left in an inconsistent state for any
reason (such as software bugs or hardware failures). For those
applications, a transaction subsystem can be enabled and used to
transactional-protect database writes.
</p>
<p>
The list of operating systems on which DB is available is too long to
detail here. Suffice to say that it is available on all major commercial
operating systems, as well as on many embedded platforms.
</p>
<p>
Finally, DB is available in a wealth of programming languages.
DB is officially supported in C, C++, and Java, but the library is also
available in many other languages, especially scripting languages such as
Perl and Python.
</p>
<div class="note" style="margin-left: 0.5in; margin-right: 0.5in;">
<h3 class="title">Note</h3>
<p>
Before going any further, it is important to mention that DB is not
a relational database (although you could use it to build a relational
database). Out of the box, DB does not provide higher-level features
such as triggers, or a high-level query language such as SQL.
Instead, DB provides just those minimal
APIs required to store and retrieve your data as
efficiently as possible.
</p>
</div>
<div class="sect1" lang="en" xml:lang="en">
<div class="titlepage">
<div>
<div>
<h2 class="title" style="clear: both"><a id="aboutthismanual"></a>About This Manual</h2>
</div>
</div>
<div></div>
</div>
<p>
This manual introduces DB. As such, this book does not examine
intermediate or advanced features such as threaded library usage or
transactional usage. Instead, this manual provides a step-by-step
introduction to DB's basic concepts and library usage.
</p>
<p>
Specifically, this manual introduces DB environments, databases,
database records, and storage and retrieval of database records. This
book also introduces cursors and their usage, and it describes
secondary databases.
</p>
<p>
For the most part, this manual focuses on the BTree access method. A
chapter is given at the end of this manual that describes some of the
concepts involving BTree usage, such as duplicate record management and comparison
routines.
</p>
<p>
Examples are given throughout this book that are designed to illustrate
API usage. At the end of each
<span>chapter,</span>
a complete example is given that
is designed to reinforce the concepts covered in that
<span>chapter.</span>
In addition to being presented in this book, these final programs are also
available in the DB software distribution. You can find them in
</p>
<pre class="programlisting"><span class="emphasis"><em>DB_INSTALL</em></span>/examples_c/getting_started</pre>
<p>
where <tt class="literal"><span class="emphasis"><em>DB_INSTALL</em></span></tt> is the
location where you placed your DB distribution.
</p>
<p>
This book uses the C programming languages for its examples.
Note that versions of this book exist for the C++ and Java languages as
well.
</p>
</div>
</div>
<div class="navfooter">
<hr />
<table width="100%" summary="Navigation footer">
<tr>
<td width="40%" align="left"><a accesskey="p" href="preface.html">Prev</a> </td>
<td width="20%" align="center">
<a accesskey="u" href="index.html">Up</a>
</td>
<td width="40%" align="right"> <a accesskey="n" href="concepts.html">Next</a></td>
</tr>
<tr>
<td width="40%" align="left" valign="top">Preface </td>
<td width="20%" align="center">
<a accesskey="h" href="index.html">Home</a>
</td>
<td width="40%" align="right" valign="top"> Berkeley DB Concepts</td>
</tr>
</table>
</div>
</body>
</html>

304
docs/gsg/C/joins.html Normal file
View File

@@ -0,0 +1,304 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>Database Joins</title>
<link rel="stylesheet" href="gettingStarted.css" type="text/css" />
<meta name="generator" content="DocBook XSL Stylesheets V1.62.4" />
<link rel="home" href="index.html" title="Getting Started with Berkeley DB" />
<link rel="up" href="indexes.html" title="Chapter 5. Secondary Databases" />
<link rel="previous" href="secondaryCursor.html" title="&#10; &#10; Using Cursors with Secondary Databases&#10; " />
<link rel="next" href="coreindexusage.html" title="Secondary Database Example" />
</head>
<body>
<div class="navheader">
<table width="100%" summary="Navigation header">
<tr>
<th colspan="3" align="center">Database Joins</th>
</tr>
<tr>
<td width="20%" align="left"><a accesskey="p" href="secondaryCursor.html">Prev</a> </td>
<th width="60%" align="center">Chapter 5. Secondary Databases</th>
<td width="20%" align="right"> <a accesskey="n" href="coreindexusage.html">Next</a></td>
</tr>
</table>
<hr />
</div>
<div class="sect1" lang="en" xml:lang="en">
<div class="titlepage">
<div>
<div>
<h2 class="title" style="clear: both"><a id="joins"></a>Database Joins</h2>
</div>
</div>
<div></div>
</div>
<p>
If you have two or more secondary databases associated with a primary
database, then you can retrieve primary records based on the intersection of
multiple secondary entries. You do this using a
<span>join cursor.</span>
</p>
<p>
Throughout this document we have presented a
<span>structure</span>
that stores
information on grocery
<span>vendors.</span>
That
<span>structure</span>
is fairly simple with a limited
number of data members, few of which would be interesting from a query
perspective. But suppose, instead, that we were storing
information on something with many more characteristics that can be queried, such
as an automobile. In that case, you may be storing information such as
color, number of doors, fuel mileage, automobile type, number of
passengers, make, model, and year, to name just a few.
</p>
<p>
In this case, you would still likely be using some unique value to key your
primary entries (in the United States, the automobile's VIN would be
ideal for this purpose). You would then create a
<span>structure</span>
that identifies
all the characteristics of the automobiles in your inventory.
</p>
<p>
To query this data, you might then create multiple secondary databases,
one for each of the characteristics that you want to query. For
example, you might create a secondary for color, another for number of
doors, another for number of passengers, and so forth. Of course, you
will need a unique
<span>key extractor function</span>
for each such secondary database. You do
all of this using the concepts and techniques described throughout this
chapter.
</p>
<p>
Once you have created this primary database and all interesting
secondaries, what you have is the ability to retrieve automobile records
based on a single characteristic. You can, for example, find all the
automobiles that are red. Or you can find all the automobiles that have
four doors. Or all the automobiles that are minivans.
</p>
<p>
The next most natural step, then, is to form compound queries, or joins.
For example, you might want to find all the automobiles that are red,
and that were built by Toyota, and that are minivans. You can do this
using a
<span>join cursor.</span>
</p>
<div class="sect2" lang="en" xml:lang="en">
<div class="titlepage">
<div>
<div>
<h3 class="title"><a id="joinUsage"></a>Using Join Cursors</h3>
</div>
</div>
<div></div>
</div>
<p>
To use a join cursor:
</p>
<div class="itemizedlist">
<ul type="disc">
<li>
<p>
Open two or more
cursors
<span>for</span>
secondary databases that are associated with
the same primary database.
</p>
</li>
<li>
<p>
Position each such cursor to the secondary key
value in which you are interested. For example, to build on
the previous description, the cursor for the color
database is positioned to the <tt class="literal">red</tt> records
while the cursor for the model database is positioned to the
<tt class="literal">minivan</tt> records, and the cursor for the
make database is positioned to <tt class="literal">Toyota</tt>.
</p>
</li>
<li>
<p>
Create an array of cursors, and
place in it each of the cursors that are participating in your join query.
<span>Note that this array must be null terminated.</span>
</p>
</li>
<li>
<p>
Obtain a join cursor. You do this using the
<tt class="methodname">DB-&gt;join()</tt>
method. You must pass this method the array of secondary cursors that you
opened and positioned in the previous steps.
</p>
</li>
<li>
<p>
Iterate over the set of matching records
until
<span>the return code is not <tt class="literal">0</tt>.</span>
</p>
</li>
<li>
<p>
Close your cursor.
</p>
</li>
<li>
<p>
If you are done with them, close all your cursors.
</p>
</li>
</ul>
</div>
<p>
For example:
</p>
<a id="c_index9"></a>
<pre class="programlisting">#include &lt;db.h&gt;
#include &lt;string.h&gt;
...
DB *automotiveDB;
DB *automotiveColorDB;
DB *automotiveMakeDB;
DB *automotiveTypeDB;
DBC *color_curs, *make_curs, *type_curs, *join_curs;
DBC *carray[4];
DBT key, data;
int ret;
char *the_color = "red";
char *the_type = "minivan";
char *the_make = "Toyota";
/* Database and secondary database opens omitted for brevity.
* Assume a primary database handle:
* automotiveDB
* Assume 3 secondary database handles:
* automotiveColorDB -- secondary database based on automobile color
* automotiveMakeDB -- secondary database based on the manufacturer
* automotiveTypeDB -- secondary database based on automobile type
*/
/* initialize pointers and structures */
color_curs = NULL;
make_curs = NULL;
type_curs = NULL;
join_curs = NULL;
memset(&amp;key, 0, sizeof(DBT));
memset(&amp;data, 0, sizeof(DBT));
/* open the cursors */
if (( ret =
automotiveColorDB-&gt;cursor(automotiveColorDB, NULL,
&amp;color_curs, 0)) != 0) {
/* Error handling goes here */
}
if (( ret =
automotiveMakeDB-&gt;cursor(automotiveMakeDB, NULL,
&amp;make_curs, 0)) != 0) {
/* Error handling goes here */
}
if (( ret =
automotiveTypeDB-&gt;cursor(automotiveTypeDB, NULL,
&amp;type_curs, 0)) != 0) {
/* Error handling goes here */
}
/* Position the cursors */
key.data = the_color;
key.size = strlen(the_color) + 1;
if ((ret = color_curs-&gt;get(color_curs, &amp;key, &amp;data, DB_SET)) != 0)
/* Error handling goes here */
key.data = the_make;
key.size = strlen(the_make) + 1;
if ((ret = make_curs-&gt;get(make_curs, &amp;key, &amp;data, DB_SET)) != 0)
/* Error handling goes here */
key.data = the_type;
key.size = strlen(the_type) + 1;
if ((ret = type_curs-&gt;get(type_curs, &amp;key, &amp;data, DB_SET)) != 0)
/* Error handling goes here */
/* Set up the cursor array */
carray[0] = color_curs;
carray[1] = make_curs;
carray[2] = type_curs;
carray[3] = NULL;
/* Create the join */
if ((ret = automotiveDB-&gt;join(automotiveDB, carray, &amp;join_curs, 0)) != 0)
/* Error handling goes here */
/* Iterate using the join cursor */
while ((ret = join_curs-&gt;get(join_curs, &amp;key, &amp;data, 0)) == 0) {
/* Do interesting things with the key and data */
}
/*
* If we exited the loop because we ran out of records,
* then it has completed successfully.
*/
if (ret == DB_NOTFOUND) {
/*
* Close all our cursors and databases as is appropriate, and
* then exit with a normal exit status (0).
*/
} </pre>
</div>
</div>
<div class="navfooter">
<hr />
<table width="100%" summary="Navigation footer">
<tr>
<td width="40%" align="left"><a accesskey="p" href="secondaryCursor.html">Prev</a> </td>
<td width="20%" align="center">
<a accesskey="u" href="indexes.html">Up</a>
</td>
<td width="40%" align="right"> <a accesskey="n" href="coreindexusage.html">Next</a></td>
</tr>
<tr>
<td width="40%" align="left" valign="top">
Using Cursors with Secondary Databases
 </td>
<td width="20%" align="center">
<a accesskey="h" href="index.html">Home</a>
</td>
<td width="40%" align="right" valign="top"> Secondary Database Example</td>
</tr>
</table>
</div>
</body>
</html>

256
docs/gsg/C/keyCreator.html Normal file
View File

@@ -0,0 +1,256 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>Implementing Key
Extractors
</title>
<link rel="stylesheet" href="gettingStarted.css" type="text/css" />
<meta name="generator" content="DocBook XSL Stylesheets V1.62.4" />
<link rel="home" href="index.html" title="Getting Started with Berkeley DB" />
<link rel="up" href="indexes.html" title="Chapter 5. Secondary Databases" />
<link rel="previous" href="indexes.html" title="Chapter 5. Secondary Databases" />
<link rel="next" href="readSecondary.html" title="Reading Secondary Databases" />
</head>
<body>
<div class="navheader">
<table width="100%" summary="Navigation header">
<tr>
<th colspan="3" align="center">Implementing Key
Extractors
</th>
</tr>
<tr>
<td width="20%" align="left"><a accesskey="p" href="indexes.html">Prev</a> </td>
<th width="60%" align="center">Chapter 5. Secondary Databases</th>
<td width="20%" align="right"> <a accesskey="n" href="readSecondary.html">Next</a></td>
</tr>
</table>
<hr />
</div>
<div class="sect1" lang="en" xml:lang="en">
<div class="titlepage">
<div>
<div>
<h2 class="title" style="clear: both"><a id="keyCreator"></a>Implementing Key
<span>Extractors</span>
</h2>
</div>
</div>
<div></div>
</div>
<p>
You must provide every secondary database with a
<span>callback</span>
that creates keys from primary records. You identify this
<span>callback</span>
<span>
when you associate your secondary database to your primary.
</span>
</p>
<p>
You can create keys using whatever data you want. Typically you will
base your key on some information found in a record's data, but you
can also use information found in the primary record's key. How you build
your keys is entirely dependent upon the nature of the index that you
want to maintain.
</p>
<p>
You implement a key extractor by writing a function that extracts
the necessary information from a primary record's key or data.
This function must conform to a specific prototype, and it must be
provided as a callback to the <tt class="methodname">associate()</tt>
method.
</p>
<p>
For example, suppose your primary database records contain data that
uses the following structure:
</p>
<a id="c_index3"></a>
<pre class="programlisting">typedef struct vendor {
char name[MAXFIELD]; /* Vendor name */
char street[MAXFIELD]; /* Street name and number */
char city[MAXFIELD]; /* City */
char state[3]; /* Two-digit US state code */
char zipcode[6]; /* US zipcode */
char phone_number[13]; /* Vendor phone number */
char sales_rep[MAXFIELD]; /* Name of sales representative */
char sales_rep_phone[MAXFIELD]; /* Sales rep's phone number */
} VENDOR; </pre>
<p>
Further suppose that you want to be able to query your primary database
based on the name of a sales representative. Then you would write a
function that looks like this:
</p>
<a id="c_index4"></a>
<pre class="programlisting">#include &lt;db.h&gt;
...
int
get_sales_rep(DB *sdbp, /* secondary db handle */
const DBT *pkey, /* primary db record's key */
const DBT *pdata, /* primary db record's data */
DBT *skey) /* secondary db record's key */
{
VENDOR *vendor;
/* First, extract the structure contained in the primary's data */
vendor = pdata-&gt;data;
/* Now set the secondary key's data to be the representative's name */
memset(skey, 0, sizeof(DBT));
skey-&gt;data = vendor-&gt;sales_rep;
skey-&gt;size = strlen(vendor-&gt;sales_rep) + 1;
/* Return 0 to indicate that the record can be created/updated. */
return (0);
} </pre>
<p>
In order to use this function, you provide it on the
<tt class="methodname">associate()</tt> method after the primary and
secondary databases have been created and opened:
</p>
<a id="c_index5"></a>
<pre class="programlisting">dbp-&gt;associate(dbp, /* Primary database */
NULL, /* TXN id */
sdbp, /* Secondary database */
get_sales_rep, /* Callback used for key creation. */
0); /* Flags */</pre>
<div class="sect2" lang="en" xml:lang="en">
<div class="titlepage">
<div>
<div>
<h3 class="title"><a id="multikeys"></a>Working with Multiple Keys</h3>
</div>
</div>
<div></div>
</div>
<p>
Until now we have only discussed indexes as if there is
a one-to-one relationship between the secondary key and
the primary database record. In fact, it is possible to
generate multiple keys for any given record, provided
that you take appropriate steps in your key creator
to do so.
</p>
<p>
For example, suppose you had a database that contained
information about books. Suppose further that you
sometimes want to look up books by author. Because
sometimes books have multiple authors, you may want to
return multiple secondary keys for every book that you
index.
</p>
<p>
To do this, you write a key extractor that returns a
<span>DBT</span>
whose <tt class="literal">data</tt> member points to an array of
<span>DBTs.</span>
Each such member of this array contains a single secondary key.
In addition, the
<span>DBT</span>
returned by your key extractor must have a size field
equal to the number of elements contained in the
<span>DBT</span>
array. Also, the flag field for the
<span>DBT</span>
returned by the callback must include
<tt class="literal">DB_DBT_MULTIPLE</tt>. For example:
</p>
<div class="note" style="margin-left: 0.5in; margin-right: 0.5in;">
<h3 class="title">Note</h3>
<p>
It is important that the array of secondary
keys created by your callback not contain
repeats. That is, every element in the array
must be unique. If the array does not contain
a unique set, then the secondary can get out
of sync with the primary.
</p>
</div>
<pre class="programlisting">int
my_callback(DB *dbp, const DBT *pkey, const DBT *pdata, DBT *skey)
{
DBT *tmpdbt;
char *tmpdata1, tmpdata2;
/*
* This example skips the step of extracting the data you
* want to use for building your secondary keys from the
* pkey or pdata DBT.
*
* Assume for the purpose of this example that the data
* is temporarily stored in two variables,
* tmpdata1 and tmpdata2.
*/
/*
* Create an array of DBTs that is large enough for the
* number of keys that you want to return. In this case,
* we go with an array of size two.
*/
tmpdbt = malloc(sizeof(DBT) * 2);
memset(tmpdbt, 0, sizeof(DBT) * 2);
/* Now assign secondary keys to each element of the array. */
tmpdbt[0].data = tmpdata1;
tmpdbt[0].size = (u_int32_t)strlen(tmpdbt[0].data) + 1;
tmpdbt[1].data = tmpdata2;
tmpdbt[1].size = (u_int32_t)strlen(tmpdbt[1].data) + 1;
/*
* Now we set flags for the returned DBT. DB_DBT_MULTIPLE is
* required in order for DB to know that the DBT references an
* array. In addition, we set DB_DBT_APPMALLOC because we
* dynamically allocated memory for the DBT's data field.
* DB_DBT_APPMALLOC causes DB to release that memory once it
* is done with the returned DBT.
*/
skey-&gt;flags = DB_DBT_MULTIPLE | DB_DBT_APPMALLOC;
/* Point the results data field to the arrays of DBTs */
skey-&gt;data = tmpdbt;
/* Indicate the returned array is of size 2 */
skey-&gt;size = 2;
return (0);
} </pre>
</div>
</div>
<div class="navfooter">
<hr />
<table width="100%" summary="Navigation footer">
<tr>
<td width="40%" align="left"><a accesskey="p" href="indexes.html">Prev</a> </td>
<td width="20%" align="center">
<a accesskey="u" href="indexes.html">Up</a>
</td>
<td width="40%" align="right"> <a accesskey="n" href="readSecondary.html">Next</a></td>
</tr>
<tr>
<td width="40%" align="left" valign="top">Chapter 5. Secondary Databases </td>
<td width="20%" align="center">
<a accesskey="h" href="index.html">Home</a>
</td>
<td width="40%" align="right" valign="top"> Reading Secondary Databases</td>
</tr>
</table>
</div>
</body>
</html>

214
docs/gsg/C/preface.html Normal file
View File

@@ -0,0 +1,214 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>Preface</title>
<link rel="stylesheet" href="gettingStarted.css" type="text/css" />
<meta name="generator" content="DocBook XSL Stylesheets V1.62.4" />
<link rel="home" href="index.html" title="Getting Started with Berkeley DB" />
<link rel="up" href="index.html" title="Getting Started with Berkeley DB" />
<link rel="previous" href="index.html" title="Getting Started with Berkeley DB" />
<link rel="next" href="introduction.html" title="Chapter 1. Introduction to Berkeley DB " />
</head>
<body>
<div class="navheader">
<table width="100%" summary="Navigation header">
<tr>
<th colspan="3" align="center">Preface</th>
</tr>
<tr>
<td width="20%" align="left"><a accesskey="p" href="index.html">Prev</a> </td>
<th width="60%" align="center"> </th>
<td width="20%" align="right"> <a accesskey="n" href="introduction.html">Next</a></td>
</tr>
</table>
<hr />
</div>
<div class="preface" lang="en" xml:lang="en">
<div class="titlepage">
<div>
<div>
<h2 class="title"><a id="preface"></a>Preface</h2>
</div>
</div>
<div></div>
</div>
<div class="toc">
<p>
<b>Table of Contents</b>
</p>
<dl>
<dt>
<span class="sect1">
<a href="preface.html#conventions">Conventions Used in this Book</a>
</span>
</dt>
<dd>
<dl>
<dt>
<span class="sect2">
<a href="preface.html#moreinfo">For More Information</a>
</span>
</dt>
</dl>
</dd>
</dl>
</div>
<p>
Welcome to Berkeley DB (DB). This document introduces
<span>DB, version 4.7. </span>
It is intended
to provide a rapid introduction to the DB API set and related concepts. The goal of this document is
to provide you with an efficient mechanism
with which you can evaluate DB against your project's technical requirements. As such, this document is
intended for
<span>C</span> developers and senior software architects who are
looking for an
<span>
in-process data management solution.
</span>
No prior experience with Berkeley DB is expected or required.
</p>
<div class="sect1" lang="en" xml:lang="en">
<div class="titlepage">
<div>
<div>
<h2 class="title" style="clear: both"><a id="conventions"></a>Conventions Used in this Book</h2>
</div>
</div>
<div></div>
</div>
<p>
The following typographical conventions are used within in this manual:
</p>
<p>
Structure names are represented in <tt class="classname">monospaced font</tt>, as are <tt class="methodname">method
names</tt>. For example: "<tt class="methodname">DB-&gt;open()</tt> is a method
on a <tt class="classname">DB</tt> handle."
</p>
<p>
Variable or non-literal text is presented in <span class="emphasis"><em>italics</em></span>. For example: "Go to your
<span class="emphasis"><em>DB_INSTALL</em></span>
directory."
</p>
<p>
Program examples are displayed in a <tt class="classname">monospaced font</tt> on a shaded background.
For example:
</p>
<pre class="programlisting">/* File: gettingstarted_common.h */
typedef struct stock_dbs {
DB *inventory_dbp; /* Database containing inventory information */
DB *vendor_dbp; /* Database containing vendor information */
char *db_home_dir; /* Directory containing the database files */
char *inventory_db_name; /* Name of the inventory database */
char *vendor_db_name; /* Name of the vendor database */
} STOCK_DBS; </pre>
<p>
In some situations, programming examples are updated from one chapter to the next. When
this occurs, the new code is presented in <b class="userinput"><tt>monospaced bold</tt></b> font. For example:
</p>
<pre class="programlisting">typedef struct stock_dbs {
DB *inventory_dbp; /* Database containing inventory information */
DB *vendor_dbp; /* Database containing vendor information */
<b class="userinput"><tt>DB *itemname_sdbp; /* Index based on the item name index */</tt></b>
char *db_home_dir; /* Directory containing the database files */
<b class="userinput"><tt>char *itemname_db_name; /* Itemname secondary database */</tt></b>
char *inventory_db_name; /* Name of the inventory database */
char *vendor_db_name; /* Name of the vendor database */
} STOCK_DBS; </pre>
<div class="note" style="margin-left: 0.5in; margin-right: 0.5in;">
<h3 class="title">Note</h3>
<p>
Finally, notes of interest are represented using a note block such
as this.
</p>
</div>
<div class="sect2" lang="en" xml:lang="en">
<div class="titlepage">
<div>
<div>
<h3 class="title"><a id="moreinfo"></a>For More Information</h3>
</div>
</div>
<div></div>
</div>
<p>
Beyond this manual, you may also find the following sources of information useful when building a
DB application:
</p>
<div class="itemizedlist">
<ul type="disc">
<li>
<p>
<a href="http://www.oracle.com/technology/documentation/berkeley-db/db/gsg_txn/C/index.html" target="_top">
Getting Started with Transaction Processing for C
</a>
</p>
</li>
<li>
<p>
<a href="http://www.oracle.com/technology/documentation/berkeley-db/db/gsg_db_rep/C/index.html" target="_top">
Berkeley DB Getting Started with Replicated Applications for C
</a>
</p>
</li>
<li>
<p>
<a href="http://www.oracle.com/technology/documentation/berkeley-db/db/ref/toc.html" target="_top">
Berkeley DB Programmer's Reference Guide
</a>
</p>
</li>
<li>
<p>
<a href="http://www.oracle.com/technology/documentation/berkeley-db/db/api_c/frame.html" target="_top">
Berkeley DB C API
</a>
</p>
</li>
</ul>
</div>
</div>
</div>
</div>
<div class="navfooter">
<hr />
<table width="100%" summary="Navigation footer">
<tr>
<td width="40%" align="left"><a accesskey="p" href="index.html">Prev</a> </td>
<td width="20%" align="center">
<a accesskey="u" href="index.html">Up</a>
</td>
<td width="40%" align="right"> <a accesskey="n" href="introduction.html">Next</a></td>
</tr>
<tr>
<td width="40%" align="left" valign="top">Getting Started with Berkeley DB </td>
<td width="20%" align="center">
<a accesskey="h" href="index.html">Home</a>
</td>
<td width="40%" align="right" valign="top"> Chapter 1. Introduction to Berkeley DB </td>
</tr>
</table>
</div>
</body>
</html>

View File

@@ -0,0 +1,140 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>Reading Secondary Databases</title>
<link rel="stylesheet" href="gettingStarted.css" type="text/css" />
<meta name="generator" content="DocBook XSL Stylesheets V1.62.4" />
<link rel="home" href="index.html" title="Getting Started with Berkeley DB" />
<link rel="up" href="indexes.html" title="Chapter 5. Secondary Databases" />
<link rel="previous" href="keyCreator.html" title="Implementing Key &#10; &#10; Extractors&#10; " />
<link rel="next" href="secondaryDelete.html" title="Deleting Secondary Database Records" />
</head>
<body>
<div class="navheader">
<table width="100%" summary="Navigation header">
<tr>
<th colspan="3" align="center">Reading Secondary Databases</th>
</tr>
<tr>
<td width="20%" align="left"><a accesskey="p" href="keyCreator.html">Prev</a> </td>
<th width="60%" align="center">Chapter 5. Secondary Databases</th>
<td width="20%" align="right"> <a accesskey="n" href="secondaryDelete.html">Next</a></td>
</tr>
</table>
<hr />
</div>
<div class="sect1" lang="en" xml:lang="en">
<div class="titlepage">
<div>
<div>
<h2 class="title" style="clear: both"><a id="readSecondary"></a>Reading Secondary Databases</h2>
</div>
</div>
<div></div>
</div>
<p>
Like a primary database, you can read records from your secondary
database either by using the
<span>
<tt class="methodname">DB-&gt;get()</tt>
or
<tt class="methodname">DB-&gt;pget()</tt>
methods,
</span>
or by using
<span>a cursor on the secondary database.</span>
The main difference between reading secondary and primary databases is that when
you read a secondary database record, the secondary record's data is not
returned to you. Instead, the primary key and data corresponding to the
secondary key are returned to you.
</p>
<p>
For example, assuming your secondary database contains keys related
to a person's full name:
</p>
<a id="c_index6"></a>
<pre class="programlisting">#include &lt;db.h&gt;
#include &lt;string.h&gt;
...
DB *my_secondary_database;
DBT key; /* Used for the search key */
DBT pkey, pdata; /* Used to return the primary key and data */
char *search_name = "John Doe";
/* Primary and secondary database opens omitted for brevity */
/* Zero out the DBTs before using them. */
memset(&amp;key, 0, sizeof(DBT));
memset(&amp;pkey, 0, sizeof(DBT));
memset(&amp;pdata, 0, sizeof(DBT));
key.data = search_name;
key.size = strlen(search_name) + 1;
/* Returns the key from the secondary database, and the data from the
* associated primary database entry.
*/
my_secondary_database-&gt;get(my_secondary_database, NULL,
&amp;key, &amp;pdata, 0);
/* Returns the key from the secondary database, and the key and data
* from the associated primary database entry.
*/
my_secondary_database-&gt;pget(my_secondary_database, NULL,
&amp;key, &amp;pkey, &amp;pdata, 0); </pre>
<p>
Note that, just like
<span>a primary database,</span>
if your secondary database supports duplicate records then
<span>
<tt class="methodname">DB-&gt;get()</tt>
and
<tt class="methodname">DB-&gt;pget()</tt>
</span>
only return the first record found in a matching duplicates set. If you
want to see all the records related to a specific secondary key, then use a
<span>
cursor opened on the secondary database. Cursors are described in
<a href="Cursors.html">Using Cursors</a>.
</span>
</p>
</div>
<div class="navfooter">
<hr />
<table width="100%" summary="Navigation footer">
<tr>
<td width="40%" align="left"><a accesskey="p" href="keyCreator.html">Prev</a> </td>
<td width="20%" align="center">
<a accesskey="u" href="indexes.html">Up</a>
</td>
<td width="40%" align="right"> <a accesskey="n" href="secondaryDelete.html">Next</a></td>
</tr>
<tr>
<td width="40%" align="left" valign="top">Implementing Key
Extractors
 </td>
<td width="20%" align="center">
<a accesskey="h" href="index.html">Home</a>
</td>
<td width="40%" align="right" valign="top"> Deleting Secondary Database Records</td>
</tr>
</table>
</div>
</body>
</html>

101
docs/gsg/C/returns.html Normal file
View File

@@ -0,0 +1,101 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>Error Returns</title>
<link rel="stylesheet" href="gettingStarted.css" type="text/css" />
<meta name="generator" content="DocBook XSL Stylesheets V1.62.4" />
<link rel="home" href="index.html" title="Getting Started with Berkeley DB" />
<link rel="up" href="introduction.html" title="Chapter 1. Introduction to Berkeley DB " />
<link rel="previous" href="environments.html" title="Environments" />
<link rel="next" href="gettingit.html" title="Getting and Using DB " />
</head>
<body>
<div class="navheader">
<table width="100%" summary="Navigation header">
<tr>
<th colspan="3" align="center">Error Returns</th>
</tr>
<tr>
<td width="20%" align="left"><a accesskey="p" href="environments.html">Prev</a> </td>
<th width="60%" align="center">Chapter 1. Introduction to Berkeley DB </th>
<td width="20%" align="right"> <a accesskey="n" href="gettingit.html">Next</a></td>
</tr>
</table>
<hr />
</div>
<div class="sect1" lang="en" xml:lang="en">
<div class="titlepage">
<div>
<div>
<h2 class="title" style="clear: both"><a id="returns"></a>Error Returns</h2>
</div>
</div>
<div></div>
</div>
<p>
Before continuing, it is useful to spend a few moments on error returns
in DB.
</p>
<p>
<span>The</span>
DB interfaces always return a value of 0 on success. If the
operation does not succeed for any reason, the return value will be
non-zero.
</p>
<p>
If a system error occurred (for example, DB ran out of disk
space, or permission to access a file was denied, or an illegal argument
was specified to one of the interfaces), DB returns an
<tt class="literal">errno</tt>
value. All of the possible values of <tt class="literal">errno</tt> are greater than 0.
</p>
<p>
If the operation did not fail due to a system error, but was not
successful either, DB returns a special error value. For
example, if you tried to retrieve data from the database and the
record for which you are searching does not exist, DB would return
<tt class="literal">DB_NOTFOUND</tt>, a special error value that means the requested
key does not appear in the database. All of the possible special error
values are less than 0.
</p>
<p>
DB also offers programmatic support for displaying error return
values. First, the <tt class="function">db_strerror</tt> function returns
a pointer to the error
message corresponding to any DB error return, similar to the
ANSI C <tt class="function">strerror</tt> function, but is able to handle
both system error returns and DB-specific return values.
</p>
<p>
Second, there are two error functions,
<tt class="methodname">DB-&gt;err</tt> and <tt class="methodname">DB-&gt;errx</tt>.
These functions work like the ANSI C <tt class="function">printf</tt> function,
taking a printf-style format string and argument list, and optionally
appending the standard error string to a message constructed from
the format string and other arguments.
</p>
</div>
<div class="navfooter">
<hr />
<table width="100%" summary="Navigation footer">
<tr>
<td width="40%" align="left"><a accesskey="p" href="environments.html">Prev</a> </td>
<td width="20%" align="center">
<a accesskey="u" href="introduction.html">Up</a>
</td>
<td width="40%" align="right"> <a accesskey="n" href="gettingit.html">Next</a></td>
</tr>
<tr>
<td width="40%" align="left" valign="top">Environments </td>
<td width="20%" align="center">
<a accesskey="h" href="index.html">Home</a>
</td>
<td width="40%" align="right" valign="top"> Getting and Using DB </td>
</tr>
</table>
</div>
</body>
</html>

View File

@@ -0,0 +1,157 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>
Using Cursors with Secondary Databases
</title>
<link rel="stylesheet" href="gettingStarted.css" type="text/css" />
<meta name="generator" content="DocBook XSL Stylesheets V1.62.4" />
<link rel="home" href="index.html" title="Getting Started with Berkeley DB" />
<link rel="up" href="indexes.html" title="Chapter 5. Secondary Databases" />
<link rel="previous" href="secondaryDelete.html" title="Deleting Secondary Database Records" />
<link rel="next" href="joins.html" title="Database Joins" />
</head>
<body>
<div class="navheader">
<table width="100%" summary="Navigation header">
<tr>
<th colspan="3" align="center">
Using Cursors with Secondary Databases
</th>
</tr>
<tr>
<td width="20%" align="left"><a accesskey="p" href="secondaryDelete.html">Prev</a> </td>
<th width="60%" align="center">Chapter 5. Secondary Databases</th>
<td width="20%" align="right"> <a accesskey="n" href="joins.html">Next</a></td>
</tr>
</table>
<hr />
</div>
<div class="sect1" lang="en" xml:lang="en">
<div class="titlepage">
<div>
<div>
<h2 class="title" style="clear: both"><a id="secondaryCursor"></a>
<span>Using Cursors with Secondary Databases</span>
</h2>
</div>
</div>
<div></div>
</div>
<p>
Just like cursors on a primary database, you can use
<span>cursors on secondary databases</span>
to iterate over the records in a secondary database. Like
<span>cursors used with primary databases,</span>
you can also use
<span>cursors with secondary databases</span>
to search for specific records in a database, to seek to the first
or last record in the database, to get the next duplicate record,
and so forth. For a complete description on cursors and their capabilities, see
<a href="Cursors.html">Using Cursors</a>.
</p>
<p>
However, when you use
<span>cursors with secondary databases:</span>
</p>
<div class="itemizedlist">
<ul type="disc">
<li>
<p>
Any data returned is the data contained on the primary database
record referenced by the secondary record.
</p>
</li>
<li>
<p>
You cannot use <tt class="literal">DB_GET_BOTH</tt> and related flags with
<tt class="methodname">DB-&gt;get()</tt>
and a secondary database. Instead, you must use
<span><tt class="methodname">DB-&gt;pget()</tt>.</span>
Also, in that case the primary and secondary key given on the call to
<tt class="methodname">DB-&gt;pget()</tt>
must match the secondary key and associated primary record key in
order for that primary record to be returned as a result of the
call.
</p>
</li>
</ul>
</div>
<p>
For example, suppose you are using the databases, classes, and key
<span>extractors</span>
described in <a href="keyCreator.html">Implementing Key
<span>Extractors</span>
</a>.
Then the following searches for a person's
name in the secondary database, and deletes all secondary and primary
records that use that name.
</p>
<a id="c_index8"></a>
<pre class="programlisting">#include &lt;db.h&gt;
#include &lt;string.h&gt;
...
DB *sdbp; /* Secondary DB handle */
DBC *cursorp; /* Cursor */
DBT key, data; /* DBTs used for the delete */
char *search_name = "John Doe"; /* Name to delete */
/* Primary and secondary database opens omitted for brevity. */
/* Get a cursor on the secondary database */
sdbp-&gt;cursor(sdbp, NULL, &amp;cursorp, 0);
/*
* Zero out the DBT before using it.
*/
memset(&amp;key, 0, sizeof(DBT));
memset(&amp;data, 0, sizeof(DBT));
key.data = search_name;
key.size = strlen(search_name) + 1;
/* Position the cursor */
while (cursorp-&gt;get(cursorp, &amp;key, &amp;data, DB_SET) == 0)
cursorp-&gt;del(cursorp, 0); </pre>
</div>
<div class="navfooter">
<hr />
<table width="100%" summary="Navigation footer">
<tr>
<td width="40%" align="left"><a accesskey="p" href="secondaryDelete.html">Prev</a> </td>
<td width="20%" align="center">
<a accesskey="u" href="indexes.html">Up</a>
</td>
<td width="40%" align="right"> <a accesskey="n" href="joins.html">Next</a></td>
</tr>
<tr>
<td width="40%" align="left" valign="top">Deleting Secondary Database Records </td>
<td width="20%" align="center">
<a accesskey="h" href="index.html">Home</a>
</td>
<td width="40%" align="right" valign="top"> Database Joins</td>
</tr>
</table>
</div>
</body>
</html>

View File

@@ -0,0 +1,184 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>Deleting Secondary Database Records</title>
<link rel="stylesheet" href="gettingStarted.css" type="text/css" />
<meta name="generator" content="DocBook XSL Stylesheets V1.62.4" />
<link rel="home" href="index.html" title="Getting Started with Berkeley DB" />
<link rel="up" href="indexes.html" title="Chapter 5. Secondary Databases" />
<link rel="previous" href="readSecondary.html" title="Reading Secondary Databases" />
<link rel="next" href="secondaryCursor.html" title="&#10; &#10; Using Cursors with Secondary Databases&#10; " />
</head>
<body>
<div class="navheader">
<table width="100%" summary="Navigation header">
<tr>
<th colspan="3" align="center">Deleting Secondary Database Records</th>
</tr>
<tr>
<td width="20%" align="left"><a accesskey="p" href="readSecondary.html">Prev</a> </td>
<th width="60%" align="center">Chapter 5. Secondary Databases</th>
<td width="20%" align="right"> <a accesskey="n" href="secondaryCursor.html">Next</a></td>
</tr>
</table>
<hr />
</div>
<div class="sect1" lang="en" xml:lang="en">
<div class="titlepage">
<div>
<div>
<h2 class="title" style="clear: both"><a id="secondaryDelete"></a>Deleting Secondary Database Records</h2>
</div>
</div>
<div></div>
</div>
<p>
In general, you
<span>will</span>
not modify a secondary database directly. In
order to modify a secondary database, you should modify the primary
database and simply allow DB to manage the secondary modifications for you.
</p>
<p>
However, as a convenience, you can delete
<span>secondary database</span>
records directly. Doing so causes the associated primary key/data pair to be deleted.
This in turn causes DB to delete all
<span>secondary database</span>
records that reference the primary record.
</p>
<p>
You can use the
<tt class="methodname">DB-&gt;del()</tt>
method to delete a secondary database record.
<span>Note that if your
<span>secondary database</span>
contains duplicate records, then deleting a record from the set of
duplicates causes all of the duplicates to be deleted as well.
</span>
</p>
<div class="note" style="margin-left: 0.5in; margin-right: 0.5in;">
<h3 class="title">Note</h3>
<p>
<span>
You can delete a secondary database record using the previously
described mechanism
</span>
only if the primary database is opened for write access.
</p>
</div>
<p>For example:</p>
<a id="c_index7"></a>
<pre class="programlisting">#include &lt;db.h&gt;
#include &lt;string.h&gt;
...
DB *dbp, *sdbp; /* Primary and secondary DB handles */
DBT key; /* DBTs used for the delete */
int ret; /* Function return value */
char *search_name = "John Doe"; /* Name to delete */
/* Primary */
ret = db_create(&amp;dbp, NULL, 0);
if (ret != 0) {
/* Error handling goes here */
}
/* Secondary */
ret = db_create(&amp;sdbp, NULL, 0);
if (ret != 0) {
/* Error handling goes here */
}
/* Usually we want to support duplicates for secondary databases */
ret = sdbp-&gt;set_flags(sdbp, DB_DUPSORT);
if (ret != 0) {
/* Error handling goes here */
}
/* open the primary database */
ret = dbp-&gt;open(dbp, /* DB structure pointer */
NULL, /* Transaction pointer */
"my_db.db", /* On-disk file that holds the database.
* Required. */
NULL, /* Optional logical database name */
DB_BTREE, /* Database access method */
0, /* Open flags */
0); /* File mode (using defaults) */
if (ret != 0) {
/* Error handling goes here */
}
/* open the secondary database */
ret = sdbp-&gt;open(sdbp, /* DB structure pointer */
NULL, /* Transaction pointer */
"my_secdb.db", /* On-disk file that holds the database.
* Required. */
NULL, /* Optional logical database name */
DB_BTREE, /* Database access method */
0, /* Open flags */
0); /* File mode (using defaults) */
if (ret != 0) {
/* Error handling goes here */
}
/* Now associate the secondary to the primary */
dbp-&gt;associate(dbp, /* Primary database */
NULL, /* TXN id */
sdbp, /* Secondary database */
get_sales_rep, /* Callback used for key creation. */
0); /* Flags */
/*
* Zero out the DBT before using it.
*/
memset(&amp;key, 0, sizeof(DBT));
key.data = search_name;
key.size = strlen(search_name) + 1;
/* Now delete the secondary record. This causes the associated primary
* record to be deleted. If any other secondary databases have secondary
* records referring to the deleted primary record, then those secondary
* records are also deleted.
*/
sdbp-&gt;del(sdbp, NULL, &amp;key, 0); </pre>
</div>
<div class="navfooter">
<hr />
<table width="100%" summary="Navigation footer">
<tr>
<td width="40%" align="left"><a accesskey="p" href="readSecondary.html">Prev</a> </td>
<td width="20%" align="center">
<a accesskey="u" href="indexes.html">Up</a>
</td>
<td width="40%" align="right"> <a accesskey="n" href="secondaryCursor.html">Next</a></td>
</tr>
<tr>
<td width="40%" align="left" valign="top">Reading Secondary Databases </td>
<td width="20%" align="center">
<a accesskey="h" href="index.html">Home</a>
</td>
<td width="40%" align="right" valign="top"> 
Using Cursors with Secondary Databases
</td>
</tr>
</table>
</div>
</body>
</html>

397
docs/gsg/C/usingDbt.html Normal file
View File

@@ -0,0 +1,397 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>Reading and Writing Database Records</title>
<link rel="stylesheet" href="gettingStarted.css" type="text/css" />
<meta name="generator" content="DocBook XSL Stylesheets V1.62.4" />
<link rel="home" href="index.html" title="Getting Started with Berkeley DB" />
<link rel="up" href="DBEntry.html" title="Chapter 3. Database Records" />
<link rel="previous" href="DBEntry.html" title="Chapter 3. Database Records" />
<link rel="next" href="cstructs.html" title="Using C Structures with DB" />
</head>
<body>
<div class="navheader">
<table width="100%" summary="Navigation header">
<tr>
<th colspan="3" align="center">Reading and Writing Database Records</th>
</tr>
<tr>
<td width="20%" align="left"><a accesskey="p" href="DBEntry.html">Prev</a> </td>
<th width="60%" align="center">Chapter 3. Database Records</th>
<td width="20%" align="right"> <a accesskey="n" href="cstructs.html">Next</a></td>
</tr>
</table>
<hr />
</div>
<div class="sect1" lang="en" xml:lang="en">
<div class="titlepage">
<div>
<div>
<h2 class="title" style="clear: both"><a id="usingDbt"></a>Reading and Writing Database Records</h2>
</div>
</div>
<div></div>
</div>
<p>
When reading and writing database records, be aware that there are some
slight differences in behavior depending on whether your database supports duplicate
records. Two or more database records are considered to be duplicates of
one another if they share the same key. The collection of records
sharing the same key are called a <span class="emphasis"><em>duplicates set.</em></span>
<span>
In DB, a given key is stored only once for a single duplicates set.
</span>
</p>
<p>
By default, DB databases do
not support duplicate records. Where duplicate records are supported,
cursors (see below) are <span>typically</span> used
to access all of the records in the duplicates set.
</p>
<p>
DB provides two basic mechanisms for the storage and retrieval of database
key/data pairs:
</p>
<div class="itemizedlist">
<ul type="disc">
<li>
<p>
The
<tt class="methodname">DBT-&gt;put()</tt>
and
<tt class="methodname">DBT-&gt;get()</tt>
methods provide the easiest access for all non-duplicate records in the database.
These methods are described in this section.
</p>
</li>
<li>
<p>Cursors provide several methods for putting and getting database
records. Cursors and their database access methods are described in
<a href="Cursors.html">Using Cursors</a>.</p>
</li>
</ul>
</div>
<div class="sect2" lang="en" xml:lang="en">
<div class="titlepage">
<div>
<div>
<h3 class="title"><a id="databaseWrite"></a>Writing Records to the Database</h3>
</div>
</div>
<div></div>
</div>
<p>
Records are stored in the database using whatever organization is
required by the access method that you have selected. In some cases (such as
BTree), records are stored in a sort order that you may want to define
(see <a href="btree.html#comparators">Setting Comparison Functions</a> for more information).
</p>
<p>
In any case, the mechanics of putting and getting database records do not
change once you have selected your access method, configured your
sorting routines (if any), and opened your database. From your
code's perspective, a simple database put and get is largely the
same no matter what access method you are using.
</p>
<p>
You use
<tt class="methodname">DB-&gt;put()</tt>
to put, or write, a database record. This method requires you to provide
the record's key and data in the form of a pair of
<span><tt class="methodname">DBT</tt> structures.</span>
You can also provide one or more flags that control DB's behavior
for the database write.
</p>
<p>
Of the flags available to this method, <tt class="literal">DB_NOOVERWRITE</tt>
may be interesting to you. This flag disallows overwriting (replacing)
an existing record in the database. If the provided key already exists
in the database, then this method returns <tt class="literal">DB_KEYEXIST</tt> even if
the database supports duplicates.
</p>
<p>
For example:
</p>
<a id="c_dbt3"></a>
<pre class="programlisting">#include &lt;db.h&gt;
#include &lt;string.h&gt;
...
char *description = "Grocery bill.";
DBT key, data;
DB *my_database;
int ret;
float money;
/* Database open omitted for clarity */
money = 122.45;
/* Zero out the DBTs before using them. */
memset(&amp;key, 0, sizeof(DBT));
memset(&amp;data, 0, sizeof(DBT));
key.data = &amp;money;
key.size = sizeof(float);
data.data = description;
data.size = strlen(description) +1;
ret = my_database-&gt;put(my_database, NULL, &amp;key, &amp;data, DB_NOOVERWRITE);
if (ret == DB_KEYEXIST) {
my_database-&gt;err(my_database, ret,
"Put failed because key %f already exists", money);
}</pre>
</div>
<div class="sect2" lang="en" xml:lang="en">
<div class="titlepage">
<div>
<div>
<h3 class="title"><a id="CoreDatabaseRead"></a>Getting Records from the Database</h3>
</div>
</div>
<div></div>
</div>
<p>
You can use the
<tt class="methodname">DB-&gt;get()</tt>
method to retrieve database records. Note that if your
database supports duplicate records, then by default this method will only
return the first record in a duplicate set. For this reason, if your
database supports duplicates, the common solution is to use a cursor to retrieve
records from it. Cursors are described in <a href="Cursors.html">Using Cursors</a>.
</p>
<p>
(You can also retrieve a set of duplicate records using a bulk get.
To do this, you use the <tt class="literal">DB_MULTIPLE</tt> flag on the
call to
<span><tt class="methodname">DB-&gt;get()</tt>.</span>
For more information, see the DB Programmer's Reference Guide).
</p>
<p>
By default,
<tt class="methodname">DB-&gt;get()</tt>
returns the first record found whose key matches the key
provide on the call to this method. If your database supports
duplicate records, you can change this behavior slightly by supplying
the <tt class="literal">DB_GET_BOTH</tt> flag. This flag causes
<tt class="methodname">DB-&gt;get()</tt>
to return the first record that matches the provided key and data.
</p>
<p>
If the specified key and/or data does not exist in the database, this
method returns <tt class="literal">DB_NOTFOUND</tt>.
</p>
<a id="c_dbt4"></a>
<pre class="programlisting">#include &lt;db.h&gt;
#include &lt;string.h&gt;
...
DBT key, data;
DB *my_database;
float money;
char description[DESCRIPTION_SIZE + 1];
/* Database open omitted for clarity */
money = 122.45;
/* Zero out the DBTs before using them. */
memset(&amp;key, 0, sizeof(DBT));
memset(&amp;data, 0, sizeof(DBT));
key.data = &amp;money;
key.size = sizeof(float);
data.data = description;
data.ulen = DESCRIPTION_SIZE + 1;
data.flags = DB_DBT_USERMEM;
my_database-&gt;get(my_database, NULL, &amp;key, &amp;data, 0);
/*
* Description is set into the memory that we supplied.
*/ </pre>
<p>
Note that in this example, the
<tt class="literal">data.size</tt>
field would be automatically set to the size of the retrieved data.
</p>
</div>
<div class="sect2" lang="en" xml:lang="en">
<div class="titlepage">
<div>
<div>
<h3 class="title"><a id="recordDelete"></a>Deleting Records</h3>
</div>
</div>
<div></div>
</div>
<p>
You can use the
<tt class="methodname">DB-&gt;del()</tt>
method to delete a record from the database. If your database supports
duplicate records, then all records associated with the provided key are
deleted. To delete just one record from a list of duplicates, use a
cursor. Cursors are described in <a href="Cursors.html">Using Cursors</a>.
</p>
<p>
You can also delete every record in the database by using
<tt class="methodname">DB-&gt;truncate().</tt>
</p>
<p>For example:</p>
<a id="c_dbt5"></a>
<pre class="programlisting">#include &lt;db.h&gt;
#include &lt;string.h&gt;
...
DBT key;
DB *my_database;
float money = 122.45;
/* Database open omitted for clarity */
/* Zero out the DBTs before using them. */
memset(&amp;key, 0, sizeof(DBT));
key.data = &amp;money;
key.size = sizeof(float);
my_database-&gt;del(my_database, NULL, &amp;key, 0);</pre>
</div>
<div class="sect2" lang="en" xml:lang="en">
<div class="titlepage">
<div>
<div>
<h3 class="title"><a id="datapersist"></a>Data Persistence</h3>
</div>
</div>
<div></div>
</div>
<p>
When you perform a database modification, your modification is made
in the in-memory cache. This means that your data modifications
are not necessarily flushed to disk, and so your data may not appear
in the database after an application restart.
</p>
<p>
Note that as a normal part of closing a database, its cache is
written to disk. However, in the event of an application or system
failure, there is no guarantee that your databases will close
cleanly. In this event, it is possible for you to lose data. Under
extremely rare circumstances, it is also possible for you to
experience database corruption.
</p>
<p>
Therefore, if you care if your data is durable across system
failures, and to guard against the rare possibility of
database corruption, you should use transactions to protect your
database modifications. Every time you commit a transaction, DB
ensures that the data will not be lost due to application or
system failure. Transaction usage is described in the
<span>
<i class="citetitle">Berkeley DB Getting Started with Transaction Processing</i> guide.
</span>
</p>
<p>
If you do not want to use transactions, then the assumption is that
your data is of a nature that it need not exist the next time your
application starts. You may want this if, for example, you are using
DB to cache data relevant only to the current application
runtime.
</p>
<p>
If, however, you are not using transactions for some reason and you
still want some guarantee that your database modifications are
persistent, then you should periodically
<span>call <tt class="methodname">DB-&gt;sync()</tt>.</span>
Syncs cause any dirty entries in the in-memory cache and the
operating system's file cache to be written to disk. As
such, they are quite expensive and you should use them sparingly.
</p>
<p>
Remember that by default a sync is performed any time a non-transactional
database is closed cleanly. (You can override this behavior by
specifying
<tt class="literal">DB_NOSYNC</tt>
on the call to
<span><tt class="methodname">DB-&gt;close()</tt>.)</span>
That said, you can manually run a sync by calling
<tt class="methodname">DB-&gt;sync().</tt>
</p>
<div class="note" style="margin-left: 0.5in; margin-right: 0.5in;">
<h3 class="title">Note</h3>
<p>
If your application or system crashes and you are not using
transactions, then you should either discard and recreate your
databases, or verify them. You can verify a database using
<span>DB-&gt;verify().</span>
If your databases do not verify cleanly, use the
<span><b class="command">db_dump</b></span> command to salvage as much of the
database as is possible. Use either the <tt class="literal">-R</tt> or
<tt class="literal">-r</tt> command line options to control how
aggressive <span><b class="command">db_dump</b></span> should be when salvaging
your databases.
</p>
</div>
</div>
</div>
<div class="navfooter">
<hr />
<table width="100%" summary="Navigation footer">
<tr>
<td width="40%" align="left"><a accesskey="p" href="DBEntry.html">Prev</a> </td>
<td width="20%" align="center">
<a accesskey="u" href="DBEntry.html">Up</a>
</td>
<td width="40%" align="right"> <a accesskey="n" href="cstructs.html">Next</a></td>
</tr>
<tr>
<td width="40%" align="left" valign="top">Chapter 3. Database Records </td>
<td width="20%" align="center">
<a accesskey="h" href="index.html">Home</a>
</td>
<td width="40%" align="right" valign="top"> Using C Structures with DB</td>
</tr>
</table>
</div>
</body>
</html>