source: main/trunk/greenstone2/build-src/packages/isis-gdl/MFFile.cpp

Last change on this file was 34961, checked in by anupama, 3 years ago

Merging Dr Bainbridge's mg-long related updates for IsisGdl that got IsisGdl working on 64 bit linux, and on new Macs that were no longer backwards compatible with 32 bit. Tested only to compile and run (CDS-ISIS tutorial) on 64 bit linux. Merged version of code untested on Mac, though it was used to generate the static 64 bit Mac IsisGdl before. Also untested on 32 bit linux, but Dr Bainbridge had earlier indicated it was backwards. At present the release kit code is still grabbing the statically built IsisGdl (for 32 and nowadayas also 64 bit Mac/Linux) as before and including in binaries. This can be changed later. These code changes are for locally compiling up GS from SVN with an IsisGdl built on the local machine meant to work on that local machine.

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