More work on documentation and examples, removed some things from the API, incorporated some of Keith's feedback.

--HG--
branch : mjc
rename : examples/c/ex_schema.c => examples/c/ex_call_center.c
extra : transplant_source : %AE%E9%C4%0B%3A%C5%0EH%E1%A8%A2L%E6%D2%D6%40G%9Dzq
This commit is contained in:
Michael Cahill
2010-12-16 22:54:09 +11:00
parent 1e1f55ddb8
commit b65420c0bd
18 changed files with 480 additions and 95 deletions

View File

@@ -12,14 +12,16 @@ That is, they are simple comma-separated lists of <code>"<key>=<value>"</code> p
Empty configuration strings may be represented in C or C++ by passing <code>NULL</code>.
Superfluous commas in the configuration string are ignored (including at the beginning and end of the string), so it is always safe to combine two configuration strings by concatenating them with a comma in between.
Superfluous commas and whitespace in the configuration string are ignored (including at the beginning and end of the string), so it is always safe to combine two configuration strings by concatenating them with a comma in between.
Keys are processed in order from left to right, with later settings overriding earlier ones unless multiple settings for a key are permitted.
\section config_examples Examples
TODO: more whitespace, complete code fragments.
<ul>
<li>To open a connection to a database, creating it if it does not exist and set a cache size of 10MiB, pass <code>"create,cache_size=10000000"</code> to ::wiredtiger_open.
<li>To open a connection to a database, creating it if it does not exist and set a cache size of 10MiB, pass <code>"create,cache_size=10M"</code> to ::wiredtiger_open.
<li>Create a table that uses C language strings for keys and values: pass <code>"keyfmt=S,valuefmt=S"</code> to WT_SESSION::create_table.</li>
<li>Assign a name to a transaction for debugging purposes: pass <code>"name=mytxn"</code> to WT_SESSION::begin_transaction.</li>
<li>Assign a priority to a transaction to avoid aborting: pass <code>"priority=100"</code> to WT_SESSION::begin_transaction.</li>

View File

@@ -13,6 +13,6 @@ The following are builtin cursor types:
<tr><td><tt>join:\<cursor1\>\&\<cursor2\>[&\<cursor3\>...]</tt></td><td>Join the contents of multiple cursors together.</td></tr>
<tr><td><tt>module:</tt></td><td>loadable modules (key=(string)name, data=(string)path)</td></tr>
<tr><td><tt>sequence:[\<seqname\>]</tt></td><td>Sequence cursor (key=recno, data=NULL)</td></tr>
<tr><td><tt>statistics:[table:\<tablename\>]</tt></td><td>database or table statistics (key=(string)keyname, data=(int64_t)value)</td></tr>
<tr><td><tt>statistics:[table:\<tablename\>]</tt></td><td>database or table statistics (key=(string)keyname, data=(string)value)</td></tr>
</table>
*/

View File

@@ -15,4 +15,8 @@ Shows how to access database and table statistics.
\example ex_schema.c
Shows how to create column-oriented data and access individual columns.
\example ex_call_center.c
A more complex schema based on a call center example, showing how to map some
SQL constructs onto the WiredTiger API.
*/

View File

@@ -8,9 +8,12 @@ The WiredTiger Data Store is a platform for extensible data management.
This documentation describes the public interface used by developers to
construct applications.
We follow SQL terminology: a database is set of tables.
We follow SQL terminology: a database is set of tables that are managed together. Tables logically consist of rows, each row has a key and a value. Tables may optionally have an associated schema, which splits the key/value pair into a set of columns. Tables may also have associated indices, each of which is ordered by some set of columns.
The API consists of only a small set of interfaces:
TODO: we need more paragraphs on this page -- maybe two more paragraphs in the Introduction that say "Applications will generally do X, Y and Z, configuration is based on strings passed to the methods, the retrieval/update interfaces is based on cursors that look like X, Y and Z."
The API consists of only a small set of classes, of which the following are
the most commonly used:
- a WT_CONNECTION represents a connection to a database. Most applications
will only open one connection to a database for each process. The first

View File

@@ -4,6 +4,8 @@
\section schema_intro Tables, Rows and Columns
XXX rewrite from scratch, fill out with more details about how to use WT_SCHEMA for various things: native C structs, portability between programming languages, non-relational data such as multiple index keys per row, etc.
Lifted from http://en.wikipedia.org/wiki/Column-oriented_DBMS.
A database program must show its data as two-dimensional tables, of columns and rows, but store it as one-dimensional strings. For example, a database might have this table.
@@ -19,7 +21,7 @@ This simple table includes an employee identifier (EmpId), name fields (Lastname
A row-oriented database serializes all of the values in a row together, then the values in the next row, and so on:
<pre>
<pre>k
1,Smith,Joe,40000;
2,Jones,Mary,50000;
3,Johnson,Cathy,44000;

View File

@@ -1,5 +1,5 @@
CC = gcc -W -Wall -Wno-unused -I../../include # -x c++
OBJS = ex_access.o ex_config.o ex_hello.o ex_sequence.o ex_stat.o ex_schema.o
CC = gcc -W -Wall -I../../include # -Wno-unused -x c++
OBJS = ex_access.o ex_call_center.o ex_config.o ex_hello.o ex_sequence.o ex_stat.o ex_schema.o
all: $(OBJS)

View File

@@ -19,33 +19,30 @@ int main()
WT_CURSOR *cursor;
const char *key, *value;
if ((ret = wiredtiger_open(home, "create", &conn)) != 0 ||
(ret = conn->open_session(conn, NULL, &session)) != 0)
if ((ret = wiredtiger_open(home, NULL, "create", &conn)) != 0 ||
(ret = conn->open_session(conn, NULL, NULL, &session)) != 0)
fprintf(stderr, "Error connecting to %s: %s\n",
home, wiredtiger_strerror(ret));
/* Note: further error checking omitted for clarity. */
if (conn->is_new) {
session->create_table(session, "access",
if (conn->is_new(conn))
ret = session->create_table(session, "access",
"keyfmt=S,valuefmt=S");
/* Insert a record. */
ret = session->open_cursor(session,
"table:access", NULL, &cursor);
cursor->set_key(cursor, "key1");
cursor->set_value(cursor, "value1");
ret = cursor->insert(cursor);
cursor->close(cursor);
}
ret = session->open_cursor(session, "table:access", NULL, &cursor);
if (conn->is_new(conn)) {
/* Insert a record. */
ret = cursor->set_key(cursor, "key1");
ret = cursor->set_value(cursor, "value1");
ret = cursor->insert(cursor);
ret = cursor->first(cursor);
}
/* Show all records. */
while ((ret = cursor->next(cursor)) == 0) {
cursor->get_key(cursor, &key);
cursor->get_value(cursor, &value);
ret = cursor->get_key(cursor, &key);
ret = cursor->get_value(cursor, &value);
printf("Got record: %s : %s\n", key, value);
}

179
examples/c/ex_call_center.c Normal file
View File

@@ -0,0 +1,179 @@
/*
* ex_call_center.c Copyright (c) 2010 WiredTiger
*
* This is an example application that demonstrates how to map a moderately
* complex SQL application into WiredTiger.
*/
#include <stdio.h>
#include <string.h>
#include <inttypes.h>
#include <wiredtiger.h>
#define ARRAY_SIZE(a) (sizeof (a) / sizeof ((a)[0]))
const char *home = "WT_TEST";
/*
* In SQL, the tables are described as follows:
*
* CREATE TABLE Customers(id INTEGER PRIMARY KEY,
* name VARCHAR(30), address VARCHAR(50), phone VARCHAR(15))
* CREATE INDEX CustomersPhone ON Cusomters(phone)
*
* CREATE TABLE Calls(id INTEGER PRIMARY KEY, call_date DATE,
* cust_id INTEGER, emp_id INTEGER, call_type VARCHAR(12), notes VARCHAR(25))
* CREATE INDEX CallsCustDate ON Calls(cust_id, call_date)
*
* In WiredTiger, both tables will use record numbers for IDs, which will be
* the key. The C structs for the records are as follows.
*/
typedef struct {
wiredtiger_recno_t id;
char *name;
char *address;
char *phone;
} CUSTOMER;
typedef struct {
wiredtiger_recno_t id;
uint64_t call_date;
wiredtiger_recno_t cust_id;
wiredtiger_recno_t emp_id;
char *call_type;
char *notes;
} CALL;
/* Description of the customer schema. */
static WT_COLUMN_INFO cust_columns[] = {
{ "id", 0, NULL, NULL },
{ "name", 1, NULL, NULL },
{ "address", 1, NULL, NULL },
{ "phone", 1, NULL, NULL }
};
static const char *cust_phone_cols[] = { "phone" };
static WT_INDEX_INFO cust_indices[] = {
{ "cust_phone", cust_phone_cols, ARRAY_SIZE(cust_phone_cols) }
};
static WT_SCHEMA cust_schema = {
"r", /* Format string for keys (recno). */
"SSS", /* Format string for data items: 3 strings */
cust_columns, /* Column descriptions. */
ARRAY_SIZE(cust_columns), /* Number of columns. */
cust_indices, /* Index descriptions. */
ARRAY_SIZE(cust_indices) /* Number of indices. */
};
/* Description of the call record schema. */
static WT_COLUMN_INFO call_columns[] = {
{ "id", 0, NULL, NULL },
{ "call_date", 0, NULL, NULL },
{ "cust_id", 0, NULL, NULL },
{ "emp_id", 0, NULL, NULL },
{ "call_type", 0, NULL, NULL },
{ "notes", 0, NULL, NULL }
};
static const char *call_cust_date_cols[] = { "cust_id", "call_date" };
static WT_INDEX_INFO call_indices[] = {
{ "call_cust_date",
call_cust_date_cols, ARRAY_SIZE(call_cust_date_cols) }
};
static WT_SCHEMA call_schema = {
"r", /* Format string for keys (recno). */
"qrrSS", /*
* Format string for data items:
* i64, 2 recnos, 2 strings
*/
call_columns, /* Column descriptions. */
ARRAY_SIZE(call_columns), /* Number of columns. */
call_indices, /* Index descriptions. */
ARRAY_SIZE(call_indices) /* Number of indices. */
};
int main()
{
int count, exact, ret;
WT_CONNECTION *conn;
WT_SESSION *session;
WT_CURSOR *cursor;
CUSTOMER cust;
CALL call;
ret = wiredtiger_open(home, NULL, "create", &conn);
if (ret != 0)
fprintf(stderr, "Error connecting to %s: %s\n",
home, wiredtiger_strerror(ret));
/* Note: error checking omitted for clarity. */
if (conn->is_new(conn)) {
ret = conn->add_schema(conn, "CUSTOMER", &cust_schema, NULL);
ret = conn->add_schema(conn, "CALL", &call_schema, NULL);
ret = session->create_table(session, "customers",
"schema=CUSTOMER");
ret = session->create_table(session, "calls",
"schema=CALL");
/* Omitted: populate the tables with some data. */
}
ret = conn->open_session(conn, NULL, NULL, &session);
/*
* First query: a call arrives. In SQL:
*
* SELECT * FROM Customers WHERE phone=?
*
* Use the cust_phone index, lookup by phone number to fill the
* customer record. The cursor will have a key format of "S" for a
* string because the cust_phone index has a single column ("phone"),
* which is of type "S".
*
* The "with_pkey" option includes the primary key in the cursor's
* values, so the value format will be "rSSS".
*/
ret = session->open_cursor(session,
"index:cust_phone", "with_pkey", &cursor);
ret = cursor->set_key(cursor, "212-555-1000");
ret = cursor->search(cursor, &exact);
if (exact == 0)
cursor->get_value(cursor, &cust.id,
&cust.name, &cust.address, &cust.phone);
printf("Got customer record for %s\n", cust.name);
ret = cursor->close(cursor, NULL);
/*
* Next query: get the recent order history. In SQL:
*
* SELECT * FROM Calls WHERE cust_id=? ORDER BY call_date DESC LIMIT 3
*
* Use the call_cust_date index to find the matching calls. Since it is
* is in increasing order by date for a given customer, we want to start
* with the last record for the customer and work backwards.
*/
ret = session->open_cursor(session,
"index:call_cust_date(cust_id,call_type,notes)", NULL, &cursor);
ret = cursor->set_key(cursor, cust.id + 1, 0);
ret = cursor->search(cursor, &exact);
/* If we found a larger entry, go back one. */
if (exact > 0)
ret = cursor->prev(cursor);
count = 0;
while ((ret = cursor->get_value(cursor,
&call.cust_id, &call.call_type, &call.notes)) == 0 &&
call.cust_id == cust.id && count++ < 3) {
printf("Got call record on date %d: type %s: %s\n",
(int)call.call_date, call.call_type, call.notes);
ret = cursor->prev(cursor);
}
ret = conn->close(conn, NULL);
return (ret);
}

View File

@@ -20,9 +20,9 @@ int main()
WT_CURSOR *cursor;
const char *key, *value;
if ((ret = wiredtiger_open(home,
if ((ret = wiredtiger_open(home, NULL,
"create,cache_size=10000000", &conn)) != 0 ||
(ret = conn->open_session(conn, NULL, &session)) != 0)
(ret = conn->open_session(conn, NULL, NULL, &session)) != 0)
fprintf(stderr, "Error connecting to %s: %s\n",
home, wiredtiger_strerror(ret));
/* Note: further error checking omitted for clarity. */

View File

@@ -18,12 +18,12 @@ int main()
WT_SESSION *session;
/* Open a connection to the database, creating it if necessary. */
if ((ret = wiredtiger_open(home, "create", &conn)) != 0)
if ((ret = wiredtiger_open(home, NULL, "create", &conn)) != 0)
fprintf(stderr, "Error connecting to %s: %s\n",
home, wiredtiger_strerror(ret));
/* Open a session for the current thread's work. */
if ((ret = conn->open_session(conn, NULL, &session)) != 0)
if ((ret = conn->open_session(conn, NULL, NULL, &session)) != 0)
fprintf(stderr, "Error opening a session on %s: %s\n",
home, wiredtiger_strerror(ret));

View File

@@ -45,7 +45,6 @@ static WT_SCHEMA pop_schema = {
ARRAY_SIZE(pop_columns), /* Number of columns. */
pop_indices, /* Index descriptions. */
ARRAY_SIZE(pop_indices), /* Number of indices. */
0 /* Session cookie size. */
};
POP_RECORD pop_data[] = {
@@ -58,7 +57,7 @@ POP_RECORD pop_data[] = {
int main()
{
int is_new, ret;
int ret;
WT_CONNECTION *conn;
WT_SESSION *session;
WT_CURSOR *cursor;
@@ -66,19 +65,19 @@ int main()
const char *country;
wiredtiger_recno_t recno;
ret = wiredtiger_open(home, "create", &conn);
ret = wiredtiger_open(home, NULL, "create", &conn);
if (ret != 0)
fprintf(stderr, "Error connecting to %s: %s\n",
home, wiredtiger_strerror(ret));
/* Note: error checking omitted for clarity. */
if (conn->is_new) {
if (conn->is_new(conn)) {
ret = conn->add_schema(conn, "POP_RECORD", &pop_schema, NULL);
ret = session->create_table(session, "population",
"schema=POP_RECORD");
}
ret = conn->open_session(conn, NULL, &session);
ret = conn->open_session(conn, NULL, NULL, &session);
ret = session->open_cursor(session, "table:population", NULL, &cursor);
endp = pop_data + ARRAY_SIZE(pop_data);

View File

@@ -17,16 +17,15 @@ int main()
WT_CONNECTION *conn;
WT_SESSION *session;
WT_CURSOR *cursor;
WT_ITEM key, value;
wiredtiger_recno_t recno;
if ((ret = wiredtiger_open(home, "create", &conn)) != 0 ||
(ret = conn->open_session(conn, NULL, &session)) != 0)
if ((ret = wiredtiger_open(home, NULL, "create", &conn)) != 0 ||
(ret = conn->open_session(conn, NULL, NULL, &session)) != 0)
fprintf(stderr, "Error connecting to %s: %s\n",
home, wiredtiger_strerror(ret));
/* Note: further error checking omitted for clarity. */
if (conn->is_new) {
if (conn->is_new(conn)) {
/*
* If we created the database, create the sequence by opening a
* cursor on the sequence view and inserting a new record.

View File

@@ -20,8 +20,8 @@ int main()
const char *key;
uint64_t value;
if ((ret = wiredtiger_open(home, "create", &conn)) != 0 ||
(ret = conn->open_session(conn, NULL, &session)) != 0)
if ((ret = wiredtiger_open(home, NULL, "create", &conn)) != 0 ||
(ret = conn->open_session(conn, NULL, NULL, &session)) != 0)
fprintf(stderr, "Error connecting to %s: %s\n",
home, wiredtiger_strerror(ret));
/* Note: further error checking omitted for clarity. */

View File

@@ -15,6 +15,7 @@ struct WT_CONNECTION; typedef struct WT_CONNECTION WT_CONNECTION;
struct WT_COLUMN_INFO; typedef struct WT_COLUMN_INFO WT_COLUMN_INFO;
struct WT_CURSOR; typedef struct WT_CURSOR WT_CURSOR;
struct WT_CURSOR_FACTORY; typedef struct WT_CURSOR_FACTORY WT_CURSOR_FACTORY;
struct WT_ERROR_HANDLER; typedef struct WT_ERROR_HANDLER WT_ERROR_HANDLER;
struct WT_INDEX_INFO; typedef struct WT_INDEX_INFO WT_INDEX_INFO;
struct WT_ITEM; typedef struct WT_ITEM WT_ITEM;
struct WT_SCHEMA; typedef struct WT_SCHEMA WT_SCHEMA;
@@ -36,19 +37,18 @@ typedef uint64_t wiredtiger_recno_t;
*/
struct WT_ITEM {
/*!
* A pointer to the location in memory of the data item.
* The memory reference of the data item.
*
* For items returned by a WT_CURSOR, the pointer is only valid until
* the next operation on that cursor. Applications that need to keep
* an item across multiple cursor operations must make a copy.
* WiredTiger never copies data into the application's buffer.
*/
const void *data;
/*!
* The number of bytes in the data item.
*/
size_t size;
uint32_t size;
};
/*!
@@ -197,6 +197,20 @@ struct WT_CURSOR {
int __F(close)(WT_CURSOR *cursor, const char *config);
};
/*!
* The interface implemented by applications in order to handle errors.
*/
struct WT_ERROR_HANDLER {
/*! Callback to handle errors within the session. */
int (*handle_error)(WT_ERROR_HANDLER *handler, int err, const char *errmsg);
/*! Optional callback to retrieve buffered messages. */
int (*get_messages)(WT_ERROR_HANDLER *handler, const char **errmsgp);
/*! Optional callback to clear buffered messages. */
int (*clear_messages)(WT_ERROR_HANDLER *handler);
};
/*!
* All data operations are performed in the context of a WT_SESSION. This
* encapsulates the thread and transactional context of the operation.
@@ -209,9 +223,6 @@ struct WT_SESSION {
/*! The connection for this session. */
WT_CONNECTION *connection;
/*! Callback to handle errors within the session. */
int (*handle_error)(WT_SESSION *session, const char *err);
/*! Close the session.
*
* \param session the session handle
@@ -407,31 +418,6 @@ struct WT_SESSION {
* their operations.
*/
struct WT_CONNECTION {
/*! The home directory of the connection. */
const char *home;
/*! Did opening this handle create the database? */
int is_new;
/*! Close a connection.
*
* Any open sessions will be closed.
*
* \param connection the connection handle
* \configempty
* \errors
*/
int __F(close)(WT_CONNECTION *connection, const char *config);
/*! Open a session.
*
* \param connection the connection handle
* \configempty
* \param sessionp the new session handle
* \errors
*/
int __F(open_session)(WT_CONNECTION *connection, const char *config, WT_SESSION **sessionp);
/*! Register a new type of cursor.
*
* \param connection the connection handle
@@ -462,6 +448,32 @@ struct WT_CONNECTION {
* \errors
*/
int __F(add_schema)(WT_CONNECTION *connection, const char *name, WT_SCHEMA *schema, const char *config);
/*! Close a connection.
*
* Any open sessions will be closed.
*
* \param connection the connection handle
* \configempty
* \errors
*/
int __F(close)(WT_CONNECTION *connection, const char *config);
/*! The home directory of the connection. */
const char *__F(get_home)(WT_CONNECTION *connection);
/*! Did opening this handle create the database? */
int __F(is_new)(WT_CONNECTION *connection);
/*! Open a session.
*
* \param connection the connection handle
* \param errhandler An error handler. If <code>NULL</code>, the connection's error handler is used
* \configempty
* \param sessionp the new session handle
* \errors
*/
int __F(open_session)(WT_CONNECTION *connection, WT_ERROR_HANDLER *errhandler, const char *config, WT_SESSION **sessionp);
};
/*!
@@ -564,14 +576,12 @@ struct WT_SCHEMA {
/*! The number of indices for a table (zero for unindexed tables). */
int num_indices;
/*! Space to allocate for this schema in every WT_SESSION handle */
size_t cookie_size;
};
/*! Open a connection to a database.
*
* \param home The path to the database home directory
* \param errhandler An error handler. If <code>NULL</code>, a builtin error handler is installed that writes error messages to stderr
* \configstart
* \config{create,["0"] or "1",create the database if it does not exist}
* \config{exclusive,["0"] or "1",fail if the database already exists}
@@ -582,7 +592,7 @@ struct WT_SCHEMA {
* \param connectionp A pointer to the newly opened connection handle
* \errors
*/
int wiredtiger_open(const char *home, const char *config, WT_CONNECTION **connectionp);
int wiredtiger_open(const char *home, WT_ERROR_HANDLER *errhandler, const char *config, WT_CONNECTION **connectionp);
/*! Get information about an error as a string.
*
@@ -656,6 +666,14 @@ int wiredtiger_struct_size(const char *fmt, ...);
<tr><td>u</td><td>WT_ITEM</td><td>byte[]</td><td>string</td><td>variable</td></tr>
* </table>
*
* The <code>'S'</code> type is encoded as a C language string terminated by a NUL character.
*
* The <code>'u'</code> type is for raw byte arrays: if it appears at the end
* of a format string (including in the default <code>"u"</code> format for
* untyped tables), the size is not stored explicitly. When <code>'u'</code>
* appears within a format string, the size is stored as a 32-bit integer in
* the same byte order as the rest of the format string, followed by the data.
*
* \section pack_examples Packing Examples
*
* For example, the string <code>"iSh"</code> will pack a 32-bit integer

View File

@@ -32,7 +32,7 @@ def unpack(fmt, s):
result = ()
pfmt = tfmt
sizebytes = 0
for f in fmt:
for offset, f in enumerate(fmt):
if f.isdigit():
sizebytes += 1
# With a fixed size, everything is encoded as a string
@@ -54,10 +54,13 @@ def unpack(fmt, s):
result += (s[:l],)
s = s[l+1:]
if f == 'u':
l = struct.unpack_from(tfmt + 'l', s)[0]
s = s[struct.calcsize(tfmt + 'l'):]
result += (s[:l],)
s = s[l:]
if offset == len(fmt) - 1:
result += (s,)
else:
l = struct.unpack_from(tfmt + 'l', s)[0]
s = s[struct.calcsize(tfmt + 'l'):]
result += (s[:l],)
s = s[l:]
pfmt = tfmt
sizebytes = 0
@@ -70,7 +73,7 @@ def pack(fmt, *values):
if not fmt:
return ''
i = sizebytes = 0
for f in fmt:
for offset, f in enumerate(fmt):
if f == 'S':
# Note: this code is being careful about embedded NUL characters
if sizebytes == 0:
@@ -81,7 +84,7 @@ def pack(fmt, *values):
sizebytes = len(str(l))
f = 's'
elif f == 'u':
if sizebytes == 0:
if sizebytes == 0 and offset != len(fmt) - 1:
l = len(values[i])
pfmt += 'l' + str(l)
values = values[:i] + (l,) + values[i:]

View File

@@ -26,6 +26,7 @@ if len(sys.argv) <= 1 or sys.argv[1] == '--help':
print ' WT_HANDLE open(string home, string config)'
print ' WT_HANDLE open_session(WT_HANDLE connection, string config)'
print ' void close_connection(WT_HANDLE connection, string config)'
print ' bool is_new(WT_HANDLE connection)'
print ' void close_session(WT_HANDLE session, string config)'
print ' WT_CURSOR_HANDLE open_cursor(WT_HANDLE session, string uri, string config)'
print ' WT_CURSOR_HANDLE dup_cursor(WT_HANDLE session, WT_HANDLE cursor, string config)'
@@ -127,6 +128,12 @@ elif cmd == 'close_connection':
sys.exit(1)
pp.pprint(client.close_connection(eval(args[0]),args[1],))
elif cmd == 'is_new':
if len(args) != 1:
print 'is_new requires 1 args'
sys.exit(1)
pp.pprint(client.is_new(eval(args[0]),))
elif cmd == 'close_session':
if len(args) != 2:
print 'close_session requires 2 args'

View File

@@ -50,6 +50,13 @@ class Iface:
"""
pass
def is_new(self, connection):
"""
Parameters:
- connection
"""
pass
def close_session(self, session, config):
"""
Parameters:
@@ -384,6 +391,36 @@ class Client(Iface):
raise result.err
return
def is_new(self, connection):
"""
Parameters:
- connection
"""
self.send_is_new(connection)
return self.recv_is_new()
def send_is_new(self, connection):
self._oprot.writeMessageBegin('is_new', TMessageType.CALL, self._seqid)
args = is_new_args()
args.connection = connection
args.write(self._oprot)
self._oprot.writeMessageEnd()
self._oprot.trans.flush()
def recv_is_new(self, ):
(fname, mtype, rseqid) = self._iprot.readMessageBegin()
if mtype == TMessageType.EXCEPTION:
x = TApplicationException()
x.read(self._iprot)
self._iprot.readMessageEnd()
raise x
result = is_new_result()
result.read(self._iprot)
self._iprot.readMessageEnd()
if result.success != None:
return result.success
raise TApplicationException(TApplicationException.MISSING_RESULT, "is_new failed: unknown result");
def close_session(self, session, config):
"""
Parameters:
@@ -1088,6 +1125,7 @@ class Processor(Iface, TProcessor):
self._processMap["open"] = Processor.process_open
self._processMap["open_session"] = Processor.process_open_session
self._processMap["close_connection"] = Processor.process_close_connection
self._processMap["is_new"] = Processor.process_is_new
self._processMap["close_session"] = Processor.process_close_session
self._processMap["open_cursor"] = Processor.process_open_cursor
self._processMap["dup_cursor"] = Processor.process_dup_cursor
@@ -1189,6 +1227,17 @@ class Processor(Iface, TProcessor):
oprot.writeMessageEnd()
oprot.trans.flush()
def process_is_new(self, seqid, iprot, oprot):
args = is_new_args()
args.read(iprot)
iprot.readMessageEnd()
result = is_new_result()
result.success = self._handler.is_new(args.connection)
oprot.writeMessageBegin("is_new", TMessageType.REPLY, seqid)
result.write(oprot)
oprot.writeMessageEnd()
oprot.trans.flush()
def process_close_session(self, seqid, iprot, oprot):
args = close_session_args()
args.read(iprot)
@@ -2118,6 +2167,123 @@ class close_connection_result:
def __ne__(self, other):
return not (self == other)
class is_new_args:
"""
Attributes:
- connection
"""
thrift_spec = (
None, # 0
(1, TType.I32, 'connection', None, None, ), # 1
)
def __init__(self, connection=None,):
self.connection = connection
def read(self, iprot):
if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None and fastbinary is not None:
fastbinary.decode_binary(self, iprot.trans, (self.__class__, self.thrift_spec))
return
iprot.readStructBegin()
while True:
(fname, ftype, fid) = iprot.readFieldBegin()
if ftype == TType.STOP:
break
if fid == 1:
if ftype == TType.I32:
self.connection = iprot.readI32();
else:
iprot.skip(ftype)
else:
iprot.skip(ftype)
iprot.readFieldEnd()
iprot.readStructEnd()
def write(self, oprot):
if oprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and self.thrift_spec is not None and fastbinary is not None:
oprot.trans.write(fastbinary.encode_binary(self, (self.__class__, self.thrift_spec)))
return
oprot.writeStructBegin('is_new_args')
if self.connection != None:
oprot.writeFieldBegin('connection', TType.I32, 1)
oprot.writeI32(self.connection)
oprot.writeFieldEnd()
oprot.writeFieldStop()
oprot.writeStructEnd()
def validate(self):
return
def __repr__(self):
L = ['%s=%r' % (key, value)
for key, value in self.__dict__.iteritems()]
return '%s(%s)' % (self.__class__.__name__, ', '.join(L))
def __eq__(self, other):
return isinstance(other, self.__class__) and self.__dict__ == other.__dict__
def __ne__(self, other):
return not (self == other)
class is_new_result:
"""
Attributes:
- success
"""
thrift_spec = (
(0, TType.BOOL, 'success', None, None, ), # 0
)
def __init__(self, success=None,):
self.success = success
def read(self, iprot):
if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None and fastbinary is not None:
fastbinary.decode_binary(self, iprot.trans, (self.__class__, self.thrift_spec))
return
iprot.readStructBegin()
while True:
(fname, ftype, fid) = iprot.readFieldBegin()
if ftype == TType.STOP:
break
if fid == 0:
if ftype == TType.BOOL:
self.success = iprot.readBool();
else:
iprot.skip(ftype)
else:
iprot.skip(ftype)
iprot.readFieldEnd()
iprot.readStructEnd()
def write(self, oprot):
if oprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and self.thrift_spec is not None and fastbinary is not None:
oprot.trans.write(fastbinary.encode_binary(self, (self.__class__, self.thrift_spec)))
return
oprot.writeStructBegin('is_new_result')
if self.success != None:
oprot.writeFieldBegin('success', TType.BOOL, 0)
oprot.writeBool(self.success)
oprot.writeFieldEnd()
oprot.writeFieldStop()
oprot.writeStructEnd()
def validate(self):
return
def __repr__(self):
L = ['%s=%r' % (key, value)
for key, value in self.__dict__.iteritems()]
return '%s(%s)' % (self.__class__.__name__, ', '.join(L))
def __eq__(self, other):
return isinstance(other, self.__class__) and self.__dict__ == other.__dict__
def __ne__(self, other):
return not (self == other)
class close_session_args:
"""
Attributes:

View File

@@ -160,18 +160,26 @@ static int __session_checkpoint(WT_SESSION *session, const char *config)
}
static const char *__conn_get_home(WT_CONNECTION *conn)
{
return NULL;
}
static int __conn_is_new(WT_CONNECTION *conn)
{
return 0;
}
static int __conn_close(WT_CONNECTION *conn, const char *config)
{
printf("WT_CONNECTION->close\n");
free((char *)conn->home);
free(conn);
return 0;
}
static int __conn_open_session(WT_CONNECTION *connection, const char *config, WT_SESSION **sessionp)
static int __conn_open_session(WT_CONNECTION *connection, WT_ERROR_HANDLER *errhandler, const char *config, WT_SESSION **sessionp)
{
WT_SESSION stds = {
NULL,
NULL,
__session_close,
__session_open_cursor,
@@ -185,8 +193,6 @@ static int __conn_open_session(WT_CONNECTION *connection, const char *config, WT
__session_commit_transaction,
__session_rollback_transaction,
__session_checkpoint,
NULL,
NULL
};
WT_SESSION *s = (WT_SESSION *)malloc(sizeof(WT_SESSION));
@@ -205,7 +211,7 @@ static int __conn_add_cursor_factory(WT_CONNECTION *connection, const char *pref
return ENOTSUP;
}
static int __conn_add_extension(WT_CONNECTION *connection, const char *prefix, const char *path, const char *config)
static int __conn_add_extension(WT_CONNECTION *connection, const char *path, const char *config)
{
return ENOTSUP;
}
@@ -215,16 +221,16 @@ static int __conn_add_schema(WT_CONNECTION *connection, const char *name, WT_SCH
return ENOTSUP;
}
int wiredtiger_open(const char *home, const char *config, WT_CONNECTION **connectionp)
int wiredtiger_open(const char *home, WT_ERROR_HANDLER *errhandler, const char *config, WT_CONNECTION **connectionp)
{
WT_CONNECTION stdc = {
NULL,
0,
__conn_close,
__conn_open_session,
__conn_add_cursor_factory,
__conn_add_extension,
__conn_add_schema
__conn_add_schema,
__conn_close,
__conn_get_home,
__conn_is_new,
__conn_open_session
};
WT_CONNECTION *c = (WT_CONNECTION *)malloc(sizeof(WT_CONNECTION));
@@ -232,7 +238,7 @@ int wiredtiger_open(const char *home, const char *config, WT_CONNECTION **connec
if (c == NULL)
return ENOMEM;
*c = stdc;
c->home = strdup(home);
/* TODO: c->home = strdup(home); */
*connectionp = c;
return 0;
}