fis-gtm/sr_unix_cm/rc_fnd_file.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;
}