~ubuntu-branches/ubuntu/maverick/evolution-data-server/maverick-proposed

« back to all changes in this revision

Viewing changes to libdb/docs/ref/transapp/transapp.cs

  • Committer: Bazaar Package Importer
  • Author(s): Didier Roche
  • Date: 2010-05-17 17:02:06 UTC
  • mfrom: (1.1.79 upstream) (1.6.12 experimental)
  • Revision ID: james.westby@ubuntu.com-20100517170206-4ufr52vwrhh26yh0
Tags: 2.30.1-1ubuntu1
* Merge from debian experimental. Remaining change:
  (LP: #42199, #229669, #173703, #360344, #508494)
  + debian/control:
    - add Vcs-Bzr tag
    - don't use libgnome
    - Use Breaks instead of Conflicts against evolution 2.25 and earlier.
  + debian/evolution-data-server.install,
    debian/patches/45_libcamel_providers_version.patch:
    - use the upstream versioning, not a Debian-specific one 
  + debian/libedata-book1.2-dev.install, debian/libebackend-1.2-dev.install,
    debian/libcamel1.2-dev.install, debian/libedataserverui1.2-dev.install:
    - install html documentation
  + debian/rules:
    - don't build documentation it's shipped with the tarball

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
#include <sys/types.h>
2
 
#include <sys/stat.h>
3
 
 
4
 
#include <errno.h>
5
 
#include <pthread.h>
6
 
#include <stdarg.h>
7
 
#include <stdlib.h>
8
 
#include <string.h>
9
 
#include <unistd.h>
10
 
 
11
 
#include <db.h>
12
 
 
13
 
#define ENV_DIRECTORY   "TXNAPP"
14
 
 
15
 
void  add_cat(DB_ENV *, DB *, char *, ...);
16
 
void  add_color(DB_ENV *, DB *, char *, int);
17
 
void  add_fruit(DB_ENV *, DB *, char *, char *);
18
 
void *checkpoint_thread(void *);
19
 
void  log_archlist(DB_ENV *);
20
 
void *logfile_thread(void *);
21
 
void  db_open(DB_ENV *, DB **, char *, int);
22
 
void  env_dir_create(void);
23
 
void  env_open(DB_ENV **);
24
 
void  usage(void);
25
 
 
26
 
int
27
 
main(int argc, char *argv[])
28
 
{
29
 
        extern char *optarg;
30
 
        extern int optind;
31
 
        DB *db_cats, *db_color, *db_fruit;
32
 
        DB_ENV *dbenv;
33
 
        pthread_t ptid;
34
 
        int ch, ret;
35
 
 
36
 
        while ((ch = getopt(argc, argv, "")) != EOF)
37
 
                switch (ch) {
38
 
                case '?':
39
 
                default:
40
 
                        usage();
41
 
                }
42
 
        argc -= optind;
43
 
        argv += optind;
44
 
 
45
 
        env_dir_create();
46
 
        env_open(&dbenv);
47
 
 
48
 
        /* Start a checkpoint thread. */
49
 
        if ((ret = pthread_create(
50
 
            &ptid, NULL, checkpoint_thread, (void *)dbenv)) != 0) {
51
 
                fprintf(stderr,
52
 
                    "txnapp: failed spawning checkpoint thread: %s\n",
53
 
                    strerror(ret));
54
 
                exit (1);
55
 
        }
56
 
 
57
 
        /* Start a logfile removal thread. */
58
 
        if ((ret = pthread_create(
59
 
            &ptid, NULL, logfile_thread, (void *)dbenv)) != 0) {
60
 
                fprintf(stderr,
61
 
                    "txnapp: failed spawning log file removal thread: %s\n",
62
 
                    strerror(ret));
63
 
                exit (1);
64
 
        }
65
 
 
66
 
        /* Open database: Key is fruit class; Data is specific type. */
67
 
        db_open(dbenv, &db_fruit, "fruit", 0);
68
 
 
69
 
        /* Open database: Key is a color; Data is an integer. */
70
 
        db_open(dbenv, &db_color, "color", 0);
71
 
 
72
 
        /*
73
 
         * Open database:
74
 
         *      Key is a name; Data is: company name, address, cat breeds.
75
 
         */
76
 
        db_open(dbenv, &db_cats, "cats", 1);
77
 
 
78
 
        add_fruit(dbenv, db_fruit, "apple", "yellow delicious");
79
 
 
80
 
        add_color(dbenv, db_color, "blue", 0);
81
 
        add_color(dbenv, db_color, "blue", 3);
82
 
 
83
 
        add_cat(dbenv, db_cats,
84
 
                "Amy Adams",
85
 
                "Sleepycat Software",
86
 
                "394 E. Riding Dr., Carlisle, MA 01741, USA",
87
 
                "abyssinian",
88
 
                "bengal",
89
 
                "chartreaux",
90
 
                NULL);
91
 
 
92
 
        return (0);
93
 
}
94
 
 
95
 
void
96
 
env_dir_create()
97
 
{
98
 
        struct stat sb;
99
 
 
100
 
        /*
101
 
         * If the directory exists, we're done.  We do not further check
102
 
         * the type of the file, DB will fail appropriately if it's the
103
 
         * wrong type.
104
 
         */
105
 
        if (stat(ENV_DIRECTORY, &sb) == 0)
106
 
                return;
107
 
 
108
 
        /* Create the directory, read/write/access owner only. */
109
 
        if (mkdir(ENV_DIRECTORY, S_IRWXU) != 0) {
110
 
                fprintf(stderr,
111
 
                    "txnapp: mkdir: %s: %s\n", ENV_DIRECTORY, strerror(errno));
112
 
                exit (1);
113
 
        }
114
 
}
115
 
 
116
 
void
117
 
env_open(DB_ENV **dbenvp)
118
 
{
119
 
        DB_ENV *dbenv;
120
 
        int ret;
121
 
 
122
 
        /* Create the environment handle. */
123
 
        if ((ret = db_env_create(&dbenv, 0)) != 0) {
124
 
                fprintf(stderr,
125
 
                    "txnapp: db_env_create: %s\n", db_strerror(ret));
126
 
                exit (1);
127
 
        }
128
 
 
129
 
        /* Set up error handling. */
130
 
        dbenv->set_errpfx(dbenv, "txnapp");
131
 
 
132
 
        /* Do deadlock detection internally. */
133
 
        if ((ret = dbenv->set_lk_detect(dbenv, DB_LOCK_DEFAULT)) != 0) {
134
 
                dbenv->err(dbenv, ret, "set_lk_detect: DB_LOCK_DEFAULT");
135
 
                exit (1);
136
 
        }
137
 
 
138
 
        /*
139
 
         * Open a transactional environment:
140
 
         *      create if it doesn't exist
141
 
         *      free-threaded handle
142
 
         *      run recovery
143
 
         *      read/write owner only
144
 
         */
145
 
        if ((ret = dbenv->open(dbenv, ENV_DIRECTORY,
146
 
            DB_CREATE | DB_INIT_LOCK | DB_INIT_LOG |
147
 
            DB_INIT_MPOOL | DB_INIT_TXN | DB_RECOVER | DB_THREAD,
148
 
            S_IRUSR | S_IWUSR)) != 0) {
149
 
                dbenv->err(dbenv, ret, "dbenv->open: %s", ENV_DIRECTORY);
150
 
                exit (1);
151
 
        }
152
 
 
153
 
        *dbenvp = dbenv;
154
 
}
155
 
 
156
 
void *
157
 
checkpoint_thread(void *arg)
158
 
{
159
 
        DB_ENV *dbenv;
160
 
        int ret;
161
 
 
162
 
        dbenv = arg;
163
 
        dbenv->errx(dbenv, "Checkpoint thread: %lu", (u_long)pthread_self());
164
 
 
165
 
        /* Checkpoint once a minute. */
166
 
        for (;; sleep(60))
167
 
                if ((ret = dbenv->txn_checkpoint(dbenv, 0, 0, 0)) != 0) {
168
 
                        dbenv->err(dbenv, ret, "checkpoint thread");
169
 
                        exit (1);
170
 
                }
171
 
 
172
 
        /* NOTREACHED */
173
 
}
174
 
 
175
 
void *
176
 
logfile_thread(void *arg)
177
 
{
178
 
        DB_ENV *dbenv;
179
 
        int ret;
180
 
        char **begin, **list;
181
 
 
182
 
        dbenv = arg;
183
 
        dbenv->errx(dbenv,
184
 
            "Log file removal thread: %lu", (u_long)pthread_self());
185
 
 
186
 
        /* Check once every 5 minutes. */
187
 
        for (;; sleep(300)) {
188
 
                /* Get the list of log files. */
189
 
                if ((ret =
190
 
                    dbenv->log_archive(dbenv, &list, DB_ARCH_ABS)) != 0) {
191
 
                        dbenv->err(dbenv, ret, "DB_ENV->log_archive");
192
 
                        exit (1);
193
 
                }
194
 
 
195
 
                /* Remove the log files. */
196
 
                if (list != NULL) {
197
 
                        for (begin = list; *list != NULL; ++list)
198
 
                                if ((ret = remove(*list)) != 0) {
199
 
                                        dbenv->err(dbenv,
200
 
                                            ret, "remove %s", *list);
201
 
                                        exit (1);
202
 
                                }
203
 
                        free (begin);
204
 
                }
205
 
        }
206
 
        /* NOTREACHED */
207
 
}
208
 
 
209
 
void
210
 
log_archlist(DB_ENV *dbenv)
211
 
{
212
 
        int ret;
213
 
        char **begin, **list;
214
 
 
215
 
        /* Get the list of database files. */
216
 
        if ((ret = dbenv->log_archive(dbenv,
217
 
            &list, DB_ARCH_ABS | DB_ARCH_DATA)) != 0) {
218
 
                dbenv->err(dbenv, ret, "DB_ENV->log_archive: DB_ARCH_DATA");
219
 
                exit (1);
220
 
        }
221
 
        if (list != NULL) {
222
 
                for (begin = list; *list != NULL; ++list)
223
 
                        printf("database file: %s\n", *list);
224
 
                free (begin);
225
 
        }
226
 
 
227
 
        /* Get the list of log files. */
228
 
        if ((ret = dbenv->log_archive(dbenv,
229
 
            &list, DB_ARCH_ABS | DB_ARCH_LOG)) != 0) {
230
 
                dbenv->err(dbenv, ret, "DB_ENV->log_archive: DB_ARCH_LOG");
231
 
                exit (1);
232
 
        }
233
 
        if (list != NULL) {
234
 
                for (begin = list; *list != NULL; ++list)
235
 
                        printf("log file: %s\n", *list);
236
 
                free (begin);
237
 
        }
238
 
}
239
 
 
240
 
void
241
 
db_open(DB_ENV *dbenv, DB **dbp, char *name, int dups)
242
 
{
243
 
        DB *db;
244
 
        int ret;
245
 
 
246
 
        /* Create the database handle. */
247
 
        if ((ret = db_create(&db, dbenv, 0)) != 0) {
248
 
                dbenv->err(dbenv, ret, "db_create");
249
 
                exit (1);
250
 
        }
251
 
 
252
 
        /* Optionally, turn on duplicate data items. */
253
 
        if (dups && (ret = db->set_flags(db, DB_DUP)) != 0) {
254
 
                dbenv->err(dbenv, ret, "db->set_flags: DB_DUP");
255
 
                exit (1);
256
 
        }
257
 
 
258
 
        /*
259
 
         * Open a database in the environment:
260
 
         *      create if it doesn't exist
261
 
         *      free-threaded handle
262
 
         *      read/write owner only
263
 
         */
264
 
        if ((ret = db->open(db, NULL, name, NULL,
265
 
            DB_BTREE, DB_CREATE | DB_THREAD, S_IRUSR | S_IWUSR)) != 0) {
266
 
                dbenv->err(dbenv, ret, "db->open: %s", name);
267
 
                exit (1);
268
 
        }
269
 
 
270
 
        *dbp = db;
271
 
}
272
 
 
273
 
void
274
 
add_fruit(DB_ENV *dbenv, DB *db, char *fruit, char *name)
275
 
{
276
 
        DBT key, data;
277
 
        DB_TXN *tid;
278
 
        int ret;
279
 
 
280
 
        /* Initialization. */
281
 
        memset(&key, 0, sizeof(key));
282
 
        memset(&data, 0, sizeof(data));
283
 
        key.data = fruit;
284
 
        key.size = strlen(fruit);
285
 
        data.data = name;
286
 
        data.size = strlen(name);
287
 
 
288
 
        for (;;) {
289
 
                /* Begin the transaction. */
290
 
                if ((ret = dbenv->txn_begin(dbenv, NULL, &tid, 0)) != 0) {
291
 
                        dbenv->err(dbenv, ret, "DB_ENV->txn_begin");
292
 
                        exit (1);
293
 
                }
294
 
 
295
 
                /* Store the value. */
296
 
                switch (ret = db->put(db, tid, &key, &data, 0)) {
297
 
                case 0:
298
 
                        /* Success: commit the change. */
299
 
                        if ((ret = tid->commit(tid, 0)) != 0) {
300
 
                                dbenv->err(dbenv, ret, "DB_TXN->commit");
301
 
                                exit (1);
302
 
                        }
303
 
                        return;
304
 
                case DB_LOCK_DEADLOCK:
305
 
                        /* Deadlock: retry the operation. */
306
 
                        if ((ret = tid->abort(tid)) != 0) {
307
 
                                dbenv->err(dbenv, ret, "DB_TXN->abort");
308
 
                                exit (1);
309
 
                        }
310
 
                        break;
311
 
                default:
312
 
                        /* Error: run recovery. */
313
 
                        dbenv->err(dbenv, ret, "dbc->put: %s/%s", fruit, name);
314
 
                        exit (1);
315
 
                }
316
 
        }
317
 
}
318
 
 
319
 
void
320
 
add_color(DB_ENV *dbenv, DB *dbp, char *color, int increment)
321
 
{
322
 
        DBT key, data;
323
 
        DB_TXN *tid;
324
 
        int original, ret;
325
 
        char buf[64];
326
 
 
327
 
        /* Initialization. */
328
 
        memset(&key, 0, sizeof(key));
329
 
        key.data = color;
330
 
        key.size = strlen(color);
331
 
        memset(&data, 0, sizeof(data));
332
 
        data.flags = DB_DBT_MALLOC;
333
 
 
334
 
        for (;;) {
335
 
                /* Begin the transaction. */
336
 
                if ((ret = dbenv->txn_begin(dbenv, NULL, &tid, 0)) != 0) {
337
 
                        dbenv->err(dbenv, ret, "DB_ENV->txn_begin");
338
 
                        exit (1);
339
 
                }
340
 
 
341
 
                /*
342
 
                 * Get the key.  If it exists, we increment the value.  If it
343
 
                 * doesn't exist, we create it.
344
 
                 */
345
 
                switch (ret = dbp->get(dbp, tid, &key, &data, 0)) {
346
 
                case 0:
347
 
                        original = atoi(data.data);
348
 
                        break;
349
 
                case DB_LOCK_DEADLOCK:
350
 
                        /* Deadlock: retry the operation. */
351
 
                        if ((ret = tid->abort(tid)) != 0) {
352
 
                                dbenv->err(dbenv, ret, "DB_TXN->abort");
353
 
                                exit (1);
354
 
                        }
355
 
                        continue;
356
 
                case DB_NOTFOUND:
357
 
                        original = 0;
358
 
                        break;
359
 
                default:
360
 
                        /* Error: run recovery. */
361
 
                        dbenv->err(
362
 
                            dbenv, ret, "dbc->get: %s/%d", color, increment);
363
 
                        exit (1);
364
 
                }
365
 
                if (data.data != NULL)
366
 
                        free(data.data);
367
 
 
368
 
                /* Create the new data item. */
369
 
                (void)snprintf(buf, sizeof(buf), "%d", original + increment);
370
 
                data.data = buf;
371
 
                data.size = strlen(buf) + 1;
372
 
 
373
 
                /* Store the new value. */
374
 
                switch (ret = dbp->put(dbp, tid, &key, &data, 0)) {
375
 
                case 0:
376
 
                        /* Success: commit the change. */
377
 
                        if ((ret = tid->commit(tid, 0)) != 0) {
378
 
                                dbenv->err(dbenv, ret, "DB_TXN->commit");
379
 
                                exit (1);
380
 
                        }
381
 
                        return;
382
 
                case DB_LOCK_DEADLOCK:
383
 
                        /* Deadlock: retry the operation. */
384
 
                        if ((ret = tid->abort(tid)) != 0) {
385
 
                                dbenv->err(dbenv, ret, "DB_TXN->abort");
386
 
                                exit (1);
387
 
                        }
388
 
                        break;
389
 
                default:
390
 
                        /* Error: run recovery. */
391
 
                        dbenv->err(
392
 
                            dbenv, ret, "dbc->put: %s/%d", color, increment);
393
 
                        exit (1);
394
 
                }
395
 
        }
396
 
}
397
 
 
398
 
void
399
 
add_cat(DB_ENV *dbenv, DB *db, char *name, ...)
400
 
{
401
 
        va_list ap;
402
 
        DBC *dbc;
403
 
        DBT key, data;
404
 
        DB_TXN *tid;
405
 
        int ret;
406
 
        char *s;
407
 
 
408
 
        /* Initialization. */
409
 
        memset(&key, 0, sizeof(key));
410
 
        memset(&data, 0, sizeof(data));
411
 
        key.data = name;
412
 
        key.size = strlen(name);
413
 
 
414
 
retry:  /* Begin the transaction. */
415
 
        if ((ret = dbenv->txn_begin(dbenv, NULL, &tid, 0)) != 0) {
416
 
                dbenv->err(dbenv, ret, "DB_ENV->txn_begin");
417
 
                exit (1);
418
 
        }
419
 
 
420
 
        /* Delete any previously existing item. */
421
 
        switch (ret = db->del(db, tid, &key, 0)) {
422
 
        case 0:
423
 
        case DB_NOTFOUND:
424
 
                break;
425
 
        case DB_LOCK_DEADLOCK:
426
 
                /* Deadlock: retry the operation. */
427
 
                if ((ret = tid->abort(tid)) != 0) {
428
 
                        dbenv->err(dbenv, ret, "DB_TXN->abort");
429
 
                        exit (1);
430
 
                }
431
 
                goto retry;
432
 
        default:
433
 
                dbenv->err(dbenv, ret, "db->del: %s", name);
434
 
                exit (1);
435
 
        }
436
 
 
437
 
        /* Create a cursor. */
438
 
        if ((ret = db->cursor(db, tid, &dbc, 0)) != 0) {
439
 
                dbenv->err(dbenv, ret, "db->cursor");
440
 
                exit (1);
441
 
        }
442
 
 
443
 
        /* Append the items, in order. */
444
 
        va_start(ap, name);
445
 
        while ((s = va_arg(ap, char *)) != NULL) {
446
 
                data.data = s;
447
 
                data.size = strlen(s);
448
 
                switch (ret = dbc->c_put(dbc, &key, &data, DB_KEYLAST)) {
449
 
                case 0:
450
 
                        break;
451
 
                case DB_LOCK_DEADLOCK:
452
 
                        va_end(ap);
453
 
 
454
 
                        /* Deadlock: retry the operation. */
455
 
                        if ((ret = dbc->c_close(dbc)) != 0) {
456
 
                                dbenv->err(
457
 
                                    dbenv, ret, "dbc->c_close");
458
 
                                exit (1);
459
 
                        }
460
 
                        if ((ret = tid->abort(tid)) != 0) {
461
 
                                dbenv->err(dbenv, ret, "DB_TXN->abort");
462
 
                                exit (1);
463
 
                        }
464
 
                        goto retry;
465
 
                default:
466
 
                        /* Error: run recovery. */
467
 
                        dbenv->err(dbenv, ret, "dbc->put: %s/%s", name, s);
468
 
                        exit (1);
469
 
                }
470
 
        }
471
 
        va_end(ap);
472
 
 
473
 
        /* Success: commit the change. */
474
 
        if ((ret = dbc->c_close(dbc)) != 0) {
475
 
                dbenv->err(dbenv, ret, "dbc->c_close");
476
 
                exit (1);
477
 
        }
478
 
        if ((ret = tid->commit(tid, 0)) != 0) {
479
 
                dbenv->err(dbenv, ret, "DB_TXN->commit");
480
 
                exit (1);
481
 
        }
482
 
}
483
 
 
484
 
void
485
 
usage()
486
 
{
487
 
        (void)fprintf(stderr, "usage: txnapp\n");
488
 
        exit(1);
489
 
}