File: mur_read_file_sp.c

package info (click to toggle)
fis-gtm 7.1-006-1
  • links: PTS, VCS
  • area: main
  • in suites: trixie
  • size: 32,908 kB
  • sloc: ansic: 344,906; asm: 5,184; csh: 4,859; sh: 2,000; awk: 294; makefile: 73; sed: 13
file content (186 lines) | stat: -rwxr-xr-x 7,009 bytes parent folder | download | duplicates (6)
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
182
183
184
185
186
/****************************************************************
 *								*
 * Copyright (c) 2003-2015 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 "min_max.h"
#include "gtm_fcntl.h"
#include "gtm_unistd.h"
#include "gtm_stat.h"
#include "gtm_string.h"
#include "gtm_aio.h"
#include "gtmio.h"
#ifdef __MVS__
#include "gtm_zos_io.h"
#endif
#include "gdsroot.h"
#include "gdsbt.h"
#include "gtm_facility.h"
#include "fileinfo.h"
#include "gdsfhead.h"
#include "filestruct.h"
#include "jnl.h"
#include "buddy_list.h"
#include "hashtab_mname.h"	/* needed for muprec.h */
#include "hashtab_int4.h"	/* needed for muprec.h */
#include "hashtab_int8.h"	/* needed for muprec.h */
#include "muprec.h"
#include "mur_read_file.h"
#include "iosp.h"
#include "copy.h"
#include "gtmmsg.h"
#include "repl_sp.h"		/* for F_CLOSE used by the JNL_FD_CLOSE macro */

GBLREF	mur_opt_struct	mur_options;
GBLREF 	mur_gbls_t	murgbl;

error_def(ERR_JNLFILEOPNERR);
error_def(ERR_SYSCALL);

#ifdef MUR_USE_AIO

/****************************************************************************************
 * Function Name: mur_fread_start
 * Input: struct mur_buffer_desc * buff
 * Output : SS_NORMAL on successful
 *          error status on unsuccessful
 * This function starts an asynchronous read in a given buffer
 ****************************************************************************************/
/* #GTM_THREAD_SAFE : The below function (mur_fread_start) is thread-safe */
uint4 mur_fread_start(jnl_ctl_list *jctl, mur_buff_desc_t *buff)
{
	buff->aiocbp->aio_offset = buff->dskaddr;
	buff->aiocbp->aio_buf = (char *)buff->base;
	buff->blen = MIN(MUR_BUFF_SIZE, jctl->eof_addr - buff->dskaddr);
	buff->aiocbp->aio_nbytes = buff->blen;
	buff->rip_channel = jctl->channel;	/* store channel that issued the AIO in order to use later for aio_cancel() */
	assert(!buff->read_in_progress);
	buff->read_in_progress = TRUE;
	AIO_READ(buff->rip_channel, buff->aiocbp, jctl->status, jctl->status2);
	return jctl->status;
}
/************************************************************************************
 * Function name: mur_fread_wait
 * Input : struct mur_buffer_desc *buff
 * Output: SS_NORMAL on success
 *         error status on unsuccessful
 * Purpose: The purpose of this routine is to make sure that a previously issued asysnchronous read
 *          in a given buffer has completed
 **************************************************************************************/
/* #GTM_THREAD_SAFE : The below function (mur_fread_wait) is thread-safe */
uint4 mur_fread_wait(jnl_ctl_list *jctl, mur_buff_desc_t *buff)
{
	ssize_t	nbytes;

	assert(buff->read_in_progress);
	buff->read_in_progress = FALSE;
	/* The aio_error function returns the error status associated with the specified aiocbp. If the aio_error function returns
	 * anything but EINPROGRESS, the asynchronous I/O operation has completed. Subsequently, we can fetch the status of the
	 * operation from a call to aio_return.
	 */
	AIO_ERROR(buff->aiocbp, jctl->status);
	if (-1 != jctl->status)
	{
		AIO_RETURN(buff->aiocbp, nbytes); /* if successful jctl->status will contain number of bytes read */
		if (-1 != nbytes)
		{
			if (buff->blen == nbytes)
				return (jctl->status = SS_NORMAL);
			/* AIO_READ didn't fetch the requested size chunk */
			assert(buff->blen > nbytes);
			DO_FILE_READ(buff->rip_channel, buff->dskaddr + nbytes, buff->base + nbytes, buff->blen - nbytes,
					jctl->status, jctl->status2);
			return jctl->status;
		}
	}
	return (jctl->status = errno);
}

/* #GTM_THREAD_SAFE : The below function (mur_fread_cancel) is thread-safe */
/* cancel asynchronous read */
uint4 mur_fread_cancel(jnl_ctl_list *jctl)
{
	int			status, index, save_err;
	reg_ctl_list		*rctl;
	mur_read_desc_t		*mur_desc;
	mur_buff_desc_t		*seq_buff;

	rctl = jctl->reg_ctl;
	mur_desc = rctl->mur_desc;
	/* At most one buffer can have read_in_progress, not both */
	assert(!(mur_desc->seq_buff[0].read_in_progress && mur_desc->seq_buff[1].read_in_progress));
	for (index = 0, save_err = 0; index < ARRAYSIZE(mur_desc->seq_buff); index++)
	{
		seq_buff = &mur_desc->seq_buff[index];
		if (seq_buff->read_in_progress)
		{
			AIO_CANCEL(seq_buff->rip_channel, NULL, status);
			if (-1 == status)
				save_err = errno;
			else if (AIO_NOTCANCELED == status)	/* the OS cannot cancel the aio once it has actually started */
				jctl->status = mur_fread_wait(seq_buff);	/* wait for it to finish. */
			seq_buff->read_in_progress = FALSE;
		}
	}
	/* Note that although the cancellation errored out for rip_channel, we are storing the status in jctl which need not
	 * actually be the jctl corresponding to rip_channel
	 */
	return (jctl->status = ((0 == save_err) ? SS_NORMAL : save_err));
}

#endif /* MUR_USE_AIO */

/* #GTM_THREAD_SAFE : The below function (mur_fopen_sp) is thread-safe */
/* Returns 0 (SS_NORMAL) for success; Non-zero for failure */
uint4	mur_fopen_sp(jnl_ctl_list *jctl, reg_ctl_list *rctl)
{
	struct stat		stat_buf;
	int			status, perms;
	sgmnt_addrs		*csa;
	ZOS_ONLY(int		realfiletag;)

	perms = O_RDONLY;
	jctl->read_only = TRUE;
	jctl->reg_ctl = rctl;	/* fill in reg_ctl backpointer from jctl to rctl. Note: rctl could be NULL */
	/* Both for recover and rollback open in read/write mode. We do not need to write in journal file
	 * for mupip journal extract/show/verify or recover -forward.  So open it as read-only
	 */
	if (mur_options.update && !mur_options.forward)
	{
		perms = O_RDWR;
		jctl->read_only = FALSE;
	}
	jctl->channel = OPEN((char *)jctl->jnl_fn, perms);
	if (FD_INVALID != jctl->channel)
	{
		FSTAT_FILE(jctl->channel, &stat_buf, status);
		if (-1 != status)
		{
#			ifdef __MVS__
			if (-1 == gtm_zos_tag_to_policy(jctl->channel, TAG_BINARY, &realfiletag))
				TAG_POLICY_GTM_PUTMSG((char *)jctl->jnl_fn, errno, realfiletag, TAG_BINARY);
#			endif
			jctl->os_filesize = (off_jnl_t)stat_buf.st_size;
			return SS_NORMAL;
		}
		jctl->status = errno;
		JNL_FD_CLOSE(jctl->channel, status);	/* sets jctl->channel to NOJNL */
	} else
		jctl->status = errno;
	assert(NOJNL == jctl->channel);
	csa = JCTL2CSA(jctl);	/* need JCTL2CSA macro instead of jctl->reg_ctl->csa because rctl could be NULL */
	if (ENOENT == jctl->status)	/* File Not Found is a common error, so no need for SYSCALL */
		gtm_putmsg_csa(CSA_ARG(csa) VARLSTCNT(5) ERR_JNLFILEOPNERR, 2, jctl->jnl_fn_len, jctl->jnl_fn, jctl->status);
	else
		gtm_putmsg_csa(CSA_ARG(csa) VARLSTCNT(12) ERR_JNLFILEOPNERR, 2, jctl->jnl_fn_len, jctl->jnl_fn,
			ERR_SYSCALL, 5, LEN_AND_STR((-1 == jctl->channel) ? "open" : "fstat"), CALLFROM, jctl->status);
	return ERR_JNLFILEOPNERR;
}