/********************************************************************** * * XRFFile.cpp * Copyright (C) 2003 UNESCO * * A component of the Greenstone digital library software * from the New Zealand Digital Library Project at the * University of Waikato, New Zealand. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * *********************************************************************/ //////////////////////////////////////////////////////////// // XrfFile.cpp: XrfFile object methods // //////////////////////////////////////////////////////////// #include "stdafx.h" #include "XRFFile.h" //----------------------------------------------------------------------------------- // IsisError XrfFile::OpenXrf(const _TCHAR *fname, FileSystem::AccessMode mode // /* = FileSystem::FILE_READWRITE */) // // Open xrf_ file with file name fname //----------------------------------------------------------------------------------- IsisError XrfFile::OpenXrf(const _TCHAR *fname, FileSystem::AccessMode mode /* = FileSystem::FILE_READWRITE */) { TCHAR xrfFileName[_MAX_PATH]; _tcscpy(xrfFileName, fname); if (!CFileBase::Exists(xrfFileName)) { xrfFileName[strlen(xrfFileName) - 3] = 'X'; xrfFileName[strlen(xrfFileName) - 2] = 'R'; xrfFileName[strlen(xrfFileName) - 1] = 'F'; } IsisError isis_error; xrfa_->xrfpos_ = -1; // No block into buffer try { FileError rc = CFileBase::Open(xrfFileName, mode); } catch(CFileBaseException) { isis_error = ISIS_XRF_OPEN_ERROR; throw CIsisDbException(isis_error, __FILE__, __LINE__); } long file_size = CFileBase::FileSize(file_name); last_block_ = file_size/XRFBLKSIZE; if (last_block_<1 || last_block_*XRFBLKSIZE != file_size) { isis_error = ISIS_XRF_CORRUPT; throw CIsisDbException(isis_error, __FILE__, __LINE__); } return ISIS_NO_ERROR; } ////////////////////////////// IsisError XrfFile::CreateXrf(const _TCHAR *fname) // Creates an xrf_ file { IsisError isis_error; try { FileError rc = CFileBase::Create(fname); // Initialize an empty block and write-it xrfa_->Init(); xrfa_->xrfpos_ = 1; // Block number xrfa_->xrfeof_ = 1; // Last xrf_ block last_block_ = 1; WriteXrf(1L); } catch(CFileBaseException) { isis_error = ISIS_XRF_CREATE_ERROR; throw CIsisDbException(isis_error, __FILE__, __LINE__); } return ISIS_NO_ERROR; } //----------------------------------------------------------------------------------- // IsisError XrfFile::CreateXrf(const _TCHAR *fname, long nextMfn) // // Special xrf_ file creation for building xrf_ blocks of an existing mst //----------------------------------------------------------------------------------- IsisError XrfFile::CreateXrf(const _TCHAR *fname, long nextMfn) // Creates an xrf_ file { IsisError isis_error; long nBlocks = (nextMfn-1)/MAXTIV + 1; // Number of blocks to allocate try { FileError rc = CFileBase::Create(fname); xrfa_->Init(); // Initialize an empty block and write-it for (int iBlock=1; iBlock<= nBlocks; iBlock++) { TRACE("\niBlock=%d", iBlock); xrfa_->xrfpos_ = iBlock; xrfa_->xrfeof_ = 0; if (iBlock == nBlocks) xrfa_->xrfeof_ = 1; WriteXrf(iBlock); } } catch(CFileBaseException) { isis_error = ISIS_XRF_CREATE_ERROR; throw CIsisDbException(isis_error, __FILE__, __LINE__); } last_block_ = nBlocks; return ISIS_NO_ERROR; } //------------------------------------------------------------------------------ // void XrfFile::UnPack(void) // // Unpack addresses of master file records. The current packed XRF block // contained in xrf_ structure will be unpacked in xrfa_ structure. // // A master file address is packed as follow: addr = mfb*2048 + mfp // // 2048 = 2**11 e.g. mfp->[0:2047] and block number -> [1: 2**20] // 2**20 = 1 048 576 // // As we can put 127 addresses per block, then the limit on number of records // is 127 * 1 048 576 //------------------------------------------------------------------------------ void XrfFile::UnPack(void) { fix_endianness(xrf_->xrfpos_); xrfa_->xrfpos_ = xrf_->xrfpos_; if (xrfa_->xrfpos_ < 0) { xrfa_->xrfpos_ = - xrf_->xrfpos_; xrfa_->xrfeof_ = 1; } else xrfa_->xrfeof_ = 0; for (int i=0; ixrftiv_[i]; // Packed value fix_endianness(j); bool b = (j < 0); if (b) j = - j; xrfa_->xrftiv_[i].xrfmfb_ = int(j / 2048L); // Unpack block number if (b) xrfa_->xrftiv_[i].xrfmfb_ = -xrfa_->xrftiv_[i].xrfmfb_; xrfa_->xrftiv_[i].xrfmfp_ = int(j % 2048L); // Unpack offset } } //------------------------------------------------------------------------------ // void XrfFile::Pack(void) // // Pack addresses of master file records. The current unpacked XRF block // contained in xrfa_ will be packed in xrf_ structure. //------------------------------------------------------------------------------ void XrfFile::Pack(void) { long j = xrfa_->xrfpos_; if (xrfa_->xrfeof_ != 0) j = -j; xrf_->xrfpos_ = j; for (int i=0; ixrftiv_[i].xrfmfb_; // Unpacked block number int b = (j < 0); if (b) j = - j; //------------------------------------------- // pack block number and offset in a long int //------------------------------------------- j = j * 2048 + xrfa_->xrftiv_[i].xrfmfp_; if (b) j = -j; xrf_->xrftiv_[i] = j; // Put value in xrf_ } } //------------------------------------------------------------------------------ // int XrfFile::GetMfp(long mfn, long& mfb, int& mfp) // // Gets the address of master file data record with MFN "mfn" by accessing the // xrf_ file). mfb is the master file block number [1:NBLK] and mfp is the offset // in the master file block where the record starts [0:BLKSIZE-1] // // Returns Active = Record active // LogicalyDeleted = Record logically deleted // PhysicalyDeleted = Record physically deleted // EndOfFile // Note: mfp can be >= than BLKSIZE if the inverted file // wasn't updated, then true mfp is mfp%BLKSIZE //------------------------------------------------------------------------------ int XrfFile::GetMfp(long mfn, long& mfb, int& mfp) { PRECONDITION(mfn>0); PRECONDITION(last_block_>0); int comp; long comb; int rc; long psxrf=(mfn-1)/MAXTIV+1; // Block number if (psxrf > last_block_) { rc = EndOfFile; // Inexistent record (eof) return rc; throw CIsisDbException(ISIS_XRF_INVALID_BLOCK, __FILE__, __LINE__); } if (psxrf != xrfa_->xrfpos_) { // If current block in xrf_ different try { ReadXrf(psxrf); // then read the block } catch (CFileBaseException e) { throw CIsisDbException(ISIS_XRF_READ_ERROR, __FILE__, __LINE__); } } int i = int((mfn-1) % MAXTIV); // Index comb = xrfa_->xrftiv_[i].xrfmfb_; // Master file block # comp = xrfa_->xrftiv_[i].xrfmfp_; // Offset in block if (comb > 0) rc = Active; // Record active else if (comb < 0 && comp > 0) rc = LogicalyDeleted; // Record logicaly deleted else if (comb == -1 && comp == 0) rc = PhysicalyDeleted; // Record physically deleted else if (comb == 0 && comp == 0) rc = EndOfFile; // Inexistent record (eof) else { throw CIsisDbException(ISIS_XRF_INVALID_STATUS, __FILE__, __LINE__); } mfb = labs(comb); mfp = comp; if (rc == Active) { ASSERT(mfb>0 && mfb <= MAXMFB); ASSERT(mfp>=0 && mfp < 2048); int mfpTemp = mfp%XRFBLKSIZE; ASSERT(mfpTemp>=0 && mfpTempInit(); xrfa_->xrfpos_ = i; xrfa_->xrfeof_ = (i==to_lastb) ? 1 : 0; // Eof flag try { WriteXrf(i); // Write xrf_ at block address xrfb } catch (CFileBaseException) { throw(ISIS_XRF_WRITE_ERROR); } } } //------------------------------------------------------------------------------ // void XrfFile::PutMfp(long mfn, long mfb, int mfp, int status) // // Puts the address of a master file record (mfb,mfp) as the address for MFN // "mfn" in xrf_ file //------------------------------------------------------------------------------ void XrfFile::PutMfp(long mfn, long mfb, int mfp, int status) { }