334 lines
11 KiB
C
334 lines
11 KiB
C
/****************************************************************
|
|
* *
|
|
* Copyright 2001, 2011 Fidelity Information Services, Inc *
|
|
* *
|
|
* This source code contains the intellectual property *
|
|
* of its copyright holder(s), and is made available *
|
|
* under a license. If you do not know the terms of *
|
|
* the license, please stop and do not read further. *
|
|
* *
|
|
****************************************************************/
|
|
|
|
#include "mdef.h"
|
|
|
|
#include <errno.h>
|
|
#include "gtm_string.h"
|
|
#include "gtm_stdio.h"
|
|
|
|
#include "rc.h"
|
|
#include "gdsroot.h"
|
|
#include "gtm_facility.h"
|
|
#include "fileinfo.h"
|
|
#include "gdsbt.h"
|
|
#include "gdsfhead.h"
|
|
#include "rc_nspace.h"
|
|
#include "iosp.h"
|
|
#include "copy.h"
|
|
#include "rc_oflow.h"
|
|
#include "error.h"
|
|
#include "gdsblk.h"
|
|
#include "gtcm.h"
|
|
#include "omi.h"
|
|
#include "io.h"
|
|
#include "gvcst_protos.h" /* for gvcst_get,gvcst_init prototype */
|
|
#include "change_reg.h"
|
|
#include "mvalconv.h"
|
|
#include "trans_log_name.h"
|
|
#include "hashtab_mname.h"
|
|
#include "hashtab.h"
|
|
|
|
/* TEMPORARY CONSTANT - minimum value of the database RC_RESERVED field */
|
|
#define RC_RESERVED 128
|
|
|
|
GBLDEF int rc_server_id = RC_DEF_SERV_ID;
|
|
GBLDEF rc_dsid_list *dsid_list = NULL;
|
|
|
|
GBLREF gd_region *gv_cur_region;
|
|
GBLREF gv_key *gv_currkey;
|
|
GBLREF gv_key *gv_altkey;
|
|
GBLREF sgmnt_addrs *cs_addrs;
|
|
GBLREF gv_namehead *gv_target;
|
|
GBLREF int4 gv_keysize;
|
|
GBLREF sgmnt_data_ptr_t cs_data;
|
|
GBLREF gd_addr *gd_header;
|
|
GBLREF rc_oflow *rc_overflow;
|
|
|
|
static rc_dsid_list *fdi_ptr = 0;
|
|
static int rc_overflow_size = 0;
|
|
|
|
static CONDITION_HANDLER(rc_fnd_file_ch1);
|
|
static CONDITION_HANDLER(rc_fnd_file_ch2);
|
|
|
|
short rc_fnd_file(rc_xdsid *xdsid)
|
|
{
|
|
gv_namehead *g;
|
|
short dsid, node;
|
|
gd_binding *map;
|
|
char buff[1024], *cp, *cp1;
|
|
mstr fpath1, fpath2;
|
|
mval v;
|
|
int i, keysize;
|
|
int len, node2;
|
|
|
|
GET_SHORT(dsid, &xdsid->dsid.value);
|
|
GET_SHORT(node, &xdsid->node.value);
|
|
if (!dsid_list)
|
|
{
|
|
/* open special database, set up entry */
|
|
dsid_list = (rc_dsid_list *)malloc(SIZEOF(rc_dsid_list));
|
|
dsid_list->dsid = RC_NSPACE_DSID;
|
|
dsid_list->next = NULL;
|
|
fpath1.addr = RC_NSPACE_PATH;
|
|
fpath1.len = SIZEOF(RC_NSPACE_PATH);
|
|
if (SS_NORMAL != TRANS_LOG_NAME(&fpath1, &fpath2, buff, SIZEOF(buff), do_sendmsg_on_log2long))
|
|
{
|
|
char msg[256];
|
|
SPRINTF(msg, "Invalid DB filename, \"%s\"", fpath1.addr);
|
|
gtcm_rep_err(msg, errno);
|
|
return RC_BADFILESPEC;
|
|
}
|
|
if (fpath2.len > MAX_FN_LEN)
|
|
return RC_BADFILESPEC;
|
|
dsid_list->fname = (char *)malloc(fpath2.len + 1);
|
|
memcpy(dsid_list->fname, fpath2.addr, fpath2.len);
|
|
*((char*)(dsid_list->fname + fpath2.len)) = 0;
|
|
gv_cur_region = (gd_region *)malloc(SIZEOF(gd_region));
|
|
memset(gv_cur_region, 0, SIZEOF(gd_region));
|
|
gv_cur_region->dyn.addr = (gd_segment *)malloc(SIZEOF(gd_segment));
|
|
memset(gv_cur_region->dyn.addr, 0, SIZEOF(gd_segment));
|
|
memcpy(gv_cur_region->dyn.addr->fname, fpath2.addr, fpath2.len);
|
|
gv_cur_region->dyn.addr->fname_len = fpath2.len;
|
|
gv_cur_region->dyn.addr->acc_meth = dba_bg;
|
|
ESTABLISH_RET(rc_fnd_file_ch1, RC_SUCCESS);
|
|
gvcst_init(gv_cur_region);
|
|
REVERT;
|
|
change_reg();
|
|
/* check to see if this DB has the reserved bytes field set
|
|
* correctly. Global pages must always have some extra unused
|
|
* space left in them (RC_RESERVED bytes) so that the page
|
|
* will fit into the client buffer when unpacked by the
|
|
* client.
|
|
*/
|
|
if (cs_data->reserved_bytes < RC_RESERVED)
|
|
{
|
|
OMI_DBG((omi_debug,
|
|
"Unable to access database file: \"%s\"\nReserved_bytes field in the file header is too small for GT.CM\n",
|
|
fpath2.addr));
|
|
free(dsid_list->fname);
|
|
dsid_list->fname = NULL;
|
|
free(dsid_list);
|
|
dsid_list = NULL;
|
|
free(gv_cur_region->dyn.addr);
|
|
gv_cur_region->dyn.addr = NULL;
|
|
free(gv_cur_region);
|
|
gv_cur_region = NULL;
|
|
return RC_FILEACCESS;
|
|
}
|
|
gv_keysize = DBKEYSIZE(gv_cur_region->max_key_size);
|
|
GVKEY_INIT(gv_currkey, gv_keysize);
|
|
GVKEY_INIT(gv_altkey, gv_keysize);
|
|
cs_addrs->dir_tree = (gv_namehead *)malloc(SIZEOF(gv_namehead) + 2 * SIZEOF(gv_key) + 3 * (gv_keysize - 1));
|
|
g = cs_addrs->dir_tree;
|
|
g->first_rec = (gv_key*)(g->clue.base + gv_keysize);
|
|
g->last_rec = (gv_key*)(g->first_rec->base + gv_keysize);
|
|
g->clue.top = g->last_rec->top = g->first_rec->top = gv_keysize;
|
|
g->clue.prev = g->clue.end = 0;
|
|
g->root = DIR_ROOT;
|
|
dsid_list->gda = (gd_addr*)malloc(SIZEOF(gd_addr) + 3 * SIZEOF(gd_binding));
|
|
dsid_list->gda->n_maps = 3;
|
|
dsid_list->gda->n_regions = 1;
|
|
dsid_list->gda->n_segments = 1;
|
|
dsid_list->gda->maps = (gd_binding*)((char*)dsid_list->gda + SIZEOF(gd_addr));
|
|
dsid_list->gda->max_rec_size = gv_cur_region->max_rec_size;
|
|
map = dsid_list->gda->maps;
|
|
map ++;
|
|
memset(map->name, 0, SIZEOF(map->name));
|
|
map->name[0] = '%';
|
|
map->reg.addr = gv_cur_region;
|
|
map++;
|
|
map->reg.addr = gv_cur_region;
|
|
memset(map->name, -1, SIZEOF(map->name));
|
|
dsid_list->gda->tab_ptr = (hash_table_mname *)malloc(SIZEOF(hash_table_mname));
|
|
init_hashtab_mname(dsid_list->gda->tab_ptr, 0, HASHTAB_NO_COMPACT, HASHTAB_NO_SPARE_TABLE);
|
|
change_reg();
|
|
if (rc_overflow->top < cs_addrs->hdr->blk_size)
|
|
{
|
|
if (rc_overflow->buff)
|
|
free(rc_overflow->buff);
|
|
rc_overflow->top = cs_addrs->hdr->blk_size;
|
|
rc_overflow->buff = (char*)malloc(rc_overflow->top);
|
|
if (rc_overflow_size < rc_overflow->top)
|
|
rc_overflow_size = rc_overflow->top;
|
|
}
|
|
}
|
|
for (fdi_ptr = dsid_list; fdi_ptr && (fdi_ptr->dsid != dsid); fdi_ptr = fdi_ptr->next)
|
|
;
|
|
if (!fdi_ptr)
|
|
{ /* need to open new database, add to list, set fdi_ptr */
|
|
gd_header = dsid_list->gda;
|
|
gv_currkey->end = 0;
|
|
v.mvtype = MV_STR;
|
|
v.str.len = RC_NSPACE_GLOB_LEN-1;
|
|
v.str.addr = RC_NSPACE_GLOB;
|
|
GV_BIND_NAME_AND_ROOT_SEARCH(gd_header, &v.str);
|
|
if (!gv_target->root) /* No namespace global */
|
|
return RC_UNDEFNAMSPC;
|
|
v.mvtype = MV_STR;
|
|
v.str.len = SIZEOF(RC_NSPACE_DSI_SUB)-1;
|
|
v.str.addr = RC_NSPACE_DSI_SUB;
|
|
mval2subsc(&v,gv_currkey);
|
|
node2 = node;
|
|
MV_FORCE_MVAL(&v,node2);
|
|
mval2subsc(&v,gv_currkey);
|
|
i = dsid / 256;
|
|
MV_FORCE_MVAL(&v,i);
|
|
mval2subsc(&v,gv_currkey);
|
|
if (gvcst_get(&v))
|
|
return RC_UNDEFNAMSPC;
|
|
for (cp = v.str.addr, i = 1; i < RC_FILESPEC_PIECE; i++)
|
|
for (; *cp++ != RC_FILESPEC_DELIM; )
|
|
;
|
|
for (cp1 = cp; *cp1++ != RC_FILESPEC_DELIM; )
|
|
;
|
|
cp1--;
|
|
len = (int)(cp1 - cp);
|
|
if (len > MAX_FN_LEN)
|
|
return RC_BADFILESPEC;
|
|
fdi_ptr = (rc_dsid_list *)malloc(SIZEOF(rc_dsid_list));
|
|
fdi_ptr->fname = (char *)malloc(len+1);
|
|
fdi_ptr->dsid = dsid;
|
|
memcpy(fdi_ptr->fname, cp, len);
|
|
*(fdi_ptr->fname + (len)) = 0;
|
|
gv_cur_region = (gd_region *)malloc(SIZEOF(gd_region));
|
|
memset(gv_cur_region, 0, SIZEOF(gd_region));
|
|
gv_cur_region->dyn.addr = (gd_segment *)malloc(SIZEOF(gd_segment));
|
|
memset(gv_cur_region->dyn.addr, 0, SIZEOF(gd_segment));
|
|
memcpy(gv_cur_region->dyn.addr->fname, cp, len);
|
|
gv_cur_region->dyn.addr->fname_len = len;
|
|
gv_cur_region->dyn.addr->acc_meth = dba_bg;
|
|
ESTABLISH_RET(rc_fnd_file_ch2, RC_SUCCESS);
|
|
gvcst_init(gv_cur_region);
|
|
REVERT;
|
|
change_reg();
|
|
/* check to see if this DB has the reserved bytes field set
|
|
* correctly. Global pages must always have some extra unused
|
|
* space left in them (RC_RESERVED bytes) so that the page
|
|
* will fit into the client buffer when unpacked by the
|
|
* client.
|
|
*/
|
|
if (cs_data->reserved_bytes < RC_RESERVED)
|
|
{
|
|
OMI_DBG((omi_debug,
|
|
"Unable to access database file: \"%s\"\nReserved_bytes field in the file header is too small for GT.CM\n",
|
|
fdi_ptr->fname));
|
|
free(dsid_list->fname);
|
|
dsid_list->fname = NULL;
|
|
free(dsid_list);
|
|
dsid_list = NULL;
|
|
free(gv_cur_region->dyn.addr);
|
|
gv_cur_region->dyn.addr = NULL;
|
|
free(gv_cur_region);
|
|
gv_cur_region = NULL;
|
|
return RC_FILEACCESS;
|
|
}
|
|
assert(!cs_addrs->hold_onto_crit); /* this ensures we can safely do unconditional grab_crit and rel_crit */
|
|
grab_crit(gv_cur_region);
|
|
cs_data->rc_srv_cnt++;
|
|
if (!cs_data->dsid)
|
|
{
|
|
cs_data->dsid = dsid;
|
|
cs_data->rc_node = node;
|
|
} else if (cs_data->dsid != dsid || cs_data->rc_node != node)
|
|
{
|
|
cs_data->rc_srv_cnt--;
|
|
rel_crit(gv_cur_region);
|
|
OMI_DBG((omi_debug, "Dataset ID/RC node mismatch"));
|
|
OMI_DBG((omi_debug, "DB file: \"%s\"\n", dsid_list->fname));
|
|
OMI_DBG((omi_debug, "Stored DSID: %d\tRC Node: %d\n", cs_data->dsid, cs_data->rc_node));
|
|
OMI_DBG((omi_debug, "RC Rq DSID: %d\tRC Node: %d\n", dsid,node));
|
|
free(fdi_ptr->fname);
|
|
fdi_ptr->fname = NULL;
|
|
free(fdi_ptr);
|
|
fdi_ptr = NULL;
|
|
free(gv_cur_region->dyn.addr);
|
|
gv_cur_region->dyn.addr = NULL;
|
|
free(gv_cur_region);
|
|
gv_cur_region = NULL;
|
|
return RC_FILEACCESS;
|
|
}
|
|
rel_crit(gv_cur_region);
|
|
keysize = DBKEYSIZE(gv_cur_region->max_key_size);
|
|
GVKEYSIZE_INCREASE_IF_NEEDED(keysize);
|
|
cs_addrs->dir_tree = (gv_namehead *)malloc(SIZEOF(gv_namehead) + 2 * SIZEOF(gv_key) + 3 * (keysize - 1));
|
|
g = cs_addrs->dir_tree;
|
|
g->first_rec = (gv_key*)(g->clue.base + keysize);
|
|
g->last_rec = (gv_key*)(g->first_rec->base + keysize);
|
|
g->clue.top = g->last_rec->top = g->first_rec->top = keysize;
|
|
g->clue.prev = g->clue.end = 0;
|
|
g->root = DIR_ROOT;
|
|
fdi_ptr->gda = (gd_addr*)malloc(SIZEOF(gd_addr) + 3 * SIZEOF(gd_binding));
|
|
fdi_ptr->gda->n_maps = 3;
|
|
fdi_ptr->gda->n_regions = 1;
|
|
fdi_ptr->gda->n_segments = 1;
|
|
fdi_ptr->gda->maps = (gd_binding*)((char*)fdi_ptr->gda + SIZEOF(gd_addr));
|
|
fdi_ptr->gda->max_rec_size = gv_cur_region->max_rec_size;
|
|
map = fdi_ptr->gda->maps;
|
|
map ++;
|
|
memset(map->name, 0, SIZEOF(map->name));
|
|
map->name[0] = '%';
|
|
map->reg.addr = gv_cur_region;
|
|
map++;
|
|
map->reg.addr = gv_cur_region;
|
|
memset(map->name, -1, SIZEOF(map->name));
|
|
fdi_ptr->gda->tab_ptr = (hash_table_mname *)malloc(SIZEOF(hash_table_mname));
|
|
init_hashtab_mname(fdi_ptr->gda->tab_ptr, 0, HASHTAB_NO_COMPACT, HASHTAB_NO_SPARE_TABLE);
|
|
fdi_ptr->next = dsid_list->next;
|
|
dsid_list->next = fdi_ptr;
|
|
}
|
|
gv_cur_region = fdi_ptr->gda->maps[1].reg.addr;
|
|
change_reg();
|
|
if (rc_overflow->top < cs_addrs->hdr->blk_size)
|
|
{
|
|
if (rc_overflow->buff)
|
|
free(rc_overflow->buff);
|
|
rc_overflow->top = cs_addrs->hdr->blk_size;
|
|
rc_overflow->buff = (char*)malloc(rc_overflow->top);
|
|
if (rc_overflow_size < rc_overflow->top)
|
|
rc_overflow_size = rc_overflow->top;
|
|
}
|
|
if (!rc_overflow -> top)
|
|
{
|
|
rc_overflow -> top = rc_overflow_size;
|
|
rc_overflow->buff = (char *)malloc(rc_overflow->top);
|
|
}
|
|
gd_header = fdi_ptr->gda;
|
|
return RC_SUCCESS;
|
|
}
|
|
|
|
/* clean up from gvcst_init() failure, when dsid_list was NULL (open first db) */
|
|
static CONDITION_HANDLER(rc_fnd_file_ch1)
|
|
{ /* undo setup */
|
|
START_CH
|
|
free(dsid_list->fname);
|
|
dsid_list = NULL;
|
|
free(gv_cur_region->dyn.addr);
|
|
gv_cur_region->dyn.addr = NULL;
|
|
free(gv_cur_region);
|
|
gv_cur_region = NULL;
|
|
NEXTCH;
|
|
}
|
|
|
|
/* clean up from gvcst_init() failure, when dsid_list was non-NULL (open new db) */
|
|
static CONDITION_HANDLER(rc_fnd_file_ch2)
|
|
{ /* undo setup */
|
|
START_CH
|
|
free(fdi_ptr->fname);
|
|
fdi_ptr->fname = NULL;
|
|
free(fdi_ptr);
|
|
free(gv_cur_region->dyn.addr);
|
|
gv_cur_region->dyn.addr = NULL;
|
|
free(gv_cur_region);
|
|
gv_cur_region = NULL;
|
|
NEXTCH;
|
|
}
|