File: util_out_print_gtmio.c

package info (click to toggle)
fis-gtm 7.0-005-1
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 32,264 kB
  • sloc: ansic: 336,687; asm: 5,184; csh: 4,823; sh: 1,945; awk: 291; makefile: 72; sed: 13
file content (137 lines) | stat: -rw-r--r-- 4,760 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
/****************************************************************
 *								*
 * Copyright (c) 2014-2022 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 GTM_TRIGGER
#include "gtm_string.h"

#include "gtm_multi_thread.h"
#include "util.h"		/* for FLUSH and util_out_print */
#include "util_out_print_vaparm.h"
#include "op.h"			/* for op_write prototype */
#include "io.h"			/* needed for io_pair typedef */
#include "gtmimagename.h"	/* for IS_MCODE_RUNNING */

GBLREF	uint4			dollar_tlevel;

#define	ZTRIGBUFF_INIT_ALLOC		1024	/* start at 1K */
#define	ZTRIGBUFF_INIT_MAX_GEOM_ALLOC	1048576	/* stop geometric growth at this value */

/* Used by MUPIP TRIGGER or $ZTRIGGER routines to buffer trigger output until TCOMMIT time
 * (as otherwise we might display stale output due to a restarted try).
 */
void	util_out_print_gtmio(caddr_t message, int flush, ...)
{
	va_list		var;
	char		*src, *dst, *newdst;
	int		srclen, dstlen, dstalloc, newlen, ptrlen;
	caddr_t		msg;
	int4		msglen;
	DCL_THREADGBL_ACCESS;

	SETUP_THREADGBL_ACCESS;
	ASSERT_SAFE_TO_UPDATE_THREAD_GBLS;
	/* we expect all trigger operations (SELECT, LOAD, etc.) to happen inside TP. exceptions should set TREF variable */
	assert(dollar_tlevel || TREF(gtmio_skip_tlevel_assert));
	va_start(var, flush);
	/* If "!AD" has been specified as the message, skip the util_out_print_vaparm call as it is possible
	 * the input string length is > the maximum length util_out_* routines are designed to handle.
	 * In that case, we dont need the parameter substitution anyways so do a memcpy instead.
	 */
	if (STRCMP(message, "!AD") || (FLUSH != flush))
	{
		util_out_print_vaparm(message, NOFLUSH_OUT, var, MAXPOSINT4);	/* WARNING: UNCHECKED faocnt - internal use only */
		src = TREF(util_outbuff_ptr);
		assert(NULL != TREF(util_outptr));
		srclen = INTCAST(TREF(util_outptr) - src) + 1;	/* 1 is for '\n' */
		assert(OUT_BUFF_SIZE >= srclen);
	} else
	{
		srclen = (int)va_arg(var, int4) + 1;
		src = (char *)va_arg(var, caddr_t);
	}
	if (FLUSH == flush)
	{
		dstalloc = TREF(ztrigbuffAllocLen);
		dstlen = TREF(ztrigbuffLen);
		/* Leave room for terminating '\0' (after the \n) for later use in FPRINTF in tp_ztrigbuff_print.
		 * Hence the use of "<=" instead of a "<" in the "if (dstalloc <= (dstlen + srclen))" check below.
		 */
		if (dstalloc <= (dstlen + srclen))
		{	/* reallocate */
			dst = TREF(ztrigbuff);
			do
			{
				if (!dstalloc)
					dstalloc = ZTRIGBUFF_INIT_ALLOC;	/* Allocate a 1K buffer at start */
				else if (ZTRIGBUFF_INIT_MAX_GEOM_ALLOC <= dstalloc)
					dstalloc += ZTRIGBUFF_INIT_MAX_GEOM_ALLOC;
				else
					dstalloc = dstalloc * 2; /* grow geometrically until a limit and linearly after that */
			} while (dstalloc <= (dstlen + srclen));
			newdst = malloc(dstalloc);
			if (dstlen)
				memcpy(newdst, dst, dstlen);
			TREF(ztrigbuff) = newdst;
			TREF(ztrigbuffAllocLen) = dstalloc;
			if (NULL != dst)
				free(dst);
		}
		dst = TREF(ztrigbuff);
		memcpy(dst + dstlen, src, srclen - 1);
		dst[dstlen + srclen - 1] = '\n';
		TREF(ztrigbuffLen) += srclen;
		TREF(util_outptr) = TREF(util_outbuff_ptr);	/* Signal text is flushed */
	}
	va_end(TREF(last_va_list_ptr));
	va_end(var);
}

void	tp_ztrigbuff_print(void)
{
	mval		flushtxt;
	char		*ptr, *ptrtop, *ptr2;
	int		len;
	DCL_THREADGBL_ACCESS;

	SETUP_THREADGBL_ACCESS;
	/* If mumps process doing trigger operations, use GTM IO routines. If not use util_out_print. The only
	 * exception is if the MUPIP caller wants to use current IO device (i.e. it has it all set up). In that
	 * case the TREF ztrig_use_io_curr_device would have been set to TRUE.
	 */
	if (IS_MCODE_RUNNING || TREF(ztrig_use_io_curr_device))
	{
		ptr = TREF(ztrigbuff);
		assert('\n' == ptr[TREF(ztrigbuffLen) - 1]);
		ptrtop = ptr + TREF(ztrigbuffLen);
		flushtxt.mvtype = MV_STR;
		do
		{
			len = INTCAST(ptrtop - ptr);
			ptr2 = memchr(ptr, '\n', len);
			assert(NULL != ptr2);
			flushtxt.str.addr = ptr;
			flushtxt.str.len = ptr2 - ptr;
			op_write(&flushtxt);
			op_wteol(1);
			ptr = ptr2 + 1;
		} while (ptr < ptrtop);
	} else
	{	/* Use util_out_print but since you pass TRUE for flush, use -1 to prevent duplicate newline */
		assert('\n' == (TREF(ztrigbuff))[TREF(ztrigbuffLen) - 1]);
		assert(TREF(ztrigbuffLen) < TREF(ztrigbuffAllocLen));
		(TREF(ztrigbuff))[TREF(ztrigbuffLen)] = '\0';
		FPRINTF(stderr, "%s", TREF(ztrigbuff));
	}
}
#endif