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

Last change on this file since 26670 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: 15.7 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(long mfb, int mfp, MfRecord &m)
97//
98// Reads the master file record beginning at address (mfb,mfp) into m
99//----------------------------------------------------------------------------------
100bool MfFile::ReadMfRecord(long mfb, int mfp, MfRecord &m)
101{
102 return m.Read(*this, mfb, mfp);
103}
104
105//-------------------------------------------------------------------------------
106// void WriteMfRecord(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(long mfb, int mfp, MfRecord &m)
112{
113 m.Write(*this, mfb, mfp);
114}
115
116
117//--------------------------------------------------------------------------------
118// void CreateMfRecord(MfRecord &m, 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, long &mfb, int &mfp)
127{
128}
129
130void MfFile::AppendNewBlock()
131{
132}
133
134//--------------------------------------------------------------------------------
135// void AddMfRecord(MfRecord &m, 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, long &mfb, int &mfp)
142{
143}
144
145
146//--------------------------------------------------------------------------------
147// void UpdateMfRecord(MfRecord &m, 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, 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(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(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(long daddr, MfRecord &m)
213//
214// Stores Master record object m to disk address daddr
215// Non blocked version
216//---------------------------------------------------------------------------------
217void MfFile::WriteMfRecord(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.