338 lines
9.7 KiB
C
338 lines
9.7 KiB
C
/****************************************************************
|
|
* *
|
|
* Copyright 2001, 2012 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 "gdsroot.h"
|
|
#include "gtm_facility.h"
|
|
#include "fileinfo.h"
|
|
#include "gdsbt.h"
|
|
#include "gdsfhead.h"
|
|
#include "gbldirnam.h"
|
|
#include "hashtab_mname.h"
|
|
#include "iosize.h"
|
|
#include "probe.h"
|
|
#include "dpgbldir.h"
|
|
#ifdef UNIX
|
|
#include "gtmio.h"
|
|
#elif defined(VMS)
|
|
#include <fab.h>
|
|
#else
|
|
#error unsupported platform
|
|
#endif
|
|
#include "dpgbldir_sysops.h"
|
|
#include "targ_alloc.h"
|
|
#include "gtm_logicals.h"
|
|
|
|
GBLREF gd_addr *gd_header;
|
|
GBLREF gv_namehead *gv_target_list;
|
|
|
|
LITREF char gde_labels[GDE_LABEL_NUM][GDE_LABEL_SIZE];
|
|
|
|
STATICDEF gdr_name *gdr_name_head;
|
|
STATICDEF gd_addr *gd_addr_head;
|
|
|
|
error_def(ERR_GDINVALID);
|
|
|
|
/*+
|
|
Function: ZGBLDIR
|
|
|
|
This function searches the list of global directory names for
|
|
the specified names. If not found, it adds the new name to the
|
|
list and calls GD_LOAD. A pointer to the global directory
|
|
structure is returned, and the name entry is pointed at it.
|
|
The global directory pointer is then returned to the caller.
|
|
|
|
Syntax: gd_addr *zgbldir(mval *v)
|
|
|
|
Prototype: ?
|
|
|
|
Return: *gd_addr -- a pointer to the global directory structure
|
|
|
|
Arguments: mval *v -- an mval that contains the name of the global
|
|
directory to be accessed. The name may require translation.
|
|
|
|
Side Effects: NONE
|
|
|
|
Notes: NONE
|
|
-*/
|
|
gd_addr *zgbldir(mval *v)
|
|
{
|
|
gd_addr *gd_ptr;
|
|
gdr_name *name;
|
|
mstr temp_mstr, *tran_name;
|
|
|
|
for (name = gdr_name_head; name; name = (gdr_name *)name->link)
|
|
if (v->str.len == name->name.len && !memcmp(v->str.addr, name->name.addr, v->str.len))
|
|
return name->gd_ptr;
|
|
if (!v->str.len)
|
|
{
|
|
temp_mstr.addr = GTM_GBLDIR;
|
|
temp_mstr.len = SIZEOF(GTM_GBLDIR) - 1;
|
|
tran_name = get_name(&temp_mstr);
|
|
} else
|
|
tran_name = get_name(&v->str);
|
|
gd_ptr = gd_load(tran_name);
|
|
name = (gdr_name *)malloc(SIZEOF(gdr_name));
|
|
if (name->name.len = v->str.len) /* Note embedded assignment */
|
|
{
|
|
name->name.addr = (char *)malloc(v->str.len);
|
|
memcpy(name->name.addr, v->str.addr, v->str.len);
|
|
}
|
|
/* Store translated global directory name as well */
|
|
assert(tran_name->len);
|
|
name->exp_name = *tran_name;
|
|
/* free up memory allocated for mstr field in get_name.
|
|
* memory allocated for addr field of the mstr is needed as it has been copied over to "name->exp_name" */
|
|
free(tran_name);
|
|
|
|
if (gdr_name_head)
|
|
name->link = (gdr_name *)gdr_name_head;
|
|
else
|
|
name->link = 0;
|
|
gdr_name_head = name;
|
|
gdr_name_head->gd_ptr = gd_ptr;
|
|
return gd_ptr;
|
|
}
|
|
|
|
/*+
|
|
Function: GD_LOAD
|
|
|
|
Syntax: gd_addr *gd_load(mstr *gd_name)
|
|
|
|
Open a global directory file and verify that it is a valid GD.
|
|
Determine if it has already been opened. If not, setup and
|
|
initialize the GT.M structures used to access the GD based on
|
|
the information in the file, enter in the linked list of global
|
|
directories and return a pointer to it. If already opened, return
|
|
a pointer to it.
|
|
|
|
Prototype: ?
|
|
|
|
Return: gd_addr * (all errors are signalled)
|
|
|
|
Arguments: gd_name is the name of the file to be opened
|
|
|
|
Side Effects: None
|
|
Notes: A) While checking may be done earlier for duplicate names,
|
|
unique identification of files can require OS specific
|
|
operations useable only after the file is open, so checks
|
|
must be done within this function for duplicate files.
|
|
-*/
|
|
gd_addr *gd_load(mstr *v)
|
|
{
|
|
void *file_ptr; /* This is a temporary structure as the file open and manipulations are currently stubs */
|
|
header_struct *header, temp_head;
|
|
gd_addr *table, *gd_addr_ptr;
|
|
gd_binding *map, *map_top;
|
|
gd_region *reg, *reg_top;
|
|
uint4 t_offset, size;
|
|
short i;
|
|
|
|
file_ptr = open_gd_file(v);
|
|
|
|
for (gd_addr_ptr = gd_addr_head; gd_addr_ptr; gd_addr_ptr = gd_addr_ptr->link)
|
|
{ /* if already open then return old structure */
|
|
if (comp_gd_addr(gd_addr_ptr, file_ptr))
|
|
{
|
|
close_gd_file(file_ptr);
|
|
return gd_addr_ptr;
|
|
}
|
|
}
|
|
file_read(file_ptr, SIZEOF(header_struct), (uchar_ptr_t)&temp_head, 1); /* Read in header and verify is valid GD */
|
|
for (i = 0; i < GDE_LABEL_NUM; i++)
|
|
{
|
|
if (!memcmp(temp_head.label, gde_labels[i], GDE_LABEL_SIZE - 1))
|
|
break;
|
|
}
|
|
if (GDE_LABEL_NUM == i)
|
|
{
|
|
close_gd_file(file_ptr);
|
|
rts_error(VARLSTCNT(8) ERR_GDINVALID, 6, v->len, v->addr, LEN_AND_LIT(GDE_LABEL_LITERAL),
|
|
SIZEOF(temp_head.label), temp_head.label);
|
|
}
|
|
size = LEGAL_IO_SIZE(temp_head.filesize);
|
|
header = (header_struct *)malloc(size);
|
|
file_read(file_ptr, size, (uchar_ptr_t)header, 1); /* Read in body of file */
|
|
table = (gd_addr *)((char *)header + SIZEOF(header_struct));
|
|
table->local_locks = (struct gd_region_struct *)((UINTPTR_T)table->local_locks + (UINTPTR_T)table);
|
|
table->maps = (struct gd_binding_struct *)((UINTPTR_T)table->maps + (UINTPTR_T)table);
|
|
table->regions = (struct gd_region_struct *)((UINTPTR_T)table->regions + (UINTPTR_T)table);
|
|
table->segments = (struct gd_segment_struct *)((UINTPTR_T)table->segments + (UINTPTR_T)table);
|
|
table->end = (table->end + (UINTPTR_T)table);
|
|
for (map = table->maps, map_top = map + table->n_maps; map < map_top; map++)
|
|
{
|
|
t_offset = map->reg.offset;
|
|
map->reg.addr = (gd_region *)((char *)table + t_offset);
|
|
assert(SIZEOF(map->name) == (MAX_MIDENT_LEN + 1));
|
|
map->name[MAX_MIDENT_LEN] = '\0'; /* reset 32nd byte to 0 since only 31 bytes are used in map.
|
|
* this is necessary so "mid_len" can be invoked on this
|
|
* as it expects a null-terminated string.
|
|
*/
|
|
}
|
|
for (reg = table->regions, reg_top = reg + table->n_regions; reg < reg_top; reg++)
|
|
{
|
|
t_offset = reg->dyn.offset;
|
|
reg->dyn.addr = (gd_segment *)((char *)table + t_offset);
|
|
}
|
|
table->link = gd_addr_head;
|
|
gd_addr_head = table;
|
|
fill_gd_addr_id(gd_addr_head, file_ptr);
|
|
close_gd_file(file_ptr);
|
|
table->tab_ptr = (hash_table_mname *)malloc(SIZEOF(hash_table_mname));
|
|
init_hashtab_mname(table->tab_ptr, 0, HASHTAB_NO_COMPACT, HASHTAB_NO_SPARE_TABLE);
|
|
return table;
|
|
}
|
|
|
|
/*+
|
|
Function: GET_NEXT_GDR
|
|
|
|
This function returns the next entry in the list of open
|
|
global directories. If the input parameter is zero, the
|
|
first entry is returned, otherwise the next entry in the
|
|
list is returned. If the input parameter is not a member
|
|
of the list, then zero will be returned.
|
|
|
|
Syntax: gd_addr *get_next_gdr(gd_addr *prev)
|
|
|
|
Prototype: ?
|
|
|
|
Return: *gd_addr -- a pointer to the global directory structure
|
|
|
|
Arguments: The previous global directory accessed;
|
|
|
|
Side Effects: NONE
|
|
|
|
Notes: NONE
|
|
-*/
|
|
gd_addr *get_next_gdr(gd_addr *prev)
|
|
{
|
|
gd_addr *ptr;
|
|
|
|
if (!prev)
|
|
return gd_addr_head;
|
|
|
|
for (ptr = gd_addr_head; ptr && ptr != prev; ptr = ptr->link)
|
|
if (!GTM_PROBE(SIZEOF(*ptr), ptr, READ)) /* Called from secshr, have to check access to memory */
|
|
return NULL;
|
|
if (ptr && GTM_PROBE(SIZEOF(*ptr), ptr, READ))
|
|
return ptr->link;
|
|
return NULL;
|
|
}
|
|
|
|
/* Maintain list of regions for GTCM_SERVER */
|
|
void cm_add_gdr_ptr(gd_region *greg)
|
|
{
|
|
gd_addr *ga;
|
|
|
|
ga = (gd_addr *)malloc(SIZEOF(gd_addr));
|
|
ga->end = 0; /* signifies a GT.CM gd_addr */
|
|
ga->regions = greg;
|
|
ga->n_regions = 1;
|
|
ga->link = gd_addr_head;
|
|
gd_addr_head = ga;
|
|
return;
|
|
}
|
|
|
|
void cm_del_gdr_ptr(gd_region *greg)
|
|
{
|
|
gd_addr *ga1, *ga2;
|
|
|
|
for (ga1 = ga2 = gd_addr_head; ga1; ga1 = ga1->link)
|
|
{
|
|
if (ga1->regions == greg)
|
|
{
|
|
if (ga1 == gd_addr_head)
|
|
gd_addr_head = ga1->link;
|
|
else
|
|
ga2->link = ga1->link;
|
|
free(ga1);
|
|
break;
|
|
}
|
|
ga2 = ga1;
|
|
}
|
|
return;
|
|
}
|
|
|
|
boolean_t get_first_gdr_name(gd_addr *current_gd_header, mstr *log_nam)
|
|
{
|
|
gdr_name *name;
|
|
|
|
for (name = gdr_name_head; name; name = (gdr_name *)name->link)
|
|
{
|
|
if (name->gd_ptr == current_gd_header)
|
|
{
|
|
*log_nam = name->exp_name;
|
|
return (TRUE);
|
|
}
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
void gd_rundown(void) /* Wipe out the global directory structures */
|
|
{
|
|
gd_addr *gda_cur, *gda_next;
|
|
gdr_name *gdn_cur, *gdn_next;
|
|
|
|
for (gda_cur = gd_addr_head; NULL != gda_cur; gda_cur = gda_next)
|
|
{
|
|
gda_next = gda_cur->link;
|
|
if (gda_cur->end)
|
|
{
|
|
gd_ht_kill(gda_cur->tab_ptr, TRUE);
|
|
free(gda_cur->tab_ptr); /* free up hashtable malloced in gd_load() */
|
|
free(gda_cur->id); /* free up gd_id malloced in gd_load()/fill_gd_addr_id() */
|
|
free((char *)gda_cur - SIZEOF(header_struct)); /* free up global directory itself */
|
|
} else
|
|
free(gda_cur); /* GT.CM gd_addr and hence header_struct wasn't malloced in cm_add_gdr_ptr */
|
|
}
|
|
assert(NULL == gv_target_list);
|
|
gd_header = gd_addr_head = (gd_addr *)NULL;
|
|
for (gdn_cur = gdr_name_head; NULL != gdn_cur; gdn_cur = gdn_next)
|
|
{
|
|
gdn_next = (gdr_name *)gdn_cur->link;
|
|
if (gdn_cur->name.len)
|
|
free(gdn_cur->name.addr);
|
|
free(gdn_cur);
|
|
}
|
|
gdr_name_head = (gdr_name *)NULL;
|
|
}
|
|
|
|
void gd_ht_kill(hash_table_mname *table, boolean_t contents) /* wipe out the hash table corresponding to a gld */
|
|
{
|
|
ht_ent_mname *tabent, *topent;
|
|
gvnh_reg_t *gvnh_reg;
|
|
gv_namehead *gvt;
|
|
|
|
if (contents)
|
|
{
|
|
for (tabent = table->base, topent = tabent + table->size; tabent < topent; tabent++)
|
|
{
|
|
if (HTENT_VALID_MNAME(tabent, gvnh_reg_t, gvnh_reg))
|
|
{
|
|
gvt = gvnh_reg->gvt;
|
|
gvt->regcnt--;
|
|
if (!gvt->regcnt)
|
|
targ_free(gvt);
|
|
free(gvnh_reg);
|
|
}
|
|
}
|
|
}
|
|
free_hashtab_mname(table);
|
|
/* We don't do a free(table) in this generic routine because it is called both by GT.M and GT.CM
|
|
* and GT.CM retains the table for reuse while GT.M doesn't. GT.M fgncal_rundown() takes care of
|
|
* this by freeing it up explicitly (after a call to ht_kill) in gd_rundown() [dpgbldir.c]
|
|
*/
|
|
return;
|
|
}
|