#include "db_config.h"
#ifndef lint
static const char revid[] = "$Id: os_vx_map.c,v 1.2 2004/03/30 01:23:48 jtownsen Exp $";
#endif
#ifndef NO_SYSTEM_INCLUDES
#include <sys/types.h>
#include <string.h>
#endif
#include "db_int.h"
typedef struct {
void *segment;
u_int32_t size;
char *name;
long segid;
} os_segdata_t;
static os_segdata_t *__os_segdata;
static int __os_segdata_size;
#define OS_SEGDATA_STARTING_SIZE 16
#define OS_SEGDATA_INCREMENT 16
static int __os_segdata_allocate
__P((DB_ENV *, const char *, REGINFO *, REGION *));
static int __os_segdata_find_byname
__P((DB_ENV *, const char *, REGINFO *, REGION *));
static int __os_segdata_init __P((DB_ENV *));
static int __os_segdata_new __P((DB_ENV *, int *));
static int __os_segdata_release __P((DB_ENV *, REGION *, int));
int
__os_r_sysattach(dbenv, infop, rp)
DB_ENV *dbenv;
REGINFO *infop;
REGION *rp;
{
int ret;
if (__os_segdata == NULL)
__os_segdata_init(dbenv);
DB_BEGIN_SINGLE_THREAD;
ret = __os_segdata_find_byname(dbenv, infop->name, infop, rp);
if (!F_ISSET(infop, REGION_CREATE)) {
if (ret != 0) {
__db_err(dbenv, "segment %s does not exist",
infop->name);
ret = EAGAIN;
}
goto out;
}
if (ret != 0 && ret != ENOENT)
goto out;
if (dbenv->shm_key == INVALID_REGION_SEGID) {
__db_err(dbenv, "no base shared memory ID specified");
ret = EAGAIN;
goto out;
}
if (ret == 0 && __os_segdata_release(dbenv, rp, 1) != 0) {
__db_err(dbenv,
"key: %ld: shared memory region already exists",
dbenv->shm_key + (infop->id - 1));
ret = EAGAIN;
goto out;
}
ret = __os_segdata_allocate(dbenv, infop->name, infop, rp);
out:
DB_END_SINGLE_THREAD;
return (ret);
}
int
__os_r_sysdetach(dbenv, infop, destroy)
DB_ENV *dbenv;
REGINFO *infop;
int destroy;
{
if (destroy)
return (__os_segdata_release(dbenv, infop->rp, 0));
return (0);
}
int
__os_mapfile(dbenv, path, fhp, len, is_rdonly, addrp)
DB_ENV *dbenv;
char *path;
DB_FH *fhp;
int is_rdonly;
size_t len;
void **addrp;
{
COMPQUIET(dbenv, NULL);
COMPQUIET(path, NULL);
COMPQUIET(fhp, NULL);
COMPQUIET(is_rdonly, 0);
COMPQUIET(len, 0);
COMPQUIET(addrp, NULL);
return (EINVAL);
}
int
__os_unmapfile(dbenv, addr, len)
DB_ENV *dbenv;
void *addr;
size_t len;
{
COMPQUIET(dbenv, NULL);
COMPQUIET(addr, NULL);
COMPQUIET(len, 0);
return (EINVAL);
}
static int
__os_segdata_init(dbenv)
DB_ENV *dbenv;
{
int ret;
if (__os_segdata != NULL) {
__db_err(dbenv, "shared memory segment already exists");
return (EEXIST);
}
DB_BEGIN_SINGLE_THREAD;
__os_segdata_size = OS_SEGDATA_STARTING_SIZE;
ret = __os_calloc(dbenv,
__os_segdata_size, sizeof(os_segdata_t), &__os_segdata);
DB_END_SINGLE_THREAD;
return (ret);
}
int
__os_segdata_destroy(dbenv)
DB_ENV *dbenv;
{
os_segdata_t *p;
int i;
if (__os_segdata == NULL)
return (0);
DB_BEGIN_SINGLE_THREAD;
for (i = 0; i < __os_segdata_size; i++) {
p = &__os_segdata[i];
if (p->name != NULL) {
__os_free(dbenv, p->name);
p->name = NULL;
}
if (p->segment != NULL) {
__os_free(dbenv, p->segment);
p->segment = NULL;
}
p->size = 0;
}
__os_free(dbenv, __os_segdata);
__os_segdata = NULL;
__os_segdata_size = 0;
DB_END_SINGLE_THREAD;
return (0);
}
static int
__os_segdata_allocate(dbenv, name, infop, rp)
DB_ENV *dbenv;
const char *name;
REGINFO *infop;
REGION *rp;
{
os_segdata_t *p;
int id, ret;
if ((ret = __os_segdata_new(dbenv, &id)) != 0)
return (ret);
p = &__os_segdata[id];
if ((ret = __os_calloc(dbenv, 1, rp->size, &p->segment)) != 0)
return (ret);
if ((ret = __os_strdup(dbenv, name, &p->name)) != 0) {
__os_free(dbenv, p->segment);
p->segment = NULL;
return (ret);
}
p->size = rp->size;
p->segid = dbenv->shm_key + infop->id - 1;
infop->addr = p->segment;
rp->segid = id;
return (0);
}
static int
__os_segdata_new(dbenv, segidp)
DB_ENV *dbenv;
int *segidp;
{
os_segdata_t *p;
int i, newsize, ret;
if (__os_segdata == NULL) {
__db_err(dbenv, "shared memory segment not initialized");
return (EAGAIN);
}
for (i = 0; i < __os_segdata_size; i++) {
p = &__os_segdata[i];
if (p->segment == NULL) {
*segidp = i;
return (0);
}
}
newsize = __os_segdata_size + OS_SEGDATA_INCREMENT;
if ((ret = __os_realloc(dbenv, newsize * sizeof(os_segdata_t),
&__os_segdata)) != 0)
return (ret);
memset(&__os_segdata[__os_segdata_size],
0, OS_SEGDATA_INCREMENT * sizeof(os_segdata_t));
*segidp = __os_segdata_size;
__os_segdata_size = newsize;
return (0);
}
static int
__os_segdata_find_byname(dbenv, name, infop, rp)
DB_ENV *dbenv;
const char *name;
REGINFO *infop;
REGION *rp;
{
os_segdata_t *p;
long segid;
int i;
if (__os_segdata == NULL) {
__db_err(dbenv, "shared memory segment not initialized");
return (EAGAIN);
}
if (name == NULL) {
__db_err(dbenv, "no segment name given");
return (EAGAIN);
}
if (F_ISSET(infop, REGION_CREATE))
segid = dbenv->shm_key + (infop->id - 1);
else {
if (rp->segid >= __os_segdata_size ||
rp->segid == INVALID_REGION_SEGID) {
__db_err(dbenv, "Invalid segment id given");
return (EAGAIN);
}
segid = __os_segdata[rp->segid].segid;
}
for (i = 0; i < __os_segdata_size; i++) {
p = &__os_segdata[i];
if (p->name != NULL && strcmp(name, p->name) == 0 &&
p->segid == segid) {
infop->addr = p->segment;
rp->segid = i;
return (0);
}
}
return (ENOENT);
}
static int
__os_segdata_release(dbenv, rp, is_locked)
DB_ENV *dbenv;
REGION *rp;
int is_locked;
{
os_segdata_t *p;
if (__os_segdata == NULL) {
__db_err(dbenv, "shared memory segment not initialized");
return (EAGAIN);
}
if (rp->segid < 0 || rp->segid >= __os_segdata_size) {
__db_err(dbenv, "segment id %ld out of range", rp->segid);
return (EINVAL);
}
if (is_locked == 0)
DB_BEGIN_SINGLE_THREAD;
p = &__os_segdata[rp->segid];
if (p->name != NULL) {
__os_free(dbenv, p->name);
p->name = NULL;
}
if (p->segment != NULL) {
__os_free(dbenv, p->segment);
p->segment = NULL;
}
p->size = 0;
if (is_locked == 0)
DB_END_SINGLE_THREAD;
return (0);
}