1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157
|
/****************************************************************
* *
* Copyright (c) 2014-2024 Fidelity National Information *
* Services, Inc. and/or its subsidiaries. All rights reserved. *
* *
* 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"
#ifdef AUTORELINK_SUPPORTED
#include "gtm_string.h"
#include "gtm_stat.h"
#include "gtm_stdlib.h"
#include "gtm_limits.h"
#include "relinkctl.h"
#include "util.h"
#include <rtnhdr.h> /* needed for zroutines.h */
#include "zroutines.h"
#include "cli.h"
#include "cliif.h"
#include "cli_parse.h"
#include "eintr_wrappers.h"
#include "gtmmsg.h"
#endif
#include "mu_rndwn_rlnkctl.h" /* for mupip_rctldump prototype */
#include "mupip_rundown.h"
#include "mupip_exit.h"
GBLDEF boolean_t in_relinkctl;
GBLREF boolean_t in_rundown;
#ifdef AUTORELINK_SUPPORTED
error_def(ERR_FILEPARSE);
error_def(ERR_MUPCLIERR);
error_def(ERR_RLNKCTLRNDWNSUC);
#endif
/* Implements MUPIP RUNDOWN -RELINKCTL */
void mu_rndwn_rlnkctl(void)
{
# ifdef AUTORELINK_SUPPORTED
open_relinkctl_sgm *linkctl;
relinkshm_hdr_t *shm_hdr;
relinkrec_t *linkrec;
relinkctl_data *hdr;
rtnobjshm_hdr_t *rtnobj_shm_hdr;
char objdir[GTM_PATH_MAX];
int i, j, recnum, n_records, shmid, shm_stat, save_errno, objcnt, stat_res, params_cnt;
unsigned short param_len;
mstr dir;
zro_ent *op;
boolean_t region, file, relink_dir, file_or_region, is_what;
DCL_THREADGBL_ACCESS;
SETUP_THREADGBL_ACCESS;
TREF(is_mu_rndwn_rlnkctl) = TRUE; /* relinkctl_open and relinkctl_rundown check this flag to act differently.
* No need to have condition handler to reset this in case of error because
* this is invoked from MUPIP RUNDOWN -RELINKCTL which is the only action
* that the calling process will do in its lifetime.
*/
file = (CLI_PRESENT == cli_present("FILE"));
region = (CLI_PRESENT == cli_present("REGION")) || (CLI_PRESENT == cli_present("R"));
relink_dir = FALSE;
file_or_region = (file || region);
params_cnt = TREF(parms_cnt);
in_relinkctl = TRUE;
/* relink_dir is set to true when two parameters are present,
* or when one parameter is passed to the relinkctl function only.
* If a region or file qualifier is present, and there is only one parameter, used it as region or file.
*/
if (2 == params_cnt || (1 == params_cnt && !file_or_region))
relink_dir = TRUE;
if (!file_or_region && (1 < params_cnt))
{
util_out_print("%GTM-E-CLIERR, Too many parameters", TRUE);
mupip_exit(ERR_MUPCLIERR);
}
if (relink_dir)
{
param_len = SIZEOF(objdir) - 1;
is_what = (TREF(parms_cnt) == 2 && !in_rundown);
if (!cli_get_str(is_what ? "WHAT": "R_OR_F_NAME", objdir, ¶m_len))
RTS_ERROR_CSA_ABT(NULL, VARLSTCNT(1) ERR_MUPCLIERR);
objdir[param_len] = '\0';
dir.addr = objdir;
dir.len = param_len;
linkctl = relinkctl_attach(&dir, NULL, SIZEOF(objdir));
assert(dir.len <= SIZEOF(objdir) - 1);
assert(('\0' == dir.addr[dir.len]) || (0 == dir.len));
assert(linkctl == TREF(open_relinkctl_list));
assert((NULL == linkctl) || (NULL == linkctl->next));
if (NULL == linkctl)
{
if (0 == dir.len)
{ /* If relinkctl_attach() did not find the object directory corresponding to the user's argument,
* dir.len is set to 0; in that case we want to print an error containing the argument, and so the
* proper length needs to be restored.
*/
dir.len = param_len;
RTS_ERROR_CSA_ABT(NULL, VARLSTCNT(5) ERR_FILEPARSE, 2, RTS_ERROR_MSTR(&dir), errno);
} else
gtm_putmsg_csa(CSA_ARG(NULL) VARLSTCNT(4) ERR_RLNKCTLRNDWNSUC, 2, RTS_ERROR_MSTR(&dir));
} else
relinkctl_rundown(TRUE, FALSE); /* Runs down the relinkctl file opened above. */
} else
{ /* Unlike other callers of zro_init(), MUPIP RUNDOWN -RELINKCTL does not want it to do relinkctl_attach() on all
* relinkctl files at once because we leave the attach logic holding the linkctl lock, which might potentially cause
* a deadlock if multiple processes are run concurrently with different $gtmroutines. So, zro_init() / zro_load()
* set the count field of each autorelink-enabled object directory to a negative number based on the
* TREF(is_mu_rndwn_rlnkctl) global, and we look at the count to decide whether to attach to an individual segment.
*/
zro_init();
objcnt = (TREF(zro_root))->count;
assert(0 < objcnt);
for (op = TREF(zro_root) + 1; (0 < objcnt--);)
{ /* Go through each object directory in our array to run down its relinkctl file. */
assert((ZRO_TYPE_OBJECT == op->type) || (ZRO_TYPE_OBJLIB == op->type));
if (ZRO_TYPE_OBJLIB == op->type)
continue; /* We only deal with object directories in this loop */
/* Currently the count field of object directory entries is either unused (with the value of 0) or marked as
* autorelink-enabled (only in case of MUPIP RUNDOWN -RELINKCTL). Assert that.
*/
assert(0 >= op->count);
if (0 > op->count)
{ /* Third parameter is 0 because the object directories are stored in fully resolved format in the
* gtmroutines object, so there is no need to update the string.
*/
linkctl = relinkctl_attach(&op->str, NULL, 0);
assert(linkctl == TREF(open_relinkctl_list));
assert((NULL == linkctl) || (NULL == linkctl->next));
if (NULL == linkctl)
{ /* We do not do a check of whether the object directory exists, unlike with an argument,
* because zro_init() would have errored out on a non-existent path.
*/
gtm_putmsg_csa(CSA_ARG(NULL) VARLSTCNT(4) ERR_RLNKCTLRNDWNSUC, 2,
RTS_ERROR_MSTR(&op->str));
} else
relinkctl_rundown(TRUE, FALSE); /* Runs down the relinkctl file opened above. */
}
/* Bump past source entries to next object entry */
op++;
assert(ZRO_TYPE_COUNT == op->type);
op += op->count;
op++;
}
}
if (in_relinkctl && !in_rundown)
mupip_rundown();
TREF(is_mu_rndwn_rlnkctl) = FALSE;
# endif /* AUTORELINK_SUPPORTED */
}
|