00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013 #include "db_config.h"
00014
00015 #ifndef NO_SYSTEM_INCLUDES
00016 #include <sys/types.h>
00017 #include <string.h>
00018 #endif
00019
00020 #include "db_int.h"
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038 typedef struct {
00039 void *segment;
00040 u_int32_t size;
00041 char *name;
00042 long segid;
00043 } os_segdata_t;
00044
00045 static os_segdata_t *__os_segdata;
00046 static int __os_segdata_size;
00047
00048 #define OS_SEGDATA_STARTING_SIZE 16
00049 #define OS_SEGDATA_INCREMENT 16
00050
00051 static int __os_segdata_allocate
00052 __P((DB_ENV *, const char *, REGINFO *, REGION *));
00053 static int __os_segdata_find_byname
00054 __P((DB_ENV *, const char *, REGINFO *, REGION *));
00055 static int __os_segdata_init __P((DB_ENV *));
00056 static int __os_segdata_new __P((DB_ENV *, int *));
00057 static int __os_segdata_release __P((DB_ENV *, REGION *, int));
00058
00059
00060
00061
00062
00063
00064
00065 int
00066 __os_r_sysattach(dbenv, infop, rp)
00067 DB_ENV *dbenv;
00068 REGINFO *infop;
00069 REGION *rp;
00070 {
00071 int ret;
00072
00073 if (__os_segdata == NULL)
00074 __os_segdata_init(dbenv);
00075
00076 DB_BEGIN_SINGLE_THREAD;
00077
00078
00079 ret = __os_segdata_find_byname(dbenv, infop->name, infop, rp);
00080
00081
00082
00083
00084
00085
00086 if (!F_ISSET(infop, REGION_CREATE)) {
00087 if (ret != 0) {
00088 __db_err(dbenv, "segment %s does not exist",
00089 infop->name);
00090 ret = EAGAIN;
00091 }
00092 goto out;
00093 }
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105 if (ret != 0 && ret != ENOENT)
00106 goto out;
00107
00108 if (dbenv->shm_key == INVALID_REGION_SEGID) {
00109 __db_err(dbenv, "no base shared memory ID specified");
00110 ret = EAGAIN;
00111 goto out;
00112 }
00113 if (ret == 0 && __os_segdata_release(dbenv, rp, 1) != 0) {
00114 __db_err(dbenv,
00115 "key: %ld: shared memory region already exists",
00116 dbenv->shm_key + (infop->id - 1));
00117 ret = EAGAIN;
00118 goto out;
00119 }
00120
00121 ret = __os_segdata_allocate(dbenv, infop->name, infop, rp);
00122 out:
00123 DB_END_SINGLE_THREAD;
00124 return (ret);
00125 }
00126
00127
00128
00129
00130
00131
00132
00133 int
00134 __os_r_sysdetach(dbenv, infop, destroy)
00135 DB_ENV *dbenv;
00136 REGINFO *infop;
00137 int destroy;
00138 {
00139
00140
00141
00142
00143 if (destroy)
00144 return (__os_segdata_release(dbenv, infop->rp, 0));
00145 return (0);
00146 }
00147
00148
00149
00150
00151
00152
00153
00154
00155 int
00156 __os_mapfile(dbenv, path, fhp, len, is_rdonly, addrp)
00157 DB_ENV *dbenv;
00158 char *path;
00159 DB_FH *fhp;
00160 int is_rdonly;
00161 size_t len;
00162 void **addrp;
00163 {
00164
00165 COMPQUIET(dbenv, NULL);
00166 COMPQUIET(path, NULL);
00167 COMPQUIET(fhp, NULL);
00168 COMPQUIET(is_rdonly, 0);
00169 COMPQUIET(len, 0);
00170 COMPQUIET(addrp, NULL);
00171 return (EINVAL);
00172 }
00173
00174
00175
00176
00177
00178
00179
00180 int
00181 __os_unmapfile(dbenv, addr, len)
00182 DB_ENV *dbenv;
00183 void *addr;
00184 size_t len;
00185 {
00186
00187 COMPQUIET(dbenv, NULL);
00188 COMPQUIET(addr, NULL);
00189 COMPQUIET(len, 0);
00190 return (EINVAL);
00191 }
00192
00193
00194
00195
00196
00197
00198 static int
00199 __os_segdata_init(dbenv)
00200 DB_ENV *dbenv;
00201 {
00202 int ret;
00203
00204 if (__os_segdata != NULL) {
00205 __db_err(dbenv, "shared memory segment already exists");
00206 return (EEXIST);
00207 }
00208
00209
00210
00211
00212 DB_BEGIN_SINGLE_THREAD;
00213 __os_segdata_size = OS_SEGDATA_STARTING_SIZE;
00214 ret = __os_calloc(dbenv,
00215 __os_segdata_size, sizeof(os_segdata_t), &__os_segdata);
00216 DB_END_SINGLE_THREAD;
00217 return (ret);
00218 }
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229 int
00230 __os_segdata_destroy(dbenv)
00231 DB_ENV *dbenv;
00232 {
00233 os_segdata_t *p;
00234 int i;
00235
00236 if (__os_segdata == NULL)
00237 return (0);
00238
00239 DB_BEGIN_SINGLE_THREAD;
00240 for (i = 0; i < __os_segdata_size; i++) {
00241 p = &__os_segdata[i];
00242 if (p->name != NULL) {
00243 __os_free(dbenv, p->name);
00244 p->name = NULL;
00245 }
00246 if (p->segment != NULL) {
00247 __os_free(dbenv, p->segment);
00248 p->segment = NULL;
00249 }
00250 p->size = 0;
00251 }
00252
00253 __os_free(dbenv, __os_segdata);
00254 __os_segdata = NULL;
00255 __os_segdata_size = 0;
00256 DB_END_SINGLE_THREAD;
00257
00258 return (0);
00259 }
00260
00261
00262
00263
00264
00265
00266
00267
00268 static int
00269 __os_segdata_allocate(dbenv, name, infop, rp)
00270 DB_ENV *dbenv;
00271 const char *name;
00272 REGINFO *infop;
00273 REGION *rp;
00274 {
00275 os_segdata_t *p;
00276 int id, ret;
00277
00278 if ((ret = __os_segdata_new(dbenv, &id)) != 0)
00279 return (ret);
00280
00281 p = &__os_segdata[id];
00282 if ((ret = __os_calloc(dbenv, 1, rp->size, &p->segment)) != 0)
00283 return (ret);
00284 if ((ret = __os_strdup(dbenv, name, &p->name)) != 0) {
00285 __os_free(dbenv, p->segment);
00286 p->segment = NULL;
00287 return (ret);
00288 }
00289 p->size = rp->size;
00290 p->segid = dbenv->shm_key + infop->id - 1;
00291
00292 infop->addr = p->segment;
00293 rp->segid = id;
00294
00295 return (0);
00296 }
00297
00298
00299
00300
00301
00302
00303
00304
00305 static int
00306 __os_segdata_new(dbenv, segidp)
00307 DB_ENV *dbenv;
00308 int *segidp;
00309 {
00310 os_segdata_t *p;
00311 int i, newsize, ret;
00312
00313 if (__os_segdata == NULL) {
00314 __db_err(dbenv, "shared memory segment not initialized");
00315 return (EAGAIN);
00316 }
00317
00318 for (i = 0; i < __os_segdata_size; i++) {
00319 p = &__os_segdata[i];
00320 if (p->segment == NULL) {
00321 *segidp = i;
00322 return (0);
00323 }
00324 }
00325
00326
00327
00328
00329 newsize = __os_segdata_size + OS_SEGDATA_INCREMENT;
00330 if ((ret = __os_realloc(dbenv, newsize * sizeof(os_segdata_t),
00331 &__os_segdata)) != 0)
00332 return (ret);
00333 memset(&__os_segdata[__os_segdata_size],
00334 0, OS_SEGDATA_INCREMENT * sizeof(os_segdata_t));
00335
00336 *segidp = __os_segdata_size;
00337 __os_segdata_size = newsize;
00338
00339 return (0);
00340 }
00341
00342
00343
00344
00345
00346
00347
00348
00349
00350
00351 static int
00352 __os_segdata_find_byname(dbenv, name, infop, rp)
00353 DB_ENV *dbenv;
00354 const char *name;
00355 REGINFO *infop;
00356 REGION *rp;
00357 {
00358 os_segdata_t *p;
00359 long segid;
00360 int i;
00361
00362 if (__os_segdata == NULL) {
00363 __db_err(dbenv, "shared memory segment not initialized");
00364 return (EAGAIN);
00365 }
00366
00367 if (name == NULL) {
00368 __db_err(dbenv, "no segment name given");
00369 return (EAGAIN);
00370 }
00371
00372
00373
00374
00375
00376
00377 if (F_ISSET(infop, REGION_CREATE))
00378 segid = dbenv->shm_key + (infop->id - 1);
00379 else {
00380 if (rp->segid >= __os_segdata_size ||
00381 rp->segid == INVALID_REGION_SEGID) {
00382 __db_err(dbenv, "Invalid segment id given");
00383 return (EAGAIN);
00384 }
00385 segid = __os_segdata[rp->segid].segid;
00386 }
00387 for (i = 0; i < __os_segdata_size; i++) {
00388 p = &__os_segdata[i];
00389 if (p->name != NULL && strcmp(name, p->name) == 0 &&
00390 p->segid == segid) {
00391 infop->addr = p->segment;
00392 rp->segid = i;
00393 return (0);
00394 }
00395 }
00396 return (ENOENT);
00397 }
00398
00399
00400
00401
00402
00403 static int
00404 __os_segdata_release(dbenv, rp, is_locked)
00405 DB_ENV *dbenv;
00406 REGION *rp;
00407 int is_locked;
00408 {
00409 os_segdata_t *p;
00410
00411 if (__os_segdata == NULL) {
00412 __db_err(dbenv, "shared memory segment not initialized");
00413 return (EAGAIN);
00414 }
00415
00416 if (rp->segid < 0 || rp->segid >= __os_segdata_size) {
00417 __db_err(dbenv, "segment id %ld out of range", rp->segid);
00418 return (EINVAL);
00419 }
00420
00421 if (is_locked == 0)
00422 DB_BEGIN_SINGLE_THREAD;
00423 p = &__os_segdata[rp->segid];
00424 if (p->name != NULL) {
00425 __os_free(dbenv, p->name);
00426 p->name = NULL;
00427 }
00428 if (p->segment != NULL) {
00429 __os_free(dbenv, p->segment);
00430 p->segment = NULL;
00431 }
00432 p->size = 0;
00433 if (is_locked == 0)
00434 DB_END_SINGLE_THREAD;
00435
00436
00437
00438 return (0);
00439 }