source: main/tags/2.53/gsdl/packages/isis-gdl/MFFile.cpp@ 32727

Last change on this file since 32727 was 6127, checked in by mdewsnip, 20 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: 15.4 KB
Line 
1/**********************************************************************
2 *
3 * MFFile.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// MfFile.cpp : Master file object methods using blocked I/O
28//
29////////////////////////////////////////////////////////////
30#include "stdafx.h"
31#include "IsisDb.h"
32#include "Checking.h"
33
34
35
36//----------------------------------------------------------------------------------
37// MfFile::MfFile() :
38//
39// Constructor, makes a Masterfile object that isn't connected to a file
40//----------------------------------------------------------------------------------
41MfFile::MfFile() : BlkFile(), hdr_created_(false), nextaddr_(MFCTLLEN)
42{
43 lastWrittenBlock_ = -1;
44}
45
46//----------------------------------------------------------------------------------
47// int MfFile::OpenMf(const TCHAR *fname,
48// FileSystem::AccessMode mode /* = FileSystem::FILE_READWRITE */)
49//
50// Opens a Masterfile object
51//----------------------------------------------------------------------------------
52int MfFile::OpenMf(const TCHAR *fname, FileSystem::AccessMode mode
53 /* = FileSystem::FILE_READWRITE */)
54{
55 int rc;
56 try
57 {
58 rc = CFileBase::Open(fname, mode);
59 hdr_created_ = true;
60 ReadMfHdr();
61 PrintMfHdr();
62 Checking::CheckMfHeader(fname, mfh_);
63 }
64 catch (CFileBaseException e)
65 {
66 throw CIsisDbException(ISIS_MF_OPEN_ERROR, __FILE__, __LINE__);
67 }
68 return rc;
69}
70
71//----------------------------------------------------------------------------------
72// int MfFile::createMf(const TCHAR *fname, int type)
73//
74// Creates a Masterfile object
75//----------------------------------------------------------------------------------
76int MfFile::CreateMf(const TCHAR *fname, int type)
77{
78 return 0;
79}
80
81//////////////////////////////
82MfFile::~MfFile()
83{
84}
85
86//----------------------------------------------------------------------------------
87// void MfFile::ReadMfRecord(long mfb, int mfp, MfRecord &m)
88//
89// Reads the master file record beginning at address (mfb,mfp) into m
90//----------------------------------------------------------------------------------
91bool MfFile::ReadMfRecord(long mfb, int mfp, MfRecord &m)
92{
93 return m.Read(*this, mfb, mfp);
94}
95
96//-------------------------------------------------------------------------------
97// void WriteMfRecord(long mfb, int mfp, MfRecord &m)
98//
99// Helper protected method, which writes the Master file record m at address
100// (mfb, mfp) mfb (1:MAXMFB), mfp (0: MFBLKSIZE)
101//-------------------------------------------------------------------------------
102void MfFile::WriteMfRecord(long mfb, int mfp, MfRecord &m)
103{
104 m.Write(*this, mfb, mfp);
105}
106
107
108//--------------------------------------------------------------------------------
109// void CreateMfRecord(MfRecord &m, long &mfb, int &mfp)
110//
111// Create a new record. The MFN to be assigned is obtained from the field nxtmfn_
112// in the Master file header. Then addMfRecord is called for adding the record
113// at the end of the master file, at the position indicated by the fields
114// nxtmfb_/nxtmfb_. The next MFN to be assigned is updated.
115//
116//--------------------------------------------------------------------------------
117void MfFile::CreateMfRecord(MfRecord &m, long &mfb, int &mfp)
118{
119}
120
121void MfFile::AppendNewBlock()
122{
123}
124
125//--------------------------------------------------------------------------------
126// void AddMfRecord(MfRecord &m, long &mfb, int &mfp)
127//
128// Add the record at the end of the master file, at the position indicated by
129// the fields nxtmfb_/nxtmfp_. (nxtmfp_ is in range [1:MFBLKSIZE])
130// Return the address where the record was stored into mfb & mfp
131//--------------------------------------------------------------------------------
132void MfFile::AddMfRecord(MfRecord &m, long &mfb, int &mfp)
133{
134}
135
136
137//--------------------------------------------------------------------------------
138// void UpdateMfRecord(MfRecord &m, long &mfb, int &mfp)
139//
140// Update a Master file record.If possible, i.e. if the record length was not
141// increased, the record is written back at its original location otherwise it is
142// written at the end of the file. In both cases, MFBWB/MFBWP are not changed.
143//
144//--------------------------------------------------------------------------------
145void MfFile::UpdateMfRecord(MfRecord &m, long &mfb, int &mfp)
146{
147}
148
149
150/////////////////////////////////////////////////////////////////////////////////////
151// methods for dumping file and record headers
152
153
154void MfFile::PrintMfHdr(SMfHeader &h)
155// Prints header record
156{
157}
158
159//////////////////////////////
160
161void MfFile::PrintMfRecord(MfRecord &m)
162// Print a master file record structure
163{
164 m.Dump();
165}
166
167/////////////////////////////////////////////////////////////////////////////////////
168// Methods for accessing records directly
169
170//----------------------------------------------------------------------------------
171// void MfFile::ReadMfRecord(long daddr, MfRecord &m)
172//
173// Reads a master file record into the master record object m.
174// Non blocked version
175//----------------------------------------------------------------------------------
176void MfFile::ReadMfRecord(long daddr, MfRecord &m)
177{
178 m.Clear();
179 ReadLeader(daddr, m); // Read record leader (Leader is added to record)
180 m.ExtractSubLeader();
181
182 //TRACE("\nReadMfRecord -- mfn=%ld mfrl=%d", m.GetMfn(), m.GetMfrl());
183 //assert(m.CheckIntegrity());
184 int mfrl = m.GetMfrl();
185 if (mfrl < 0) mfrl = -mfrl; // mfrl can be negative!!!!
186 char* p = new char[mfrl];
187 CFileBase::Fetch(p, mfrl, daddr);
188 m.AddToRecord(p+GetLeaderSize(), mfrl-GetLeaderSize());
189 delete[] p;
190 nextaddr_ += mfrl;
191 int mfb = nextaddr_ / MFBLKSIZE + 1;
192 int mfp = nextaddr_ % MFBLKSIZE;
193 if (mfp > MFBLKSIZE - GetMinLeaderSize())
194 {
195 mfb++;
196 mfp = 0;
197 }
198 nextaddr_ = (mfb-1)*MFBLKSIZE + mfp;
199 m.DecomposeRecord();
200}
201
202//---------------------------------------------------------------------------------
203// void MfFile::WriteMfRecord(long daddr, MfRecord &m)
204//
205// Stores Master record object m to disk address daddr
206// Non blocked version
207//---------------------------------------------------------------------------------
208void MfFile::WriteMfRecord(long daddr, MfRecord &m)
209{
210}
211/////////////////////////////////////////////////////////////////////////////////////
212// Master file locking methods
213
214
215
216//-----------------------------------------------------------------------------------
217// void MfFile::InitFileLockHdr(SMfLockHeader &hdr)
218//
219// Initialize a the lock header for a newly constructed file lock header.
220//-----------------------------------------------------------------------------------
221void MfFile::InitFileLockHdr(SMfLockHeader &hdr)
222{
223 hdr.lockProtect_ = (uint32_t)0;
224 hdr.readLock_ = (uint32_t)0;
225 hdr.writeLock_ = (uint32_t)0;
226}
227
228//-----------------------------------------------------------------------------------
229// FileError MfFile::WriteFileLockHdr(const SMfLockHeader &hdr)
230//
231// Write the lock header to the file.
232// Returns a non-zero value to indicate an error condition or zero if successful.
233//-----------------------------------------------------------------------------------
234FileError MfFile::WriteFileLockHdr(const SMfLockHeader &hdr)
235{
236
237 return CFileBase::Store(&hdr, sizeof(SMfLockHeader), sizeof(SMfHeader));
238}
239
240//-----------------------------------------------------------------------------------
241// FileError MfFile::ReadFileLockHdr(SMfLockHeader &hdr)
242//
243// Read the lock header from the file.
244// Returns a non-zero value to indicate an error condition or zero if successful.
245//-----------------------------------------------------------------------------------
246FileError MfFile::ReadFileLockHdr(SMfLockHeader &hdr)
247{
248
249 return CFileBase::Fetch(&hdr, sizeof(SMfLockHeader), sizeof(SMfHeader));
250}
251
252//-----------------------------------------------------------------------------------
253// int MfFile::LockFile(CFileMgrLockType l_type)
254//
255// Lock the file and set the lock access mode to shared or exclusive.
256// Returns a non-zero value if the file cannot be locked or the lock variable cannot
257// be changed because it is exclusive or another thread is currently updating it.
258//-----------------------------------------------------------------------------------
259int MfFile::LockFile(MfLockType l_type)
260{
261 // Read the file lock to ensure that this file has a lock header
262 // and to keep the header in sync during multiple file access.
263 SMfLockHeader lock_header;
264 if (ReadFileLockHdr(lock_header) != FILE_NO_ERROR)
265 return fileError_;
266
267 // Cannot modifiy this lock until the thread holding it releases the
268 // lock header.
269 if (lock_header.lockProtect_ != 0)
270 {
271 fileError_ = ISIS_MFLOCK_ACCESS_ERROR;
272#ifdef __CPP_EXCEPTIONS__
273 throw CFileBaseException(fileError_);
274#else
275 return fileError_;
276#endif
277 }
278
279 switch (l_type)
280 {
281 case MF_WRITE_LOCK :
282 // Cannot obtain an exclusive lock until all the threads in the
283 // read lock queue have finished
284 if ((lock_header.readLock_ != 0) ||
285 (lock_header.writeLock_ != 0))
286 {
287 fileError_ = ISIS_MFLOCK_ERROR;
288 #ifdef __CPP_EXCEPTIONS__
289 throw CFileBaseException(fileError_);
290 #else
291 return fileError_;
292 #endif
293 }
294 else
295 {
296 lock_header.writeLock_ = 1;
297 }
298
299 lock_header.lockProtect_ = 1;
300 if (CFileBase::Store(&lock_header.lockProtect_, sizeof(uint32_t),
301 sizeof(SMfHeader)) != FILE_NO_ERROR)
302 return fileError_;
303
304 // Skip over the read lock member
305 SeekTo(sizeof(SMfHeader) + (sizeof(uint32_t) * 2));
306 if (CFileBase::Store(&lock_header.writeLock_, sizeof(uint32_t)) !=
307 FILE_NO_ERROR)
308 return fileError_;
309
310 lock_header.lockProtect_ = (uint32_t)0;
311 if (CFileBase::Store(&lock_header.lockProtect_, sizeof(uint32_t),
312 sizeof(SMfHeader)) != FILE_NO_ERROR)
313 return fileError_;
314 break;
315
316 case MF_READ_LOCK :
317 // This lock is exclusively owned and cannot be read locked
318 // until the thread holding this lock release the exclusive lock.
319 if (lock_header.writeLock_ == 1)
320 {
321 fileError_ = ISIS_MFLOCK_ERROR;
322 #ifdef __CPP_EXCEPTIONS__
323 throw CFileBaseException(fileError_);
324 #else
325 return fileError_;
326 #endif
327 }
328
329 if (lock_header.readLock_ < 0xFFFFFFFF)
330 {
331 lock_header.readLock_++;
332 }
333 else
334 {
335 fileError_ = ISIS_MFLOCK_ERROR;
336 #ifdef __CPP_EXCEPTIONS__
337 throw CFileBaseException(fileError_);
338 #else
339 return fileError_;
340 #endif
341 }
342
343 lock_header.lockProtect_ = 1;
344 if (CFileBase::Store(&lock_header.lockProtect_, sizeof(uint32_t),
345 sizeof(SMfHeader)) != FILE_NO_ERROR)
346 return fileError_;
347
348 if (CFileBase::Store(&lock_header.readLock_, sizeof(uint32_t)) !=
349 FILE_NO_ERROR)
350 return fileError_;
351
352 lock_header.lockProtect_ = (uint32_t)0;
353 if (CFileBase::Store(&lock_header.lockProtect_, sizeof(uint32_t),
354 sizeof(SMfHeader)) != FILE_NO_ERROR)
355 return fileError_;
356 break;
357
358 default: // Invalid lock type specified
359 fileError_ = ISIS_INVALID_LOCK_TYPE;
360 #ifdef __CPP_EXCEPTIONS__
361 throw CFileBaseException(fileError_);
362 #else
363 return fileError_;
364 #endif
365 }
366
367 return fileError_ = fileError_ = FILE_NO_ERROR;
368}
369
370//-----------------------------------------------------------------------------------
371// int MfFile::UnlockFile(CFileMgrLockType l_type)
372//
373// Unlock the file. Returns a non-zero value if the file cannot be unlocked or the
374// lock variable cannot be changed because it is exclusive or another thread is
375// currently updating it.
376//-----------------------------------------------------------------------------------
377int MfFile::UnlockFile(MfLockType l_type)
378{
379
380 // Read the file lock to ensure that this file has a lock header
381 // and to keep the header in sync during multiple file access.
382 SMfLockHeader lock_header;
383 if (ReadFileLockHdr(lock_header) != FILE_NO_ERROR)
384 return fileError_;
385
386 // Cannot modifiy this lock until the thread holding it releases the
387 // lock header.
388 if (lock_header.lockProtect_ != 0)
389 {
390 fileError_ = ISIS_MFLOCK_ACCESS_ERROR;
391#ifdef __CPP_EXCEPTIONS__
392 throw CFileBaseException(fileError_);
393#else
394 return fileError_;
395#endif
396 }
397
398 switch (l_type)
399 {
400 case MF_WRITE_LOCK :
401 if (lock_header.writeLock_ == 0)
402 return FILE_NO_ERROR;
403 else
404 lock_header.writeLock_ = 0;
405
406 lock_header.lockProtect_ = 1;
407 if (CFileBase::Store(&lock_header.lockProtect_, sizeof(uint32_t),
408 sizeof(SMfHeader)) != FILE_NO_ERROR)
409 return fileError_;
410
411 // Skip over the read lock member
412 SeekTo(sizeof(SMfHeader) + (sizeof(uint32_t) * 2));
413 if (CFileBase::Store(&lock_header.writeLock_, sizeof(uint32_t)) !=
414 FILE_NO_ERROR)
415 return fileError_;
416
417 lock_header.lockProtect_ = (uint32_t)0;
418 if (CFileBase::Store(&lock_header.lockProtect_, sizeof(uint32_t),
419 sizeof(SMfHeader)) != FILE_NO_ERROR)
420 return fileError_;
421 break;
422
423 case MF_READ_LOCK :
424 if (lock_header.readLock_ == 0) // This record is not locked
425 return fileError_ = FILE_NO_ERROR;
426 else if (lock_header.readLock_ > 0) // Prevent read lock rollover
427 lock_header.readLock_--;
428 else
429 lock_header.readLock_ = 0;
430
431 lock_header.lockProtect_ = 1;
432 if (CFileBase::Store(&lock_header.lockProtect_, sizeof(uint32_t),
433 sizeof(SMfHeader)) != FILE_NO_ERROR)
434 return fileError_;
435
436 if (CFileBase::Store(&lock_header.readLock_, sizeof(uint32_t)) !=
437 FILE_NO_ERROR)
438 return fileError_;
439
440 lock_header.lockProtect_ = (uint32_t)0;
441 if (CFileBase::Store(&lock_header.lockProtect_, sizeof(uint32_t),
442 sizeof(SMfHeader)) != FILE_NO_ERROR)
443 return fileError_;
444 break;
445
446 default: // Invalid lock type specified
447 fileError_ = FMGR_INVALID_LOCK_TYPE;
448 #ifdef __CPP_EXCEPTIONS__
449 throw CFileBaseException(fileError_);
450 #else
451 return fileError_;
452 #endif
453 }
454
455 return fileError_ = fileError_ = FILE_NO_ERROR;
456}
457
458//-----------------------------------------------------------------------------------
459// FileError MfFile::ResetFileLock()
460//
461// Reset the file's lock header. This function will clear all the file lock fields
462// without testing the lock or the lock protect. Returns a non-zero value to indicate
463// an error condition or zero if successful.
464//-----------------------------------------------------------------------------------
465FileError MfFile::ResetFileLock()
466{
467 SMfLockHeader lock_header;
468 InitFileLockHdr(lock_header);
469 return WriteFileLockHdr(lock_header);
470}
Note: See TracBrowser for help on using the repository browser.