2009-02-01 20:53:54 +01:00
// recstore.h
2010-02-09 22:48:21 +01:00
/*
* Copyright ( C ) 2010 10 gen Inc .
*
* This program is free software : you can redistribute it and / or modify
* it under the terms of the GNU Affero General Public License , version 3 ,
* as published by the Free Software Foundation .
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU Affero General Public License for more details .
*
* You should have received a copy of the GNU Affero General Public License
* along with this program . If not , see < http : //www.gnu.org/licenses/>.
*/
2009-02-01 20:53:54 +01:00
# pragma once
2009-02-06 19:29:57 +01:00
# include "../util/file.h"
2009-02-01 20:53:54 +01:00
namespace mongo {
2009-02-03 00:18:22 +01:00
using boost : : uint32_t ;
using boost : : uint64_t ;
2009-02-02 04:21:32 +01:00
2009-02-01 20:53:54 +01:00
/* Current version supports only consistent record sizes within a store. */
2009-02-03 00:18:22 +01:00
class BasicRecStore {
struct RecStoreHeader {
uint32_t version ;
uint32_t recsize ;
uint64_t leof ; // logical eof, actual file might be prealloc'd further
uint64_t firstDeleted ; // 0 = no deleted recs
2009-02-06 20:33:26 +01:00
uint32_t cleanShutdown ; // 0 = clean
2009-02-03 00:18:22 +01:00
char reserved [ 8192 - 8 - 8 - 4 - 4 - 4 ] ; // we want our records page-aligned in the file if they are a multiple of a page's size -- so we make this 8KB with that goal
RecStoreHeader ( ) {
version = 65 ;
recsize = 0 ;
leof = sizeof ( RecStoreHeader ) ;
firstDeleted = 0 ;
cleanShutdown = 1 ;
memset ( reserved , 0 , sizeof ( reserved ) ) ;
}
} ;
2009-02-01 20:53:54 +01:00
public :
2009-03-13 16:56:28 +01:00
BasicRecStore ( int _fileNumber ) : fileNumber ( _fileNumber ) { }
2009-02-03 00:18:22 +01:00
~ BasicRecStore ( ) ;
void init ( const char * fn , unsigned recsize ) ;
2009-02-01 20:53:54 +01:00
fileofs insert ( const char * buf , unsigned len ) ;
void update ( fileofs o , const char * buf , unsigned len ) ;
void remove ( fileofs o , unsigned len ) ;
2009-02-03 00:18:22 +01:00
void get ( fileofs o , char * buf , unsigned len ) ;
2009-03-13 16:56:28 +01:00
int fileNumber ; // this goes in DiskLoc::a
2009-03-17 22:02:21 +01:00
string filename ;
2009-02-01 20:53:54 +01:00
private :
2009-02-03 00:18:22 +01:00
2009-02-01 20:53:54 +01:00
void writeHeader ( ) ;
2009-02-06 19:29:57 +01:00
File f ;
2009-02-01 20:53:54 +01:00
fileofs len ;
RecStoreHeader h ; // h.reserved is wasteful here; fix later.
2009-02-03 00:18:22 +01:00
void write ( fileofs ofs , const char * data , unsigned len ) {
2009-02-06 19:29:57 +01:00
f . write ( ofs , data , len ) ;
2009-12-28 22:43:43 +01:00
massert ( 10380 , " basicrecstore write io error " , ! f . bad ( ) ) ;
2009-02-03 00:18:22 +01:00
}
2009-02-01 20:53:54 +01:00
} ;
/* --- implementation --- */
2009-02-03 00:18:22 +01:00
inline BasicRecStore : : ~ BasicRecStore ( ) {
2009-02-01 20:53:54 +01:00
h . cleanShutdown = 0 ;
2009-02-06 20:33:26 +01:00
if ( f . is_open ( ) ) {
2009-02-01 20:53:54 +01:00
writeHeader ( ) ;
2009-02-06 20:33:26 +01:00
f . fsync ( ) ;
}
2009-02-01 20:53:54 +01:00
}
2009-02-03 00:18:22 +01:00
inline void BasicRecStore : : writeHeader ( ) {
write ( 0 , ( const char * ) & h , 28 ) ; // update header in file for new leof
2009-12-28 22:43:43 +01:00
uassert ( 10115 , " file io error in BasicRecStore [1] " , ! f . bad ( ) ) ;
2009-02-01 20:53:54 +01:00
}
2009-02-03 00:18:22 +01:00
inline fileofs BasicRecStore : : insert ( const char * buf , unsigned reclen ) {
2009-02-01 20:53:54 +01:00
if ( h . firstDeleted ) {
2009-12-28 22:43:43 +01:00
uasserted ( 11500 , " deleted not yet implemented recstoreinsert " ) ;
2009-02-01 20:53:54 +01:00
}
2009-12-28 22:43:43 +01:00
massert ( 10381 , " bad len " , reclen = = h . recsize ) ;
2009-02-01 20:53:54 +01:00
fileofs ofs = h . leof ;
h . leof + = reclen ;
if ( h . leof > len ) {
// grow the file. we grow quite a bit to avoid excessive file system fragmentations
len + = ( len / 8 ) + h . recsize ;
2009-12-28 22:43:43 +01:00
uassert ( 10116 , " recstore file too big for 32 bit " , len < = 0x7fffffff | | sizeof ( std : : streamoff ) > 4 ) ;
2009-02-03 00:18:22 +01:00
write ( len , " " , 0 ) ;
2009-02-01 20:53:54 +01:00
}
writeHeader ( ) ;
2009-02-03 00:18:22 +01:00
write ( ofs , buf , reclen ) ;
2009-12-28 22:43:43 +01:00
uassert ( 10117 , " file io error in BasicRecStore [2] " , ! f . bad ( ) ) ;
2009-02-01 20:53:54 +01:00
return ofs ;
}
2009-02-03 00:18:22 +01:00
/* so far, it's ok to read or update a subset of a record */
inline void BasicRecStore : : update ( fileofs o , const char * buf , unsigned len ) {
assert ( o < = h . leof & & o > = sizeof ( RecStoreHeader ) ) ;
write ( o , buf , len ) ;
}
inline void BasicRecStore : : get ( fileofs o , char * buf , unsigned len ) {
2009-02-01 20:53:54 +01:00
assert ( o < = h . leof & & o > = sizeof ( RecStoreHeader ) ) ;
2009-02-06 19:29:57 +01:00
f . read ( o , buf , len ) ;
2009-12-28 22:43:43 +01:00
massert ( 10382 , " basicrestore::get I/O error " , ! f . bad ( ) ) ;
2009-02-01 20:53:54 +01:00
}
2009-02-03 00:18:22 +01:00
inline void BasicRecStore : : remove ( fileofs o , unsigned len ) {
2009-12-28 22:43:43 +01:00
uasserted ( 11501 , " not yet implemented recstoreremove " ) ;
2009-02-01 20:53:54 +01:00
}
}