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

« back to all changes in this revision

Viewing changes to libdb/libdb_java/java_locked.c

  • 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
 
/*-
2
 
 * See the file LICENSE for redistribution information.
3
 
 *
4
 
 * Copyright (c) 1997-2002
5
 
 *      Sleepycat Software.  All rights reserved.
6
 
 */
7
 
#include "db_config.h"
8
 
 
9
 
#ifndef lint
10
 
static const char revid[] = "$Id$";
11
 
#endif /* not lint */
12
 
 
13
 
#include <jni.h>
14
 
#include <errno.h>
15
 
#include <stdlib.h>
16
 
#include <string.h>
17
 
 
18
 
#include "db_int.h"
19
 
#include "java_util.h"
20
 
 
21
 
/****************************************************************
22
 
 *
23
 
 * Implementation of functions to manipulate LOCKED_DBT.
24
 
 */
25
 
int
26
 
locked_dbt_get(LOCKED_DBT *ldbt, JNIEnv *jnienv, DB_ENV *dbenv,
27
 
               jobject jdbt, OpKind kind)
28
 
{
29
 
        DBT *dbt;
30
 
 
31
 
        COMPQUIET(dbenv, NULL);
32
 
        ldbt->jdbt = jdbt;
33
 
        ldbt->java_array_len = 0;
34
 
        ldbt->flags = 0;
35
 
        ldbt->kind = kind;
36
 
        ldbt->java_data = 0;
37
 
        ldbt->before_data = 0;
38
 
        ldbt->javainfo =
39
 
                (DBT_JAVAINFO *)get_private_dbobj(jnienv, name_DBT, jdbt);
40
 
 
41
 
        if (!verify_non_null(jnienv, ldbt->javainfo)) {
42
 
                report_exception(jnienv, "Dbt is gc'ed?", 0, 0);
43
 
                F_SET(ldbt, LOCKED_ERROR);
44
 
                return (EINVAL);
45
 
        }
46
 
        if (F_ISSET(ldbt->javainfo, DBT_JAVAINFO_LOCKED)) {
47
 
                report_exception(jnienv, "Dbt is already in use", 0, 0);
48
 
                F_SET(ldbt, LOCKED_ERROR);
49
 
                return (EINVAL);
50
 
        }
51
 
        dbt = &ldbt->javainfo->dbt;
52
 
 
53
 
        if ((*jnienv)->GetBooleanField(jnienv,
54
 
            jdbt, fid_Dbt_must_create_data) != 0)
55
 
                F_SET(ldbt, LOCKED_CREATE_DATA);
56
 
        else
57
 
                ldbt->javainfo->array =
58
 
                        (*jnienv)->GetObjectField(jnienv, jdbt, fid_Dbt_data);
59
 
 
60
 
        dbt->size = (*jnienv)->GetIntField(jnienv, jdbt, fid_Dbt_size);
61
 
        dbt->ulen = (*jnienv)->GetIntField(jnienv, jdbt, fid_Dbt_ulen);
62
 
        dbt->dlen = (*jnienv)->GetIntField(jnienv, jdbt, fid_Dbt_dlen);
63
 
        dbt->doff = (*jnienv)->GetIntField(jnienv, jdbt, fid_Dbt_doff);
64
 
        dbt->flags = (*jnienv)->GetIntField(jnienv, jdbt, fid_Dbt_flags);
65
 
        ldbt->javainfo->offset = (*jnienv)->GetIntField(jnienv, jdbt,
66
 
                                                    fid_Dbt_offset);
67
 
 
68
 
        /*
69
 
         * If no flags are set, use default behavior of DB_DBT_MALLOC.
70
 
         * We can safely set dbt->flags because flags will never be copied
71
 
         * back to the Java Dbt.
72
 
         */
73
 
        if (kind != inOp &&
74
 
            !F_ISSET(dbt, DB_DBT_USERMEM | DB_DBT_MALLOC | DB_DBT_REALLOC))
75
 
                F_SET(dbt, DB_DBT_MALLOC);
76
 
 
77
 
        /*
78
 
         * If this is requested to be realloc with an existing array,
79
 
         * we cannot use the underlying realloc, because the array we
80
 
         * will pass in is allocated by the Java VM, not us, so it
81
 
         * cannot be realloced.  We simulate the reallocation by using
82
 
         * USERMEM and reallocating the java array when a ENOMEM error
83
 
         * occurs.  We change the flags during the operation, and they
84
 
         * are reset when the operation completes (in locked_dbt_put).
85
 
         */
86
 
        if (F_ISSET(dbt, DB_DBT_REALLOC) && ldbt->javainfo->array != NULL) {
87
 
                F_CLR(dbt, DB_DBT_REALLOC);
88
 
                F_SET(dbt, DB_DBT_USERMEM);
89
 
                F_SET(ldbt, LOCKED_REALLOC_NONNULL);
90
 
        }
91
 
 
92
 
        if ((F_ISSET(dbt, DB_DBT_USERMEM) || kind != outOp) &&
93
 
            !F_ISSET(ldbt, LOCKED_CREATE_DATA)) {
94
 
 
95
 
                /*
96
 
                 * If writing with DB_DBT_USERMEM
97
 
                 * or it's a set (or get/set) operation,
98
 
                 * then the data should point to a java array.
99
 
                 * Note that outOp means data is coming out of the database
100
 
                 * (it's a get).  inOp means data is going into the database
101
 
                 * (either a put, or a key input).
102
 
                 */
103
 
                if (!ldbt->javainfo->array) {
104
 
                        report_exception(jnienv, "Dbt.data is null", 0, 0);
105
 
                        F_SET(ldbt, LOCKED_ERROR);
106
 
                        return (EINVAL);
107
 
                }
108
 
 
109
 
                /* Verify other parameters */
110
 
                ldbt->java_array_len = (*jnienv)->GetArrayLength(jnienv,
111
 
                                                        ldbt->javainfo->array);
112
 
                if (ldbt->javainfo->offset < 0 ) {
113
 
                        report_exception(jnienv, "Dbt.offset illegal", 0, 0);
114
 
                        F_SET(ldbt, LOCKED_ERROR);
115
 
                        return (EINVAL);
116
 
                }
117
 
                if (dbt->size + ldbt->javainfo->offset > ldbt->java_array_len) {
118
 
                        report_exception(jnienv,
119
 
                         "Dbt.size + Dbt.offset greater than array length",
120
 
                                         0, 0);
121
 
                        F_SET(ldbt, LOCKED_ERROR);
122
 
                        return (EINVAL);
123
 
                }
124
 
 
125
 
                ldbt->java_data = (*jnienv)->GetByteArrayElements(jnienv,
126
 
                                                ldbt->javainfo->array,
127
 
                                                (jboolean *)0);
128
 
 
129
 
                dbt->data = ldbt->before_data = ldbt->java_data +
130
 
                        ldbt->javainfo->offset;
131
 
        }
132
 
        else if (!F_ISSET(ldbt, LOCKED_CREATE_DATA)) {
133
 
 
134
 
                /*
135
 
                 * If writing with DB_DBT_MALLOC or DB_DBT_REALLOC with
136
 
                 * a null array, then the data is allocated by DB.
137
 
                 */
138
 
                dbt->data = ldbt->before_data = 0;
139
 
        }
140
 
 
141
 
        /*
142
 
         * RPC makes the assumption that if dbt->size is non-zero, there
143
 
         * is data to copy from dbt->data.  We may have set dbt->size
144
 
         * to a non-zero integer above but decided not to point
145
 
         * dbt->data at anything.  (One example is if we're doing an outOp
146
 
         * with an already-used Dbt whose values we expect to just
147
 
         * overwrite.)
148
 
         *
149
 
         * Clean up the dbt fields so we don't run into trouble.
150
 
         * (Note that doff, dlen, and flags all may contain meaningful
151
 
         * values.)
152
 
         */
153
 
        if (dbt->data == NULL)
154
 
                dbt->size = dbt->ulen = 0;
155
 
 
156
 
        F_SET(ldbt->javainfo, DBT_JAVAINFO_LOCKED);
157
 
        return (0);
158
 
}
159
 
 
160
 
/*
161
 
 * locked_dbt_put must be called for any LOCKED_DBT struct before a
162
 
 * java handler returns to the user.  It can be thought of as the
163
 
 * LOCKED_DBT destructor.  It copies any information from temporary
164
 
 * structures back to user accessible arrays, and of course must free
165
 
 * memory and remove references.  The LOCKED_DBT itself is not freed,
166
 
 * as it is expected to be a stack variable.
167
 
 *
168
 
 * Note that after this call, the LOCKED_DBT can still be used in
169
 
 * limited ways, e.g. to look at values in the C DBT.
170
 
 */
171
 
void
172
 
locked_dbt_put(LOCKED_DBT *ldbt, JNIEnv *jnienv, DB_ENV *dbenv)
173
 
{
174
 
        DBT *dbt;
175
 
 
176
 
        dbt = &ldbt->javainfo->dbt;
177
 
 
178
 
        /*
179
 
         * If the error flag was set, we never succeeded
180
 
         * in allocating storage.
181
 
         */
182
 
        if (F_ISSET(ldbt, LOCKED_ERROR))
183
 
                return;
184
 
 
185
 
        if (((F_ISSET(dbt, DB_DBT_USERMEM) ||
186
 
              F_ISSET(ldbt, LOCKED_REALLOC_NONNULL)) ||
187
 
             ldbt->kind == inOp) && !F_ISSET(ldbt, LOCKED_CREATE_DATA)) {
188
 
 
189
 
                /*
190
 
                 * If writing with DB_DBT_USERMEM or it's a set
191
 
                 * (or get/set) operation, then the data may be already in
192
 
                 * the java array, in which case, we just need to release it.
193
 
                 * If DB didn't put it in the array (indicated by the
194
 
                 * dbt->data changing), we need to do that
195
 
                 */
196
 
                if (ldbt->before_data != ldbt->java_data) {
197
 
                        (*jnienv)->SetByteArrayRegion(jnienv,
198
 
                                                      ldbt->javainfo->array,
199
 
                                                      ldbt->javainfo->offset,
200
 
                                                      dbt->ulen,
201
 
                                                      ldbt->before_data);
202
 
                }
203
 
                (*jnienv)->ReleaseByteArrayElements(jnienv,
204
 
                                                    ldbt->javainfo->array,
205
 
                                                    ldbt->java_data, 0);
206
 
                dbt->data = 0;
207
 
        }
208
 
        else if (F_ISSET(dbt, DB_DBT_MALLOC | DB_DBT_REALLOC) &&
209
 
            ldbt->kind != inOp && !F_ISSET(ldbt, LOCKED_CREATE_DATA)) {
210
 
 
211
 
                /*
212
 
                 * If writing with DB_DBT_MALLOC, or DB_DBT_REALLOC
213
 
                 * with a zero buffer, then the data was allocated by
214
 
                 * DB.  If dbt->data is zero, it means an error
215
 
                 * occurred (and should have been already reported).
216
 
                 */
217
 
                if (dbt->data) {
218
 
 
219
 
                        /*
220
 
                         * In the case of SET_RANGE, the key is inOutOp
221
 
                         * and when not found, its data will be left as
222
 
                         * its original value.  Only copy and free it
223
 
                         * here if it has been allocated by DB
224
 
                         * (dbt->data has changed).
225
 
                         */
226
 
                        if (dbt->data != ldbt->before_data) {
227
 
                                jbyteArray newarr;
228
 
 
229
 
                                if ((newarr = (*jnienv)->NewByteArray(jnienv,
230
 
                                    dbt->size)) == NULL) {
231
 
                                        /* The JVM has posted an exception. */
232
 
                                        F_SET(ldbt, LOCKED_ERROR);
233
 
                                        return;
234
 
                                }
235
 
                                (*jnienv)->SetObjectField(jnienv, ldbt->jdbt,
236
 
                                                          fid_Dbt_data,
237
 
                                                          newarr);
238
 
                                ldbt->javainfo->offset = 0;
239
 
                                (*jnienv)->SetByteArrayRegion(jnienv,
240
 
                                              newarr, 0, dbt->size,
241
 
                                              (jbyte *)dbt->data);
242
 
                                (void)__os_ufree(dbenv, dbt->data);
243
 
                                dbt->data = 0;
244
 
                        }
245
 
                }
246
 
        }
247
 
 
248
 
        /*
249
 
         * The size field may have changed after a DB API call,
250
 
         * so we set that back too.
251
 
         */
252
 
        (*jnienv)->SetIntField(jnienv, ldbt->jdbt, fid_Dbt_size, dbt->size);
253
 
        ldbt->javainfo->array = NULL;
254
 
        F_CLR(ldbt->javainfo, DBT_JAVAINFO_LOCKED);
255
 
}
256
 
 
257
 
/*
258
 
 * Realloc the java array to receive data if the DBT used
259
 
 * DB_DBT_REALLOC flag with a non-null data array, and the last
260
 
 * operation set the size field to an amount greater than ulen.
261
 
 * Return 1 if these conditions are met, otherwise 0.  This is used
262
 
 * internally to simulate the operations needed for DB_DBT_REALLOC.
263
 
 */
264
 
int locked_dbt_realloc(LOCKED_DBT *ldbt, JNIEnv *jnienv, DB_ENV *dbenv)
265
 
{
266
 
        DBT *dbt;
267
 
 
268
 
        COMPQUIET(dbenv, NULL);
269
 
        dbt = &ldbt->javainfo->dbt;
270
 
 
271
 
        if (!F_ISSET(ldbt, LOCKED_REALLOC_NONNULL) ||
272
 
            F_ISSET(ldbt, LOCKED_ERROR) || dbt->size <= dbt->ulen)
273
 
                return (0);
274
 
 
275
 
        (*jnienv)->ReleaseByteArrayElements(jnienv, ldbt->javainfo->array,
276
 
                                            ldbt->java_data, 0);
277
 
 
278
 
        /*
279
 
         * We allocate a new array of the needed size.
280
 
         * We'll set the offset to 0, as the old offset
281
 
         * really doesn't make any sense.
282
 
         */
283
 
        if ((ldbt->javainfo->array = (*jnienv)->NewByteArray(jnienv,
284
 
            dbt->size)) == NULL) {
285
 
                F_SET(ldbt, LOCKED_ERROR);
286
 
                return (0);
287
 
        }
288
 
 
289
 
        ldbt->java_array_len = dbt->ulen = dbt->size;
290
 
        ldbt->javainfo->offset = 0;
291
 
        (*jnienv)->SetObjectField(jnienv, ldbt->jdbt, fid_Dbt_data,
292
 
            ldbt->javainfo->array);
293
 
        ldbt->java_data = (*jnienv)->GetByteArrayElements(jnienv,
294
 
            ldbt->javainfo->array, (jboolean *)0);
295
 
        memcpy(ldbt->java_data, ldbt->before_data, dbt->ulen);
296
 
        dbt->data = ldbt->before_data = ldbt->java_data;
297
 
        return (1);
298
 
}
299
 
 
300
 
/****************************************************************
301
 
 *
302
 
 * Implementation of functions to manipulate LOCKED_STRING.
303
 
 */
304
 
int
305
 
locked_string_get(LOCKED_STRING *ls, JNIEnv *jnienv, jstring jstr)
306
 
{
307
 
        ls->jstr = jstr;
308
 
 
309
 
        if (jstr == 0)
310
 
                ls->string = 0;
311
 
        else
312
 
                ls->string = (*jnienv)->GetStringUTFChars(jnienv, jstr,
313
 
                                                          (jboolean *)0);
314
 
        return (0);
315
 
}
316
 
 
317
 
void locked_string_put(LOCKED_STRING *ls, JNIEnv *jnienv)
318
 
{
319
 
        if (ls->jstr)
320
 
                (*jnienv)->ReleaseStringUTFChars(jnienv, ls->jstr, ls->string);
321
 
}