source: trunk/gsdl/packages/isis-gdl/XRFFile.cpp@ 7138

Last change on this file since 7138 was 6127, checked in by mdewsnip, 21 years ago

IsisGdl package for reading CDS/ISIS databases. Provided by Jean-Claude Dauphin at UNESCO, and modified slightly to compile and run under Linux.

  • Property svn:keywords set to Author Date Id Revision
File size: 9.3 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 IsisError isis_error;
45 xrfa_->xrfpos_ = -1; // No block into buffer
46 try {
47 FileError rc = CFileBase::Open(fname, mode);
48 }
49 catch(CFileBaseException)
50 {
51 isis_error = ISIS_XRF_OPEN_ERROR;
52 throw CIsisDbException(isis_error, __FILE__, __LINE__);
53 }
54 long file_size = CFileBase::FileSize(file_name);
55
56 last_block_ = file_size/XRFBLKSIZE;
57
58 if (last_block_<1 || last_block_*XRFBLKSIZE != file_size)
59 {
60 isis_error = ISIS_XRF_CORRUPT;
61 throw CIsisDbException(isis_error, __FILE__, __LINE__);
62 }
63
64 return ISIS_NO_ERROR;
65}
66
67//////////////////////////////
68
69
70IsisError XrfFile::CreateXrf(const _TCHAR *fname)
71// Creates an xrf_ file
72{
73 IsisError isis_error;
74 try
75 {
76 FileError rc = CFileBase::Create(fname);
77 // Initialize an empty block and write-it
78 xrfa_->Init();
79 xrfa_->xrfpos_ = 1; // Block number
80 xrfa_->xrfeof_ = 1; // Last xrf_ block
81 last_block_ = 1;
82 WriteXrf(1L);
83 }
84 catch(CFileBaseException)
85 {
86 isis_error = ISIS_XRF_CREATE_ERROR;
87 throw CIsisDbException(isis_error, __FILE__, __LINE__);
88 }
89
90 return ISIS_NO_ERROR;
91}
92//-----------------------------------------------------------------------------------
93// IsisError XrfFile::CreateXrf(const _TCHAR *fname, long nextMfn)
94//
95// Special xrf_ file creation for building xrf_ blocks of an existing mst
96//-----------------------------------------------------------------------------------
97IsisError XrfFile::CreateXrf(const _TCHAR *fname, long nextMfn)
98// Creates an xrf_ file
99{
100 IsisError isis_error;
101 long nBlocks = (nextMfn-1)/MAXTIV + 1; // Number of blocks to allocate
102 try
103 {
104 FileError rc = CFileBase::Create(fname);
105 xrfa_->Init();
106 // Initialize an empty block and write-it
107 for (int iBlock=1; iBlock<= nBlocks; iBlock++)
108 {
109 TRACE("\niBlock=%d", iBlock);
110 xrfa_->xrfpos_ = iBlock;
111 xrfa_->xrfeof_ = 0;
112 if (iBlock == nBlocks)
113 xrfa_->xrfeof_ = 1;
114
115 WriteXrf(iBlock);
116 }
117 }
118 catch(CFileBaseException)
119 {
120 isis_error = ISIS_XRF_CREATE_ERROR;
121 throw CIsisDbException(isis_error, __FILE__, __LINE__);
122 }
123
124 last_block_ = nBlocks;
125 return ISIS_NO_ERROR;
126}
127
128//------------------------------------------------------------------------------
129// void XrfFile::UnPack(void)
130//
131// Unpack addresses of master file records. The current packed XRF block
132// contained in xrf_ structure will be unpacked in xrfa_ structure.
133//
134// A master file address is packed as follow: addr = mfb*2048 + mfp
135//
136// 2048 = 2**11 e.g. mfp->[0:2047] and block number -> [1: 2**20]
137// 2**20 = 1 048 576
138//
139// As we can put 127 addresses per block, then the limit on number of records
140// is 127 * 1 048 576
141//------------------------------------------------------------------------------
142void XrfFile::UnPack(void)
143{
144 xrfa_->xrfpos_ = xrf_->xrfpos_;
145 if (xrfa_->xrfpos_ < 0)
146 {
147 xrfa_->xrfpos_ = - xrf_->xrfpos_;
148 xrfa_->xrfeof_ = 1;
149 }
150 else
151 xrfa_->xrfeof_ = 0;
152
153 for (int i=0; i<MAXTIV; i++)
154 {
155 long j = xrf_->xrftiv_[i]; // Packed value
156 bool b = (j < 0);
157 if (b)
158 j = - j;
159 xrfa_->xrftiv_[i].xrfmfb_ = int(j / 2048L); // Unpack block number
160 if (b)
161 xrfa_->xrftiv_[i].xrfmfb_ = -xrfa_->xrftiv_[i].xrfmfb_;
162 xrfa_->xrftiv_[i].xrfmfp_ = int(j % 2048L); // Unpack offset
163 }
164}
165
166//------------------------------------------------------------------------------
167// void XrfFile::Pack(void)
168//
169// Pack addresses of master file records. The current unpacked XRF block
170// contained in xrfa_ will be packed in xrf_ structure.
171//------------------------------------------------------------------------------
172void XrfFile::Pack(void)
173{
174 long j = xrfa_->xrfpos_;
175 if (xrfa_->xrfeof_ != 0)
176 j = -j;
177 xrf_->xrfpos_ = j;
178
179
180 for (int i=0; i<MAXTIV; i++)
181 {
182 j = xrfa_->xrftiv_[i].xrfmfb_; // Unpacked block number
183 int b = (j < 0);
184 if (b)
185 j = - j;
186 //-------------------------------------------
187 // pack block number and offset in a long int
188 //-------------------------------------------
189 j = j * 2048 + xrfa_->xrftiv_[i].xrfmfp_;
190 if (b) j = -j;
191 xrf_->xrftiv_[i] = j; // Put value in xrf_
192 }
193}
194
195//------------------------------------------------------------------------------
196// int XrfFile::GetMfp(long mfn, long& mfb, int& mfp)
197//
198// Gets the address of master file data record with MFN "mfn" by accessing the
199// xrf_ file). mfb is the master file block number [1:NBLK] and mfp is the offset
200// in the master file block where the record starts [0:BLKSIZE-1]
201//
202// Returns Active = Record active
203// LogicalyDeleted = Record logically deleted
204// PhysicalyDeleted = Record physically deleted
205// EndOfFile
206// Note: mfp can be >= than BLKSIZE if the inverted file
207// wasn't updated, then true mfp is mfp%BLKSIZE
208//------------------------------------------------------------------------------
209int XrfFile::GetMfp(long mfn, long& mfb, int& mfp)
210{
211 PRECONDITION(mfn>0);
212 PRECONDITION(last_block_>0);
213 int comp;
214 long comb;
215 int rc;
216
217 long psxrf=(mfn-1)/MAXTIV+1; // Block number
218 if (psxrf > last_block_)
219 {
220 rc = EndOfFile; // Inexistent record (eof)
221 return rc;
222 throw CIsisDbException(ISIS_XRF_INVALID_BLOCK, __FILE__, __LINE__);
223 }
224 if (psxrf != xrfa_->xrfpos_)
225 { // If current block in xrf_ different
226 try
227 {
228 ReadXrf(psxrf); // then read the block
229 }
230 catch (CFileBaseException e)
231 {
232 throw CIsisDbException(ISIS_XRF_READ_ERROR, __FILE__, __LINE__);
233 }
234
235 }
236 int i = int((mfn-1) % MAXTIV); // Index
237 comb = xrfa_->xrftiv_[i].xrfmfb_; // Master file block #
238 comp = xrfa_->xrftiv_[i].xrfmfp_; // Offset in block
239
240 if (comb > 0)
241 rc = Active; // Record active
242 else if (comb < 0 && comp > 0)
243 rc = LogicalyDeleted; // Record logicaly deleted
244 else if (comb == -1 && comp == 0)
245 rc = PhysicalyDeleted; // Record physically deleted
246 else if (comb == 0 && comp == 0)
247 rc = EndOfFile; // Inexistent record (eof)
248 else
249 {
250 throw CIsisDbException(ISIS_XRF_INVALID_STATUS, __FILE__, __LINE__);
251 }
252 mfb = labs(comb);
253 mfp = comp;
254 if (rc == Active)
255 {
256 ASSERT(mfb>0 && mfb <= MAXMFB);
257 ASSERT(mfp>=0 && mfp < 2048);
258 int mfpTemp = mfp%XRFBLKSIZE;
259 ASSERT(mfpTemp>=0 && mfpTemp<XRFBLKSIZE);
260 }
261 return(rc);
262}
263
264void XrfFile::Grow(long from_lastb, long to_lastb)
265{
266 for (long i=from_lastb+1; i<=to_lastb; i++)
267 {
268 //--------------------
269 // append empty blocks
270 //--------------------
271 xrfa_->Init();
272 xrfa_->xrfpos_ = i;
273 xrfa_->xrfeof_ = (i==to_lastb) ? 1 : 0; // Eof flag
274 try
275 {
276 WriteXrf(i); // Write xrf_ at block address xrfb
277 }
278 catch (CFileBaseException)
279 {
280 throw(ISIS_XRF_WRITE_ERROR);
281 }
282 }
283}
284
285//------------------------------------------------------------------------------
286// void XrfFile::PutMfp(long mfn, long mfb, int mfp, int status)
287//
288// Puts the address of a master file record (mfb,mfp) as the address for MFN
289// "mfn" in xrf_ file
290//------------------------------------------------------------------------------
291void XrfFile::PutMfp(long mfn, long mfb, int mfp, int status)
292{
293}
Note: See TracBrowser for help on using the repository browser.