+ mgr = GlobalAlloc (GMEM_FIXED|GMEM_ZEROINIT, sizeof(BtMgr));
+ attr = FILE_ATTRIBUTE_NORMAL;
+ mgr->idx = CreateFile(name, GENERIC_READ| GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_ALWAYS, attr, NULL);
+
+ if( mgr->idx == INVALID_HANDLE_VALUE )
+ return GlobalFree(mgr), NULL;
+
+ // normalize cacheblk to multiple of sysinfo->dwAllocationGranularity
+ GetSystemInfo(sysinfo);
+ cacheblk = sysinfo->dwAllocationGranularity;
+#endif
+
+#ifdef unix
+ latchmgr = malloc (BT_maxpage);
+ *amt = 0;
+
+ // read minimum page size to get root info
+
+ if( size = lseek (mgr->idx, 0L, 2) ) {
+ if( pread(mgr->idx, latchmgr, BT_minpage, 0) == BT_minpage )
+ bits = latchmgr->alloc->bits;
+ else
+ return free(mgr), free(latchmgr), NULL;
+ } else if( mode == BT_ro )
+ return free(latchmgr), bt_mgrclose (mgr), NULL;
+#else
+ latchmgr = VirtualAlloc(NULL, BT_maxpage, MEM_COMMIT, PAGE_READWRITE);
+ size = GetFileSize(mgr->idx, amt);
+
+ if( size || *amt ) {
+ if( !ReadFile(mgr->idx, (char *)latchmgr, BT_minpage, amt, NULL) )
+ return bt_mgrclose (mgr), NULL;
+ bits = latchmgr->alloc->bits;
+ } else if( mode == BT_ro )
+ return bt_mgrclose (mgr), NULL;
+#endif
+
+ mgr->page_size = 1 << bits;
+ mgr->page_bits = bits;
+
+ mgr->poolmax = poolmax;
+ mgr->mode = mode;
+
+ if( cacheblk < mgr->page_size )
+ cacheblk = mgr->page_size;
+
+ // mask for partial memmaps
+
+ mgr->poolmask = (cacheblk >> bits) - 1;
+
+ // see if requested size of pages per memmap is greater
+
+ if( (1 << segsize) > mgr->poolmask )
+ mgr->poolmask = (1 << segsize) - 1;
+
+ mgr->seg_bits = 0;
+
+ while( (1 << mgr->seg_bits) <= mgr->poolmask )
+ mgr->seg_bits++;
+
+ mgr->hashsize = hashsize;
+
+#ifdef unix
+ mgr->pool = calloc (poolmax, sizeof(BtPool));
+ mgr->hash = calloc (hashsize, sizeof(ushort));
+ mgr->latch = calloc (hashsize, sizeof(BtSpinLatch));
+#else
+ mgr->pool = GlobalAlloc (GMEM_FIXED|GMEM_ZEROINIT, poolmax * sizeof(BtPool));
+ mgr->hash = GlobalAlloc (GMEM_FIXED|GMEM_ZEROINIT, hashsize * sizeof(ushort));
+ mgr->latch = GlobalAlloc (GMEM_FIXED|GMEM_ZEROINIT, hashsize * sizeof(BtSpinLatch));
+#endif
+
+ if( size || *amt )
+ goto mgrlatch;
+
+ // initialize an empty b-tree with latch page, root page, page of leaves
+ // and page(s) of latches
+
+ memset (latchmgr, 0, 1 << bits);
+ nlatchpage = BT_latchtable / (mgr->page_size / sizeof(BtLatchSet)) + 1;
+ bt_putid(latchmgr->alloc->right, MIN_lvl+1+nlatchpage);
+ latchmgr->alloc->bits = mgr->page_bits;
+
+ latchmgr->nlatchpage = nlatchpage;
+ latchmgr->latchtotal = nlatchpage * (mgr->page_size / sizeof(BtLatchSet));
+
+ // initialize latch manager
+
+ latchhash = (mgr->page_size - sizeof(BtLatchMgr)) / sizeof(BtHashEntry);
+
+ // size of hash table = total number of latchsets
+
+ if( latchhash > latchmgr->latchtotal )
+ latchhash = latchmgr->latchtotal;
+
+ latchmgr->latchhash = latchhash;
+
+#ifdef unix
+ if( write (mgr->idx, latchmgr, mgr->page_size) < mgr->page_size )
+ return bt_mgrclose (mgr), NULL;
+#else
+ if( !WriteFile (mgr->idx, (char *)latchmgr, mgr->page_size, amt, NULL) )
+ return bt_mgrclose (mgr), NULL;
+
+ if( *amt < mgr->page_size )
+ return bt_mgrclose (mgr), NULL;
+#endif
+
+ memset (latchmgr, 0, 1 << bits);
+ latchmgr->alloc->bits = mgr->page_bits;
+
+ for( lvl=MIN_lvl; lvl--; ) {
+ slotptr(latchmgr->alloc, 1)->off = offsetof(struct BtPage_, fence);
+ bt_putid(slotptr(latchmgr->alloc, 1)->id, lvl ? MIN_lvl - lvl + 1 : 0); // next(lower) page number
+ latchmgr->alloc->fence[0] = 2;
+ latchmgr->alloc->fence[1] = 0xff;
+ latchmgr->alloc->fence[2] = 0xff;
+ latchmgr->alloc->min = mgr->page_size;
+ latchmgr->alloc->lvl = lvl;
+ latchmgr->alloc->cnt = 1;
+ latchmgr->alloc->act = 1;
+#ifdef unix
+ if( write (mgr->idx, latchmgr, mgr->page_size) < mgr->page_size )
+ return bt_mgrclose (mgr), NULL;
+#else
+ if( !WriteFile (mgr->idx, (char *)latchmgr, mgr->page_size, amt, NULL) )
+ return bt_mgrclose (mgr), NULL;
+
+ if( *amt < mgr->page_size )
+ return bt_mgrclose (mgr), NULL;
+#endif
+ }
+
+ // clear out latch manager locks
+ // and rest of pages to round out segment
+
+ memset(latchmgr, 0, mgr->page_size);
+ last = MIN_lvl + 1;
+
+ while( last <= ((MIN_lvl + 1 + nlatchpage) | mgr->poolmask) ) {
+#ifdef unix
+ pwrite(mgr->idx, latchmgr, mgr->page_size, last << mgr->page_bits);
+#else
+ SetFilePointer (mgr->idx, last << mgr->page_bits, NULL, FILE_BEGIN);
+ if( !WriteFile (mgr->idx, (char *)latchmgr, mgr->page_size, amt, NULL) )
+ return bt_mgrclose (mgr), NULL;
+ if( *amt < mgr->page_size )
+ return bt_mgrclose (mgr), NULL;