1<!--$Id: cursor.so,v 1.12 2004/03/05 21:47:36 bostic Exp $--> 2<!--Copyright (c) 1997,2008 Oracle. All rights reserved.--> 3<!--See the file LICENSE for redistribution information.--> 4<html> 5<head> 6<title>Berkeley DB Reference Guide: Transactional cursors</title> 7<meta name="description" content="Berkeley DB: An embedded database programmatic toolkit."> 8<meta name="keywords" content="embedded,database,programmatic,toolkit,btree,hash,hashing,transaction,transactions,locking,logging,access method,access methods,Java,C,C++"> 9</head> 10<body bgcolor=white> 11<table width="100%"><tr valign=top> 12<td><b><dl><dt>Berkeley DB Reference Guide:<dd>Berkeley DB Transactional Data Store Applications</dl></b></td> 13<td align=right><a href="../transapp/read.html"><img src="../../images/prev.gif" alt="Prev"></a><a href="../toc.html"><img src="../../images/ref.gif" alt="Ref"></a><a href="../transapp/nested.html"><img src="../../images/next.gif" alt="Next"></a> 14</td></tr></table> 15<p align=center><b>Transactional cursors</b></p> 16<p>Berkeley DB cursors may be used inside a transaction, exactly as any other 17<a href="../../api_c/db_class.html">DB</a> method. The enclosing transaction ID must be specified when 18the cursor is created, but it does not then need to be further specified 19on operations performed using the cursor. One important point to 20remember is that a cursor <b>must be closed</b> before the enclosing 21transaction is committed or aborted.</p> 22<p>The following code fragment uses a cursor to store a new key in the cats 23database with four associated data items. The key is a name. The data 24items are a company name and a list of the breeds of cat owned. Each 25of the data entries is stored as a duplicate data item. In this 26example, transactions are necessary to ensure that either all or none 27of the data items appear in case of system or application failure.</p> 28<blockquote><pre>int 29main(int argc, char *argv) 30{ 31 extern int optind; 32 DB *db_cats, *db_color, *db_fruit; 33 DB_ENV *dbenv; 34 int ch; 35<p> 36 while ((ch = getopt(argc, argv, "")) != EOF) 37 switch (ch) { 38 case '?': 39 default: 40 usage(); 41 } 42 argc -= optind; 43 argv += optind; 44<p> 45 env_dir_create(); 46 env_open(&dbenv); 47<p> 48 /* Open database: Key is fruit class; Data is specific type. */ 49 db_open(dbenv, &db_fruit, "fruit", 0); 50<p> 51 /* Open database: Key is a color; Data is an integer. */ 52 db_open(dbenv, &db_color, "color", 0); 53<p> 54 /* 55 * Open database: 56 * Key is a name; Data is: company name, cat breeds. 57 */ 58 db_open(dbenv, &db_cats, "cats", 1); 59<p> 60 add_fruit(dbenv, db_fruit, "apple", "yellow delicious"); 61<p> 62 add_color(dbenv, db_color, "blue", 0); 63 add_color(dbenv, db_color, "blue", 3); 64<p> 65<b> add_cat(dbenv, db_cats, 66 "Amy Adams", 67 "Oracle", 68 "abyssinian", 69 "bengal", 70 "chartreaux", 71 NULL);</b> 72<p> 73 return (0); 74} 75<p> 76<b>int 77add_cat(DB_ENV *dbenv, DB *db, char *name, ...) 78{ 79 va_list ap; 80 DBC *dbc; 81 DBT key, data; 82 DB_TXN *tid; 83 int fail, ret, t_ret; 84 char *s; 85<p> 86 /* Initialization. */ 87 fail = 0; 88<p> 89 memset(&key, 0, sizeof(key)); 90 memset(&data, 0, sizeof(data)); 91 key.data = name; 92 key.size = strlen(name); 93<p> 94retry: /* Begin the transaction. */ 95 if ((ret = dbenv->txn_begin(dbenv, NULL, &tid, 0)) != 0) { 96 dbenv->err(dbenv, ret, "DB_ENV->txn_begin"); 97 exit (1); 98 } 99<p> 100 /* Delete any previously existing item. */ 101 switch (ret = db->del(db, tid, &key, 0)) { 102 case 0: 103 case DB_NOTFOUND: 104 break; 105 case DB_LOCK_DEADLOCK: 106 default: 107 /* Retry the operation. */ 108 if ((t_ret = tid->abort(tid)) != 0) { 109 dbenv->err(dbenv, t_ret, "DB_TXN->abort"); 110 exit (1); 111 } 112 if (fail++ == MAXIMUM_RETRY) 113 return (ret); 114 goto retry; 115 } 116<p> 117 /* Create a cursor. */ 118 if ((ret = db->cursor(db, tid, &dbc, 0)) != 0) { 119 dbenv->err(dbenv, ret, "db->cursor"); 120 exit (1); 121 } 122<p> 123 /* Append the items, in order. */ 124 va_start(ap, name); 125 while ((s = va_arg(ap, char *)) != NULL) { 126 data.data = s; 127 data.size = strlen(s); 128 switch (ret = dbc->c_put(dbc, &key, &data, DB_KEYLAST)) { 129 case 0: 130 break; 131 case DB_LOCK_DEADLOCK: 132 default: 133 va_end(ap); 134<p> 135 /* Retry the operation. */ 136 if ((t_ret = dbc->c_close(dbc)) != 0) { 137 dbenv->err( 138 dbenv, t_ret, "dbc->c_close"); 139 exit (1); 140 } 141 if ((t_ret = tid->abort(tid)) != 0) { 142 dbenv->err(dbenv, t_ret, "DB_TXN->abort"); 143 exit (1); 144 } 145 if (fail++ == MAXIMUM_RETRY) 146 return (ret); 147 goto retry; 148 } 149 } 150 va_end(ap); 151<p> 152 /* Success: commit the change. */ 153 if ((ret = dbc->c_close(dbc)) != 0) { 154 dbenv->err(dbenv, ret, "dbc->c_close"); 155 exit (1); 156 } 157 if ((ret = tid->commit(tid, 0)) != 0) { 158 dbenv->err(dbenv, ret, "DB_TXN->commit"); 159 exit (1); 160 } 161 return (0); 162}</b></pre></blockquote> 163<table width="100%"><tr><td><br></td><td align=right><a href="../transapp/read.html"><img src="../../images/prev.gif" alt="Prev"></a><a href="../toc.html"><img src="../../images/ref.gif" alt="Ref"></a><a href="../transapp/nested.html"><img src="../../images/next.gif" alt="Next"></a> 164</td></tr></table> 165<p><font size=1>Copyright (c) 1996,2008 Oracle. All rights reserved.</font> 166</body> 167</html> 168