upscaledb  2.2.1
env1.c
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2005-2016 Christoph Rupp (chris@crupp.de).
3  * All Rights Reserved.
4  *
5  * This program is free software: you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation, either version 3 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU General Public License for more details.
14  *
15  * See the file COPYING for License information.
16  */
17 
23 #include <stdio.h>
24 #include <string.h>
25 #include <stdlib.h> /* for exit() */
26 #include <ups/upscaledb.h>
27 
28 void
29 error(const char *foo, ups_status_t st) {
30  printf("%s() returned error %d: %s\n", foo, st, ups_strerror(st));
31  exit(-1);
32 }
33 
34 #define MAX_DBS 2
35 
36 #define DBNAME_CUSTOMER 1
37 #define DBNAME_ORDER 2
38 
39 #define MAX_CUSTOMERS 4
40 #define MAX_ORDERS 8
41 
42 /* A structure for the "customer" database */
43 typedef struct {
44  uint32_t id; /* customer id */
45  char name[32]; /* customer name */
46  /* ... additional information could follow here */
47 } customer_t;
48 
49 /* A structure for the "orders" database */
50 typedef struct {
51  uint32_t id; /* order id */
52  uint32_t customer_id; /* customer id */
53  char assignee[32]; /* assigned to whom? */
54  /* ... additional information could follow here */
55 } order_t;
56 
57 int
58 main(int argc, char **argv) {
59  int i;
60  ups_status_t st; /* status variable */
61  ups_db_t *db[MAX_DBS]; /* upscaledb database objects */
62  ups_env_t *env; /* upscaledb environment */
63  ups_cursor_t *cursor[MAX_DBS]; /* a cursor for each database */
64 
65  ups_key_t key = {0};
66  ups_key_t cust_key = {0};
67  ups_key_t ord_key = {0};
68  ups_record_t record = {0};
69  ups_record_t cust_record = {0};
70  ups_record_t ord_record = {0};
71 
72  ups_parameter_t params[] = {
74  {0, }
75  };
76 
77  customer_t customers[MAX_CUSTOMERS] = {
78  { 1, "Alan Antonov Corp." },
79  { 2, "Barry Broke Inc." },
80  { 3, "Carl Caesar Lat." },
81  { 4, "Doris Dove Brd." }
82  };
83 
84  order_t orders[MAX_ORDERS] = {
85  { 1, 1, "Joe" },
86  { 2, 1, "Tom" },
87  { 3, 3, "Joe" },
88  { 4, 4, "Tom" },
89  { 5, 3, "Ben" },
90  { 6, 3, "Ben" },
91  { 7, 4, "Chris" },
92  { 8, 1, "Ben" }
93  };
94 
95  /* Now create a new upscaledb Environment */
96  st = ups_env_create(&env, "test.db", 0, 0664, 0);
97  if (st != UPS_SUCCESS)
98  error("ups_env_create", st);
99 
100  /*
101  * Then create the two Databases in this Environment; each Database
102  * has a name - the first is our "customer" Database, the second
103  * is for the "orders"
104  *
105  * All database keys are uint32_t types.
106  */
107  st = ups_env_create_db(env, &db[0], DBNAME_CUSTOMER, 0, &params[0]);
108  if (st != UPS_SUCCESS)
109  error("ups_env_create_db (customer)", st);
110  st = ups_env_create_db(env, &db[1], DBNAME_ORDER, 0, &params[0]);
111  if (st != UPS_SUCCESS)
112  error("ups_env_create_db (order)", st);
113 
114  /* Create a Cursor for each Database */
115  for (i = 0; i < MAX_DBS; i++) {
116  st = ups_cursor_create(&cursor[i], db[i], 0, 0);
117  if (st != UPS_SUCCESS) {
118  printf("ups_cursor_create() failed with error %d\n", st);
119  return (-1);
120  }
121  }
122 
123  /* Insert a few customers in the first database */
124  for (i = 0; i < MAX_CUSTOMERS; i++) {
125  key.size = sizeof(int);
126  key.data = &customers[i].id;
127 
128  record.size = sizeof(customer_t);
129  record.data = &customers[i];
130 
131  st = ups_db_insert(db[0], 0, &key, &record, 0);
132  if (st != UPS_SUCCESS)
133  error("ups_db_insert (customer)", st);
134  }
135 
136  /* And now the orders in the second database */
137  for (i = 0; i < MAX_ORDERS; i++) {
138  key.size = sizeof(int);
139  key.data = &orders[i].id;
140 
141  record.size = sizeof(order_t);
142  record.data = &orders[i];
143 
144  st = ups_db_insert(db[1], 0, &key, &record, 0);
145  if (st != UPS_SUCCESS)
146  error("ups_db_insert (order)", st);
147  }
148 
149  /*
150  * To demonstrate even more functions: close all objects, then
151  * re-open the environment and the two databases.
152  *
153  * Note that ups_env_close automatically calls ups_db_close on all
154  * databases.
155  */
156  for (i = 0; i < MAX_DBS; i++) {
157  st = ups_cursor_close(cursor[i]);
158  if (st != UPS_SUCCESS)
159  error("ups_cursor_close", st);
160  }
161  st = ups_env_close(env, 0);
162  if (st != UPS_SUCCESS)
163  error("ups_env_close", st);
164 
165  /* Now reopen the environment and the databases */
166  st = ups_env_open(&env, "test.db", 0, 0);
167  if (st != UPS_SUCCESS)
168  error("ups_env_open", st);
169  st = ups_env_open_db(env, &db[0], DBNAME_CUSTOMER, 0, 0);
170  if (st != UPS_SUCCESS)
171  error("ups_env_open_db (customer)", st);
172  st = ups_env_open_db(env, &db[1], DBNAME_ORDER, 0, 0);
173  if (st != UPS_SUCCESS)
174  error("ups_env_open_db (order)", st);
175 
176  /* Re-create a cursor for each database */
177  for (i = 0; i < MAX_DBS; i++) {
178  st = ups_cursor_create(&cursor[i], db[i], 0, 0);
179  if (st != UPS_SUCCESS) {
180  printf("ups_cursor_create() failed with error %d\n", st);
181  return (-1);
182  }
183  }
184 
185  /*
186  * Now start the query - we want to dump each customer with his
187  * orders
188  *
189  * We have a loop with two cursors - the first cursor looping over
190  * the database with customers, the second loops over the orders.
191  */
192  while (1) {
193  customer_t *customer;
194 
195  st = ups_cursor_move(cursor[0], &cust_key, &cust_record,
197  if (st != UPS_SUCCESS) {
198  /* reached end of the database? */
199  if (st == UPS_KEY_NOT_FOUND)
200  break;
201  else
202  error("ups_cursor_next(customer)", st);
203  }
204 
205  customer = (customer_t *)cust_record.data;
206 
207  /* print the customer id and name */
208  printf("customer %d ('%s')\n", customer->id, customer->name);
209 
210  /*
211  * The inner loop prints all orders of this customer. Move the
212  * cursor to the first entry.
213  */
214  st = ups_cursor_move(cursor[1], &ord_key, &ord_record,
216  if (st != UPS_SUCCESS) {
217  /* reached end of the database? */
218  if (st == UPS_KEY_NOT_FOUND)
219  continue;
220  else
221  error("ups_cursor_next(order)", st);
222  }
223 
224  do {
225  order_t *order = (order_t *)ord_record.data;
226 
227  /* print this order, if it belongs to the current customer */
228  if (order->customer_id == customer->id)
229  printf(" order: %d (assigned to %s)\n",
230  order->id, order->assignee);
231 
232  st = ups_cursor_move(cursor[1], &ord_key,
233  &ord_record, UPS_CURSOR_NEXT);
234  if (st != UPS_SUCCESS) {
235  /* reached end of the database? */
236  if (st == UPS_KEY_NOT_FOUND)
237  break;
238  else
239  error("ups_cursor_next(order)", st);
240  }
241  } while (1);
242  }
243 
244  /*
245  * Now close the environment handle; the flag UPS_AUTO_CLEANUP will
246  * automatically close all databases and cursors
247  */
248  st = ups_env_close(env, UPS_AUTO_CLEANUP);
249  if (st != UPS_SUCCESS)
250  error("ups_env_close", st);
251 
252  printf("success!\n");
253  return (0);
254 }
255 
UPS_EXPORT ups_status_t UPS_CALLCONV ups_env_open(ups_env_t **env, const char *filename, uint32_t flags, const ups_parameter_t *param)
UPS_EXPORT const char *UPS_CALLCONV ups_strerror(ups_status_t status)
#define DBNAME_CUSTOMER
Definition: env1.c:36
UPS_EXPORT ups_status_t UPS_CALLCONV ups_env_close(ups_env_t *env, uint32_t flags)
int main(int argc, char **argv)
Definition: env1.c:58
#define MAX_DBS
Definition: env1.c:34
UPS_EXPORT ups_status_t UPS_CALLCONV ups_db_insert(ups_db_t *db, ups_txn_t *txn, ups_key_t *key, ups_record_t *record, uint32_t flags)
#define UPS_TYPE_UINT32
Definition: upscaledb.h:322
UPS_EXPORT ups_status_t UPS_CALLCONV ups_cursor_move(ups_cursor_t *cursor, ups_key_t *key, ups_record_t *record, uint32_t flags)
char assignee[32]
Definition: env1.c:53
unsigned int uint32_t
Definition: msstdint.h:85
Include file for upscaledb embedded database.
uint16_t size
Definition: upscaledb.h:255
char name[32]
Definition: env1.c:45
uint32_t id
Definition: env1.c:44
struct ups_db_t ups_db_t
Definition: upscaledb.h:156
#define UPS_CURSOR_NEXT
Definition: upscaledb.h:2051
#define MAX_ORDERS
Definition: env1.c:40
struct ups_cursor_t ups_cursor_t
Definition: upscaledb.h:177
#define MAX_CUSTOMERS
Definition: env1.c:39
#define UPS_AUTO_CLEANUP
Definition: upscaledb.h:1883
UPS_EXPORT ups_status_t UPS_CALLCONV ups_cursor_close(ups_cursor_t *cursor)
void error(const char *foo, ups_status_t st)
Definition: env1.c:29
#define UPS_SUCCESS
Definition: upscaledb.h:341
UPS_EXPORT ups_status_t UPS_CALLCONV ups_env_open_db(ups_env_t *env, ups_db_t **db, uint16_t name, uint32_t flags, const ups_parameter_t *params)
UPS_EXPORT ups_status_t UPS_CALLCONV ups_env_create(ups_env_t **env, const char *filename, uint32_t flags, uint32_t mode, const ups_parameter_t *param)
void * data
Definition: upscaledb.h:258
#define UPS_CURSOR_FIRST
Definition: upscaledb.h:2045
uint32_t customer_id
Definition: env1.c:52
Definition: env1.c:50
#define DBNAME_ORDER
Definition: env1.c:37
void * data
Definition: upscaledb.h:207
uint32_t size
Definition: upscaledb.h:204
int ups_status_t
Definition: types.h:139
UPS_EXPORT ups_status_t UPS_CALLCONV ups_env_create_db(ups_env_t *env, ups_db_t **db, uint16_t name, uint32_t flags, const ups_parameter_t *params)
#define UPS_PARAM_KEY_TYPE
Definition: upscaledb.h:1710
uint32_t id
Definition: env1.c:51
UPS_EXPORT ups_status_t UPS_CALLCONV ups_cursor_create(ups_cursor_t **cursor, ups_db_t *db, ups_txn_t *txn, uint32_t flags)
#define UPS_KEY_NOT_FOUND
Definition: upscaledb.h:361
struct ups_env_t ups_env_t
Definition: upscaledb.h:165