Fairport  v1.0.38
fairport/disk/disk.h
Go to the documentation of this file.
00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 #ifndef FAIRPORT_DISK_DISK_H
00011 #define FAIRPORT_DISK_DISK_H
00012 
00013 #include <cstddef>
00014 
00015 #include "fairport/util/primitives.h"
00016 
00018 namespace fairport
00019 {
00021 namespace disk
00022 {
00023 
00028 template<typename T>
00029 struct block_reference
00030 {
00031     typedef T block_id_disk;
00032     typedef T location;
00033 
00034     block_id_disk bid; 
00035     location ib;       
00036 } FAIRPORT_MS_STRUCT;
00038 static_assert(sizeof(block_reference<ulong>) == 8, "block_reference<ulong> incorrect size");
00039 static_assert(sizeof(block_reference<ulonglong>) == 16, "block_reference<ulonglong> incorrect size");
00041 
00042 //
00043 // header
00044 //
00045 
00048 
00052 const size_t header_fmap_entries = 128;
00053 
00057 const size_t header_fpmap_size = 128;
00058 
00062 const size_t header_lock_entries = 32;
00063 
00067 enum database_format
00068 {
00069     database_format_ansi_min = 14,      
00070     database_format_ansi = 15,          
00071     database_format_unicode_min = 20,   
00072     database_format_unicode = 23        
00073 };
00074 
00078 enum database_type
00079 {
00080     database_ost = 12, 
00081     database_pst = 19  
00082 };
00083 
00086 const ushort pst_magic = 0x4D53;
00089 const ushort ost_magic = 0x4F53;
00090 
00096 enum crypt_method
00097 {
00098     crypt_method_none = 0,    
00099     crypt_method_permute = 1, 
00100     crypt_method_cyclic = 2   
00101 };
00102 
00111 template<typename T>
00112 struct root
00113 {
00114     typedef T location;
00115     typedef T count;
00116 
00117     ulong cOrphans;             
00118     location ibFileEof;         
00119     location ibAMapLast;        
00120     count cbAMapFree;           
00121     count cbPMapFree;           
00122     block_reference<T> brefNBT; 
00123     block_reference<T> brefBBT; 
00124     byte fAMapValid;            
00125     byte bARVec;                
00126     ushort cARVec;              
00127 } FAIRPORT_MS_STRUCT;
00129 static_assert(sizeof(root<ulong>) == 40, "root<ulong> incorrect size");
00130 static_assert(sizeof(root<ulonglong>) == 80, "root<ulonglong> incorrect size");
00131 static_assert(offsetof(root<ulonglong>, cOrphans) == 0, "root<ulonglong> cOrphans at incorrect offset");
00132 static_assert(offsetof(root<ulonglong>, ibFileEof) == 8, "root<ulonglong> ibFileEof at incorrect offset");
00133 static_assert(offsetof(root<ulonglong>, ibAMapLast) == 16, "root<ulonglong> ibAMapLast at incorrect offset");
00134 static_assert(offsetof(root<ulonglong>, cbAMapFree) == 24, "root<ulonglong> cbAMapFree at incorrect offset");
00135 static_assert(offsetof(root<ulonglong>, cbPMapFree) == 32, "root<ulonglong> cbPMapFree at incorrect offset");
00136 static_assert(offsetof(root<ulonglong>, brefNBT) == 40, "root<ulonglong> brefNBT at incorrect offset");
00137 static_assert(offsetof(root<ulonglong>, brefBBT) == 56, "root<ulonglong> brefBBT at incorrect offset");
00138 static_assert(offsetof(root<ulonglong>, fAMapValid) == 72, "root<ulonglong> fAMapValid at incorrect offset");
00139 static_assert(offsetof(root<ulonglong>, bARVec) == 73, "root<ulonglong> bARVec at incorrect offset");
00140 static_assert(offsetof(root<ulonglong>, cARVec) == 74, "root<ulonglong> cARVec at incorrect offset");
00142 
00148 const uint hlmagic = 0x4e444221;
00149 
00151 template<typename T>
00152 struct header
00153 {
00154 } FAIRPORT_MS_STRUCT;
00156 
00164 template<>
00165 struct header<ulonglong>
00166 {
00167     typedef ulonglong block_id_disk;   
00168     typedef ulonglong location;        
00169     typedef ulonglong count;           
00170 
00171     ulong dwMagic;                     
00172     ulong dwCRCPartial;
00173     ushort wMagicClient;               
00174     ushort wVer;                       
00175     ushort wVerClient;                 
00176     byte bPlatformCreate;              
00177     byte bPlatformAccess;              
00178     ulong dwOpenDBID;                  
00179     ulong dwOpenClaimID;               
00180     block_id_disk bidUnused;           
00181     block_id_disk bidNextP;            
00182     ulong dwUnique;
00183     node_id rgnid[nid_type_max];       
00184     root<ulonglong> root_info;         
00185     byte rgbFM[header_fmap_entries];   
00186     byte rgbFP[header_fpmap_size];     
00187     byte bSentinel;                    
00188     byte bCryptMethod;                 
00189     byte rgbReserved[2];               
00190 #ifdef __GNUC__
00191     // GCC refuses to pack this next to rgbReserved
00192     byte bidNextB[8];
00193 #else
00194 #pragma pack(4)
00195     block_id_disk bidNextB;            
00196 #pragma pack()
00197 #endif
00198     ulong dwCRCFull;
00199     byte rgbVersionEncoded[3];
00200     byte bLockSemaphore;               
00201     byte rgbLock[header_lock_entries]; 
00202 } FAIRPORT_MS_STRUCT;
00204 static_assert(sizeof(header<ulonglong>) == 568, "header<ulonglong> incorrect size");
00205 static_assert(offsetof(header<ulonglong>, rgnid) == 44, "header<ulonglong> rgnid at incorrect offset");
00206 static_assert(offsetof(header<ulonglong>, root_info) == 176, "header<ulonglong> root_info at incorrect offset");
00207 static_assert(offsetof(header<ulonglong>, rgbFM) == 256, "header<ulonglong> rgbFM at incorrect offset");
00208 static_assert(offsetof(header<ulonglong>, dwCRCFull) == 524, "header<ulonglong> dwCRCFull at incorrect offset");
00210 
00217 template<>
00218 struct header<ulong>
00219 {
00220     typedef ulong block_id_disk;
00221     typedef ulong location;
00222     typedef ulong count;
00223 
00224     ulong dwMagic;
00225     ulong dwCRCPartial;
00226     ushort wMagicClient;
00227     ushort wVer;
00228     ushort wVerClient;
00229     byte bPlatformCreate;
00230     byte bPlatformAccess;
00231     ulong dwOpenDBID;
00232     ulong dwOpenClaimID;
00233 #ifdef __GNUC__
00234     byte bidNextB[4];
00235 #else
00236     block_id_disk bidNextB;
00237 #endif
00238     block_id_disk bidNextP;
00239     ulong dwUnique;
00240     node_id rgnid[nid_type_max];
00241     root<ulong> root_info;
00242     byte rgbFM[header_fmap_entries];
00243     byte rgbFP[header_fpmap_size];
00244     byte bSentinel;
00245     byte bCryptMethod;
00246     byte rgbReserved[2];
00247     ulonglong ullReserved;
00248     ulong dwReserved;
00249     byte rgbVersionEncoded[3];
00250     byte bLockSemaphore;
00251     byte rgbLock[header_lock_entries];
00252 } FAIRPORT_MS_STRUCT;
00254 static_assert(sizeof(header<ulong>) == 512, "header<ulong> incorrect size");
00255 static_assert(offsetof(header<ulong>, rgnid) == 36, "header<ulong> rgnid at incorrect offset");
00256 static_assert(offsetof(header<ulong>, rgbFM) == 204, "header<ulong> rgbFM at incorrect offset");
00258 
00260 template<typename T>
00261 struct header_crc_locations
00262 {
00263 } FAIRPORT_MS_STRUCT;
00265 
00269 template<>
00270 struct header_crc_locations<ulong>
00271 {
00272     static const size_t start = offsetof(header<ulong>, wMagicClient);
00273     static const size_t end = offsetof(header<ulong>, bLockSemaphore);
00274     static const size_t length = end - start;
00275 } FAIRPORT_MS_STRUCT;
00276 
00281 template<>
00282 struct header_crc_locations<ulonglong>
00283 {
00284     static const size_t partial_start = header_crc_locations<ulong>::start;
00285     static const size_t partial_end = header_crc_locations<ulong>::end;
00286     static const size_t partial_length = header_crc_locations<ulong>::length;
00287     static const size_t full_start = offsetof(header<ulonglong>, wMagicClient);
00288     static const size_t full_end = offsetof(header<ulonglong>, dwCRCFull);
00289     static const size_t full_length = full_end - full_start;
00290 } FAIRPORT_MS_STRUCT;
00291 
00292 //
00293 // utility functions
00294 //
00295 
00298 
00301 const ulong crc_table[] = {
00302     0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, 0x076DC419, 0x706AF48F,
00303     0xE963A535, 0x9E6495A3, 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988,
00304     0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91, 0x1DB71064, 0x6AB020F2,
00305     0xF3B97148, 0x84BE41DE, 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7,
00306     0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, 0x14015C4F, 0x63066CD9,
00307     0xFA0F3D63, 0x8D080DF5, 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172,
00308     0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, 0x35B5A8FA, 0x42B2986C,
00309     0xDBBBC9D6, 0xACBCF940, 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59,
00310     0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, 0x21B4F4B5, 0x56B3C423,
00311     0xCFBA9599, 0xB8BDA50F, 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924,
00312     0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D, 0x76DC4190, 0x01DB7106,
00313     0x98D220BC, 0xEFD5102A, 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433,
00314     0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, 0x7F6A0DBB, 0x086D3D2D,
00315     0x91646C97, 0xE6635C01, 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E,
00316     0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457, 0x65B0D9C6, 0x12B7E950,
00317     0x8BBEB8EA, 0xFCB9887C, 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65,
00318     0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, 0x4ADFA541, 0x3DD895D7,
00319     0xA4D1C46D, 0xD3D6F4FB, 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0,
00320     0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9, 0x5005713C, 0x270241AA,
00321     0xBE0B1010, 0xC90C2086, 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F,
00322     0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, 0x59B33D17, 0x2EB40D81,
00323     0xB7BD5C3B, 0xC0BA6CAD, 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A,
00324     0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683, 0xE3630B12, 0x94643B84,
00325     0x0D6D6A3E, 0x7A6A5AA8, 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1,
00326     0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, 0xF762575D, 0x806567CB,
00327     0x196C3671, 0x6E6B06E7, 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC,
00328     0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, 0xD6D6A3E8, 0xA1D1937E,
00329     0x38D8C2C4, 0x4FDFF252, 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B,
00330     0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, 0xDF60EFC3, 0xA867DF55,
00331     0x316E8EEF, 0x4669BE79, 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236,
00332     0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F, 0xC5BA3BBE, 0xB2BD0B28,
00333     0x2BB45A92, 0x5CB36A04, 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D,
00334     0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, 0x9C0906A9, 0xEB0E363F,
00335     0x72076785, 0x05005713, 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38,
00336     0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21, 0x86D3D2D4, 0xF1D4E242,
00337     0x68DDB3F8, 0x1FDA836E, 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777,
00338     0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, 0x8F659EFF, 0xF862AE69,
00339     0x616BFFD3, 0x166CCF45, 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2,
00340     0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB, 0xAED16A4A, 0xD9D65ADC,
00341     0x40DF0B66, 0x37D83BF0, 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9,
00342     0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, 0xBAD03605, 0xCDD70693,
00343     0x54DE5729, 0x23D967BF, 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94,
00344     0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D
00345 };
00346 
00350 const byte table1[] =
00351 {
00352       65,  54,  19,  98, 168,  33, 110, 187,
00353      244,  22, 204,   4, 127, 100, 232,  93,
00354       30, 242, 203,  42, 116, 197,  94,  53,
00355      210, 149,  71, 158, 150,  45, 154, 136,
00356       76, 125, 132,  63, 219, 172,  49, 182,
00357       72,  95, 246, 196, 216,  57, 139, 231,
00358       35,  59,  56, 142, 200, 193, 223,  37,
00359      177,  32, 165,  70,  96,  78, 156, 251,
00360      170, 211,  86,  81,  69, 124,  85,   0,
00361        7, 201,  43, 157, 133, 155,   9, 160,
00362      143, 173, 179,  15,  99, 171, 137,  75,
00363      215, 167,  21,  90, 113, 102,  66, 191,
00364       38,  74, 107, 152, 250, 234, 119,  83,
00365      178, 112,   5,  44, 253,  89,  58, 134,
00366      126, 206,   6, 235, 130, 120,  87, 199,
00367      141,  67, 175, 180,  28, 212,  91, 205,
00368      226, 233,  39,  79, 195,   8, 114, 128,
00369      207, 176, 239, 245,  40, 109, 190,  48,
00370       77,  52, 146, 213,  14,  60,  34,  50,
00371      229, 228, 249, 159, 194, 209,  10, 129,
00372       18, 225, 238, 145, 131, 118, 227, 151,
00373      230,  97, 138,  23, 121, 164, 183, 220,
00374      144, 122,  92, 140,   2, 166, 202, 105,
00375      222,  80,  26,  17, 147, 185,  82, 135,
00376       88, 252, 237,  29,  55,  73,  27, 106,
00377      224,  41,  51, 153, 189, 108, 217, 148,
00378      243,  64,  84, 111, 240, 198, 115, 184,
00379      214,  62, 101,  24,  68,  31, 221, 103,
00380       16, 241,  12,  25, 236, 174,   3, 161,
00381       20, 123, 169,  11, 255, 248, 163, 192,
00382      162,   1, 247,  46, 188,  36, 104, 117,
00383       13, 254, 186,  47, 181, 208, 218,  61,
00384 };
00385 
00389 const byte table2[] =
00390 {
00391       20,  83,  15,  86, 179, 200, 122, 156,
00392      235, 101,  72,  23,  22,  21, 159,   2,
00393      204,  84, 124, 131,   0,  13,  12,  11,
00394      162,  98, 168, 118, 219, 217, 237, 199,
00395      197, 164, 220, 172, 133, 116, 214, 208,
00396      167, 155, 174, 154, 150, 113, 102, 195,
00397       99, 153, 184, 221, 115, 146, 142, 132,
00398      125, 165,  94, 209,  93, 147, 177,  87,
00399       81,  80, 128, 137,  82, 148,  79,  78,
00400       10, 107, 188, 141, 127, 110,  71,  70,
00401       65,  64,  68,   1,  17, 203,   3,  63,
00402      247, 244, 225, 169, 143,  60,  58, 249,
00403      251, 240,  25,  48, 130,   9,  46, 201,
00404      157, 160, 134,  73, 238, 111,  77, 109,
00405      196,  45, 129,  52,  37, 135,  27, 136,
00406      170, 252,   6, 161,  18,  56, 253,  76,
00407       66, 114, 100,  19,  55,  36, 106, 117,
00408      119,  67, 255, 230, 180,  75,  54,  92,
00409      228, 216,  53,  61,  69, 185,  44, 236,
00410      183,  49,  43,  41,   7, 104, 163,  14,
00411      105, 123,  24, 158,  33,  57, 190,  40,
00412       26,  91, 120, 245,  35, 202,  42, 176,
00413      175,  62, 254,   4, 140, 231, 229, 152,
00414       50, 149, 211, 246,  74, 232, 166, 234,
00415      233, 243, 213,  47, 112,  32, 242,  31,
00416        5, 103, 173,  85,  16, 206, 205, 227,
00417       39,  59, 218, 186, 215, 194,  38, 212,
00418      145,  29, 210,  28,  34,  51, 248, 250,
00419      241,  90, 239, 207, 144, 182, 139, 181,
00420      189, 192, 191,   8, 151,  30, 108, 226,
00421       97, 224, 198, 193,  89, 171, 187,  88,
00422      222,  95, 223,  96, 121, 126, 178, 138,
00423 };
00424 
00428 const byte table3[] =
00429 {
00430       71, 241, 180, 230,  11, 106, 114,  72,
00431      133,  78, 158, 235, 226, 248, 148,  83,
00432      224, 187, 160,   2, 232,  90,   9, 171,
00433      219, 227, 186, 198, 124, 195,  16, 221,
00434       57,   5, 150,  48, 245,  55,  96, 130,
00435      140, 201,  19,  74, 107,  29, 243, 251,
00436      143,  38, 151, 202, 145,  23,   1, 196,
00437       50,  45, 110,  49, 149, 255, 217,  35,
00438      209,   0,  94, 121, 220,  68,  59,  26,
00439       40, 197,  97,  87,  32, 144,  61, 131,
00440      185,  67, 190, 103, 210,  70,  66, 118,
00441      192, 109,  91, 126, 178,  15,  22,  41,
00442       60, 169,   3,  84,  13, 218,  93, 223,
00443      246, 183, 199,  98, 205, 141,   6, 211,
00444      105,  92, 134, 214,  20, 247, 165, 102,
00445      117, 172, 177, 233,  69,  33, 112,  12,
00446      135, 159, 116, 164,  34,  76, 111, 191,
00447       31,  86, 170,  46, 179, 120,  51,  80,
00448      176, 163, 146, 188, 207,  25,  28, 167,
00449       99, 203,  30,  77,  62,  75,  27, 155,
00450       79, 231, 240, 238, 173,  58, 181,  89,
00451        4, 234,  64,  85,  37,  81, 229, 122,
00452      137,  56, 104,  82, 123, 252,  39, 174,
00453      215, 189, 250,   7, 244, 204, 142,  95,
00454      239,  53, 156, 132,  43,  21, 213, 119,
00455       52,  73, 182,  18,  10, 127, 113, 136,
00456      253, 157,  24,  65, 125, 147, 216,  88,
00457       44, 206, 254,  36, 175, 222, 184,  54,
00458      200, 161, 128, 166, 153, 152, 168,  47,
00459       14, 129, 101, 115, 228, 194, 162, 138,
00460      212, 225,  17, 208,   8, 139,  42, 242,
00461      237, 154, 100,  63, 193, 108, 249, 236
00462 };
00463 
00471 template<typename T>
00472 ushort compute_signature(T id, T address);
00473 
00480 template<typename T>
00481 ushort compute_signature(const block_reference<T>& reference) { return compute_signature(reference.bid, reference.ib); }
00482 
00489 ulong compute_crc(const void * pdata, ulong cb);
00490 
00500 void permute(void * pdata, ulong cb, bool encrypt);
00501 
00511 void cyclic(void * pdata, ulong cb, ulong key);
00512 
00513 
00514 //
00515 // page structures
00516 //
00517 
00520 
00521 
00525 const size_t page_size = 512;
00526 
00532 enum page_type
00533 {
00534     page_type_bbt = 0x80,   
00535     page_type_nbt = 0x81,   
00536     page_type_fmap = 0x82,  
00537     page_type_pmap = 0x83,  
00538     page_type_amap = 0x84,  
00539     page_type_fpmap = 0x85, 
00540     page_type_dlist = 0x86  
00541 };
00542 
00544 template<typename T>
00545 struct page_trailer
00546 {
00547 } FAIRPORT_MS_STRUCT;
00549 
00555 template<>
00556 struct page_trailer<ulonglong>
00557 {
00558     typedef ulonglong block_id_disk;
00559 
00560     byte page_type;        
00561     byte page_type_repeat; 
00562     ushort signature;      
00563     ulong crc;             
00564     block_id_disk bid;     
00565 } FAIRPORT_MS_STRUCT;
00567 static_assert(sizeof(page_trailer<ulonglong>) == 16, "page_trailer<ulonglong> incorrect size");
00569 
00576 template<>
00577 struct page_trailer<ulong>
00578 {
00579     typedef ulong block_id_disk;
00580 
00581     byte page_type;
00582     byte page_type_repeat;
00583     ushort signature;
00584     block_id_disk bid;
00585     ulong crc;
00586 } FAIRPORT_MS_STRUCT;
00588 static_assert(sizeof(page_trailer<ulong>) == 12, "page_trailer<ulong> incorrect size");
00590 
00595 template<typename T>
00596 struct page
00597 {
00598     static const size_t page_data_size = page_size - sizeof(page_trailer<T>); 
00599 
00600     byte data[page_data_size]; 
00601     page_trailer<T> trailer;   
00602 } FAIRPORT_MS_STRUCT;
00604 static_assert(sizeof(page<ulong>) == page_size, "page<ulong> incorrect size");
00605 static_assert(sizeof(page<ulonglong>) == page_size, "page<ulonglong> incorrect size");
00607 
00611 const size_t bytes_per_slot = 64;
00612 
00616 const size_t first_amap_page_location = 0x4400;
00617 
00629 template<typename T>
00630 struct amap_page : public page<T>
00631 {
00632 } FAIRPORT_MS_STRUCT;
00634 static_assert(sizeof(amap_page<ulong>) == page_size, "amap_page<ulong> incorrect size");
00635 static_assert(sizeof(amap_page<ulonglong>) == page_size, "amap_page<ulonglong> incorrect size");
00637 
00648 template<typename T>
00649 struct pmap_page : public page<T>
00650 {
00651 } FAIRPORT_MS_STRUCT;
00653 static_assert(sizeof(pmap_page<ulong>) == page_size, "pmap_page<ulong> incorrect size");
00654 static_assert(sizeof(pmap_page<ulonglong>) == page_size, "pmap_page<ulonglong> incorrect size");
00656 
00666 template<typename T>
00667 struct fmap_page : public page<T>
00668 {
00669 } FAIRPORT_MS_STRUCT;
00671 static_assert(sizeof(fmap_page<ulong>) == page_size, "fmap_page<ulong> incorrect size");
00672 static_assert(sizeof(fmap_page<ulonglong>) == page_size, "fmap_page<ulonglong> incorrect size");
00674 
00688 template<typename T>
00689 struct fpmap_page : public page<T>
00690 {
00691 } FAIRPORT_MS_STRUCT;
00693 static_assert(sizeof(fpmap_page<ulong>) == page_size, "fpmap_page<ulong> incorrect size");
00694 static_assert(sizeof(fpmap_page<ulonglong>) == page_size, "fpmap_page<ulonglong> incorrect size");
00696 
00700 const size_t dlist_page_location = 0x4200;
00701 
00711 template<typename T>
00712 struct dlist_page
00713 {
00714     static const size_t extra_space = page<T>::page_data_size - 8;
00715     static const size_t max_entries = extra_space / sizeof(ulong); 
00716 
00717     byte flags;                       
00718     byte num_entries;                 
00719     union
00720     {
00721         ulong current_page;           
00722         ulong backfill_location;      
00723     };
00724     union
00725     {
00726         ulong entries[max_entries];   
00727         byte _ignore[extra_space];
00728     };
00729     page_trailer<T> trailer;          
00730 } FAIRPORT_MS_STRUCT;
00732 static_assert(sizeof(dlist_page<ulong>) == page_size, "dlist_page<ulong> incorrect size");
00733 static_assert(sizeof(dlist_page<ulonglong>) == page_size, "dlist_page<ulonglong> incorrect size");
00735 
00739 const ulong dlist_page_num_mask = 0x0000FFFF;
00740 
00744 const ulong dlist_slots_shift = 20;
00745 
00750 inline ulong dlist_get_page_num(ulong entry) { return entry & dlist_page_num_mask; } 
00751 
00756 inline ulong dlist_get_slots(ulong entry) { return entry >> dlist_slots_shift; }
00757 
00764 template<typename T>
00765 struct bt_entry
00766 {
00767     typedef T bt_key;
00768 
00769     bt_key key;               
00770     block_reference<T> ref;   
00771 } FAIRPORT_MS_STRUCT;
00773 static_assert(sizeof(bt_entry<ulong>) == 12, "bt_entry<ulong> incorrect size");
00774 static_assert(sizeof(bt_entry<ulonglong>) == 24, "bt_entry<ulonglong> incorrect size");
00776 
00783 template<typename T>
00784 struct nbt_leaf_entry
00785 {
00786     typedef T nid_index;
00787     typedef T block_id_disk;
00788 
00789     nid_index nid;       
00790     block_id_disk data;  
00791     block_id_disk sub;   
00792     node_id parent_nid;  
00793 } FAIRPORT_MS_STRUCT;
00795 static_assert(sizeof(nbt_leaf_entry<ulong>) == 16, "nbt_leaf_entry<ulong> incorrect size");
00796 static_assert(sizeof(nbt_leaf_entry<ulonglong>) == 32, "nbt_leaf_entry<ulonglong> incorrect size");
00798 
00805 template<typename T>
00806 struct bbt_leaf_entry
00807 {
00808     block_reference<T> ref; 
00809     ushort size;            
00810     ushort ref_count;       
00811 } FAIRPORT_MS_STRUCT;
00813 static_assert(sizeof(bbt_leaf_entry<ulong>) == 12, "bbt_leaf_entry<ulong> incorrect size");
00814 static_assert(sizeof(bbt_leaf_entry<ulonglong>) == 24, "bbt_leaf_entry<ulonglong> incorrect size");
00816 
00827 template<typename T, typename EntryType>
00828 struct bt_page
00829 {
00830     static const size_t extra_space = page<T>::page_data_size - sizeof(T);
00831     static const size_t max_entries = extra_space / sizeof(EntryType); 
00832     union
00833     {
00834         EntryType entries[max_entries];
00835         byte _ignore[extra_space];
00836     };
00837 
00838     byte num_entries;          
00839     byte num_entries_max;      
00840     byte entry_size;           
00841     byte level;                
00842 
00843     page_trailer<T> trailer;   
00844 } FAIRPORT_MS_STRUCT;
00846 namespace detail {
00847     // We can't pass types containing "," to offsetof, because it's a
00848     // preprocessor macro, and it doesn't really understand how to parse an
00849     // argument list.  So we declare some aliases in a "detail" namespace
00850     // where they won't pollute the header.
00851     typedef bt_page<ulong, bt_entry<ulong> > bt_page_ulong;
00852     typedef bt_page<ulonglong, bt_entry<ulonglong> > bt_page_ulonglong;
00853 }
00854 static_assert(offsetof(detail::bt_page_ulong, num_entries) == 496, "bt_page<ulong, bt_entry<ulong> > num_entries at incorrect offset");
00855 static_assert(offsetof(detail::bt_page_ulonglong, num_entries) == 488, "bt_page<ulonglong, bt_entry<ulonglong> > num_entries at incorrect offset");
00856 static_assert(offsetof(detail::bt_page_ulong, trailer) == 500, "bt_page<ulong, bt_entry<ulong> > trailer at incorrect offset");
00857 static_assert(offsetof(detail::bt_page_ulonglong, trailer) == 496, "bt_page<ulonglong, bt_entry<ulonglong> > trailer at incorrect offset");
00859 
00866 template<typename T>
00867 struct nbt_nonleaf_page : public bt_page<T, bt_entry<T> >
00868 {
00869 } FAIRPORT_MS_STRUCT;
00871 static_assert(sizeof(nbt_nonleaf_page<ulong>) == page_size, "nbt_nonleaf_page<ulong> incorrect size");
00872 static_assert(sizeof(nbt_nonleaf_page<ulonglong>) == page_size, "nbt_nonleaf_page<ulonglong> incorrect size");
00874 
00882 template<typename T>
00883 struct bbt_nonleaf_page : public bt_page<T, bt_entry<T> >
00884 {
00885 } FAIRPORT_MS_STRUCT;
00887 static_assert(sizeof(bbt_nonleaf_page<ulong>) == page_size, "bbt_nonleaf_page<ulong> incorrect size");
00888 static_assert(sizeof(bbt_nonleaf_page<ulonglong>) == page_size, "bbt_nonleaf_page<ulonglong> incorrect size");
00890 
00898 template<typename T>
00899 struct nbt_leaf_page : public bt_page<T, nbt_leaf_entry<T> >
00900 {
00901 } FAIRPORT_MS_STRUCT;
00903 static_assert(sizeof(nbt_leaf_page<ulong>) == page_size, "nbt_leaf_page<ulong> incorrect size");
00904 static_assert(sizeof(nbt_leaf_page<ulonglong>) == page_size, "nbt_leaf_page<ulonglong> incorrect size");
00906 
00914 template<typename T>
00915 struct bbt_leaf_page : public bt_page<T, bbt_leaf_entry<T> >
00916 {
00917 } FAIRPORT_MS_STRUCT;
00919 static_assert(sizeof(bbt_leaf_page<ulong>) == page_size, "bbt_leaf_page<ulong> incorrect size");
00920 static_assert(sizeof(bbt_leaf_page<ulonglong>) == page_size, "bbt_leaf_page<ulonglong> incorrect size");
00922 
00923 //
00924 // block structures
00925 //
00926 
00929 
00933 const size_t max_block_disk_size = 8 * 1024;
00934 
00938 enum block_types
00939 {
00940     block_type_external = 0x00, 
00941     block_type_extended = 0x01, 
00942     block_type_sub = 0x02       
00943 };
00944 
00953 template<typename T>
00954 size_t align_disk(size_t size);
00955 
00963 size_t align_slot(size_t size);
00964 
00968 const uint block_id_attached_bit = 0x1;
00969 
00973 const uint block_id_internal_bit = 0x2;
00974 
00978 const uint block_id_increment = 0x4;
00979 
00986 template<typename T>
00987 bool bid_is_external(T bid) { return ((bid & block_id_internal_bit) == 0); }
00988 
00995 template<typename T>
00996 bool bid_is_internal(T bid) { return !bid_is_external(bid); }
00997 
00999 template<typename T>
01000 struct block_trailer
01001 {
01002 } FAIRPORT_MS_STRUCT;
01004 
01014 template<>
01015 struct block_trailer<ulonglong>
01016 {
01017     typedef ulonglong block_id_disk;
01018 
01019     ushort cb;           
01020     ushort signature;    
01021     ulong crc;           
01022     block_id_disk bid;   
01023 } FAIRPORT_MS_STRUCT;
01025 static_assert(sizeof(block_trailer<ulonglong>) == 16, "block_trailer<ulonglong> incorrect size");
01027 
01035 template<>
01036 struct block_trailer<ulong>
01037 {
01038     typedef ulong block_id_disk;
01039 
01040     ushort cb;
01041     ushort signature;
01042     block_id_disk bid;
01043     ulong crc;
01044 } FAIRPORT_MS_STRUCT;
01046 static_assert(sizeof(block_trailer<ulong>) == 12, "block_trailer<ulong> incorrect size");
01048 
01057 template<typename T>
01058 struct external_block
01059 {
01060     static const size_t max_size = max_block_disk_size - sizeof(block_trailer<T>);
01061     byte data[1];   
01062 } FAIRPORT_MS_STRUCT;
01063 
01065 template<typename T>
01066 struct extended_block
01067 {
01068 } FAIRPORT_MS_STRUCT;
01070 
01082 template<>
01083 struct extended_block<ulonglong>
01084 {
01085     typedef ulonglong block_id_disk;
01086 
01087     static const size_t max_count = (external_block<ulonglong>::max_size - 8) / sizeof(extended_block<ulonglong>::block_id_disk);
01088     static const size_t max_size = external_block<ulonglong>::max_size * extended_block<ulonglong>::max_count;
01089 
01090     byte block_type;       
01091     byte level;            
01092     ushort count;          
01093     ulong total_size;      
01094     block_id_disk bid[1];  
01095 } FAIRPORT_MS_STRUCT;
01096 
01104 template<>
01105 struct extended_block<ulong>
01106 {
01107     typedef ulong block_id_disk;
01108 
01109     static const size_t max_count = ((4096L) - sizeof(block_trailer<ulong>) - 8) / sizeof(extended_block<ulong>::block_id_disk);
01110     static const size_t max_size = external_block<ulong>::max_size * extended_block<ulong>::max_count;
01111 
01112     byte block_type;
01113     byte level;
01114     ushort count;
01115     ulong total_size;
01116     block_id_disk bid[1];
01117 } FAIRPORT_MS_STRUCT;
01118 
01126 template<typename T>
01127 struct sub_leaf_entry
01128 {
01129     typedef T block_id_disk;
01130 
01131     node_id nid;        
01132     block_id_disk data; 
01133     block_id_disk sub;  
01134 } FAIRPORT_MS_STRUCT;
01136 static_assert(sizeof(sub_leaf_entry<ulong>) == 12, "sub_leaf_entry<ulong> incorrect size");
01137 static_assert(sizeof(sub_leaf_entry<ulonglong>) == 24, "sub_leaf_entry<ulonglong> incorrect size");
01139 
01147 template<typename T>
01148 struct sub_nonleaf_entry
01149 {
01150     typedef T block_id_disk;
01151 
01152     node_id nid_key;             
01153     block_id_disk sub_block_bid; 
01154 } FAIRPORT_MS_STRUCT;
01156 static_assert(sizeof(sub_nonleaf_entry<ulong>) == 8, "sub_nonleaf_entry<ulong> incorrect size");
01157 static_assert(sizeof(sub_nonleaf_entry<ulonglong>) == 16, "sub_nonleaf_entry<ulonglong> incorrect size");
01159 
01169 template<typename T, typename EntryType>
01170 struct sub_block
01171 {
01172     byte block_type;    
01173     byte level;         
01174     ushort count;       
01175     EntryType entry[1]; 
01176 } FAIRPORT_MS_STRUCT;
01177 
01185 template<typename T>
01186 struct sub_nonleaf_block : public sub_block<T, sub_nonleaf_entry<T> >
01187 {
01188 } FAIRPORT_MS_STRUCT;
01189 
01197 template<typename T>
01198 struct sub_leaf_block : public sub_block<T, sub_leaf_entry<T> >
01199 {
01200 } FAIRPORT_MS_STRUCT;
01201 
01202 //
01203 // heap structures
01204 //
01205 
01208 
01212 const byte heap_signature = 0xEC;
01213 
01216 const uint heap_max_alloc_size = 3580;
01217 
01220 const uint heap_max_alloc_size_wver_14 = 3068;
01221 
01225 enum heap_client_signature
01226 {
01227    heap_sig_gmp = 0x6C,  //< Internal
01228    heap_sig_tc = 0x7C,   //< Table context
01229    heap_sig_smp = 0x8C,  //< Internal
01230    heap_sig_hmp = 0x9C,  //< Internal
01231    heap_sig_ch = 0xA5,   //< \deprecated Internal
01232    heap_sig_chtc = 0xAC, //< \deprecated Internal
01233    heap_sig_bth = 0xB5,  //< BTree on Heap
01234    heap_sig_pc = 0xBC    //< Property Context
01235 };
01236 
01239 enum heap_fill_level
01240 {
01241     heap_fill_empty,    //< >= 3584 bytes free
01242     heap_fill_1,        //< 2560 - 3583 bytes free
01243     heap_fill_2,        //< 2048 - 2559 bytes free
01244     heap_fill_3,        //< 1792 - 2047 bytes free
01245     heap_fill_4,        //< 1536 - 1791 bytes free
01246     heap_fill_5,        //< 1280 - 1535 bytes free
01247     heap_fill_6,        //< 1024 - 1279 bytes free
01248     heap_fill_7,        //< 768 - 1023 bytes free
01249     heap_fill_8,        //< 512 - 767 bytes free
01250     heap_fill_9,        //< 256 - 511 bytes free
01251     heap_fill_10,       //< 128 - 255 bytes free
01252     heap_fill_11,       //< 64 - 127 bytes free
01253     heap_fill_12,       //< 32 - 63 bytes free
01254     heap_fill_13,       //< 16 - 31 bytes free
01255     heap_fill_14,       //< 8 - 15 bytes free
01256     heap_fill_full      //< < 8 bytes free
01257 };
01258 
01262 struct heap_first_header
01263 {
01264     static const uint fill_level_size = 4; 
01265 
01266     ushort page_map_offset;  
01267     byte signature;          
01268     byte client_signature;   
01269     heap_id root_id;         
01270     byte page_fill_levels[fill_level_size]; 
01271 } FAIRPORT_MS_STRUCT;
01272 
01276 struct heap_page_header
01277 {
01278     ushort page_map_offset; 
01279 } FAIRPORT_MS_STRUCT;
01280 
01284 struct heap_page_fill_header
01285 {
01286     static const uint fill_level_size = 64; 
01287 
01288     ushort page_map_offset; 
01289     byte page_fill_levels[fill_level_size]; 
01290 } FAIRPORT_MS_STRUCT;
01291 
01305 struct heap_page_map
01306 {
01307     ushort num_allocs; 
01308     ushort num_frees;  
01309     ushort allocs[1];  
01310 } FAIRPORT_MS_STRUCT;
01311 
01312 //
01313 // bth structures
01314 //
01315 
01318 
01323 struct bth_header
01324 {
01325     byte bth_signature; 
01326     byte key_size;      
01327     byte entry_size;    
01328     byte num_levels;    
01329     heap_id root;       
01330 } FAIRPORT_MS_STRUCT;
01331 
01340 #pragma pack(2)
01341 template<typename K>
01342 struct bth_nonleaf_entry
01343 {
01344     K key;                       
01345     heap_id page FAIRPORT_PACK_2;  
01346 };
01347 #pragma pack()
01348 
01349 static_assert(sizeof(bth_nonleaf_entry<ushort>) == 6, "bth_nonleaf_entry<ushort> incorrect size");
01350 static_assert(offsetof(bth_nonleaf_entry<ushort>, key) == 0, "bth_nonleaf_entry<ushort> key at incorrect offset");
01351 static_assert(offsetof(bth_nonleaf_entry<ushort>, page) == 2, "bth_nonleaf_entry<ushort> page at incorrect offset");
01353 
01361 template<typename K, typename V>
01362 struct bth_leaf_entry
01363 {
01364     K key;   
01365     V value; 
01366 } FAIRPORT_MS_STRUCT;
01367 
01380 template<typename EntryType>
01381 struct bth_node
01382 {
01383     EntryType entries[1]; 
01384 } FAIRPORT_MS_STRUCT;
01385 
01393 template<typename K, typename V>
01394 struct bth_leaf_node : bth_node<bth_leaf_entry<K,V> >
01395 {
01396 } FAIRPORT_MS_STRUCT;
01397 
01405 template<typename K>
01406 struct bth_nonleaf_node : bth_node<bth_nonleaf_entry<K> >
01407 {
01408 } FAIRPORT_MS_STRUCT;
01409 
01410 //
01411 // pc structures
01412 //
01413 
01416 
01424 #pragma pack(2)
01425 struct prop_entry
01426 {
01427     ushort type;     //$< Property type
01428     heapnode_id id;  //$< Heapnode id for variable length properties, or the value directly for fixed size property types
01429 };
01430 #pragma pack()
01431 
01432 static_assert(sizeof(bth_leaf_entry<ushort, prop_entry>) == 8, "bth_leaf_entry<ushort, prop_entry> incorrect size");
01434 
01440 struct sub_object
01441 {
01442     node_id nid; //$< The subnode id containing the data for the object
01443     ulong size;  //$< The size of the object
01444 } FAIRPORT_MS_STRUCT;
01445 
01453 struct mv_toc
01454 {
01455     ulong count;      //$< Number of entries in the TOC
01456     ulong offsets[1]; //$< Array of offsets for the start of each entry
01457 } FAIRPORT_MS_STRUCT;
01458 
01459 //
01460 // tc structures
01461 //
01462 
01465 
01469 enum tc_offsets
01470 {
01471     tc_offsets_four,    //$< Offset of the end of the four and eight byte columns
01472     tc_offsets_two,     //$< Offset of the end of the two byte columns
01473     tc_offsets_one,     //$< Offset of the end of the one byte columns
01474     tc_offsets_bitmap,  //$< Offset of the end of the existance bitmap
01475     tc_offsets_max      //$< Number of entries in the offset array
01476 };
01477 
01481 #pragma pack(2)
01482 struct column_description
01483 {
01484     ushort type;        //$< Column property type
01485     prop_id id;         //$< Column property id
01486     ushort offset;      //$< Offset into the row
01487     byte size;          //$< Width of the column
01488     byte bit_offset;    //$< Bit offset into the existance bitmap
01489 };
01490 
01497 struct gust_column_description
01498 {
01499     ushort type;
01500     prop_id id;
01501     ushort offset;
01502     byte size;
01503     byte unused1;
01504     ushort bit_offset;
01505     ushort unused2;
01506     node_id data_subnode;
01507 };
01508 
01512 struct tc_header
01513 {
01514     byte signature;             //$< TC signature, \ref heap_sig_tc
01515     byte num_columns;           //$< Number of columns in this table
01516     ushort size_offsets[tc_offsets_max]; // Row offset array, see \ref tc_offsets
01517     heap_id row_btree_id;       //$< The bth_header allocation for the row mapping btree
01518     heapnode_id row_matrix_id;  //$< The heapnode_id allocation for the row matrix
01519     byte unused[4];
01520     column_description columns[1]; //$< Column description array, of length num_columns
01521 };
01522 
01526 struct gust_header
01527 {
01528     byte signature;
01529     byte unused1;
01530     ushort size_offsets[tc_offsets_max];
01531     heap_id row_btree_id;
01532     heapnode_id row_matrix_id;
01533     byte unused2[4];
01534     ushort num_columns;
01535     node_id column_subnode;
01536     ulong unused3;
01537     ulong unused4;
01538 };
01539 #pragma pack()
01540 
01541 //
01542 // nameid structures
01543 //
01544 
01547 
01554 struct nameid
01555 {
01556     union
01557     {
01558         ulong id;               
01559         ulong string_offset;    
01560     };
01561     ulong index;                
01562 } FAIRPORT_MS_STRUCT;
01563 
01572 struct nameid_hash_entry
01573 {
01574     ulong hash_base;            
01575     ulong index;                
01576 } FAIRPORT_MS_STRUCT;
01578 static_assert(sizeof(nameid) == 8, "nameid incorrect size");
01579 static_assert(sizeof(nameid_hash_entry) == 8, "nameid incorrect size");
01581 
01587 inline ushort nameid_get_prop_index(const nameid& n) { return (ushort)(n.index >> 16); }
01588 
01594 inline ushort nameid_get_guid_index(const nameid& n) { return (ushort)((ushort)n.index >> 1); }
01595 
01601 inline bool nameid_is_string(const nameid& n) { return n.index & 0x1; }
01602 
01608 inline ushort nameid_get_prop_index(const nameid_hash_entry& n) { return (ushort)(n.index >> 16); }
01609 
01615 inline ushort nameid_get_guid_index(const nameid_hash_entry& n) { return (ushort)((ushort)n.index >> 1); }
01616 
01622 inline bool nameid_is_string(const nameid_hash_entry& n) { return n.index & 0x1; }
01623 
01624 } // end disk namespace
01625 } // end fairport namespace
01626 
01627 
01628 template<typename T>
01629 inline fairport::ushort fairport::disk::compute_signature(T id, T address)
01630 {
01631     T value = address ^ id;
01632 
01633     return (ushort(ushort(value >> 16) ^ ushort(value)));
01634 }
01635 
01636 inline fairport::ulong fairport::disk::compute_crc(const void * pdata, ulong cb)
01637 {
01638     ulong crc = 0;
01639     const byte * pb = reinterpret_cast<const byte*>(pdata);
01640 
01641     while(cb-- > 0)
01642         crc = crc_table[(int)(byte)crc ^ *pb++] ^ (crc >> 8);
01643 
01644     return crc;
01645 }
01646 
01647 inline void fairport::disk::permute(void * pdata, ulong cb, bool encrypt)
01648 {
01649     byte * pb = reinterpret_cast<byte*>(pdata);
01650     const byte * ptable = encrypt ? table1 : table3;
01651     byte b;
01652 
01653     while(cb-- > 0)
01654     {
01655         b = *pb;
01656         *pb++ = ptable[b];
01657     }
01658 }
01659 
01660 inline void fairport::disk::cyclic(void * pdata, ulong cb, ulong key)
01661 {
01662     byte * pb = reinterpret_cast<byte*>(pdata);
01663     byte b;
01664     ushort w;
01665 
01666     w = (ushort)(key ^ (key >> 16));
01667 
01668     while (cb-- > 0)
01669     {
01670         b = *pb;
01671         b = (byte)(b + (byte)w);
01672         b = table1[b];
01673         b = (byte)(b + (byte)(w >> 8));
01674         b = table2[b];
01675         b = (byte)(b - (byte)(w >> 8));
01676         b = table3[b];
01677         b = (byte)(b - (byte)w);
01678         *pb++ = b;
01679 
01680         w = (ushort)(w + 1);
01681     }
01682 }
01683 
01684 template<typename T>
01685 inline size_t fairport::disk::align_disk(size_t size)
01686 {
01687     return align_slot(size + sizeof(block_trailer<T>));
01688 }
01689 
01690 inline size_t fairport::disk::align_slot(size_t size)
01691 {
01692     return ((size + bytes_per_slot - 1) & ~(bytes_per_slot - 1));
01693 }
01694 
01695 #endif