source: main/trunk/greenstone2/build-src/packages/isis-gdl/XRFFile.cpp@ 26670

Last change on this file since 26670 was 13518, checked in by mdewsnip, 17 years ago

Running this on a big-endian machine would fail to read little-endian CDS/ISIS files. I've assumed most (all?) CDS/ISIS files are little-endian, and added code to convert the values into the right endianness on big-endian machines.

  • Property svn:keywords set to Author Date Id Revision
File size: 9.6 KB
Line 
1/**********************************************************************
2 *
3 * XRFFile.cpp
4 * Copyright (C) 2003 UNESCO
5 *
6 * A component of the Greenstone digital library software
7 * from the New Zealand Digital Library Project at the
8 * University of Waikato, New Zealand.
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 *
24 *********************************************************************/
25
26////////////////////////////////////////////////////////////
27// XrfFile.cpp: XrfFile object methods
28//
29////////////////////////////////////////////////////////////
30#include "stdafx.h"
31#include "XRFFile.h"
32
33
34
35//-----------------------------------------------------------------------------------
36// IsisError XrfFile::OpenXrf(const _TCHAR *fname, FileSystem::AccessMode mode
37// /* = FileSystem::FILE_READWRITE */)
38//
39// Open xrf_ file with file name fname
40//-----------------------------------------------------------------------------------
41IsisError XrfFile::OpenXrf(const _TCHAR *fname, FileSystem::AccessMode mode
42 /* = FileSystem::FILE_READWRITE */)
43{
44 TCHAR xrfFileName[_MAX_PATH];
45 _tcscpy(xrfFileName, fname);
46
47 if (!CFileBase::Exists(xrfFileName)) {
48 xrfFileName[strlen(xrfFileName) - 3] = 'X';
49 xrfFileName[strlen(xrfFileName) - 2] = 'R';
50 xrfFileName[strlen(xrfFileName) - 1] = 'F';
51 }
52
53 IsisError isis_error;
54 xrfa_->xrfpos_ = -1; // No block into buffer
55 try {
56 FileError rc = CFileBase::Open(xrfFileName, mode);
57 }
58 catch(CFileBaseException)
59 {
60 isis_error = ISIS_XRF_OPEN_ERROR;
61 throw CIsisDbException(isis_error, __FILE__, __LINE__);
62 }
63 long file_size = CFileBase::FileSize(file_name);
64
65 last_block_ = file_size/XRFBLKSIZE;
66
67 if (last_block_<1 || last_block_*XRFBLKSIZE != file_size)
68 {
69 isis_error = ISIS_XRF_CORRUPT;
70 throw CIsisDbException(isis_error, __FILE__, __LINE__);
71 }
72
73 return ISIS_NO_ERROR;
74}
75
76//////////////////////////////
77
78
79IsisError XrfFile::CreateXrf(const _TCHAR *fname)
80// Creates an xrf_ file
81{
82 IsisError isis_error;
83 try
84 {
85 FileError rc = CFileBase::Create(fname);
86 // Initialize an empty block and write-it
87 xrfa_->Init();
88 xrfa_->xrfpos_ = 1; // Block number
89 xrfa_->xrfeof_ = 1; // Last xrf_ block
90 last_block_ = 1;
91 WriteXrf(1L);
92 }
93 catch(CFileBaseException)
94 {
95 isis_error = ISIS_XRF_CREATE_ERROR;
96 throw CIsisDbException(isis_error, __FILE__, __LINE__);
97 }
98
99 return ISIS_NO_ERROR;
100}
101//-----------------------------------------------------------------------------------
102// IsisError XrfFile::CreateXrf(const _TCHAR *fname, long nextMfn)
103//
104// Special xrf_ file creation for building xrf_ blocks of an existing mst
105//-----------------------------------------------------------------------------------
106IsisError XrfFile::CreateXrf(const _TCHAR *fname, long nextMfn)
107// Creates an xrf_ file
108{
109 IsisError isis_error;
110 long nBlocks = (nextMfn-1)/MAXTIV + 1; // Number of blocks to allocate
111 try
112 {
113 FileError rc = CFileBase::Create(fname);
114 xrfa_->Init();
115 // Initialize an empty block and write-it
116 for (int iBlock=1; iBlock<= nBlocks; iBlock++)
117 {
118 TRACE("\niBlock=%d", iBlock);
119 xrfa_->xrfpos_ = iBlock;
120 xrfa_->xrfeof_ = 0;
121 if (iBlock == nBlocks)
122 xrfa_->xrfeof_ = 1;
123
124 WriteXrf(iBlock);
125 }
126 }
127 catch(CFileBaseException)
128 {
129 isis_error = ISIS_XRF_CREATE_ERROR;
130 throw CIsisDbException(isis_error, __FILE__, __LINE__);
131 }
132
133 last_block_ = nBlocks;
134 return ISIS_NO_ERROR;
135}
136
137//------------------------------------------------------------------------------
138// void XrfFile::UnPack(void)
139//
140// Unpack addresses of master file records. The current packed XRF block
141// contained in xrf_ structure will be unpacked in xrfa_ structure.
142//
143// A master file address is packed as follow: addr = mfb*2048 + mfp
144//
145// 2048 = 2**11 e.g. mfp->[0:2047] and block number -> [1: 2**20]
146// 2**20 = 1 048 576
147//
148// As we can put 127 addresses per block, then the limit on number of records
149// is 127 * 1 048 576
150//------------------------------------------------------------------------------
151void XrfFile::UnPack(void)
152{
153 fix_endianness(xrf_->xrfpos_);
154
155 xrfa_->xrfpos_ = xrf_->xrfpos_;
156 if (xrfa_->xrfpos_ < 0)
157 {
158 xrfa_->xrfpos_ = - xrf_->xrfpos_;
159 xrfa_->xrfeof_ = 1;
160 }
161 else
162 xrfa_->xrfeof_ = 0;
163
164 for (int i=0; i<MAXTIV; i++)
165 {
166 long j = xrf_->xrftiv_[i]; // Packed value
167 fix_endianness(j);
168 bool b = (j < 0);
169 if (b)
170 j = - j;
171 xrfa_->xrftiv_[i].xrfmfb_ = int(j / 2048L); // Unpack block number
172 if (b)
173 xrfa_->xrftiv_[i].xrfmfb_ = -xrfa_->xrftiv_[i].xrfmfb_;
174 xrfa_->xrftiv_[i].xrfmfp_ = int(j % 2048L); // Unpack offset
175 }
176}
177
178//------------------------------------------------------------------------------
179// void XrfFile::Pack(void)
180//
181// Pack addresses of master file records. The current unpacked XRF block
182// contained in xrfa_ will be packed in xrf_ structure.
183//------------------------------------------------------------------------------
184void XrfFile::Pack(void)
185{
186 long j = xrfa_->xrfpos_;
187 if (xrfa_->xrfeof_ != 0)
188 j = -j;
189 xrf_->xrfpos_ = j;
190
191
192 for (int i=0; i<MAXTIV; i++)
193 {
194 j = xrfa_->xrftiv_[i].xrfmfb_; // Unpacked block number
195 int b = (j < 0);
196 if (b)
197 j = - j;
198 //-------------------------------------------
199 // pack block number and offset in a long int
200 //-------------------------------------------
201 j = j * 2048 + xrfa_->xrftiv_[i].xrfmfp_;
202 if (b) j = -j;
203 xrf_->xrftiv_[i] = j; // Put value in xrf_
204 }
205}
206
207//------------------------------------------------------------------------------
208// int XrfFile::GetMfp(long mfn, long& mfb, int& mfp)
209//
210// Gets the address of master file data record with MFN "mfn" by accessing the
211// xrf_ file). mfb is the master file block number [1:NBLK] and mfp is the offset
212// in the master file block where the record starts [0:BLKSIZE-1]
213//
214// Returns Active = Record active
215// LogicalyDeleted = Record logically deleted
216// PhysicalyDeleted = Record physically deleted
217// EndOfFile
218// Note: mfp can be >= than BLKSIZE if the inverted file
219// wasn't updated, then true mfp is mfp%BLKSIZE
220//------------------------------------------------------------------------------
221int XrfFile::GetMfp(long mfn, long& mfb, int& mfp)
222{
223 PRECONDITION(mfn>0);
224 PRECONDITION(last_block_>0);
225 int comp;
226 long comb;
227 int rc;
228
229 long psxrf=(mfn-1)/MAXTIV+1; // Block number
230 if (psxrf > last_block_)
231 {
232 rc = EndOfFile; // Inexistent record (eof)
233 return rc;
234 throw CIsisDbException(ISIS_XRF_INVALID_BLOCK, __FILE__, __LINE__);
235 }
236 if (psxrf != xrfa_->xrfpos_)
237 { // If current block in xrf_ different
238 try
239 {
240 ReadXrf(psxrf); // then read the block
241 }
242 catch (CFileBaseException e)
243 {
244 throw CIsisDbException(ISIS_XRF_READ_ERROR, __FILE__, __LINE__);
245 }
246
247 }
248 int i = int((mfn-1) % MAXTIV); // Index
249 comb = xrfa_->xrftiv_[i].xrfmfb_; // Master file block #
250 comp = xrfa_->xrftiv_[i].xrfmfp_; // Offset in block
251
252 if (comb > 0)
253 rc = Active; // Record active
254 else if (comb < 0 && comp > 0)
255 rc = LogicalyDeleted; // Record logicaly deleted
256 else if (comb == -1 && comp == 0)
257 rc = PhysicalyDeleted; // Record physically deleted
258 else if (comb == 0 && comp == 0)
259 rc = EndOfFile; // Inexistent record (eof)
260 else
261 {
262 throw CIsisDbException(ISIS_XRF_INVALID_STATUS, __FILE__, __LINE__);
263 }
264 mfb = labs(comb);
265 mfp = comp;
266 if (rc == Active)
267 {
268 ASSERT(mfb>0 && mfb <= MAXMFB);
269 ASSERT(mfp>=0 && mfp < 2048);
270 int mfpTemp = mfp%XRFBLKSIZE;
271 ASSERT(mfpTemp>=0 && mfpTemp<XRFBLKSIZE);
272 }
273 return(rc);
274}
275
276void XrfFile::Grow(long from_lastb, long to_lastb)
277{
278 for (long i=from_lastb+1; i<=to_lastb; i++)
279 {
280 //--------------------
281 // append empty blocks
282 //--------------------
283 xrfa_->Init();
284 xrfa_->xrfpos_ = i;
285 xrfa_->xrfeof_ = (i==to_lastb) ? 1 : 0; // Eof flag
286 try
287 {
288 WriteXrf(i); // Write xrf_ at block address xrfb
289 }
290 catch (CFileBaseException)
291 {
292 throw(ISIS_XRF_WRITE_ERROR);
293 }
294 }
295}
296
297//------------------------------------------------------------------------------
298// void XrfFile::PutMfp(long mfn, long mfb, int mfp, int status)
299//
300// Puts the address of a master file record (mfb,mfp) as the address for MFN
301// "mfn" in xrf_ file
302//------------------------------------------------------------------------------
303void XrfFile::PutMfp(long mfn, long mfb, int mfp, int status)
304{
305}
Note: See TracBrowser for help on using the repository browser.