284 lines
9.8 KiB
C
284 lines
9.8 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 "gtm_string.h"
|
|
#include "buddy_list.h"
|
|
#include "gdsroot.h"
|
|
#include "gtm_facility.h"
|
|
#include "fileinfo.h"
|
|
#include "gdsbt.h"
|
|
#include "gdsfhead.h"
|
|
#include "view.h"
|
|
#include "toktyp.h"
|
|
#include "targ_alloc.h"
|
|
#include "valid_mname.h"
|
|
#include "dpgbldir.h"
|
|
#include "lv_val.h" /* needed for "symval" structure */
|
|
#include "min_max.h"
|
|
|
|
LITREF mval literal_one;
|
|
|
|
GBLREF gd_addr *gd_header;
|
|
GBLREF gvt_container *gvt_pending_list;
|
|
GBLREF buddy_list *gvt_pending_buddy_list;
|
|
GBLREF symval *curr_symval;
|
|
|
|
static buddy_list *noisolation_buddy_list; /* a buddy_list for maintaining the globals that are noisolated */
|
|
|
|
void view_arg_convert(viewtab_entry *vtp, mval *parm, viewparm *parmblk)
|
|
{
|
|
static int4 first_time = TRUE;
|
|
int n, res;
|
|
ht_ent_mname *tabent;
|
|
mstr tmpstr, namestr;
|
|
gd_region *r_top, *r_ptr;
|
|
mname_entry gvent, lvent;
|
|
mident_fixed lcl_buff;
|
|
unsigned char global_names[1024], stashed;
|
|
noisolation_element *gvnh_entry;
|
|
unsigned char *src, *nextsrc, *src_top, *dst, *dst_top, y;
|
|
gd_binding *temp_gd_map, *temp_gd_map_top;
|
|
gv_namehead *temp_gv_target;
|
|
gvt_container *gvtc;
|
|
gvnh_reg_t *gvnh_reg;
|
|
|
|
error_def(ERR_VIEWARGCNT);
|
|
error_def(ERR_NOREGION);
|
|
error_def(ERR_VIEWGVN);
|
|
error_def(ERR_VIEWLVN);
|
|
|
|
switch(vtp->parm)
|
|
{
|
|
case VTP_NULL:
|
|
if (parm != 0)
|
|
rts_error(VARLSTCNT(4) ERR_VIEWARGCNT, 2, strlen((const char *)vtp->keyword), vtp->keyword);
|
|
break;
|
|
case (VTP_NULL | VTP_VALUE):
|
|
if (NULL == parm)
|
|
{
|
|
parmblk->value = (mval *)&literal_one;
|
|
break;
|
|
}
|
|
/* caution: fall through */
|
|
case VTP_VALUE:
|
|
if (NULL == parm)
|
|
rts_error(VARLSTCNT(4) ERR_VIEWARGCNT, 2, strlen((const char *)vtp->keyword), vtp->keyword);
|
|
parmblk->value = parm;
|
|
break;
|
|
case (VTP_NULL | VTP_DBREGION):
|
|
if (NULL == parm)
|
|
{
|
|
parmblk->gv_ptr = 0;
|
|
break;
|
|
}
|
|
/* caution: fall through */
|
|
case VTP_DBREGION:
|
|
if (NULL == parm)
|
|
rts_error(VARLSTCNT(4) ERR_VIEWARGCNT, 2, strlen((const char *)vtp->keyword), vtp->keyword);
|
|
if (!gd_header) /* IF GD_HEADER ==0 THEN OPEN GBLDIR */
|
|
gvinit();
|
|
r_ptr = gd_header->regions;
|
|
if (!parm->str.len && vtp->keycode == VTK_GVNEXT) /* "" => 1st region */
|
|
parmblk->gv_ptr = r_ptr;
|
|
else
|
|
{
|
|
for (r_top = r_ptr + gd_header->n_regions; ; r_ptr++)
|
|
{
|
|
if (r_ptr >= r_top)
|
|
rts_error(VARLSTCNT(4) ERR_NOREGION,2, parm->str.len, parm->str.addr);
|
|
tmpstr.len = r_ptr->rname_len;
|
|
tmpstr.addr = (char *) r_ptr->rname;
|
|
MSTR_CMP(tmpstr, parm->str, n);
|
|
if (0 == n)
|
|
break;
|
|
}
|
|
parmblk->gv_ptr = r_ptr;
|
|
}
|
|
break;
|
|
case VTP_DBKEY:
|
|
if (NULL == parm)
|
|
rts_error(VARLSTCNT(4) ERR_VIEWARGCNT, 2, strlen((const char *)vtp->keyword), vtp->keyword);
|
|
if (!gd_header) /* IF GD_HEADER ==0 THEN OPEN GBLDIR */
|
|
gvinit();
|
|
memset(&parmblk->ident.c[0], 0, SIZEOF(parmblk->ident));
|
|
if (parm->str.len >= 2 && *parm->str.addr == '^')
|
|
{
|
|
namestr.addr = parm->str.addr + 1; /* skip initial '^' */
|
|
namestr.len = parm->str.len - 1;
|
|
if (namestr.len > MAX_MIDENT_LEN)
|
|
namestr.len = MAX_MIDENT_LEN;
|
|
if (valid_mname(&namestr))
|
|
memcpy(&parmblk->ident.c[0], namestr.addr, namestr.len);
|
|
else
|
|
rts_error(VARLSTCNT(4) ERR_VIEWGVN, 2, parm->str.len, parm->str.addr);
|
|
} else
|
|
rts_error(VARLSTCNT(4) ERR_VIEWGVN, 2, parm->str.len, parm->str.addr);
|
|
break;
|
|
case VTP_RTNAME:
|
|
if (NULL == parm)
|
|
rts_error(VARLSTCNT(4) ERR_VIEWARGCNT, 2, strlen((const char *)vtp->keyword), vtp->keyword);
|
|
memset(&parmblk->ident.c[0], 0, SIZEOF(parmblk->ident));
|
|
if (parm->str.len > 0)
|
|
memcpy(&parmblk->ident.c[0], parm->str.addr,
|
|
(parm->str.len <= MAX_MIDENT_LEN ? parm->str.len : MAX_MIDENT_LEN));
|
|
break;
|
|
case VTP_NULL | VTP_DBKEYLIST:
|
|
if (NULL == parm || 0 == parm->str.len)
|
|
{
|
|
parmblk->ni_list.gvnh_list = NULL;
|
|
parmblk->ni_list.type = NOISOLATION_NULL;
|
|
break;
|
|
}
|
|
/* caution : explicit fall through */
|
|
case VTP_DBKEYLIST:
|
|
if (NULL == parm)
|
|
rts_error(VARLSTCNT(4) ERR_VIEWARGCNT, 2, strlen((const char *)vtp->keyword), vtp->keyword);
|
|
if (!gd_header)
|
|
gvinit();
|
|
if (first_time)
|
|
{
|
|
noisolation_buddy_list = (buddy_list *)malloc(SIZEOF(buddy_list));
|
|
initialize_list(noisolation_buddy_list, SIZEOF(noisolation_element), NOISOLATION_INIT_ALLOC);
|
|
gvt_pending_buddy_list = (buddy_list *)malloc(SIZEOF(buddy_list));
|
|
initialize_list(gvt_pending_buddy_list, SIZEOF(gvt_container), NOISOLATION_INIT_ALLOC);
|
|
first_time = FALSE;
|
|
}
|
|
if (SIZEOF(global_names) <= parm->str.len)
|
|
GTMASSERT;
|
|
tmpstr.len = parm->str.len; /* we need to change len and should not change parm->str, so take a copy */
|
|
tmpstr.addr = parm->str.addr;
|
|
if (0 != tmpstr.len)
|
|
{
|
|
switch (*tmpstr.addr)
|
|
{
|
|
case '+' :
|
|
parmblk->ni_list.type = NOISOLATION_PLUS;
|
|
tmpstr.addr++;
|
|
tmpstr.len--;
|
|
break;
|
|
case '-' :
|
|
parmblk->ni_list.type = NOISOLATION_MINUS;
|
|
tmpstr.addr++;
|
|
tmpstr.len--;
|
|
break;
|
|
default :
|
|
parmblk->ni_list.type = NOISOLATION_NULL;
|
|
break;
|
|
}
|
|
memcpy(global_names, tmpstr.addr, tmpstr.len);
|
|
global_names[tmpstr.len] = '\0';
|
|
src = (unsigned char *)strtok((char *)global_names, ",");
|
|
REINITIALIZE_LIST(noisolation_buddy_list); /* reinitialize the noisolation buddy_list */
|
|
parmblk->ni_list.gvnh_list = NULL;
|
|
for ( ; src < &global_names[tmpstr.len + 1]; src = nextsrc)
|
|
{
|
|
nextsrc = (unsigned char *)strtok(NULL, ",");
|
|
if (NULL == nextsrc)
|
|
nextsrc = &global_names[tmpstr.len + 1];
|
|
if (nextsrc - src >= 2 && '^' == *src)
|
|
{
|
|
namestr.addr = (char *)src + 1; /* skip initial '^' */
|
|
namestr.len = INTCAST(nextsrc - src - 2); /* don't count initial ^ and trailing 0 */
|
|
if (namestr.len > MAX_MIDENT_LEN)
|
|
namestr.len = MAX_MIDENT_LEN;
|
|
if (valid_mname(&namestr))
|
|
{
|
|
memcpy(&lcl_buff.c[0], namestr.addr, namestr.len);
|
|
gvent.var_name.len = namestr.len;
|
|
} else
|
|
rts_error(VARLSTCNT(4) ERR_VIEWGVN, 2, nextsrc - src - 1, src);
|
|
} else
|
|
rts_error(VARLSTCNT(4) ERR_VIEWGVN, 2, nextsrc - src - 1, src);
|
|
temp_gv_target = NULL;
|
|
gvent.var_name.addr = &lcl_buff.c[0];
|
|
COMPUTE_HASH_MNAME(&gvent);
|
|
if (NULL == (tabent = lookup_hashtab_mname(gd_header->tab_ptr, &gvent))
|
|
|| (NULL == (gvnh_reg = (gvnh_reg_t *)tabent->value)))
|
|
{
|
|
temp_gd_map = gd_header->maps;
|
|
temp_gd_map_top = temp_gd_map + gd_header->n_maps;
|
|
temp_gd_map++; /* get past local locks */
|
|
for (; (res = memcmp(gvent.var_name.addr, &(temp_gd_map->name[0]),
|
|
gvent.var_name.len)) >= 0; temp_gd_map++)
|
|
{
|
|
assert (temp_gd_map < temp_gd_map_top);
|
|
if (0 == res && 0 != temp_gd_map->name[gvent.var_name.len])
|
|
break;
|
|
}
|
|
r_ptr = temp_gd_map->reg.addr;
|
|
assert(r_ptr->max_key_size <= MAX_KEY_SZ);
|
|
temp_gv_target = (gv_namehead *)targ_alloc(r_ptr->max_key_size, &gvent, r_ptr);
|
|
gvnh_reg = (gvnh_reg_t *)malloc(SIZEOF(gvnh_reg_t));
|
|
gvnh_reg->gvt = temp_gv_target;
|
|
gvnh_reg->gd_reg = r_ptr;
|
|
if (NULL != tabent)
|
|
{ /* Since the global name was found but gv_target was null and
|
|
* now we created a new gv_target, the hash table key must point
|
|
* to the newly created gv_target->gvname. */
|
|
tabent->key = temp_gv_target->gvname;
|
|
tabent->value = (char *)gvnh_reg;
|
|
} else
|
|
{
|
|
if (!add_hashtab_mname((hash_table_mname *)gd_header->tab_ptr,
|
|
&temp_gv_target->gvname, gvnh_reg, &tabent))
|
|
GTMASSERT;
|
|
}
|
|
if (!r_ptr->open)
|
|
{ /* Record list of all gv_targets that have been allocated BEFORE the
|
|
* region has been opened. Once the region gets opened, we will re-examine
|
|
* this list and reallocate them (if needed) since they have now been
|
|
* allocated using the region's max_key_size value which could potentially
|
|
* be different from the max_key_size value in the corresponding database
|
|
* file header.
|
|
*/
|
|
gvtc = (gvt_container *)get_new_free_element(gvt_pending_buddy_list);
|
|
gvtc->gvnh_reg = gvnh_reg;
|
|
assert(!gvtc->gvnh_reg->gd_reg->open);
|
|
gvtc->next_gvtc = (struct gvt_container_struct *)gvt_pending_list;
|
|
gvt_pending_list = gvtc;
|
|
}
|
|
} else
|
|
temp_gv_target = gvnh_reg->gvt;
|
|
gvnh_entry = (noisolation_element *)get_new_element(noisolation_buddy_list, 1);
|
|
gvnh_entry->gvnh = temp_gv_target;
|
|
gvnh_entry->next = parmblk->ni_list.gvnh_list;
|
|
parmblk->ni_list.gvnh_list = gvnh_entry;
|
|
}
|
|
} else
|
|
rts_error(VARLSTCNT(4) ERR_VIEWGVN, 2, tmpstr.len, tmpstr.addr);
|
|
break;
|
|
case VTP_LVN:
|
|
if (NULL == parm)
|
|
rts_error(VARLSTCNT(4) ERR_VIEWARGCNT, 2, strlen((const char *)vtp->keyword), vtp->keyword);
|
|
if (0 < parm->str.len)
|
|
{
|
|
lvent.var_name.addr = parm->str.addr;
|
|
lvent.var_name.len = parm->str.len;
|
|
if (lvent.var_name.len > MAX_MIDENT_LEN)
|
|
lvent.var_name.len = MAX_MIDENT_LEN;
|
|
if (!valid_mname(&lvent.var_name))
|
|
rts_error(VARLSTCNT(4) ERR_VIEWLVN, 2, parm->str.len, parm->str.addr);
|
|
} else
|
|
rts_error(VARLSTCNT(4) ERR_VIEWLVN, 2, parm->str.len, parm->str.addr);
|
|
/* Now look up the name.. */
|
|
COMPUTE_HASH_MNAME(&lvent);
|
|
if ((tabent = lookup_hashtab_mname(&curr_symval->h_symtab, &lvent)) && (NULL != tabent->value))
|
|
parmblk->value = (mval *)tabent->value; /* Return lv_val ptr */
|
|
else
|
|
rts_error(VARLSTCNT(4) ERR_VIEWLVN, 2, parm->str.len, parm->str.addr);
|
|
break;
|
|
default:
|
|
GTMASSERT;
|
|
}
|
|
}
|