00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035 #include "BitMap.h"
00036 #include "RioError.h"
00037
00038 #include <stdlib.h>
00039 #include <string.h>
00040 #include <errno.h>
00041 #include <sys/types.h>
00042 #include <sys/stat.h>
00043 #include <fcntl.h>
00044 #include <unistd.h>
00045 #include <stdio.h>
00046
00047
00048
00049
00050 BitMap::BitMap()
00051 {
00052 m_FileName = NULL;
00053 m_nBits = 0;
00054 m_nFree = 0;
00055 m_nFreeConfirmed = 0;
00056 m_nBytes = 0;
00057 m_BitMap = NULL;
00058 m_handle = -1;
00059 m_log = NULL;
00060 m_changed = false;
00061 }
00062
00063 BitMap::~BitMap()
00064 {
00065 iclose();
00066 ifreestg();
00067 }
00068
00069
00070
00071 void BitMap::ifreestg()
00072 {
00073 if( m_BitMap != 0 )
00074 {
00075 delete[] m_BitMap;
00076 m_BitMap = 0;
00077 }
00078
00079 if( m_FileName != 0 )
00080 {
00081 delete[] m_FileName;
00082 m_FileName = 0;
00083 }
00084 m_nBits = m_nBytes = 0;
00085 }
00086
00087
00088
00089 int BitMap::iclose()
00090 {
00091 if( m_handle != -1 )
00092 {
00093 if( close( m_handle ) == -1 )
00094 {
00095 *m_log << "BitMap::Close(): Error closing bitmap file "
00096 << m_FileName << "\n SYSTEM ERROR: " << strerror( errno )
00097 << endl;
00098 return ERROR_OBJECTMANAGER + ERROR_UNEXPECTED;
00099 }
00100 m_handle = -1;
00101 }
00102 return 0;
00103 }
00104
00105
00106 int BitMap::Initialize( char *BitMapFileName, unsigned int nBits,
00107 ostream *Logstream )
00108 {
00109 m_log = Logstream;
00110
00111 if( nBits < 1 )
00112 {
00113 (*m_log) << "BitMap::Initialize(): Unexpected error. "
00114 << " Number of Bits specified is less than one"
00115 << endl;
00116 return ERROR_OBJECTMANAGER + ERROR_UNEXPECTED;
00117 }
00118
00119 ifreestg();
00120
00121 m_nBits = nBits;
00122 m_nBytes = ( m_nBits + 7 ) >> 3;
00123 m_BitMap = new unsigned char[m_nBytes];
00124 if( m_BitMap == NULL )
00125 {
00126 ifreestg();
00127 return ERROR_OBJECTMANAGER + ERROR_MEMORY;
00128 }
00129
00130
00131 m_FileName = new char [strlen( BitMapFileName ) + 1];
00132
00133 if( m_FileName == NULL )
00134 {
00135 ifreestg();
00136 return ERROR_OBJECTMANAGER + ERROR_MEMORY;
00137 }
00138
00139 strcpy( m_FileName, BitMapFileName );
00140
00141 return 0;
00142 }
00143
00144
00145
00146 int BitMap::Format()
00147 {
00148
00149 memset( m_BitMap, 0, m_nBytes );
00150
00151
00152 unsigned int x;
00153 for( x = m_nBits; x < ( m_nBytes << 3 ); x++ )
00154 {
00155 SetBit( x );
00156 }
00157
00158
00159 m_handle = open( m_FileName, O_RDWR | O_TRUNC | O_CREAT, 0700 );
00160 if( m_handle == -1 )
00161 {
00162 (*m_log) << "BitMap::Format(): "
00163 << " open create for " << m_FileName << " failed "
00164 << strerror(errno) << endl;
00165 return ERROR_OBJECTMANAGER + ERROR_SYSTEM_CONFIGURATION;
00166 }
00167
00168
00169 m_nFree = CountnFree();
00170
00171
00172 m_changed = true;
00173 return Confirm();
00174 }
00175
00176
00177 int BitMap::Load()
00178 {
00179
00180 m_handle = open( m_FileName, O_RDWR, 0 );
00181 if( m_handle == -1 )
00182 {
00183 RioErr << "BitMap::Load(): Could not open bitmap file "
00184 << m_FileName << " with RDWR permissions, trying to open with "
00185 << "RDONLY permission" << endl;
00186
00187 m_handle = open( m_FileName, O_RDONLY, 0 );
00188 if( m_handle == -1 )
00189 {
00190
00191
00192 char answer[128] = "";
00193
00194 do {
00195
00196
00197
00198
00199 RioErr << "BitMap::Load() You have to format the new disk "
00200 << " before start server. Exiting..." << endl;
00201 return ERROR_OBJECTMANAGER + ERROR_UNEXPECTED;
00202 }while(( answer[0] != 'Y' ) && ( answer[0] != 'y' ));
00203
00204
00205 RioErr << " Trying to format ... " << endl;
00206 int rc2 = Format();
00207
00208 unsigned int junk;
00209 if( !rc2 )
00210 {
00211 rc2 = AllocSeq( 0, &junk );
00212 }
00213 if( !rc2 )
00214 {
00215 rc2 = AllocSeq( 1, &junk );
00216 }
00217 if( rc2 )
00218 {
00219 RioErr << " Error! " << endl;
00220 return ERROR_OBJECTMANAGER + ERROR_UNEXPECTED;
00221 }
00222 RioErr << " New device formatted. " << endl;
00223 Confirm();
00224 close( m_handle );
00225 RioErr << " Trying to open the new device." << endl;
00226 m_handle = open( m_FileName, O_RDWR, 0 );
00227 if( m_handle == -1 )
00228 {
00229 RioErr << "BitMap::Load(): Could not open bitmap file "
00230 << m_FileName << endl
00231 << " SYSTEM ERROR: " << strerror(errno) << endl;
00232 return ERROR_OBJECTMANAGER + ERROR_UNEXPECTED;
00233 }
00234 RioErr << " OK. " << endl;
00235
00236 }
00237 }
00238
00239 unsigned int nBytes;
00240 nBytes = read( m_handle, m_BitMap, m_nBytes );
00241 if( ( nBytes != ( unsigned int )m_nBytes ) )
00242 {
00243 RioErr << "BitMap::Load(): Error reading bitmap file "
00244 << m_FileName << endl
00245 << " SYSTEM ERROR: " << strerror(errno) << endl;
00246 close( m_handle );
00247 return ERROR_OBJECTMANAGER + ERROR_UNEXPECTED;
00248 }
00249
00250
00251 m_nFree = CountnFree();
00252 m_nFreeConfirmed = m_nFree;
00253
00254 m_changed = false;
00255 return 0;
00256 }
00257
00258
00259
00260 int BitMap::Reset()
00261 {
00262 unsigned int nBytes;
00263
00264 lseek( m_handle, 0, SEEK_SET );
00265 nBytes = read( m_handle, m_BitMap, m_nBytes );
00266 if( ( nBytes != ( unsigned int ) m_nBytes ) )
00267 {
00268 (*m_log) << "BitMap::Reset(): Error reading bitmap file "
00269 << m_FileName << " - " << strerror(errno) << endl;
00270
00271
00272 iclose();
00273 return ERROR_OBJECTMANAGER + ERROR_UNEXPECTED;
00274 }
00275
00276 m_nFree = m_nFreeConfirmed;
00277 m_changed = false;
00278 return 0;
00279 }
00280
00281
00282
00283
00284 int BitMap::Confirm()
00285 {
00286
00287 if( m_changed )
00288 {
00289
00290 lseek( m_handle, 0, SEEK_SET );
00291 unsigned int nBytes;
00292
00293 nBytes = write( m_handle, m_BitMap, m_nBytes );
00294 if( ( nBytes != ( unsigned int ) m_nBytes ) )
00295 {
00296 (*m_log) << "BitMap::Flush(): Error writing bitmap file "
00297 << m_FileName << "\n SYSTEM ERROR: " << strerror(errno)
00298 << endl;
00299 return ERROR_OBJECTMANAGER + ERROR_UNEXPECTED;
00300 }
00301
00302 fsync( m_handle );
00303 m_nFreeConfirmed = m_nFree;
00304 m_changed = false;
00305 }
00306 return 0;
00307 }
00308
00309
00310
00311 int BitMap::AllocSeq(unsigned int Startbit, unsigned int *Bit)
00312 {
00313 if( m_nFree <= 0 )
00314 {
00315 return ERROR_BITMAP + 1;
00316 }
00317
00318 if( Startbit >= m_nBits )
00319 {
00320 abort();
00321 }
00322
00323 unsigned int x = Startbit;
00324 int off;
00325 unsigned int BitCount = 0;
00326
00327 while( 1 )
00328 {
00329
00330
00331 if( BitCount > ( m_nBits + 8 ) )
00332 break;
00333 if( x >= m_nBits )
00334 x = 0;
00335 off = x >> 3;
00336
00337
00338
00339 if( m_BitMap[off] == 0xff )
00340 {
00341 x = ( off + 1 ) << 3;
00342 BitCount += 8;
00343 }
00344 else
00345 {
00346 if( !TestBit( x ) )
00347 {
00348 SetBit( x );
00349 *Bit = x;
00350 m_changed = true;
00351 m_nFree--;
00352 return 0;
00353 }
00354 x++;
00355 BitCount++;
00356 }
00357 }
00358
00359
00360
00361
00362 *m_log << "BitMap::AllocSeq(): no free bits found for "
00363 << m_FileName << " (UNEXPECTED ERROR)" << endl;
00364 return ERROR_BITMAP + 2;
00365 }
00366
00367
00368 void BitMap::Free(const unsigned int Bit)
00369 {
00370 if( TestBit( Bit ) )
00371 {
00372 ClearBit(Bit);
00373 m_changed = true;
00374 m_nFree++;
00375 return;
00376 }
00377
00378
00379 *m_log << "BitMap::Free(): Attempt to free bit already free for "
00380 << m_FileName << " bit " << Bit << endl;
00381 RioErr << "BitMap::Free(): Attempt to free bit already free for "
00382 << m_FileName << " bit " << Bit << endl;
00383 }
00384
00385
00386 unsigned int BitMap::CountnFree()
00387 {
00388
00389 unsigned int count = 0;
00390 for( unsigned int i = 0;i < m_nBytes; i++ )
00391 {
00392 count += CountFreeBits( m_BitMap[i] );
00393 }
00394
00395 return count;
00396 }
00397
00398
00399 bool BitMap::TestBit( const unsigned int Bit )
00400 {
00401 int mask = 0x80 >> ( Bit & 7 );
00402 int off = Bit >> 3;
00403 return (( m_BitMap[off] & mask ) != 0);
00404 }
00405
00406
00407 void BitMap::SetBit ( const unsigned int Bit )
00408 {
00409 int mask = 0x80 >> ( Bit & 7 );
00410 int off = Bit >> 3;
00411 m_BitMap[off] |= mask;
00412 }
00413
00414
00415 void BitMap::ClearBit ( const unsigned int Bit )
00416 {
00417 int mask = 0x80 >> ( Bit & 7 );
00418 int off = Bit >> 3;
00419 m_BitMap[off] &= ~mask;
00420 }
00421
00422
00423 unsigned int BitMap::CountFreeBits( const int byte )
00424 {
00425 unsigned int count = 0;
00426 int mask = 0x80;
00427 for( int i = 0; i < 8; i++ )
00428 {
00429 if( ( mask & byte ) == 0 )
00430 count++;
00431 mask = mask >> 1;
00432 }
00433 return count;
00434 }
00435