1
0
mirror of https://github.com/MariaDB/server.git synced 2025-07-29 05:21:33 +03:00

merge fix

This commit is contained in:
Sinisa@sinisa.nasamreza.org
2003-02-22 17:14:50 +02:00
183 changed files with 1768 additions and 12156 deletions

View File

@ -8,6 +8,6 @@ c_warnings="$c_warnings $debug_extra_warnings"
cxx_warnings="$cxx_warnings $debug_extra_warnings"
extra_configs="$pentium_configs $debug_configs"
extra_configs="$extra_configs --with-debug=full --with-vio --with-openssl --without-innodb"
extra_configs="$extra_configs --with-debug=full --with-openssl"
. "$path/FINISH.sh"

View File

@ -18,6 +18,7 @@ bk@admin.bk
davida@isil.mysql.com
gluh@gluh.(none)
gluh@gluh.mysql.r18.ru
guilhem@mysql.com
gweir@work.mysql.com
heikki@donna.mysql.fi
heikki@hundin.mysql.fi

View File

@ -53,6 +53,8 @@ This is a manual about @strong{MySQL} internals.
* caching:: How MySQL Handles Caching
* flush tables:: How MySQL Handles @code{FLUSH TABLES}
* filesort:: How MySQL Does Sorting (@code{filesort})
* selects:: How MySQL performs different selects
* transformations:: How MySQL transforms subqueries
* coding guidelines:: Coding Guidelines
* mysys functions:: Functions In The @code{mysys} Library
* DBUG:: DBUG Tags To Use
@ -220,7 +222,7 @@ After this it will give other threads a chance to open the same tables.
@end itemize
@node filesort, coding guidelines, flush tables, Top
@node filesort, selects, flush tables, Top
@chapter How MySQL Does Sorting (@code{filesort})
@itemize @bullet
@ -260,8 +262,584 @@ and then we read the rows in the sorted order into a row buffer
@end itemize
@node selects, transformations, flush tables, Top
@chapter How MySQL performs different selects
@node coding guidelines, mysys functions, filesort, Top
@node select steps,,,
@section Steps of select executing
Every select performed in such base steps:
@itemize
@item
JOIN::prepare
@itemize @bullet
@item
initialization and linking JOIN structure to st_select_lex
@item
fix_fields() for all items (after fix_fields we know everything
about item)
@item
moving HAVING to WHERE if possible
@item
initialization procedure if exists
@end itemize
@item
JOIN::optimize
@itemize @bullet
@item
single select optimization
@item
creation first temporary table if need
@end itemize
@item
JOIN::exec
@itemize @bullet
@item
performing select (may be created second temporary table)
@end itemize
@item
JOIN::cleanup
@itemize @bullet
@item
removing all temporary tables, other cleanup
@end itemize
@item
JOIN::reinit
@itemize @bullet
@item
prepare all structures to SELECT executing (with JOIN::exec)
@end itemize
@end itemize
@node select select_result
@section select_result CLASS
Very important role in SELECT performing have select_result class and
classes inherited from it (usually called with "select_" prefix). This
class provide interface for results transmitting.
Key methods in this class are following:
@itemize @bullet
@item
@strong{send_fields} sends giving item list headers (type, name, etc..)
@item
@strong{send_data} sends giving item list values as row of table of result
@item
@strong{send_error} send error to used used mainly for error interception,
making some operation and then ::send_error will be called.
@end itemize
For example there are fillowing select_result classes:
@itemize
@item
@strong{select_send} used for sending results though network layer
@item
@strong{select_export} used for exporting data to file
@item
@strong{multi_delete} used for multi-delete
@item
@strong{select_insert} used for INSERT ... SELECT ...
@item
@strong{multi_update} used for multi-update
@end itemize
@node select simple
@section SIMPLE or PRIMARY SELECT.
For performing single primary select SELECT used function mysql_select,
which:
@itemize @bullet
@item
allocate JOIN;
@item
JOIN::prepare;
@item
JOIN::optimize;
@item
JOIN::exec;
@item
JOIN::cleanup.
@end itemize
In previous versions of mysql all SELECTs was performed with help of this
function and mysql_select() was not divided on parts.
@node select structure
@section Structure Of Complex Select
There 2 structures which describe SELECTS:
@itemize @bullet
@item
st_select_lex (SELECT_LEX) it represent SELECT itself
@item
st_select_lex_unit (SELECT_LEX_UNIT) group several selects in bunch
@end itemize
and represent UNION operation (absence of UNION is union
with 1 SELECT and this structure present in any case). In future this
structure will be used for EXCEPT and INTERSECT.
For example:
@example
(SELECT ... )UNION(SELECT ... (SELECT...)...(SELECT...UNION...SELECT))
1 2 3 4 5 6 7
@end example
will be represent as
@example
------------------------------------------------------------------------
level 1
SELECT_LEX_UNIT(2)
|
+---------------+
| |
SELECT_LEX(1) SELECT_LEX(3)
|
--------------- | ------------------------------------------------------
| level 2
+-------------------+
| |
SELECT_LEX_UNIT(4) SELECT_LEX_UNIT(6)
| |
| +--------------+
| | |
SELECT_LEX(4) SELECT_LEX(5) SELECT_LEX(7)
------------------------------------------------------------------------
@end example
Note: single subselect 4 have it's own SELECT_LEX_UNIT.
Most upper SELECT_LEX_UNIT (#2 in example) stored in LEX.
First and most upper SELECT_LEX (#1 in example) stored in LEX, too.
This two structures always exist.
In time of creating or performing any JOIN::* operation
LEX::current_select point on appropriate SELECT_LEX.
Only during parsing global (for whole UNION) ORDER_BY & LIMIT clauses
LEX::current_select points to SELECT_LEX_UNIT of this unit to store this
parameter in this SELECT_LEX_UNIT (SELECT_LEX and SELECT_LEX_UNIT are
inherited from st_select_lex_node).
@node select union
@section Non-Subselect UNIONs Executing
Non subselect unions performed with help of mysql_union(). for now it
divided on following steps:
@itemize
@item
st_select_lex_unit::prepare
@itemize @bullet
@item
create temporary table for union results storing (if UNION witout
ALL option, 'distinct' parameter will be passed to table creation
procedure). Types/lengths of table's fields will be determinated
by first SELECT item list.
@item
create select_union (inherited from select_result) which will
write selects results in this temporary table
@item
allocate JOIN and perform JOIN::prepare for all SELECTs belonged
to UNION
@end itemize
@item
st_select_lex_unit::exec
@itemize @bullet
@item
delete rows from temporary table if it is not first call
@item
if first call call JOIN::optimize else JOIN::reinit and then
JOIN::exec for all SELECTs (select_union will write result for
temporary table). If union is cacheable and this method called
second, (third, ...) time it will do nothing.
@item
call mysql_select on temporary table with global ORDER BY and
LIMIT parameters after collecting results from all SELECTs.
@end itemize
@end itemize
As far as mysql_select need SELECT_LEX structure SELECT_LEX of first
SELECT of this UNION will be passed to it, but also fake_select_lex
parameter will be passed to mysql_select() too, to prevent linking
this SELECT_LEX with JOIN on this mysql_select() session.
PROBLEM: this fake select need workaround in many places.
@node select derived
@section Derived Tables Executing
Derived tables processing is first operation on any query. It performed
before creation list of tables of whole query and opening/locking this
tables.
If lex->derived_tables flag present will be scanned all SELECT_LEX (there
are list of all SELECT_LEX in reverse order (first SELECT in query will
be last in this list) lex->all_selects_list).
Pointer on derived table SELECT_LEX_UNIT stored in TABLE_LIST structure
(TABLE_LIST::derived). And for any table which have this pointer will
be called mysql_derived().
mysql_derived():
@itemize @bullet
@item
Creates list of all tables used in this query, opens and locks it
@item
Creates temporary table for storing results
@item
Creates union_result for writing result in this table
@item
Calls mysql_select or mysql_union for execute query
@item
Removes all derived table subtree from SELECTs tree (if it is
not EXPLAIN)
@item
Stores pointer to this temporary table in TABLE_LIST structure, then
this table will be used by outer query. This table table will not be
skipped in checking grants, because tables from which this table was
received was checked in mysql_derived.
@item
Links this temporary table in thd->derived_tables for removing after
query executing. this table will be closed in close_thread_tables if
second parameter of it (bool skip_derived) will be true.
@end itemize
@node select subselect
@section Subselects
In expression subselect represented by Item inherited from Item_subselect.
To hide difference in performing single SELECTs and UNIONs
Item_subselect use two different engines, which provide uniformed
interface for access to underplaid SELECT or UNION
(subselect_single_select_engine and subselect_union_engine, both are
inherited from subselect_engine).
Engine will be created in time of Item_select constructing
(Item_subselect::init method).
On Item_subselect::fix_fields() will be called engine->prepare().
Before calling any value getting method (val, val_int, val_str,
bring_value (in case of row result)) will be called engine->exec(),
which execute query or just do nothing if subselect is cacheable and
already executed.
Items inherited from provide it's own select_result classes. There are
2 type of it:
@itemize @bullet
@item
select_singlerow_subselect it store values of giving row in
Item_singlerow_subselect cache on send_data() call and report error
if Item_subselect have 'assigned' attribute.
@item
select_exists_subselect just store 1 as value of
Item_exists_subselect on send_data() call. As far as
Item_in_subselect and Item_allany_subselect inherited from
Item_exists_subselect, they use same select_result class.
@end itemize
Item_select will never call cleanup() procedure for JOIN. Every
JOIN::cleanup will call cleanup() for inner JOINs. Most upper
JOIN::cleanup will be called by mysql_select() or mysql_union().
@node select select engine
@section Single Select Engine
subselect_single_select_engine:
@itemize @bullet
@item
@strong{constructor} allocate JOIN and store pointers on SELECT_LEX and JOIN
@item
@strong{prepare()} call JOIN::prepare
@item
@strong{fix_length_and_dec()} prepare cache and receive type and
parameters of returning items (it called only by
Item_singlerow_subselect)
@item
@strong{exec()} drop 'assigned flag of Item_subselect. If called first time
JOIN::optimize and JOINexec(), else do nothing or JOIN::reinit()
JOIN::exec() depending of type of subquery.
@end itemize
@node select union engine
@section Union Engine
subselect_union_engine:
@itemize @bullet
@item
@strong{constructor} just store pointer to st_select_lex_union
(SELECT_LEX_UNION)
@item
@strong{prepare()} call st_select_lex_unit::prepare
@item
@strong{fix_length_and_dec()} prepare cache and receive type and
parameters (maximum of length) of returning items (it called
only by Item_singlerow_subselect)
@item
@strong{exec()} call st_select_lex_unit::exec(). st_select_lex_unit::exec()
can drop 'assigned' flag of Item_subselect if
st_select_lex_unit::item is not 0.
@end itemize
@node selectexplain
@section Explain Execution
For EXPLAIN result showing for every SELECT will be called mysql_select
with option SELECT_DESCRIBE.
For main UNION will be called mysql_explain_union.
mysql_explain_union call mysql_explain_select for every SELECT in given
union.
mysql_explain_select call mysql_select with SELECT_DESCRIBE.
mysql_select create JOIN for select (if it not exists, because if it
called for subselect JOIN can be created in JOIN::optimize of outer
query when it decided to calculate value of subselect). Then it call
JOIN::prepare, JOIN::optimize, JOIN exec and JOIN::cleanup as usual.
JOIN::exec called for SELECT with SELECT_DESCRIBE option call
select_describe.
select_describe return to user description of SELECT and call
mysql_explain_union for every inner UNION
PROBLEM: how it will work with global query optimization?
@node transformations, coding guidelines, selects, Top
@chapter How MySQL transforms subqueries
Item_subselect virtual method select_transformer is used to rewrite
subqueries. It is called from Item_subselect::init (which called in
Item_subselect constructor)
@node transformation IN
@section Item_in_subselect::select_transformer
Item_in_subselect::select_transformer is divided on two parts for
scalar left part and row left part:
@node transformation scalar IN
@subsection Scalar IN Subselect
To rewrite scalar IN subselect used method
Item_in_subselect::single_value_transformer, Scalar IN subselect will
be replaced with Item_in_optimizer.
Item_in_optimizer item is special boolean function. On value request
(one of val, val_int or val_str methods) it evaluate left expression of
IN by storing it value in cache item (one of Item_cache* items), then it
test cache is it NULL. If left expression (cache) is NULL then
Item_in_optimizer return NULL, else it evaluate Item_in_subselect.
Example queries.
@example
a) SELECT * from t1 where t1.a in (SELECT t2.a FROM t2);
b) SELECT * from t1 where t1.a in (SELECT t2.a FROM t2 GROUP BY t2.a);
@end example
@itemize
@item
Item_in_subselect inherit mechanism of getting value from
Item_exists_subselect.
@item
Select_transformer stores reference to left expression in its
conditions: (in WHERE in case 'a' and in a HAVING in case 'b')
@item
Item from item list of this select (t2.a) can be referred with special
reference (Item_ref_null_helper or Item_asterisk_remover).
This reference informs Item_in_optimizer if item (t2.a) is NULL by
setting the 'was_null' flag.
@item
The return value from Item_in_subselect will be evaluated as following:
@itemize @bullet
@item
If TRUE return true
@item
If NULL return null
@item
If FALSE and 'was_null' is set, return null
@item
return FALSE
@end itemize
@end itemize
<left_expression> IN (SELECT <item> ...) will be represented like
following:
@example
+-----------------+
|Item_in_optimizer|
+-----------------+
|
+---------------------+------------+
| |
+-----------------------+ +-----------------+
| <left_expression> | |Item_in_subselect|
| | +-----------------+
+-----------------------+ |
|<left_expression cache>| +-----------+-----------+
| | | |
+-----------------------+ | |
^ +----------+ +--------------------+
+<<<<<<<<<<<<<<<<<| Item_ref | +<<<|Item_ref_null_helper|
+----------+ V +--------------------+
V +--------------------+
+>>>| <item> |
+--------------------+
@end example
where '<<<<<<<<<' is reference in meaning of Item_ref.
Item_ref used for point to <left_expression cache>, because in time of
transformation we know only address of variable where pointer on cache
will be stored.
If select have ORDER BY clause it will be wiped out, because no sense in
ORDER BY without LIMIT here.
If IN subselect union condition of every select in UNION will be changed
personally.
Following is examples of IN transformations:
@example
a) <left_expression> IN (SELECT <item> FROM t
WHERE <where_exp>)
will be represented as
(SELECT 1 FROM t
WHERE <where_exp> and
Item_ref(<cached_left_expression>)=<Item_asterisk_remover(<Item>)>)
b) <left_expression> IN (SELECT <item> FROM t
HAVING <having_expr>
ORDER BY 1)
will be represented as
(SELECT <item> as ref_null_helper FROM t
HAVING <having_exp> AND
Item_ref(<cached_left_expression>) = ref_null_helper)
c) <left_expression> IN (SELECT <item> UNION ...)
will be represented as
(SELECT 1
HAVING Item_ref(<cached_left_expression>)=
<Item_asterisk_remover(<Item>)>
UNION ...)
(having without FROM is syntax error, but having condition is checked
even for subselect without FROM)
d) <left_expression> IN (select <item>)
will be completely replaced with <left_expression> = <item>
@end example
Now conditions (WHERE (a) or HAVING (b)) will be changed depends of
select in following way:
If subselect have HAVING , sum function or GROUP BY (case a) then item
list will be unchanged and Item_ref_null_helper reference will be
created on item list element. Condition will be added to HAVING condition.
If subselect have not HAVING, sum function or GROUP BY (case b) then:
@itemize @bullet
@item
@strong{item list} will be replaced with 1.
@item
@strong{<item>} from item list will be stored in Item_asterisk_remover, which
inherit from Item_ref_null_helper, but store item on which refer by
itself, and also it can resolve '*' item.
@item
@strong{<left_expression cache> = <Item_ref_null_helper>} will be added to
WHERE clause this item or to HAVING clause if this subselect have
no FROM clause and subselect is union (case c).
@end itemize
Single select without FROM will be reduced to just
<left_expression> = <item> without using Item_in_optimizer.
@node transformations row IN
@subsection Row IN Subselect
To rewrite row IN subselect used method
Item_in_subselect::row_value_transformer. It work in almost same way as
scalar analog, but work with Item_cache_row for caching left expression
and use references on elements of Item_cache_row.
To refer on item list it use Item_ref_on_list_position.
Item_ref_on_list_position::fix_fields will find item in item list of
subselect by number and create Item_ref_null_helper to refer on it. It
used to find reference when all '*' items will be translated in item
list. Subselect with have HAVING, sum functions or GROUP BY will
transformed in following way:
@example
ROW(l1, l2, ... lN) IN (SELECT i1, i2, ... iM FROM t HAVING <having_expr>)
will be following:
(SELECT i1, i2, ... iM FROM t
HAVING <having_expr> and
<cache_l1> = <ref_on_list_position(1)> AND
<cache_l2> = <ref_on_list_position(2)> AND
...
<cache_lN> = <ref_on_list_position(N)>)
@end example
In this way will be transformed select without FROM, too.
For other subselect it will be same but for WHERE clause.
@node transformations all any
@section Item_allany_subselect
Item_allany_subselect is inherited from Item_in_subselect.
ALL/ANY/SOME use same algorithm (and same method of Item_in_subselect)
as scalar IN, but use different function instead of '='.
ANY/SOME use same function that was listed after left expression.
ALL use inverted function, and all subselect passed as argument to
Item_func_not.
@node transformations singlerow
@section Item_singlerow_subselect
Item_singlerow_subselect will be rewritten only if it have not FROM
clause, it is not part of UNION and it is scalar subselect. For now will
not be converted subselects with field or reference on top of item list
(we can't change name of such items from one hand, but from other hand
we should assign to it name of whole subselect which will be reduced);
Following will not be reduced:
@example
SELECT a;
SELECT 1 UNION SELECT 2;
SELECT 1 FROM t1;
@end example
Following select will be reduced:
@example
SELECT 1;
SELECT a+2;
@end example
Such subselect will be completely replaced by its expression from item
list and its SELECT_LEX and SELECT_LEX_UNIT will be removed from
SELECT_LEX's tree.
But all Item_fields and Item_ref of that expression will be marked for
special fix_fields() procedure. fix_fields() for such Item will be
performed is same way as for items of inner subselect. Also if this
expression is Item_fields or Item_ref then name of this new item will
be same as name of this item (but not '(SELECT ...)'). It is done to
prevent broke references on such items from more inner subselects.
@node coding guidelines, mysys functions, transformations, Top
@chapter Coding Guidelines
@itemize @bullet
@ -1836,7 +2414,7 @@ able to provide the optimal information for all parameters.
If number of columns, in the header packet, is not 0 then the
prepared statement will contain a result set. In this case the packet
is followed by a field description result set. @xref{4.1 field descr}.
is followed by a field description result set. @xref{4.1 field desc}.
@node 4.1 long data,,,

View File

@ -25,15 +25,15 @@ SUBDIRS = . include @docs_dirs@ \
@readline_topdir@ @readline_dir@ \
@thread_dirs@ pstack @sql_client_dirs@ \
@sql_server_dirs@ scripts man tests \
BUILD netware os2 @libmysqld_dirs@ \
@bench_dirs@ support-files @fs_dirs@ @tools_dirs@ \
@platform_dir@
BUILD @netware_dir@ os2 @libmysqld_dirs@ \
@bench_dirs@ support-files @fs_dirs@ @tools_dirs@
# Relink after clean
linked_sources = linked_client_sources linked_server_sources \
linked_libmysql_sources linked_libmysql_r_sources \
linked_libmysqld_sources linked_libmysqldex_sources \
linked_include_sources
linked_include_sources @linked_netware_sources@
CLEANFILES = $(linked_sources)
@ -64,6 +64,10 @@ linked_libmysqldex_sources:
cd libmysqld/examples; $(MAKE) link_sources
echo timestamp > linked_libmysqldex_sources
linked_netware_sources:
cd @netware_dir@; $(MAKE) link_sources
echo timestamp > linked_netware_sources
#avoid recursive make calls in sql directory
linked_server_sources:
cd sql; rm -f mini_client_errors.c;@LN_CP_F@ ../libmysql/errmsg.c mini_client_errors.c
@ -74,7 +78,7 @@ init-db: all
$(top_builddir)/scripts/mysql_install_db
bin-dist: all
$(top_builddir)/scripts/make_binary_distribution
$(top_builddir)/scripts/make_binary_distribution @MAKE_BINARY_DISTRIBUTION_OPTIONS@
# Remove BK's "SCCS" subdirectories from source distribution
dist-hook:
@ -88,3 +92,4 @@ tags:
test:
cd mysql-test ; ./mysql-test-run

View File

@ -128,6 +128,10 @@ SOURCE="..\strings\ctype-euc_kr.c"
# End Source File
# Begin Source File
SOURCE="..\strings\ctype-extra.c"
# End Source File
# Begin Source File
SOURCE="..\strings\ctype-gb2312.c"
# End Source File
# Begin Source File
@ -136,10 +140,18 @@ SOURCE="..\strings\ctype-gbk.c"
# End Source File
# Begin Source File
SOURCE="..\strings\ctype-latin1.c"
# End Source File
# Begin Source File
SOURCE="..\strings\ctype-latin1_de.c"
# End Source File
# Begin Source File
SOURCE="..\strings\ctype-mb.c"
# End Source File
# Begin Source File
SOURCE="..\strings\ctype-simple.c"
# End Source File
# Begin Source File

View File

@ -139,6 +139,10 @@ SOURCE="..\strings\ctype-euc_kr.c"
# End Source File
# Begin Source File
SOURCE="..\strings\ctype-extra.c"
# End Source File
# Begin Source File
SOURCE="..\strings\ctype-gb2312.c"
# End Source File
# Begin Source File
@ -147,10 +151,18 @@ SOURCE="..\strings\ctype-gbk.c"
# End Source File
# Begin Source File
SOURCE="..\strings\ctype-latin1.c"
# End Source File
# Begin Source File
SOURCE="..\strings\ctype-latin1_de.c"
# End Source File
# Begin Source File
SOURCE="..\strings\ctype-mb.c"
# End Source File
# Begin Source File
SOURCE="..\strings\ctype-simple.c"
# End Source File
# Begin Source File
@ -260,7 +272,6 @@ SOURCE=..\mysys\my_alloc.c
# Begin Source File
SOURCE=..\mysys\my_compress.c
# ADD CPP /I "../zlib"
# End Source File
# Begin Source File
@ -360,7 +371,7 @@ SOURCE=..\mysys\my_thr_init.c
# End Source File
# Begin Source File
SOURCE=..\mysys\my_vsnprintf.c
SOURCE=..\strings\my_vsnprintf.c
# End Source File
# Begin Source File
@ -478,5 +489,9 @@ SOURCE=..\vio\viossl.c
SOURCE=..\vio\viosslfactories.c
# End Source File
# Begin Source File
SOURCE=..\strings\xml.c
# End Source File
# End Target
# End Project

View File

@ -52,7 +52,7 @@ BSC32=bscmake.exe
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib Wsock32.lib ..\lib_release\myisam.lib ..\lib_release\myisammrg.lib ..\lib_release\mysys.lib ..\lib_release\strings.lib ..\lib_release\regex.lib ..\lib_release\heap.lib ..\lib_release\innodb.lib ..\lib_release\bdb.lib ..\lib_release\zlib.lib # SUBTRACT LINK32 /nologo /dll /pdb:none /machine:I386 /out:"../lib_release/libmysqld.dll" /implib:"../lib_release/libmysqld.lib"
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib Wsock32.lib ..\lib_release\myisam.lib ..\lib_release\myisammrg.lib ..\lib_release\mysys.lib ..\lib_release\strings.lib ..\lib_release\regex.lib ..\lib_release\heap.lib ..\lib_release\innodb.lib ..\lib_release\bdb.lib ..\lib_release\zlib.lib /nologo /dll /pdb:none /machine:I386 /out:"../lib_release/libmysqld.dll" /implib:"../lib_release/libmysqld.lib"
!ELSEIF "$(CFG)" == "libmysqld - Win32 Debug"
@ -77,7 +77,7 @@ BSC32=bscmake.exe
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib Wsock32.lib ..\lib_debug\dbug.lib ..\lib_debug\mysys.lib ..\lib_debug\strings.lib ..\lib_debug\regex.lib ..\lib_debug\heap.lib ..\lib_debug\innodb.lib # SUBTRACT LINK32 /nologo /dll /pdb:none /debug /machine:I386 /nodefaultlib:"LIBCMTD" /out:"../lib_debug/libmysqld.dll" /implib:"../lib_debug/libmysqld.lib"
# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib Wsock32.lib ..\lib_debug\dbug.lib ..\lib_debug\mysys.lib ..\lib_debug\strings.lib ..\lib_debug\regex.lib ..\lib_debug\heap.lib ..\lib_debug\innodb.lib /nologo /dll /pdb:none /debug /machine:I386 /nodefaultlib:"LIBCMTD" /out:"../lib_debug/libmysqld.dll" /implib:"../lib_debug/libmysqld.lib"
!ENDIF
@ -180,6 +180,10 @@ SOURCE=..\sql\item_func.cpp
# End Source File
# Begin Source File
SOURCE=.\item_row.cpp
# End Source File
# Begin Source File
SOURCE=..\sql\item_strfunc.cpp
# End Source File
# Begin Source File
@ -236,10 +240,6 @@ SOURCE=..\sql\mini_client.cpp
# End Source File
# Begin Source File
SOURCE=..\sql\net_pkg.cpp
# End Source File
# Begin Source File
SOURCE=..\sql\net_serv.cpp
# End Source File
# Begin Source File
@ -264,6 +264,10 @@ SOURCE=..\sql\procedure.cpp
# End Source File
# Begin Source File
SOURCE=.\protocol.cpp
# End Source File
# Begin Source File
SOURCE=..\sql\records.cpp
# End Source File
# Begin Source File
@ -328,6 +332,10 @@ SOURCE=..\sql\sql_handler.cpp
# End Source File
# Begin Source File
SOURCE=.\sql_help.cpp
# End Source File
# Begin Source File
SOURCE=..\sql\sql_insert.cpp
# End Source File
# Begin Source File

View File

@ -142,6 +142,10 @@ SOURCE=.\myrg_rnext.c
# End Source File
# Begin Source File
SOURCE=.\myrg_rnext_same.c
# End Source File
# Begin Source File
SOURCE=.\myrg_rprev.c
# End Source File
# Begin Source File

View File

@ -101,10 +101,34 @@ SOURCE=.\ChildFrm.cpp
# End Source File
# Begin Source File
SOURCE="..\strings\ctype-extra.c"
# End Source File
# Begin Source File
SOURCE="..\strings\ctype-latin1.c"
# End Source File
# Begin Source File
SOURCE="..\strings\ctype-mb.c"
# End Source File
# Begin Source File
SOURCE=..\strings\is_prefix.c
# End Source File
# Begin Source File
SOURCE=.\MainFrm.cpp
# End Source File
# Begin Source File
SOURCE=..\mysys\my_sleep.c
# End Source File
# Begin Source File
SOURCE=..\strings\my_vsnprintf.c
# End Source File
# Begin Source File
SOURCE=.\MySqlManager.cpp
# End Source File
# Begin Source File

View File

@ -410,6 +410,10 @@ SOURCE=.\my_seek.c
# End Source File
# Begin Source File
SOURCE=.\my_sleep.c
# End Source File
# Begin Source File
SOURCE=.\my_static.c
# End Source File
# Begin Source File

View File

@ -104,6 +104,10 @@ SOURCE=.\bmove512.c
# End Source File
# Begin Source File
SOURCE=.\bmove_upp.c
# End Source File
# Begin Source File
SOURCE=".\ctype-big5.c"
# End Source File
# Begin Source File
@ -120,6 +124,10 @@ SOURCE=".\ctype-euc_kr.c"
# End Source File
# Begin Source File
SOURCE=".\ctype-extra.c"
# End Source File
# Begin Source File
SOURCE=".\ctype-gb2312.c"
# End Source File
# Begin Source File
@ -128,6 +136,10 @@ SOURCE=".\ctype-gbk.c"
# End Source File
# Begin Source File
SOURCE=".\ctype-latin1.c"
# End Source File
# Begin Source File
SOURCE=".\ctype-latin1_de.c"
# End Source File
# Begin Source File
@ -168,6 +180,10 @@ SOURCE=.\int2str.c
# End Source File
# Begin Source File
SOURCE=.\is_prefix.c
# End Source File
# Begin Source File
SOURCE=.\llstr.c
# End Source File
# Begin Source File
@ -188,34 +204,27 @@ SOURCE=.\str2int.c
# End Source File
# Begin Source File
SOURCE=.\Strings.asm
SOURCE=.\strcend.c
# End Source File
# Begin Source File
!IF "$(CFG)" == "strings - Win32 Release"
SOURCE=.\strend.c
# End Source File
# Begin Source File
# Begin Custom Build
OutDir=.\release
InputPath=.\Strings.asm
InputName=Strings
SOURCE=.\strfill.c
# End Source File
# Begin Source File
"$(OutDir)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
ml /Cx /nologo /DDOS386 /DM_I386 /Zm /coff /c /Fo $(Outdir)\$(InputName).obj $(InputPath)
SOURCE=.\strmake.c
# End Source File
# Begin Source File
# End Custom Build
!ELSEIF "$(CFG)" == "strings - Win32 Debug"
# Begin Custom Build
OutDir=.\debug
InputPath=.\Strings.asm
InputName=Strings
"$(OutDir)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
ml /Cx /nologo /DDOS386 /DM_I386 /Zm /coff /c /Fo $(Outdir)\$(InputName).obj $(InputPath)
# End Custom Build
!ENDIF
SOURCE=.\strmov.c
# End Source File
# Begin Source File
SOURCE=.\strnmov.c
# End Source File
# Begin Source File
@ -235,34 +244,7 @@ SOURCE=.\strtoull.c
# End Source File
# Begin Source File
SOURCE=.\Strxmov.asm
!IF "$(CFG)" == "strings - Win32 Release"
# Begin Custom Build
OutDir=.\release
InputPath=.\Strxmov.asm
InputName=Strxmov
"$(OutDir)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
ml /Cx /nologo /DDOS386 /DM_I386 /Zm /coff /c /Fo $(Outdir)\$(InputName).obj $(InputPath)
# End Custom Build
!ELSEIF "$(CFG)" == "strings - Win32 Debug"
# Begin Custom Build
OutDir=.\debug
InputPath=.\Strxmov.asm
InputName=Strxmov
"$(OutDir)\$(InputName).obj" : $(SOURCE) "$(INTDIR)" "$(OUTDIR)"
ml /Cx /nologo /DDOS386 /DM_I386 /Zm /coff /c /Fo $(Outdir)\$(InputName).obj $(InputPath)
# End Custom Build
!ENDIF
SOURCE=.\strxmov.c
# End Source File
# Begin Source File

2
bdb/dist/s_include vendored
View File

@ -71,7 +71,7 @@ head defonly _DB_INT_DEF_IN_ > $i_dfile
# Process the standard directories, creating per-directory prototype
# files and adding to the external prototype and #define files.
for i in db btree clib common crypto dbreg env fileops hash hmac \
for i in db btree clib common dbreg env fileops hash hmac \
lock log mp mutex os qam rep rpc_client rpc_server tcl txn xa; do
head "_${i}_ext_h_" > $i_pfile

2
bdb/dist/s_recover vendored
View File

@ -66,4 +66,4 @@ for i in db dbreg btree fileops hash qam txn; do
done
# Build the example application's recovery routines.
(cd ../examples_c/ex_apprec && sh auto_rebuild)
#(cd ../examples_c/ex_apprec && sh auto_rebuild)

8
bdb/dist/s_symlink vendored
View File

@ -14,7 +14,7 @@ build btree/tags ../dist/tags
build build_unix/tags ../dist/tags
build clib/tags ../dist/tags
build common/tags ../dist/tags
build crypto/tags ../dist/tags
#build crypto/tags ../dist/tags
build cxx/tags ../dist/tags
build db/tags ../dist/tags
build db185/tags ../dist/tags
@ -34,9 +34,9 @@ build dbinc_auto/tags ../dist/tags
build dbm/tags ../dist/tags
build dbreg/tags ../dist/tags
build env/tags ../dist/tags
build examples_c/tags ../dist/tags
build examples_cxx/tags ../dist/tags
build examples_java java/src/com/sleepycat/examples
#build examples_c/tags ../dist/tags
#build examples_cxx/tags ../dist/tags
#build examples_java java/src/com/sleepycat/examples
build fileops/tags ../dist/tags
build hash/tags ../dist/tags
build hmac/tags ../dist/tags

View File

@ -1,29 +0,0 @@
# $Id: README,v 11.5 2002/02/26 16:22:45 krinsky Exp $
ex_access.c Using just the DB access methods.
ex_apprec Application-specific recovery.
ex_btrec.c Using the BTREE access method with record numbers.
ex_env.c Setting up the DB environment.
ex_lock.c Locking.
ex_mpool.c Shared memory buffer pools.
ex_repquote Replication. This creates a toy stock quote server
with DB's single-master, multiple-client replication,
with communication over TCP.
ex_tpcb.c TPC/B.
Ex_tpcb sets up a framework in which to run a TPC/B test.
Database initialization (the -i flag) and running the
benchmark (-n flag) must take place separately (i.e.,
first create the database, then run 1 or more copies of
the benchmark). Furthermore, when running more than one
TPCB process, it is necessary to run the deadlock detector
(db_deadlock), since it is possible for concurrent tpcb
processes to deadlock. For performance measurement, it
will also be beneficial to run the db_checkpoint process
as well.

View File

@ -1,382 +0,0 @@
/*-
* Copyright (c) 2001-2002
* Sleepycat Software. All rights reserved.
*
* $Id: bench_001.c,v 1.13 2002/08/15 02:45:39 bostic Exp $
*/
/*
* bench_001 - time bulk fetch interface.
* Without -R builds a btree acording to the arguments.
* With -R runs and times bulk fetches. If -d is specified
* during reads the DB_MULTIPLE interface is used
* otherwise the DB_MULTIPLE_KEY interface is used.
*
* ARGUMENTS:
* -c cachesize [1000 * pagesize]
* -d number of duplicates [none]
* -E don't use environment
* -I Just initialize the environment
* -i number of read iterations [1000000]
* -l length of data item [20]
* -n number of keys [1000000]
* -p pagesize [65536]
* -R perform read test.
* -T incorporate transactions.
*
* COMPILE:
* cc -I /usr/local/BerkeleyDB/include \
* -o bench_001 -O2 bench_001.c /usr/local/BerkeleyDB/lib/libdb.so
*/
#include <sys/types.h>
#include <sys/time.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <db.h>
#define DATABASE "bench_001.db"
int main(int, char *[]);
void usage(void);
const char
*progname = "bench_001"; /* Program name. */
/*
* db_init --
* Initialize the environment.
*/
DB_ENV *
db_init(home, prefix, cachesize, txn)
char *home, *prefix;
int cachesize, txn;
{
DB_ENV *dbenv;
int flags, ret;
if ((ret = db_env_create(&dbenv, 0)) != 0) {
dbenv->err(dbenv, ret, "db_env_create");
return (NULL);
}
dbenv->set_errfile(dbenv, stderr);
dbenv->set_errpfx(dbenv, prefix);
(void)dbenv->set_cachesize(dbenv, 0,
cachesize == 0 ? 50 * 1024 * 1024 : (u_int32_t)cachesize, 0);
flags = DB_CREATE | DB_INIT_MPOOL;
if (txn)
flags |= DB_INIT_TXN | DB_INIT_LOCK;
if ((ret = dbenv->open(dbenv, home, flags, 0)) != 0) {
dbenv->err(dbenv, ret, "DB_ENV->open: %s", home);
(void)dbenv->close(dbenv, 0);
return (NULL);
}
return (dbenv);
}
/*
* get -- loop getting batches of records.
*
*/
int
get(dbp, txn, datalen, num, dups, iter, countp)
DB *dbp;
int txn, datalen, num, dups, iter, *countp;
{
DBC *dbcp;
DBT key, data;
DB_TXN *txnp;
u_int32_t len, klen;
int count, flags, i, j, ret;
void *pointer, *dp, *kp;
memset(&key, 0, sizeof(key));
key.data = &j;
key.size = sizeof(j);
memset(&data, 0, sizeof(data));
data.flags = DB_DBT_USERMEM;
data.data = malloc(datalen*1024*1024);
data.ulen = data.size = datalen*1024*1024;
count = 0;
flags = DB_SET;
if (!dups)
flags |= DB_MULTIPLE_KEY;
else
flags |= DB_MULTIPLE;
for (i = 0; i < iter; i++) {
txnp = NULL;
if (txn)
dbp->dbenv->txn_begin(dbp->dbenv, NULL, &txnp, 0);
dbp->cursor(dbp, txnp, &dbcp, 0);
j = random() % num;
switch (ret = dbcp->c_get(dbcp, &key, &data, flags)) {
case 0:
break;
default:
dbp->err(dbcp->dbp, ret, "DBC->c_get");
return (ret);
}
DB_MULTIPLE_INIT(pointer, &data);
if (dups)
while (pointer != NULL) {
DB_MULTIPLE_NEXT(pointer, &data, dp, len);
if (dp != NULL)
count++;
}
else
while (pointer != NULL) {
DB_MULTIPLE_KEY_NEXT(pointer,
&data, kp, klen, dp, len);
if (kp != NULL)
count++;
}
dbcp->c_close(dbcp);
if (txn)
txnp->commit(txnp, 0);
}
*countp = count;
return (0);
}
/*
* fill - fill a db
* Since we open/created the db with transactions (potentially),
* we need to populate it with transactions. We'll bundle the puts
* 10 to a transaction.
*/
#define PUTS_PER_TXN 10
int
fill(dbenv, dbp, txn, datalen, num, dups)
DB_ENV *dbenv;
DB *dbp;
int txn, datalen, num, dups;
{
DBT key, data;
DB_TXN *txnp;
struct data {
int id;
char str[1];
} *data_val;
int count, i, ret;
/*
* Insert records into the database, where the key is the user
* input and the data is the user input in reverse order.
*/
txnp = NULL;
ret = 0;
count = 0;
memset(&key, 0, sizeof(DBT));
memset(&data, 0, sizeof(DBT));
key.data = &i;
key.size = sizeof(i);
data.data = data_val = (struct data *) malloc(datalen);
memcpy(data_val->str, "0123456789012345678901234567890123456789",
datalen - sizeof (data_val->id));
data.size = datalen;
data.flags = DB_DBT_USERMEM;
for (i = 0; i < num; i++) {
if (txn != 0 && i % PUTS_PER_TXN == 0) {
if (txnp != NULL) {
ret = txnp->commit(txnp, 0);
txnp = NULL;
if (ret != 0)
goto err;
}
if ((ret =
dbenv->txn_begin(dbenv, NULL, &txnp, 0)) != 0)
goto err;
}
data_val->id = 0;
do {
switch (ret =
dbp->put(dbp, txnp, &key, &data, 0)) {
case 0:
count++;
break;
default:
dbp->err(dbp, ret, "DB->put");
goto err;
}
} while (++data_val->id < dups);
}
if (txnp != NULL)
ret = txnp->commit(txnp, 0);
printf("%d\n", count);
return (ret);
err: if (txnp != NULL)
(void)txnp->abort(txnp);
return (ret);
}
int
main(argc, argv)
int argc;
char *argv[];
{
extern char *optarg;
extern int optind;
DB *dbp;
DB_ENV *dbenv;
DB_TXN *txnp;
struct timeval start_time, end_time;
double secs;
int cache, ch, count, datalen, dups, env, init, iter, num, pagesize;
int ret, rflag, txn;
txnp = NULL;
datalen = 20;
iter = num = 1000000;
env = 1;
dups = init = rflag = txn = 0;
pagesize = 65536;
cache = 1000 * pagesize;
while ((ch = getopt(argc, argv, "c:d:EIi:l:n:p:RT")) != EOF)
switch (ch) {
case 'c':
cache = atoi(optarg);
break;
case 'd':
dups = atoi(optarg);
break;
case 'E':
env = 0;
break;
case 'I':
init = 1;
break;
case 'i':
iter = atoi(optarg);
break;
case 'l':
datalen = atoi(optarg);
break;
case 'n':
num = atoi(optarg);
break;
case 'p':
pagesize = atoi(optarg);
break;
case 'R':
rflag = 1;
break;
case 'T':
txn = 1;
break;
case '?':
default:
usage();
}
argc -= optind;
argv += optind;
/* Remove the previous database. */
if (!rflag) {
if (env)
system("rm -rf BENCH_001; mkdir BENCH_001");
else
(void)unlink(DATABASE);
}
dbenv = NULL;
if (env == 1 &&
(dbenv = db_init("BENCH_001", "bench_001", cache, txn)) == NULL)
return (-1);
if (init)
exit(0);
/* Create and initialize database object, open the database. */
if ((ret = db_create(&dbp, dbenv, 0)) != 0) {
fprintf(stderr,
"%s: db_create: %s\n", progname, db_strerror(ret));
exit(EXIT_FAILURE);
}
dbp->set_errfile(dbp, stderr);
dbp->set_errpfx(dbp, progname);
if ((ret = dbp->set_pagesize(dbp, pagesize)) != 0) {
dbp->err(dbp, ret, "set_pagesize");
goto err1;
}
if (dups && (ret = dbp->set_flags(dbp, DB_DUP)) != 0) {
dbp->err(dbp, ret, "set_flags");
goto err1;
}
if (env == 0 && (ret = dbp->set_cachesize(dbp, 0, cache, 0)) != 0) {
dbp->err(dbp, ret, "set_cachesize");
goto err1;
}
if ((ret = dbp->set_flags(dbp, DB_DUP)) != 0) {
dbp->err(dbp, ret, "set_flags");
goto err1;
}
if (txn != 0)
if ((ret = dbenv->txn_begin(dbenv, NULL, &txnp, 0)) != 0)
goto err1;
if ((ret = dbp->open(
dbp, txnp, DATABASE, NULL, DB_BTREE, DB_CREATE, 0664)) != 0) {
dbp->err(dbp, ret, "%s: open", DATABASE);
if (txnp != NULL)
(void)txnp->abort(txnp);
goto err1;
}
if (txnp != NULL)
ret = txnp->commit(txnp, 0);
txnp = NULL;
if (ret != 0)
goto err1;
if (rflag) {
/* If no environment, fill the cache. */
if (!env && (ret =
get(dbp, txn, datalen, num, dups, iter, &count)) != 0)
goto err1;
/* Time the get loop. */
gettimeofday(&start_time, NULL);
if ((ret =
get(dbp, txn, datalen, num, dups, iter, &count)) != 0)
goto err1;
gettimeofday(&end_time, NULL);
secs =
(((double)end_time.tv_sec * 1000000 + end_time.tv_usec) -
((double)start_time.tv_sec * 1000000 + start_time.tv_usec))
/ 1000000;
printf("%d records read using %d batches in %.2f seconds: ",
count, iter, secs);
printf("%.0f records/second\n", (double)count / secs);
} else if ((ret = fill(dbenv, dbp, txn, datalen, num, dups)) != 0)
goto err1;
/* Close everything down. */
if ((ret = dbp->close(dbp, rflag ? DB_NOSYNC : 0)) != 0) {
fprintf(stderr,
"%s: DB->close: %s\n", progname, db_strerror(ret));
return (1);
}
return (ret);
err1: (void)dbp->close(dbp, 0);
return (1);
}
void
usage()
{
(void)fprintf(stderr, "usage: %s %s\n\t%s\n",
progname, "[-EIRT] [-c cachesize] [-d dups]",
"[-i iterations] [-l datalen] [-n keys] [-p pagesize]");
exit(EXIT_FAILURE);
}

View File

@ -1,162 +0,0 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 1997-2002
* Sleepycat Software. All rights reserved.
*
* $Id: ex_access.c,v 11.22 2002/09/03 12:54:26 bostic Exp $
*/
#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifdef _WIN32
extern int getopt(int, char * const *, const char *);
#else
#include <unistd.h>
#endif
#include <db.h>
#define DATABASE "access.db"
int main __P((int, char *[]));
int usage __P((void));
int
main(argc, argv)
int argc;
char *argv[];
{
extern int optind;
DB *dbp;
DBC *dbcp;
DBT key, data;
u_int32_t len;
int ch, ret, rflag;
char *database, *p, *t, buf[1024], rbuf[1024];
const char *progname = "ex_access"; /* Program name. */
rflag = 0;
while ((ch = getopt(argc, argv, "r")) != EOF)
switch (ch) {
case 'r':
rflag = 1;
break;
case '?':
default:
return (usage());
}
argc -= optind;
argv += optind;
/* Accept optional database name. */
database = *argv == NULL ? DATABASE : argv[0];
/* Optionally discard the database. */
if (rflag)
(void)remove(database);
/* Create and initialize database object, open the database. */
if ((ret = db_create(&dbp, NULL, 0)) != 0) {
fprintf(stderr,
"%s: db_create: %s\n", progname, db_strerror(ret));
return (EXIT_FAILURE);
}
dbp->set_errfile(dbp, stderr);
dbp->set_errpfx(dbp, progname);
if ((ret = dbp->set_pagesize(dbp, 1024)) != 0) {
dbp->err(dbp, ret, "set_pagesize");
goto err1;
}
if ((ret = dbp->set_cachesize(dbp, 0, 32 * 1024, 0)) != 0) {
dbp->err(dbp, ret, "set_cachesize");
goto err1;
}
if ((ret = dbp->open(dbp,
NULL, database, NULL, DB_BTREE, DB_CREATE, 0664)) != 0) {
dbp->err(dbp, ret, "%s: open", database);
goto err1;
}
/*
* Insert records into the database, where the key is the user
* input and the data is the user input in reverse order.
*/
memset(&key, 0, sizeof(DBT));
memset(&data, 0, sizeof(DBT));
for (;;) {
printf("input> ");
fflush(stdout);
if (fgets(buf, sizeof(buf), stdin) == NULL)
break;
if (strcmp(buf, "exit\n") == 0 || strcmp(buf, "quit\n") == 0)
break;
if ((len = strlen(buf)) <= 1)
continue;
for (t = rbuf, p = buf + (len - 2); p >= buf;)
*t++ = *p--;
*t++ = '\0';
key.data = buf;
data.data = rbuf;
data.size = key.size = len - 1;
switch (ret =
dbp->put(dbp, NULL, &key, &data, DB_NOOVERWRITE)) {
case 0:
break;
default:
dbp->err(dbp, ret, "DB->put");
if (ret != DB_KEYEXIST)
goto err1;
break;
}
}
printf("\n");
/* Acquire a cursor for the database. */
if ((ret = dbp->cursor(dbp, NULL, &dbcp, 0)) != 0) {
dbp->err(dbp, ret, "DB->cursor");
goto err1;
}
/* Initialize the key/data pair so the flags aren't set. */
memset(&key, 0, sizeof(key));
memset(&data, 0, sizeof(data));
/* Walk through the database and print out the key/data pairs. */
while ((ret = dbcp->c_get(dbcp, &key, &data, DB_NEXT)) == 0)
printf("%.*s : %.*s\n",
(int)key.size, (char *)key.data,
(int)data.size, (char *)data.data);
if (ret != DB_NOTFOUND) {
dbp->err(dbp, ret, "DBcursor->get");
goto err2;
}
/* Close everything down. */
if ((ret = dbcp->c_close(dbcp)) != 0) {
dbp->err(dbp, ret, "DBcursor->close");
goto err1;
}
if ((ret = dbp->close(dbp, 0)) != 0) {
fprintf(stderr,
"%s: DB->close: %s\n", progname, db_strerror(ret));
return (EXIT_FAILURE);
}
return (EXIT_SUCCESS);
err2: (void)dbcp->c_close(dbcp);
err1: (void)dbp->close(dbp, 0);
return (EXIT_FAILURE);
}
int
usage()
{
(void)fprintf(stderr, "usage: ex_access [-r] [database]\n");
return (EXIT_FAILURE);
}

View File

@ -1,9 +0,0 @@
# Script to rebuild automatically generated files for ex_apprec.
E=../examples_c/ex_apprec
cd ../../dist
awk -f gen_rec.awk \
-v source_file=$E/ex_apprec_auto.c \
-v header_file=$E/ex_apprec_auto.h \
-v template_file=$E/ex_apprec_template < $E/ex_apprec.src

View File

@ -1,267 +0,0 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 1996-2002
* Sleepycat Software. All rights reserved.
*
* $Id: ex_apprec.c,v 1.2 2002/08/06 05:39:01 bostic Exp $
*/
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <db.h>
#include "ex_apprec.h"
int apprec_dispatch __P((DB_ENV *, DBT *, DB_LSN *, db_recops));
int open_env __P((const char *, FILE *, const char *, DB_ENV **));
int verify_absence __P((DB_ENV *, const char *));
int verify_presence __P((DB_ENV *, const char *));
int
main(argc, argv)
int argc;
char *argv[];
{
extern char *optarg;
extern int optind;
DB_ENV *dbenv;
DB_LSN lsn;
DB_TXN *txn;
DBT dirnamedbt;
int ret;
const char *home;
char ch, dirname[256];
const char *progname = "ex_apprec"; /* Program name. */
/* Default home. */
home = "TESTDIR";
while ((ch = getopt(argc, argv, "h:")) != EOF)
switch (ch) {
case 'h':
home = optarg;
break;
default:
fprintf(stderr, "usage: %s [-h home]", progname);
exit(EXIT_FAILURE);
}
printf("Set up environment.\n");
if ((ret = open_env(home, stderr, progname, &dbenv)) != 0)
return (EXIT_FAILURE);
printf("Create a directory in a transaction.\n");
/*
* This application's convention is to log the full directory name,
* including trailing nul.
*/
memset(&dirnamedbt, 0, sizeof(dirnamedbt));
sprintf(dirname, "%s/MYDIRECTORY", home);
dirnamedbt.data = dirname;
dirnamedbt.size = strlen(dirname) + 1;
if ((ret = dbenv->txn_begin(dbenv, NULL, &txn, 0)) != 0) {
dbenv->err(dbenv, ret, "txn_begin");
return (EXIT_FAILURE);
}
/* Remember, always log actions before you execute them! */
memset(&lsn, 0, sizeof(lsn));
if ((ret =
ex_apprec_mkdir_log(dbenv, txn, &lsn, 0, &dirnamedbt)) != 0) {
dbenv->err(dbenv, ret, "mkdir_log");
return (EXIT_FAILURE);
}
if (mkdir(dirname, 0755) != 0) {
dbenv->err(dbenv, errno, "mkdir");
return (EXIT_FAILURE);
}
printf("Verify the directory's presence: ");
verify_presence(dbenv, dirname);
printf("check.\n");
/* Now abort the transaction and verify that the directory goes away. */
printf("Abort the transaction.\n");
if ((ret = txn->abort(txn)) != 0) {
dbenv->err(dbenv, ret, "txn_abort");
return (EXIT_FAILURE);
}
printf("Verify the directory's absence: ");
verify_absence(dbenv, dirname);
printf("check.\n");
/* Now do the same thing over again, only with a commit this time. */
printf("Create a directory in a transaction.\n");
memset(&dirnamedbt, 0, sizeof(dirnamedbt));
sprintf(dirname, "%s/MYDIRECTORY", home);
dirnamedbt.data = dirname;
dirnamedbt.size = strlen(dirname) + 1;
if ((ret = dbenv->txn_begin(dbenv, NULL, &txn, 0)) != 0) {
dbenv->err(dbenv, ret, "txn_begin");
return (EXIT_FAILURE);
}
memset(&lsn, 0, sizeof(lsn));
if ((ret =
ex_apprec_mkdir_log(dbenv, txn, &lsn, 0, &dirnamedbt)) != 0) {
dbenv->err(dbenv, ret, "mkdir_log");
return (EXIT_FAILURE);
}
if (mkdir(dirname, 0755) != 0) {
dbenv->err(dbenv, errno, "mkdir");
return (EXIT_FAILURE);
}
printf("Verify the directory's presence: ");
verify_presence(dbenv, dirname);
printf("check.\n");
/* Now abort the transaction and verify that the directory goes away. */
printf("Commit the transaction.\n");
if ((ret = txn->commit(txn, 0)) != 0) {
dbenv->err(dbenv, ret, "txn_commit");
return (EXIT_FAILURE);
}
printf("Verify the directory's presence: ");
verify_presence(dbenv, dirname);
printf("check.\n");
printf("Now remove the directory, then run recovery.\n");
if ((ret = dbenv->close(dbenv, 0)) != 0) {
fprintf(stderr, "DB_ENV->close: %s\n", db_strerror(ret));
return (EXIT_FAILURE);
}
if (rmdir(dirname) != 0) {
fprintf(stderr,
"%s: rmdir failed with error %s", progname,
strerror(errno));
}
verify_absence(dbenv, dirname);
/* Opening with DB_RECOVER runs recovery. */
if ((ret = open_env(home, stderr, progname, &dbenv)) != 0)
return (EXIT_FAILURE);
printf("Verify the directory's presence: ");
verify_presence(dbenv, dirname);
printf("check.\n");
/* Close the handle. */
if ((ret = dbenv->close(dbenv, 0)) != 0) {
fprintf(stderr, "DB_ENV->close: %s\n", db_strerror(ret));
return (EXIT_FAILURE);
}
return (EXIT_SUCCESS);
}
int
open_env(home, errfp, progname, dbenvp)
const char *home, *progname;
FILE *errfp;
DB_ENV **dbenvp;
{
DB_ENV *dbenv;
int ret;
/*
* Create an environment object and initialize it for error
* reporting.
*/
if ((ret = db_env_create(&dbenv, 0)) != 0) {
fprintf(errfp, "%s: %s\n", progname, db_strerror(ret));
return (ret);
}
dbenv->set_errfile(dbenv, errfp);
dbenv->set_errpfx(dbenv, progname);
/* Set up our custom recovery dispatch function. */
if ((ret = dbenv->set_app_dispatch(dbenv, apprec_dispatch)) != 0) {
dbenv->err(dbenv, ret, "set_app_dispatch");
return (ret);
}
/*
* Open the environment with full transactional support, running
* recovery.
*/
if ((ret =
dbenv->open(dbenv, home, DB_CREATE | DB_RECOVER | DB_INIT_LOCK |
DB_INIT_LOG | DB_INIT_MPOOL | DB_INIT_TXN, 0)) != 0) {
dbenv->err(dbenv, ret, "environment open: %s", home);
dbenv->close(dbenv, 0);
return (ret);
}
*dbenvp = dbenv;
return (0);
}
/*
* Sample application dispatch function to handle user-specified log record
* types.
*/
int
apprec_dispatch(dbenv, dbt, lsn, op)
DB_ENV *dbenv;
DBT *dbt;
DB_LSN *lsn;
db_recops op;
{
u_int32_t rectype;
/* Pull the record type out of the log record. */
memcpy(&rectype, dbt->data, sizeof(rectype));
switch (rectype) {
case DB_ex_apprec_mkdir:
return (ex_apprec_mkdir_recover(dbenv, dbt, lsn, op, NULL));
default:
/*
* We've hit an unexpected, allegedly user-defined record
* type.
*/
dbenv->errx(dbenv, "Unexpected log record type encountered");
return (EINVAL);
}
}
int
verify_absence(dbenv, dirname)
DB_ENV *dbenv;
const char *dirname;
{
if (access(dirname, F_OK) == 0) {
dbenv->errx(dbenv, "Error--directory present!");
exit(EXIT_FAILURE);
}
return (0);
}
int
verify_presence(dbenv, dirname)
DB_ENV *dbenv;
const char *dirname;
{
if (access(dirname, F_OK) != 0) {
dbenv->errx(dbenv, "Error--directory not present!");
exit(EXIT_FAILURE);
}
return (0);
}

View File

@ -1,24 +0,0 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 2002
* Sleepycat Software. All rights reserved.
*
* $Id: ex_apprec.h,v 1.2 2002/08/08 15:47:00 bostic Exp $
*/
#ifndef _EX_APPREC_H_
#define _EX_APPREC_H_
#include "ex_apprec_auto.h"
int ex_apprec_mkdir_log
__P((DB_ENV *, DB_TXN *, DB_LSN *, u_int32_t, const DBT *));
int ex_apprec_mkdir_print
__P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));
int ex_apprec_mkdir_read
__P((DB_ENV *, void *, ex_apprec_mkdir_args **));
int ex_apprec_mkdir_recover
__P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));
#endif /* !_EX_APPREC_H_ */

View File

@ -1,41 +0,0 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 2002
* Sleepycat Software. All rights reserved.
*
* $Id: ex_apprec.src,v 1.3 2002/08/08 15:47:00 bostic Exp $
*/
PREFIX ex_apprec
/*
* This is the source file used to generate the application-specific recovery
* functions used by the ex_apprec example. It should be turned into usable
* source code (including a template for the recovery function itself) by
* invoking changing to the dist directory of the DB distribution and
* running the gen_rec.awk script there as follows:
*
* awk -f ./gen_rec.awk \
* -v source_file=../examples_c/ex_apprec/ex_apprec_auto.c \
* -v header_file=../examples_c/ex_apprec/ex_apprec_auto.h \
* -v template_file=../examples_c/ex_apprec/ex_apprec_template \
* < ../examples_c/ex_apprec/ex_apprec.src
INCLUDE #include <ctype.h>
INCLUDE #include <errno.h>
INCLUDE #include <stdlib.h>
INCLUDE #include <string.h>
INCLUDE
INCLUDE #include <db.h>
INCLUDE
INCLUDE #include "ex_apprec.h"
/*
* mkdir: used to create a directory
*
* dirname: relative or absolute pathname of the directory to be created
*/
BEGIN mkdir 10000
DBT dirname DBT s
END

View File

@ -1,115 +0,0 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 1996-2002
* Sleepycat Software. All rights reserved.
*
* $Id: ex_apprec_rec.c,v 1.2 2002/08/06 05:39:02 bostic Exp $
*/
/*
* This file is based on the template file ex_apprec_template. Note that
* because ex_apprec_mkdir, like most application-specific recovery functions,
* does not make use of DB-private structures, it has actually been simplified
* significantly.
*/
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
#include <stdlib.h>
#include <unistd.h>
#include <db.h>
#include "ex_apprec.h"
/*
* ex_apprec_mkdir_recover --
* Recovery function for mkdir.
*
* PUBLIC: int ex_apprec_mkdir_recover
* PUBLIC: __P((DB_ENV *, DBT *, DB_LSN *, db_recops, void *));
*/
int
ex_apprec_mkdir_recover(dbenv, dbtp, lsnp, op, info)
DB_ENV *dbenv;
DBT *dbtp;
DB_LSN *lsnp;
db_recops op;
void *info;
{
ex_apprec_mkdir_args *argp;
int ret;
argp = NULL;
/*
* Shut up the compiler--"info" is used for the recovery functions
* belonging to transaction meta-operations such as txn_create, and
* need not concern us here either.
*/
info = NULL;
if ((ret = ex_apprec_mkdir_read(dbenv, dbtp->data, &argp)) != 0)
goto out;
switch (op) {
case DB_TXN_ABORT:
case DB_TXN_BACKWARD_ROLL:
/*
* If we're aborting, we need to remove the directory if it
* exists. We log the trailing zero in pathnames, so we can
* simply pass the data part of the DBT into rmdir as a string.
* (Note that we don't have any alignment guarantees, but for
* a char * this doesn't matter.)
*
* Ignore all errors other than ENOENT; DB may attempt to undo
* or redo operations without knowing whether they have already
* been done or undone, so we should never assume in a recovery
* function that the task definitely needs doing or undoing.
*/
ret = rmdir(argp->dirname.data);
if (ret != 0 && errno != ENOENT)
dbenv->err(dbenv, ret, "Error in abort of mkdir");
else
ret = 0;
break;
case DB_TXN_FORWARD_ROLL:
/*
* The forward direction is just the opposite; here, we ignore
* EEXIST, because the directory may already exist.
*/
ret = mkdir(argp->dirname.data, 0755);
if (ret != 0 && errno != EEXIST)
dbenv->err(dbenv,
ret, "Error in roll-forward of mkdir");
else
ret = 0;
break;
default:
/*
* We might want to handle DB_TXN_PRINT or DB_TXN_APPLY here,
* too, but we don't try to print the log records and aren't
* using replication, so there's no need to in this example.
*/
dbenv->errx(dbenv, "Unexpected operation type\n");
return (EINVAL);
}
/*
* The recovery function is responsible for returning the LSN of the
* previous log record in this transaction, so that transaction aborts
* can follow the chain backwards.
*
* (If we'd wanted the LSN of this record earlier, we could have
* read it from lsnp, as well--but because we weren't working with
* pages or other objects that store their LSN and base recovery
* decisions on it, we didn't need to.)
*/
*lsnp = argp->prev_lsn;
out: if (argp != NULL)
free(argp);
return (ret);
}

View File

@ -1,203 +0,0 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 1997-2002
* Sleepycat Software. All rights reserved.
*
* $Id: ex_btrec.c,v 11.18 2002/01/23 15:33:18 bostic Exp $
*/
#include <sys/types.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <db.h>
#define DATABASE "access.db"
#define WORDLIST "../test/wordlist"
int main __P((void));
int ex_btrec __P((void));
void show __P((const char *, DBT *, DBT *));
int
main()
{
return (ex_btrec() == 1 ? EXIT_FAILURE : EXIT_SUCCESS);
}
int
ex_btrec()
{
DB *dbp;
DBC *dbcp;
DBT key, data;
DB_BTREE_STAT *statp;
FILE *fp;
db_recno_t recno;
u_int32_t len;
int cnt, ret;
char *p, *t, buf[1024], rbuf[1024];
const char *progname = "ex_btrec"; /* Program name. */
/* Open the word database. */
if ((fp = fopen(WORDLIST, "r")) == NULL) {
fprintf(stderr, "%s: open %s: %s\n",
progname, WORDLIST, db_strerror(errno));
return (1);
}
/* Remove the previous database. */
(void)remove(DATABASE);
/* Create and initialize database object, open the database. */
if ((ret = db_create(&dbp, NULL, 0)) != 0) {
fprintf(stderr,
"%s: db_create: %s\n", progname, db_strerror(ret));
return (1);
}
dbp->set_errfile(dbp, stderr);
dbp->set_errpfx(dbp, progname); /* 1K page sizes. */
if ((ret = dbp->set_pagesize(dbp, 1024)) != 0) {
dbp->err(dbp, ret, "set_pagesize");
return (1);
} /* Record numbers. */
if ((ret = dbp->set_flags(dbp, DB_RECNUM)) != 0) {
dbp->err(dbp, ret, "set_flags: DB_RECNUM");
return (1);
}
if ((ret = dbp->open(dbp,
NULL, DATABASE, NULL, DB_BTREE, DB_CREATE, 0664)) != 0) {
dbp->err(dbp, ret, "open: %s", DATABASE);
return (1);
}
/*
* Insert records into the database, where the key is the word
* preceded by its record number, and the data is the same, but
* in reverse order.
*/
memset(&key, 0, sizeof(DBT));
memset(&data, 0, sizeof(DBT));
for (cnt = 1; cnt <= 1000; ++cnt) {
(void)sprintf(buf, "%04d_", cnt);
if (fgets(buf + 4, sizeof(buf) - 4, fp) == NULL)
break;
len = strlen(buf);
for (t = rbuf, p = buf + (len - 2); p >= buf;)
*t++ = *p--;
*t++ = '\0';
key.data = buf;
data.data = rbuf;
data.size = key.size = len - 1;
if ((ret =
dbp->put(dbp, NULL, &key, &data, DB_NOOVERWRITE)) != 0) {
dbp->err(dbp, ret, "DB->put");
if (ret != DB_KEYEXIST)
goto err1;
}
}
/* Close the word database. */
(void)fclose(fp);
/* Print out the number of records in the database. */
if ((ret = dbp->stat(dbp, &statp, 0)) != 0) {
dbp->err(dbp, ret, "DB->stat");
goto err1;
}
printf("%s: database contains %lu records\n",
progname, (u_long)statp->bt_ndata);
free(statp);
/* Acquire a cursor for the database. */
if ((ret = dbp->cursor(dbp, NULL, &dbcp, 0)) != 0) {
dbp->err(dbp, ret, "DB->cursor");
goto err1;
}
/*
* Prompt the user for a record number, then retrieve and display
* that record.
*/
for (;;) {
/* Get a record number. */
printf("recno #> ");
fflush(stdout);
if (fgets(buf, sizeof(buf), stdin) == NULL)
break;
recno = atoi(buf);
/*
* Reset the key each time, the dbp->c_get() routine returns
* the key and data pair, not just the key!
*/
key.data = &recno;
key.size = sizeof(recno);
if ((ret = dbcp->c_get(dbcp, &key, &data, DB_SET_RECNO)) != 0)
goto get_err;
/* Display the key and data. */
show("k/d\t", &key, &data);
/* Move the cursor a record forward. */
if ((ret = dbcp->c_get(dbcp, &key, &data, DB_NEXT)) != 0)
goto get_err;
/* Display the key and data. */
show("next\t", &key, &data);
/*
* Retrieve the record number for the following record into
* local memory.
*/
data.data = &recno;
data.size = sizeof(recno);
data.ulen = sizeof(recno);
data.flags |= DB_DBT_USERMEM;
if ((ret = dbcp->c_get(dbcp, &key, &data, DB_GET_RECNO)) != 0) {
get_err: dbp->err(dbp, ret, "DBcursor->get");
if (ret != DB_NOTFOUND && ret != DB_KEYEMPTY)
goto err2;
} else
printf("retrieved recno: %lu\n", (u_long)recno);
/* Reset the data DBT. */
memset(&data, 0, sizeof(data));
}
if ((ret = dbcp->c_close(dbcp)) != 0) {
dbp->err(dbp, ret, "DBcursor->close");
goto err1;
}
if ((ret = dbp->close(dbp, 0)) != 0) {
fprintf(stderr,
"%s: DB->close: %s\n", progname, db_strerror(ret));
return (1);
}
return (0);
err2: (void)dbcp->c_close(dbcp);
err1: (void)dbp->close(dbp, 0);
return (ret);
}
/*
* show --
* Display a key/data pair.
*/
void
show(msg, key, data)
const char *msg;
DBT *key, *data;
{
printf("%s%.*s : %.*s\n", msg,
(int)key->size, (char *)key->data,
(int)data->size, (char *)data->data);
}

View File

@ -1,226 +0,0 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 1996-2002
* Sleepycat Software. All rights reserved.
*
* $Id: ex_dbclient.c,v 1.28 2002/08/06 06:11:24 bostic Exp $
*/
#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <db.h>
#define DATABASE_HOME "database"
#define DATABASE "access.db"
int db_clientrun __P((DB_ENV *, const char *));
int ex_dbclient_run __P((const char *, FILE *, const char *, const char *));
int main __P((int, char *[]));
/*
* An example of a program creating/configuring a Berkeley DB environment.
*/
int
main(argc, argv)
int argc;
char *argv[];
{
const char *home;
if (argc != 2) {
fprintf(stderr, "Usage: %s hostname\n", argv[0]);
return (EXIT_FAILURE);
}
/*
* All of the shared database files live in DATABASE_HOME, but
* data files will live in CONFIG_DATA_DIR.
*/
home = DATABASE_HOME;
return (ex_dbclient_run(home,
stderr, argv[1], argv[0]) == 0 ? EXIT_SUCCESS : EXIT_FAILURE);
}
int
ex_dbclient(host)
const char *host;
{
const char *home;
const char *progname = "ex_dbclient"; /* Program name. */
int ret;
/*
* All of the shared database files live in DATABASE_HOME, but
* data files will live in CONFIG_DATA_DIR.
*/
home = DATABASE_HOME;
if ((ret = ex_dbclient_run(home, stderr, host, progname)) != 0)
return (ret);
return (0);
}
int
ex_dbclient_run(home, errfp, host, progname)
const char *home, *host, *progname;
FILE *errfp;
{
DB_ENV *dbenv;
int ret, retry;
/*
* Create an environment object and initialize it for error
* reporting.
*/
if ((ret = db_env_create(&dbenv, DB_CLIENT)) != 0) {
fprintf(errfp, "%s: %s\n", progname, db_strerror(ret));
return (1);
}
retry = 0;
retry:
while (retry < 5) {
/*
* Set the server host we are talking to.
*/
if ((ret = dbenv->set_rpc_server(dbenv, NULL, host, 10000,
10000, 0)) != 0) {
fprintf(stderr, "Try %d: DB_ENV->set_rpc_server: %s\n",
retry, db_strerror(ret));
retry++;
sleep(15);
} else
break;
}
if (retry >= 5) {
fprintf(stderr,
"DB_ENV->set_rpc_server: %s\n", db_strerror(ret));
dbenv->close(dbenv, 0);
return (1);
}
/*
* We want to specify the shared memory buffer pool cachesize,
* but everything else is the default.
*/
if ((ret = dbenv->set_cachesize(dbenv, 0, 64 * 1024, 0)) != 0) {
dbenv->err(dbenv, ret, "set_cachesize");
dbenv->close(dbenv, 0);
return (1);
}
/*
* We have multiple processes reading/writing these files, so
* we need concurrency control and a shared buffer pool, but
* not logging or transactions.
*/
if ((ret = dbenv->open(dbenv, home,
DB_CREATE | DB_INIT_LOCK | DB_INIT_MPOOL, 0)) != 0) {
dbenv->err(dbenv, ret, "environment open: %s", home);
dbenv->close(dbenv, 0);
if (ret == DB_NOSERVER)
goto retry;
return (1);
}
ret = db_clientrun(dbenv, progname);
printf("db_clientrun returned %d\n", ret);
if (ret == DB_NOSERVER)
goto retry;
/* Close the handle. */
if ((ret = dbenv->close(dbenv, 0)) != 0) {
fprintf(stderr, "DB_ENV->close: %s\n", db_strerror(ret));
return (1);
}
return (0);
}
int
db_clientrun(dbenv, progname)
DB_ENV *dbenv;
const char *progname;
{
DB *dbp;
DBT key, data;
u_int32_t len;
int ret;
char *p, *t, buf[1024], rbuf[1024];
/* Remove the previous database. */
/* Create and initialize database object, open the database. */
if ((ret = db_create(&dbp, dbenv, 0)) != 0) {
fprintf(stderr,
"%s: db_create: %s\n", progname, db_strerror(ret));
return (ret);
}
if ((ret = dbp->set_pagesize(dbp, 1024)) != 0) {
dbp->err(dbp, ret, "set_pagesize");
goto err1;
}
if ((ret = dbp->open(dbp,
NULL, DATABASE, NULL, DB_BTREE, DB_CREATE, 0664)) != 0) {
dbp->err(dbp, ret, "%s: open", DATABASE);
goto err1;
}
/*
* Insert records into the database, where the key is the user
* input and the data is the user input in reverse order.
*/
memset(&key, 0, sizeof(DBT));
memset(&data, 0, sizeof(DBT));
for (;;) {
printf("input> ");
fflush(stdout);
if (fgets(buf, sizeof(buf), stdin) == NULL)
break;
if ((len = strlen(buf)) <= 1)
continue;
for (t = rbuf, p = buf + (len - 2); p >= buf;)
*t++ = *p--;
*t++ = '\0';
key.data = buf;
data.data = rbuf;
data.size = key.size = len - 1;
switch (ret =
dbp->put(dbp, NULL, &key, &data, DB_NOOVERWRITE)) {
case 0:
break;
default:
dbp->err(dbp, ret, "DB->put");
if (ret != DB_KEYEXIST)
goto err1;
break;
}
memset(&data, 0, sizeof(DBT));
switch (ret = dbp->get(dbp, NULL, &key, &data, 0)) {
case 0:
printf("%.*s : %.*s\n",
(int)key.size, (char *)key.data,
(int)data.size, (char *)data.data);
break;
default:
dbp->err(dbp, ret, "DB->get");
break;
}
}
if ((ret = dbp->close(dbp, 0)) != 0) {
fprintf(stderr,
"%s: DB->close: %s\n", progname, db_strerror(ret));
return (1);
}
return (0);
err1: (void)dbp->close(dbp, 0);
return (ret);
}

View File

@ -1,135 +0,0 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 1996-2002
* Sleepycat Software. All rights reserved.
*
* $Id: ex_env.c,v 11.27 2002/08/15 14:34:11 bostic Exp $
*/
#include <sys/types.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <db.h>
#ifdef macintosh
#define DATABASE_HOME ":database"
#define CONFIG_DATA_DIR ":database"
#else
#ifdef DB_WIN32
#define DATABASE_HOME "\\tmp\\database"
#define CONFIG_DATA_DIR "\\database\\files"
#else
#define DATABASE_HOME "/tmp/database"
#define CONFIG_DATA_DIR "/database/files"
#endif
#endif
int db_setup __P((const char *, const char *, FILE *, const char *));
int db_teardown __P((const char *, const char *, FILE *, const char *));
int main __P((void));
/*
* An example of a program creating/configuring a Berkeley DB environment.
*/
int
main()
{
const char *data_dir, *home;
const char *progname = "ex_env"; /* Program name. */
/*
* All of the shared database files live in DATABASE_HOME, but
* data files will live in CONFIG_DATA_DIR.
*/
home = DATABASE_HOME;
data_dir = CONFIG_DATA_DIR;
printf("Setup env\n");
if (db_setup(home, data_dir, stderr, progname) != 0)
return (EXIT_FAILURE);
printf("Teardown env\n");
if (db_teardown(home, data_dir, stderr, progname) != 0)
return (EXIT_FAILURE);
return (EXIT_SUCCESS);
}
int
db_setup(home, data_dir, errfp, progname)
const char *home, *data_dir, *progname;
FILE *errfp;
{
DB_ENV *dbenv;
int ret;
/*
* Create an environment object and initialize it for error
* reporting.
*/
if ((ret = db_env_create(&dbenv, 0)) != 0) {
fprintf(errfp, "%s: %s\n", progname, db_strerror(ret));
return (1);
}
dbenv->set_errfile(dbenv, errfp);
dbenv->set_errpfx(dbenv, progname);
/*
* We want to specify the shared memory buffer pool cachesize,
* but everything else is the default.
*/
if ((ret = dbenv->set_cachesize(dbenv, 0, 64 * 1024, 0)) != 0) {
dbenv->err(dbenv, ret, "set_cachesize");
dbenv->close(dbenv, 0);
return (1);
}
/* Databases are in a subdirectory. */
(void)dbenv->set_data_dir(dbenv, data_dir);
/* Open the environment with full transactional support. */
if ((ret = dbenv->open(dbenv, home,
DB_CREATE | DB_INIT_LOCK | DB_INIT_LOG | DB_INIT_MPOOL | DB_INIT_TXN,
0)) != 0) {
dbenv->err(dbenv, ret, "environment open: %s", home);
dbenv->close(dbenv, 0);
return (1);
}
/* Do something interesting... */
/* Close the handle. */
if ((ret = dbenv->close(dbenv, 0)) != 0) {
fprintf(stderr, "DB_ENV->close: %s\n", db_strerror(ret));
return (1);
}
return (0);
}
int
db_teardown(home, data_dir, errfp, progname)
const char *home, *data_dir, *progname;
FILE *errfp;
{
DB_ENV *dbenv;
int ret;
/* Remove the shared database regions. */
if ((ret = db_env_create(&dbenv, 0)) != 0) {
fprintf(errfp, "%s: %s\n", progname, db_strerror(ret));
return (1);
}
dbenv->set_errfile(dbenv, errfp);
dbenv->set_errpfx(dbenv, progname);
(void)dbenv->set_data_dir(dbenv, data_dir);
if ((ret = dbenv->remove(dbenv, home, 0)) != 0) {
fprintf(stderr, "DB_ENV->remove: %s\n", db_strerror(ret));
return (1);
}
return (0);
}

View File

@ -1,239 +0,0 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 1997-2002
* Sleepycat Software. All rights reserved.
*
* $Id: ex_lock.c,v 11.18 2002/04/10 21:48:20 bostic Exp $
*/
#include <sys/types.h>
#include <stdlib.h>
#include <string.h>
#ifdef _WIN32
extern int getopt(int, char * const *, const char *);
#else
#include <unistd.h>
#endif
#include <db.h>
int db_init __P((const char *, u_int32_t, int));
int main __P((int, char *[]));
int usage __P((void));
DB_ENV *dbenv;
const char
*progname = "ex_lock"; /* Program name. */
int
main(argc, argv)
int argc;
char *argv[];
{
extern char *optarg;
extern int optind;
DBT lock_dbt;
DB_LOCK lock;
DB_LOCK *locks;
db_lockmode_t lock_type;
long held;
u_int32_t len, locker, maxlocks;
int ch, do_unlink, did_get, i, lockid, lockcount, ret;
const char *home;
char opbuf[16], objbuf[1024], lockbuf[16];
home = "TESTDIR";
maxlocks = 0;
do_unlink = 0;
while ((ch = getopt(argc, argv, "h:m:u")) != EOF)
switch (ch) {
case 'h':
home = optarg;
break;
case 'm':
if ((i = atoi(optarg)) <= 0)
return (usage());
maxlocks = (u_int32_t)i; /* XXX: possible overflow. */
break;
case 'u':
do_unlink = 1;
break;
case '?':
default:
return (usage());
}
argc -= optind;
argv += optind;
if (argc != 0)
return (usage());
/* Initialize the database environment. */
if ((ret = db_init(home, maxlocks, do_unlink)) != 0)
return (ret);
locks = 0;
lockcount = 0;
/*
* Accept lock requests.
*/
if ((ret = dbenv->lock_id(dbenv, &locker)) != 0) {
dbenv->err(dbenv, ret, "unable to get locker id");
(void)dbenv->close(dbenv, 0);
return (EXIT_FAILURE);
}
lockid = -1;
memset(&lock_dbt, 0, sizeof(lock_dbt));
for (held = 0, did_get = 0;;) {
printf("Operation get/release [get]> ");
fflush(stdout);
if (fgets(opbuf, sizeof(opbuf), stdin) == NULL)
break;
if ((len = strlen(opbuf)) <= 1 || strcmp(opbuf, "get\n") == 0) {
/* Acquire a lock. */
printf("input object (text string) to lock> ");
fflush(stdout);
if (fgets(objbuf, sizeof(objbuf), stdin) == NULL)
break;
if ((len = strlen(objbuf)) <= 1)
continue;
do {
printf("lock type read/write [read]> ");
fflush(stdout);
if (fgets(lockbuf,
sizeof(lockbuf), stdin) == NULL)
break;
len = strlen(lockbuf);
} while (len > 1 &&
strcmp(lockbuf, "read\n") != 0 &&
strcmp(lockbuf, "write\n") != 0);
if (len == 1 || strcmp(lockbuf, "read\n") == 0)
lock_type = DB_LOCK_READ;
else
lock_type = DB_LOCK_WRITE;
lock_dbt.data = objbuf;
lock_dbt.size = strlen(objbuf);
ret = dbenv->lock_get(dbenv, locker,
DB_LOCK_NOWAIT, &lock_dbt, lock_type, &lock);
if (ret == 0) {
did_get = 1;
lockid = lockcount++;
if (locks == NULL)
locks =
(DB_LOCK *)malloc(sizeof(DB_LOCK));
else
locks = (DB_LOCK *)realloc(locks,
lockcount * sizeof(DB_LOCK));
locks[lockid] = lock;
}
} else {
/* Release a lock. */
do {
printf("input lock to release> ");
fflush(stdout);
if (fgets(objbuf,
sizeof(objbuf), stdin) == NULL)
break;
} while ((len = strlen(objbuf)) <= 1);
lockid = strtol(objbuf, NULL, 16);
if (lockid < 0 || lockid >= lockcount) {
printf("Lock #%d out of range\n", lockid);
continue;
}
lock = locks[lockid];
ret = dbenv->lock_put(dbenv, &lock);
did_get = 0;
}
switch (ret) {
case 0:
printf("Lock #%d %s\n", lockid,
did_get ? "granted" : "released");
held += did_get ? 1 : -1;
break;
case DB_LOCK_NOTGRANTED:
dbenv->err(dbenv, ret, NULL);
break;
case DB_LOCK_DEADLOCK:
dbenv->err(dbenv, ret,
"lock_%s", did_get ? "get" : "put");
break;
default:
dbenv->err(dbenv, ret,
"lock_%s", did_get ? "get" : "put");
(void)dbenv->close(dbenv, 0);
return (EXIT_FAILURE);
}
}
printf("\nClosing lock region %ld locks held\n", held);
if (locks != NULL)
free(locks);
if ((ret = dbenv->close(dbenv, 0)) != 0) {
fprintf(stderr,
"%s: dbenv->close: %s\n", progname, db_strerror(ret));
return (EXIT_FAILURE);
}
return (EXIT_SUCCESS);
}
/*
* db_init --
* Initialize the environment.
*/
int
db_init(home, maxlocks, do_unlink)
const char *home;
u_int32_t maxlocks;
int do_unlink;
{
int ret;
if ((ret = db_env_create(&dbenv, 0)) != 0) {
fprintf(stderr, "%s: db_env_create: %s\n",
progname, db_strerror(ret));
return (EXIT_FAILURE);
}
if (do_unlink) {
if ((ret = dbenv->remove(dbenv, home, DB_FORCE)) != 0) {
fprintf(stderr, "%s: dbenv->remove: %s\n",
progname, db_strerror(ret));
return (EXIT_FAILURE);
}
if ((ret = db_env_create(&dbenv, 0)) != 0) {
fprintf(stderr, "%s: db_env_create: %s\n",
progname, db_strerror(ret));
return (EXIT_FAILURE);
}
}
dbenv->set_errfile(dbenv, stderr);
dbenv->set_errpfx(dbenv, progname);
if (maxlocks != 0)
dbenv->set_lk_max_locks(dbenv, maxlocks);
if ((ret =
dbenv->open(dbenv, home, DB_CREATE | DB_INIT_LOCK, 0)) != 0) {
dbenv->err(dbenv, ret, NULL);
(void)dbenv->close(dbenv, 0);
return (EXIT_FAILURE);
}
return (0);
}
int
usage()
{
(void)fprintf(stderr,
"usage: %s [-u] [-h home] [-m maxlocks]\n", progname);
return (EXIT_FAILURE);
}

View File

@ -1,253 +0,0 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 1997-2002
* Sleepycat Software. All rights reserved.
*
* $Id: ex_mpool.c,v 11.26 2002/08/15 14:34:56 bostic Exp $
*/
#include <sys/types.h>
#include <errno.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#ifdef _WIN32
extern int getopt(int, char * const *, const char *);
#else
#include <unistd.h>
#endif
#include <db.h>
int init __P((const char *, int, int, const char *));
int run __P((int, int, int, int, const char *));
int run_mpool __P((int, int, int, int, const char *));
int main __P((int, char *[]));
int usage __P((const char *));
#define MPOOL "mpool" /* File. */
int
main(argc, argv)
int argc;
char *argv[];
{
extern char *optarg;
extern int optind;
int cachesize, ch, hits, npages, pagesize;
char *progname;
cachesize = 20 * 1024;
hits = 1000;
npages = 50;
pagesize = 1024;
progname = argv[0];
while ((ch = getopt(argc, argv, "c:h:n:p:")) != EOF)
switch (ch) {
case 'c':
if ((cachesize = atoi(optarg)) < 20 * 1024)
return (usage(progname));
break;
case 'h':
if ((hits = atoi(optarg)) <= 0)
return (usage(progname));
break;
case 'n':
if ((npages = atoi(optarg)) <= 0)
return (usage(progname));
break;
case 'p':
if ((pagesize = atoi(optarg)) <= 0)
return (usage(progname));
break;
case '?':
default:
return (usage(progname));
}
argc -= optind;
argv += optind;
return (run_mpool(pagesize, cachesize,
hits, npages, progname) == 0 ? EXIT_SUCCESS : EXIT_FAILURE);
}
int
usage(progname)
const char *progname;
{
(void)fprintf(stderr,
"usage: %s [-c cachesize] [-h hits] [-n npages] [-p pagesize]\n",
progname);
return (EXIT_FAILURE);
}
int
run_mpool(pagesize, cachesize, hits, npages, progname)
int pagesize, cachesize, hits, npages;
const char *progname;
{
int ret;
/* Initialize the file. */
if ((ret = init(MPOOL, pagesize, npages, progname)) != 0)
return (ret);
/* Get the pages. */
if ((ret = run(hits, cachesize, pagesize, npages, progname)) != 0)
return (ret);
return (0);
}
/*
* init --
* Create a backing file.
*/
int
init(file, pagesize, npages, progname)
const char *file, *progname;
int pagesize, npages;
{
FILE *fp;
int cnt;
char *p;
/*
* Create a file with the right number of pages, and store a page
* number on each page.
*/
if ((fp = fopen(file, "wb")) == NULL) {
fprintf(stderr,
"%s: %s: %s\n", progname, file, strerror(errno));
return (1);
}
if ((p = (char *)malloc(pagesize)) == NULL) {
fprintf(stderr, "%s: %s\n", progname, strerror(ENOMEM));
return (1);
}
/* The pages are numbered from 0. */
for (cnt = 0; cnt <= npages; ++cnt) {
*(int *)p = cnt;
if (fwrite(p, pagesize, 1, fp) != 1) {
fprintf(stderr,
"%s: %s: %s\n", progname, file, strerror(errno));
return (1);
}
}
(void)fclose(fp);
free(p);
return (0);
}
/*
* run --
* Get a set of pages.
*/
int
run(hits, cachesize, pagesize, npages, progname)
int hits, cachesize, pagesize, npages;
const char *progname;
{
DB_ENV *dbenv;
DB_MPOOLFILE *mfp;
db_pgno_t pageno;
int cnt, ret;
void *p;
dbenv = NULL;
mfp = NULL;
printf("%s: cachesize: %d; pagesize: %d; N pages: %d\n",
progname, cachesize, pagesize, npages);
/*
* Open a memory pool, specify a cachesize, output error messages
* to stderr.
*/
if ((ret = db_env_create(&dbenv, 0)) != 0) {
fprintf(stderr,
"%s: db_env_create: %s\n", progname, db_strerror(ret));
return (1);
}
dbenv->set_errfile(dbenv, stderr);
dbenv->set_errpfx(dbenv, progname);
#ifdef HAVE_VXWORKS
if ((ret = dbenv->set_shm_key(dbenv, VXSHM_KEY)) != 0) {
dbenv->err(dbenv, ret, "set_shm_key");
return (1);
}
#endif
/* Set the cachesize. */
if ((ret = dbenv->set_cachesize(dbenv, 0, cachesize, 0)) != 0) {
dbenv->err(dbenv, ret, "set_cachesize");
goto err;
}
/* Open the environment. */
if ((ret = dbenv->open(
dbenv, NULL, DB_CREATE | DB_INIT_MPOOL, 0)) != 0) {
dbenv->err(dbenv, ret, "DB_ENV->open");
goto err;
}
/* Open the file in the environment. */
if ((ret = dbenv->memp_fcreate(dbenv, &mfp, 0)) != 0) {
dbenv->err(dbenv, ret, "DB_ENV->memp_fcreate: %s", MPOOL);
goto err;
}
if ((ret = mfp->open(mfp, MPOOL, 0, 0, pagesize)) != 0) {
dbenv->err(dbenv, ret, "DB_MPOOLFILE->open: %s", MPOOL);
goto err;
}
printf("retrieve %d random pages... ", hits);
srand((u_int)time(NULL));
for (cnt = 0; cnt < hits; ++cnt) {
pageno = (rand() % npages) + 1;
if ((ret = mfp->get(mfp, &pageno, 0, &p)) != 0) {
dbenv->err(dbenv, ret,
"unable to retrieve page %lu", (u_long)pageno);
goto err;
}
if (*(db_pgno_t *)p != pageno) {
dbenv->errx(dbenv,
"wrong page retrieved (%lu != %d)",
(u_long)pageno, *(int *)p);
goto err;
}
if ((ret = mfp->put(mfp, p, 0)) != 0) {
dbenv->err(dbenv, ret,
"unable to return page %lu", (u_long)pageno);
goto err;
}
}
printf("successful.\n");
/* Close the file. */
if ((ret = mfp->close(mfp, 0)) != 0) {
dbenv->err(dbenv, ret, "DB_MPOOLFILE->close");
goto err;
}
/* Close the pool. */
if ((ret = dbenv->close(dbenv, 0)) != 0) {
fprintf(stderr,
"%s: db_env_create: %s\n", progname, db_strerror(ret));
return (1);
}
return (0);
err: if (mfp != NULL)
(void)mfp->close(mfp, 0);
if (dbenv != NULL)
(void)dbenv->close(dbenv, 0);
return (1);
}

View File

@ -1,69 +0,0 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 2001-2002
* Sleepycat Software. All rights reserved.
*
* $Id: ex_repquote.h,v 1.27 2002/04/23 04:27:50 krinsky Exp $
*/
#ifndef _EX_REPQUOTE_H_
#define _EX_REPQUOTE_H_
#define SELF_EID 1
typedef struct {
char *host; /* Host name. */
u_int32_t port; /* Port on which to connect to this site. */
} repsite_t;
/* Globals */
extern int master_eid;
extern char *myaddr;
struct __member; typedef struct __member member_t;
struct __machtab; typedef struct __machtab machtab_t;
/* Arguments for the connect_all thread. */
typedef struct {
DB_ENV *dbenv;
const char *progname;
const char *home;
machtab_t *machtab;
repsite_t *sites;
int nsites;
} all_args;
/* Arguments for the connect_loop thread. */
typedef struct {
DB_ENV *dbenv;
const char * home;
const char * progname;
machtab_t *machtab;
int port;
} connect_args;
#define CACHESIZE (10 * 1024 * 1024)
#define DATABASE "quote.db"
#define SLEEPTIME 3
void *connect_all __P((void *args));
void *connect_thread __P((void *args));
int doclient __P((DB_ENV *, const char *, machtab_t *));
int domaster __P((DB_ENV *, const char *));
int get_accepted_socket __P((const char *, int));
int get_connected_socket __P((machtab_t *, const char *, const char *, int, int *, int *));
int get_next_message __P((int, DBT *, DBT *));
int listen_socket_init __P((const char *, int));
int listen_socket_accept __P((machtab_t *, const char *, int, int *));
int machtab_getinfo __P((machtab_t *, int, u_int32_t *, int *));
int machtab_init __P((machtab_t **, int, int));
void machtab_parm __P((machtab_t *, int *, int *, u_int32_t *));
int machtab_rem __P((machtab_t *, int, int));
int quote_send __P((DB_ENV *, const DBT *, const DBT *, int, u_int32_t));
#ifndef COMPQUIET
#define COMPQUIET(x,y) x = (y)
#endif
#endif /* !_EX_REPQUOTE_H_ */

View File

@ -1,250 +0,0 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 2001-2002
* Sleepycat Software. All rights reserved.
*
* $Id: ex_rq_client.c,v 1.29 2002/01/23 15:33:19 bostic Exp $
*/
#include <sys/types.h>
#include <sys/wait.h>
#include <errno.h>
#include <pthread.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <db.h>
#include "ex_repquote.h"
static void *check_loop __P((void *));
static void *display_loop __P((void *));
static int print_stocks __P((DBC *));
typedef struct {
const char *progname;
DB_ENV *dbenv;
} disploop_args;
typedef struct {
DB_ENV *dbenv;
machtab_t *machtab;
} checkloop_args;
int
doclient(dbenv, progname, machtab)
DB_ENV *dbenv;
const char *progname;
machtab_t *machtab;
{
checkloop_args cargs;
disploop_args dargs;
pthread_t check_thr, disp_thr;
void *cstatus, *dstatus;
int rval, s;
rval = EXIT_SUCCESS;
s = -1;
memset(&dargs, 0, sizeof(dargs));
dstatus = (void *)EXIT_FAILURE;
dargs.progname = progname;
dargs.dbenv = dbenv;
if (pthread_create(&disp_thr, NULL, display_loop, (void *)&dargs)) {
dbenv->err(dbenv, errno, "display_loop pthread_create failed");
goto err;
}
cargs.dbenv = dbenv;
cargs.machtab = machtab;
if (pthread_create(&check_thr, NULL, check_loop, (void *)&cargs)) {
dbenv->err(dbenv, errno, "check_thread pthread_create failed");
goto err;
}
if (pthread_join(disp_thr, &dstatus) ||
pthread_join(check_thr, &cstatus)) {
dbenv->err(dbenv, errno, "pthread_join failed");
goto err;
}
if (0) {
err: rval = EXIT_FAILURE;
}
return (rval);
}
/*
* Our only job is to check that the master is valid and if it's not
* for an extended period, to trigger an election. We do two phases.
* If we do not have a master, first we send out a request for a master
* to identify itself (that would be a call to rep_start). If that fails,
* we trigger an election.
*/
static void *
check_loop(args)
void *args;
{
DB_ENV *dbenv;
DBT dbt;
checkloop_args *cargs;
int count, n, pri;
machtab_t *machtab;
u_int32_t timeout;
cargs = (checkloop_args *)args;
dbenv = cargs->dbenv;
machtab = cargs->machtab;
#define IDLE_INTERVAL 1
count = 0;
while (master_eid == DB_EID_INVALID) {
/*
* Call either rep_start or rep_elect depending on if
* count is 0 or 1.
*/
if (count == 0) {
memset(&dbt, 0, sizeof(dbt));
dbt.data = myaddr;
dbt.size = strlen(myaddr) + 1;
(void)dbenv->rep_start(dbenv, &dbt, DB_REP_CLIENT);
count = 1;
} else {
machtab_parm(machtab, &n, &pri, &timeout);
(void)dbenv->rep_elect(dbenv,
n, pri, timeout, &master_eid);
count = 0;
}
sleep(IDLE_INTERVAL);
}
return ((void *)EXIT_SUCCESS);
}
static void *
display_loop(args)
void *args;
{
DB *dbp;
DB_ENV *dbenv;
DBC *dbc;
const char *progname;
disploop_args *dargs;
int ret, rval;
dargs = (disploop_args *)args;
progname = dargs->progname;
dbenv = dargs->dbenv;
dbc = NULL;
dbp = NULL;
for (;;) {
/* If we become master, shut this loop off. */
if (master_eid == SELF_EID)
break;
if (dbp == NULL) {
if ((ret = db_create(&dbp, dbenv, 0)) != 0) {
dbenv->err(dbenv, ret, "db_create");
return ((void *)EXIT_FAILURE);
}
if ((ret = dbp->open(dbp, NULL,
DATABASE, NULL, DB_BTREE, DB_RDONLY, 0)) != 0) {
if (ret == ENOENT) {
printf(
"No stock database yet available.\n");
if ((ret = dbp->close(dbp, 0)) != 0) {
dbenv->err(dbenv,
ret, "DB->close");
goto err;
}
dbp = NULL;
sleep(SLEEPTIME);
continue;
}
dbenv->err(dbenv, ret, "DB->open");
goto err;
}
}
if ((ret = dbp->cursor(dbp, NULL, &dbc, 0)) != 0) {
dbenv->err(dbenv, ret, "DB->cursor");
goto err;
}
if ((ret = print_stocks(dbc)) != 0) {
dbenv->err(dbenv, ret, "database traversal failed");
goto err;
}
if ((ret = dbc->c_close(dbc)) != 0) {
dbenv->err(dbenv, ret, "DB->close");
goto err;
}
dbc = NULL;
sleep(SLEEPTIME);
}
rval = EXIT_SUCCESS;
if (0) {
err: rval = EXIT_FAILURE;
}
if (dbc != NULL && (ret = dbc->c_close(dbc)) != 0) {
dbenv->err(dbenv, ret, "DB->close");
rval = EXIT_FAILURE;
}
if (dbp != NULL && (ret = dbp->close(dbp, 0)) != 0) {
dbenv->err(dbenv, ret, "DB->close");
return ((void *)EXIT_FAILURE);
}
return ((void *)rval);
}
static int
print_stocks(dbc)
DBC *dbc;
{
DBT key, data;
#define MAXKEYSIZE 10
#define MAXDATASIZE 20
char keybuf[MAXKEYSIZE + 1], databuf[MAXDATASIZE + 1];
int ret;
u_int32_t keysize, datasize;
memset(&key, 0, sizeof(key));
memset(&data, 0, sizeof(data));
printf("\tSymbol\tPrice\n");
printf("\t======\t=====\n");
for (ret = dbc->c_get(dbc, &key, &data, DB_FIRST);
ret == 0;
ret = dbc->c_get(dbc, &key, &data, DB_NEXT)) {
keysize = key.size > MAXKEYSIZE ? MAXKEYSIZE : key.size;
memcpy(keybuf, key.data, keysize);
keybuf[keysize] = '\0';
datasize = data.size >= MAXDATASIZE ? MAXDATASIZE : data.size;
memcpy(databuf, data.data, datasize);
databuf[datasize] = '\0';
printf("\t%s\t%s\n", keybuf, databuf);
}
printf("\n");
return (ret == DB_NOTFOUND ? 0 : ret);
}

View File

@ -1,303 +0,0 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 2001-2002
* Sleepycat Software. All rights reserved.
*
* $Id: ex_rq_main.c,v 1.23 2002/08/06 05:39:03 bostic Exp $
*/
#include <sys/types.h>
#include <pthread.h>
#include <errno.h>
#include <signal.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <db.h>
#include "ex_repquote.h"
/*
* Process globals (we could put these in the machtab I suppose.
*/
int master_eid;
char *myaddr;
static int env_init __P((const char *, const char *, DB_ENV **, machtab_t *,
u_int32_t));
static void usage __P((const char *));
int
main(argc, argv)
int argc;
char *argv[];
{
extern char *optarg;
extern int optind;
DB_ENV *dbenv;
DBT local;
enum { MASTER, CLIENT, UNKNOWN } whoami;
all_args aa;
connect_args ca;
machtab_t *machtab;
pthread_t all_thr, conn_thr;
repsite_t site, *sitep, self, *selfp;
struct sigaction sigact;
int maxsites, nsites, ret, priority, totalsites;
char *c, ch;
const char *home, *progname;
void *astatus, *cstatus;
master_eid = DB_EID_INVALID;
dbenv = NULL;
whoami = UNKNOWN;
machtab = NULL;
selfp = sitep = NULL;
maxsites = nsites = ret = totalsites = 0;
priority = 100;
home = "TESTDIR";
progname = "ex_repquote";
while ((ch = getopt(argc, argv, "Ch:Mm:n:o:p:")) != EOF)
switch (ch) {
case 'M':
whoami = MASTER;
master_eid = SELF_EID;
break;
case 'C':
whoami = CLIENT;
break;
case 'h':
home = optarg;
break;
case 'm':
if ((myaddr = strdup(optarg)) == NULL) {
fprintf(stderr,
"System error %s\n", strerror(errno));
goto err;
}
self.host = optarg;
self.host = strtok(self.host, ":");
if ((c = strtok(NULL, ":")) == NULL) {
fprintf(stderr, "Bad host specification.\n");
goto err;
}
self.port = atoi(c);
selfp = &self;
break;
case 'n':
totalsites = atoi(optarg);
break;
case 'o':
site.host = optarg;
site.host = strtok(site.host, ":");
if ((c = strtok(NULL, ":")) == NULL) {
fprintf(stderr, "Bad host specification.\n");
goto err;
}
site.port = atoi(c);
if (sitep == NULL || nsites >= maxsites) {
maxsites = maxsites == 0 ? 10 : 2 * maxsites;
if ((sitep = realloc(sitep,
maxsites * sizeof(repsite_t))) == NULL) {
fprintf(stderr, "System error %s\n",
strerror(errno));
goto err;
}
}
sitep[nsites++] = site;
break;
case 'p':
priority = atoi(optarg);
break;
case '?':
default:
usage(progname);
}
/* Error check command line. */
if (whoami == UNKNOWN) {
fprintf(stderr, "Must specify -M or -C.\n");
goto err;
}
if (selfp == NULL)
usage(progname);
if (home == NULL)
usage(progname);
/*
* Turn off SIGPIPE so that we don't kill processes when they
* happen to lose a connection at the wrong time.
*/
memset(&sigact, 0, sizeof(sigact));
sigact.sa_handler = SIG_IGN;
if ((ret = sigaction(SIGPIPE, &sigact, NULL)) != 0) {
fprintf(stderr,
"Unable to turn off SIGPIPE: %s\n", strerror(ret));
goto err;
}
/*
* We are hardcoding priorities here that all clients have the
* same priority except for a designated master who gets a higher
* priority.
*/
if ((ret =
machtab_init(&machtab, priority, totalsites)) != 0)
goto err;
/*
* We can know open our environment, although we're not ready to
* begin replicating. However, we want to have a dbenv around
* so that we can send it into any of our message handlers.
*/
if ((ret = env_init(progname, home, &dbenv, machtab, DB_RECOVER)) != 0)
goto err;
/*
* Now sets up comm infrastructure. There are two phases. First,
* we open our port for listening for incoming connections. Then
* we attempt to connect to every host we know about.
*/
ca.dbenv = dbenv;
ca.home = home;
ca.progname = progname;
ca.machtab = machtab;
ca.port = selfp->port;
if ((ret = pthread_create(&conn_thr, NULL, connect_thread, &ca)) != 0)
goto err;
aa.dbenv = dbenv;
aa.progname = progname;
aa.home = home;
aa.machtab = machtab;
aa.sites = sitep;
aa.nsites = nsites;
if ((ret = pthread_create(&all_thr, NULL, connect_all, &aa)) != 0)
goto err;
/*
* We have now got the entire communication infrastructure set up.
* It's time to declare ourselves to be a client or master.
*/
if (whoami == MASTER) {
if ((ret = dbenv->rep_start(dbenv, NULL, DB_REP_MASTER)) != 0) {
dbenv->err(dbenv, ret, "dbenv->rep_start failed");
goto err;
}
if ((ret = domaster(dbenv, progname)) != 0) {
dbenv->err(dbenv, ret, "Master failed");
goto err;
}
} else {
memset(&local, 0, sizeof(local));
local.data = myaddr;
local.size = strlen(myaddr) + 1;
if ((ret =
dbenv->rep_start(dbenv, &local, DB_REP_CLIENT)) != 0) {
dbenv->err(dbenv, ret, "dbenv->rep_start failed");
goto err;
}
/* Sleep to give ourselves a minute to find a master. */
sleep(5);
if ((ret = doclient(dbenv, progname, machtab)) != 0) {
dbenv->err(dbenv, ret, "Client failed");
goto err;
}
}
/* Wait on the connection threads. */
if (pthread_join(all_thr, &astatus) || pthread_join(conn_thr, &cstatus))
ret = errno;
if (ret == 0 &&
((int)astatus != EXIT_SUCCESS || (int)cstatus != EXIT_SUCCESS))
ret = -1;
err: if (machtab != NULL)
free(machtab);
if (dbenv != NULL)
(void)dbenv->close(dbenv, 0);
return (ret);
}
/*
* In this application, we specify all communication via the command line.
* In a real application, we would expect that information about the other
* sites in the system would be maintained in some sort of configuration
* file. The critical part of this interface is that we assume at startup
* that we can find out 1) what host/port we wish to listen on for connections,
* 2) a (possibly empty) list of other sites we should attempt to connect to.
* 3) whether we are a master or client (if we don't know, we should come up
* as a client and see if there is a master out there) and 4) what our
* Berkeley DB home environment is.
*
* These pieces of information are expressed by the following flags.
* -m host:port (required; m stands for me)
* -o host:port (optional; o stands for other; any number of these may be
* specified)
* -[MC] M for master/C for client
* -h home directory
* -n nsites (optional; number of sites in replication group; defaults to 0
* in which case we try to dynamically compute the number of sites in
* the replication group.)
* -p priority (optional: defaults to 100)
*/
static void
usage(progname)
const char *progname;
{
fprintf(stderr, "usage: %s ", progname);
fprintf(stderr, "[-CM][-h home][-o host:port][-m host:port]%s",
"[-n nsites][-p priority]\n");
exit(EXIT_FAILURE);
}
/* Open and configure an environment. */
int
env_init(progname, home, dbenvp, machtab, flags)
const char *progname, *home;
DB_ENV **dbenvp;
machtab_t *machtab;
u_int32_t flags;
{
DB_ENV *dbenv;
int ret;
char *prefix;
if ((prefix = malloc(strlen(progname) + 2)) == NULL) {
fprintf(stderr,
"%s: System error: %s\n", progname, strerror(errno));
return (errno);
}
sprintf(prefix, "%s:", progname);
if ((ret = db_env_create(&dbenv, 0)) != 0) {
fprintf(stderr, "%s: env create failed: %s\n",
progname, db_strerror(ret));
return (ret);
}
dbenv->set_errfile(dbenv, stderr);
dbenv->set_errpfx(dbenv, prefix);
/* (void)dbenv->set_verbose(dbenv, DB_VERB_REPLICATION, 1); */
(void)dbenv->set_cachesize(dbenv, 0, CACHESIZE, 0);
/* (void)dbenv->set_flags(dbenv, DB_TXN_NOSYNC, 1); */
dbenv->app_private = machtab;
(void)dbenv->set_rep_transport(dbenv, SELF_EID, quote_send);
flags |= DB_CREATE | DB_THREAD |
DB_INIT_LOCK | DB_INIT_LOG | DB_INIT_MPOOL | DB_INIT_TXN;
ret = dbenv->open(dbenv, home, flags, 0);
*dbenvp = dbenv;
return (ret);
}

View File

@ -1,165 +0,0 @@
/*-
* #include <pthread.h>
* See the file LICENSE for redistribution information.
*
* Copyright (c) 2001-2002
* Sleepycat Software. All rights reserved.
*
* $Id: ex_rq_master.c,v 1.22 2002/08/06 05:39:03 bostic Exp $
*/
#include <sys/types.h>
#include <errno.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <db.h>
#include "ex_repquote.h"
static void *master_loop __P((void *));
#define BUFSIZE 1024
int
domaster(dbenv, progname)
DB_ENV *dbenv;
const char *progname;
{
int ret, t_ret;
pthread_t interface_thr;
pthread_attr_t attr;
COMPQUIET(progname, NULL);
/* Spawn off a thread to handle the basic master interface. */
if ((ret = pthread_attr_init(&attr)) != 0 &&
(ret = pthread_attr_setdetachstate(&attr,
PTHREAD_CREATE_DETACHED)) != 0)
goto err;
if ((ret = pthread_create(&interface_thr,
&attr, master_loop, (void *)dbenv)) != 0)
goto err;
err: if ((t_ret = pthread_attr_destroy(&attr)) != 0 && ret == 0)
ret = t_ret;
return (ret);
}
static void *
master_loop(dbenvv)
void *dbenvv;
{
DB *dbp;
DB_ENV *dbenv;
DB_TXN *txn;
DBT key, data;
char buf[BUFSIZE], *rbuf;
int ret;
dbp = NULL;
txn = NULL;
dbenv = (DB_ENV *)dbenvv;
/*
* Check if the database exists and if it verifies cleanly.
* If it does, run with it; else recreate it and go. Note
* that we have to verify outside of the environment.
*/
#ifdef NOTDEF
if ((ret = db_create(&dbp, NULL, 0)) != 0)
return (ret);
if ((ret = dbp->verify(dbp, DATABASE, NULL, NULL, 0)) != 0) {
if ((ret = dbp->remove(dbp, DATABASE, NULL, 0)) != 0 &&
ret != DB_NOTFOUND && ret != ENOENT)
return (ret);
#endif
if ((ret = db_create(&dbp, dbenv, 0)) != 0)
return ((void *)ret);
if ((ret = dbenv->txn_begin(dbenv, NULL, &txn, 0)) != 0)
goto err;
if ((ret = dbp->open(dbp, txn, DATABASE,
NULL, DB_BTREE, DB_CREATE /* | DB_THREAD */, 0)) != 0)
goto err;
ret = txn->commit(txn, 0);
txn = NULL;
if (ret != 0) {
dbp = NULL;
goto err;
}
#ifdef NOTDEF
} else {
/* Reopen in the environment. */
if ((ret = dbp->close(dbp, 0)) != 0)
return (ret);
if ((ret = db_create(&dbp, dbenv, 0)) != 0)
return (ret);
if ((ret = dbp->open(dbp,
DATABASE, NULL, DB_UNKNOWN, DB_THREAD, 0)) != 0)
goto err;
}
#endif
/*
* XXX
* It would probably be kind of cool to do this in Tcl and
* have a nice GUI. It would also be cool to be independently
* wealthy.
*/
memset(&key, 0, sizeof(key));
memset(&data, 0, sizeof(data));
for (;;) {
printf("QUOTESERVER> ");
fflush(stdout);
if (fgets(buf, sizeof(buf), stdin) == NULL)
break;
(void)strtok(&buf[0], " \t\n");
rbuf = strtok(NULL, " \t\n");
if (rbuf == NULL || rbuf[0] == '\0') {
if (strncmp(buf, "exit", 4) == 0 ||
strncmp(buf, "quit", 4) == 0)
break;
dbenv->errx(dbenv, "Format: TICKER VALUE");
continue;
}
key.data = buf;
key.size = strlen(buf);
data.data = rbuf;
data.size = strlen(rbuf);
if ((ret = dbenv->txn_begin(dbenv, NULL, &txn, 0)) != 0)
goto err;
switch (ret =
dbp->put(dbp, txn, &key, &data, 0)) {
case 0:
break;
default:
dbp->err(dbp, ret, "DB->put");
if (ret != DB_KEYEXIST)
goto err;
break;
}
ret = txn->commit(txn, 0);
txn = NULL;
if (ret != 0)
goto err;
}
err: if (txn != NULL)
(void)txn->abort(txn);
if (dbp != NULL)
(void)dbp->close(dbp, DB_NOSYNC);
return ((void *)ret);
}

View File

@ -1,692 +0,0 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 2001-2002
* Sleepycat Software. All rights reserved.
*
* $Id: ex_rq_net.c,v 1.37 2002/08/06 05:39:04 bostic Exp $
*/
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <sys/wait.h>
#include <assert.h>
#include <errno.h>
#include <netdb.h>
#include <pthread.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <db.h>
#include <dbinc/queue.h> /* !!!: for the LIST_XXX macros. */
#include "ex_repquote.h"
int machtab_add __P((machtab_t *, int, u_int32_t, int, int *));
ssize_t readn __P((int, void *, size_t));
/*
* This file defines the communication infrastructure for the ex_repquote
* sample application.
*
* This application uses TCP/IP for its communication. In an N-site
* replication group, this means that there are N * N communication
* channels so that every site can communicate with every other site
* (this allows elections to be held when the master fails). We do
* not require that anyone know about all sites when the application
* starts up. In order to communicate, the application should know
* about someone, else it has no idea how to ever get in the game.
*
* Communication is handled via a number of different threads. These
* thread functions are implemented in rep_util.c In this file, we
* define the data structures that maintain the state that describes
* the comm infrastructure, the functions that manipulates this state
* and the routines used to actually send and receive data over the
* sockets.
*/
/*
* The communication infrastructure is represented by a machine table,
* machtab_t, which is essentially a mutex-protected linked list of members
* of the group. The machtab also contains the parameters that are needed
* to call for an election. We hardwire values for these parameters in the
* init function, but these could be set via some configuration setup in a
* real application. We reserve the machine-id 1 to refer to ourselves and
* make the machine-id 0 be invalid.
*/
#define MACHID_INVALID 0
#define MACHID_SELF 1
struct __machtab {
LIST_HEAD(__machlist, __member) machlist;
int nextid;
pthread_mutex_t mtmutex;
u_int32_t timeout_time;
int current;
int max;
int nsites;
int priority;
};
/* Data structure that describes each entry in the machtab. */
struct __member {
u_int32_t hostaddr; /* Host IP address. */
int port; /* Port number. */
int eid; /* Application-specific machine id. */
int fd; /* File descriptor for the socket. */
LIST_ENTRY(__member) links;
/* For linked list of all members we know of. */
};
static int quote_send_broadcast __P((machtab_t *,
const DBT *, const DBT *, u_int32_t));
static int quote_send_one __P((const DBT *, const DBT *, int, u_int32_t));
/*
* machtab_init --
* Initialize the machine ID table.
* XXX Right now we treat the number of sites as the maximum
* number we've ever had on the list at one time. We probably
* want to make that smarter.
*/
int
machtab_init(machtabp, pri, nsites)
machtab_t **machtabp;
int pri, nsites;
{
int ret;
machtab_t *machtab;
if ((machtab = malloc(sizeof(machtab_t))) == NULL)
return (ENOMEM);
LIST_INIT(&machtab->machlist);
/* Reserve eid's 0 and 1. */
machtab->nextid = 2;
machtab->timeout_time = 2 * 1000000; /* 2 seconds. */
machtab->current = machtab->max = 0;
machtab->priority = pri;
machtab->nsites = nsites;
ret = pthread_mutex_init(&machtab->mtmutex, NULL);
*machtabp = machtab;
return (ret);
}
/*
* machtab_add --
* Add a file descriptor to the table of machines, returning
* a new machine ID.
*/
int
machtab_add(machtab, fd, hostaddr, port, idp)
machtab_t *machtab;
int fd;
u_int32_t hostaddr;
int port, *idp;
{
int ret;
member_t *m, *member;
if ((member = malloc(sizeof(member_t))) == NULL)
return (ENOMEM);
member->fd = fd;
member->hostaddr = hostaddr;
member->port = port;
if ((ret = pthread_mutex_lock(&machtab->mtmutex)) != 0)
return (ret);
for (m = LIST_FIRST(&machtab->machlist);
m != NULL; m = LIST_NEXT(m, links))
if (m->hostaddr == hostaddr && m->port == port)
break;
if (m == NULL) {
member->eid = machtab->nextid++;
LIST_INSERT_HEAD(&machtab->machlist, member, links);
} else
member->eid = m->eid;
ret = pthread_mutex_unlock(&machtab->mtmutex);
if (idp != NULL)
*idp = member->eid;
if (m == NULL) {
if (++machtab->current > machtab->max)
machtab->max = machtab->current;
} else {
free(member);
ret = EEXIST;
}
return (ret);
}
/*
* machtab_getinfo --
* Return host and port information for a particular machine id.
*/
int
machtab_getinfo(machtab, eid, hostp, portp)
machtab_t *machtab;
int eid;
u_int32_t *hostp;
int *portp;
{
int ret;
member_t *member;
if ((ret = pthread_mutex_lock(&machtab->mtmutex)) != 0)
return (ret);
for (member = LIST_FIRST(&machtab->machlist);
member != NULL;
member = LIST_NEXT(member, links))
if (member->eid == eid) {
*hostp = member->hostaddr;
*portp = member->port;
break;
}
if ((ret = pthread_mutex_unlock(&machtab->mtmutex)) != 0)
return (ret);
return (member != NULL ? 0 : EINVAL);
}
/*
* machtab_rem --
* Remove a mapping from the table of machines. Lock indicates
* whether we need to lock the machtab or not (0 indicates we do not
* need to lock; non-zero indicates that we do need to lock).
*/
int
machtab_rem(machtab, eid, lock)
machtab_t *machtab;
int eid;
int lock;
{
int found, ret;
member_t *member;
ret = 0;
if (lock && (ret = pthread_mutex_lock(&machtab->mtmutex)) != 0)
return (ret);
for (found = 0, member = LIST_FIRST(&machtab->machlist);
member != NULL;
member = LIST_NEXT(member, links))
if (member->eid == eid) {
found = 1;
LIST_REMOVE(member, links);
(void)close(member->fd);
free(member);
machtab->current--;
break;
}
if (LIST_FIRST(&machtab->machlist) == NULL)
machtab->nextid = 2;
if (lock)
ret = pthread_mutex_unlock(&machtab->mtmutex);
return (ret);
}
void
machtab_parm(machtab, nump, prip, timeoutp)
machtab_t *machtab;
int *nump, *prip;
u_int32_t *timeoutp;
{
if (machtab->nsites == 0)
*nump = machtab->max;
else
*nump = machtab->nsites;
*prip = machtab->priority;
*timeoutp = machtab->timeout_time;
}
/*
* listen_socket_init --
* Initialize a socket for listening on the specified port. Returns
* a file descriptor for the socket, ready for an accept() call
* in a thread that we're happy to let block.
*/
int
listen_socket_init(progname, port)
const char *progname;
int port;
{
int s;
struct protoent *proto;
struct sockaddr_in si;
if ((proto = getprotobyname("tcp")) == NULL)
return (-1);
if ((s = socket(AF_INET, SOCK_STREAM, proto->p_proto)) < 0)
return (-1);
memset(&si, 0, sizeof(si));
si.sin_family = AF_INET;
si.sin_addr.s_addr = htonl(INADDR_ANY);
si.sin_port = htons(port);
if (bind(s, (struct sockaddr *)&si, sizeof(si)) != 0)
goto err;
if (listen(s, 5) != 0)
goto err;
return (s);
err: fprintf(stderr, "%s: %s", progname, strerror(errno));
close (s);
return (-1);
}
/*
* listen_socket_accept --
* Accept a connection on a socket. This is essentially just a wrapper
* for accept(3).
*/
int
listen_socket_accept(machtab, progname, s, eidp)
machtab_t *machtab;
const char *progname;
int s, *eidp;
{
struct sockaddr_in si;
int si_len;
int host, ns, port, ret;
COMPQUIET(progname, NULL);
wait: memset(&si, 0, sizeof(si));
si_len = sizeof(si);
ns = accept(s, (struct sockaddr *)&si, &si_len);
host = ntohl(si.sin_addr.s_addr);
port = ntohs(si.sin_port);
ret = machtab_add(machtab, ns, host, port, eidp);
if (ret == EEXIST) {
close(ns);
goto wait;
} else if (ret != 0)
goto err;
return (ns);
err: close(ns);
return (-1);
}
/*
* get_accepted_socket --
* Listen on the specified port, and return a file descriptor
* when we have accepted a connection on it.
*/
int
get_accepted_socket(progname, port)
const char *progname;
int port;
{
struct protoent *proto;
struct sockaddr_in si;
int si_len;
int s, ns;
if ((proto = getprotobyname("tcp")) == NULL)
return (-1);
if ((s = socket(AF_INET, SOCK_STREAM, proto->p_proto)) < 0)
return (-1);
memset(&si, 0, sizeof(si));
si.sin_family = AF_INET;
si.sin_addr.s_addr = htonl(INADDR_ANY);
si.sin_port = htons(port);
if (bind(s, (struct sockaddr *)&si, sizeof(si)) != 0)
goto err;
if (listen(s, 5) != 0)
goto err;
memset(&si, 0, sizeof(si));
si_len = sizeof(si);
ns = accept(s, (struct sockaddr *)&si, &si_len);
return (ns);
err: fprintf(stderr, "%s: %s", progname, strerror(errno));
close (s);
return (-1);
}
/*
* get_connected_socket --
* Connect to the specified port of the specified remote machine,
* and return a file descriptor when we have accepted a connection on it.
* Add this connection to the machtab. If we already have a connection
* open to this machine, then don't create another one, return the eid
* of the connection (in *eidp) and set is_open to 1. Return 0.
*/
int
get_connected_socket(machtab, progname, remotehost, port, is_open, eidp)
machtab_t *machtab;
const char *progname, *remotehost;
int port, *is_open, *eidp;
{
int ret, s;
struct hostent *hp;
struct protoent *proto;
struct sockaddr_in si;
u_int32_t addr;
*is_open = 0;
if ((proto = getprotobyname("tcp")) == NULL)
return (-1);
if ((hp = gethostbyname(remotehost)) == NULL) {
fprintf(stderr, "%s: host not found: %s\n", progname,
strerror(errno));
return (-1);
}
if ((s = socket(AF_INET, SOCK_STREAM, proto->p_proto)) < 0)
return (-1);
memset(&si, 0, sizeof(si));
memcpy((char *)&si.sin_addr, hp->h_addr, hp->h_length);
addr = ntohl(si.sin_addr.s_addr);
ret = machtab_add(machtab, s, addr, port, eidp);
if (ret == EEXIST) {
*is_open = 1;
close(s);
return (0);
} else if (ret != 0) {
close (s);
return (-1);
}
si.sin_family = AF_INET;
si.sin_port = htons(port);
if (connect(s, (struct sockaddr *)&si, sizeof(si)) < 0) {
fprintf(stderr, "%s: connection failed: %s",
progname, strerror(errno));
(void)machtab_rem(machtab, *eidp, 1);
return (-1);
}
return (s);
}
/*
* get_next_message --
* Read a single message from the specified file descriptor, and
* return it in the format used by rep functions (two DBTs and a type).
*
* This function is called in a loop by both clients and masters, and
* the resulting DBTs are manually dispatched to DB_ENV->rep_process_message().
*/
int
get_next_message(fd, rec, control)
int fd;
DBT *rec, *control;
{
size_t nr;
u_int32_t rsize, csize;
u_int8_t *recbuf, *controlbuf;
/*
* The protocol we use on the wire is dead simple:
*
* 4 bytes - rec->size
* (# read above) - rec->data
* 4 bytes - control->size
* (# read above) - control->data
*/
/* Read rec->size. */
nr = readn(fd, &rsize, 4);
if (nr != 4)
return (1);
/* Read the record itself. */
if (rsize > 0) {
if (rec->size < rsize)
rec->data = realloc(rec->data, rsize);
recbuf = rec->data;
nr = readn(fd, recbuf, rsize);
} else {
if (rec->data != NULL)
free(rec->data);
rec->data = NULL;
}
rec->size = rsize;
/* Read control->size. */
nr = readn(fd, &csize, 4);
if (nr != 4)
return (1);
/* Read the control struct itself. */
if (csize > 0) {
controlbuf = control->data;
if (control->size < csize)
controlbuf = realloc(controlbuf, csize);
nr = readn(fd, controlbuf, csize);
if (nr != csize)
return (1);
} else {
if (control->data != NULL)
free(control->data);
controlbuf = NULL;
}
control->data = controlbuf;
control->size = csize;
return (0);
}
/*
* readn --
* Read a full n characters from a file descriptor, unless we get an error
* or EOF.
*/
ssize_t
readn(fd, vptr, n)
int fd;
void *vptr;
size_t n;
{
size_t nleft;
ssize_t nread;
char *ptr;
ptr = vptr;
nleft = n;
while (nleft > 0) {
if ( (nread = read(fd, ptr, nleft)) < 0) {
/*
* Call read() again on interrupted system call;
* on other errors, bail.
*/
if (errno == EINTR)
nread = 0;
else
return (-1);
} else if (nread == 0)
break; /* EOF */
nleft -= nread;
ptr += nread;
}
return (n - nleft);
}
/*
* quote_send --
* The f_send function for DB_ENV->set_rep_transport.
*/
int
quote_send(dbenv, control, rec, eid, flags)
DB_ENV *dbenv;
const DBT *control, *rec;
int eid;
u_int32_t flags;
{
int fd, n, ret, t_ret;
machtab_t *machtab;
member_t *m;
machtab = (machtab_t *)dbenv->app_private;
if (eid == DB_EID_BROADCAST) {
/*
* Right now, we do not require successful transmission.
* I'd like to move this requiring at least one successful
* transmission on PERMANENT requests.
*/
n = quote_send_broadcast(machtab, rec, control, flags);
if (n < 0 /*|| (n == 0 && LF_ISSET(DB_REP_PERMANENT))*/)
return (DB_REP_UNAVAIL);
return (0);
}
if ((ret = pthread_mutex_lock(&machtab->mtmutex)) != 0)
return (ret);
fd = 0;
for (m = LIST_FIRST(&machtab->machlist); m != NULL;
m = LIST_NEXT(m, links)) {
if (m->eid == eid) {
fd = m->fd;
break;
}
}
if (fd == 0) {
dbenv->err(dbenv, DB_REP_UNAVAIL,
"quote_send: cannot find machine ID %d", eid);
return (DB_REP_UNAVAIL);
}
ret = quote_send_one(rec, control, fd, flags);
if ((t_ret = (pthread_mutex_unlock(&machtab->mtmutex))) != 0 &&
ret == 0)
ret = t_ret;
return (ret);
}
/*
* quote_send_broadcast --
* Send a message to everybody.
* Returns the number of sites to which this message was successfully
* communicated. A -1 indicates a fatal error.
*/
static int
quote_send_broadcast(machtab, rec, control, flags)
machtab_t *machtab;
const DBT *rec, *control;
u_int32_t flags;
{
int ret, sent;
member_t *m, *next;
if ((ret = pthread_mutex_lock(&machtab->mtmutex)) != 0)
return (0);
sent = 0;
for (m = LIST_FIRST(&machtab->machlist); m != NULL; m = next) {
next = LIST_NEXT(m, links);
if ((ret = quote_send_one(rec, control, m->fd, flags)) != 0) {
(void)machtab_rem(machtab, m->eid, 0);
} else
sent++;
}
if (pthread_mutex_unlock(&machtab->mtmutex) != 0)
return (-1);
return (sent);
}
/*
* quote_send_one --
* Send a message to a single machine, given that machine's file
* descriptor.
*
* !!!
* Note that the machtab mutex should be held through this call.
* It doubles as a synchronizer to make sure that two threads don't
* intersperse writes that are part of two single messages.
*/
static int
quote_send_one(rec, control, fd, flags)
const DBT *rec, *control;
int fd;
u_int32_t flags;
{
int retry;
ssize_t bytes_left, nw;
u_int8_t *wp;
COMPQUIET(flags, 0);
/*
* The protocol is simply: write rec->size, write rec->data,
* write control->size, write control->data.
*/
nw = write(fd, &rec->size, 4);
if (nw != 4)
return (DB_REP_UNAVAIL);
if (rec->size > 0) {
nw = write(fd, rec->data, rec->size);
if (nw < 0)
return (DB_REP_UNAVAIL);
if (nw != (ssize_t)rec->size) {
/* Try a couple of times to finish the write. */
wp = (u_int8_t *)rec->data + nw;
bytes_left = rec->size - nw;
for (retry = 0; bytes_left > 0 && retry < 3; retry++) {
nw = write(fd, wp, bytes_left);
if (nw < 0)
return (DB_REP_UNAVAIL);
bytes_left -= nw;
wp += nw;
}
if (bytes_left > 0)
return (DB_REP_UNAVAIL);
}
}
nw = write(fd, &control->size, 4);
if (nw != 4)
return (DB_REP_UNAVAIL);
if (control->size > 0) {
nw = write(fd, control->data, control->size);
if (nw != (ssize_t)control->size)
return (DB_REP_UNAVAIL);
}
return (0);
}

View File

@ -1,412 +0,0 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 2001-2002
* Sleepycat Software. All rights reserved.
*
* $Id: ex_rq_util.c,v 1.20 2002/08/06 05:39:04 bostic Exp $
*/
#include <sys/types.h>
#include <errno.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <db.h>
#include "ex_repquote.h"
static int connect_site __P((DB_ENV *, machtab_t *, const char *,
repsite_t *, int *, int *));
void * elect_thread __P((void *));
typedef struct {
DB_ENV *dbenv;
machtab_t *machtab;
} elect_args;
typedef struct {
DB_ENV *dbenv;
const char *progname;
const char *home;
int fd;
u_int32_t eid;
machtab_t *tab;
} hm_loop_args;
/*
* This is a generic message handling loop that is used both by the
* master to accept messages from a client as well as by clients
* to communicate with other clients.
*/
void *
hm_loop(args)
void *args;
{
DB_ENV *dbenv;
DBT rec, control;
const char *c, *home, *progname;
int fd, eid, n, newm;
int open, pri, r, ret, t_ret, tmpid;
elect_args *ea;
hm_loop_args *ha;
machtab_t *tab;
pthread_t elect_thr;
repsite_t self;
u_int32_t timeout;
void *status;
ea = NULL;
ha = (hm_loop_args *)args;
dbenv = ha->dbenv;
fd = ha->fd;
home = ha->home;
eid = ha->eid;
progname = ha->progname;
tab = ha->tab;
free(ha);
memset(&rec, 0, sizeof(DBT));
memset(&control, 0, sizeof(DBT));
for (ret = 0; ret == 0;) {
if ((ret = get_next_message(fd, &rec, &control)) != 0) {
/*
* Close this connection; if it's the master call
* for an election.
*/
close(fd);
if ((ret = machtab_rem(tab, eid, 1)) != 0)
break;
/*
* If I'm the master, I just lost a client and this
* thread is done.
*/
if (master_eid == SELF_EID)
break;
/*
* If I was talking with the master and the master
* went away, I need to call an election; else I'm
* done.
*/
if (master_eid != eid)
break;
master_eid = DB_EID_INVALID;
machtab_parm(tab, &n, &pri, &timeout);
if ((ret = dbenv->rep_elect(dbenv,
n, pri, timeout, &newm)) != 0)
continue;
/*
* Regardless of the results, the site I was talking
* to is gone, so I have nothing to do but exit.
*/
if (newm == SELF_EID && (ret =
dbenv->rep_start(dbenv, NULL, DB_REP_MASTER)) == 0)
ret = domaster(dbenv, progname);
break;
}
tmpid = eid;
switch(r = dbenv->rep_process_message(dbenv,
&control, &rec, &tmpid)) {
case DB_REP_NEWSITE:
/*
* Check if we got sent connect information and if we
* did, if this is me or if we already have a
* connection to this new site. If we don't,
* establish a new one.
*/
/* No connect info. */
if (rec.size == 0)
break;
/* It's me, do nothing. */
if (strncmp(myaddr, rec.data, rec.size) == 0)
break;
self.host = (char *)rec.data;
self.host = strtok(self.host, ":");
if ((c = strtok(NULL, ":")) == NULL) {
dbenv->errx(dbenv, "Bad host specification");
goto out;
}
self.port = atoi(c);
/*
* We try to connect to the new site. If we can't,
* we treat it as an error since we know that the site
* should be up if we got a message from it (even
* indirectly).
*/
if ((ret = connect_site(dbenv,
tab, progname, &self, &open, &eid)) != 0)
goto out;
break;
case DB_REP_HOLDELECTION:
if (master_eid == SELF_EID)
break;
/* Make sure that previous election has finished. */
if (ea != NULL) {
(void)pthread_join(elect_thr, &status);
ea = NULL;
}
if ((ea = calloc(sizeof(elect_args), 1)) == NULL) {
ret = errno;
goto out;
}
ea->dbenv = dbenv;
ea->machtab = tab;
ret = pthread_create(&elect_thr,
NULL, elect_thread, (void *)ea);
break;
case DB_REP_NEWMASTER:
/* Check if it's us. */
master_eid = tmpid;
if (tmpid == SELF_EID) {
if ((ret = dbenv->rep_start(dbenv,
NULL, DB_REP_MASTER)) != 0)
goto out;
ret = domaster(dbenv, progname);
}
break;
case 0:
break;
default:
dbenv->err(dbenv, r, "DB_ENV->rep_process_message");
break;
}
}
out: if ((t_ret = machtab_rem(tab, eid, 1)) != 0 && ret == 0)
ret = t_ret;
/* Don't close the environment before any children exit. */
if (ea != NULL)
(void)pthread_join(elect_thr, &status);
return ((void *)ret);
}
/*
* This is a generic thread that spawns a thread to listen for connections
* on a socket and then spawns off child threads to handle each new
* connection.
*/
void *
connect_thread(args)
void *args;
{
DB_ENV *dbenv;
const char *home, *progname;
int fd, i, eid, ns, port, ret;
hm_loop_args *ha;
connect_args *cargs;
machtab_t *machtab;
#define MAX_THREADS 25
pthread_t hm_thrs[MAX_THREADS];
pthread_attr_t attr;
ha = NULL;
cargs = (connect_args *)args;
dbenv = cargs->dbenv;
home = cargs->home;
progname = cargs->progname;
machtab = cargs->machtab;
port = cargs->port;
if ((ret = pthread_attr_init(&attr)) != 0)
return ((void *)EXIT_FAILURE);
if ((ret =
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED)) != 0)
goto err;
/*
* Loop forever, accepting connections from new machines,
* and forking off a thread to handle each.
*/
if ((fd = listen_socket_init(progname, port)) < 0) {
ret = errno;
goto err;
}
for (i = 0; i < MAX_THREADS; i++) {
if ((ns = listen_socket_accept(machtab,
progname, fd, &eid)) < 0) {
ret = errno;
goto err;
}
if ((ha = calloc(sizeof(hm_loop_args), 1)) == NULL)
goto err;
ha->progname = progname;
ha->home = home;
ha->fd = ns;
ha->eid = eid;
ha->tab = machtab;
ha->dbenv = dbenv;
if ((ret = pthread_create(&hm_thrs[i++], &attr,
hm_loop, (void *)ha)) != 0)
goto err;
ha = NULL;
}
/* If we fell out, we ended up with too many threads. */
dbenv->errx(dbenv, "Too many threads");
ret = ENOMEM;
err: pthread_attr_destroy(&attr);
return (ret == 0 ? (void *)EXIT_SUCCESS : (void *)EXIT_FAILURE);
}
/*
* Open a connection to everyone that we've been told about. If we
* cannot open some connections, keep trying.
*/
void *
connect_all(args)
void *args;
{
DB_ENV *dbenv;
all_args *aa;
const char *home, *progname;
hm_loop_args *ha;
int failed, i, eid, nsites, open, ret, *success;
machtab_t *machtab;
repsite_t *sites;
ha = NULL;
aa = (all_args *)args;
dbenv = aa->dbenv;
progname = aa->progname;
home = aa->home;
machtab = aa->machtab;
nsites = aa->nsites;
sites = aa->sites;
ret = 0;
/* Some implementations of calloc are sad about alloc'ing 0 things. */
if ((success = calloc(nsites > 0 ? nsites : 1, sizeof(int))) == NULL) {
dbenv->err(dbenv, errno, "connect_all");
ret = 1;
goto err;
}
for (failed = nsites; failed > 0;) {
for (i = 0; i < nsites; i++) {
if (success[i])
continue;
ret = connect_site(dbenv, machtab,
progname, &sites[i], &open, &eid);
/*
* If we couldn't make the connection, this isn't
* fatal to the loop, but we have nothing further
* to do on this machine at the moment.
*/
if (ret == DB_REP_UNAVAIL)
continue;
if (ret != 0)
goto err;
failed--;
success[i] = 1;
/* If the connection is already open, we're done. */
if (ret == 0 && open == 1)
continue;
}
sleep(1);
}
err: free(success);
return (ret ? (void *)EXIT_FAILURE : (void *)EXIT_SUCCESS);
}
int
connect_site(dbenv, machtab, progname, site, is_open, eidp)
DB_ENV *dbenv;
machtab_t *machtab;
const char *progname;
repsite_t *site;
int *is_open;
int *eidp;
{
int ret, s;
hm_loop_args *ha;
pthread_t hm_thr;
if ((s = get_connected_socket(machtab, progname,
site->host, site->port, is_open, eidp)) < 0)
return (DB_REP_UNAVAIL);
if (*is_open)
return (0);
if ((ha = calloc(sizeof(hm_loop_args), 1)) == NULL) {
ret = errno;
goto err;
}
ha->progname = progname;
ha->fd = s;
ha->eid = *eidp;
ha->tab = machtab;
ha->dbenv = dbenv;
if ((ret = pthread_create(&hm_thr, NULL,
hm_loop, (void *)ha)) != 0) {
dbenv->err(dbenv, ret, "connect site");
goto err1;
}
return (0);
err1: free(ha);
err:
return (ret);
}
/*
* We need to spawn off a new thread in which to hold an election in
* case we are the only thread listening on for messages.
*/
void *
elect_thread(args)
void *args;
{
DB_ENV *dbenv;
elect_args *eargs;
int n, ret, pri;
machtab_t *machtab;
u_int32_t timeout;
eargs = (elect_args *)args;
dbenv = eargs->dbenv;
machtab = eargs->machtab;
free(eargs);
machtab_parm(machtab, &n, &pri, &timeout);
while ((ret =
dbenv->rep_elect(dbenv, n, pri, timeout, &master_eid)) != 0)
sleep(2);
/* Check if it's us. */
if (master_eid == SELF_EID)
ret = dbenv->rep_start(dbenv, NULL, DB_REP_MASTER);
return ((void *)(ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE));
}

View File

@ -1,629 +0,0 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 1997-2002
* Sleepycat Software. All rights reserved.
*
* $Id: ex_thread.c,v 11.34 2002/08/15 14:37:13 bostic Exp $
*/
#include <sys/types.h>
#include <sys/time.h>
#include <errno.h>
#include <pthread.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#ifdef _WIN32
extern int getopt(int, char * const *, const char *);
#else
#include <unistd.h>
#endif
#include <db.h>
/*
* NB: This application is written using POSIX 1003.1b-1993 pthreads
* interfaces, which may not be portable to your system.
*/
extern int sched_yield __P((void)); /* Pthread yield function. */
int db_init __P((const char *));
void *deadlock __P((void *));
void fatal __P((const char *, int, int));
void onint __P((int));
int main __P((int, char *[]));
int reader __P((int));
void stats __P((void));
void *trickle __P((void *));
void *tstart __P((void *));
int usage __P((void));
void word __P((void));
int writer __P((int));
int quit; /* Interrupt handling flag. */
struct _statistics {
int aborted; /* Write. */
int aborts; /* Read/write. */
int adds; /* Write. */
int deletes; /* Write. */
int txns; /* Write. */
int found; /* Read. */
int notfound; /* Read. */
} *perf;
const char
*progname = "ex_thread"; /* Program name. */
#define DATABASE "access.db" /* Database name. */
#define WORDLIST "../test/wordlist" /* Dictionary. */
/*
* We can seriously increase the number of collisions and transaction
* aborts by yielding the scheduler after every DB call. Specify the
* -p option to do this.
*/
int punish; /* -p */
int nlist; /* -n */
int nreaders; /* -r */
int verbose; /* -v */
int nwriters; /* -w */
DB *dbp; /* Database handle. */
DB_ENV *dbenv; /* Database environment. */
int nthreads; /* Total threads. */
char **list; /* Word list. */
/*
* ex_thread --
* Run a simple threaded application of some numbers of readers and
* writers competing for a set of words.
*
* Example UNIX shell script to run this program:
* % rm -rf TESTDIR
* % mkdir TESTDIR
* % ex_thread -h TESTDIR
*/
int
main(argc, argv)
int argc;
char *argv[];
{
extern char *optarg;
extern int errno, optind;
DB_TXN *txnp;
pthread_t *tids;
int ch, i, ret;
const char *home;
void *retp;
txnp = NULL;
nlist = 1000;
nreaders = nwriters = 4;
home = "TESTDIR";
while ((ch = getopt(argc, argv, "h:pn:r:vw:")) != EOF)
switch (ch) {
case 'h':
home = optarg;
break;
case 'p':
punish = 1;
break;
case 'n':
nlist = atoi(optarg);
break;
case 'r':
nreaders = atoi(optarg);
break;
case 'v':
verbose = 1;
break;
case 'w':
nwriters = atoi(optarg);
break;
case '?':
default:
return (usage());
}
argc -= optind;
argv += optind;
/* Initialize the random number generator. */
srand(getpid() | time(NULL));
/* Register the signal handler. */
(void)signal(SIGINT, onint);
/* Build the key list. */
word();
/* Remove the previous database. */
(void)remove(DATABASE);
/* Initialize the database environment. */
if ((ret = db_init(home)) != 0)
return (ret);
/* Initialize the database. */
if ((ret = db_create(&dbp, dbenv, 0)) != 0) {
dbenv->err(dbenv, ret, "db_create");
(void)dbenv->close(dbenv, 0);
return (EXIT_FAILURE);
}
if ((ret = dbp->set_pagesize(dbp, 1024)) != 0) {
dbp->err(dbp, ret, "set_pagesize");
goto err;
}
if ((ret = dbenv->txn_begin(dbenv, NULL, &txnp, 0)) != 0)
fatal("txn_begin", ret, 1);
if ((ret = dbp->open(dbp, txnp,
DATABASE, NULL, DB_BTREE, DB_CREATE | DB_THREAD, 0664)) != 0) {
dbp->err(dbp, ret, "%s: open", DATABASE);
goto err;
} else {
ret = txnp->commit(txnp, 0);
txnp = NULL;
if (ret != 0)
goto err;
}
nthreads = nreaders + nwriters + 2;
printf("Running: readers %d, writers %d\n", nreaders, nwriters);
fflush(stdout);
/* Create statistics structures, offset by 1. */
if ((perf = calloc(nreaders + nwriters + 1, sizeof(*perf))) == NULL)
fatal(NULL, errno, 1);
/* Create thread ID structures. */
if ((tids = malloc(nthreads * sizeof(pthread_t))) == NULL)
fatal(NULL, errno, 1);
/* Create reader/writer threads. */
for (i = 0; i < nreaders + nwriters; ++i)
if ((ret =
pthread_create(&tids[i], NULL, tstart, (void *)i)) != 0)
fatal("pthread_create", ret > 0 ? ret : errno, 1);
/* Create buffer pool trickle thread. */
if (pthread_create(&tids[i], NULL, trickle, &i))
fatal("pthread_create", errno, 1);
++i;
/* Create deadlock detector thread. */
if (pthread_create(&tids[i], NULL, deadlock, &i))
fatal("pthread_create", errno, 1);
/* Wait for the threads. */
for (i = 0; i < nthreads; ++i)
(void)pthread_join(tids[i], &retp);
printf("Exiting\n");
stats();
err: if (txnp != NULL)
(void)txnp->abort(txnp);
(void)dbp->close(dbp, 0);
(void)dbenv->close(dbenv, 0);
return (EXIT_SUCCESS);
}
int
reader(id)
int id;
{
DBT key, data;
int n, ret;
char buf[64];
/*
* DBT's must use local memory or malloc'd memory if the DB handle
* is accessed in a threaded fashion.
*/
memset(&key, 0, sizeof(DBT));
memset(&data, 0, sizeof(DBT));
data.flags = DB_DBT_MALLOC;
/*
* Read-only threads do not require transaction protection, unless
* there's a need for repeatable reads.
*/
while (!quit) {
/* Pick a key at random, and look it up. */
n = rand() % nlist;
key.data = list[n];
key.size = strlen(key.data);
if (verbose) {
sprintf(buf, "reader: %d: list entry %d\n", id, n);
write(STDOUT_FILENO, buf, strlen(buf));
}
switch (ret = dbp->get(dbp, NULL, &key, &data, 0)) {
case DB_LOCK_DEADLOCK: /* Deadlock. */
++perf[id].aborts;
break;
case 0: /* Success. */
++perf[id].found;
free(data.data);
break;
case DB_NOTFOUND: /* Not found. */
++perf[id].notfound;
break;
default:
sprintf(buf,
"reader %d: dbp->get: %s", id, (char *)key.data);
fatal(buf, ret, 0);
}
}
return (0);
}
int
writer(id)
int id;
{
DBT key, data;
DB_TXN *tid;
time_t now, then;
int n, ret;
char buf[256], dbuf[10000];
time(&now);
then = now;
/*
* DBT's must use local memory or malloc'd memory if the DB handle
* is accessed in a threaded fashion.
*/
memset(&key, 0, sizeof(DBT));
memset(&data, 0, sizeof(DBT));
data.data = dbuf;
data.ulen = sizeof(dbuf);
data.flags = DB_DBT_USERMEM;
while (!quit) {
/* Pick a random key. */
n = rand() % nlist;
key.data = list[n];
key.size = strlen(key.data);
if (verbose) {
sprintf(buf, "writer: %d: list entry %d\n", id, n);
write(STDOUT_FILENO, buf, strlen(buf));
}
/* Abort and retry. */
if (0) {
retry: if ((ret = tid->abort(tid)) != 0)
fatal("DB_TXN->abort", ret, 1);
++perf[id].aborts;
++perf[id].aborted;
}
/* Thread #1 prints out the stats every 20 seconds. */
if (id == 1) {
time(&now);
if (now - then >= 20) {
stats();
then = now;
}
}
/* Begin the transaction. */
if ((ret = dbenv->txn_begin(dbenv, NULL, &tid, 0)) != 0)
fatal("txn_begin", ret, 1);
/*
* Get the key. If it doesn't exist, add it. If it does
* exist, delete it.
*/
switch (ret = dbp->get(dbp, tid, &key, &data, 0)) {
case DB_LOCK_DEADLOCK:
goto retry;
case 0:
goto delete;
case DB_NOTFOUND:
goto add;
}
sprintf(buf, "writer: %d: dbp->get", id);
fatal(buf, ret, 1);
/* NOTREACHED */
delete: /* Delete the key. */
switch (ret = dbp->del(dbp, tid, &key, 0)) {
case DB_LOCK_DEADLOCK:
goto retry;
case 0:
++perf[id].deletes;
goto commit;
}
sprintf(buf, "writer: %d: dbp->del", id);
fatal(buf, ret, 1);
/* NOTREACHED */
add: /* Add the key. 1 data item in 30 is an overflow item. */
data.size = 20 + rand() % 128;
if (rand() % 30 == 0)
data.size += 8192;
switch (ret = dbp->put(dbp, tid, &key, &data, 0)) {
case DB_LOCK_DEADLOCK:
goto retry;
case 0:
++perf[id].adds;
goto commit;
default:
sprintf(buf, "writer: %d: dbp->put", id);
fatal(buf, ret, 1);
}
commit: /* The transaction finished, commit it. */
if ((ret = tid->commit(tid, 0)) != 0)
fatal("DB_TXN->commit", ret, 1);
/*
* Every time the thread completes 20 transactions, show
* our progress.
*/
if (++perf[id].txns % 20 == 0) {
sprintf(buf,
"writer: %2d: adds: %4d: deletes: %4d: aborts: %4d: txns: %4d\n",
id, perf[id].adds, perf[id].deletes,
perf[id].aborts, perf[id].txns);
write(STDOUT_FILENO, buf, strlen(buf));
}
/*
* If this thread was aborted more than 5 times before
* the transaction finished, complain.
*/
if (perf[id].aborted > 5) {
sprintf(buf,
"writer: %2d: adds: %4d: deletes: %4d: aborts: %4d: txns: %4d: ABORTED: %2d\n",
id, perf[id].adds, perf[id].deletes,
perf[id].aborts, perf[id].txns, perf[id].aborted);
write(STDOUT_FILENO, buf, strlen(buf));
}
perf[id].aborted = 0;
}
return (0);
}
/*
* stats --
* Display reader/writer thread statistics. To display the statistics
* for the mpool trickle or deadlock threads, use db_stat(1).
*/
void
stats()
{
int id;
char *p, buf[8192];
p = buf + sprintf(buf, "-------------\n");
for (id = 0; id < nreaders + nwriters;)
if (id++ < nwriters)
p += sprintf(p,
"writer: %2d: adds: %4d: deletes: %4d: aborts: %4d: txns: %4d\n",
id, perf[id].adds,
perf[id].deletes, perf[id].aborts, perf[id].txns);
else
p += sprintf(p,
"reader: %2d: found: %5d: notfound: %5d: aborts: %4d\n",
id, perf[id].found,
perf[id].notfound, perf[id].aborts);
p += sprintf(p, "-------------\n");
write(STDOUT_FILENO, buf, p - buf);
}
/*
* db_init --
* Initialize the environment.
*/
int
db_init(home)
const char *home;
{
int ret;
if ((ret = db_env_create(&dbenv, 0)) != 0) {
fprintf(stderr,
"%s: db_env_create: %s\n", progname, db_strerror(ret));
return (EXIT_FAILURE);
}
if (punish) {
(void)dbenv->set_flags(dbenv, DB_YIELDCPU, 1);
(void)db_env_set_func_yield(sched_yield);
}
dbenv->set_errfile(dbenv, stderr);
dbenv->set_errpfx(dbenv, progname);
(void)dbenv->set_cachesize(dbenv, 0, 100 * 1024, 0);
(void)dbenv->set_lg_max(dbenv, 200000);
if ((ret = dbenv->open(dbenv, home,
DB_CREATE | DB_INIT_LOCK | DB_INIT_LOG |
DB_INIT_MPOOL | DB_INIT_TXN | DB_THREAD, 0)) != 0) {
dbenv->err(dbenv, ret, NULL);
(void)dbenv->close(dbenv, 0);
return (EXIT_FAILURE);
}
return (0);
}
/*
* tstart --
* Thread start function for readers and writers.
*/
void *
tstart(arg)
void *arg;
{
pthread_t tid;
u_int id;
id = (u_int)arg + 1;
tid = pthread_self();
if (id <= (u_int)nwriters) {
printf("write thread %d starting: tid: %lu\n", id, (u_long)tid);
fflush(stdout);
writer(id);
} else {
printf("read thread %d starting: tid: %lu\n", id, (u_long)tid);
fflush(stdout);
reader(id);
}
/* NOTREACHED */
return (NULL);
}
/*
* deadlock --
* Thread start function for DB_ENV->lock_detect.
*/
void *
deadlock(arg)
void *arg;
{
struct timeval t;
pthread_t tid;
arg = arg; /* XXX: shut the compiler up. */
tid = pthread_self();
printf("deadlock thread starting: tid: %lu\n", (u_long)tid);
fflush(stdout);
t.tv_sec = 0;
t.tv_usec = 100000;
while (!quit) {
(void)dbenv->lock_detect(dbenv, 0, DB_LOCK_YOUNGEST, NULL);
/* Check every 100ms. */
(void)select(0, NULL, NULL, NULL, &t);
}
return (NULL);
}
/*
* trickle --
* Thread start function for memp_trickle.
*/
void *
trickle(arg)
void *arg;
{
pthread_t tid;
int wrote;
char buf[64];
arg = arg; /* XXX: shut the compiler up. */
tid = pthread_self();
printf("trickle thread starting: tid: %lu\n", (u_long)tid);
fflush(stdout);
while (!quit) {
(void)dbenv->memp_trickle(dbenv, 10, &wrote);
if (verbose) {
sprintf(buf, "trickle: wrote %d\n", wrote);
write(STDOUT_FILENO, buf, strlen(buf));
}
if (wrote == 0) {
sleep(1);
sched_yield();
}
}
return (NULL);
}
/*
* word --
* Build the dictionary word list.
*/
void
word()
{
FILE *fp;
int cnt;
char buf[256];
if ((fp = fopen(WORDLIST, "r")) == NULL)
fatal(WORDLIST, errno, 1);
if ((list = malloc(nlist * sizeof(char *))) == NULL)
fatal(NULL, errno, 1);
for (cnt = 0; cnt < nlist; ++cnt) {
if (fgets(buf, sizeof(buf), fp) == NULL)
break;
if ((list[cnt] = strdup(buf)) == NULL)
fatal(NULL, errno, 1);
}
nlist = cnt; /* In case nlist was larger than possible. */
}
/*
* fatal --
* Report a fatal error and quit.
*/
void
fatal(msg, err, syserr)
const char *msg;
int err, syserr;
{
fprintf(stderr, "%s: ", progname);
if (msg != NULL) {
fprintf(stderr, "%s", msg);
if (syserr)
fprintf(stderr, ": ");
}
if (syserr)
fprintf(stderr, "%s", strerror(err));
fprintf(stderr, "\n");
exit(EXIT_FAILURE);
/* NOTREACHED */
}
/*
* usage --
* Usage message.
*/
int
usage()
{
(void)fprintf(stderr,
"usage: %s [-pv] [-h home] [-n words] [-r readers] [-w writers]\n",
progname);
return (EXIT_FAILURE);
}
/*
* onint --
* Interrupt signal handler.
*/
void
onint(signo)
int signo;
{
signo = 0; /* Quiet compiler. */
quit = 1;
}

View File

@ -1,698 +0,0 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 1997-2002
* Sleepycat Software. All rights reserved.
*
* $Id: ex_tpcb.c,v 11.42 2002/08/06 05:39:00 bostic Exp $
*/
#include <sys/types.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#ifdef _WIN32
extern int getopt(int, char * const *, const char *);
#else
#include <unistd.h>
#endif
#include <db.h>
typedef enum { ACCOUNT, BRANCH, TELLER } FTYPE;
DB_ENV *db_init __P((const char *, const char *, int, int, u_int32_t));
int hpopulate __P((DB *, int, int, int, int));
int populate __P((DB *, u_int32_t, u_int32_t, int, const char *));
u_int32_t random_id __P((FTYPE, int, int, int));
u_int32_t random_int __P((u_int32_t, u_int32_t));
int tp_populate __P((DB_ENV *, int, int, int, int, int));
int tp_run __P((DB_ENV *, int, int, int, int, int));
int tp_txn __P((DB_ENV *, DB *, DB *, DB *, DB *, int, int, int, int));
int invarg __P((const char *, int, const char *));
int main __P((int, char *[]));
int usage __P((const char *));
/*
* This program implements a basic TPC/B driver program. To create the
* TPC/B database, run with the -i (init) flag. The number of records
* with which to populate the account, history, branch, and teller tables
* is specified by the a, s, b, and t flags respectively. To run a TPC/B
* test, use the n flag to indicate a number of transactions to run (note
* that you can run many of these processes in parallel to simulate a
* multiuser test run).
*/
#define TELLERS_PER_BRANCH 10
#define ACCOUNTS_PER_TELLER 10000
#define HISTORY_PER_BRANCH 2592000
/*
* The default configuration that adheres to TPCB scaling rules requires
* nearly 3 GB of space. To avoid requiring that much space for testing,
* we set the parameters much lower. If you want to run a valid 10 TPS
* configuration, define VALID_SCALING.
*/
#ifdef VALID_SCALING
#define ACCOUNTS 1000000
#define BRANCHES 10
#define TELLERS 100
#define HISTORY 25920000
#endif
#ifdef TINY
#define ACCOUNTS 1000
#define BRANCHES 10
#define TELLERS 100
#define HISTORY 10000
#endif
#ifdef VERY_TINY
#define ACCOUNTS 500
#define BRANCHES 10
#define TELLERS 50
#define HISTORY 5000
#endif
#if !defined(VALID_SCALING) && !defined(TINY) && !defined(VERY_TINY)
#define ACCOUNTS 100000
#define BRANCHES 10
#define TELLERS 100
#define HISTORY 259200
#endif
#define HISTORY_LEN 100
#define RECLEN 100
#define BEGID 1000000
typedef struct _defrec {
u_int32_t id;
u_int32_t balance;
u_int8_t pad[RECLEN - sizeof(u_int32_t) - sizeof(u_int32_t)];
} defrec;
typedef struct _histrec {
u_int32_t aid;
u_int32_t bid;
u_int32_t tid;
u_int32_t amount;
u_int8_t pad[RECLEN - 4 * sizeof(u_int32_t)];
} histrec;
int
main(argc, argv)
int argc;
char *argv[];
{
extern char *optarg;
extern int optind;
DB_ENV *dbenv;
int accounts, branches, seed, tellers, history;
int ch, iflag, mpool, ntxns, ret, txn_no_sync, verbose;
const char *home, *progname;
home = "TESTDIR";
progname = "ex_tpcb";
accounts = branches = history = tellers = 0;
iflag = mpool = ntxns = txn_no_sync = verbose = 0;
seed = (int)time(NULL);
while ((ch = getopt(argc, argv, "a:b:c:fh:in:S:s:t:v")) != EOF)
switch (ch) {
case 'a': /* Number of account records */
if ((accounts = atoi(optarg)) <= 0)
return (invarg(progname, ch, optarg));
break;
case 'b': /* Number of branch records */
if ((branches = atoi(optarg)) <= 0)
return (invarg(progname, ch, optarg));
break;
case 'c': /* Cachesize in bytes */
if ((mpool = atoi(optarg)) <= 0)
return (invarg(progname, ch, optarg));
break;
case 'f': /* Fast mode: no txn sync. */
txn_no_sync = 1;
break;
case 'h': /* DB home. */
home = optarg;
break;
case 'i': /* Initialize the test. */
iflag = 1;
break;
case 'n': /* Number of transactions */
if ((ntxns = atoi(optarg)) <= 0)
return (invarg(progname, ch, optarg));
break;
case 'S': /* Random number seed. */
if ((seed = atoi(optarg)) <= 0)
return (invarg(progname, ch, optarg));
break;
case 's': /* Number of history records */
if ((history = atoi(optarg)) <= 0)
return (invarg(progname, ch, optarg));
break;
case 't': /* Number of teller records */
if ((tellers = atoi(optarg)) <= 0)
return (invarg(progname, ch, optarg));
break;
case 'v': /* Verbose option. */
verbose = 1;
break;
case '?':
default:
return (usage(progname));
}
argc -= optind;
argv += optind;
srand((u_int)seed);
/* Initialize the database environment. */
if ((dbenv = db_init(home,
progname, mpool, iflag, txn_no_sync ? DB_TXN_NOSYNC : 0)) == NULL)
return (EXIT_FAILURE);
accounts = accounts == 0 ? ACCOUNTS : accounts;
branches = branches == 0 ? BRANCHES : branches;
tellers = tellers == 0 ? TELLERS : tellers;
history = history == 0 ? HISTORY : history;
if (verbose)
printf("%ld Accounts, %ld Branches, %ld Tellers, %ld History\n",
(long)accounts, (long)branches,
(long)tellers, (long)history);
if (iflag) {
if (ntxns != 0)
return (usage(progname));
tp_populate(dbenv,
accounts, branches, history, tellers, verbose);
} else {
if (ntxns == 0)
return (usage(progname));
tp_run(dbenv, ntxns, accounts, branches, tellers, verbose);
}
if ((ret = dbenv->close(dbenv, 0)) != 0) {
fprintf(stderr, "%s: dbenv->close failed: %s\n",
progname, db_strerror(ret));
return (EXIT_FAILURE);
}
return (EXIT_SUCCESS);
}
int
invarg(progname, arg, str)
const char *progname;
int arg;
const char *str;
{
(void)fprintf(stderr,
"%s: invalid argument for -%c: %s\n", progname, arg, str);
return (EXIT_FAILURE);
}
int
usage(progname)
const char *progname;
{
const char *a1, *a2;
a1 = "[-fv] [-a accounts] [-b branches]\n";
a2 = "\t[-c cache_size] [-h home] [-S seed] [-s history] [-t tellers]";
(void)fprintf(stderr, "usage: %s -i %s %s\n", progname, a1, a2);
(void)fprintf(stderr,
" %s -n transactions %s %s\n", progname, a1, a2);
return (EXIT_FAILURE);
}
/*
* db_init --
* Initialize the environment.
*/
DB_ENV *
db_init(home, prefix, cachesize, initializing, flags)
const char *home, *prefix;
int cachesize, initializing;
u_int32_t flags;
{
DB_ENV *dbenv;
u_int32_t local_flags;
int ret;
if ((ret = db_env_create(&dbenv, 0)) != 0) {
dbenv->err(dbenv, ret, "db_env_create");
return (NULL);
}
dbenv->set_errfile(dbenv, stderr);
dbenv->set_errpfx(dbenv, prefix);
(void)dbenv->set_cachesize(dbenv, 0,
cachesize == 0 ? 4 * 1024 * 1024 : (u_int32_t)cachesize, 0);
if (flags & (DB_TXN_NOSYNC))
(void)dbenv->set_flags(dbenv, DB_TXN_NOSYNC, 1);
flags &= ~(DB_TXN_NOSYNC);
local_flags = flags | DB_CREATE | (initializing ? DB_INIT_MPOOL :
DB_INIT_TXN | DB_INIT_LOCK | DB_INIT_LOG | DB_INIT_MPOOL);
if ((ret = dbenv->open(dbenv, home, local_flags, 0)) != 0) {
dbenv->err(dbenv, ret, "DB_ENV->open: %s", home);
(void)dbenv->close(dbenv, 0);
return (NULL);
}
return (dbenv);
}
/*
* Initialize the database to the specified number of accounts, branches,
* history records, and tellers.
*/
int
tp_populate(env, accounts, branches, history, tellers, verbose)
DB_ENV *env;
int accounts, branches, history, tellers, verbose;
{
DB *dbp;
u_int32_t balance, idnum, oflags;
u_int32_t end_anum, end_bnum, end_tnum;
u_int32_t start_anum, start_bnum, start_tnum;
int ret;
idnum = BEGID;
balance = 500000;
oflags = DB_CREATE | DB_TRUNCATE;
if ((ret = db_create(&dbp, env, 0)) != 0) {
env->err(env, ret, "db_create");
return (1);
}
(void)dbp->set_h_nelem(dbp, (u_int32_t)accounts);
if ((ret = dbp->open(dbp, NULL, "account", NULL,
DB_HASH, oflags, 0644)) != 0) {
env->err(env, ret, "DB->open: account");
return (1);
}
start_anum = idnum;
populate(dbp, idnum, balance, accounts, "account");
idnum += accounts;
end_anum = idnum - 1;
if ((ret = dbp->close(dbp, 0)) != 0) {
env->err(env, ret, "DB->close: account");
return (1);
}
if (verbose)
printf("Populated accounts: %ld - %ld\n",
(long)start_anum, (long)end_anum);
/*
* Since the number of branches is very small, we want to use very
* small pages and only 1 key per page, i.e., key-locking instead
* of page locking.
*/
if ((ret = db_create(&dbp, env, 0)) != 0) {
env->err(env, ret, "db_create");
return (1);
}
(void)dbp->set_h_ffactor(dbp, 1);
(void)dbp->set_h_nelem(dbp, (u_int32_t)branches);
(void)dbp->set_pagesize(dbp, 512);
if ((ret = dbp->open(dbp, NULL, "branch", NULL,
DB_HASH, oflags, 0644)) != 0) {
env->err(env, ret, "DB->open: branch");
return (1);
}
start_bnum = idnum;
populate(dbp, idnum, balance, branches, "branch");
idnum += branches;
end_bnum = idnum - 1;
if ((ret = dbp->close(dbp, 0)) != 0) {
env->err(env, ret, "DB->close: branch");
return (1);
}
if (verbose)
printf("Populated branches: %ld - %ld\n",
(long)start_bnum, (long)end_bnum);
/*
* In the case of tellers, we also want small pages, but we'll let
* the fill factor dynamically adjust itself.
*/
if ((ret = db_create(&dbp, env, 0)) != 0) {
env->err(env, ret, "db_create");
return (1);
}
(void)dbp->set_h_ffactor(dbp, 0);
(void)dbp->set_h_nelem(dbp, (u_int32_t)tellers);
(void)dbp->set_pagesize(dbp, 512);
if ((ret = dbp->open(dbp, NULL, "teller", NULL,
DB_HASH, oflags, 0644)) != 0) {
env->err(env, ret, "DB->open: teller");
return (1);
}
start_tnum = idnum;
populate(dbp, idnum, balance, tellers, "teller");
idnum += tellers;
end_tnum = idnum - 1;
if ((ret = dbp->close(dbp, 0)) != 0) {
env->err(env, ret, "DB->close: teller");
return (1);
}
if (verbose)
printf("Populated tellers: %ld - %ld\n",
(long)start_tnum, (long)end_tnum);
if ((ret = db_create(&dbp, env, 0)) != 0) {
env->err(env, ret, "db_create");
return (1);
}
(void)dbp->set_re_len(dbp, HISTORY_LEN);
if ((ret = dbp->open(dbp, NULL, "history", NULL,
DB_RECNO, oflags, 0644)) != 0) {
env->err(env, ret, "DB->open: history");
return (1);
}
hpopulate(dbp, history, accounts, branches, tellers);
if ((ret = dbp->close(dbp, 0)) != 0) {
env->err(env, ret, "DB->close: history");
return (1);
}
return (0);
}
int
populate(dbp, start_id, balance, nrecs, msg)
DB *dbp;
u_int32_t start_id, balance;
int nrecs;
const char *msg;
{
DBT kdbt, ddbt;
defrec drec;
int i, ret;
kdbt.flags = 0;
kdbt.data = &drec.id;
kdbt.size = sizeof(u_int32_t);
ddbt.flags = 0;
ddbt.data = &drec;
ddbt.size = sizeof(drec);
memset(&drec.pad[0], 1, sizeof(drec.pad));
for (i = 0; i < nrecs; i++) {
drec.id = start_id + (u_int32_t)i;
drec.balance = balance;
if ((ret =
(dbp->put)(dbp, NULL, &kdbt, &ddbt, DB_NOOVERWRITE)) != 0) {
dbp->err(dbp,
ret, "Failure initializing %s file\n", msg);
return (1);
}
}
return (0);
}
int
hpopulate(dbp, history, accounts, branches, tellers)
DB *dbp;
int history, accounts, branches, tellers;
{
DBT kdbt, ddbt;
histrec hrec;
db_recno_t key;
int i, ret;
memset(&kdbt, 0, sizeof(kdbt));
memset(&ddbt, 0, sizeof(ddbt));
ddbt.data = &hrec;
ddbt.size = sizeof(hrec);
kdbt.data = &key;
kdbt.size = sizeof(key);
memset(&hrec.pad[0], 1, sizeof(hrec.pad));
hrec.amount = 10;
for (i = 1; i <= history; i++) {
hrec.aid = random_id(ACCOUNT, accounts, branches, tellers);
hrec.bid = random_id(BRANCH, accounts, branches, tellers);
hrec.tid = random_id(TELLER, accounts, branches, tellers);
if ((ret = dbp->put(dbp, NULL, &kdbt, &ddbt, DB_APPEND)) != 0) {
dbp->err(dbp, ret, "dbp->put");
return (1);
}
}
return (0);
}
u_int32_t
random_int(lo, hi)
u_int32_t lo, hi;
{
u_int32_t ret;
int t;
#ifndef RAND_MAX
#define RAND_MAX 0x7fffffff
#endif
t = rand();
ret = (u_int32_t)(((double)t / ((double)(RAND_MAX) + 1)) *
(hi - lo + 1));
ret += lo;
return (ret);
}
u_int32_t
random_id(type, accounts, branches, tellers)
FTYPE type;
int accounts, branches, tellers;
{
u_int32_t min, max, num;
max = min = BEGID;
num = accounts;
switch(type) {
case TELLER:
min += branches;
num = tellers;
/* FALLTHROUGH */
case BRANCH:
if (type == BRANCH)
num = branches;
min += accounts;
/* FALLTHROUGH */
case ACCOUNT:
max = min + num - 1;
}
return (random_int(min, max));
}
int
tp_run(dbenv, n, accounts, branches, tellers, verbose)
DB_ENV *dbenv;
int n, accounts, branches, tellers, verbose;
{
DB *adb, *bdb, *hdb, *tdb;
double gtps, itps;
int failed, ifailed, ret, txns;
time_t starttime, curtime, lasttime;
adb = bdb = hdb = tdb = NULL;
txns = failed = 0;
/*
* Open the database files.
*/
if ((ret = db_create(&adb, dbenv, 0)) != 0) {
dbenv->err(dbenv, ret, "db_create");
goto err;
}
if ((ret = adb->open(adb, NULL, "account", NULL, DB_UNKNOWN,
DB_AUTO_COMMIT, 0)) != 0) {
dbenv->err(dbenv, ret, "DB->open: account");
goto err;
}
if ((ret = db_create(&bdb, dbenv, 0)) != 0) {
dbenv->err(dbenv, ret, "db_create");
goto err;
}
if ((ret = bdb->open(bdb, NULL, "branch", NULL, DB_UNKNOWN,
DB_AUTO_COMMIT, 0)) != 0) {
dbenv->err(dbenv, ret, "DB->open: branch");
goto err;
}
if ((ret = db_create(&hdb, dbenv, 0)) != 0) {
dbenv->err(dbenv, ret, "db_create");
goto err;
}
if ((ret = hdb->open(hdb, NULL, "history", NULL, DB_UNKNOWN,
DB_AUTO_COMMIT, 0)) != 0) {
dbenv->err(dbenv, ret, "DB->open: history");
goto err;
}
if ((ret = db_create(&tdb, dbenv, 0)) != 0) {
dbenv->err(dbenv, ret, "db_create");
goto err;
}
if ((ret = tdb->open(tdb, NULL, "teller", NULL, DB_UNKNOWN,
DB_AUTO_COMMIT, 0)) != 0) {
dbenv->err(dbenv, ret, "DB->open: teller");
goto err;
}
starttime = time(NULL);
lasttime = starttime;
for (ifailed = 0; n-- > 0;) {
txns++;
ret = tp_txn(dbenv, adb, bdb, tdb, hdb,
accounts, branches, tellers, verbose);
if (ret != 0) {
failed++;
ifailed++;
}
if (n % 5000 == 0) {
curtime = time(NULL);
gtps = (double)(txns - failed) / (curtime - starttime);
itps = (double)(5000 - ifailed) / (curtime - lasttime);
printf("%d txns %d failed ", txns, failed);
printf("%6.2f TPS (gross) %6.2f TPS (interval)\n",
gtps, itps);
lasttime = curtime;
ifailed = 0;
}
}
err: if (adb != NULL)
(void)adb->close(adb, 0);
if (bdb != NULL)
(void)bdb->close(bdb, 0);
if (tdb != NULL)
(void)tdb->close(tdb, 0);
if (hdb != NULL)
(void)hdb->close(hdb, 0);
printf("%ld transactions begun %ld failed\n", (long)txns, (long)failed);
return (ret == 0 ? 0 : 1);
}
/*
* XXX Figure out the appropriate way to pick out IDs.
*/
int
tp_txn(dbenv, adb, bdb, tdb, hdb, accounts, branches, tellers, verbose)
DB_ENV *dbenv;
DB *adb, *bdb, *tdb, *hdb;
int accounts, branches, tellers, verbose;
{
DBC *acurs, *bcurs, *tcurs;
DBT d_dbt, d_histdbt, k_dbt, k_histdbt;
DB_TXN *t;
db_recno_t key;
defrec rec;
histrec hrec;
int account, branch, teller, ret;
t = NULL;
acurs = bcurs = tcurs = NULL;
/*
* XXX We could move a lot of this into the driver to make this
* faster.
*/
account = random_id(ACCOUNT, accounts, branches, tellers);
branch = random_id(BRANCH, accounts, branches, tellers);
teller = random_id(TELLER, accounts, branches, tellers);
memset(&d_histdbt, 0, sizeof(d_histdbt));
memset(&k_histdbt, 0, sizeof(k_histdbt));
k_histdbt.data = &key;
k_histdbt.size = sizeof(key);
memset(&k_dbt, 0, sizeof(k_dbt));
k_dbt.size = sizeof(int);
memset(&d_dbt, 0, sizeof(d_dbt));
d_dbt.flags = DB_DBT_USERMEM;
d_dbt.data = &rec;
d_dbt.ulen = sizeof(rec);
hrec.aid = account;
hrec.bid = branch;
hrec.tid = teller;
hrec.amount = 10;
/* Request 0 bytes since we're just positioning. */
d_histdbt.flags = DB_DBT_PARTIAL;
/* START TIMING */
if (dbenv->txn_begin(dbenv, NULL, &t, 0) != 0)
goto err;
if (adb->cursor(adb, t, &acurs, 0) != 0 ||
bdb->cursor(bdb, t, &bcurs, 0) != 0 ||
tdb->cursor(tdb, t, &tcurs, 0) != 0)
goto err;
/* Account record */
k_dbt.data = &account;
if (acurs->c_get(acurs, &k_dbt, &d_dbt, DB_SET) != 0)
goto err;
rec.balance += 10;
if (acurs->c_put(acurs, &k_dbt, &d_dbt, DB_CURRENT) != 0)
goto err;
/* Branch record */
k_dbt.data = &branch;
if (bcurs->c_get(bcurs, &k_dbt, &d_dbt, DB_SET) != 0)
goto err;
rec.balance += 10;
if (bcurs->c_put(bcurs, &k_dbt, &d_dbt, DB_CURRENT) != 0)
goto err;
/* Teller record */
k_dbt.data = &teller;
if (tcurs->c_get(tcurs, &k_dbt, &d_dbt, DB_SET) != 0)
goto err;
rec.balance += 10;
if (tcurs->c_put(tcurs, &k_dbt, &d_dbt, DB_CURRENT) != 0)
goto err;
/* History record */
d_histdbt.flags = 0;
d_histdbt.data = &hrec;
d_histdbt.ulen = sizeof(hrec);
if (hdb->put(hdb, t, &k_histdbt, &d_histdbt, DB_APPEND) != 0)
goto err;
if (acurs->c_close(acurs) != 0 || bcurs->c_close(bcurs) != 0 ||
tcurs->c_close(tcurs) != 0)
goto err;
ret = t->commit(t, 0);
t = NULL;
if (ret != 0)
goto err;
/* END TIMING */
return (0);
err: if (acurs != NULL)
(void)acurs->c_close(acurs);
if (bcurs != NULL)
(void)bcurs->c_close(bcurs);
if (tcurs != NULL)
(void)tcurs->c_close(tcurs);
if (t != NULL)
(void)t->abort(t);
if (verbose)
printf("Transaction A=%ld B=%ld T=%ld failed\n",
(long)account, (long)branch, (long)teller);
return (-1);
}

View File

@ -1,39 +0,0 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 1996-2002
* Sleepycat Software. All rights reserved.
*
* $Id: ex_tpcb.h,v 11.6 2002/01/11 15:52:06 bostic Exp $
*/
#ifndef _TPCB_H_
#define _TPCB_H_
typedef enum { ACCOUNT, BRANCH, TELLER } FTYPE;
#define TELLERS_PER_BRANCH 100
#define ACCOUNTS_PER_TELLER 1000
#define ACCOUNTS 1000000
#define BRANCHES 10
#define TELLERS 1000
#define HISTORY 1000000
#define HISTORY_LEN 100
#define RECLEN 100
#define BEGID 1000000
typedef struct _defrec {
u_int32_t id;
u_int32_t balance;
u_int8_t pad[RECLEN - sizeof(u_int32_t) - sizeof(u_int32_t)];
} defrec;
typedef struct _histrec {
u_int32_t aid;
u_int32_t bid;
u_int32_t tid;
u_int32_t amount;
u_int8_t pad[RECLEN - 4 * sizeof(u_int32_t)];
} histrec;
#endif /* _TPCB_H_ */

View File

@ -1,136 +0,0 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 1997-2002
* Sleepycat Software. All rights reserved.
*
* $Id: AccessExample.cpp,v 11.18 2002/01/23 15:33:20 bostic Exp $
*/
#include <sys/types.h>
#include <iostream>
#include <iomanip>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <db_cxx.h>
using std::cin;
using std::cout;
using std::cerr;
class AccessExample
{
public:
AccessExample();
void run();
private:
static const char FileName[];
// no need for copy and assignment
AccessExample(const AccessExample &);
void operator = (const AccessExample &);
};
int main()
{
// Use a try block just to report any errors.
// An alternate approach to using exceptions is to
// use error models (see DbEnv::set_error_model()) so
// that error codes are returned for all Berkeley DB methods.
//
try {
AccessExample app;
app.run();
return (EXIT_SUCCESS);
}
catch (DbException &dbe) {
cerr << "AccessExample: " << dbe.what() << "\n";
return (EXIT_FAILURE);
}
}
const char AccessExample::FileName[] = "access.db";
AccessExample::AccessExample()
{
}
void AccessExample::run()
{
// Remove the previous database.
(void)remove(FileName);
// Create the database object.
// There is no environment for this simple example.
Db db(0, 0);
db.set_error_stream(&cerr);
db.set_errpfx("AccessExample");
db.set_pagesize(1024); /* Page size: 1K. */
db.set_cachesize(0, 32 * 1024, 0);
db.open(NULL, FileName, NULL, DB_BTREE, DB_CREATE, 0664);
//
// Insert records into the database, where the key is the user
// input and the data is the user input in reverse order.
//
char buf[1024];
char rbuf[1024];
char *t;
char *p;
int ret;
int len;
for (;;) {
cout << "input> ";
cout.flush();
cin.getline(buf, sizeof(buf));
if (cin.eof())
break;
if ((len = strlen(buf)) <= 0)
continue;
for (t = rbuf, p = buf + (len - 1); p >= buf;)
*t++ = *p--;
*t++ = '\0';
Dbt key(buf, len + 1);
Dbt data(rbuf, len + 1);
ret = db.put(0, &key, &data, DB_NOOVERWRITE);
if (ret == DB_KEYEXIST) {
cout << "Key " << buf << " already exists.\n";
}
}
cout << "\n";
// We put a try block around this section of code
// to ensure that our database is properly closed
// in the event of an error.
//
try {
// Acquire a cursor for the table.
Dbc *dbcp;
db.cursor(NULL, &dbcp, 0);
// Walk through the table, printing the key/data pairs.
Dbt key;
Dbt data;
while (dbcp->get(&key, &data, DB_NEXT) == 0) {
char *key_string = (char *)key.get_data();
char *data_string = (char *)data.get_data();
cout << key_string << " : " << data_string << "\n";
}
dbcp->close();
}
catch (DbException &dbe) {
cerr << "AccessExample: " << dbe.what() << "\n";
}
db.close(0);
}

View File

@ -1,224 +0,0 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 1997-2002
* Sleepycat Software. All rights reserved.
*
* $Id: BtRecExample.cpp,v 11.21 2002/01/23 15:33:20 bostic Exp $
*/
#include <sys/types.h>
#include <errno.h>
#include <iostream>
#include <iomanip>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <db_cxx.h>
using std::cout;
using std::cerr;
#define DATABASE "access.db"
#define WORDLIST "../test/wordlist"
const char *progname = "BtRecExample"; // Program name.
class BtRecExample
{
public:
BtRecExample(FILE *fp);
~BtRecExample();
void run();
void stats();
void show(const char *msg, Dbt *key, Dbt *data);
private:
Db *dbp;
Dbc *dbcp;
};
BtRecExample::BtRecExample(FILE *fp)
{
char *p, *t, buf[1024], rbuf[1024];
int ret;
// Remove the previous database.
(void)remove(DATABASE);
dbp = new Db(NULL, 0);
dbp->set_error_stream(&cerr);
dbp->set_errpfx(progname);
dbp->set_pagesize(1024); // 1K page sizes.
dbp->set_flags(DB_RECNUM); // Record numbers.
dbp->open(NULL, DATABASE, NULL, DB_BTREE, DB_CREATE, 0664);
//
// Insert records into the database, where the key is the word
// preceded by its record number, and the data is the same, but
// in reverse order.
//
for (int cnt = 1; cnt <= 1000; ++cnt) {
(void)sprintf(buf, "%04d_", cnt);
if (fgets(buf + 4, sizeof(buf) - 4, fp) == NULL)
break;
u_int32_t len = strlen(buf);
buf[len - 1] = '\0';
for (t = rbuf, p = buf + (len - 2); p >= buf;)
*t++ = *p--;
*t++ = '\0';
// As a convenience for printing, we include the null terminator
// in the stored data.
//
Dbt key(buf, len);
Dbt data(rbuf, len);
if ((ret = dbp->put(NULL, &key, &data, DB_NOOVERWRITE)) != 0) {
dbp->err(ret, "Db::put");
if (ret != DB_KEYEXIST)
throw DbException(ret);
}
}
}
BtRecExample::~BtRecExample()
{
if (dbcp != 0)
dbcp->close();
dbp->close(0);
delete dbp;
}
//
// Print out the number of records in the database.
//
void BtRecExample::stats()
{
DB_BTREE_STAT *statp;
dbp->stat(&statp, 0);
cout << progname << ": database contains "
<< (u_long)statp->bt_ndata << " records\n";
// Note: must use free, not delete.
// This struct is allocated by C.
//
free(statp);
}
void BtRecExample::run()
{
db_recno_t recno;
int ret;
char buf[1024];
// Acquire a cursor for the database.
dbp->cursor(NULL, &dbcp, 0);
//
// Prompt the user for a record number, then retrieve and display
// that record.
//
for (;;) {
// Get a record number.
cout << "recno #> ";
cout.flush();
if (fgets(buf, sizeof(buf), stdin) == NULL)
break;
recno = atoi(buf);
//
// Start with a fresh key each time,
// the dbp->get() routine returns
// the key and data pair, not just the key!
//
Dbt key(&recno, sizeof(recno));
Dbt data;
if ((ret = dbcp->get(&key, &data, DB_SET_RECNO)) != 0) {
dbp->err(ret, "DBcursor->get");
throw DbException(ret);
}
// Display the key and data.
show("k/d\t", &key, &data);
// Move the cursor a record forward.
if ((ret = dbcp->get(&key, &data, DB_NEXT)) != 0) {
dbp->err(ret, "DBcursor->get");
throw DbException(ret);
}
// Display the key and data.
show("next\t", &key, &data);
//
// Retrieve the record number for the following record into
// local memory.
//
data.set_data(&recno);
data.set_size(sizeof(recno));
data.set_ulen(sizeof(recno));
data.set_flags(data.get_flags() | DB_DBT_USERMEM);
if ((ret = dbcp->get(&key, &data, DB_GET_RECNO)) != 0) {
if (ret != DB_NOTFOUND && ret != DB_KEYEMPTY) {
dbp->err(ret, "DBcursor->get");
throw DbException(ret);
}
}
else {
cout << "retrieved recno: " << (u_long)recno << "\n";
}
}
dbcp->close();
dbcp = NULL;
}
//
// show --
// Display a key/data pair.
//
void BtRecExample::show(const char *msg, Dbt *key, Dbt *data)
{
cout << msg << (char *)key->get_data()
<< " : " << (char *)data->get_data() << "\n";
}
int
main()
{
FILE *fp;
// Open the word database.
if ((fp = fopen(WORDLIST, "r")) == NULL) {
fprintf(stderr, "%s: open %s: %s\n",
progname, WORDLIST, db_strerror(errno));
return (EXIT_FAILURE);
}
try {
BtRecExample app(fp);
// Close the word database.
(void)fclose(fp);
fp = NULL;
app.stats();
app.run();
}
catch (DbException &dbe) {
cerr << "Exception: " << dbe.what() << "\n";
return (EXIT_FAILURE);
}
return (EXIT_SUCCESS);
}

View File

@ -1,121 +0,0 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 1997-2002
* Sleepycat Software. All rights reserved.
*
* $Id: EnvExample.cpp,v 11.24 2002/01/11 15:52:15 bostic Exp $
*/
#include <sys/types.h>
#include <errno.h>
#include <iostream>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <db_cxx.h>
using std::ostream;
using std::cout;
using std::cerr;
#ifdef macintosh
#define DATABASE_HOME ":database"
#define CONFIG_DATA_DIR ":database"
#else
#ifdef DB_WIN32
#define DATABASE_HOME "\\tmp\\database"
#define CONFIG_DATA_DIR "\\database\\files"
#else
#define DATABASE_HOME "/tmp/database"
#define CONFIG_DATA_DIR "/database/files"
#endif
#endif
void db_setup(const char *, const char *, ostream&);
void db_teardown(const char *, const char *, ostream&);
const char *progname = "EnvExample"; /* Program name. */
//
// An example of a program creating/configuring a Berkeley DB environment.
//
int
main(int, char **)
{
//
// Note: it may be easiest to put all Berkeley DB operations in a
// try block, as seen here. Alternatively, you can change the
// ErrorModel in the DbEnv so that exceptions are never thrown
// and check error returns from all methods.
//
try {
const char *data_dir, *home;
//
// All of the shared database files live in /home/database,
// but data files live in /database.
//
home = DATABASE_HOME;
data_dir = CONFIG_DATA_DIR;
cout << "Setup env\n";
db_setup(home, data_dir, cerr);
cout << "Teardown env\n";
db_teardown(home, data_dir, cerr);
return (EXIT_SUCCESS);
}
catch (DbException &dbe) {
cerr << "EnvExample: " << dbe.what() << "\n";
return (EXIT_FAILURE);
}
}
// Note that any of the db calls can throw DbException
void
db_setup(const char *home, const char *data_dir, ostream& err_stream)
{
//
// Create an environment object and initialize it for error
// reporting.
//
DbEnv *dbenv = new DbEnv(0);
dbenv->set_error_stream(&err_stream);
dbenv->set_errpfx(progname);
//
// We want to specify the shared memory buffer pool cachesize,
// but everything else is the default.
//
dbenv->set_cachesize(0, 64 * 1024, 0);
// Databases are in a subdirectory.
(void)dbenv->set_data_dir(data_dir);
// Open the environment with full transactional support.
dbenv->open(home,
DB_CREATE | DB_INIT_LOCK | DB_INIT_LOG | DB_INIT_MPOOL | DB_INIT_TXN, 0);
// Do something interesting...
// Close the handle.
dbenv->close(0);
}
void
db_teardown(const char *home, const char *data_dir, ostream& err_stream)
{
// Remove the shared database regions.
DbEnv *dbenv = new DbEnv(0);
dbenv->set_error_stream(&err_stream);
dbenv->set_errpfx(progname);
(void)dbenv->set_data_dir(data_dir);
dbenv->remove(home, 0);
delete dbenv;
}

View File

@ -1,244 +0,0 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 1997-2002
* Sleepycat Software. All rights reserved.
*
* $Id: LockExample.cpp,v 11.22 2002/01/11 15:52:15 bostic Exp $
*/
#include <sys/types.h>
#include <errno.h>
#include <iostream>
#include <stdlib.h>
#include <string.h>
#include <db_cxx.h>
using std::cin;
using std::cout;
using std::cerr;
const char *progname = "LockExample"; // Program name.
//
// An example of a program using DBLock and related classes.
//
class LockExample : public DbEnv
{
public:
void run();
int error_code() { return (ecode); }
LockExample(const char *home, u_int32_t maxlocks, int do_unlink);
private:
static const char FileName[];
int ecode;
// no need for copy and assignment
LockExample(const LockExample &);
void operator = (const LockExample &);
};
static int usage(); // forward
int
main(int argc, char *argv[])
{
const char *home;
int do_unlink;
u_int32_t maxlocks;
int i;
home = "TESTDIR";
maxlocks = 0;
do_unlink = 0;
for (int argnum = 1; argnum < argc; ++argnum) {
if (strcmp(argv[argnum], "-h") == 0) {
if (++argnum >= argc)
return (usage());
home = argv[argnum];
}
else if (strcmp(argv[argnum], "-m") == 0) {
if (++argnum >= argc)
return (usage());
if ((i = atoi(argv[argnum])) <= 0)
return (usage());
maxlocks = (u_int32_t)i; /* XXX: possible overflow. */
}
else if (strcmp(argv[argnum], "-u") == 0) {
do_unlink = 1;
}
else {
return (usage());
}
}
try {
int ecode;
if (do_unlink) {
// Create an environment that immediately
// removes all files.
LockExample tmp(home, maxlocks, do_unlink);
if ((ecode = tmp.error_code()) != 0)
return (ecode);
}
LockExample app(home, maxlocks, do_unlink);
if ((ecode = app.error_code()) != 0)
return (ecode);
app.run();
app.close(0);
return (EXIT_SUCCESS);
}
catch (DbException &dbe) {
cerr << "LockExample: " << dbe.what() << "\n";
return (EXIT_FAILURE);
}
}
LockExample::LockExample(const char *home, u_int32_t maxlocks, int do_unlink)
: DbEnv(0)
, ecode(0)
{
int ret;
if (do_unlink) {
if ((ret = remove(home, DB_FORCE)) != 0) {
cerr << progname << ": DbEnv::remove: "
<< strerror(errno) << "\n";
ecode = EXIT_FAILURE;
}
}
else {
set_error_stream(&cerr);
set_errpfx("LockExample");
if (maxlocks != 0)
set_lk_max_locks(maxlocks);
open(home, DB_CREATE | DB_INIT_LOCK, 0);
}
}
void LockExample::run()
{
long held;
u_int32_t len, locker;
int did_get, ret;
DbLock *locks = 0;
int lockcount = 0;
char objbuf[1024];
int lockid = 0;
//
// Accept lock requests.
//
lock_id(&locker);
for (held = 0;;) {
cout << "Operation get/release [get]> ";
cout.flush();
char opbuf[16];
cin.getline(opbuf, sizeof(opbuf));
if (cin.eof())
break;
if ((len = strlen(opbuf)) <= 1 || strcmp(opbuf, "get") == 0) {
// Acquire a lock.
cout << "input object (text string) to lock> ";
cout.flush();
cin.getline(objbuf, sizeof(objbuf));
if (cin.eof())
break;
if ((len = strlen(objbuf)) <= 0)
continue;
char lockbuf[16];
do {
cout << "lock type read/write [read]> ";
cout.flush();
cin.getline(lockbuf, sizeof(lockbuf));
if (cin.eof())
break;
len = strlen(lockbuf);
} while (len >= 1 &&
strcmp(lockbuf, "read") != 0 &&
strcmp(lockbuf, "write") != 0);
db_lockmode_t lock_type;
if (len <= 1 || strcmp(lockbuf, "read") == 0)
lock_type = DB_LOCK_READ;
else
lock_type = DB_LOCK_WRITE;
Dbt dbt(objbuf, strlen(objbuf));
DbLock lock;
ret = lock_get(locker, DB_LOCK_NOWAIT, &dbt,
lock_type, &lock);
did_get = 1;
lockid = lockcount++;
if (locks == NULL) {
locks = new DbLock[1];
}
else {
DbLock *newlocks = new DbLock[lockcount];
for (int lockno = 0; lockno < lockid; lockno++) {
newlocks[lockno] = locks[lockno];
}
delete locks;
locks = newlocks;
}
locks[lockid] = lock;
} else {
// Release a lock.
do {
cout << "input lock to release> ";
cout.flush();
cin.getline(objbuf, sizeof(objbuf));
if (cin.eof())
break;
} while ((len = strlen(objbuf)) <= 0);
lockid = strtol(objbuf, NULL, 16);
if (lockid < 0 || lockid >= lockcount) {
cout << "Lock #" << lockid << " out of range\n";
continue;
}
DbLock lock = locks[lockid];
ret = lock_put(&lock);
did_get = 0;
}
switch (ret) {
case 0:
cout << "Lock #" << lockid << " "
<< (did_get ? "granted" : "released")
<< "\n";
held += did_get ? 1 : -1;
break;
case DB_LOCK_NOTGRANTED:
cout << "Lock not granted\n";
break;
case DB_LOCK_DEADLOCK:
cerr << "LockExample: lock_"
<< (did_get ? "get" : "put")
<< ": " << "returned DEADLOCK";
break;
default:
cerr << "LockExample: lock_get: %s",
strerror(errno);
}
}
cout << "\n";
cout << "Closing lock region " << held << " locks held\n";
if (locks != 0)
delete locks;
}
static int
usage()
{
cerr << "usage: LockExample [-u] [-h home] [-m maxlocks]\n";
return (EXIT_FAILURE);
}

View File

@ -1,218 +0,0 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 1997-2002
* Sleepycat Software. All rights reserved.
*
* $Id: MpoolExample.cpp,v 11.23 2002/01/11 15:52:15 bostic Exp $
*/
#include <sys/types.h>
#include <errno.h>
#include <fcntl.h>
#include <iostream>
#include <fstream>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <db_cxx.h>
using std::cout;
using std::cerr;
using std::ios;
using std::ofstream;
#define MPOOL "mpool"
int init(const char *, int, int);
int run(DB_ENV *, int, int, int);
static int usage();
const char *progname = "MpoolExample"; // Program name.
class MpoolExample : public DbEnv
{
public:
MpoolExample();
int initdb(const char *home, int cachesize);
int run(int hits, int pagesize, int npages);
private:
static const char FileName[];
// no need for copy and assignment
MpoolExample(const MpoolExample &);
void operator = (const MpoolExample &);
};
int main(int argc, char *argv[])
{
int ret;
int cachesize = 20 * 1024;
int hits = 1000;
int npages = 50;
int pagesize = 1024;
for (int i = 1; i < argc; ++i) {
if (strcmp(argv[i], "-c") == 0) {
if ((cachesize = atoi(argv[++i])) < 20 * 1024)
usage();
}
else if (strcmp(argv[i], "-h") == 0) {
if ((hits = atoi(argv[++i])) <= 0)
usage();
}
else if (strcmp(argv[i], "-n") == 0) {
if ((npages = atoi(argv[++i])) <= 0)
usage();
}
else if (strcmp(argv[i], "-p") == 0) {
if ((pagesize = atoi(argv[++i])) <= 0)
usage();
}
else {
usage();
}
}
// Initialize the file.
if ((ret = init(MPOOL, pagesize, npages)) != 0)
return (ret);
try {
MpoolExample app;
cout << progname
<< ": cachesize: " << cachesize
<< "; pagesize: " << pagesize
<< "; N pages: " << npages << "\n";
if ((ret = app.initdb(NULL, cachesize)) != 0)
return (ret);
if ((ret = app.run(hits, pagesize, npages)) != 0)
return (ret);
cout << "MpoolExample: completed\n";
return (EXIT_SUCCESS);
}
catch (DbException &dbe) {
cerr << "MpoolExample: " << dbe.what() << "\n";
return (EXIT_FAILURE);
}
}
//
// init --
// Create a backing file.
//
int
init(const char *file, int pagesize, int npages)
{
// Create a file with the right number of pages, and store a page
// number on each page.
ofstream of(file, ios::out | ios::binary);
if (of.fail()) {
cerr << "MpoolExample: " << file << ": open failed\n";
return (EXIT_FAILURE);
}
char *p = new char[pagesize];
memset(p, 0, pagesize);
// The pages are numbered from 0.
for (int cnt = 0; cnt <= npages; ++cnt) {
*(db_pgno_t *)p = cnt;
of.write(p, pagesize);
if (of.fail()) {
cerr << "MpoolExample: " << file << ": write failed\n";
return (EXIT_FAILURE);
}
}
delete [] p;
return (EXIT_SUCCESS);
}
static int
usage()
{
cerr << "usage: MpoolExample [-c cachesize] "
<< "[-h hits] [-n npages] [-p pagesize]\n";
return (EXIT_FAILURE);
}
// Note: by using DB_CXX_NO_EXCEPTIONS, we get explicit error returns
// from various methods rather than exceptions so we can report more
// information with each error.
//
MpoolExample::MpoolExample()
: DbEnv(DB_CXX_NO_EXCEPTIONS)
{
}
int MpoolExample::initdb(const char *home, int cachesize)
{
set_error_stream(&cerr);
set_errpfx("MpoolExample");
set_cachesize(0, cachesize, 0);
open(home, DB_CREATE | DB_INIT_MPOOL, 0);
return (EXIT_SUCCESS);
}
//
// run --
// Get a set of pages.
//
int
MpoolExample::run(int hits, int pagesize, int npages)
{
db_pgno_t pageno;
int cnt, ret;
void *p;
// Open the file in the environment.
DbMpoolFile *mfp;
if ((ret = memp_fcreate(&mfp, 0)) != 0) {
cerr << "MpoolExample: memp_fcreate failed: "
<< strerror(ret) << "\n";
return (EXIT_FAILURE);
}
mfp->open(MPOOL, 0, 0, pagesize);
cout << "retrieve " << hits << " random pages... ";
srand((unsigned int)time(NULL));
for (cnt = 0; cnt < hits; ++cnt) {
pageno = (rand() % npages) + 1;
if ((ret = mfp->get(&pageno, 0, &p)) != 0) {
cerr << "MpoolExample: unable to retrieve page "
<< (unsigned long)pageno << ": "
<< strerror(ret) << "\n";
return (EXIT_FAILURE);
}
if (*(db_pgno_t *)p != pageno) {
cerr << "MpoolExample: wrong page retrieved ("
<< (unsigned long)pageno << " != "
<< *(int *)p << ")\n";
return (EXIT_FAILURE);
}
if ((ret = mfp->put(p, 0)) != 0) {
cerr << "MpoolExample: unable to return page "
<< (unsigned long)pageno << ": "
<< strerror(ret) << "\n";
return (EXIT_FAILURE);
}
}
cout << "successful.\n";
// Close the pool.
if ((ret = close(0)) != 0) {
cerr << "MpoolExample: " << strerror(ret) << "\n";
return (EXIT_FAILURE);
}
return (EXIT_SUCCESS);
}

View File

@ -1,657 +0,0 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 1997-2002
* Sleepycat Software. All rights reserved.
*
* $Id: TpcbExample.cpp,v 11.30 2002/02/13 06:08:34 mjc Exp $
*/
#include <sys/types.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <iostream>
#include <iomanip>
#include <db_cxx.h>
using std::cout;
using std::cerr;
typedef enum { ACCOUNT, BRANCH, TELLER } FTYPE;
static int invarg(int, char *);
u_int32_t random_id(FTYPE, u_int32_t, u_int32_t, u_int32_t);
u_int32_t random_int(u_int32_t, u_int32_t);
static int usage(void);
int verbose;
const char *progname = "TpcbExample"; // Program name.
class TpcbExample : public DbEnv
{
public:
void populate(int, int, int, int);
void run(int, int, int, int);
int txn(Db *, Db *, Db *, Db *,
int, int, int);
void populateHistory(Db *, int, u_int32_t, u_int32_t, u_int32_t);
void populateTable(Db *, u_int32_t, u_int32_t, int, const char *);
// Note: the constructor creates a DbEnv(), which is
// not fully initialized until the DbEnv::open() method
// is called.
//
TpcbExample(const char *home, int cachesize,
int initializing, int flags);
private:
static const char FileName[];
// no need for copy and assignment
TpcbExample(const TpcbExample &);
void operator = (const TpcbExample &);
};
//
// This program implements a basic TPC/B driver program. To create the
// TPC/B database, run with the -i (init) flag. The number of records
// with which to populate the account, history, branch, and teller tables
// is specified by the a, s, b, and t flags respectively. To run a TPC/B
// test, use the n flag to indicate a number of transactions to run (note
// that you can run many of these processes in parallel to simulate a
// multiuser test run).
//
#define TELLERS_PER_BRANCH 100
#define ACCOUNTS_PER_TELLER 1000
#define HISTORY_PER_BRANCH 2592000
/*
* The default configuration that adheres to TPCB scaling rules requires
* nearly 3 GB of space. To avoid requiring that much space for testing,
* we set the parameters much lower. If you want to run a valid 10 TPS
* configuration, define VALID_SCALING.
*/
#ifdef VALID_SCALING
#define ACCOUNTS 1000000
#define BRANCHES 10
#define TELLERS 100
#define HISTORY 25920000
#endif
#ifdef TINY
#define ACCOUNTS 1000
#define BRANCHES 10
#define TELLERS 100
#define HISTORY 10000
#endif
#if !defined(VALID_SCALING) && !defined(TINY)
#define ACCOUNTS 100000
#define BRANCHES 10
#define TELLERS 100
#define HISTORY 259200
#endif
#define HISTORY_LEN 100
#define RECLEN 100
#define BEGID 1000000
struct Defrec {
u_int32_t id;
u_int32_t balance;
u_int8_t pad[RECLEN - sizeof(u_int32_t) - sizeof(u_int32_t)];
};
struct Histrec {
u_int32_t aid;
u_int32_t bid;
u_int32_t tid;
u_int32_t amount;
u_int8_t pad[RECLEN - 4 * sizeof(u_int32_t)];
};
int
main(int argc, char *argv[])
{
unsigned long seed;
int accounts, branches, tellers, history;
int iflag, mpool, ntxns, txn_no_sync;
const char *home;
char *endarg;
home = "TESTDIR";
accounts = branches = history = tellers = 0;
txn_no_sync = 0;
mpool = ntxns = 0;
verbose = 0;
iflag = 0;
seed = (unsigned long)time(NULL);
for (int i = 1; i < argc; ++i) {
if (strcmp(argv[i], "-a") == 0) {
// Number of account records
if ((accounts = atoi(argv[++i])) <= 0)
return (invarg('a', argv[i]));
}
else if (strcmp(argv[i], "-b") == 0) {
// Number of branch records
if ((branches = atoi(argv[++i])) <= 0)
return (invarg('b', argv[i]));
}
else if (strcmp(argv[i], "-c") == 0) {
// Cachesize in bytes
if ((mpool = atoi(argv[++i])) <= 0)
return (invarg('c', argv[i]));
}
else if (strcmp(argv[i], "-f") == 0) {
// Fast mode: no txn sync.
txn_no_sync = 1;
}
else if (strcmp(argv[i], "-h") == 0) {
// DB home.
home = argv[++i];
}
else if (strcmp(argv[i], "-i") == 0) {
// Initialize the test.
iflag = 1;
}
else if (strcmp(argv[i], "-n") == 0) {
// Number of transactions
if ((ntxns = atoi(argv[++i])) <= 0)
return (invarg('n', argv[i]));
}
else if (strcmp(argv[i], "-S") == 0) {
// Random number seed.
seed = strtoul(argv[++i], &endarg, 0);
if (*endarg != '\0')
return (invarg('S', argv[i]));
}
else if (strcmp(argv[i], "-s") == 0) {
// Number of history records
if ((history = atoi(argv[++i])) <= 0)
return (invarg('s', argv[i]));
}
else if (strcmp(argv[i], "-t") == 0) {
// Number of teller records
if ((tellers = atoi(argv[++i])) <= 0)
return (invarg('t', argv[i]));
}
else if (strcmp(argv[i], "-v") == 0) {
// Verbose option.
verbose = 1;
}
else {
return (usage());
}
}
srand((unsigned int)seed);
accounts = accounts == 0 ? ACCOUNTS : accounts;
branches = branches == 0 ? BRANCHES : branches;
tellers = tellers == 0 ? TELLERS : tellers;
history = history == 0 ? HISTORY : history;
if (verbose)
cout << (long)accounts << " Accounts, "
<< (long)branches << " Branches, "
<< (long)tellers << " Tellers, "
<< (long)history << " History\n";
try {
// Initialize the database environment.
// Must be done in within a try block, unless you
// change the error model in the environment options.
//
TpcbExample app(home, mpool, iflag,
txn_no_sync ? DB_TXN_NOSYNC : 0);
if (iflag) {
if (ntxns != 0)
return (usage());
app.populate(accounts, branches, history, tellers);
}
else {
if (ntxns == 0)
return (usage());
app.run(ntxns, accounts, branches, tellers);
}
app.close(0);
return (EXIT_SUCCESS);
}
catch (DbException &dbe) {
cerr << "TpcbExample: " << dbe.what() << "\n";
return (EXIT_FAILURE);
}
}
static int
invarg(int arg, char *str)
{
cerr << "TpcbExample: invalid argument for -"
<< (char)arg << ": " << str << "\n";
return (EXIT_FAILURE);
}
static int
usage()
{
cerr << "usage: TpcbExample [-fiv] [-a accounts] [-b branches]\n"
<< " [-c cachesize] [-h home] [-n transactions ]\n"
<< " [-S seed] [-s history] [-t tellers]\n";
return (EXIT_FAILURE);
}
TpcbExample::TpcbExample(const char *home, int cachesize,
int initializing, int flags)
: DbEnv(0)
{
u_int32_t local_flags;
set_error_stream(&cerr);
set_errpfx("TpcbExample");
(void)set_cachesize(0, cachesize == 0 ?
4 * 1024 * 1024 : (u_int32_t)cachesize, 0);
if (flags & (DB_TXN_NOSYNC))
set_flags(DB_TXN_NOSYNC, 1);
flags &= ~(DB_TXN_NOSYNC);
local_flags = flags | DB_CREATE | DB_INIT_MPOOL;
if (!initializing)
local_flags |= DB_INIT_TXN | DB_INIT_LOCK | DB_INIT_LOG;
open(home, local_flags, 0);
}
//
// Initialize the database to the specified number of accounts, branches,
// history records, and tellers.
//
void
TpcbExample::populate(int accounts, int branches, int history, int tellers)
{
Db *dbp;
int err;
u_int32_t balance, idnum;
u_int32_t end_anum, end_bnum, end_tnum;
u_int32_t start_anum, start_bnum, start_tnum;
idnum = BEGID;
balance = 500000;
dbp = new Db(this, 0);
dbp->set_h_nelem((unsigned int)accounts);
if ((err = dbp->open(NULL, "account", NULL, DB_HASH,
DB_CREATE | DB_TRUNCATE, 0644)) != 0) {
DbException except("Account file create failed", err);
throw except;
}
start_anum = idnum;
populateTable(dbp, idnum, balance, accounts, "account");
idnum += accounts;
end_anum = idnum - 1;
if ((err = dbp->close(0)) != 0) {
DbException except("Account file close failed", err);
throw except;
}
delete dbp;
if (verbose)
cout << "Populated accounts: "
<< (long)start_anum << " - " << (long)end_anum << "\n";
dbp = new Db(this, 0);
//
// Since the number of branches is very small, we want to use very
// small pages and only 1 key per page. This is the poor-man's way
// of getting key locking instead of page locking.
//
dbp->set_h_ffactor(1);
dbp->set_h_nelem((unsigned int)branches);
dbp->set_pagesize(512);
if ((err = dbp->open(NULL, "branch", NULL, DB_HASH,
DB_CREATE | DB_TRUNCATE, 0644)) != 0) {
DbException except("Branch file create failed", err);
throw except;
}
start_bnum = idnum;
populateTable(dbp, idnum, balance, branches, "branch");
idnum += branches;
end_bnum = idnum - 1;
if ((err = dbp->close(0)) != 0) {
DbException except("Close of branch file failed", err);
throw except;
}
delete dbp;
if (verbose)
cout << "Populated branches: "
<< (long)start_bnum << " - " << (long)end_bnum << "\n";
dbp = new Db(this, 0);
//
// In the case of tellers, we also want small pages, but we'll let
// the fill factor dynamically adjust itself.
//
dbp->set_h_ffactor(0);
dbp->set_h_nelem((unsigned int)tellers);
dbp->set_pagesize(512);
if ((err = dbp->open(NULL, "teller", NULL, DB_HASH,
DB_CREATE | DB_TRUNCATE, 0644)) != 0) {
DbException except("Teller file create failed", err);
throw except;
}
start_tnum = idnum;
populateTable(dbp, idnum, balance, tellers, "teller");
idnum += tellers;
end_tnum = idnum - 1;
if ((err = dbp->close(0)) != 0) {
DbException except("Close of teller file failed", err);
throw except;
}
delete dbp;
if (verbose)
cout << "Populated tellers: "
<< (long)start_tnum << " - " << (long)end_tnum << "\n";
dbp = new Db(this, 0);
dbp->set_re_len(HISTORY_LEN);
if ((err = dbp->open(NULL, "history", NULL, DB_RECNO,
DB_CREATE | DB_TRUNCATE, 0644)) != 0) {
DbException except("Create of history file failed", err);
throw except;
}
populateHistory(dbp, history, accounts, branches, tellers);
if ((err = dbp->close(0)) != 0) {
DbException except("Close of history file failed", err);
throw except;
}
delete dbp;
}
void
TpcbExample::populateTable(Db *dbp,
u_int32_t start_id, u_int32_t balance,
int nrecs, const char *msg)
{
Defrec drec;
memset(&drec.pad[0], 1, sizeof(drec.pad));
Dbt kdbt(&drec.id, sizeof(u_int32_t));
Dbt ddbt(&drec, sizeof(drec));
for (int i = 0; i < nrecs; i++) {
drec.id = start_id + (u_int32_t)i;
drec.balance = balance;
int err;
if ((err =
dbp->put(NULL, &kdbt, &ddbt, DB_NOOVERWRITE)) != 0) {
cerr << "Failure initializing " << msg << " file: "
<< strerror(err) << "\n";
DbException except("failure initializing file", err);
throw except;
}
}
}
void
TpcbExample::populateHistory(Db *dbp, int nrecs, u_int32_t accounts,
u_int32_t branches, u_int32_t tellers)
{
Histrec hrec;
memset(&hrec.pad[0], 1, sizeof(hrec.pad));
hrec.amount = 10;
db_recno_t key;
Dbt kdbt(&key, sizeof(u_int32_t));
Dbt ddbt(&hrec, sizeof(hrec));
for (int i = 1; i <= nrecs; i++) {
hrec.aid = random_id(ACCOUNT, accounts, branches, tellers);
hrec.bid = random_id(BRANCH, accounts, branches, tellers);
hrec.tid = random_id(TELLER, accounts, branches, tellers);
int err;
key = (db_recno_t)i;
if ((err = dbp->put(NULL, &kdbt, &ddbt, DB_APPEND)) != 0) {
DbException except("failure initializing history file",
err);
throw except;
}
}
}
u_int32_t
random_int(u_int32_t lo, u_int32_t hi)
{
u_int32_t ret;
int t;
t = rand();
ret = (u_int32_t)(((double)t / ((double)(RAND_MAX) + 1)) *
(hi - lo + 1));
ret += lo;
return (ret);
}
u_int32_t
random_id(FTYPE type, u_int32_t accounts, u_int32_t branches, u_int32_t tellers)
{
u_int32_t min, max, num;
max = min = BEGID;
num = accounts;
switch(type) {
case TELLER:
min += branches;
num = tellers;
// Fallthrough
case BRANCH:
if (type == BRANCH)
num = branches;
min += accounts;
// Fallthrough
case ACCOUNT:
max = min + num - 1;
}
return (random_int(min, max));
}
void
TpcbExample::run(int n, int accounts, int branches, int tellers)
{
Db *adb, *bdb, *hdb, *tdb;
double gtps, itps;
int failed, ifailed, ret, txns;
time_t starttime, curtime, lasttime;
//
// Open the database files.
//
int err;
adb = new Db(this, 0);
if ((err = adb->open(NULL, "account", NULL, DB_UNKNOWN,
DB_AUTO_COMMIT, 0)) != 0) {
DbException except("Open of account file failed", err);
throw except;
}
bdb = new Db(this, 0);
if ((err = bdb->open(NULL, "branch", NULL, DB_UNKNOWN,
DB_AUTO_COMMIT, 0)) != 0) {
DbException except("Open of branch file failed", err);
throw except;
}
tdb = new Db(this, 0);
if ((err = tdb->open(NULL, "teller", NULL, DB_UNKNOWN,
DB_AUTO_COMMIT, 0)) != 0) {
DbException except("Open of teller file failed", err);
throw except;
}
hdb = new Db(this, 0);
if ((err = hdb->open(NULL, "history", NULL, DB_UNKNOWN,
DB_AUTO_COMMIT, 0)) != 0) {
DbException except("Open of history file failed", err);
throw except;
}
txns = failed = ifailed = 0;
starttime = time(NULL);
lasttime = starttime;
while (n-- > 0) {
txns++;
ret = txn(adb, bdb, tdb, hdb, accounts, branches, tellers);
if (ret != 0) {
failed++;
ifailed++;
}
if (n % 5000 == 0) {
curtime = time(NULL);
gtps = (double)(txns - failed) / (curtime - starttime);
itps = (double)(5000 - ifailed) / (curtime - lasttime);
// We use printf because it provides much simpler
// formatting than iostreams.
//
printf("%d txns %d failed ", txns, failed);
printf("%6.2f TPS (gross) %6.2f TPS (interval)\n",
gtps, itps);
lasttime = curtime;
ifailed = 0;
}
}
(void)adb->close(0);
(void)bdb->close(0);
(void)tdb->close(0);
(void)hdb->close(0);
cout << (long)txns << " transactions begun "
<< (long)failed << " failed\n";
}
//
// XXX Figure out the appropriate way to pick out IDs.
//
int
TpcbExample::txn(Db *adb, Db *bdb, Db *tdb, Db *hdb,
int accounts, int branches, int tellers)
{
Dbc *acurs = NULL;
Dbc *bcurs = NULL;
Dbc *tcurs = NULL;
DbTxn *t = NULL;
db_recno_t key;
Defrec rec;
Histrec hrec;
int account, branch, teller, ret;
Dbt d_dbt;
Dbt d_histdbt;
Dbt k_dbt;
Dbt k_histdbt(&key, sizeof(key));
//
// XXX We could move a lot of this into the driver to make this
// faster.
//
account = random_id(ACCOUNT, accounts, branches, tellers);
branch = random_id(BRANCH, accounts, branches, tellers);
teller = random_id(TELLER, accounts, branches, tellers);
k_dbt.set_size(sizeof(int));
d_dbt.set_flags(DB_DBT_USERMEM);
d_dbt.set_data(&rec);
d_dbt.set_ulen(sizeof(rec));
hrec.aid = account;
hrec.bid = branch;
hrec.tid = teller;
hrec.amount = 10;
// Request 0 bytes since we're just positioning.
d_histdbt.set_flags(DB_DBT_PARTIAL);
// START TIMING
if (txn_begin(NULL, &t, 0) != 0)
goto err;
if (adb->cursor(t, &acurs, 0) != 0 ||
bdb->cursor(t, &bcurs, 0) != 0 ||
tdb->cursor(t, &tcurs, 0) != 0)
goto err;
// Account record
k_dbt.set_data(&account);
if (acurs->get(&k_dbt, &d_dbt, DB_SET) != 0)
goto err;
rec.balance += 10;
if (acurs->put(&k_dbt, &d_dbt, DB_CURRENT) != 0)
goto err;
// Branch record
k_dbt.set_data(&branch);
if (bcurs->get(&k_dbt, &d_dbt, DB_SET) != 0)
goto err;
rec.balance += 10;
if (bcurs->put(&k_dbt, &d_dbt, DB_CURRENT) != 0)
goto err;
// Teller record
k_dbt.set_data(&teller);
if (tcurs->get(&k_dbt, &d_dbt, DB_SET) != 0)
goto err;
rec.balance += 10;
if (tcurs->put(&k_dbt, &d_dbt, DB_CURRENT) != 0)
goto err;
// History record
d_histdbt.set_flags(0);
d_histdbt.set_data(&hrec);
d_histdbt.set_ulen(sizeof(hrec));
if (hdb->put(t, &k_histdbt, &d_histdbt, DB_APPEND) != 0)
goto err;
if (acurs->close() != 0 || bcurs->close() != 0 || tcurs->close() != 0)
goto err;
ret = t->commit(0);
t = NULL;
if (ret != 0)
goto err;
// END TIMING
return (0);
err:
if (acurs != NULL)
(void)acurs->close();
if (bcurs != NULL)
(void)bcurs->close();
if (tcurs != NULL)
(void)tcurs->close();
if (t != NULL)
(void)t->abort();
if (verbose)
cout << "Transaction A=" << (long)account
<< " B=" << (long)branch
<< " T=" << (long)teller << " failed\n";
return (-1);
}

View File

@ -1,761 +0,0 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 1997-2002
* Sleepycat Software. All rights reserved.
*
* $Id: Db.java,v 11.110 2002/09/09 20:47:31 bostic Exp $
*/
package com.sleepycat.db;
import java.io.OutputStream;
import java.io.FileNotFoundException;
/**
*
* @author Donald D. Anderson
*/
public class Db
{
// BEGIN-JAVA-SPECIAL-CONSTANTS
/* DO NOT EDIT: automatically built by dist/s_java. */
public static final int DB_BTREE = 1;
public static final int DB_DONOTINDEX = -30999;
public static final int DB_HASH = 2;
public static final int DB_KEYEMPTY = -30998;
public static final int DB_KEYEXIST = -30997;
public static final int DB_LOCK_DEADLOCK = -30996;
public static final int DB_LOCK_NOTGRANTED = -30995;
public static final int DB_NOSERVER = -30994;
public static final int DB_NOSERVER_HOME = -30993;
public static final int DB_NOSERVER_ID = -30992;
public static final int DB_NOTFOUND = -30991;
public static final int DB_OLD_VERSION = -30990;
public static final int DB_PAGE_NOTFOUND = -30989;
public static final int DB_QUEUE = 4;
public static final int DB_RECNO = 3;
public static final int DB_REP_DUPMASTER = -30988;
public static final int DB_REP_HOLDELECTION = -30987;
public static final int DB_REP_NEWMASTER = -30986;
public static final int DB_REP_NEWSITE = -30985;
public static final int DB_REP_OUTDATED = -30984;
public static final int DB_RUNRECOVERY = -30982;
public static final int DB_SECONDARY_BAD = -30981;
public static final int DB_TXN_ABORT = 0;
public static final int DB_TXN_APPLY = 1;
public static final int DB_TXN_BACKWARD_ROLL = 3;
public static final int DB_TXN_FORWARD_ROLL = 4;
public static final int DB_TXN_PRINT = 8;
public static final int DB_UNKNOWN = 5;
public static final int DB_VERIFY_BAD = -30980;
public static final int DB_AFTER;
public static final int DB_AGGRESSIVE;
public static final int DB_APPEND;
public static final int DB_ARCH_ABS;
public static final int DB_ARCH_DATA;
public static final int DB_ARCH_LOG;
public static final int DB_AUTO_COMMIT;
public static final int DB_BEFORE;
public static final int DB_CACHED_COUNTS;
public static final int DB_CDB_ALLDB;
public static final int DB_CHKSUM_SHA1;
public static final int DB_CLIENT;
public static final int DB_CONSUME;
public static final int DB_CONSUME_WAIT;
public static final int DB_CREATE;
public static final int DB_CURRENT;
public static final int DB_CXX_NO_EXCEPTIONS;
public static final int DB_DBT_MALLOC;
public static final int DB_DBT_PARTIAL;
public static final int DB_DBT_REALLOC;
public static final int DB_DBT_USERMEM;
public static final int DB_DIRECT;
public static final int DB_DIRECT_DB;
public static final int DB_DIRECT_LOG;
public static final int DB_DIRTY_READ;
public static final int DB_DUP;
public static final int DB_DUPSORT;
public static final int DB_EID_BROADCAST;
public static final int DB_EID_INVALID;
public static final int DB_ENCRYPT;
public static final int DB_ENCRYPT_AES;
public static final int DB_EXCL;
public static final int DB_FAST_STAT;
public static final int DB_FIRST;
public static final int DB_FLUSH;
public static final int DB_FORCE;
public static final int DB_GET_BOTH;
public static final int DB_GET_BOTH_RANGE;
public static final int DB_GET_RECNO;
public static final int DB_INIT_CDB;
public static final int DB_INIT_LOCK;
public static final int DB_INIT_LOG;
public static final int DB_INIT_MPOOL;
public static final int DB_INIT_TXN;
public static final int DB_JOINENV;
public static final int DB_JOIN_ITEM;
public static final int DB_JOIN_NOSORT;
public static final int DB_KEYFIRST;
public static final int DB_KEYLAST;
public static final int DB_LAST;
public static final int DB_LOCKDOWN;
public static final int DB_LOCK_DEFAULT;
public static final int DB_LOCK_EXPIRE;
public static final int DB_LOCK_GET;
public static final int DB_LOCK_GET_TIMEOUT;
public static final int DB_LOCK_IREAD;
public static final int DB_LOCK_IWR;
public static final int DB_LOCK_IWRITE;
public static final int DB_LOCK_MAXLOCKS;
public static final int DB_LOCK_MINLOCKS;
public static final int DB_LOCK_MINWRITE;
public static final int DB_LOCK_NOWAIT;
public static final int DB_LOCK_OLDEST;
public static final int DB_LOCK_PUT;
public static final int DB_LOCK_PUT_ALL;
public static final int DB_LOCK_PUT_OBJ;
public static final int DB_LOCK_RANDOM;
public static final int DB_LOCK_READ;
public static final int DB_LOCK_TIMEOUT;
public static final int DB_LOCK_WRITE;
public static final int DB_LOCK_YOUNGEST;
public static final int DB_MULTIPLE;
public static final int DB_MULTIPLE_KEY;
public static final int DB_NEXT;
public static final int DB_NEXT_DUP;
public static final int DB_NEXT_NODUP;
public static final int DB_NODUPDATA;
public static final int DB_NOLOCKING;
public static final int DB_NOMMAP;
public static final int DB_NOORDERCHK;
public static final int DB_NOOVERWRITE;
public static final int DB_NOPANIC;
public static final int DB_NOSYNC;
public static final int DB_ODDFILESIZE;
public static final int DB_ORDERCHKONLY;
public static final int DB_OVERWRITE;
public static final int DB_PANIC_ENVIRONMENT;
public static final int DB_POSITION;
public static final int DB_PREV;
public static final int DB_PREV_NODUP;
public static final int DB_PRINTABLE;
public static final int DB_PRIORITY_DEFAULT;
public static final int DB_PRIORITY_HIGH;
public static final int DB_PRIORITY_LOW;
public static final int DB_PRIORITY_VERY_HIGH;
public static final int DB_PRIORITY_VERY_LOW;
public static final int DB_PRIVATE;
public static final int DB_RDONLY;
public static final int DB_RECNUM;
public static final int DB_RECORDCOUNT;
public static final int DB_RECOVER;
public static final int DB_RECOVER_FATAL;
public static final int DB_REGION_INIT;
public static final int DB_RENUMBER;
public static final int DB_REP_CLIENT;
public static final int DB_REP_LOGSONLY;
public static final int DB_REP_MASTER;
public static final int DB_REP_PERMANENT;
public static final int DB_REP_UNAVAIL;
public static final int DB_REVSPLITOFF;
public static final int DB_RMW;
public static final int DB_SALVAGE;
public static final int DB_SET;
public static final int DB_SET_LOCK_TIMEOUT;
public static final int DB_SET_RANGE;
public static final int DB_SET_RECNO;
public static final int DB_SET_TXN_TIMEOUT;
public static final int DB_SNAPSHOT;
public static final int DB_STAT_CLEAR;
public static final int DB_SYSTEM_MEM;
public static final int DB_THREAD;
public static final int DB_TRUNCATE;
public static final int DB_TXN_NOSYNC;
public static final int DB_TXN_NOWAIT;
public static final int DB_TXN_SYNC;
public static final int DB_TXN_WRITE_NOSYNC;
public static final int DB_UPGRADE;
public static final int DB_USE_ENVIRON;
public static final int DB_USE_ENVIRON_ROOT;
public static final int DB_VERB_CHKPOINT;
public static final int DB_VERB_DEADLOCK;
public static final int DB_VERB_RECOVERY;
public static final int DB_VERB_REPLICATION;
public static final int DB_VERB_WAITSFOR;
public static final int DB_VERIFY;
public static final int DB_VERSION_MAJOR;
public static final int DB_VERSION_MINOR;
public static final int DB_VERSION_PATCH;
public static final int DB_WRITECURSOR;
public static final int DB_XA_CREATE;
public static final int DB_XIDDATASIZE;
public static final int DB_YIELDCPU;
// END-JAVA-SPECIAL-CONSTANTS
// Note: the env can be null
//
public Db(DbEnv env, int flags)
throws DbException
{
constructor_env_ = env;
_init(env, flags);
if (env == null) {
dbenv_ = new DbEnv(this);
}
else {
dbenv_ = env;
}
dbenv_._add_db(this);
}
//
// Our parent DbEnv is notifying us that the environment is closing.
//
/*package*/ void _notify_dbenv_close()
{
dbenv_ = null;
_notify_internal();
}
private native void _init(DbEnv env, int flags)
throws DbException;
private native void _notify_internal();
// methods
//
public synchronized void associate(DbTxn txn, Db secondary,
DbSecondaryKeyCreate key_creator,
int flags)
throws DbException
{
secondary.secondary_key_create_ = key_creator;
_associate(txn, secondary, key_creator, flags);
}
public native void _associate(DbTxn txn, Db secondary,
DbSecondaryKeyCreate key_creator, int flags)
throws DbException;
public synchronized int close(int flags)
throws DbException
{
try {
dbenv_._remove_db(this);
return _close(flags);
}
finally {
if (constructor_env_ == null) {
dbenv_._notify_db_close();
}
dbenv_ = null;
}
}
public native int _close(int flags)
throws DbException;
public native Dbc cursor(DbTxn txnid, int flags)
throws DbException;
public native int del(DbTxn txnid, Dbt key, int flags)
throws DbException;
public native void err(int errcode, String message);
public native void errx(String message);
public native int fd()
throws DbException;
// overrides Object.finalize
protected void finalize()
throws Throwable
{
if (dbenv_ == null)
_finalize(null, null);
else
_finalize(dbenv_.errcall_, dbenv_.errpfx_);
}
protected native void _finalize(DbErrcall errcall, String errpfx)
throws Throwable;
// returns: 0, DB_NOTFOUND, or throws error
public native int get(DbTxn txnid, Dbt key, Dbt data, int flags)
throws DbException;
public native boolean get_byteswapped();
public native /*DBTYPE*/ int get_type();
public native Dbc join(Dbc curslist[], int flags)
throws DbException;
public native void key_range(DbTxn txnid, Dbt key,
DbKeyRange range, int flags)
throws DbException;
public synchronized void open(DbTxn txnid, String file,
String database, /*DBTYPE*/ int type,
int flags, int mode)
throws DbException, FileNotFoundException
{
_open(txnid, file, database, type, flags, mode);
}
// (Internal)
public native void _open(DbTxn txnid, String file,
String database, /*DBTYPE*/ int type,
int flags, int mode)
throws DbException, FileNotFoundException;
// returns: 0, DB_NOTFOUND, or throws error
public native int pget(DbTxn txnid, Dbt key, Dbt pkey, Dbt data, int flags)
throws DbException;
// returns: 0, DB_KEYEXIST, or throws error
public native int put(DbTxn txnid, Dbt key, Dbt data, int flags)
throws DbException;
public synchronized void rename(String file, String database,
String newname, int flags)
throws DbException, FileNotFoundException
{
try {
_rename(file, database, newname, flags);
}
finally {
if (constructor_env_ == null) {
dbenv_._notify_db_close();
}
dbenv_ = null;
}
}
public native void _rename(String file, String database,
String newname, int flags)
throws DbException, FileNotFoundException;
public synchronized void remove(String file,
String database, int flags)
throws DbException, FileNotFoundException
{
try {
_remove(file, database, flags);
}
finally {
if (constructor_env_ == null) {
dbenv_._notify_db_close();
}
dbenv_ = null;
}
}
public native void _remove(String file, String database,
int flags)
throws DbException, FileNotFoundException;
// Comparison function.
public void set_append_recno(DbAppendRecno append_recno)
throws DbException
{
append_recno_ = append_recno;
append_recno_changed(append_recno);
}
// (Internal)
private native void append_recno_changed(DbAppendRecno append_recno)
throws DbException;
// Comparison function.
public void set_bt_compare(DbBtreeCompare bt_compare)
throws DbException
{
bt_compare_ = bt_compare;
bt_compare_changed(bt_compare);
}
// (Internal)
private native void bt_compare_changed(DbBtreeCompare bt_compare)
throws DbException;
// Maximum keys per page.
public native void set_bt_maxkey(int maxkey)
throws DbException;
// Minimum keys per page.
public native void set_bt_minkey(int minkey)
throws DbException;
// Prefix function.
public void set_bt_prefix(DbBtreePrefix bt_prefix)
throws DbException
{
bt_prefix_ = bt_prefix;
bt_prefix_changed(bt_prefix);
}
// (Internal)
private native void bt_prefix_changed(DbBtreePrefix bt_prefix)
throws DbException;
// Set cache size
public native void set_cachesize(int gbytes, int bytes, int ncaches)
throws DbException;
// Set cache priority
public native void set_cache_priority(/* DB_CACHE_PRIORITY */ int priority)
throws DbException;
// Duplication resolution
public void set_dup_compare(DbDupCompare dup_compare)
throws DbException
{
dup_compare_ = dup_compare;
dup_compare_changed(dup_compare);
}
// (Internal)
private native void dup_compare_changed(DbDupCompare dup_compare)
throws DbException;
// Encryption
public native void set_encrypt(String passwd, /*u_int32_t*/ int flags)
throws DbException;
// Error message callback.
public void set_errcall(DbErrcall errcall)
{
if (dbenv_ != null)
dbenv_.set_errcall(errcall);
}
// Error stream.
public void set_error_stream(OutputStream s)
{
DbOutputStreamErrcall errcall = new DbOutputStreamErrcall(s);
set_errcall(errcall);
}
// Error message prefix.
public void set_errpfx(String errpfx)
{
if (dbenv_ != null)
dbenv_.set_errpfx(errpfx);
}
// Feedback
public void set_feedback(DbFeedback feedback)
throws DbException
{
feedback_ = feedback;
feedback_changed(feedback);
}
// (Internal)
private native void feedback_changed(DbFeedback feedback)
throws DbException;
// Flags.
public native void set_flags(/*u_int32_t*/ int flags)
throws DbException;
// Internal - only intended for testing purposes in the Java RPC server
public native int get_flags_raw()
throws DbException;
// Fill factor.
public native void set_h_ffactor(/*unsigned*/ int h_ffactor)
throws DbException;
// Hash function.
public void set_h_hash(DbHash h_hash)
throws DbException
{
h_hash_ = h_hash;
hash_changed(h_hash);
}
// (Internal)
private native void hash_changed(DbHash hash)
throws DbException;
// Number of elements.
public native void set_h_nelem(/*unsigned*/ int h_nelem)
throws DbException;
// Byte order.
public native void set_lorder(int lorder)
throws DbException;
// Underlying page size.
public native void set_pagesize(/*size_t*/ long pagesize)
throws DbException;
// Variable-length delimiting byte.
public native void set_re_delim(int re_delim)
throws DbException;
// Length for fixed-length records.
public native void set_re_len(/*u_int32_t*/ int re_len)
throws DbException;
// Fixed-length padding byte.
public native void set_re_pad(int re_pad)
throws DbException;
// Source file name.
public native void set_re_source(String re_source)
throws DbException;
// Extent size of Queue
public native void set_q_extentsize(/*u_int32_t*/ int extent_size)
throws DbException;
// returns a DbBtreeStat or DbHashStat
public native Object stat(int flags)
throws DbException;
public native void sync(int flags)
throws DbException;
public native int truncate(DbTxn txnid, int flags)
throws DbException;
public native void upgrade(String name, int flags)
throws DbException;
public native void verify(String name, String subdb,
OutputStream outstr, int flags)
throws DbException;
////////////////////////////////////////////////////////////////
//
// private data
//
private long private_dbobj_ = 0;
private long private_info_ = 0;
private DbEnv dbenv_ = null;
private DbEnv constructor_env_ = null;
private DbFeedback feedback_ = null;
private DbAppendRecno append_recno_ = null;
private DbBtreeCompare bt_compare_ = null;
private DbBtreePrefix bt_prefix_ = null;
private DbDupCompare dup_compare_ = null;
private DbHash h_hash_ = null;
private DbSecondaryKeyCreate secondary_key_create_ = null;
////////////////////////////////////////////////////////////////
//
// static methods and data that implement
// loading the native library and doing any
// extra sanity checks on startup.
//
private static boolean already_loaded_ = false;
public static void load_db()
{
if (already_loaded_)
return;
// An alternate library name can be specified via a property.
//
String override;
if ((override = System.getProperty("sleepycat.db.libfile")) != null) {
System.load(override);
}
else if ((override = System.getProperty("sleepycat.db.libname")) != null) {
System.loadLibrary(override);
}
else {
String os = System.getProperty("os.name");
if (os != null && os.startsWith("Windows")) {
// library name is "libdb_java30.dll" (for example) on Win/*
System.loadLibrary("libdb_java" +
DbConstants.DB_VERSION_MAJOR +
DbConstants.DB_VERSION_MINOR);
}
else {
// library name is "libdb_java-3.0.so" (for example) on UNIX
// Note: "db_java" isn't good enough;
// some Unixes require us to use the explicit SONAME.
System.loadLibrary("db_java-" +
DbConstants.DB_VERSION_MAJOR + "." +
DbConstants.DB_VERSION_MINOR);
}
}
already_loaded_ = true;
}
static private native void one_time_init();
static private void check_constant(int c1, int c2)
{
if (c1 != c2) {
System.err.println("Db: constant mismatch");
Thread.dumpStack();
System.exit(1);
}
}
static {
Db.load_db();
// BEGIN-JAVA-CONSTANT-INITIALIZATION
/* DO NOT EDIT: automatically built by dist/s_java. */
DB_AFTER = DbConstants.DB_AFTER;
DB_AGGRESSIVE = DbConstants.DB_AGGRESSIVE;
DB_APPEND = DbConstants.DB_APPEND;
DB_ARCH_ABS = DbConstants.DB_ARCH_ABS;
DB_ARCH_DATA = DbConstants.DB_ARCH_DATA;
DB_ARCH_LOG = DbConstants.DB_ARCH_LOG;
DB_AUTO_COMMIT = DbConstants.DB_AUTO_COMMIT;
DB_BEFORE = DbConstants.DB_BEFORE;
DB_CACHED_COUNTS = DbConstants.DB_CACHED_COUNTS;
DB_CDB_ALLDB = DbConstants.DB_CDB_ALLDB;
DB_CHKSUM_SHA1 = DbConstants.DB_CHKSUM_SHA1;
DB_CLIENT = DbConstants.DB_CLIENT;
DB_CONSUME = DbConstants.DB_CONSUME;
DB_CONSUME_WAIT = DbConstants.DB_CONSUME_WAIT;
DB_CREATE = DbConstants.DB_CREATE;
DB_CURRENT = DbConstants.DB_CURRENT;
DB_CXX_NO_EXCEPTIONS = DbConstants.DB_CXX_NO_EXCEPTIONS;
DB_DBT_MALLOC = DbConstants.DB_DBT_MALLOC;
DB_DBT_PARTIAL = DbConstants.DB_DBT_PARTIAL;
DB_DBT_REALLOC = DbConstants.DB_DBT_REALLOC;
DB_DBT_USERMEM = DbConstants.DB_DBT_USERMEM;
DB_DIRECT = DbConstants.DB_DIRECT;
DB_DIRECT_DB = DbConstants.DB_DIRECT_DB;
DB_DIRECT_LOG = DbConstants.DB_DIRECT_LOG;
DB_DIRTY_READ = DbConstants.DB_DIRTY_READ;
DB_DUP = DbConstants.DB_DUP;
DB_DUPSORT = DbConstants.DB_DUPSORT;
DB_EID_BROADCAST = DbConstants.DB_EID_BROADCAST;
DB_EID_INVALID = DbConstants.DB_EID_INVALID;
DB_ENCRYPT = DbConstants.DB_ENCRYPT;
DB_ENCRYPT_AES = DbConstants.DB_ENCRYPT_AES;
DB_EXCL = DbConstants.DB_EXCL;
DB_FAST_STAT = DbConstants.DB_FAST_STAT;
DB_FIRST = DbConstants.DB_FIRST;
DB_FLUSH = DbConstants.DB_FLUSH;
DB_FORCE = DbConstants.DB_FORCE;
DB_GET_BOTH = DbConstants.DB_GET_BOTH;
DB_GET_BOTH_RANGE = DbConstants.DB_GET_BOTH_RANGE;
DB_GET_RECNO = DbConstants.DB_GET_RECNO;
DB_INIT_CDB = DbConstants.DB_INIT_CDB;
DB_INIT_LOCK = DbConstants.DB_INIT_LOCK;
DB_INIT_LOG = DbConstants.DB_INIT_LOG;
DB_INIT_MPOOL = DbConstants.DB_INIT_MPOOL;
DB_INIT_TXN = DbConstants.DB_INIT_TXN;
DB_JOINENV = DbConstants.DB_JOINENV;
DB_JOIN_ITEM = DbConstants.DB_JOIN_ITEM;
DB_JOIN_NOSORT = DbConstants.DB_JOIN_NOSORT;
DB_KEYFIRST = DbConstants.DB_KEYFIRST;
DB_KEYLAST = DbConstants.DB_KEYLAST;
DB_LAST = DbConstants.DB_LAST;
DB_LOCKDOWN = DbConstants.DB_LOCKDOWN;
DB_LOCK_DEFAULT = DbConstants.DB_LOCK_DEFAULT;
DB_LOCK_EXPIRE = DbConstants.DB_LOCK_EXPIRE;
DB_LOCK_GET = DbConstants.DB_LOCK_GET;
DB_LOCK_GET_TIMEOUT = DbConstants.DB_LOCK_GET_TIMEOUT;
DB_LOCK_IREAD = DbConstants.DB_LOCK_IREAD;
DB_LOCK_IWR = DbConstants.DB_LOCK_IWR;
DB_LOCK_IWRITE = DbConstants.DB_LOCK_IWRITE;
DB_LOCK_MAXLOCKS = DbConstants.DB_LOCK_MAXLOCKS;
DB_LOCK_MINLOCKS = DbConstants.DB_LOCK_MINLOCKS;
DB_LOCK_MINWRITE = DbConstants.DB_LOCK_MINWRITE;
DB_LOCK_NOWAIT = DbConstants.DB_LOCK_NOWAIT;
DB_LOCK_OLDEST = DbConstants.DB_LOCK_OLDEST;
DB_LOCK_PUT = DbConstants.DB_LOCK_PUT;
DB_LOCK_PUT_ALL = DbConstants.DB_LOCK_PUT_ALL;
DB_LOCK_PUT_OBJ = DbConstants.DB_LOCK_PUT_OBJ;
DB_LOCK_RANDOM = DbConstants.DB_LOCK_RANDOM;
DB_LOCK_READ = DbConstants.DB_LOCK_READ;
DB_LOCK_TIMEOUT = DbConstants.DB_LOCK_TIMEOUT;
DB_LOCK_WRITE = DbConstants.DB_LOCK_WRITE;
DB_LOCK_YOUNGEST = DbConstants.DB_LOCK_YOUNGEST;
DB_MULTIPLE = DbConstants.DB_MULTIPLE;
DB_MULTIPLE_KEY = DbConstants.DB_MULTIPLE_KEY;
DB_NEXT = DbConstants.DB_NEXT;
DB_NEXT_DUP = DbConstants.DB_NEXT_DUP;
DB_NEXT_NODUP = DbConstants.DB_NEXT_NODUP;
DB_NODUPDATA = DbConstants.DB_NODUPDATA;
DB_NOLOCKING = DbConstants.DB_NOLOCKING;
DB_NOMMAP = DbConstants.DB_NOMMAP;
DB_NOORDERCHK = DbConstants.DB_NOORDERCHK;
DB_NOOVERWRITE = DbConstants.DB_NOOVERWRITE;
DB_NOPANIC = DbConstants.DB_NOPANIC;
DB_NOSYNC = DbConstants.DB_NOSYNC;
DB_ODDFILESIZE = DbConstants.DB_ODDFILESIZE;
DB_ORDERCHKONLY = DbConstants.DB_ORDERCHKONLY;
DB_OVERWRITE = DbConstants.DB_OVERWRITE;
DB_PANIC_ENVIRONMENT = DbConstants.DB_PANIC_ENVIRONMENT;
DB_POSITION = DbConstants.DB_POSITION;
DB_PREV = DbConstants.DB_PREV;
DB_PREV_NODUP = DbConstants.DB_PREV_NODUP;
DB_PRINTABLE = DbConstants.DB_PRINTABLE;
DB_PRIORITY_DEFAULT = DbConstants.DB_PRIORITY_DEFAULT;
DB_PRIORITY_HIGH = DbConstants.DB_PRIORITY_HIGH;
DB_PRIORITY_LOW = DbConstants.DB_PRIORITY_LOW;
DB_PRIORITY_VERY_HIGH = DbConstants.DB_PRIORITY_VERY_HIGH;
DB_PRIORITY_VERY_LOW = DbConstants.DB_PRIORITY_VERY_LOW;
DB_PRIVATE = DbConstants.DB_PRIVATE;
DB_RDONLY = DbConstants.DB_RDONLY;
DB_RECNUM = DbConstants.DB_RECNUM;
DB_RECORDCOUNT = DbConstants.DB_RECORDCOUNT;
DB_RECOVER = DbConstants.DB_RECOVER;
DB_RECOVER_FATAL = DbConstants.DB_RECOVER_FATAL;
DB_REGION_INIT = DbConstants.DB_REGION_INIT;
DB_RENUMBER = DbConstants.DB_RENUMBER;
DB_REP_CLIENT = DbConstants.DB_REP_CLIENT;
DB_REP_LOGSONLY = DbConstants.DB_REP_LOGSONLY;
DB_REP_MASTER = DbConstants.DB_REP_MASTER;
DB_REP_PERMANENT = DbConstants.DB_REP_PERMANENT;
DB_REP_UNAVAIL = DbConstants.DB_REP_UNAVAIL;
DB_REVSPLITOFF = DbConstants.DB_REVSPLITOFF;
DB_RMW = DbConstants.DB_RMW;
DB_SALVAGE = DbConstants.DB_SALVAGE;
DB_SET = DbConstants.DB_SET;
DB_SET_LOCK_TIMEOUT = DbConstants.DB_SET_LOCK_TIMEOUT;
DB_SET_RANGE = DbConstants.DB_SET_RANGE;
DB_SET_RECNO = DbConstants.DB_SET_RECNO;
DB_SET_TXN_TIMEOUT = DbConstants.DB_SET_TXN_TIMEOUT;
DB_SNAPSHOT = DbConstants.DB_SNAPSHOT;
DB_STAT_CLEAR = DbConstants.DB_STAT_CLEAR;
DB_SYSTEM_MEM = DbConstants.DB_SYSTEM_MEM;
DB_THREAD = DbConstants.DB_THREAD;
DB_TRUNCATE = DbConstants.DB_TRUNCATE;
DB_TXN_NOSYNC = DbConstants.DB_TXN_NOSYNC;
DB_TXN_NOWAIT = DbConstants.DB_TXN_NOWAIT;
DB_TXN_SYNC = DbConstants.DB_TXN_SYNC;
DB_TXN_WRITE_NOSYNC = DbConstants.DB_TXN_WRITE_NOSYNC;
DB_UPGRADE = DbConstants.DB_UPGRADE;
DB_USE_ENVIRON = DbConstants.DB_USE_ENVIRON;
DB_USE_ENVIRON_ROOT = DbConstants.DB_USE_ENVIRON_ROOT;
DB_VERB_CHKPOINT = DbConstants.DB_VERB_CHKPOINT;
DB_VERB_DEADLOCK = DbConstants.DB_VERB_DEADLOCK;
DB_VERB_RECOVERY = DbConstants.DB_VERB_RECOVERY;
DB_VERB_REPLICATION = DbConstants.DB_VERB_REPLICATION;
DB_VERB_WAITSFOR = DbConstants.DB_VERB_WAITSFOR;
DB_VERIFY = DbConstants.DB_VERIFY;
DB_VERSION_MAJOR = DbConstants.DB_VERSION_MAJOR;
DB_VERSION_MINOR = DbConstants.DB_VERSION_MINOR;
DB_VERSION_PATCH = DbConstants.DB_VERSION_PATCH;
DB_WRITECURSOR = DbConstants.DB_WRITECURSOR;
DB_XA_CREATE = DbConstants.DB_XA_CREATE;
DB_XIDDATASIZE = DbConstants.DB_XIDDATASIZE;
DB_YIELDCPU = DbConstants.DB_YIELDCPU;
// END-JAVA-CONSTANT-INITIALIZATION
one_time_init();
}
}
// end of Db.java

View File

@ -1,22 +0,0 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 2000-2002
* Sleepycat Software. All rights reserved.
*
* $Id: DbAppDispatch.java,v 11.6 2002/02/26 16:23:02 krinsky Exp $
*/
package com.sleepycat.db;
/*
* This interface is used by DbEnv.set_app_dispatch()
*
*/
public interface DbAppDispatch
{
// The value of recops is one of the Db.DB_TXN_* constants
public abstract int app_dispatch(DbEnv env, Dbt dbt, DbLsn lsn, int recops);
}
// end of DbAppDispatch.java

View File

@ -1,22 +0,0 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 2000-2002
* Sleepycat Software. All rights reserved.
*
* $Id: DbAppendRecno.java,v 11.5 2002/01/11 15:52:33 bostic Exp $
*/
package com.sleepycat.db;
/*
* This interface is used by Db.set_append_recno()
*
*/
public interface DbAppendRecno
{
public abstract void db_append_recno(Db db, Dbt data, int recno)
throws DbException;
}
// end of DbAppendRecno.java

View File

@ -1,21 +0,0 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 2000-2002
* Sleepycat Software. All rights reserved.
*
* $Id: DbBtreeCompare.java,v 11.6 2002/01/11 15:52:33 bostic Exp $
*/
package com.sleepycat.db;
/*
* This interface is used by DbEnv.set_bt_compare()
*
*/
public interface DbBtreeCompare
{
public abstract int bt_compare(Db db, Dbt dbt1, Dbt dbt2);
}
// end of DbBtreeCompare.java

View File

@ -1,21 +0,0 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 2000-2002
* Sleepycat Software. All rights reserved.
*
* $Id: DbBtreePrefix.java,v 11.6 2002/01/11 15:52:33 bostic Exp $
*/
package com.sleepycat.db;
/*
* This interface is used by DbEnv.set_bt_prefix()
*
*/
public interface DbBtreePrefix
{
public abstract int bt_prefix(Db db, Dbt dbt1, Dbt dbt2);
}
// end of DbBtreePrefix.java

View File

@ -1,21 +0,0 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 2000-2002
* Sleepycat Software. All rights reserved.
*
* $Id: DbClient.java,v 11.4 2002/01/11 15:52:33 bostic Exp $
*/
package com.sleepycat.db;
/*
* This interface is used by DbEnv.set_rpc_server().
* It is a placeholder for a future capability.
*
*/
public interface DbClient
{
}
// end of DbClient.java

View File

@ -1,28 +0,0 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 1999-2002
* Sleepycat Software. All rights reserved.
*
* $Id: DbDeadlockException.java,v 11.6 2002/01/11 15:52:33 bostic Exp $
*/
package com.sleepycat.db;
public class DbDeadlockException extends DbException
{
// methods
//
public DbDeadlockException(String s)
{
super(s);
}
public DbDeadlockException(String s, int errno)
{
super(s, errno);
}
}
// end of DbDeadlockException.java

View File

@ -1,21 +0,0 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 2000-2002
* Sleepycat Software. All rights reserved.
*
* $Id: DbDupCompare.java,v 11.6 2002/01/11 15:52:34 bostic Exp $
*/
package com.sleepycat.db;
/*
* This interface is used by DbEnv.set_dup_compare()
*
*/
public interface DbDupCompare
{
public abstract int dup_compare(Db db, Dbt dbt1, Dbt dbt2);
}
// end of DbDupCompare.java

View File

@ -1,430 +0,0 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 1997-2002
* Sleepycat Software. All rights reserved.
*
* $Id: DbEnv.java,v 11.58 2002/08/29 14:22:22 margo Exp $
*/
package com.sleepycat.db;
import java.io.OutputStream;
import java.io.FileNotFoundException;
import java.util.Date;
import java.util.Enumeration;
import java.util.Vector;
/**
*
* @author Donald D. Anderson
*/
public class DbEnv
{
// methods
//
//
// After using this constructor, set any parameters via
// the set_* access methods below, and finally open
// the environment by calling open().
//
public DbEnv(int flags) throws DbException
{
constructor_flags_ = flags;
_init(errstream_, constructor_flags_);
}
//
// This constructor is purposely not public.
// It is used internally to create a DbEnv wrapper
// when an underlying environment already exists.
//
/*package*/ DbEnv(Db db)
{
_init_using_db(errstream_, db);
}
//
// When a Db is created, it is kept in a private list,
// so that Db's can be notified when the environment
// is closed. This allows us to detect and guard
// against the following situation:
// DbEnv env = new DbEnv(0);
// Db db = new Db(0);
// env.close();
// db.close();
//
// This *is* a programming error, but not protecting
// against it will crash the VM.
//
/*package*/ void _add_db(Db db)
{
dblist_.addElement(db);
}
//
// Remove from the private list of Db's.
//
/*package*/ void _remove_db(Db db)
{
dblist_.removeElement(db);
}
//
// Iterate all the Db's in the list, and
// notify them that the environment is closing,
// so they can clean up.
//
/*package*/ void _notify_dbs()
{
Enumeration enum = dblist_.elements();
while (enum.hasMoreElements()) {
Db db = (Db)enum.nextElement();
db._notify_dbenv_close();
}
dblist_.removeAllElements();
}
// close discards any internal memory.
// After using close, the DbEnv can be reopened.
//
public synchronized void close(int flags)
throws DbException
{
_notify_dbs();
_close(flags);
}
// (Internal)
private native void _close(int flags)
throws DbException;
public native void dbremove(DbTxn txn, String name, String subdb,
int flags)
throws DbException;
public native void dbrename(DbTxn txn, String name, String subdb,
String newname, int flags)
throws DbException;
public native void err(int errcode, String message);
public native void errx(String message);
// overrides Object.finalize
protected void finalize()
throws Throwable
{
_notify_dbs();
_finalize(errcall_, errpfx_);
}
// (Internal)
protected native void _finalize(DbErrcall errcall, String errpfx)
throws Throwable;
// (Internal)
// called during constructor
private native void _init(DbErrcall errcall, int flags) throws DbException;
// (Internal)
// called when DbEnv is constructed as part of Db constructor.
private native void _init_using_db(DbErrcall errcall, Db db);
/*package*/ native void _notify_db_close();
public native void open(String db_home, int flags, int mode)
throws DbException, FileNotFoundException;
// remove removes any files and discards any internal memory.
// (i.e. implicitly it does a close, if the environment is open).
// After using close, the DbEnv can no longer be used;
// create another one if needed.
//
public native synchronized void remove(String db_home, int flags)
throws DbException, FileNotFoundException;
////////////////////////////////////////////////////////////////
// simple get/set access methods
//
// If you are calling set_ methods, you need to
// use the constructor with one argument along with open().
public native void set_cachesize(int gbytes, int bytes, int ncaches)
throws DbException;
// Encryption
public native void set_encrypt(String passwd, /*u_int32_t*/ int flags)
throws DbException;
// Error message callback.
public void set_errcall(DbErrcall errcall)
{
errcall_ = errcall;
_set_errcall(errcall);
}
public native void _set_errcall(DbErrcall errcall);
// Error stream.
public void set_error_stream(OutputStream s)
{
DbOutputStreamErrcall errcall = new DbOutputStreamErrcall(s);
set_errcall(errcall);
}
// Error message prefix.
public void set_errpfx(String errpfx)
{
errpfx_ = errpfx;
_set_errpfx(errpfx);
}
private native void _set_errpfx(String errpfx);
// Feedback
public void set_feedback(DbEnvFeedback feedback)
throws DbException
{
feedback_ = feedback;
feedback_changed(feedback);
}
// (Internal)
private native void feedback_changed(DbEnvFeedback feedback)
throws DbException;
// Generate debugging messages.
public native void set_verbose(int which, boolean onoff)
throws DbException;
public native void set_data_dir(String data_dir)
throws DbException;
// Log buffer size.
public native void set_lg_bsize(/*u_int32_t*/ int lg_bsize)
throws DbException;
// Log directory.
public native void set_lg_dir(String lg_dir)
throws DbException;
// Maximum log file size.
public native void set_lg_max(/*u_int32_t*/ int lg_max)
throws DbException;
// Log region size.
public native void set_lg_regionmax(/*u_int32_t*/ int lg_regionmax)
throws DbException;
// Two dimensional conflict matrix.
public native void set_lk_conflicts(byte[][] lk_conflicts)
throws DbException;
// Deadlock detect on every conflict.
public native void set_lk_detect(/*u_int32_t*/ int lk_detect)
throws DbException;
/**
* @deprecated DB 3.2.6, see the online documentation.
*/
// Maximum number of locks.
public native void set_lk_max(/*unsigned*/ int lk_max)
throws DbException;
// Maximum number of lockers.
public native void set_lk_max_lockers(/*unsigned*/ int lk_max_lockers)
throws DbException;
// Maximum number of locks.
public native void set_lk_max_locks(/*unsigned*/ int lk_max_locks)
throws DbException;
// Maximum number of locked objects.
public native void set_lk_max_objects(/*unsigned*/ int lk_max_objects)
throws DbException;
// Maximum file size for mmap.
public native void set_mp_mmapsize(/*size_t*/ long mmapsize)
throws DbException;
public native void set_flags(int flags, boolean onoff)
throws DbException;
public native void set_rep_limit(int gbytes, int bytes) throws DbException;
public void set_rep_transport(int envid, DbRepTransport transport)
throws DbException
{
rep_transport_ = transport;
rep_transport_changed(envid, transport);
}
// (Internal)
private native void rep_transport_changed(int envid,
DbRepTransport transport)
throws DbException;
public native void set_rpc_server(DbClient client, String host,
long cl_timeout, long sv_timeout,
int flags)
throws DbException;
public native void set_shm_key(long shm_key)
throws DbException;
public native void set_tas_spins(int tas_spins)
throws DbException;
public native void set_timeout(/*db_timeout_t*/ long timeout,
/*u_int32_t*/ int flags)
throws DbException;
public native void set_tmp_dir(String tmp_dir)
throws DbException;
// Feedback
public void set_app_dispatch(DbAppDispatch app_dispatch)
throws DbException
{
app_dispatch_ = app_dispatch;
app_dispatch_changed(app_dispatch);
}
// (Internal)
private native void app_dispatch_changed(DbAppDispatch app_dispatch)
throws DbException;
// Maximum number of transactions.
public native void set_tx_max(/*unsigned*/ int tx_max)
throws DbException;
// Note: only the seconds (not milliseconds) of the timestamp
// are used in this API.
public void set_tx_timestamp(Date timestamp)
throws DbException
{
_set_tx_timestamp(timestamp.getTime()/1000);
}
// (Internal)
private native void _set_tx_timestamp(long seconds)
throws DbException;
// Versioning information
public native static int get_version_major();
public native static int get_version_minor();
public native static int get_version_patch();
public native static String get_version_string();
// Convert DB error codes to strings
public native static String strerror(int errcode);
public native int lock_detect(int flags, int atype)
throws DbException;
public native DbLock lock_get(/*u_int32_t*/ int locker,
int flags,
Dbt obj,
/*db_lockmode_t*/ int lock_mode)
throws DbException;
public native void lock_put(DbLock lock)
throws DbException;
public native /*u_int32_t*/ int lock_id()
throws DbException;
public native void lock_id_free(/*u_int32_t*/ int id)
throws DbException;
public native DbLockStat lock_stat(/*u_int32_t*/ int flags)
throws DbException;
public native void lock_vec(/*u_int32_t*/ int locker,
int flags,
DbLockRequest[] list,
int offset,
int count)
throws DbException;
public native String[] log_archive(int flags)
throws DbException;
public native static int log_compare(DbLsn lsn0, DbLsn lsn1);
public native DbLogc log_cursor(int flags)
throws DbException;
public native String log_file(DbLsn lsn)
throws DbException;
public native void log_flush(DbLsn lsn)
throws DbException;
public native void log_put(DbLsn lsn, Dbt data, int flags)
throws DbException;
public native DbLogStat log_stat(/*u_int32_t*/ int flags)
throws DbException;
public native DbMpoolStat memp_stat(/*u_int32_t*/ int flags)
throws DbException;
public native DbMpoolFStat[] memp_fstat(/*u_int32_t*/ int flags)
throws DbException;
public native int memp_trickle(int pct)
throws DbException;
public native int rep_elect(int nsites, int pri, int timeout)
throws DbException;
public static class RepProcessMessage {
public int envid;
}
public native int rep_process_message(Dbt control, Dbt rec,
RepProcessMessage result)
throws DbException;
public native void rep_start(Dbt cookie, int flags)
throws DbException;
public native DbRepStat rep_stat(/*u_int32_t*/ int flags)
throws DbException;
public native DbTxn txn_begin(DbTxn pid, int flags)
throws DbException;
public native void txn_checkpoint(int kbyte, int min, int flags)
throws DbException;
public native DbPreplist[] txn_recover(int count, int flags)
throws DbException;
public native DbTxnStat txn_stat(/*u_int32_t*/ int flags)
throws DbException;
////////////////////////////////////////////////////////////////
//
// private data
//
private long private_dbobj_ = 0;
private long private_info_ = 0;
private int constructor_flags_ = 0;
private Vector dblist_ = new Vector(); // Db's that are open
private DbEnvFeedback feedback_ = null;
private DbRepTransport rep_transport_ = null;
private DbAppDispatch app_dispatch_ = null;
private DbOutputStreamErrcall errstream_ =
new DbOutputStreamErrcall(System.err);
/*package*/ DbErrcall errcall_ = errstream_;
/*package*/ String errpfx_;
static {
Db.load_db();
}
}
// end of DbEnv.java

View File

@ -1,19 +0,0 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 1999-2002
* Sleepycat Software. All rights reserved.
*
* $Id: DbEnvFeedback.java,v 11.6 2002/01/11 15:52:34 bostic Exp $
*/
package com.sleepycat.db;
public interface DbEnvFeedback
{
// methods
//
public abstract void feedback(DbEnv env, int opcode, int pct);
}
// end of DbFeedback.java

View File

@ -1,23 +0,0 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 1997-2002
* Sleepycat Software. All rights reserved.
*
* $Id: DbErrcall.java,v 11.6 2002/01/11 15:52:35 bostic Exp $
*/
package com.sleepycat.db;
/**
*
* @author Donald D. Anderson
*/
public interface DbErrcall
{
// methods
//
public abstract void errcall(String prefix, String buffer);
}
// end of DbErrcall.java

View File

@ -1,56 +0,0 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 1997-2002
* Sleepycat Software. All rights reserved.
*
* $Id: DbException.java,v 11.7 2002/01/11 15:52:35 bostic Exp $
*/
package com.sleepycat.db;
/**
*
* @author Donald D. Anderson
*/
public class DbException extends Exception
{
// methods
//
public DbException(String s)
{
super(s);
}
public DbException(String s, int errno)
{
super(s);
this.errno_ = errno;
}
public String toString()
{
String s = super.toString();
if (errno_ == 0)
return s;
else
return s + ": " + DbEnv.strerror(errno_);
}
// get/set methods
//
public int get_errno()
{
return errno_;
}
// private data
//
private int errno_ = 0;
}
// end of DbException.java

View File

@ -1,23 +0,0 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 1997-2002
* Sleepycat Software. All rights reserved.
*
* $Id: DbFeedback.java,v 11.7 2002/01/11 15:52:35 bostic Exp $
*/
package com.sleepycat.db;
/**
*
* @author Donald D. Anderson
*/
public interface DbFeedback
{
// methods
//
public abstract void feedback(Db db, int opcode, int pct);
}
// end of DbFeedback.java

View File

@ -1,21 +0,0 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 2000-2002
* Sleepycat Software. All rights reserved.
*
* $Id: DbHash.java,v 11.5 2002/01/11 15:52:36 bostic Exp $
*/
package com.sleepycat.db;
/*
* This interface is used by DbEnv.set_bt_compare()
*
*/
public interface DbHash
{
public abstract int hash(Db db, byte[] data, int len);
}
// end of DbHash.java

View File

@ -1,23 +0,0 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 1997-2002
* Sleepycat Software. All rights reserved.
*
* $Id: DbKeyRange.java,v 1.4 2002/01/11 15:52:36 bostic Exp $
*/
package com.sleepycat.db;
/**
*
* @author Donald D. Anderson
*/
public class DbKeyRange
{
public double less;
public double equal;
public double greater;
}
// end of DbKeyRange.java

View File

@ -1,33 +0,0 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 1997-2002
* Sleepycat Software. All rights reserved.
*
* $Id: DbLock.java,v 11.8 2002/01/11 15:52:36 bostic Exp $
*/
package com.sleepycat.db;
/**
*
* @author Donald D. Anderson
*/
public class DbLock
{
protected native void finalize()
throws Throwable;
// get/set methods
//
// private data
//
private long private_dbobj_ = 0;
static {
Db.load_db();
}
}
// end of DbLock.java

View File

@ -1,57 +0,0 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 1997-2002
* Sleepycat Software. All rights reserved.
*
* $Id: DbLockNotGrantedException.java,v 11.3 2002/01/11 15:52:36 bostic Exp $
*/
package com.sleepycat.db;
public class DbLockNotGrantedException extends DbException {
public DbLockNotGrantedException(String message,
int op, int mode, Dbt obj,
DbLock lock, int index)
{
super(message, Db.DB_LOCK_NOTGRANTED);
this.op = op;
this.mode = mode;
this.obj = obj;
this.lock = lock;
this.index = index;
}
public int get_op()
{
return op;
}
public int get_mode()
{
return mode;
}
public Dbt get_obj()
{
return obj;
}
public DbLock get_lock()
{
return lock;
}
public int get_index()
{
return index;
}
private int op;
private int mode;
private Dbt obj;
private DbLock lock;
private int index;
}

View File

@ -1,67 +0,0 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 1997-2002
* Sleepycat Software. All rights reserved.
*
* $Id: DbLockRequest.java,v 11.4 2002/01/16 07:45:24 mjc Exp $
*/
package com.sleepycat.db;
public class DbLockRequest
{
public DbLockRequest(int op, int mode, Dbt obj, DbLock lock)
{
this.op = op;
this.mode = mode;
this.obj = obj;
this.lock = lock;
}
public int get_op()
{
return op;
}
public void set_op(int op)
{
this.op = op;
}
public int get_mode()
{
return mode;
}
public void set_mode(int mode)
{
this.mode = mode;
}
public Dbt get_obj()
{
return obj;
}
public void set_obj(Dbt obj)
{
this.obj = obj;
}
public DbLock get_lock()
{
return lock;
}
public void set_lock(DbLock lock)
{
this.lock = lock;
}
private /* db_lockop_t */ int op;
private /* db_lockmode_t */ int mode;
private /* db_timeout_t */ int timeout;
private Dbt obj;
private DbLock lock;
}

View File

@ -1,39 +0,0 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 1997-2002
* Sleepycat Software. All rights reserved.
*
* $Id: DbLogc.java,v 11.3 2002/01/11 15:52:37 bostic Exp $
*/
package com.sleepycat.db;
/**
*
* @author Donald D. Anderson
*/
public class DbLogc
{
// methods
//
public native void close(int flags)
throws DbException;
// returns: 0, DB_NOTFOUND, or throws error
public native int get(DbLsn lsn, Dbt data, int flags)
throws DbException;
protected native void finalize()
throws Throwable;
// private data
//
private long private_dbobj_ = 0;
static {
Db.load_db();
}
}
// end of DbLogc.java

View File

@ -1,42 +0,0 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 1997-2002
* Sleepycat Software. All rights reserved.
*
* $Id: DbLsn.java,v 11.8 2002/01/11 15:52:37 bostic Exp $
*/
package com.sleepycat.db;
/**
*
* @author Donald D. Anderson
*/
public class DbLsn
{
// methods
//
public DbLsn()
{
init_lsn();
}
protected native void finalize()
throws Throwable;
private native void init_lsn();
// get/set methods
//
// private data
//
private long private_dbobj_ = 0;
static {
Db.load_db();
}
}
// end of DbLsn.java

View File

@ -1,49 +0,0 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 1999-2002
* Sleepycat Software. All rights reserved.
*
* $Id: DbMemoryException.java,v 11.7 2002/01/11 15:52:37 bostic Exp $
*/
package com.sleepycat.db;
public class DbMemoryException extends DbException
{
// methods
//
public DbMemoryException(String s)
{
super(s);
}
public DbMemoryException(String s, int errno)
{
super(s, errno);
}
public void set_dbt(Dbt dbt)
{
this.dbt = dbt;
}
public Dbt get_dbt()
{
return dbt;
}
/* Override of DbException.toString():
* the extra verbage that comes from DbEnv.strerror(ENOMEM)
* is not helpful.
*/
public String toString()
{
return getMessage();
}
Dbt dbt = null;
}
// end of DbMemoryException.java

View File

@ -1,38 +0,0 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 1997-2002
* Sleepycat Software. All rights reserved.
*
* $Id: DbMpoolStat.java,v 11.7 2002/01/11 15:52:38 bostic Exp $
*/
package com.sleepycat.db;
/*
* This is filled in and returned by the
* DbMpool.stat() method.
*/
public class DbMpoolStat
{
public int st_cache_hit; // Pages found in the cache.
public int st_cache_miss; // Pages not found in the cache.
public int st_map; // Pages from mapped files.
public int st_page_create; // Pages created in the cache.
public int st_page_in; // Pages read in.
public int st_page_out; // Pages written out.
public int st_ro_evict; // Clean pages forced from the cache.
public int st_rw_evict; // Dirty pages forced from the cache.
public int st_hash_buckets; // Number of hash buckets.
public int st_hash_searches; // Total hash chain searches.
public int st_hash_longest; // Longest hash chain searched.
public int st_hash_examined; // Total hash entries searched.
public int st_page_clean; // Clean pages.
public int st_page_dirty; // Dirty pages.
public int st_page_trickle; // Pages written by memp_trickle.
public int st_region_wait; // Region lock granted after wait.
public int st_region_nowait; // Region lock granted without wait.
public int st_regsize; // Region size.
}
// end of DbMpoolStat.java

View File

@ -1,46 +0,0 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 2001-2002
* Sleepycat Software. All rights reserved.
*
* $Id: DbMultipleDataIterator.java,v 1.5 2002/01/11 15:52:38 bostic Exp $
*/
package com.sleepycat.db;
/**
*
* @author David M. Krinsky
*/
public class DbMultipleDataIterator extends DbMultipleIterator
{
// public methods
public DbMultipleDataIterator(Dbt data)
{
super(data);
}
public boolean next(Dbt data)
{
int dataoff = DbUtil.array2int(buf, pos);
// crack out the data offset and length.
if (dataoff < 0) {
return (false);
}
pos -= int32sz;
int datasz = DbUtil.array2int(buf, pos);
pos -= int32sz;
data.set_data(buf);
data.set_size(datasz);
data.set_offset(dataoff);
return (true);
}
}
// end of DbMultipleDataIterator.java

View File

@ -1,51 +0,0 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 2001-2002
* Sleepycat Software. All rights reserved.
*
* $Id: DbMultipleIterator.java,v 1.5 2002/01/11 15:52:38 bostic Exp $
*/
package com.sleepycat.db;
/**
*
* @author David M. Krinsky
*/
// DbMultipleIterator is a shared package-private base class for the three
// types of bulk-return Iterator; it should never be instantiated directly,
// but it handles the functionality shared by its subclasses.
class DbMultipleIterator
{
// Package-private methods and members: used by our subclasses.
// Called implicitly by the subclass
DbMultipleIterator(Dbt data)
{
buf = data.get_data();
size = data.get_ulen();
// The offset will always be zero from the front of the buffer
// DB returns, and the buffer is opaque, so don't bother
// handling an offset.
// The initial position is pointing at the last u_int32_t
// in the buffer.
pos = size - int32sz;
}
// The C macros use sizeof(u_int32_t). Fortunately, java ints
// are always four bytes. Make this a constant just for form's sake.
static final int int32sz = 4;
// Current position within the buffer; equivalent to "pointer"
// in the DB_MULTIPLE macros.
int pos;
// A reference to the encoded buffer returned from the original
// Db/Dbc.get call on the data Dbt, and its size.
byte[] buf;
int size;
}
// end of DbMultipleIterator.java

View File

@ -1,56 +0,0 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 2001-2002
* Sleepycat Software. All rights reserved.
*
* $Id: DbMultipleKeyDataIterator.java,v 1.5 2002/01/11 15:52:39 bostic Exp $
*/
package com.sleepycat.db;
/**
*
* @author David M. Krinsky
*/
public class DbMultipleKeyDataIterator extends DbMultipleIterator
{
// public methods
public DbMultipleKeyDataIterator(Dbt data)
{
super(data);
}
public boolean next(Dbt key, Dbt data)
{
int keyoff = DbUtil.array2int(buf, pos);
// crack out the key and data offsets and lengths.
if (keyoff < 0) {
return (false);
}
pos -= int32sz;
int keysz = DbUtil.array2int(buf, pos);
pos -= int32sz;
int dataoff = DbUtil.array2int(buf, pos);
pos -= int32sz;
int datasz = DbUtil.array2int(buf, pos);
pos -= int32sz;
key.set_data(buf);
key.set_size(keysz);
key.set_offset(keyoff);
data.set_data(buf);
data.set_size(datasz);
data.set_offset(dataoff);
return (true);
}
}
// end of DbMultipleKeyDataIterator.java

View File

@ -1,51 +0,0 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 2001-2002
* Sleepycat Software. All rights reserved.
*
* $Id: DbMultipleRecnoDataIterator.java,v 1.5 2002/01/11 15:52:39 bostic Exp $
*/
package com.sleepycat.db;
/**
*
* @author David M. Krinsky
*/
public class DbMultipleRecnoDataIterator extends DbMultipleIterator
{
// public methods
public DbMultipleRecnoDataIterator(Dbt data)
{
super(data);
}
public boolean next(Dbt key, Dbt data)
{
int keyoff = DbUtil.array2int(buf, pos);
// crack out the key offset and the data offset and length.
if (keyoff < 0) {
return (false);
}
pos -= int32sz;
int dataoff = DbUtil.array2int(buf, pos);
pos -= int32sz;
int datasz = DbUtil.array2int(buf, pos);
pos -= int32sz;
key.set_recno_key_from_buffer(buf, keyoff);
data.set_data(buf);
data.set_size(datasz);
data.set_offset(dataoff);
return (true);
}
}
// end of DbMultipleRecnoDataIterator.java

View File

@ -1,58 +0,0 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 1997-2002
* Sleepycat Software. All rights reserved.
*
* $Id: DbOutputStreamErrcall.java,v 11.6 2002/01/11 15:52:39 bostic Exp $
*/
package com.sleepycat.db;
import java.io.OutputStream;
import java.io.IOException;
/**
*
* @author Donald D. Anderson
*
* This class is not public, as it is only used internally
* by Db to implement a default error handler.
*/
/*package*/ class DbOutputStreamErrcall implements DbErrcall
{
DbOutputStreamErrcall(OutputStream stream)
{
this.stream_ = stream;
}
// errcall implements DbErrcall
//
public void errcall(String prefix, String buffer)
{
try {
if (prefix != null) {
stream_.write(prefix.getBytes());
stream_.write((new String(": ")).getBytes());
}
stream_.write(buffer.getBytes());
stream_.write((new String("\n")).getBytes());
}
catch (IOException e) {
// well, we tried.
// Do our best to report the problem by other means.
//
System.err.println("DbOutputStreamErrcall Exception: " + e);
if (prefix != null)
System.err.print(prefix + ": ");
System.err.println(buffer + "\n");
}
}
// private data
//
private OutputStream stream_;
}
// end of DbOutputStreamErrcall.java

View File

@ -1,22 +0,0 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 1999-2002
* Sleepycat Software. All rights reserved.
*
* $Id: DbPreplist.java,v 11.3 2002/01/11 15:52:40 bostic Exp $
*/
package com.sleepycat.db;
/*
* This is filled in and returned by the
* DbEnv.txn_recover() method.
*/
public class DbPreplist
{
public DbTxn txn;
public byte gid[];
}
// end of DbPreplist.java

View File

@ -1,19 +0,0 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 2001-2002
* Sleepycat Software. All rights reserved.
*
* $Id: DbRepTransport.java,v 11.2 2002/01/11 15:52:40 bostic Exp $
*/
package com.sleepycat.db;
/*
* This is used as a callback by DbEnv.set_rep_transport.
*/
public interface DbRepTransport
{
public int send(DbEnv env, Dbt control, Dbt rec, int flags, int envid)
throws DbException;
}

View File

@ -1,32 +0,0 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 1997-2002
* Sleepycat Software. All rights reserved.
*
* $Id: DbRunRecoveryException.java,v 11.6 2002/01/11 15:52:40 bostic Exp $
*/
package com.sleepycat.db;
/**
*
* @author Donald D. Anderson
*/
public class DbRunRecoveryException extends DbException
{
// methods
//
public DbRunRecoveryException(String s)
{
super(s);
}
public DbRunRecoveryException(String s, int errno)
{
super(s, errno);
}
}
// end of DbRunRecoveryException.java

View File

@ -1,22 +0,0 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 1999-2002
* Sleepycat Software. All rights reserved.
*
* $Id: DbSecondaryKeyCreate.java,v 11.3 2002/01/11 15:52:40 bostic Exp $
*/
package com.sleepycat.db;
/*
* This is used as a callback by Db.associate.
*/
public interface DbSecondaryKeyCreate
{
public int secondary_key_create(Db secondary, Dbt key,
Dbt data, Dbt result)
throws DbException;
}
// end of DbSecondaryKeyCreate.java

View File

@ -1,77 +0,0 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 1997-2002
* Sleepycat Software. All rights reserved.
*
* $Id: DbTxn.java,v 11.17 2002/08/29 14:22:22 margo Exp $
*/
package com.sleepycat.db;
/**
*
* @author Donald D. Anderson
*/
public class DbTxn
{
// methods
//
public native void abort()
throws DbException;
public native void commit(int flags)
throws DbException;
public native void discard(int flags)
throws DbException;
public native /*u_int32_t*/ int id()
throws DbException;
public native void prepare(byte[] gid)
throws DbException;
public native void set_timeout(/*db_timeout_t*/ long timeout,
/*u_int32_t*/ int flags)
throws DbException;
// We override Object.equals because it is possible for
// the Java API to create multiple DbTxns that reference
// the same underlying object. This can happen for example
// during DbEnv.txn_recover().
//
public boolean equals(Object obj)
{
if (this == obj)
return true;
if (obj != null && (obj instanceof DbTxn)) {
DbTxn that = (DbTxn)obj;
return (this.private_dbobj_ == that.private_dbobj_);
}
return false;
}
// We must override Object.hashCode whenever we override
// Object.equals() to enforce the maxim that equal objects
// have the same hashcode.
//
public int hashCode()
{
return ((int)private_dbobj_ ^ (int)(private_dbobj_ >> 32));
}
// get/set methods
//
// private data
//
private long private_dbobj_ = 0;
static {
Db.load_db();
}
}
// end of DbTxn.java

View File

@ -1,98 +0,0 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 2001-2002
* Sleepycat Software. All rights reserved.
*
* $Id: DbUtil.java,v 11.5 2002/01/11 15:52:41 bostic Exp $
*/
package com.sleepycat.db;
/**
*
* @author David M. Krinsky
*/
// DbUtil is a simple, package-private wrapper class that holds a few
// static utility functions other parts of the package share and that don't
// have a good home elsewhere. (For now, that's limited to byte-array-to-int
// conversion and back.)
class DbUtil
{
// Get the u_int32_t stored beginning at offset "offset" into
// array "arr". We have to do the conversion manually since it's
// a C-native int, and we're not really supposed to make this kind of
// cast in Java.
static int array2int(byte[] arr, int offset)
{
int b1, b2, b3, b4;
int pos = offset;
// Get the component bytes; b4 is most significant, b1 least.
if (big_endian) {
b4 = arr[pos++];
b3 = arr[pos++];
b2 = arr[pos++];
b1 = arr[pos];
} else {
b1 = arr[pos++];
b2 = arr[pos++];
b3 = arr[pos++];
b4 = arr[pos];
}
// Bytes are signed. Convert [-128, -1] to [128, 255].
if (b1 < 0) { b1 += 256; }
if (b2 < 0) { b2 += 256; }
if (b3 < 0) { b3 += 256; }
if (b4 < 0) { b4 += 256; }
// Put the bytes in their proper places in an int.
b2 <<= 8;
b3 <<= 16;
b4 <<= 24;
// Return their sum.
return (b1 + b2 + b3 + b4);
}
// Store the specified u_int32_t, with endianness appropriate
// to the platform we're running on, into four consecutive bytes of
// the specified byte array, starting from the specified offset.
static void int2array(int n, byte[] arr, int offset)
{
int b1, b2, b3, b4;
int pos = offset;
b1 = n & 0xff;
b2 = (n >> 8) & 0xff;
b3 = (n >> 16) & 0xff;
b4 = (n >> 24) & 0xff;
// Bytes are signed. Convert [128, 255] to [-128, -1].
if (b1 >= 128) { b1 -= 256; }
if (b2 >= 128) { b2 -= 256; }
if (b3 >= 128) { b3 -= 256; }
if (b4 >= 128) { b4 -= 256; }
// Put the bytes in the appropriate place in the array.
if (big_endian) {
arr[pos++] = (byte)b4;
arr[pos++] = (byte)b3;
arr[pos++] = (byte)b2;
arr[pos] = (byte)b1;
} else {
arr[pos++] = (byte)b1;
arr[pos++] = (byte)b2;
arr[pos++] = (byte)b3;
arr[pos] = (byte)b4;
}
}
private static final boolean big_endian = is_big_endian();
private static native boolean is_big_endian();
}
// end of DbUtil.java

View File

@ -1,60 +0,0 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 1997-2002
* Sleepycat Software. All rights reserved.
*
* $Id: Dbc.java,v 11.9 2002/01/11 15:52:41 bostic Exp $
*/
package com.sleepycat.db;
/**
*
* @author Donald D. Anderson
*/
public class Dbc
{
// methods
//
public native void close()
throws DbException;
public native int count(int flags)
throws DbException;
// returns: 0, DB_KEYEMPTY, or throws error
public native int del(int flags)
throws DbException;
public native Dbc dup(int flags)
throws DbException;
// returns: 0, DB_NOTFOUND, or throws error
public native int get(Dbt key, Dbt data, int flags)
throws DbException;
// returns: 0, DB_NOTFOUND, or throws error
public native int pget(Dbt key, Dbt pkey, Dbt data, int flags)
throws DbException;
// returns: 0, DB_KEYEXIST, or throws error
public native int put(Dbt key, Dbt data, int flags)
throws DbException;
protected native void finalize()
throws Throwable;
// get/set methods
//
// private data
//
private long private_dbobj_ = 0;
static {
Db.load_db();
}
}
// end of Dbc.java

View File

@ -1,230 +0,0 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 1997-2002
* Sleepycat Software. All rights reserved.
*
* $Id: Dbt.java,v 11.15 2002/09/04 00:37:25 mjc Exp $
*/
package com.sleepycat.db;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
/**
*
* @author Donald D. Anderson
*/
public class Dbt
{
// methods
//
public Dbt(byte[] data)
{
init();
this.data = data;
if (data != null) {
this.size = data.length;
}
}
public Dbt(byte[] data, int off, int len)
{
init();
this.data = data;
this.offset = off;
this.size = len;
}
public Dbt()
{
init();
}
public Dbt(Object serialobj) throws java.io.IOException
{
init();
this.set_object(serialobj);
}
protected native void finalize()
throws Throwable;
// get/set methods
//
// key/data
public byte[] get_data()
{
// In certain circumstances, like callbacks to
// user code that have Dbt args, we do not create
// data arrays until the user explicitly does a get_data.
// This saves us from needlessly creating objects
// (potentially large arrays) that may never be accessed.
//
if (must_create_data) {
data = create_data();
must_create_data = false;
}
return data;
}
public void set_data(byte[] data)
{
this.data = data;
this.must_create_data = false;
}
// get_offset/set_offset is unique to the Java portion
// of the DB APIs. They can be used to get/set the offset
// into the attached byte array.
//
public int get_offset()
{
return offset;
}
public void set_offset(int offset)
{
this.offset = offset;
}
// key/data length
public /*u_int32_t*/ int get_size()
{
return size;
}
public void set_size(/*u_int32_t*/ int size)
{
this.size = size;
}
// RO: length of user buffer.
public /*u_int32_t*/ int get_ulen()
{
return ulen;
}
public void set_ulen(/*u_int32_t*/ int ulen)
{
this.ulen = ulen;
}
// RO: get/put record length.
public /*u_int32_t*/ int get_dlen()
{
return dlen;
}
public void set_dlen(/*u_int32_t*/ int dlen)
{
this.dlen = dlen;
}
// RO: get/put record offset.
public /*u_int32_t*/ int get_doff()
{
return doff;
}
public void set_doff(/*u_int32_t*/ int doff)
{
this.doff = doff;
}
// flags
public /*u_int32_t*/ int get_flags()
{
return flags;
}
public void set_flags(/*u_int32_t*/ int flags)
{
this.flags = flags;
}
// Helper methods to get/set a Dbt from a serializable object.
public Object get_object() throws java.io.IOException,
java.lang.ClassNotFoundException
{
ByteArrayInputStream bytestream = new ByteArrayInputStream(get_data());
ObjectInputStream ois = new ObjectInputStream(bytestream);
Object serialobj = ois.readObject();
ois.close();
bytestream.close();
return (serialobj);
}
public void set_object(Object serialobj) throws java.io.IOException
{
ByteArrayOutputStream bytestream = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bytestream);
oos.writeObject(serialobj);
oos.close();
byte[] buf = bytestream.toByteArray();
bytestream.close();
set_data(buf);
set_offset(0);
set_size(buf.length);
}
// These are not in the original DB interface.
// They can be used to set the recno key for a Dbt.
// Note: if data is less than (offset + 4) bytes, these
// methods may throw an ArrayIndexException. get_recno_key_data()
// will additionally throw a NullPointerException if data is null.
public void set_recno_key_data(int recno)
{
if (data == null) {
data = new byte[4];
size = 4;
offset = 0;
}
DbUtil.int2array(recno, data, offset);
}
public int get_recno_key_data()
{
return (DbUtil.array2int(data, offset));
}
// Used internally by DbMultipleRecnoIterator
//
/*package*/ void set_recno_key_from_buffer(byte[] data, int offset)
{
this.data = data;
this.offset = offset;
this.size = 4;
}
static {
Db.load_db();
}
// private methods
//
private native void init();
private native byte[] create_data();
// private data
//
private long private_dbobj_ = 0;
private byte[] data = null;
private int offset = 0;
private int size = 0;
private int ulen = 0;
private int dlen = 0;
private int doff = 0;
private int flags = 0;
private boolean must_create_data = false;
}
// end of Dbt.java

View File

@ -1,190 +0,0 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 1997-2002
* Sleepycat Software. All rights reserved.
*
* $Id: DbXAResource.java,v 1.2 2002/08/09 01:54:57 bostic Exp $
*/
package com.sleepycat.db.xa;
import com.sleepycat.db.Db;
import com.sleepycat.db.DbEnv;
import com.sleepycat.db.DbTxn;
import javax.transaction.xa.XAResource;
import javax.transaction.xa.XAException;
import javax.transaction.xa.Xid;
public class DbXAResource implements XAResource
{
public DbXAResource(String home, int rmid, int flags)
throws XAException
{
this.home = home;
this.rmid = rmid;
// We force single-threading for calls to _init/_close.
// This makes our internal code much easier, and
// should not be a performance burden.
synchronized (DbXAResource.class) {
_init(home, rmid, flags);
}
}
//
// Alternate constructor for convenience.
// Uses an rmid that is unique within this JVM,
// numbered started at 0.
//
public DbXAResource(String home)
throws XAException
{
this(home, get_unique_rmid(), 0);
}
private native void _init(String home, int rmid, int flags);
public void close(int flags)
throws XAException
{
// We force single-threading for calls to _init/_close.
// This makes our internal code much easier, and
// should not be a performance burden.
synchronized (DbXAResource.class) {
_close(home, rmid, flags);
}
}
private native void _close(String home, int rmid, int flags);
public void commit(Xid xid, boolean onePhase)
throws XAException
{
_commit(xid, rmid, onePhase);
}
private native void _commit(Xid xid, int rmid, boolean onePhase);
public void end(Xid xid, int flags)
throws XAException
{
_end(xid, rmid, flags);
}
private native void _end(Xid xid, int rmid, int flags);
public void forget(Xid xid)
throws XAException
{
_forget(xid, rmid);
}
private native void _forget(Xid xid, int rmid);
public int getTransactionTimeout()
throws XAException
{
return transactionTimeout;
}
public boolean isSameRM(XAResource xares)
throws XAException
{
if (!(xares instanceof DbXAResource))
return false;
return (this.rmid == ((DbXAResource)xares).rmid);
}
public int prepare(Xid xid)
throws XAException
{
return _prepare(xid, rmid);
}
private native int _prepare(Xid xid, int rmid);
public Xid [] recover(int flag)
throws XAException
{
return _recover(rmid, flag);
}
private native Xid[] _recover(int rmid, int flags);
public void rollback(Xid xid)
throws XAException
{
_rollback(xid, rmid);
System.err.println("DbXAResource.rollback returned");
}
private native void _rollback(Xid xid, int rmid);
public boolean setTransactionTimeout(int seconds)
throws XAException
{
// XXX we are not using the transaction timeout.
transactionTimeout = seconds;
return true;
}
public void start(Xid xid, int flags)
throws XAException
{
_start(xid, rmid, flags);
}
private native void _start(Xid xid, int rmid, int flags);
private static synchronized int get_unique_rmid()
{
return unique_rmid++;
}
public interface DbAttach
{
public DbEnv get_env();
public DbTxn get_txn();
}
protected static class DbAttachImpl implements DbAttach
{
private DbEnv env;
private DbTxn txn;
DbAttachImpl(DbEnv env, DbTxn txn)
{
this.env = env;
this.txn = txn;
}
public DbTxn get_txn()
{
return txn;
}
public DbEnv get_env()
{
return env;
}
}
public static native DbAttach xa_attach(Xid xid, Integer rmid);
////////////////////////////////////////////////////////////////
//
// private data
//
private long private_dbobj_ = 0;
private int transactionTimeout = 0;
private String home;
private int rmid;
private static int unique_rmid = 0;
static
{
Db.load_db();
}
}

View File

@ -1,49 +0,0 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 1997-2002
* Sleepycat Software. All rights reserved.
*
* $Id: DbXid.java,v 1.2 2002/08/09 01:54:58 bostic Exp $
*/
package com.sleepycat.db.xa;
import com.sleepycat.db.DbException;
import com.sleepycat.db.DbTxn;
import javax.transaction.xa.XAException;
import javax.transaction.xa.Xid;
public class DbXid implements Xid
{
public DbXid(int formatId, byte[] gtrid, byte[] bqual)
throws XAException
{
this.formatId = formatId;
this.gtrid = gtrid;
this.bqual = bqual;
}
public int getFormatId()
{
return formatId;
}
public byte[] getGlobalTransactionId()
{
return gtrid;
}
public byte[] getBranchQualifier()
{
return bqual;
}
////////////////////////////////////////////////////////////////
//
// private data
//
private byte[] gtrid;
private byte[] bqual;
private int formatId;
}

View File

@ -1,181 +0,0 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 1997-2002
* Sleepycat Software. All rights reserved.
*
* $Id: AccessExample.java,v 11.12 2002/02/05 22:27:13 mjc Exp $
*/
package com.sleepycat.examples;
import com.sleepycat.db.*;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.InputStreamReader;
import java.io.IOException;
import java.io.PrintStream;
class AccessExample
{
private static final String FileName = "access.db";
public AccessExample()
{
}
public static void main(String argv[])
{
try
{
AccessExample app = new AccessExample();
app.run();
}
catch (DbException dbe)
{
System.err.println("AccessExample: " + dbe.toString());
System.exit(1);
}
catch (FileNotFoundException fnfe)
{
System.err.println("AccessExample: " + fnfe.toString());
System.exit(1);
}
System.exit(0);
}
// Prompts for a line, and keeps prompting until a non blank
// line is returned. Returns null on error.
//
static public String askForLine(InputStreamReader reader,
PrintStream out, String prompt)
{
String result = "";
while (result != null && result.length() == 0) {
out.print(prompt);
out.flush();
result = getLine(reader);
}
return result;
}
// Not terribly efficient, but does the job.
// Works for reading a line from stdin or a file.
// Returns null on EOF. If EOF appears in the middle
// of a line, returns that line, then null on next call.
//
static public String getLine(InputStreamReader reader)
{
StringBuffer b = new StringBuffer();
int c;
try {
while ((c = reader.read()) != -1 && c != '\n') {
if (c != '\r')
b.append((char)c);
}
}
catch (IOException ioe) {
c = -1;
}
if (c == -1 && b.length() == 0)
return null;
else
return b.toString();
}
public void run()
throws DbException, FileNotFoundException
{
// Remove the previous database.
new File(FileName).delete();
// Create the database object.
// There is no environment for this simple example.
Db table = new Db(null, 0);
table.set_error_stream(System.err);
table.set_errpfx("AccessExample");
table.open(null, FileName, null, Db.DB_BTREE, Db.DB_CREATE, 0644);
//
// Insert records into the database, where the key is the user
// input and the data is the user input in reverse order.
//
InputStreamReader reader = new InputStreamReader(System.in);
for (;;) {
String line = askForLine(reader, System.out, "input> ");
if (line == null)
break;
String reversed = (new StringBuffer(line)).reverse().toString();
// See definition of StringDbt below
//
StringDbt key = new StringDbt(line);
StringDbt data = new StringDbt(reversed);
try
{
int err;
if ((err = table.put(null,
key, data, Db.DB_NOOVERWRITE)) == Db.DB_KEYEXIST) {
System.out.println("Key " + line + " already exists.");
}
}
catch (DbException dbe)
{
System.out.println(dbe.toString());
}
System.out.println("");
}
// Acquire an iterator for the table.
Dbc iterator;
iterator = table.cursor(null, 0);
// Walk through the table, printing the key/data pairs.
// See class StringDbt defined below.
//
StringDbt key = new StringDbt();
StringDbt data = new StringDbt();
while (iterator.get(key, data, Db.DB_NEXT) == 0)
{
System.out.println(key.getString() + " : " + data.getString());
}
iterator.close();
table.close(0);
}
// Here's an example of how you can extend a Dbt in a straightforward
// way to allow easy storage/retrieval of strings, or whatever
// kind of data you wish. We've declared it as a static inner
// class, but it need not be.
//
static /*inner*/
class StringDbt extends Dbt
{
StringDbt()
{
set_flags(Db.DB_DBT_MALLOC); // tell Db to allocate on retrieval
}
StringDbt(String value)
{
setString(value);
set_flags(Db.DB_DBT_MALLOC); // tell Db to allocate on retrieval
}
void setString(String value)
{
byte[] data = value.getBytes();
set_data(data);
set_size(data.length);
}
String getString()
{
return new String(get_data(), 0, get_size());
}
}
}

View File

@ -1,340 +0,0 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 1997-2002
* Sleepycat Software. All rights reserved.
*
* $Id: BtRecExample.java,v 11.11 2002/02/05 22:27:13 mjc Exp $
*/
package com.sleepycat.examples;
import com.sleepycat.db.*;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.InputStreamReader;
import java.io.IOException;
import java.io.PrintStream;
public class BtRecExample
{
static final String progname = "BtRecExample"; // Program name.
static final String database = "access.db";
static final String wordlist = "../test/wordlist";
BtRecExample(BufferedReader reader)
throws DbException, IOException, FileNotFoundException
{
int ret;
// Remove the previous database.
File f = new File(database);
f.delete();
dbp = new Db(null, 0);
dbp.set_error_stream(System.err);
dbp.set_errpfx(progname);
dbp.set_pagesize(1024); // 1K page sizes.
dbp.set_flags(Db.DB_RECNUM); // Record numbers.
dbp.open(null, database, null, Db.DB_BTREE, Db.DB_CREATE, 0664);
//
// Insert records into the database, where the key is the word
// preceded by its record number, and the data is the same, but
// in reverse order.
//
for (int cnt = 1; cnt <= 1000; ++cnt) {
String numstr = String.valueOf(cnt);
while (numstr.length() < 4)
numstr = "0" + numstr;
String buf = numstr + '_' + reader.readLine();
StringBuffer rbuf = new StringBuffer(buf).reverse();
StringDbt key = new StringDbt(buf);
StringDbt data = new StringDbt(rbuf.toString());
if ((ret = dbp.put(null, key, data, Db.DB_NOOVERWRITE)) != 0) {
if (ret != Db.DB_KEYEXIST)
throw new DbException("Db.put failed" + ret);
}
}
}
void run()
throws DbException
{
int recno;
int ret;
// Acquire a cursor for the database.
dbcp = dbp.cursor(null, 0);
//
// Prompt the user for a record number, then retrieve and display
// that record.
//
InputStreamReader reader = new InputStreamReader(System.in);
for (;;) {
// Get a record number.
String line = askForLine(reader, System.out, "recno #> ");
if (line == null)
break;
try {
recno = Integer.parseInt(line);
}
catch (NumberFormatException nfe) {
System.err.println("Bad record number: " + nfe);
continue;
}
//
// Start with a fresh key each time, the dbp.get() routine returns
// the key and data pair, not just the key!
//
RecnoStringDbt key = new RecnoStringDbt(recno, 100);
RecnoStringDbt data = new RecnoStringDbt(100);
if ((ret = dbcp.get(key, data, Db.DB_SET_RECNO)) != 0) {
throw new DbException("Dbc.get failed", ret);
}
// Display the key and data.
show("k/d\t", key, data);
// Move the cursor a record forward.
if ((ret = dbcp.get(key, data, Db.DB_NEXT)) != 0) {
throw new DbException("Dbc.get failed", ret);
}
// Display the key and data.
show("next\t", key, data);
RecnoStringDbt datano = new RecnoStringDbt(100);
//
// Retrieve the record number for the following record into
// local memory.
//
if ((ret = dbcp.get(key, datano, Db.DB_GET_RECNO)) != 0) {
if (ret != Db.DB_NOTFOUND && ret != Db.DB_KEYEMPTY) {
throw new DbException("Dbc.get failed", ret);
}
}
else {
recno = datano.getRecno();
System.out.println("retrieved recno: " + recno);
}
}
dbcp.close();
dbcp = null;
}
//
// Print out the number of records in the database.
//
void stats()
throws DbException
{
DbBtreeStat statp;
statp = (DbBtreeStat)dbp.stat(0);
System.out.println(progname + ": database contains " +
statp.bt_ndata + " records");
}
void show(String msg, RecnoStringDbt key, RecnoStringDbt data)
throws DbException
{
System.out.println(msg + key.getString() + ": " + data.getString());
}
public void shutdown()
throws DbException
{
if (dbcp != null) {
dbcp.close();
dbcp = null;
}
if (dbp != null) {
dbp.close(0);
dbp = null;
}
}
public static void main(String argv[])
{
try {
// Open the word database.
FileReader freader = new FileReader(wordlist);
BtRecExample app = new BtRecExample(new BufferedReader(freader));
// Close the word database.
freader.close();
freader = null;
app.stats();
app.run();
} catch (FileNotFoundException fnfe) {
System.err.println(progname + ": unexpected open error " + fnfe);
System.exit (1);
} catch (IOException ioe) {
System.err.println(progname + ": open " + wordlist + ": " + ioe);
System.exit (1);
} catch (DbException dbe) {
System.err.println("Exception: " + dbe);
System.exit(dbe.get_errno());
}
System.exit(0);
}
// Prompts for a line, and keeps prompting until a non blank
// line is returned. Returns null on error.
//
static public String askForLine(InputStreamReader reader,
PrintStream out, String prompt)
{
String result = "";
while (result != null && result.length() == 0) {
out.print(prompt);
out.flush();
result = getLine(reader);
}
return result;
}
// Not terribly efficient, but does the job.
// Works for reading a line from stdin or a file.
// Returns null on EOF. If EOF appears in the middle
// of a line, returns that line, then null on next call.
//
static public String getLine(InputStreamReader reader)
{
StringBuffer b = new StringBuffer();
int c;
try {
while ((c = reader.read()) != -1 && c != '\n') {
if (c != '\r')
b.append((char)c);
}
}
catch (IOException ioe) {
c = -1;
}
if (c == -1 && b.length() == 0)
return null;
else
return b.toString();
}
private Dbc dbcp;
private Db dbp;
// Here's an example of how you can extend a Dbt in a straightforward
// way to allow easy storage/retrieval of strings.
// We've declared it as a static inner class, but it need not be.
//
static /*inner*/
class StringDbt extends Dbt
{
StringDbt(byte[] arr)
{
set_flags(Db.DB_DBT_USERMEM);
set_data(arr);
set_size(arr.length);
}
StringDbt()
{
set_flags(Db.DB_DBT_MALLOC); // tell Db to allocate on retrieval
}
StringDbt(String value)
{
setString(value);
set_flags(Db.DB_DBT_MALLOC); // tell Db to allocate on retrieval
}
void setString(String value)
{
byte[] data = value.getBytes();
set_data(data);
set_size(data.length);
// must set ulen because sometimes a string is returned
set_ulen(data.length);
}
String getString()
{
return new String(get_data(), 0, get_size());
}
}
// Here's an example of how you can extend a Dbt to store
// (potentially) both recno's and strings in the same
// structure.
//
static /*inner*/
class RecnoStringDbt extends Dbt
{
RecnoStringDbt(int maxsize)
{
this(0, maxsize); // let other constructor do most of the work
}
RecnoStringDbt(int value, int maxsize)
{
set_flags(Db.DB_DBT_USERMEM); // do not allocate on retrieval
arr = new byte[maxsize];
set_data(arr); // use our local array for data
set_ulen(maxsize); // size of return storage
setRecno(value);
}
RecnoStringDbt(String value, int maxsize)
{
set_flags(Db.DB_DBT_USERMEM); // do not allocate on retrieval
arr = new byte[maxsize];
set_data(arr); // use our local array for data
set_ulen(maxsize); // size of return storage
setString(value);
}
void setRecno(int value)
{
set_recno_key_data(value);
set_size(arr.length);
}
void setString(String value)
{
byte[] data = value.getBytes();
set_data(data);
set_size(data.length);
}
int getRecno()
{
return get_recno_key_data();
}
String getString()
{
return new String(get_data(), 0, get_size());
}
byte arr[];
}
}

View File

@ -1,198 +0,0 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 1997-2002
* Sleepycat Software. All rights reserved.
*
* $Id: BulkAccessExample.java,v 1.6 2002/02/05 22:27:13 mjc Exp $
*/
package com.sleepycat.examples;
import com.sleepycat.db.*;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.InputStreamReader;
import java.io.IOException;
import java.io.PrintStream;
class BulkAccessExample
{
private static final String FileName = "access.db";
public BulkAccessExample()
{
}
public static void main(String argv[])
{
try
{
BulkAccessExample app = new BulkAccessExample();
app.run();
}
catch (DbException dbe)
{
System.err.println("BulkAccessExample: " + dbe.toString());
System.exit(1);
}
catch (FileNotFoundException fnfe)
{
System.err.println("BulkAccessExample: " + fnfe.toString());
System.exit(1);
}
System.exit(0);
}
// Prompts for a line, and keeps prompting until a non blank
// line is returned. Returns null on error.
//
static public String askForLine(InputStreamReader reader,
PrintStream out, String prompt)
{
String result = "";
while (result != null && result.length() == 0) {
out.print(prompt);
out.flush();
result = getLine(reader);
}
return result;
}
// Not terribly efficient, but does the job.
// Works for reading a line from stdin or a file.
// Returns null on EOF. If EOF appears in the middle
// of a line, returns that line, then null on next call.
//
static public String getLine(InputStreamReader reader)
{
StringBuffer b = new StringBuffer();
int c;
try {
while ((c = reader.read()) != -1 && c != '\n') {
if (c != '\r')
b.append((char)c);
}
}
catch (IOException ioe) {
c = -1;
}
if (c == -1 && b.length() == 0)
return null;
else
return b.toString();
}
public void run()
throws DbException, FileNotFoundException
{
// Remove the previous database.
new File(FileName).delete();
// Create the database object.
// There is no environment for this simple example.
Db table = new Db(null, 0);
table.set_error_stream(System.err);
table.set_errpfx("BulkAccessExample");
table.open(null, FileName, null, Db.DB_BTREE, Db.DB_CREATE, 0644);
//
// Insert records into the database, where the key is the user
// input and the data is the user input in reverse order.
//
InputStreamReader reader = new InputStreamReader(System.in);
for (;;) {
String line = askForLine(reader, System.out, "input> ");
if (line == null)
break;
String reversed = (new StringBuffer(line)).reverse().toString();
// See definition of StringDbt below
//
StringDbt key = new StringDbt(line);
StringDbt data = new StringDbt(reversed);
try
{
int err;
if ((err = table.put(null,
key, data, Db.DB_NOOVERWRITE)) == Db.DB_KEYEXIST) {
System.out.println("Key " + line + " already exists.");
}
}
catch (DbException dbe)
{
System.out.println(dbe.toString());
}
System.out.println("");
}
// Acquire a cursor for the table and two Dbts.
Dbc dbc = table.cursor(null, 0);
Dbt foo = new Dbt();
foo.set_flags(Db.DB_DBT_MALLOC);
Dbt bulk_data = new Dbt();
// Set Db.DB_DBT_USERMEM on the data Dbt; Db.DB_MULTIPLE_KEY requires
// it. Then allocate a byte array of a reasonable size; we'll
// go through the database in chunks this big.
bulk_data.set_flags(Db.DB_DBT_USERMEM);
bulk_data.set_data(new byte[1000000]);
bulk_data.set_ulen(1000000);
// Walk through the table, printing the key/data pairs.
//
while (dbc.get(foo, bulk_data, Db.DB_NEXT | Db.DB_MULTIPLE_KEY) == 0)
{
DbMultipleKeyDataIterator iterator;
iterator = new DbMultipleKeyDataIterator(bulk_data);
StringDbt key, data;
key = new StringDbt();
data = new StringDbt();
while (iterator.next(key, data)) {
System.out.println(key.getString() + " : " + data.getString());
}
}
dbc.close();
table.close(0);
}
// Here's an example of how you can extend a Dbt in a straightforward
// way to allow easy storage/retrieval of strings, or whatever
// kind of data you wish. We've declared it as a static inner
// class, but it need not be.
//
static /*inner*/
class StringDbt extends Dbt
{
StringDbt()
{
set_flags(Db.DB_DBT_MALLOC); // tell Db to allocate on retrieval
}
StringDbt(String value)
{
setString(value);
set_flags(Db.DB_DBT_MALLOC); // tell Db to allocate on retrieval
}
void setString(String value)
{
byte[] data = value.getBytes();
set_data(data);
set_size(data.length);
}
String getString()
{
return new String(get_data(), get_offset(), get_size());
}
}
}

View File

@ -1,128 +0,0 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 1997-2002
* Sleepycat Software. All rights reserved.
*
* $Id: EnvExample.java,v 11.9 2002/01/11 15:52:42 bostic Exp $
*/
package com.sleepycat.examples;
import com.sleepycat.db.*;
import java.io.FileNotFoundException;
import java.io.OutputStream;
/*
* An example of a program using DbEnv to configure its DB
* environment.
*
* For comparison purposes, this example uses a similar structure
* as examples/ex_env.c and examples_cxx/EnvExample.cpp.
*/
public class EnvExample
{
private static final String progname = "EnvExample";
private static final String DATABASE_HOME = "/tmp/database";
private static void db_application()
throws DbException
{
// Do something interesting...
// Your application goes here.
}
private static void db_setup(String home, String data_dir,
OutputStream errs)
throws DbException, FileNotFoundException
{
//
// Create an environment object and initialize it for error
// reporting.
//
DbEnv dbenv = new DbEnv(0);
dbenv.set_error_stream(errs);
dbenv.set_errpfx(progname);
//
// We want to specify the shared memory buffer pool cachesize,
// but everything else is the default.
//
dbenv.set_cachesize(0, 64 * 1024, 0);
// Databases are in a subdirectory.
dbenv.set_data_dir(data_dir);
// Open the environment with full transactional support.
//
// open() will throw a DbException if there is an error.
//
// open is declared to throw a FileNotFoundException, which normally
// shouldn't occur with the DB_CREATE option.
//
dbenv.open(DATABASE_HOME,
Db.DB_CREATE | Db.DB_INIT_LOCK | Db.DB_INIT_LOG |
Db.DB_INIT_MPOOL | Db.DB_INIT_TXN, 0);
try {
// Start your application.
db_application();
}
finally {
// Close the environment. Doing this in the
// finally block ensures it is done, even if
// an error is thrown.
//
dbenv.close(0);
}
}
private static void db_teardown(String home, String data_dir,
OutputStream errs)
throws DbException, FileNotFoundException
{
// Remove the shared database regions.
DbEnv dbenv = new DbEnv(0);
dbenv.set_error_stream(errs);
dbenv.set_errpfx(progname);
dbenv.set_data_dir(data_dir);
dbenv.remove(home, 0);
}
public static void main(String[] args)
{
//
// All of the shared database files live in /tmp/database,
// but data files live in /database.
//
// Using Berkeley DB in C/C++, we need to allocate two elements
// in the array and set config[1] to NULL. This is not
// necessary in Java.
//
String home = DATABASE_HOME;
String config = "/database/files";
try {
System.out.println("Setup env");
db_setup(home, config, System.err);
System.out.println("Teardown env");
db_teardown(home, config, System.err);
}
catch (DbException dbe) {
System.err.println(progname + ": environment open: " + dbe.toString());
System.exit (1);
}
catch (FileNotFoundException fnfe) {
System.err.println(progname +
": unexpected open environment error " + fnfe);
System.exit (1);
}
}
}

View File

@ -1,235 +0,0 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 1997-2002
* Sleepycat Software. All rights reserved.
*
* $Id: LockExample.java,v 11.8 2002/01/11 15:52:43 bostic Exp $
*/
package com.sleepycat.examples;
import com.sleepycat.db.*;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.IOException;
import java.io.PrintStream;
import java.util.Vector;
//
// An example of a program using DbLock and related classes.
//
class LockExample extends DbEnv
{
private static final String progname = "LockExample";
private static final String LOCK_HOME = "TESTDIR";
public LockExample(String home, int maxlocks, boolean do_unlink)
throws DbException, FileNotFoundException
{
super(0);
if (do_unlink) {
remove(home, Db.DB_FORCE);
}
else {
set_error_stream(System.err);
set_errpfx("LockExample");
if (maxlocks != 0)
set_lk_max_locks(maxlocks);
open(home, Db.DB_CREATE|Db.DB_INIT_LOCK, 0);
}
}
// Prompts for a line, and keeps prompting until a non blank
// line is returned. Returns null on error.
//
static public String askForLine(InputStreamReader reader,
PrintStream out, String prompt)
{
String result = "";
while (result != null && result.length() == 0) {
out.print(prompt);
out.flush();
result = getLine(reader);
}
return result;
}
// Not terribly efficient, but does the job.
// Works for reading a line from stdin or a file.
// Returns null on EOF. If EOF appears in the middle
// of a line, returns that line, then null on next call.
//
static public String getLine(InputStreamReader reader)
{
StringBuffer b = new StringBuffer();
int c;
try {
while ((c = reader.read()) != -1 && c != '\n') {
if (c != '\r')
b.append((char)c);
}
}
catch (IOException ioe) {
c = -1;
}
if (c == -1 && b.length() == 0)
return null;
else
return b.toString();
}
public void run()
throws DbException
{
long held;
int len = 0, locker;
int ret;
boolean did_get = false;
int lockid = 0;
InputStreamReader in = new InputStreamReader(System.in);
Vector locks = new Vector();
//
// Accept lock requests.
//
locker = lock_id();
for (held = 0;;) {
String opbuf = askForLine(in, System.out,
"Operation get/release [get]> ");
if (opbuf == null)
break;
try {
if (opbuf.equals("get")) {
// Acquire a lock.
String objbuf = askForLine(in, System.out,
"input object (text string) to lock> ");
if (objbuf == null)
break;
String lockbuf;
do {
lockbuf = askForLine(in, System.out,
"lock type read/write [read]> ");
if (lockbuf == null)
break;
len = lockbuf.length();
} while (len >= 1 &&
!lockbuf.equals("read") &&
!lockbuf.equals("write"));
int lock_type;
if (len <= 1 || lockbuf.equals("read"))
lock_type = Db.DB_LOCK_READ;
else
lock_type = Db.DB_LOCK_WRITE;
Dbt dbt = new Dbt(objbuf.getBytes());
DbLock lock;
did_get = true;
lock = lock_get(locker, Db.DB_LOCK_NOWAIT,
dbt, lock_type);
lockid = locks.size();
locks.addElement(lock);
} else {
// Release a lock.
String objbuf;
objbuf = askForLine(in, System.out,
"input lock to release> ");
if (objbuf == null)
break;
lockid = Integer.parseInt(objbuf, 16);
if (lockid < 0 || lockid >= locks.size()) {
System.out.println("Lock #" + lockid + " out of range");
continue;
}
did_get = false;
DbLock lock = (DbLock)locks.elementAt(lockid);
lock_put(lock);
}
System.out.println("Lock #" + lockid + " " +
(did_get ? "granted" : "released"));
held += did_get ? 1 : -1;
}
catch (DbException dbe) {
switch (dbe.get_errno()) {
case Db.DB_LOCK_NOTGRANTED:
System.out.println("Lock not granted");
break;
case Db.DB_LOCK_DEADLOCK:
System.err.println("LockExample: lock_" +
(did_get ? "get" : "put") +
": returned DEADLOCK");
break;
default:
System.err.println("LockExample: lock_get: " + dbe.toString());
}
}
}
System.out.println();
System.out.println("Closing lock region " + String.valueOf(held) +
" locks held");
}
private static void usage()
{
System.err.println("usage: LockExample [-u] [-h home] [-m maxlocks]");
System.exit(1);
}
public static void main(String argv[])
{
String home = LOCK_HOME;
boolean do_unlink = false;
int maxlocks = 0;
for (int i = 0; i < argv.length; ++i) {
if (argv[i].equals("-h")) {
if (++i >= argv.length)
usage();
home = argv[i];
}
else if (argv[i].equals("-m")) {
if (++i >= argv.length)
usage();
try {
maxlocks = Integer.parseInt(argv[i]);
}
catch (NumberFormatException nfe) {
usage();
}
}
else if (argv[i].equals("-u")) {
do_unlink = true;
}
else {
usage();
}
}
try {
if (do_unlink) {
// Create an environment that immediately
// removes all files.
LockExample tmp = new LockExample(home, maxlocks, do_unlink);
}
LockExample app = new LockExample(home, maxlocks, do_unlink);
app.run();
app.close(0);
}
catch (DbException dbe) {
System.err.println(progname + ": " + dbe.toString());
}
catch (Throwable t) {
System.err.println(progname + ": " + t.toString());
}
System.out.println("LockExample completed");
}
}

View File

@ -1,843 +0,0 @@
/*-
* See the file LICENSE for redistribution information.
*
* Copyright (c) 1997-2002
* Sleepycat Software. All rights reserved.
*
* $Id: TpcbExample.java,v 11.16 2002/02/13 06:08:35 mjc Exp $
*/
package com.sleepycat.examples;
import com.sleepycat.db.*;
import java.io.FileNotFoundException;
import java.util.Calendar;
import java.util.Date;
import java.util.Random;
import java.util.GregorianCalendar;
import java.math.BigDecimal;
//
// This program implements a basic TPC/B driver program. To create the
// TPC/B database, run with the -i (init) flag. The number of records
// with which to populate the account, history, branch, and teller tables
// is specified by the a, s, b, and t flags respectively. To run a TPC/B
// test, use the n flag to indicate a number of transactions to run (note
// that you can run many of these processes in parallel to simulate a
// multiuser test run).
//
class TpcbExample extends DbEnv
{
public static final int TELLERS_PER_BRANCH = 10;
public static final int ACCOUNTS_PER_TELLER = 10000;
public static final int HISTORY_PER_BRANCH = 2592000;
//
// The default configuration that adheres to TPCB scaling rules requires
// nearly 3 GB of space. To avoid requiring that much space for testing,
// we set the parameters much lower. If you want to run a valid 10 TPS
// configuration, uncomment the VALID_SCALING configuration
//
// VALID_SCALING configuration
/*
public static final int ACCOUNTS = 1000000;
public static final int BRANCHES = 10;
public static final int TELLERS = 100;
public static final int HISTORY = 25920000;
*/
// TINY configuration
/*
public static final int ACCOUNTS = 1000;
public static final int BRANCHES = 10;
public static final int TELLERS = 100;
public static final int HISTORY = 10000;
*/
// Default configuration
public static final int ACCOUNTS = 100000;
public static final int BRANCHES = 10;
public static final int TELLERS = 100;
public static final int HISTORY = 259200;
public static final int HISTORY_LEN = 100;
public static final int RECLEN = 100;
public static final int BEGID = 1000000;
// used by random_id()
public static final int ACCOUNT = 0;
public static final int BRANCH = 1;
public static final int TELLER = 2;
private static boolean verbose = false;
private static final String progname = "TpcbExample"; // Program name.
public TpcbExample(String home, int cachesize,
boolean initializing, int flags)
throws DbException, FileNotFoundException
{
super(0);
set_error_stream(System.err);
set_errpfx(progname);
set_cachesize(0, cachesize == 0 ? 4 * 1024 * 1024 : cachesize, 0);
if ((flags & (Db.DB_TXN_NOSYNC)) != 0)
set_flags(Db.DB_TXN_NOSYNC, true);
flags &= ~(Db.DB_TXN_NOSYNC);
int local_flags = flags | Db.DB_CREATE;
if (initializing)
local_flags |= Db.DB_INIT_MPOOL;
else
local_flags |= Db.DB_INIT_TXN | Db.DB_INIT_LOCK |
Db.DB_INIT_LOG | Db.DB_INIT_MPOOL;
open(home, local_flags, 0); // may throw DbException
}
//
// Initialize the database to the specified number of accounts, branches,
// history records, and tellers.
//
// Note: num_h was unused in the original ex_tpcb.c example.
//
public void
populate(int num_a, int num_b, int num_h, int num_t)
{
Db dbp = null;
int err;
int balance, idnum;
int end_anum, end_bnum, end_tnum;
int start_anum, start_bnum, start_tnum;
int h_nelem;
idnum = BEGID;
balance = 500000;
h_nelem = num_a;
try {
dbp = new Db(this, 0);
dbp.set_h_nelem(h_nelem);
dbp.open(null, "account", null, Db.DB_HASH,
Db.DB_CREATE | Db.DB_TRUNCATE, 0644);
}
// can be DbException or FileNotFoundException
catch (Exception e1) {
errExit(e1, "Open of account file failed");
}
start_anum = idnum;
populateTable(dbp, idnum, balance, h_nelem, "account");
idnum += h_nelem;
end_anum = idnum - 1;
try {
dbp.close(0);
}
catch (DbException e2) {
errExit(e2, "Account file close failed");
}
if (verbose)
System.out.println("Populated accounts: "
+ String.valueOf(start_anum) + " - " + String.valueOf(end_anum));
//
// Since the number of branches is very small, we want to use very
// small pages and only 1 key per page. This is the poor-man's way
// of getting key locking instead of page locking.
//
h_nelem = (int)num_b;
try {
dbp = new Db(this, 0);
dbp.set_h_nelem(h_nelem);
dbp.set_h_ffactor(1);
dbp.set_pagesize(512);
dbp.open(null, "branch", null, Db.DB_HASH,
Db.DB_CREATE | Db.DB_TRUNCATE, 0644);
}
// can be DbException or FileNotFoundException
catch (Exception e3) {
errExit(e3, "Branch file create failed");
}
start_bnum = idnum;
populateTable(dbp, idnum, balance, h_nelem, "branch");
idnum += h_nelem;
end_bnum = idnum - 1;
try {
dbp.close(0);
}
catch (DbException dbe4) {
errExit(dbe4, "Close of branch file failed");
}
if (verbose)
System.out.println("Populated branches: "
+ String.valueOf(start_bnum) + " - " + String.valueOf(end_bnum));
//
// In the case of tellers, we also want small pages, but we'll let
// the fill factor dynamically adjust itself.
//
h_nelem = (int)num_t;
try {
dbp = new Db(this, 0);
dbp.set_h_nelem(h_nelem);
dbp.set_h_ffactor(0);
dbp.set_pagesize(512);
dbp.open(null, "teller", null, Db.DB_HASH,
Db.DB_CREATE | Db.DB_TRUNCATE, 0644);
}
// can be DbException or FileNotFoundException
catch (Exception e5) {
errExit(e5, "Teller file create failed");
}
start_tnum = idnum;
populateTable(dbp, idnum, balance, h_nelem, "teller");
idnum += h_nelem;
end_tnum = idnum - 1;
try {
dbp.close(0);
}
catch (DbException e6) {
errExit(e6, "Close of teller file failed");
}
if (verbose)
System.out.println("Populated tellers: "
+ String.valueOf(start_tnum) + " - " + String.valueOf(end_tnum));
try {
dbp = new Db(this, 0);
dbp.set_re_len(HISTORY_LEN);
dbp.open(null, "history", null, Db.DB_RECNO,
Db.DB_CREATE | Db.DB_TRUNCATE, 0644);
}
// can be DbException or FileNotFoundException
catch (Exception e7) {
errExit(e7, "Create of history file failed");
}
populateHistory(dbp, num_h, num_a, num_b, num_t);
try {
dbp.close(0);
}
catch (DbException e8) {
errExit(e8, "Close of history file failed");
}
}
public void
populateTable(Db dbp,
int start_id, int balance,
int nrecs, String msg)
{
Defrec drec = new Defrec();
Dbt kdbt = new Dbt(drec.data);
kdbt.set_size(4); // sizeof(int)
Dbt ddbt = new Dbt(drec.data);
ddbt.set_size(drec.data.length); // uses whole array
try {
for (int i = 0; i < nrecs; i++) {
kdbt.set_recno_key_data(start_id + (int)i);
drec.set_balance(balance);
dbp.put(null, kdbt, ddbt, Db.DB_NOOVERWRITE);
}
}
catch (DbException dbe) {
System.err.println("Failure initializing " + msg + " file: " +
dbe.toString());
System.exit(1);
}
}
public void
populateHistory(Db dbp, int nrecs,
int anum, int bnum, int tnum)
{
Histrec hrec = new Histrec();
hrec.set_amount(10);
byte arr[] = new byte[4]; // sizeof(int)
int i;
Dbt kdbt = new Dbt(arr);
kdbt.set_size(arr.length);
Dbt ddbt = new Dbt(hrec.data);
ddbt.set_size(hrec.data.length);
try {
for (i = 1; i <= nrecs; i++) {
kdbt.set_recno_key_data(i);
hrec.set_aid(random_id(ACCOUNT, anum, bnum, tnum));
hrec.set_bid(random_id(BRANCH, anum, bnum, tnum));
hrec.set_tid(random_id(TELLER, anum, bnum, tnum));
dbp.put(null, kdbt, ddbt, Db.DB_APPEND);
}
}
catch (DbException dbe) {
errExit(dbe, "Failure initializing history file");
}
}
static Random rand = new Random();
public static int
random_int(int lo, int hi)
{
int ret;
int t;
t = rand.nextInt();
if (t < 0)
t = -t;
ret = (int)(((double)t / ((double)(Integer.MAX_VALUE) + 1)) *
(hi - lo + 1));
ret += lo;
return (ret);
}
public static int
random_id(int type, int accounts, int branches, int tellers)
{
int min, max, num;
max = min = BEGID;
num = accounts;
switch(type) {
case TELLER:
min += branches;
num = tellers;
// Fallthrough
case BRANCH:
if (type == BRANCH)
num = branches;
min += accounts;
// Fallthrough
case ACCOUNT:
max = min + num - 1;
}
return (random_int(min, max));
}
public void
run(int n, int accounts, int branches, int tellers)
{
Db adb = null;
Db bdb = null;
Db hdb = null;
Db tdb = null;
double gtps, itps;
int failed, ifailed, ret, txns;
long starttime, curtime, lasttime;
//
// Open the database files.
//
int err;
try {
adb = new Db(this, 0);
adb.open(null, "account", null, Db.DB_UNKNOWN,
Db.DB_AUTO_COMMIT, 0);
bdb = new Db(this, 0);
bdb.open(null, "branch", null, Db.DB_UNKNOWN,
Db.DB_AUTO_COMMIT, 0);
tdb = new Db(this, 0);
tdb.open(null, "teller", null, Db.DB_UNKNOWN,
Db.DB_AUTO_COMMIT, 0);
hdb = new Db(this, 0);
hdb.open(null, "history", null, Db.DB_UNKNOWN,
Db.DB_AUTO_COMMIT, 0);
}
catch (DbException dbe) {
errExit(dbe, "Open of db files failed");
}
catch (FileNotFoundException fnfe) {
errExit(fnfe, "Open of db files failed, missing file");
}
txns = failed = ifailed = 0;
starttime = (new Date()).getTime();
lasttime = starttime;
while (n-- > 0) {
txns++;
ret = txn(adb, bdb, tdb, hdb, accounts, branches, tellers);
if (ret != 0) {
failed++;
ifailed++;
}
if (n % 5000 == 0) {
curtime = (new Date()).getTime();
gtps = (double)(txns - failed) /
((curtime - starttime) / 1000.0);
itps = (double)(5000 - ifailed) /
((curtime - lasttime) / 1000.0);
System.out.print(String.valueOf(txns) + " txns " +
String.valueOf(failed) + " failed ");
System.out.println(showRounded(gtps, 2) + " TPS (gross) " +
showRounded(itps, 2) + " TPS (interval)");
lasttime = curtime;
ifailed = 0;
}
}
try {
adb.close(0);
bdb.close(0);
tdb.close(0);
hdb.close(0);
}
catch (DbException dbe2) {
errExit(dbe2, "Close of db files failed");
}
System.out.println((long)txns + " transactions begun "
+ String.valueOf(failed) + " failed");
}
//
// XXX Figure out the appropriate way to pick out IDs.
//
public int
txn(Db adb, Db bdb, Db tdb, Db hdb,
int anum, int bnum, int tnum)
{
Dbc acurs = null;
Dbc bcurs = null;
Dbc hcurs = null;
Dbc tcurs = null;
DbTxn t = null;
Defrec rec = new Defrec();
Histrec hrec = new Histrec();
int account, branch, teller;
Dbt d_dbt = new Dbt();
Dbt d_histdbt = new Dbt();
Dbt k_dbt = new Dbt();
Dbt k_histdbt = new Dbt();
account = random_id(ACCOUNT, anum, bnum, tnum);
branch = random_id(BRANCH, anum, bnum, tnum);
teller = random_id(TELLER, anum, bnum, tnum);
// The history key will not actually be retrieved,
// but it does need to be set to something.
byte hist_key[] = new byte[4];
k_histdbt.set_data(hist_key);
k_histdbt.set_size(4 /* == sizeof(int)*/);
byte key_bytes[] = new byte[4];
k_dbt.set_data(key_bytes);
k_dbt.set_size(4 /* == sizeof(int)*/);
d_dbt.set_flags(Db.DB_DBT_USERMEM);
d_dbt.set_data(rec.data);
d_dbt.set_ulen(rec.length());
hrec.set_aid(account);
hrec.set_bid(branch);
hrec.set_tid(teller);
hrec.set_amount(10);
// Request 0 bytes since we're just positioning.
d_histdbt.set_flags(Db.DB_DBT_PARTIAL);
// START TIMING
try {
t = txn_begin(null, 0);
acurs = adb.cursor(t, 0);
bcurs = bdb.cursor(t, 0);
tcurs = tdb.cursor(t, 0);
hcurs = hdb.cursor(t, 0);
// Account record
k_dbt.set_recno_key_data(account);
if (acurs.get(k_dbt, d_dbt, Db.DB_SET) != 0)
throw new TpcbException("acurs get failed");
rec.set_balance(rec.get_balance() + 10);
acurs.put(k_dbt, d_dbt, Db.DB_CURRENT);
// Branch record
k_dbt.set_recno_key_data(branch);
if (bcurs.get(k_dbt, d_dbt, Db.DB_SET) != 0)
throw new TpcbException("bcurs get failed");
rec.set_balance(rec.get_balance() + 10);
bcurs.put(k_dbt, d_dbt, Db.DB_CURRENT);
// Teller record
k_dbt.set_recno_key_data(teller);
if (tcurs.get(k_dbt, d_dbt, Db.DB_SET) != 0)
throw new TpcbException("ccurs get failed");
rec.set_balance(rec.get_balance() + 10);
tcurs.put(k_dbt, d_dbt, Db.DB_CURRENT);
// History record
d_histdbt.set_flags(0);
d_histdbt.set_data(hrec.data);
d_histdbt.set_ulen(hrec.length());
if (hdb.put(t, k_histdbt, d_histdbt, Db.DB_APPEND) != 0)
throw(new DbException("put failed"));
acurs.close();
bcurs.close();
tcurs.close();
hcurs.close();
// null out t in advance; if the commit fails,
// we don't want to abort it in the catch clause.
DbTxn tmptxn = t;
t = null;
tmptxn.commit(0);
// END TIMING
return (0);
}
catch (Exception e) {
try {
if (acurs != null)
acurs.close();
if (bcurs != null)
bcurs.close();
if (tcurs != null)
tcurs.close();
if (hcurs != null)
hcurs.close();
if (t != null)
t.abort();
}
catch (DbException dbe) {
// not much we can do here.
}
if (verbose) {
System.out.println("Transaction A=" + String.valueOf(account)
+ " B=" + String.valueOf(branch)
+ " T=" + String.valueOf(teller) + " failed");
System.out.println("Reason: " + e.toString());
}
return (-1);
}
}
static void errExit(Exception err, String s)
{
System.err.print(progname + ": ");
if (s != null) {
System.err.print(s + ": ");
}
System.err.println(err.toString());
System.exit(1);
}
public static void main(String argv[])
{
long seed;
int accounts, branches, tellers, history;
boolean iflag, txn_no_sync;
int mpool, ntxns;
String home, endarg;
home = "TESTDIR";
accounts = branches = history = tellers = 0;
txn_no_sync = false;
mpool = ntxns = 0;
verbose = false;
iflag = false;
seed = (new GregorianCalendar()).get(Calendar.SECOND);
for (int i = 0; i < argv.length; ++i)
{
if (argv[i].equals("-a")) {
// Number of account records
if ((accounts = Integer.parseInt(argv[++i])) <= 0)
invarg(argv[i]);
}
else if (argv[i].equals("-b")) {
// Number of branch records
if ((branches = Integer.parseInt(argv[++i])) <= 0)
invarg(argv[i]);
}
else if (argv[i].equals("-c")) {
// Cachesize in bytes
if ((mpool = Integer.parseInt(argv[++i])) <= 0)
invarg(argv[i]);
}
else if (argv[i].equals("-f")) {
// Fast mode: no txn sync.
txn_no_sync = true;
}
else if (argv[i].equals("-h")) {
// DB home.
home = argv[++i];
}
else if (argv[i].equals("-i")) {
// Initialize the test.
iflag = true;
}
else if (argv[i].equals("-n")) {
// Number of transactions
if ((ntxns = Integer.parseInt(argv[++i])) <= 0)
invarg(argv[i]);
}
else if (argv[i].equals("-S")) {
// Random number seed.
seed = Long.parseLong(argv[++i]);
if (seed <= 0)
invarg(argv[i]);
}
else if (argv[i].equals("-s")) {
// Number of history records
if ((history = Integer.parseInt(argv[++i])) <= 0)
invarg(argv[i]);
}
else if (argv[i].equals("-t")) {
// Number of teller records
if ((tellers = Integer.parseInt(argv[++i])) <= 0)
invarg(argv[i]);
}
else if (argv[i].equals("-v")) {
// Verbose option.
verbose = true;
}
else
{
usage();
}
}
rand.setSeed((int)seed);
TpcbExample app = null;
// Initialize the database environment.
// Must be done in within a try block.
//
try {
app = new TpcbExample(home, mpool, iflag,
txn_no_sync ? Db.DB_TXN_NOSYNC : 0);
}
catch (Exception e1) {
errExit(e1, "initializing environment failed");
}
accounts = accounts == 0 ? ACCOUNTS : accounts;
branches = branches == 0 ? BRANCHES : branches;
tellers = tellers == 0 ? TELLERS : tellers;
history = history == 0 ? HISTORY : history;
if (verbose)
System.out.println((long)accounts + " Accounts, "
+ String.valueOf(branches) + " Branches, "
+ String.valueOf(tellers) + " Tellers, "
+ String.valueOf(history) + " History");
if (iflag) {
if (ntxns != 0)
usage();
app.populate(accounts, branches, history, tellers);
}
else {
if (ntxns == 0)
usage();
app.run(ntxns, accounts, branches, tellers);
}
// Shut down the application.
try {
app.close(0);
}
catch (DbException dbe2) {
errExit(dbe2, "appexit failed");
}
System.exit(0);
}
private static void invarg(String str)
{
System.err.println("TpcbExample: invalid argument: " + str);
System.exit(1);
}
private static void usage()
{
System.err.println(
"usage: TpcbExample [-fiv] [-a accounts] [-b branches]\n" +
" [-c cachesize] [-h home] [-n transactions ]\n" +
" [-S seed] [-s history] [-t tellers]");
System.exit(1);
}
// round 'd' to 'scale' digits, and return result as string
private String showRounded(double d, int scale)
{
return new BigDecimal(d).
setScale(scale, BigDecimal.ROUND_HALF_DOWN).toString();
}
// The byte order is our choice.
//
static long get_int_in_array(byte[] array, int offset)
{
return
((0xff & array[offset+0]) << 0) |
((0xff & array[offset+1]) << 8) |
((0xff & array[offset+2]) << 16) |
((0xff & array[offset+3]) << 24);
}
// Note: Value needs to be long to avoid sign extension
static void set_int_in_array(byte[] array, int offset, long value)
{
array[offset+0] = (byte)((value >> 0) & 0x0ff);
array[offset+1] = (byte)((value >> 8) & 0x0ff);
array[offset+2] = (byte)((value >> 16) & 0x0ff);
array[offset+3] = (byte)((value >> 24) & 0x0ff);
}
};
// Simulate the following C struct:
// struct Defrec {
// u_int32_t id;
// u_int32_t balance;
// u_int8_t pad[RECLEN - sizeof(int) - sizeof(int)];
// };
class Defrec
{
public Defrec()
{
data = new byte[TpcbExample.RECLEN];
}
public int length()
{
return TpcbExample.RECLEN;
}
public long get_id()
{
return TpcbExample.get_int_in_array(data, 0);
}
public void set_id(long value)
{
TpcbExample.set_int_in_array(data, 0, value);
}
public long get_balance()
{
return TpcbExample.get_int_in_array(data, 4);
}
public void set_balance(long value)
{
TpcbExample.set_int_in_array(data, 4, value);
}
static {
Defrec d = new Defrec();
d.set_balance(500000);
}
public byte[] data;
}
// Simulate the following C struct:
// struct Histrec {
// u_int32_t aid;
// u_int32_t bid;
// u_int32_t tid;
// u_int32_t amount;
// u_int8_t pad[RECLEN - 4 * sizeof(u_int32_t)];
// };
class Histrec
{
public Histrec()
{
data = new byte[TpcbExample.RECLEN];
}
public int length()
{
return TpcbExample.RECLEN;
}
public long get_aid()
{
return TpcbExample.get_int_in_array(data, 0);
}
public void set_aid(long value)
{
TpcbExample.set_int_in_array(data, 0, value);
}
public long get_bid()
{
return TpcbExample.get_int_in_array(data, 4);
}
public void set_bid(long value)
{
TpcbExample.set_int_in_array(data, 4, value);
}
public long get_tid()
{
return TpcbExample.get_int_in_array(data, 8);
}
public void set_tid(long value)
{
TpcbExample.set_int_in_array(data, 8, value);
}
public long get_amount()
{
return TpcbExample.get_int_in_array(data, 12);
}
public void set_amount(long value)
{
TpcbExample.set_int_in_array(data, 12, value);
}
public byte[] data;
}
class TpcbException extends Exception
{
TpcbException()
{
super();
}
TpcbException(String s)
{
super(s);
}
}

View File

@ -1885,6 +1885,9 @@ print_table_data_xml(MYSQL_RES *result)
{
MYSQL_ROW cur;
MYSQL_FIELD *fields;
#ifdef __NETWARE__
uint lines= 0;
#endif
mysql_field_seek(result,0);

View File

@ -987,6 +987,9 @@ static void dumpTable(uint numFields, char *table)
MYSQL_FIELD *field;
MYSQL_ROW row;
ulong rownr, row_break, total_length, init_length;
#if defined(__NETWARE__) && defined(THREAD)
uint lines= 0;
#endif
if (verbose)
fprintf(stderr, "-- Sending SELECT query...\n");
@ -1216,6 +1219,11 @@ static void dumpTable(uint numFields, char *table)
}
else if (!opt_xml)
fputs(");\n", md_result_file);
#if defined(__NETWARE__) && defined(THREAD)
/* on a long result the screen could hog the cpu */
if ((lines++ & 1023) == 0)
pthread_yield();
#endif
}
/* XML - close table tag and supress regular output */

View File

@ -259,7 +259,7 @@ const char *command_names[]=
"enable_warnings",
"disable_warnings",
"enable_info",
"diable_info",
"disable_info",
0
};

View File

@ -35,10 +35,10 @@ rm -f $AVAILABLE_LANGUAGES_ERRORS_RULES
for i in $AVAILABLE_LANGUAGES
do
AVAILABLE_LANGUAGES_ERRORS="$AVAILABLE_LANGUAGES_ERRORS $i/errmsg.sys"
case $SYSTEM_TYPE in
*netware* | *modesto*)
case $host_os in
netware* | modesto*)
echo "$i/errmsg.sys: $i/errmsg.txt
\$(top_builddir)/extra/comp_err.cyg \$^ $i/errmsg.sys" \
\$(top_builddir)/extra/comp_err.linux \$^ $i/errmsg.sys" \
>> $AVAILABLE_LANGUAGES_ERRORS_RULES
;;
*)
@ -1067,7 +1067,10 @@ dnl Is this the right match for DEC OSF on alpha?
*netware*)
# No need for curses library so set it to null
with_named_curses=""
PLATFORM_NETWARE=yes
# No thread library - in LibC
with_named_thread=""
#
# Edit Makefile.in files.
#
@ -1089,36 +1092,36 @@ dnl Is this the right match for DEC OSF on alpha?
fi
case $file in
sql/Makefile.in)
# Use gen_lex_hash.cyg instead of gen_lex_hash
# Use gen_lex_hash.linux instead of gen_lex_hash
# Add library dependencies to mysqld_DEPENDENCIES
lib_DEPENDENCIES="\$(bdb_libs_with_path) \$(innodb_libs) \$(pstack_libs) \$(innodb_system_libs) \$(openssl_libs)"
cat > $filesed << EOF
s,\(^.*\$(MAKE) gen_lex_hash\),#\1,
s,\(\./gen_lex_hash\),\1.cyg,
s,\(\./gen_lex_hash\),\1.linux,
s%\(mysqld_DEPENDENCIES = \) %\1$lib_DEPENDENCIES %
EOF
;;
sql/share/Makefile.in)
cat > $filesed << EOF
s,\(extra/comp_err\),\1.cyg,
s,\(extra/comp_err\),\1.linux,
EOF
;;
libmysql/Makefile.in)
cat > $filesed << EOF
s,\(\./conf_to_src\)\( \$(top_srcdir)\),\1.cyg\2,
s,\(: conf_to_src\),\1.cyg,
s,\(\./conf_to_src\)\( \$(top_srcdir)\),\1.linux\2,
s,\(: conf_to_src\),\1.linux,
EOF
;;
libmysql_r/Makefile.in)
cat > $filesed << EOF
s,\(\./conf_to_src\)\( \$(top_srcdir)\),\1.cyg\2,
s,\(: conf_to_src\),\1.cyg,
s,\(\./conf_to_src\)\( \$(top_srcdir)\),\1.linux\2,
s,\(: conf_to_src\),\1.linux,
EOF
;;
strings/Makefile.in)
cat > $filesed << EOF
s,\(\./conf_to_src\)\( \$(top_srcdir)\),\1.cyg\2,
s,\(: conf_to_src\),\1.cyg,
s,\(\./conf_to_src\)\( \$(top_srcdir)\),\1.linux\2,
s,\(: conf_to_src\),\1.linux,
EOF
;;
client/Makefile.in)
@ -1167,7 +1170,6 @@ EOF
;;
esac
AM_CONDITIONAL(PLATFORM_NETWARE, test "$PLATFORM_NETWARE" = "yes")
#---START: Used in for client configure
# Check if we threads are in libc or if we should use
@ -2270,13 +2272,6 @@ AC_ARG_WITH(extra-charsets,
[extra_charsets="$withval"],
[extra_charsets="none"])
AC_ARG_WITH(platform-dir,
[ --with-platform-dir=DIR
Add specified directory to list of SUBDIRS to build.],
[ with_platform_dir=$withval ],
[ with_platform_dir=no ]
)
AC_MSG_CHECKING("character sets")
if test "$extra_charsets" = none; then
@ -2458,12 +2453,15 @@ AC_SUBST(CLIENT_LIBS)
AC_SUBST(sql_client_dirs)
AC_SUBST(linked_client_targets)
platform_dir=
if test "$with_platform_dir" != "no"
then
platform_dir="$with_platform_dir"
# If configuring for NetWare, set up to link sources from and build the netware directory
netware_dir=
linked_netware_sources=
if expr "$SYSTEM_TYPE" : ".*netware.*" > /dev/null; then
netware_dir="netware"
linked_netware_sources="linked_netware_sources"
fi
AC_SUBST(platform_dir)
AC_SUBST(netware_dir)
AC_SUBST(linked_netware_sources)
if test "$with_server" = "yes" -o "$THREAD_SAFE_CLIENT" != "no"
then
@ -2630,6 +2628,17 @@ AC_SUBST(GXX)
#Remove TOOLS_LIBS, because this is included in LIBRARIES
#AC_SUBST(TOOLS_LIBS)
# Set configuration options for make_binary_distribution
case $SYSTEM_TYPE in
*netware*)
MAKE_BINARY_DISTRIBUTION_OPTIONS=--no-strip
;;
*)
MAKE_BINARY_DISTRIBUTION_OPTIONS=
;;
esac
AC_SUBST(MAKE_BINARY_DISTRIBUTION_OPTIONS)
# Output results
if test "$compile_readline" = "yes"

View File

@ -16,6 +16,8 @@
/* Wait until a program dies */
#ifndef __NETWARE__
#include <my_global.h>
#include <m_string.h>
#include <my_getopt.h>
@ -101,3 +103,15 @@ void usage(void)
my_print_help(my_long_options);
exit(-1);
}
#else
#include <stdio.h>
main()
{
fprintf(stderr,"This tool has not been ported to NetWare\n");
return 0;
}
#endif /* __NETWARE__ */

View File

@ -431,7 +431,7 @@ struct tm *localtime_r(const time_t *clock, struct tm *res);
#define pthread_kill(A,B) pthread_dummy(0)
#undef pthread_detach_this_thread
#define pthread_detach_this_thread() { pthread_t tmp=pthread_self() ; pthread_detach(&tmp); }
#else /* HAVE_PTHREAD_ATTR_CREATE && !HAVE_SIGWAIT */
#elif !defined(__NETWARE__) /* HAVE_PTHREAD_ATTR_CREATE && !HAVE_SIGWAIT */
#define HAVE_PTHREAD_KILL
#endif

View File

@ -595,7 +595,7 @@ my_bool
simple_command(MYSQL *mysql,enum enum_server_command command, const char *arg,
unsigned long length, my_bool skip_check);
unsigned long net_safe_read(MYSQL* mysql);
void STDCALL mysql_once_init(void);
void mysql_once_init(void);
#ifdef __NETWARE__
#pragma pack(pop) /* restore alignment */

View File

@ -774,7 +774,8 @@ char* getlogin(void);
/* default to "root" on NetWare */
static void read_user_name(char *name)
{
(void)strmake(name,"root", USERNAME_LENGTH);
char *str=getenv("USER");
strmake(name, str ? str : "UNKNOWN_USER", USERNAME_LENGTH);
}
#elif !defined(MSDOS) && ! defined(VMS) && !defined(__WIN__) && !defined(OS2)
@ -1776,7 +1777,7 @@ mysql_init(MYSQL *mysql)
outside program.
*/
void STDCALL mysql_once_init(void)
void mysql_once_init(void)
{
if (!mysql_client_init)
{
@ -4373,7 +4374,6 @@ int STDCALL mysql_execute(MYSQL_STMT *stmt)
set_stmt_error(stmt, CR_NO_PREPARE_STMT);
DBUG_RETURN(1);
}
stmt->mysql->fields= stmt->fields;
if (stmt->param_count)
{
NET *net= &stmt->mysql->net;
@ -5433,12 +5433,15 @@ int STDCALL mysql_stmt_store_result(MYSQL_STMT *stmt)
static my_bool stmt_close(MYSQL_STMT *stmt, my_bool skip_list)
{
MYSQL *mysql;
my_bool error= 0;
DBUG_ENTER("mysql_stmt_close");
DBUG_ASSERT(stmt != 0);
mysql= stmt->mysql;
if (!(mysql= stmt->mysql))
{
my_free((gptr) stmt, MYF(MY_WME));
DBUG_RETURN(0);
}
if (mysql->status != MYSQL_STATUS_READY)
{
/* Clear the current execution status */
@ -5457,18 +5460,20 @@ static my_bool stmt_close(MYSQL_STMT *stmt, my_bool skip_list)
{
char buff[4];
int4store(buff, stmt->stmt_id);
error= simple_command(mysql, COM_CLOSE_STMT, buff, 4, 1);
}
if (!error)
if (simple_command(mysql, COM_CLOSE_STMT, buff, 4, 1))
{
set_stmt_errmsg(stmt, mysql->net.last_error, mysql->net.last_errno);
stmt->mysql= NULL; /* connection isn't valid anymore */
DBUG_RETURN(1);
}
}
mysql_free_result(stmt->result);
free_root(&stmt->mem_root, MYF(0));
if (!skip_list)
mysql->stmts= list_delete(mysql->stmts, &stmt->list);
mysql->status= MYSQL_STATUS_READY;
my_free((gptr) stmt, MYF(MY_WME));
}
DBUG_RETURN(error);
DBUG_RETURN(0);
}
my_bool STDCALL mysql_stmt_close(MYSQL_STMT *stmt)

View File

@ -468,7 +468,6 @@ uint STDCALL mysql_warning_count(MYSQL *mysql)
void Protocol_simple::prepare_for_resend()
{
MYSQL_ROWS *cur;
ulong len;
MYSQL_DATA *result= thd->mysql->result->data;
DBUG_ENTER("send_data");

View File

@ -31,7 +31,6 @@
#include <errno.h>
#include <my_sys.h>
#include <violite.h>
#include <my_sys.h>
#include <my_net.h>
#include <m_string.h>
#include <dbug.h>

View File

@ -66,7 +66,7 @@ TYPELIB sql_protocol_typelib = {array_elements(sql_protocol_names_lib)-1,"",
#define closesocket(A) close(A)
#endif
void STDCALL mysql_once_init(void);
void mysql_once_init(void);
static void end_server(MYSQL *mysql);
static void append_wild(char *to,char *end,const char *wild);
static ulong mysql_sub_escape_string(CHARSET_INFO *charset_info, char *to,
@ -386,7 +386,7 @@ mysql_init(MYSQL *mysql)
}
void STDCALL mysql_once_init()
void mysql_once_init()
{
if (!mysql_client_init)
{
@ -1038,11 +1038,10 @@ mysql_list_fields(MYSQL *mysql __attribute__((unused)), const char *table __attr
}
/* List all running processes (threads) in server */
#ifdef DUMMY
MYSQL_RES * STDCALL
mysql_list_processes(MYSQL *mysql)
{
#ifdef DUMMY
MYSQL_DATA *fields;
uint field_count;
uchar *pos;
@ -1063,9 +1062,9 @@ mysql_list_processes(MYSQL *mysql)
mysql->status=MYSQL_STATUS_GET_RESULT;
mysql->field_count=field_count;
DBUG_RETURN(mysql_store_result(mysql));
return (MYSQL_RES*)mysql;
}
#endif /*DUMMY*/
return 0;
}
int STDCALL

View File

@ -124,13 +124,9 @@ int main(int argc,char *argv[])
{
keylen=*(info->lastkey);
#if HA_FT_WTYPE == HA_KEYTYPE_FLOAT
subkeys=mi_sint4korr(info->lastkey+keylen+1);
subkeys=ft_sintXkorr(info->lastkey+keylen+1);
if (subkeys >= 0)
weight=*(float*)&subkeys;
#else
#error
#endif
snprintf(buf,MAX_LEN,"%.*s",(int) keylen,info->lastkey+1);
my_casedn_str(default_charset_info,buf);

View File

@ -1893,6 +1893,7 @@ int mi_repair_by_sort(MI_CHECK *param, register MI_INFO *info,
{
sort_param.read_cache=param->read_cache;
sort_param.keyinfo=share->keyinfo+sort_param.key;
sort_param.seg=sort_param.keyinfo->seg;
if (!(((ulonglong) 1 << sort_param.key) & key_map))
{
/* Remember old statistics for key */
@ -1906,7 +1907,7 @@ int mi_repair_by_sort(MI_CHECK *param, register MI_INFO *info,
if ((!(param->testflag & T_SILENT)))
printf ("- Fixing index %d\n",sort_param.key+1);
sort_param.max_pos=sort_param.pos=share->pack.header_length;
keyseg=sort_param.keyinfo->seg;
keyseg=sort_param.seg;
bzero((char*) sort_param.unique,sizeof(sort_param.unique));
sort_param.key_length=share->rec_reflength;
for (i=0 ; keyseg[i].type != HA_KEYTYPE_END; i++)
@ -2255,6 +2256,7 @@ int mi_repair_parallel(MI_CHECK *param, register MI_INFO *info,
{
sort_param[i].key=key;
sort_param[i].keyinfo=share->keyinfo+key;
sort_param[i].seg=sort_param[i].keyinfo->seg;
if (!(((ulonglong) 1 << key) & key_map))
{
/* Remember old statistics for key */
@ -2292,7 +2294,7 @@ int mi_repair_parallel(MI_CHECK *param, register MI_INFO *info,
(share->base.pack_reclength * i));
sort_param[i].key_length=share->rec_reflength;
for (keyseg=sort_param[i].keyinfo->seg; keyseg->type != HA_KEYTYPE_END;
for (keyseg=sort_param[i].seg; keyseg->type != HA_KEYTYPE_END;
keyseg++)
{
sort_param[i].key_length+=keyseg->length;
@ -3051,7 +3053,7 @@ static int sort_key_cmp(MI_SORT_PARAM *sort_param, const void *a,
const void *b)
{
uint not_used;
return (ha_key_cmp(sort_param->keyinfo->seg, *((uchar**) a), *((uchar**) b),
return (ha_key_cmp(sort_param->seg, *((uchar**) a), *((uchar**) b),
USE_WHOLE_KEY, SEARCH_SAME,&not_used));
} /* sort_key_cmp */
@ -3066,7 +3068,7 @@ static int sort_key_write(MI_SORT_PARAM *sort_param, const void *a)
if (sort_info->key_block->inited)
{
cmp=ha_key_cmp(sort_param->keyinfo->seg,sort_info->key_block->lastkey,
cmp=ha_key_cmp(sort_param->seg,sort_info->key_block->lastkey,
(uchar*) a, USE_WHOLE_KEY,SEARCH_FIND | SEARCH_UPDATE,
&diff_pos);
sort_param->unique[diff_pos-1]++;
@ -3091,7 +3093,7 @@ static int sort_key_write(MI_SORT_PARAM *sort_param, const void *a)
llbuff2));
param->testflag|=T_RETRY_WITHOUT_QUICK;
if (sort_info->param->testflag & T_VERBOSE)
_mi_print_key(stdout,sort_param->keyinfo->seg,(uchar*) a, USE_WHOLE_KEY);
_mi_print_key(stdout,sort_param->seg,(uchar*) a, USE_WHOLE_KEY);
return (sort_delete_record(sort_param));
}
#ifndef DBUG_OFF
@ -3182,7 +3184,7 @@ static int sort_ft_key_write(MI_SORT_PARAM *sort_param, const void *a)
get_key_full_length_rdonly(val_off, ft_buf->lastkey);
if (val_off == a_len &&
mi_compare_text(sort_param->keyinfo->seg->charset,
mi_compare_text(sort_param->seg->charset,
((uchar *)a)+1,a_len-1,
ft_buf->lastkey+1,val_off-1, 0)==0)
{

View File

@ -484,6 +484,7 @@ MI_INFO *mi_open(const char *name, int mode, uint open_flags)
if (mi_open_datafile(&info, share, old_info->dfile))
goto err;
errpos=5;
have_rtree= old_info->rtree_recursion_state != NULL;
}
/* alloc and set up private structure parts */
@ -492,13 +493,16 @@ MI_INFO *mi_open(const char *name, int mode, uint open_flags)
&info.blobs,sizeof(MI_BLOB)*share->base.blobs,
&info.buff,(share->base.max_key_block_length*2+
share->base.max_key_length),
&info.rtree_recursion_state,have_rtree ? 1024 : 0,
&info.lastkey,share->base.max_key_length*3+1,
&info.filename,strlen(org_name)+1,
&info.rtree_recursion_state,have_rtree ? 1024 : 0,
NullS))
goto err;
errpos=6;
if (!have_rtree)
info.rtree_recursion_state= NULL;
strmov(info.filename,org_name);
memcpy(info.blobs,share->blobs,sizeof(MI_BLOB)*share->base.blobs);
info.lastkey2=info.lastkey+share->base.max_key_length;

View File

@ -272,7 +272,7 @@ struct st_myisam_info {
#ifdef THREAD
THR_LOCK_DATA lock;
#endif
uchar * rtree_recursion_state; /* For RTREE */
uchar *rtree_recursion_state; /* For RTREE */
int rtree_recursion_depth;
};
@ -295,6 +295,7 @@ typedef struct st_mi_sort_param
uint maxbuffers, keys, find_length, sort_keys_length;
my_bool fix_datafile, master;
MI_KEYDEF *keyinfo;
HA_KEYSEG *seg;
SORT_INFO *sort_info;
uchar **sort_keys;
byte *rec_buff;

Some files were not shown because too many files have changed in this diff Show More