~ubuntu-branches/ubuntu/quantal/ceph/quantal

« back to all changes in this revision

Viewing changes to doc/api/librados.rst

  • Committer: Package Import Robot
  • Author(s): James Page
  • Date: 2012-07-16 09:56:24 UTC
  • mfrom: (0.3.11)
  • mto: This revision was merged to the branch mainline in revision 17.
  • Revision ID: package-import@ubuntu.com-20120716095624-azr2w4hbhei1rxmx
Tags: upstream-0.48
ImportĀ upstreamĀ versionĀ 0.48

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
==============
 
2
 Librados (C)
 
3
==============
 
4
 
 
5
.. highlight:: c
 
6
 
 
7
`Librados` provides low-level access to the RADOS service. For an
 
8
overview of RADOS, see :doc:`/architecture`.
 
9
 
 
10
 
 
11
Example: connecting and writing an object
 
12
=========================================
 
13
 
 
14
To use `Librados`, you instantiate a :c:type:`rados_t` variable (a cluster handle) and
 
15
call :c:func:`rados_create()` with a pointer to it::
 
16
 
 
17
        int err;
 
18
        rados_t cluster;
 
19
 
 
20
        err = rados_create(&cluster, NULL);
 
21
        if (err < 0) {
 
22
                fprintf(stderr, "%s: cannot create a cluster handle: %s\n", argv[0], strerror(-err));
 
23
                exit(1);
 
24
        }
 
25
 
 
26
Then you configure your :c:type:`rados_t` to connect to your cluster,
 
27
either by setting individual values (:c:func:`rados_conf_set()`),
 
28
using a configuration file (:c:func:`rados_conf_read_file()`), using
 
29
command line options (:c:func:`rados_conf_parse_argv`), or an
 
30
environment variable (:c:func:`rados_conf_parse_env()`)::
 
31
 
 
32
        err = rados_conf_read_file(cluster, "/path/to/myceph.conf");
 
33
        if (err < 0) {
 
34
                fprintf(stderr, "%s: cannot read config file: %s\n", argv[0], strerror(-err));
 
35
                exit(1);
 
36
        }
 
37
 
 
38
Once the cluster handle is configured, you can connect to the cluster with :c:func:`rados_connect()`::
 
39
 
 
40
        err = rados_connect(cluster);
 
41
        if (err < 0) {
 
42
                fprintf(stderr, "%s: cannot connect to cluster: %s\n", argv[0], strerror(-err));
 
43
                exit(1);
 
44
        }
 
45
 
 
46
Then you open an "IO context", a :c:type:`rados_ioctx_t`, with :c:func:`rados_ioctx_create()`::
 
47
 
 
48
        rados_ioctx_t io;
 
49
        char *poolname = "mypool";
 
50
 
 
51
        err = rados_ioctx_create(cluster, poolname, &io);
 
52
        if (err < 0) {
 
53
                fprintf(stderr, "%s: cannot open rados pool %s: %s\n", argv[0], poolname, strerror(-err));
 
54
                rados_shutdown(cluster);
 
55
                exit(1);
 
56
        }
 
57
 
 
58
Note that the pool you try to access must exist.
 
59
 
 
60
Then you can use the RADOS data manipulation functions, for example
 
61
write into an object called ``greeting`` with
 
62
:c:func:`rados_write_full()`::
 
63
 
 
64
        err = rados_write_full(io, "greeting", "hello", 5);
 
65
        if (err < 0) {
 
66
                fprintf(stderr, "%s: cannot write pool %s: %s\n", argv[0], poolname, strerror(-err));
 
67
                rados_ioctx_destroy(io);
 
68
                rados_shutdown(cluster);
 
69
                exit(1);
 
70
        }
 
71
 
 
72
In the end, you'll want to close your IO context and connection to RADOS with :c:func:`rados_ioctx_destroy()` and :c:func:`rados_shutdown()`::
 
73
 
 
74
        rados_ioctx_destroy(io);
 
75
        rados_shutdown(cluster);
 
76
 
 
77
 
 
78
Asychronous IO
 
79
==============
 
80
 
 
81
When doing lots of IO, you often don't need to wait for one operation
 
82
to complete before starting the next one. `Librados` provides
 
83
asynchronous versions of several operations:
 
84
 
 
85
* :c:func:`rados_aio_write`
 
86
* :c:func:`rados_aio_append`
 
87
* :c:func:`rados_aio_write_full`
 
88
* :c:func:`rados_aio_read`
 
89
 
 
90
For each operation, you must first create a
 
91
:c:type:`rados_completion_t` that represents what to do when the
 
92
operation is safe or complete by calling
 
93
:c:func:`rados_aio_create_completion`. If you don't need anything
 
94
special to happen, you can pass NULL::
 
95
 
 
96
        rados_completion_t comp;
 
97
        err = rados_aio_create_completion(NULL, NULL, NULL, &comp);
 
98
        if (err < 0) {
 
99
                fprintf(stderr, "%s: could not create aio completion: %s\n", argv[0], strerror(-err));
 
100
                rados_ioctx_destroy(io);
 
101
                rados_shutdown(cluster);
 
102
                exit(1);
 
103
        }
 
104
 
 
105
Now you can call any of the aio operations, and wait for it to
 
106
be in memory or on disk on all replicas::
 
107
 
 
108
        err = rados_aio_write(io, "foo", comp, "bar", 3, 0);
 
109
        if (err < 0) {
 
110
                fprintf(stderr, "%s: could not schedule aio write: %s\n", argv[0], strerror(-err));
 
111
                rados_aio_release(comp);
 
112
                rados_ioctx_destroy(io);
 
113
                rados_shutdown(cluster);
 
114
                exit(1);
 
115
        }
 
116
        rados_wait_for_complete(comp); // in memory
 
117
        rados_wait_for_safe(comp); // on disk
 
118
 
 
119
Finally, we need to free the memory used by the completion with :c:func:`rados_aio_release`::
 
120
 
 
121
        rados_aio_release(comp);
 
122
 
 
123
You can use the callbacks to tell your application when writes are
 
124
durable, or when read buffers are full. For example, if you wanted to
 
125
measure the latency of each operation when appending to several
 
126
objects, you could schedule several writes and store the ack and
 
127
commit time in the corresponding callback, then wait for all of them
 
128
to complete using :c:func:`rados_aio_flush` before analyzing the
 
129
latencies::
 
130
 
 
131
        typedef struct {
 
132
                struct timeval start;
 
133
                struct timeval ack_end;
 
134
                struct timeval commit_end;
 
135
        } req_duration;
 
136
 
 
137
        void ack_callback(rados_completion_t comp, void *arg) {
 
138
                req_duration *dur = (req_duration *) arg;
 
139
                gettimeofday(&dur->ack_end, NULL);
 
140
        }
 
141
 
 
142
        void commit_callback(rados_completion_t comp, void *arg) {
 
143
                req_duration *dur = (req_duration *) arg;
 
144
                gettimeofday(&dur->commit_end, NULL);
 
145
        }
 
146
 
 
147
        int output_append_latency(rados_ioctx_t io, const char *data, size_t len, size_t num_writes) {
 
148
                req_duration times[num_writes];
 
149
                rados_completion_t comps[num_writes];
 
150
                for (size_t i = 0; i < num_writes; ++i) {
 
151
                        gettimeofday(&times[i].start, NULL);
 
152
                        int err = rados_aio_create_completion((void*) &times[i], ack_callback, commit_callback, &comps[i]);
 
153
                        if (err < 0) {
 
154
                                fprintf(stderr, "Error creating rados completion: %s\n", strerror(-err));
 
155
                                return err;
 
156
                        }
 
157
                        char obj_name[100];
 
158
                        snprintf(obj_name, sizeof(obj_name), "foo%ld", (unsigned long)i);
 
159
                        err = rados_aio_append(io, obj_name, comps[i], data, len);
 
160
                        if (err < 0) {
 
161
                                fprintf(stderr, "Error from rados_aio_append: %s", strerror(-err));
 
162
                                return err;
 
163
                        }
 
164
                }
 
165
                // wait until all requests finish *and* the callbacks complete
 
166
                rados_aio_flush(io);
 
167
                // the latencies can now be analyzed
 
168
                printf("Request # | Ack latency (s) | Commit latency (s)\n");
 
169
                for (size_t i = 0; i < num_writes; ++i) {
 
170
                        // don't forget to free the completions
 
171
                        rados_aio_release(comps[i]);
 
172
                        struct timeval ack_lat, commit_lat;
 
173
                        timersub(&times[i].ack_end, &times[i].start, &ack_lat);
 
174
                        timersub(&times[i].commit_end, &times[i].start, &commit_lat);
 
175
                        printf("%9ld | %8ld.%06ld | %10ld.%06ld\n", (unsigned long) i, ack_lat.tv_sec, ack_lat.tv_usec, commit_lat.tv_sec, commit_lat.tv_usec);
 
176
                }
 
177
                return 0;
 
178
        }
 
179
 
 
180
Note that all the :c:type:`rados_completion_t` must be freed with :c:func:`rados_aio_release` to avoid leaking memory.
 
181
 
 
182
 
 
183
API calls
 
184
=========
 
185
 
 
186
 .. doxygenfile:: librados.h