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 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181
|
/****************************************************************
* *
* Copyright (c) 2001-2018 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. *
* *
****************************************************************/
/*
* -----------------------------------
* lke_showtree : displays a lock tree
* used in : lke_show.c
* -----------------------------------
*/
#include "mdef.h"
#include <stddef.h>
#include "gtm_signal.h"
#include "gtm_string.h"
#include "gtm_stdio.h"
#include "mlkdef.h"
#include "cmidef.h"
#include "gtmio.h"
#include "lke.h"
#include "mlk_shrblk_delete_if_empty.h"
#define KDIM 64 /* max number of subscripts */
GBLREF VSIG_ATOMIC_T util_interrupt;
error_def(ERR_CTRLC);
mlk_shrblk_ptr_t mlk_shrblk_sort(mlk_shrblk_ptr_t head);
void lke_show_memory(mlk_shrblk_ptr_t bhead, char *prefix)
{
mlk_shrblk_ptr_t b, bnext, parent, children;
mlk_shrsub_ptr_t dsub;
mlk_prcblk_ptr_t pending;
char temp[MAX_ZWR_KEY_SZ + 1];
char new_prefix[KDIM + 2];
hash128_state_t hs;
uint4 total_len;
gtm_uint16 hashres;
uint4 hash;
SNPRINTF(new_prefix, KDIM + 2, " %s", prefix);
for (b = bhead, bnext = 0; bnext != bhead; b = bnext)
{
dsub = (mlk_shrsub_ptr_t)R2A(b->value);
memcpy(temp, dsub->data, dsub->length);
temp[dsub->length] = '\0';
parent = b->parent ? (mlk_shrblk_ptr_t)R2A(b->parent) : NULL;
children = b->children ? (mlk_shrblk_ptr_t)R2A(b->children) : NULL;
pending = b->pending ? (mlk_prcblk_ptr_t)R2A(b->pending) : NULL;
PRINTF("%s%s : [shrblk] %p : [shrsub] %p (len=%d) : [shrhash] %x : [parent] %p : [children] %p : [pending] %p : "
"[owner] %u : [auxowner] %" PRIuPTR "\n",
prefix, temp, b, dsub, dsub->length, b->hash, parent, children, pending, b->owner, b->auxowner);
HASH128_STATE_INIT(hs, 0);
total_len = 0;
mlk_shrhash_val_build(b, &total_len, &hs);
gtmmrhash_128_result(&hs, total_len, &hashres);
hash = (uint4)hashres.one;
if (hash != b->hash) /* Should never happen; only here in case things get mangled. */
PRINTF("\t\t: [computed shrhash] %x\n", hash);
FFLUSH(stdout);
if (b->children)
lke_show_memory((mlk_shrblk_ptr_t)R2A(b->children), new_prefix);
bnext = (mlk_shrblk_ptr_t)R2A(b->rsib);
}
}
void lke_show_hashtable(mlk_pvtctl_ptr_t pctl)
{
uint4 hash, si, num_buckets;
mlk_shrhash_map_t usedmap;
mlk_shrhash_ptr_t shrhash, current_bucket;
mlk_shrblk_ptr_t current_shrblk;
shrhash = pctl->shrhash;
num_buckets = pctl->shrhash_size;
for (si = 0 ; si < num_buckets; si++)
{
current_bucket = &shrhash[si];
usedmap = current_bucket->usedmap;
hash = current_bucket->hash;
if ((0 == current_bucket->shrblk_idx) && (0 == usedmap))
continue;
current_shrblk = MLK_SHRHASH_SHRBLK_CHECK(*pctl, current_bucket);
PRINTF("%d\t: [shrblk] %p : [hash] %x : [usedmap] %" PRIUSEDMAP "\n", si, current_shrblk, hash, usedmap);
FFLUSH(stdout);
}
PRINTF("\t: [num_buckets] %d\n", num_buckets);
FFLUSH(stdout);
}
/* Note: *shr_sub_size keeps track of total subscript area in lock space. Initialize *shr_sub_size to 0 before calling this.
* lke_showtree() will keep adding on previous value of shr_sub_size. If such info is not needed simply pass NULL to shr_sub_size.
* Also, caller must check if the hash table is external. If so, make a copy and point ctl->blkhash at it.
*/
bool lke_showtree(struct CLB *lnk,
mlk_pvtctl_ptr_t pctl,
bool all,
bool wait,
pid_t pid,
mstr one_lock,
bool memory,
int *shr_sub_size)
{
mlk_shrblk_ptr_t node, start[KDIM];
mlk_shrblk_ptr_t tree;
mlk_ctldata_ptr_t ctl;
unsigned char subscript_offset[KDIM];
static char name_buffer[MAX_ZWR_KEY_SZ + 1];
static MSTR_DEF(name, 0, name_buffer);
int depth = 0;
bool locks = FALSE;
int string_size = 0;
ctl = pctl->ctl;
assert(ctl && ctl->blkroot);
tree = (mlk_shrblk_ptr_t)R2A(ctl->blkroot);
if (memory)
{
lke_show_memory(tree, " ");
if (shr_sub_size)
(*shr_sub_size) = ctl->subfree - ctl->subbase;
lke_show_hashtable(pctl);
return TRUE;
}
node = start[0]
= mlk_shrblk_sort(tree);
subscript_offset[0] = 0;
for (;;)
{
name.len = subscript_offset[depth];
assertpro(node->value);
string_size += MLK_SHRSUB_SIZE((mlk_shrsub_ptr_t)R2A(node->value));
/* Display the lock node */
locks = lke_showlock(lnk, node, &name, all, wait, TRUE, pid, one_lock, FALSE)
|| locks;
/* Move to the next node */
if (node->children == 0)
{
/* This node has no children, so move to the right */
node = (mlk_shrblk_ptr_t)R2A(node->rsib);
while (node == start[depth])
{
/* There are no more siblings to the right at this depth,
so move up and then right */
if (node->parent == 0)
{
/* We're already at the top, so we're done */
assert(depth == 0);
if (shr_sub_size)
(*shr_sub_size) = string_size;
return locks;
}
--depth;
node = (mlk_shrblk_ptr_t)R2A(((mlk_shrblk_ptr_t)R2A(node->parent))->rsib);
}
}
else
{
/* This node has children, so move down */
++depth;
node = start[depth]
= mlk_shrblk_sort((mlk_shrblk_ptr_t)R2A(node->children));
subscript_offset[depth] = name.len;
}
if (util_interrupt)
rts_error_csa(CSA_ARG(NULL) VARLSTCNT(1) ERR_CTRLC);
}
}
|