2 * Copyright (c) 2008, 2009, 2010, 2011 Kernel Drivers, LLC.
3 * Copyright (c) 2009, 2010, 2011 Your File System, Inc.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
10 * - Redistributions of source code must retain the above copyright notice,
11 * this list of conditions and the following disclaimer.
12 * - Redistributions in binary form must reproduce the above copyright
14 * this list of conditions and the following disclaimer in the
16 * and/or other materials provided with the distribution.
17 * - Neither the names of Kernel Drivers, LLC and Your File System, Inc.
18 * nor the names of their contributors may be used to endorse or promote
19 * products derived from this software without specific prior written
20 * permission from Kernel Drivers, LLC and Your File System, Inc.
22 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
23 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
24 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
25 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
26 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
27 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
28 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
29 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
30 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
31 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
32 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 // File: AFSBTreeSupport.cpp
39 #include "AFSCommon.h"
42 AFSLocateHashEntry( IN AFSBTreeEntry *TopNode,
43 IN ULONGLONG HashIndex,
44 IN OUT AFSBTreeEntry **TreeEntry)
47 NTSTATUS ntStatus = STATUS_SUCCESS;
48 AFSBTreeEntry *pEntry = NULL;
49 AFSBTreeEntry *pCurrentEntry = NULL;
51 pCurrentEntry = TopNode;
57 // If the rootnode passed is null then the directory is empty
63 try_return( ntStatus = STATUS_INVALID_PARAMETER);
67 // If the requestor is looking for the root node itself, then return it.
70 if( TopNode->HashIndex == HashIndex)
75 try_return( ntStatus);
79 // Loop through the nodes in the tree
82 while( pCurrentEntry != NULL)
86 // Greater values are to the right link.
89 if( HashIndex > pCurrentEntry->HashIndex)
93 // Go to the next RIGHT entry, if there is one
96 if( pCurrentEntry->rightLink != NULL)
99 pCurrentEntry = (AFSBTreeEntry *)pCurrentEntry->rightLink;
105 // Came to the end of the branch so bail
108 pCurrentEntry = NULL;
113 else if( HashIndex < pCurrentEntry->HashIndex)
117 // Go to the next LEFT entry, if one exists
120 if( pCurrentEntry->leftLink != NULL)
123 pCurrentEntry = (AFSBTreeEntry *)pCurrentEntry->leftLink;
129 // End of the branch ...
132 pCurrentEntry = NULL;
144 *TreeEntry = pCurrentEntry;
159 AFSInsertHashEntry( IN AFSBTreeEntry *TopNode,
160 IN AFSBTreeEntry *FileIDEntry)
163 NTSTATUS ntStatus = STATUS_SUCCESS;
164 AFSBTreeEntry *pCurrentEntry = NULL;
166 pCurrentEntry = TopNode;
172 // If we have no root node then we can;t start the search.
175 if( pCurrentEntry == NULL)
178 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
179 AFS_TRACE_LEVEL_WARNING,
180 "AFSInsertHashEntry Invalid root node\n");
182 try_return( ntStatus = STATUS_UNSUCCESSFUL);
186 // Locate the branch end to insert the node
189 while( pCurrentEntry != NULL)
193 // Greater vlued indices are to the right link
196 if( FileIDEntry->HashIndex > pCurrentEntry->HashIndex)
200 // Go to the next RIGHT entry, if it exists
203 if( pCurrentEntry->rightLink != NULL)
205 pCurrentEntry = (AFSBTreeEntry *)pCurrentEntry->rightLink;
211 // Located the end of the branch line so insert the node
214 pCurrentEntry->rightLink = (void *)FileIDEntry;
216 FileIDEntry->parentLink = (void *)pCurrentEntry;
221 else if( FileIDEntry->HashIndex < pCurrentEntry->HashIndex)
225 // Go to the next LEFT entry, if it exists
228 if( pCurrentEntry->leftLink != NULL)
230 pCurrentEntry = (AFSBTreeEntry *)pCurrentEntry->leftLink;
236 // Located the branch line end so insert the node here
239 pCurrentEntry->leftLink = (void *)FileIDEntry;
241 FileIDEntry->parentLink = (void *)pCurrentEntry;
249 AFSDbgLogMsg( AFS_SUBSYSTEM_FILE_PROCESSING,
250 AFS_TRACE_LEVEL_WARNING,
251 "AFSInsertHashEntry Attempt to re-insert a CRC %I64X\n",
252 FileIDEntry->HashIndex);
256 ntStatus = STATUS_UNSUCCESSFUL;
271 AFSRemoveHashEntry( IN AFSBTreeEntry **TopNode,
272 IN AFSBTreeEntry *FileIDEntry)
275 NTSTATUS ntStatus = STATUS_UNSUCCESSFUL;
276 AFSBTreeEntry *pRightNode = NULL;
277 AFSBTreeEntry *pLeftNode = NULL;
278 AFSBTreeEntry *pCurrentNode = NULL;
279 AFSBTreeEntry *pParentNode = NULL;
281 pRightNode = (AFSBTreeEntry *)FileIDEntry->rightLink;
282 pLeftNode = (AFSBTreeEntry *)FileIDEntry->leftLink;
283 pParentNode = (AFSBTreeEntry *)FileIDEntry->parentLink;
288 if( (pRightNode == NULL) && (pLeftNode == NULL))
291 if( pParentNode != NULL)
294 if( pParentNode->leftLink == FileIDEntry)
297 pParentNode->leftLink = NULL;
302 pParentNode->rightLink = NULL;
309 // Removing the top node
318 if( pRightNode != NULL)
321 if( pParentNode != NULL)
324 // Replace the parent node where this entry was.
325 if( pParentNode->rightLink == FileIDEntry)
328 pParentNode->rightLink = pRightNode;
333 pParentNode->leftLink = pRightNode;
339 *TopNode = pRightNode;
341 pRightNode->parentLink = NULL;
344 pRightNode->parentLink = pParentNode;
347 if( pLeftNode != NULL)
350 // To connect the left node, we must walk the chain of the
351 // right nodes left side until we reach the end.
352 // At the end attach the leftNode
353 if( pRightNode != NULL)
356 pCurrentNode = pRightNode;
358 while( pCurrentNode->leftLink != NULL)
361 pCurrentNode = (AFSBTreeEntry *)pCurrentNode->leftLink;
364 pCurrentNode->leftLink = pLeftNode;
366 pLeftNode->parentLink = pCurrentNode;
371 if( pParentNode != NULL)
374 // This is where we have a left node with no right node.
375 // So, attach the left node to the parent of
376 // the removed nodes branch
377 if( pParentNode->rightLink == FileIDEntry)
380 pParentNode->rightLink = pLeftNode;
385 pParentNode->leftLink = pLeftNode;
388 pLeftNode->parentLink = pParentNode;
393 *TopNode = pLeftNode;
395 pLeftNode->parentLink = NULL;
402 // Cleanup the just removed node
405 FileIDEntry->leftLink = NULL;
406 FileIDEntry->parentLink = NULL;
407 FileIDEntry->rightLink = NULL;
409 ntStatus = STATUS_SUCCESS;