00001 // Copyright (C) 2001, Compaq Computer Corporation 00002 // 00003 // This file is part of Vesta. 00004 // 00005 // Vesta is free software; you can redistribute it and/or 00006 // modify it under the terms of the GNU Lesser General Public 00007 // License as published by the Free Software Foundation; either 00008 // version 2.1 of the License, or (at your option) any later version. 00009 // 00010 // Vesta is distributed in the hope that it will be useful, 00011 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00013 // Lesser General Public License for more details. 00014 // 00015 // You should have received a copy of the GNU Lesser General Public 00016 // License along with Vesta; if not, write to the Free Software 00017 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 00018 00019 // 00020 // VestaLogPrivate.H 00021 // 00022 // Log changes to the repository state 00023 // Portion of VestaLog that is private to the implementation but is 00024 // needed by the compiler to build clients. 00025 // 00026 00027 #ifndef _VLOGP 00028 #define _VLOGP 1 00029 00030 #include "Basics.H" 00031 #include <netinet/in.h> 00032 00033 static const int DiskBlockSize = 512; 00034 00035 struct VLogBlock { 00036 VLogBlock *next; 00037 int phy; // "physical" block number (address in file) 00038 int pocketPhy; // reading: phy # of block left in pocket after 00039 // this one was sequenced. 00040 // writing: phy # of unused block in pocket 00041 bool tailCommitted; // during reading, true if the bytes beyond 00042 // len are known to be committed 00043 struct data_block { 00044 // Both seq and len are always in big-endian order. 00045 Bit32 seq_; // hashed sequence number of this logical block 00046 Bit16 len_; // (offset to end of last record in this block, or 00047 // 0 if no record ends in this block) + 00048 // (2 bit block version number in high-order bits) 00049 char bytes[DiskBlockSize - 6]; 00050 00051 inline Bit32 getSeq() throw() 00052 { return ntohl(seq_); }; 00053 inline Bit16 getLen() throw() 00054 { return ntohs(len_) & 0x3FFF; }; 00055 inline Bit16 getVer() throw() 00056 { return (ntohs(len_) >> 14) & 0x0003; }; 00057 inline void setSeq(Bit32 seq) throw() 00058 { seq_ = htonl(seq); }; 00059 inline void setLen(Bit16 len) throw() 00060 { len_ = htons(len | (getVer() << 14)); }; 00061 inline void setVer(Bit16 ver) throw() 00062 { len_ = htons(getLen() | ((ver & 0x0003) << 14)); }; 00063 } *data; 00064 00065 VLogBlock() 00066 { 00067 data = NEW_PTRFREE(data_block); 00068 #if defined(VALGRIND_SUPPORT) 00069 memset((void *) data, 0, sizeof(data_block)); 00070 #endif 00071 } 00072 ~VLogBlock() 00073 { 00074 delete data; 00075 data = NULL; // Help out the garbage collecotr 00076 } 00077 }; 00078 00079 00080 struct VestaLogPrivate { 00081 enum State { initial=0, recovering, recovered, ready, logging, bad }; 00082 bool checkpointing; 00083 bool readonly; 00084 bool bakckp; // true if backing up checkpoints 00085 bool hitEOF; // reading: true if we got an end-of-file 00086 bool usePocket; // writing: true if we should write to pocket next 00087 bool commUsePocket; // writing: usePocket after last commit 00088 int nesting; // if state==logging, how deeply starts are nested. 00089 State state; 00090 char* directory; // directory containing log and checkpoint files 00091 char* directory2; // dir containing backup of log (and ckp), or NULL 00092 int version; // log version currently open 00093 int ccVersion; // highest committed checkpoint 00094 int ccVersion2; // highest committed checkpoint in backup (if any) 00095 int fd; // log file descriptor 00096 int fd2; // log file descriptor for backup, -1 if none 00097 int lockfd; // lock file descriptor 00098 int lockfd2; // lock file descriptor for backup 00099 int curSeq; // seq number of first block in cur chain 00100 int curLen; // offset of next byte in buf->bytes to read or write 00101 int nextSeq; // reading: seq number of next block not yet sequenced 00102 int nextPhy; // reading: phy address of next block not yet read 00103 int commSeq; // writing: curSeq of last block written to commit 00104 int commPhy; // writing: cur->phy after last commit 00105 int commPocketPhy; // writing: cur->pocketPhy after last commit 00106 VLogBlock* cur; // reading: chain of blocks already read and sequenced 00107 // writing: buffer for block being assembled 00108 VLogBlock* last; // reading: last block in cur chain, NULL if none 00109 VLogBlock* pocket; // reading: holds saved out-of-order block 00110 VLogBlock* free; // free list 00111 00112 inline VLogBlock* balloc() throw() { 00113 if (free) { 00114 VLogBlock* b = free; 00115 free = free->next; 00116 b->next = NULL; // just to be cautious 00117 return b; 00118 } else { 00119 return NEW(VLogBlock); 00120 } 00121 }; 00122 inline void bfree(VLogBlock *b) throw() { 00123 b->next = free; 00124 free = b; 00125 }; 00126 void extendCur() // extend the cur chain by one block 00127 throw(VestaLog::Eof, VestaLog::Error); 00128 void makeBytesAvail() // ensure bytes to read in cur 00129 throw(VestaLog::Eof, VestaLog::Error); 00130 void writeCur() // write out cur block 00131 throw(VestaLog::Error); 00132 void makeSpaceAvail() // write full cur block and empty cur 00133 throw(VestaLog::Error); 00134 void eraseUncommitted(int fd) // write invalid data to unused blocks 00135 throw(VestaLog::Error); 00136 VLogBlock* readBlock() // read next block, return NULL if EOF 00137 throw(VestaLog::Error); 00138 }; 00139 00140 #endif //_VLOGP