File: gv_srch_map.c

package info (click to toggle)
fis-gtm 6.3-014-3
  • links: PTS, VCS
  • area: main
  • in suites: bullseye
  • size: 36,680 kB
  • sloc: ansic: 333,039; asm: 5,180; csh: 4,956; sh: 1,924; awk: 291; makefile: 66; sed: 13
file content (171 lines) | stat: -rw-r--r-- 5,916 bytes parent folder | download | duplicates (3)
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
/****************************************************************
 *								*
 * Copyright (c) 2013-2017 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"

#include "gdsroot.h"
#include "gdsbt.h"
#include "gdsfhead.h"
#include "gvcst_protos.h"	/* needed by OPEN_BASEREG_IF_STATSREG */

/* Searches a global directory map array for which map entry an input "key" falls in.
 * "key" could be an unsubscripted or subscripted global reference.
 * "skip_basedb_open" is set to TRUE in a special case from a call in "gvcst_init_statsDB" and is FALSE otherwise.
 *	In that special case, the caller knows to set the ^%YGS map entry to point to the appropriate statsdb region
 *	so we do not need to do unnecessary opens of other basedb regions. But otherwise this function ensures that
 *	if ever a map entry is returned that points to a statsdb region, the corresponding basedb region has been opened.
 */
gd_binding *gv_srch_map(gd_addr *addr, char *key, int key_len, boolean_t skip_basedb_open)
{
	int		res;
	int		low, high, mid;
	gd_binding	*map_start, *map;
#	ifdef DEBUG
	int		dbg_match;
#	endif

	map_start = addr->maps;
	assert(('%' == map_start[1].gvkey.addr[0]) && (1 == map_start[1].gvname_len));
	/* We expect all callers to search for global names that start with "^%" or higher. */
	assert(0 <= memcmp(key, &(map_start[1].gvkey.addr[0]), key_len));
	low = 2;	/* get past local locks AND first map entry which is always "%" */
	high = addr->n_maps - 1;
	DEBUG_ONLY(dbg_match = -1;)
	/* At all times in the loop, "low" corresponds to the smallest possible value for "map"
	 * and "high" corresponds to the highest possible value for "map".
	 */
	do
	{
		if (low == high)
		{
			assert((-1 == dbg_match) || (low == dbg_match));
			map = &map_start[low];
			if (!skip_basedb_open)
				OPEN_BASEREG_IF_STATSREG(map);	/* can modify map->reg.addr if statsDBReg */
			return map;
		}
		assert(low < high);
		mid = (low + high) / 2;
		assert(low <= mid);
		assert(mid < high);
		map = &map_start[mid];
		res = memcmp(key, &(map->gvkey.addr[0]), key_len);
		if (0 > res)
			high = mid;
		else if (0 < res)
			low = mid + 1;
		else if (key_len < (map->gvkey_len - 1))
			high = mid;
		else
		{
			assert(key_len == (map->gvkey_len - 1));
			low = mid + 1;
#			ifdef DEBUG
			dbg_match = low;
#			else
			map = &map_start[low];
			if (!skip_basedb_open)
				OPEN_BASEREG_IF_STATSREG(map);	/* can modify map->reg.addr if statsDBReg */
			return map;
#			endif
		}
	} while (TRUE);
}

/* Similar to gv_srch_map except that it does a linear search starting at a specific map and going FORWARD.
 * We expect this function to be invoked in case the caller expects the target map to be found very close to the current map.
 * This might be faster in some cases than a binary search of the entire gld map array (done by gv_srch_map).
 */
gd_binding *gv_srch_map_linear(gd_binding *start_map, char *key, int key_len)
{
	gd_binding	*map;
	int		res;
#	ifdef DEBUG
	gd_addr		*addr;
	DCL_THREADGBL_ACCESS;

	SETUP_THREADGBL_ACCESS;
#	endif
	map = start_map;
	DEBUG_ONLY(
		addr = TREF(gd_targ_addr);
		assert(map > addr->maps);
	)
	for ( ; ; map++)
	{
		/* Currently, the only callers of this function are gvcst_spr_* functions (e.g. "gvcst_spr_data" etc.).
		 * And most of them (except gvcst_spr_query/gvcst_start_queryget) start an implicit TP transaction right
		 * after this call. And since statsDB init is deferred once in TP, it is preferable to do the init before
		 * the TP begins. So we include the OPEN_BASEREG_IF_STATSREG macro call here instead of in each of the
		 * caller. This can be moved back to the individual callers if new callers of this function happen which
		 * don't need this macro.
		 */
		OPEN_BASEREG_IF_STATSREG(map);	/* can modify map->reg.addr if statsDBReg */
		assert(map < &addr->maps[addr->n_maps]);
		res = memcmp(key, &map->gvkey.addr[0], key_len);
		if (0 < res)
			continue;
		if (0 > res)
			break;
		/* res == 0 at this point */
		if (key_len < (map->gvkey_len - 1))
			break;
		assert(key_len == (map->gvkey_len - 1));
		map++;
		break;
	}
	OPEN_BASEREG_IF_STATSREG(map);	/* can modify map->reg.addr if statsDBReg */
	return map;
}

/* Similar to gv_srch_map_linear except that it does the linear search going BACKWARD. */
gd_binding *gv_srch_map_linear_backward(gd_binding *start_map, char *key, int key_len)
{
	gd_binding	*map;
	int		res;
#	ifdef DEBUG
	gd_addr		*addr;
	DCL_THREADGBL_ACCESS;

	SETUP_THREADGBL_ACCESS;
#	endif
	map = start_map;
	DEBUG_ONLY(
		addr = TREF(gd_targ_addr);
		assert(map < &addr->maps[addr->n_maps]);
	)
	for ( ; ; map--)
	{
		/* Currently, the only caller of this function is "gvcst_spr_zprevious". And it starts an implicit TP transaction
		 * right after this call. And since statsDB init is deferred once in TP, it is preferable to do the init before
		 * the TP begins. So we include the OPEN_BASEREG_IF_STATSREG macro call here instead of in each of the
		 * caller. This can be moved back to the individual callers if new callers of this function happen which
		 * don't need this macro.
		 */
		OPEN_BASEREG_IF_STATSREG(map);	/* can modify map->reg.addr if statsDBReg */
		assert(map >= addr->maps);
		res = memcmp(key, &map->gvkey.addr[0], key_len);
		if (0 < res)
			break;
		if (0 > res)
			continue;
		/* res == 0 at this point */
		if (key_len < (map->gvkey_len - 1))
			continue;
		assert(key_len == (map->gvkey_len - 1));
		break;
	}
	map++;
	assert(map > addr->maps);
	OPEN_BASEREG_IF_STATSREG(map);	/* can modify map->reg.addr if statsDBReg */
	return map;
}