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

Last change on this file since 12714 was 12714, checked in by mdewsnip, 18 years ago

Can now handle uppercase extensions on Linux.

  • Property svn:keywords set to Author Date Id Revision
File size: 9.5 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 xrfa_->xrfpos_ = xrf_->xrfpos_;
154 if (xrfa_->xrfpos_ < 0)
155 {
156 xrfa_->xrfpos_ = - xrf_->xrfpos_;
157 xrfa_->xrfeof_ = 1;
158 }
159 else
160 xrfa_->xrfeof_ = 0;
161
162 for (int i=0; i<MAXTIV; i++)
163 {
164 long j = xrf_->xrftiv_[i]; // Packed value
165 bool b = (j < 0);
166 if (b)
167 j = - j;
168 xrfa_->xrftiv_[i].xrfmfb_ = int(j / 2048L); // Unpack block number
169 if (b)
170 xrfa_->xrftiv_[i].xrfmfb_ = -xrfa_->xrftiv_[i].xrfmfb_;
171 xrfa_->xrftiv_[i].xrfmfp_ = int(j % 2048L); // Unpack offset
172 }
173}
174
175//------------------------------------------------------------------------------
176// void XrfFile::Pack(void)
177//
178// Pack addresses of master file records. The current unpacked XRF block
179// contained in xrfa_ will be packed in xrf_ structure.
180//------------------------------------------------------------------------------
181void XrfFile::Pack(void)
182{
183 long j = xrfa_->xrfpos_;
184 if (xrfa_->xrfeof_ != 0)
185 j = -j;
186 xrf_->xrfpos_ = j;
187
188
189 for (int i=0; i<MAXTIV; i++)
190 {
191 j = xrfa_->xrftiv_[i].xrfmfb_; // Unpacked block number
192 int b = (j < 0);
193 if (b)
194 j = - j;
195 //-------------------------------------------
196 // pack block number and offset in a long int
197 //-------------------------------------------
198 j = j * 2048 + xrfa_->xrftiv_[i].xrfmfp_;
199 if (b) j = -j;
200 xrf_->xrftiv_[i] = j; // Put value in xrf_
201 }
202}
203
204//------------------------------------------------------------------------------
205// int XrfFile::GetMfp(long mfn, long& mfb, int& mfp)
206//
207// Gets the address of master file data record with MFN "mfn" by accessing the
208// xrf_ file). mfb is the master file block number [1:NBLK] and mfp is the offset
209// in the master file block where the record starts [0:BLKSIZE-1]
210//
211// Returns Active = Record active
212// LogicalyDeleted = Record logically deleted
213// PhysicalyDeleted = Record physically deleted
214// EndOfFile
215// Note: mfp can be >= than BLKSIZE if the inverted file
216// wasn't updated, then true mfp is mfp%BLKSIZE
217//------------------------------------------------------------------------------
218int XrfFile::GetMfp(long mfn, long& mfb, int& mfp)
219{
220 PRECONDITION(mfn>0);
221 PRECONDITION(last_block_>0);
222 int comp;
223 long comb;
224 int rc;
225
226 long psxrf=(mfn-1)/MAXTIV+1; // Block number
227 if (psxrf > last_block_)
228 {
229 rc = EndOfFile; // Inexistent record (eof)
230 return rc;
231 throw CIsisDbException(ISIS_XRF_INVALID_BLOCK, __FILE__, __LINE__);
232 }
233 if (psxrf != xrfa_->xrfpos_)
234 { // If current block in xrf_ different
235 try
236 {
237 ReadXrf(psxrf); // then read the block
238 }
239 catch (CFileBaseException e)
240 {
241 throw CIsisDbException(ISIS_XRF_READ_ERROR, __FILE__, __LINE__);
242 }
243
244 }
245 int i = int((mfn-1) % MAXTIV); // Index
246 comb = xrfa_->xrftiv_[i].xrfmfb_; // Master file block #
247 comp = xrfa_->xrftiv_[i].xrfmfp_; // Offset in block
248
249 if (comb > 0)
250 rc = Active; // Record active
251 else if (comb < 0 && comp > 0)
252 rc = LogicalyDeleted; // Record logicaly deleted
253 else if (comb == -1 && comp == 0)
254 rc = PhysicalyDeleted; // Record physically deleted
255 else if (comb == 0 && comp == 0)
256 rc = EndOfFile; // Inexistent record (eof)
257 else
258 {
259 throw CIsisDbException(ISIS_XRF_INVALID_STATUS, __FILE__, __LINE__);
260 }
261 mfb = labs(comb);
262 mfp = comp;
263 if (rc == Active)
264 {
265 ASSERT(mfb>0 && mfb <= MAXMFB);
266 ASSERT(mfp>=0 && mfp < 2048);
267 int mfpTemp = mfp%XRFBLKSIZE;
268 ASSERT(mfpTemp>=0 && mfpTemp<XRFBLKSIZE);
269 }
270 return(rc);
271}
272
273void XrfFile::Grow(long from_lastb, long to_lastb)
274{
275 for (long i=from_lastb+1; i<=to_lastb; i++)
276 {
277 //--------------------
278 // append empty blocks
279 //--------------------
280 xrfa_->Init();
281 xrfa_->xrfpos_ = i;
282 xrfa_->xrfeof_ = (i==to_lastb) ? 1 : 0; // Eof flag
283 try
284 {
285 WriteXrf(i); // Write xrf_ at block address xrfb
286 }
287 catch (CFileBaseException)
288 {
289 throw(ISIS_XRF_WRITE_ERROR);
290 }
291 }
292}
293
294//------------------------------------------------------------------------------
295// void XrfFile::PutMfp(long mfn, long mfb, int mfp, int status)
296//
297// Puts the address of a master file record (mfb,mfp) as the address for MFN
298// "mfn" in xrf_ file
299//------------------------------------------------------------------------------
300void XrfFile::PutMfp(long mfn, long mfb, int mfp, int status)
301{
302}
Note: See TracBrowser for help on using the repository browser.