데이터셋 I/O API
본 부록에서는 데이터셋 I/O API의 인터페이스를 사용하여 C로 작성된 애플리케이션 프로그램에서 데이터셋의 레코 드에 대해 읽기/쓰기를 수행하는 방법에 대해서 설명한다.
1. 개요
OpenFrame에서 제공하는 데이터셋 I/O API의 인터페이스를 사용하면, C 언어로 작성된 애플리케이션 프로그램에서 JCL의 DD 문장으로 할당된 데이터셋에 대한 레코드의 읽기/쓰기를 수행할 수 있다.
Main COBOL 애플리케이션 프로그램에서 Open된 데이터셋을 C로 작성된 서브 프로그램에서 읽기/쓰기 등의 I/O를 수행하기 위해서는 FCD Handling API 라이브러리를 사용할 것을 권장한다. |
데이터셋 I/O API를 사용해서 프로그램을 작성하려면, OpenFrame 바이너리와 함께 배포되는 tcfh.h 헤더 파일을 사용자 프로그램에 포함해야 하고, 사용자 프로그램을 컴파일할 때, libtcfh.so 라이브러리를 링크해야 한다.
데이터셋 I/O API의 인터페이스는 다음과 같이 분류할 수 있다.
-
File Open/Close
API 설명 레코드를 처리하기 위해 데이터셋을 연다.
레코드를 처리하기 위해 열었던 데이터셋을 닫는다.
-
Record Access
API 설명 순차처리를 위해 내부 레코드 포인터를 이동시킨다.
데이터셋에서 레코드 하나를 읽는다.
데이터셋에 레코드 하나를 기록한다.
데이터셋에 있는 한 레코드의 내용을 변경한다.
데이터셋에 있는 한 레코드를 삭제한다.
-
PDS Member Handling
API 설명 데이터셋의 디렉터리 리스트를 구성한다.
데이터셋의 디렉터리 리스트를 조회한다.
데이터셋의 디렉터리 리스트를 이용하여 멤버에 접근한다.
데이터셋의 멤버명을 이용하여 멤버에 접근한다.
데이터셋의 멤버 추가, 교체, 변경, 삭제, 초기화를 한다.
2. File Open/Close
2.1. tcfh_open()
레코드를 처리하기 위해 데이터셋을 연다. 데이터셋을 Open하는 작업은 JCL에서 DD 문으로 할당된 데이터셋에 대해 실제 레코드를 읽기/쓰기 등의 I/O를 하기 위해 준비하는 과정이다.
-
프로토타입
int tcfh_open(tcfh_file_t *file, int open_mode, int flags);
-
파라미터
파라미터 설명 file (입력/출력)
열려고 하는 데이터셋에 대한 정보를 담은 파일 구조체이다.
open_mode (입력)
데이터셋 OPEN 모드이다.
-
INPUT
-
OUTPUT
-
INOUT
-
EXTEND
flags (입력)
데이터셋 OPEN 옵션이다.
-
NO REWIND
-
VB MOVE: VB 데이터 셋을 열 때 RDW를 레코드 길이에 포함하지 않도록 한다.
-
-
반환값
정상적으로 실행된 경우 0을 반환하고 에러가 발생한 경우 음수의 에러 코드를 반환한다.
-
참고
데이터셋을 열기 위해서는 열려고 하는 데이터셋에 대한 정보를 담은 파일 구조체의 포인터를 제공해야 한다. 이 파일 구조체는 tcfh.h 헤더 파일에 정의되어 있다.
/* -------------------------- file I/O block --------------------------- */ typedef struct tcfh_file_s { char file_name[8+2]; /* file name - SELECT clause */ char file_status[2]; /* file status - I/O interface */ uint8_t organization; /* organization - SELECT clause */ uint8_t access_mode; /* access mode - SELECT clause */ uint8_t open_mode; /* open mode - tcfh_open() */ uint8_t misc_flags; /* miscellaneous - SELECT clause */ /* 64 bit separating line */ char file_path[256]; /* file path - tcfh_open() */ /* 64 bit separating line */ int32_t file_handle; /* file handle - tcfh_open() */ int32_t relative_key; /* relative key - C(C++) program */ /* 64 bit separating line */ int16_t key_length; /* key length - DCL statement */ int16_t key_loc; /* key position - DCL statement */ int16_t rec_size; /* record size - DCL statement */ int16_t cur_reclen; /* current record length - I/O interface */ ... } tcfh_file_t;
앞의 파일 구조체에서 Open할 때 지정해 주어야 하는 항목은 다음과 같다.
항목 설명 file_name
JCL에 기술된 DD 이름이다.
organization
데이터셋의 구조이다.
-
0 : 순차
-
1 : 상대
-
2 : 인덱스
acess_mode
액세스 모드이다.
-
0 : 순차
-
1 : 임의
-
2 : 둘 다
데이터셋을 열 때 tcfh_open() API의 파라미터로 OPEN 모드를 명시해야 한다. 지원되는 데이터셋 OPEN 모드는 다음과 같다.
매크로 OPEN 모드 설명 TCFH_OPEN_INPUT
0
INPUT 모드이다.
TCFH_OPEN_OUTPUT
1
OUTPUT 모드이다.
TCFH_OPEN_INOUT
2
INPUT/OUTPUT 모드이다.
TCFH_OPEN_EXTEND
3
EXTEND 모드이다.
성공적으로 데이터셋이 열린 경우 파일 구조체의 file_status, file_path, file_handle 등의 값이 설정된다.
-
2.2. tcfh_close()
레코드를 처리하기 위해 열었던 데이터셋을 닫는다. 데이터셋을 Close하는 작업은 애플리케이션에서 데이터셋에 대한 읽기/쓰기 등의 I/O를 수행한 후에 애플리케이션과 물리적인 데이터셋과의 연결을 끊는 과정이다.
-
프로토타입
int tcfh_close(tcfh_file_t *file, int flags);
-
파라미터
파라미터 설명 file (입력/출력)
닫으려고 하는 데이터셋에 대한 정보를 담은 파일 구조체이다.
flags (입력)
데이터셋 닫기 옵션이다.
-
WITH LOCK
-
-
반환값
정상적으로 실행된 경우 0을 반환하고 에러가 발생한 경우 음수의 에러 코드를 반환한다.
-
참고
CLOSE 명령의 참고할 사항은 다음과 같다.
-
tcfh_close() API의 file 파라미터에는 tcfh_open() API에 제공되었던 파일 구조체의 포인터를 전달한다.
-
tcfh_close() API를 사용해서 성공적으로 CLOSE 된 데이터셋은 tcfh_open() API를 사용해서 다시 Open할 수 있다.
-
3. Record Access
3.1. tcfh_start()
RELATIVE 데이터셋 또는 INDEXED 데이터셋에서 다음 번에 읽을 레코드 위치로 내부 레코드 포인터를 이동시킨다. 이동시킬 레코드의 위치는 RELATIVE 데이터셋의 경우에는 파일 구조체의 relative_key 필드에 상대 레코드 번호를 지정하고, INDEXED 데이터셋의 경우에는 tcfh_start() API의 key 파라미터에 키 값을 지정한다.
-
프로토타입
int tcfh_start(tcfh_file_t *file, char *key, int keylen, int flags);
-
파라미터
파라미터 설명 file (입력/출력)
처리하려고 하는 데이터셋에 대한 정보를 담은 파일 구조체이다.
key (입력/출력)
인덱스 데이터셋인 경우 키 값이다.
keylen (입력)
인덱스 데이터셋인 경우 키 길이이다.
flags (입력)
데이터셋 START 옵션이다.
-
EQUAL
-
GTEQ
-
-
반환값
정상적으로 실행된 경우 0을 반환하고 에러가 발생한 경우 음수의 에러 코드를 반환한다.
-
주의사항
START 명령의 주의사항은 다음과 같다.
-
데이터셋을 INPUT 또는 INOUT 모드로 열어야만 START 명령을 수행할 수 있다.
-
명령을 수행한 후 파일 구조체의 file_status로 파일의 상태를 조사할 수 있다.
-
RELATIVE 데이터셋인 경우 RRN은 파일 구조체의 relative_key 필드를 사용한다.
-
3.2. tcfh_read()
순차적으로 데이터셋의 레코드를 읽거나 키를 지정해서 랜덤하게 레코드를 읽는다.
랜덤하게 레코드를 읽을 때는 RELATIVE 데이터셋의 경우에는 파일 구조체의 relative_key 필드에 상대 레코드 번호를 지정하고, INDEXED 데이터셋의 경우에는 tcfh_read() API이 key 파라미터에 키 값을 지정한다.
순차적으로 데이터셋의 레코드를 읽는 경우에는 tcfh_read() API의 flags 파라미터에 TCFH_READ_NEXT 매크로를 지정하고, 랜덤하게 레코드를 읽을 때는 TCFH_READ_DEFAULT 매크로를 지정한다.
가변 길이 레코드 데이터셋의 경우 READ 명령을 사용해서 데이터셋의 레코드를 읽었을 때 파일 구조체의 cur_reclen 필드를 조사해서 읽은 레코드의 길이를 얻을 수 있다. 이 때 얻은 레코드의 길이는 tcfh_read() API의 buf 파라미터로 지정된 버퍼에 복사된 레코드 데이터의 길이, 즉, RDW를 제외한 레코드의 데이터 부분의 길이이다.
-
프로토타입
tcfh_read(tcfh_file_t *file, char *key, int keylen, char *buf, int buflen, int flags);
-
파라미터
파라미터 설명 file (입력/출력)
처리하려고 하는 데이터셋에 대한 정보를 담은 파일 구조체이다.
key (입력/출력)
인덱스 데이터셋인 경우 키 값이다.
keylen (입력)
인덱스 데이터셋인 경우 키 길이이다.
buf (출력)
레코드 데이터를 담기 위한 버퍼이다.
buflen (입력)
레코드 데이터 버퍼 크기이다.
flags (입력)
데이터셋 READ 옵션이다.
-
DEFAULT
-
NEXT
-
-
반환값
정상적으로 실행된 경우 0을 반환하고 에러가 발생한 경우 음수의 에러 코드를 반환한다.
-
주의사항
READ 명령의 주의사항은 다음과 같다.
-
데이터셋을 INPUT 또는 INOUT 모드로 열어야만 READ 명령을 수행할 수 있다.
-
명령을 수행한 후 파일 구조체의 file_status로 파일의 상태를 조사할 수 있다.
-
RELATIVE 데이터셋인 경우 RRN은 파일 구조체의 relative_key 필드를 사용한다.
-
읽은 레코드 데이터의 길이는 파일 구조체의 cur_reclen 필드에서 구한다.
-
3.3. tcfh_write()
데이터셋에 새로운 레코드를 기록한다. 순차 데이터셋의 경우에는 데이터셋의 마지막에 레코드를 기록하고, RELATIVE 데이터셋의 경우에는 파일 구조체의 relative_key 필드에 지정된 상대 레코드 번호 위치에 레코드를 기록한다. INDEXED 데이터셋의 경우에는 tcfh_write() API의 key 파라미터에 지정된 키 순서에 맞게 레코드가 저장된다.
가변 길이 레코드 데이터셋의 경우 WRITE 명령을 사용해서 데이터셋의 레코드를 기록할 때 기록하려는 레코드의 길이는 tcfh_write() API의 buflen 파라미터에 지정한다. 이때, 지정하는 레코드의 길이는 tcfh_write() API의 buf 파라미터로 지정된 버퍼에 담기 레코드 데이터의 길이, 즉, RDW를 제외한 레코드의 데이터 부분의 길이를 지정한다.
-
프로토타입
tcfh_write(tcfh_file_t *file, char *key, int keylen, char *buf, int buflen, int flags);
-
파라미터
파라미터 설명 file (입력/출력)
처리하려고 하는 데이터셋에 대한 정보를 담은 파일 구조체이다.
key (입력/출력)
인덱스 데이터셋인 경우 키 값이다.
keylen (입력)
인덱스 데이터셋인 경우 키 길이이다.
buf (출력)
레코드 데이터를 담고 있는 버퍼이다.
buflen (입력)
레코드 데이터의 길이이다.
flags (입력)
데이터셋 WRITE 옵션이다.
-
반환값
정상적으로 실행된 경우 0을 반환하고 에러가 발생한 경우 음수의 에러 코드를 반환한다.
-
주의사항
WRITE 명령의 주의사항은 다음과 같다.
-
OUTPUT, INOUT 또는 EXTEND 모드로 열어야만 WRITE 명령을 사용할 수 있다.
-
INOUT 모드로 연 경우 순차 액세스를 통한 WRITE는 불가능하다.
-
명령을 수행한 후 파일 구조체의 file_status로 파일의 상태를 조사할 수 있다.
-
RELATIVE 데이터셋인 경우 RRN은 파일 구조체의 relative_key 필드를 사용한다.
-
3.4. tcfh_rewrite()
데이터셋에 있는 기존 레코드의 내용을 변경한다. RELATIVE 데이터셋의 경우에는 파일 구조체의 relative_key 필드에 지정된 상대 레코드 번호 위치에 있는 레코드를 변경한다. INDEXED 데이터셋의 경우에는 tcfh_rewrite() API의 key 파라미터에 지정된 키 순서에 맞는 레코드가 변경된다.
가변 길이 레코드 데이터셋의 경우 REWRITE 명령을 사용해서 데이터셋의 레코드를 변경할 때 변경하려는 레코드의 길이는 tcfh_rewrite() API의 buflen 파라미터에 지정한다. 이때, 지정하는 레코드의 길이는 tcfh_rewrite() API의 buf 파라미터로 지정된 버퍼에 담긴 레코드 데이터의 길이, 즉, RDW를 제외한 레코드의 데이터 부분의 길이를 지정한다.
-
프로토타입
tcfh_rewrite(tcfh_file_t *file, char *key, int keylen, char *buf, int buflen, int flags);
-
파라미터
파라미터 설명 file (입력/출력)
처리하려고 하는 데이터셋에 대한 정보를 담은 파일 구조체이다.
key (입력)
인덱스 데이터셋인 경우 키 값이다.
keylen (입력)
인덱스 데이터셋인 경우 키 길이이다.
buf (입력)
레코드 데이터를 담고 있는 버퍼이다.
buflen (입력)
레코드 데이터의 길이이다.
flags (입력)
데이터셋 REWRITE 옵션이다.
-
반환값
정상적으로 실행된 경우 0을 반환하고 에러가 발생한 경우 음수의 에러 코드를 반환한다.
-
주의사항
REWRITE 명령의 주의사항은 다음과 같다.
-
데이터셋을 INOUT 모드로 열어야만 REWRITE 명령을 사용할 수 있다.
-
순차 액세스인 경우 REWRITE 전에 READ로 변경할 레코드를 읽어야 한다.
-
명령을 수행한 후 파일 구조체의 file_status로 파일의 상태를 조사할 수 있다.
-
RELATIVE 데이터셋인 경우 RRN은 파일 구조체의 relative_key 필드를 사용한다.
-
3.5. tcfh_delete()
RELATIVE 데이터셋이나 INDEXED 데이터셋의 경우 데이터셋에 있는 레코드를 삭제한다. RELATIVE 데이터셋의 경우에는 파일 구조체의 relative_key 필드에 지정된 상대 레코드 번호 위치에 있는 레코드를 삭제한다. INDEXED 데이터셋의 경우에는 tcfh_delete() API의 key 파라미터에 지정된 키 순서에 맞는 레코드가 삭제된다.
-
프로토타입
int tcfh_delete(tcfh_file_t *file, char *key, int keylen, int flags);
-
파라미터
파라미터 설명 file (입력/출력)
처리하려고 하는 데이터셋에 대한 정보를 담은 파일 구조체이다.
key (입력)
인덱스 데이터셋인 경우 키 값이다.
keylen (입력)
인덱스 데이터셋인 경우 키 길이이다.
flags (입력)
데이터셋 DELETE 옵션이다.
-
반환값
정상적으로 실행된 경우 0을 반환하고 에러가 발생한 경우 음수의 에러 코드를 반환한다.
-
주의사항
DELETE 명령의 주의사항은 다음과 같다.
-
데이터셋을 INOUT 모드로 열어야만 DELETE 명령을 사용할 수 있다.
-
순차 액세스인 경우 DELETE 전에 READ로 삭제할 레코드를 읽어야 한다.
-
명령을 수행한 후 파일 구조체의 file_status로 파일의 상태를 조사할 수 있다.
-
RELATIVE 데이터셋인 경우 RRN은 파일 구조체의 relative_key 필드를 사용한다.
-
4. PDS Member Handling
4.1. tcfh_bldl()
PDS의 디렉터리 리스트를 구성한다.
-
프로토타입
int tcfh_bldl(tcfh_file_t *file, char *filter);
-
파라미터
파라미터 설명 file (입력/출력)
처리할 데이터셋에 대한 정보를 담은 파일 구조체이다.
filter (입력)
리스트를 구성할 멤버에 제한을 주는 값이다.
데이터셋의 멤버 전체를 리스트로 구성할 때는 애스터리스크(*)나 NULL 값을 지정한다. "ABC"로 시작하는 멤버만을 구성하고자 한다면 filter에 "ABC"값을 지정한다.
-
반환값
정상적으로 실행된 경우 디렉터리 리스트를 구성한 멤버의 수를 반환하고 에러가 발생한 경우 음수의 에러 코드를 반환한다.
-
참고
BLDL 명령의 참고사항은 다음과 같다.
-
명령을 수행한 후 파일 구조체의 file_status로 파일의 상태를 조사할 수 있다.
-
4.2. tcfh_bldl_info()
PDS의 디렉터리 리스트를 조회한다. tcfh_bldl()를 실행한 후 이용할 수 있다.
순차적으로 데이터셋의 레코드를 읽는 경우 tcfh_read()의 flags 파라미터에 TCFH_READ_NEXT 매크로를 지정하고, 랜덤하게 레코드를 읽을 때는 TCFH_READ_DEFAULT 매크로를 지정한다.
가변 길이 레코드 데이터셋의 경우 READ 명령을 사용해서 데이터셋의 레코드를 읽었을 때, 파일 구조체의 cur_reclen 필드를 조사해서 읽은 레코드의 길이를 얻을 수 있다. 레코드의 길이는 tcfh_read()의 buf 파라미터로 지정된 버퍼에 복사된 레코드 데이터의 길이(RDW를 제외한 레코드의 데이터 부분의 길이)이다.
-
프로토타입
int tcfh_bldl_info(tcfh_file_t *file, int number, tcfh_membstat_t *stat);
-
파라미터
파라미터 설명 file (입력/출력)
처리할 데이터셋에 대한 정보를 담은 파일 구조체이다.
number (입력)
디렉터리 리스트에서의 상대 주소값이다.
stat (출력)
인덱스 데이터셋인 경우 키 길이이다.
-
반환값
정상적으로 실행된 경우 0을 반환하고 에러가 발생한 경우 음수의 에러 코드를 반환한다.
-
참고
멤버 정보를 조회하기 위해서는 멤버에 대한 정보를 담은 파일 구조체의 포인터를 제공해야 한다. 이 파일 구조체는 tcfh.h 헤더 파일에 정의되어 있다.
/* -------------------------- file I/O block --------------------------- */ typedef struct tcfh_membstat_s { char member[64]; int64_t size; char lastmoddt[8+2]; /* last modified date */ char lastmodtm[6+2]; /* last modified time */ } tcfh_membstat_t;
앞의 파일 구조체에서 정보를 제공하는 항목은 다음과 같다.
항목 설명 member (출력)
PDS의 멤버명이 기술된다.
size (출력)
해당 멤버가 저장된 UNIX 파일의 크기를 나타낸다.
lastmoddt (출력)
해당 멤버의 마지막 수정 날짜를 나타낸다.
lastmodtm (출력)
해당 멤버의 마지막 수정 시각을 나타낸다.
4.3. tcfh_find_by_bldl()
PDS의 멤버에 접근한다. tcfh_bldl()를 실행한 후 사용할 수 있다.
-
프로토타입
int tcfh_find_by_bldl(tcfh_file_t *file, int num);
-
파라미터
파라미터 설명 file (입력/출력)
처리할 데이터셋에 대한 정보를 담은 파일 구조체이다.
num (입력)
인덱스 데이터셋인 경우 키 값이다.
-
반환값
정상적으로 실행된 경우 0을 반환하고 에러가 발생한 경우 음수의 에러 코드를 반환한다.
-
참고
FIND 명령의 참고사항은 다음과 같다.
-
명령을 수행한 후 파일 구조체의 file_status로 파일의 상태를 조사할 수 있다.
-
4.4. tcfh_find_by_name()
PDS의 멤버에 접근한다. tcfh_bldl()와는 무관하게 사용할 수 있다.
-
프로토타입
int tcfh_find_by_name(tcfh_file_t *file, char *name);
-
파라미터
파라미터 설명 file (입력/출력)
처리할 데이터셋에 대한 정보를 담은 파일 구조체이다.
name (입력)
접근할 멤버명을 지정한다.
-
반환값
정상적으로 실행된 경우 0을 반환하고 에러가 발생한 경우 음수의 에러 코드를 반환한다.
-
참고
FIND 명령의 참고사항은 다음과 같다.
-
명령을 수행한 후 파일 구조체의 file_status로 파일의 상태를 조사할 수 있다.
-
4.5. tcfh_stow()
PDS에 멤버를 추가, 교체, 삭제, 초기화를 하거나 멤버명을 변경한다.
-
프로토타입
int tcfh_stow(tcfh_file_t *file, char *name, int flags);
-
파라미터
파라미터 설명 file (입력/출력)
처리할 데이터셋에 대한 정보를 담은 파일 구조체이다.
name (입력)
처리할 멤버명을 기술한다.
멤버명을 기술하는 경우 슬래시(/) 기호로 변경 전, 변경 후의 멤버명을 구분한다. (예: "BEFORE/AFTER" )
flags (입력)
데이터셋 STOW 옵션이다.
-
TCFH_STOW_ADD
-
TCFH_STOW_DELETE
-
TCFH_STOW_CHANGE
-
TCFH_STOW_REPLACE
-
TCFH_STOW_INITIALIZE
-
-
반환값
정상적으로 실행된 경우 0을 반환하고 에러가 발생한 경우 음수의 에러 코드를 반환한다.
-
주의사항
STOW 명령의 주의사항은 다음과 같다.
-
멤버를 추가, 교체하는 경우 WRITE 명령이 선행되어야 한다.
-
명령을 수행한 후 파일 구조체의 file_status로 파일의 상태를 조사할 수 있다.
-
5. File Status Code
데이터셋에 대한 읽기/쓰기를 수행한 후, 데이터셋에 대한 상태를 확인하기 위해서는 데이터셋에 대한 정보를 담고 있는 파일 구조체의 file_status 필드를 조사한다. file_status 필드에는 데이터셋에 대한 상태 코드를 담고 있다.
다음은 데이터셋에 대한 상태 코드에 대한 설명이다.
코드 | 설명 |
---|---|
00 |
작업을 성공적으로 수행했다. |
02 |
인덱스 파일인 경우 중복 키가 허용된 데이터셋에 대해 중복 키가 발생했다. |
10 |
다음 레코드가 없다(즉, 파일을 끝까지 읽었다). |
22 |
인덱스 파일이나 상대 파일의 경우 중복 키 오류가 발생했다. |
23 |
키에 해당하는 레코드를 찾을 수 없다(FIND 명령인 경우 멤버를 찾을 수 없다). |
37 |
지정된 OPEN 모드가 지원되지 않는다. |
38 |
이미 LOCK으로 닫혀진 파일에 대해 Open을 시도했다. |
39 |
데이터셋의 속성 지정이 올바르지 않다. |
41 |
이미 열린 파일에 대해 Open을 시도했다. |
42 |
이미 닫힌 파일에 대해 Close를 시도했다. |
43 |
순차 모드에서 REWRITE나 DELETE 명령 이전 명령이 READ가 아니다. |
44 |
REWRITE하려고 하는 레코드의 길이가 기존 레코드의 길이와 같지 않다. |
47 |
INPUT이나 INOUT 모드가 아닌데 READ나 START 명령을 수행했다. |
48 |
OUTPUT, INOUT 또는 EXTEND 모드가 아닌데 WRITE 명령을 수행했다. |
49 |
INOUT 모드가 아닌데 DELETE나 REWRITE 명령을 수행했다. |
99 |
시스템 오류가 발생했다. |