#include <osi.h>
#include "afsd.h"
+#ifdef USE_BPLUS
+#include "cm_btree.h"
+#endif
#include <rx\rx.h>
#include <rx\rx_null.h>
#include <WINNT/syscfg.h>
extern afs_int32 cryptall;
extern int cm_enableServerLocks;
extern int cm_deleteReadOnly;
+#ifdef USE_BPLUS
extern afs_int32 cm_BPlusTrees;
+#endif
extern afs_int32 cm_OfflineROIsValid;
extern const char **smb_ExecutableExtensions;
}
afsi_log("CM DeleteReadOnly is %u", cm_deleteReadOnly);
+#ifdef USE_BPLUS
dummyLen = sizeof(DWORD);
code = RegQueryValueEx(parmKey, "BPlusTrees", NULL, NULL,
(BYTE *) &dwValue, &dummyLen);
}
afsi_log("CM BPlusTrees is %u", cm_BPlusTrees);
+ if (cm_BPlusTrees && !cm_InitBPlusDir()) {
+ cm_BPlusTrees = 0;
+ afsi_log("CM BPlusTree initialization failure; disabled for this session");
+ }
+#else
+ afsi_log("CM BPlusTrees is not supported");
+#endif
+
if ((RegQueryValueEx( parmKey, "PrefetchExecutableExtensions", 0,
®Type, NULL, &dummyLen) == ERROR_SUCCESS) &&
(regType == REG_MULTI_SZ))
smb_InitIoctl();
cm_InitCallback();
-
+
code = cm_InitMappedMemory(virtualCache, cm_CachePath, stats, cm_chunkSize, cacheBlocks, blockSize);
afsi_log("cm_InitMappedMemory code %x", code);
if (code != 0) {
static void _xferentry(Nptr srcNode, int srcEntry, Nptr destNode, int destEntry);
static void _setentry(Nptr node, int entry, keyT key, Nptr downNode);
+/* access key and data values for B+tree methods */
+/* pass values to getSlot(), descend...() */
+static keyT getfunkey(Tree *B);
+static dataT getfundata(Tree *B);
+static void setfunkey(Tree *B, keyT v);
+static void setfundata(Tree *B, dataT v);
+
+
#ifdef DEBUG_BTREE
static int _isRoot(Tree *B, Nptr n)
{
/***********************************************************************\
| B+tree Initialization and Cleanup Routines |
\***********************************************************************/
+static DWORD TlsKeyIndex;
+static DWORD TlsDataIndex;
+
+long cm_InitBPlusDir(void)
+{
+ if ((TlsKeyIndex = TlsAlloc()) == TLS_OUT_OF_INDEXES)
+ return 0;
+
+ if ((TlsDataIndex = TlsAlloc()) == TLS_OUT_OF_INDEXES)
+ return 0;
+
+ return 1;
+}
/******************** Set up B+tree structure **********************/
Tree *initBtree(unsigned int poolsz, unsigned int fanout, KeyCmp keyCmp)
}
+/* access key and data values for B+tree methods */
+/* pass values to getSlot(), descend...() */
+static keyT getfunkey(Tree *B) {
+ keyT *tlsKey;
+
+ // Retrieve a data pointer for the current thread.
+ tlsKey = (keyT *) TlsGetValue(TlsKeyIndex);
+ if (tlsKey == NULL) {
+ if (GetLastError() != ERROR_SUCCESS)
+ osi_panic("TlsGetValue failed", __FILE__, __LINE__);
+ else
+ osi_panic("get before set", __FILE__, __LINE__);
+ }
+
+ return *tlsKey;
+}
+
+static dataT getfundata(Tree *B) {
+ dataT *tlsData;
+
+ // Retrieve a data pointer for the current thread.
+ tlsData = (dataT *) TlsGetValue(TlsDataIndex);
+ if (tlsData == NULL) {
+ if (GetLastError() != ERROR_SUCCESS)
+ osi_panic("TlsGetValue failed", __FILE__, __LINE__);
+ else
+ osi_panic("get before set", __FILE__, __LINE__);
+ }
+
+ return *tlsData;
+}
+
+static void setfunkey(Tree *B, keyT theKey) {
+ keyT *tlsKey;
+
+ tlsKey = (keyT *) TlsGetValue(TlsKeyIndex);
+ if (tlsKey == NULL) {
+ if (GetLastError() != ERROR_SUCCESS)
+ osi_panic("TlsGetValue failed", __FILE__, __LINE__);
+
+ tlsKey = malloc(sizeof(keyT));
+
+ if (!TlsSetValue(TlsKeyIndex, tlsKey))
+ osi_panic("TlsSetValue failed", __FILE__, __LINE__);
+ }
+
+ *tlsKey = theKey;
+}
+
+static void setfundata(Tree *B, dataT theData) {
+ dataT *tlsData;
+
+ tlsData = (dataT *) TlsGetValue(TlsDataIndex);
+ if (tlsData == NULL) {
+ if (GetLastError() != ERROR_SUCCESS)
+ osi_panic("TlsGetValue failed", __FILE__, __LINE__);
+
+ tlsData = malloc(sizeof(dataT));
+
+ if (!TlsSetValue(TlsDataIndex, tlsData))
+ osi_panic("TlsSetValue failed", __FILE__, __LINE__);
+ }
+
+ *tlsData = theData;
+}
+
+
/***********************************************************************\
| Find leaf node in which data nodes can be found |
\***********************************************************************/
mid = (lo + hi) >> 1;
switch (findslot = bestMatch(B, curr, mid)) {
case BTLOWER: /* check lower half of range */
- findslot = findKey(B, curr, lo, mid - 1); /* never in 2-3+trees */
+ if (mid > 1)
+ findslot = findKey(B, curr, lo, mid - 1); /* never in 2-3+trees */
break;
case BTUPPER: /* check upper half of range */
- findslot = findKey(B, curr, mid + 1, hi);
+ if (mid < getfanout(B))
+ findslot = findKey(B, curr, mid + 1, hi);
break;
case BTERROR:
sprintf(B->message, "FINDKEY: (lo %d hi %d) Bad key ordering on node %d (0x%p)\n",
unsigned int height; /* nodes traversed from root to leaves */
Nptr pool; /* list of all nodes */
Nptr empty; /* list of empty nodes */
- keyT theKey; /* the key value used in tree operations */
- dataT theData; /* data used for insertions/deletions */
union { /* nodes to change in insert and delete */
- Nptr split;
+ Nptr split; /* protected by scp->dirlock write-lock */
Nptr merge;
} branch;
KeyCmp keycmp; /* pointer to function comparing two keys */
long cm_BPlusDirFreeEnumeration(cm_direnum_t *enump);
long cm_BPlusDirEnumTest(cm_scache_t * dscp, afs_uint32 locked);
+long cm_InitBPlusDir(void);
+
+/************ Statistic Counter ***************************************/
+
extern afs_uint32 bplus_free_tree;
extern afs_uint32 bplus_dv_error;
extern afs_uint64 bplus_free_time;
+
/************ Accessor Macros *****************************************/
/* low level definition of Nptr value usage */
#define xferentry(j, q, v, z) _xferentry(j, q, v, z)
#define setentry(j, q, v, z) _setentry(j, q, v, z)
-
-/* access key and data values for B+tree methods */
-/* pass values to getSlot(), descend...() */
-#define getfunkey(B) ((B)->theKey)
-#define getfundata(B) ((B)->theData)
-#define setfunkey(B,v) ((B)->theKey = (v))
-#define setfundata(B,v) ((B)->theData = (v))
-
/* define number of B+tree nodes for free node pool */
#define getpoolsize(B) ((B)->poolsize)
#define setpoolsize(B,v) ((B)->poolsize = (v))