401 lines
8.8 KiB
C
401 lines
8.8 KiB
C
/*
|
|
* CDE - Common Desktop Environment
|
|
*
|
|
* Copyright (c) 1993-2012, The Open Group. All rights reserved.
|
|
*
|
|
* These libraries and programs are free software; you can
|
|
* redistribute them and/or modify them under the terms of the GNU
|
|
* Lesser General Public License as published by the Free Software
|
|
* Foundation; either version 2 of the License, or (at your option)
|
|
* any later version.
|
|
*
|
|
* These libraries and programs are distributed in the hope that
|
|
* they will be useful, but WITHOUT ANY WARRANTY; without even the
|
|
* implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
|
* PURPOSE. See the GNU Lesser General Public License for more
|
|
* details.
|
|
*
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
* License along with these librararies and programs; if not, write
|
|
* to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
|
|
* Floor, Boston, MA 02110-1301 USA
|
|
*/
|
|
//%% (c) Copyright 1993, 1994 Hewlett-Packard Company
|
|
//%% (c) Copyright 1993, 1994 International Business Machines Corp.
|
|
//%% (c) Copyright 1993, 1994 Sun Microsystems, Inc.
|
|
//%% (c) Copyright 1993, 1994 Novell, Inc.
|
|
//%% $XConsortium: tt_isam_file.C /main/3 1995/10/20 16:43:39 rswiston $
|
|
/*
|
|
* tt_isam_file.cc - Defines the TT ISAM file class. This class simplifies
|
|
* opening, closing, reading and writing an ISAM file.
|
|
*
|
|
* Copyright (c) 1992 by Sun Microsystems, Inc.
|
|
*/
|
|
|
|
#include "tt_isam_file.h"
|
|
#include "util/tt_port.h"
|
|
#include "dm_access_cache.h"
|
|
|
|
extern FILE *errstr;
|
|
|
|
bool_t _Tt_isam_file::isamFatalErrorHandlerSet = FALSE;
|
|
|
|
_Tt_isam_file::_Tt_isam_file (const _Tt_string &file, int mode)
|
|
{
|
|
setTtISAMFileDefaults();
|
|
fileName = file;
|
|
fileMode = mode;
|
|
|
|
if ((fileDescriptor = cached_isopen(file, mode)) != -1) {
|
|
getISAMFileInfo();
|
|
}
|
|
else {
|
|
getStatusInfo();
|
|
}
|
|
}
|
|
|
|
_Tt_isam_file
|
|
::_Tt_isam_file (const _Tt_string &file,
|
|
int max_record_length,
|
|
int min_record_length,
|
|
_Tt_isam_key_descriptor_ptr primary_key_descriptor,
|
|
int mode)
|
|
{
|
|
setTtISAMFileDefaults();
|
|
fileName = file;
|
|
fileMode = mode;
|
|
|
|
if ((fileDescriptor = cached_isopen(file, mode)) == -1) {
|
|
newFlag = TRUE;
|
|
isreclen = min_record_length;
|
|
fileDescriptor = isbuild(file,
|
|
max_record_length,
|
|
primary_key_descriptor->getKeyDescriptor(),
|
|
mode);
|
|
}
|
|
|
|
if (fileDescriptor != -1) {
|
|
getISAMFileInfo();
|
|
}
|
|
else {
|
|
errorStatus = iserrno;
|
|
currentRecordLength = -1;
|
|
currentRecordNumber = -1;
|
|
}
|
|
}
|
|
|
|
void _Tt_isam_file::setTtISAMFileDefaults ()
|
|
{
|
|
eraseFlag = FALSE;
|
|
fileName = (char *)NULL;
|
|
fileMode = 0;
|
|
keyDescriptorList = new _Tt_isam_key_descriptor_list;
|
|
newFlag = FALSE;
|
|
|
|
if (!isamFatalErrorHandlerSet) {
|
|
isamFatalErrorHandlerSet = TRUE;
|
|
(void)iscntl(ALLISFD, ISCNTL_FATAL, &_Tt_isam_file::isamFatalErrorHandler);
|
|
}
|
|
|
|
iserrno = 0;
|
|
}
|
|
|
|
_Tt_isam_file::~_Tt_isam_file ()
|
|
{
|
|
if (eraseFlag) {
|
|
(void)iserase(fileName);
|
|
}
|
|
else {
|
|
(void)cached_isclose(fileDescriptor);
|
|
}
|
|
}
|
|
|
|
void _Tt_isam_file::setErase (bool_t flag)
|
|
{
|
|
eraseFlag = flag;
|
|
}
|
|
|
|
int _Tt_isam_file::sync ()
|
|
{
|
|
iserrno = 0;
|
|
|
|
(void)isfsync(fileDescriptor);
|
|
|
|
errorStatus = iserrno;
|
|
return errorStatus;
|
|
}
|
|
|
|
//
|
|
// islock and isunlock are not supported by mini-isam
|
|
//
|
|
//int _Tt_isam_file::lock ()
|
|
//{
|
|
// iserrno = 0;
|
|
//
|
|
// (void)islock(fileDescriptor);
|
|
//
|
|
// errorStatus = iserrno;
|
|
// return errorStatus;
|
|
//}
|
|
//
|
|
//int _Tt_isam_file::unlock ()
|
|
//{
|
|
// iserrno = 0;
|
|
//
|
|
// (void)isunlock(fileDescriptor);
|
|
//
|
|
// errorStatus = iserrno;
|
|
// return errorStatus;
|
|
//}
|
|
|
|
int _Tt_isam_file::rename (const _Tt_string &new_file)
|
|
{
|
|
iserrno = 0;
|
|
|
|
int results = isrename(fileName, new_file);
|
|
|
|
errorStatus = iserrno;
|
|
if (!results) {
|
|
fileName = new_file;
|
|
newFlag = FALSE;
|
|
|
|
if ((fileDescriptor = cached_isopen(new_file, fileMode)) != -1) {
|
|
getISAMFileInfo();
|
|
}
|
|
else {
|
|
getStatusInfo();
|
|
}
|
|
}
|
|
|
|
return errorStatus;
|
|
}
|
|
|
|
int _Tt_isam_file::addIndex (_Tt_isam_key_descriptor_ptr key_descriptor)
|
|
{
|
|
iserrno = 0;
|
|
|
|
int results = isaddindex(fileDescriptor, key_descriptor->getKeyDescriptor());
|
|
|
|
errorStatus = iserrno;
|
|
if (!results) {
|
|
getISAMFileInfo();
|
|
}
|
|
|
|
return errorStatus;
|
|
}
|
|
|
|
_Tt_isam_record_ptr _Tt_isam_file::getEmptyRecord ()
|
|
{
|
|
return (new _Tt_isam_record(keyDescriptorList,
|
|
maxRecordLength,
|
|
minRecordLength));
|
|
}
|
|
|
|
int _Tt_isam_file
|
|
::findStartRecord (const _Tt_isam_key_descriptor_ptr &key_descriptor,
|
|
int length,
|
|
const _Tt_isam_record_ptr &record,
|
|
int mode)
|
|
{
|
|
iserrno = 0;
|
|
|
|
(void)isstart(fileDescriptor,
|
|
key_descriptor->getKeyDescriptor(),
|
|
length,
|
|
(char *)record->getRecord(),
|
|
mode);
|
|
|
|
getStatusInfo();
|
|
return errorStatus;
|
|
}
|
|
|
|
_Tt_isam_record_ptr _Tt_isam_file::readRecord (int mode)
|
|
{
|
|
iserrno = 0;
|
|
|
|
_Tt_isam_record_ptr record = (_Tt_isam_record *)NULL;
|
|
_Tt_string record_buffer(maxRecordLength);
|
|
int results = isread(fileDescriptor,
|
|
(char *)record_buffer,
|
|
mode);
|
|
|
|
getStatusInfo();
|
|
if (!results) {
|
|
record = getFullRecord(record_buffer);
|
|
}
|
|
|
|
return record;
|
|
}
|
|
|
|
int _Tt_isam_file::readRecord (int mode,
|
|
const _Tt_isam_record_ptr &record)
|
|
{
|
|
iserrno = 0;
|
|
|
|
int results = isread(fileDescriptor, (char *)record->getRecord(), mode);
|
|
|
|
getStatusInfo();
|
|
if (!results) {
|
|
record->setLength(currentRecordLength);
|
|
}
|
|
|
|
return errorStatus;
|
|
}
|
|
|
|
int _Tt_isam_file::updateCurrentRecord (const _Tt_isam_record_ptr &record)
|
|
{
|
|
iserrno = 0;
|
|
|
|
isreclen = record->getLength();
|
|
(void)isrewcurr(fileDescriptor, (char *)record->getRecord());
|
|
|
|
getStatusInfo();
|
|
return errorStatus;
|
|
}
|
|
|
|
int
|
|
_Tt_isam_file::updateRecord (long recnum, const _Tt_isam_record_ptr &record)
|
|
{
|
|
iserrno = 0;
|
|
|
|
isreclen = record->getLength();
|
|
(void)isrewrec(fileDescriptor, recnum, (char *)record->getRecord());
|
|
|
|
getStatusInfo();
|
|
return errorStatus;
|
|
}
|
|
|
|
int _Tt_isam_file::writeRecord (const _Tt_isam_record_ptr &record)
|
|
{
|
|
iserrno = 0;
|
|
|
|
isreclen = record->getLength();
|
|
(void)iswrite(fileDescriptor, (char *)record->getRecord());
|
|
|
|
getStatusInfo();
|
|
return errorStatus;
|
|
}
|
|
|
|
int _Tt_isam_file::deleteCurrentRecord ()
|
|
{
|
|
iserrno = 0;
|
|
|
|
(void)isdelcurr(fileDescriptor);
|
|
|
|
getStatusInfo();
|
|
return errorStatus;
|
|
}
|
|
|
|
int _Tt_isam_file::deleteRecord (long recnum)
|
|
{
|
|
iserrno = 0;
|
|
|
|
(void)isdelrec(fileDescriptor, recnum);
|
|
|
|
getStatusInfo();
|
|
return errorStatus;
|
|
}
|
|
|
|
int _Tt_isam_file::writeMagicString (const _Tt_string &magic_string)
|
|
{
|
|
iserrno = 0;
|
|
|
|
(void)iscntl(fileDescriptor,
|
|
ISCNTL_APPLMAGIC_WRITE,
|
|
(char *)magic_string);
|
|
|
|
errorStatus = iserrno;
|
|
return errorStatus;
|
|
}
|
|
|
|
_Tt_string _Tt_isam_file::readMagicString ()
|
|
{
|
|
iserrno = 0;
|
|
|
|
_Tt_string magic_string_bytes(ISAPPLMAGICLEN);
|
|
memset((char *)magic_string_bytes, '\0', ISAPPLMAGICLEN);
|
|
|
|
(void)iscntl(fileDescriptor,
|
|
ISCNTL_APPLMAGIC_READ,
|
|
(char *)magic_string_bytes);
|
|
|
|
errorStatus = iserrno;
|
|
|
|
_Tt_string magic_string = (char *)magic_string_bytes;
|
|
return magic_string;
|
|
}
|
|
|
|
int _Tt_isam_file::setFatalErrorHandler (FatalErrorHandlerFunction function)
|
|
{
|
|
iserrno = 0;
|
|
|
|
(void)iscntl(fileDescriptor, ISCNTL_FATAL, function);
|
|
|
|
errorStatus = iserrno;
|
|
return errorStatus;
|
|
}
|
|
|
|
_Tt_isam_record_ptr
|
|
_Tt_isam_file::getFullRecord (const _Tt_string &record_buffer)
|
|
{
|
|
_Tt_isam_record_ptr record_ptr = new _Tt_isam_record(keyDescriptorList,
|
|
maxRecordLength,
|
|
minRecordLength);
|
|
record_ptr->setBytes(0, currentRecordLength, record_buffer);
|
|
record_ptr->setLength(currentRecordLength);
|
|
|
|
return record_ptr;
|
|
}
|
|
|
|
void _Tt_isam_file::getISAMFileInfo ()
|
|
{
|
|
iserrno = 0;
|
|
|
|
struct dictinfo file_info;
|
|
struct keydesc key_descriptor;
|
|
short num_keys;
|
|
int results = isindexinfo(fileDescriptor,
|
|
(keydesc *)&file_info,
|
|
0);
|
|
|
|
getStatusInfo();
|
|
if (!results) {
|
|
keyDescriptorList->flush();
|
|
|
|
// If the file has var length records, the MSB is set in the di_nkeys
|
|
// field. This guarantees to turn the bit off...
|
|
num_keys = file_info.di_nkeys & ~DICTVARLENBIT;
|
|
|
|
if (num_keys == 1) {
|
|
(void)isindexinfo(fileDescriptor, &key_descriptor, 1);
|
|
if (key_descriptor.k_nparts == 0) {
|
|
num_keys = 0;
|
|
}
|
|
else {
|
|
num_keys = 1;
|
|
}
|
|
}
|
|
|
|
maxRecordLength = file_info.di_recsize;
|
|
minRecordLength = isreclen;
|
|
|
|
for (int i=1; i <= num_keys; i++) {
|
|
isindexinfo(fileDescriptor, &key_descriptor, i);
|
|
|
|
_Tt_isam_key_descriptor_ptr key_descriptor_ptr =
|
|
new _Tt_isam_key_descriptor;
|
|
key_descriptor_ptr->keyDescriptor = key_descriptor;
|
|
|
|
keyDescriptorList->append(key_descriptor_ptr);
|
|
}
|
|
|
|
errorStatus = iserrno;
|
|
}
|
|
}
|
|
|
|
int _Tt_isam_file::isamFatalErrorHandler (char *msg)
|
|
{
|
|
_tt_syslog(errstr, LOG_ERR, "NetISAM: %s", msg);
|
|
return 1;
|
|
}
|