interval_tree.c
来自「lustre 1.6.5 source code」· C语言 代码 · 共 753 行 · 第 1/2 页
C
753 行
/* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*- * vim:expandtab:shiftwidth=8:tabstop=8: * * Interval tree library used by ldlm extent lock code * * Copyright (c) 2007 Cluster File Systems, Inc. * Author: Huang Wei <huangwei@clusterfs.com> * Author: Jay Xiong <jinshan.xiong@sun.com> * * This file is part of the Lustre file system, http://www.lustre.org * Lustre is a trademark of Cluster File Systems, Inc. * * You may have signed or agreed to another license before downloading * this software. If so, you are bound by the terms and conditions * of that agreement, and the following does not apply to you. See the * LICENSE file included with this distribution for more information. * * If you did not agree to a different license, then this copy of Lustre * is open source software; you can redistribute it and/or modify it * under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * In either case, Lustre is distributed in the hope that it will be * useful, but WITHOUT ANY WARRANTY; without even the implied warranty * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * license text for more details. */#ifdef __KERNEL__# include <lustre_dlm.h>#else# include <liblustre.h># include <libcfs/kp30.h>#endif#include <obd_support.h>#include <interval_tree.h>enum { INTERVAL_RED = 0, INTERVAL_BLACK = 1};static inline int node_is_left_child(struct interval_node *node){ LASSERT(node->in_parent != NULL); return node == node->in_parent->in_left;}static inline int node_is_right_child(struct interval_node *node){ LASSERT(node->in_parent != NULL); return node == node->in_parent->in_right;}static inline int node_is_red(struct interval_node *node){ return node->in_color == INTERVAL_RED;}static inline int node_is_black(struct interval_node *node){ return node->in_color == INTERVAL_BLACK;}static inline int extent_compare(struct interval_node_extent *e1, struct interval_node_extent *e2){ int rc; if (e1->start == e2->start) { if (e1->end < e2->end) rc = -1; else if (e1->end > e2->end) rc = 1; else rc = 0; } else { if (e1->start < e2->start) rc = -1; else rc = 1; } return rc;}static inline int extent_equal(struct interval_node_extent *e1, struct interval_node_extent *e2){ return (e1->start == e2->start) && (e1->end == e2->end);}static inline int extent_overlapped(struct interval_node_extent *e1, struct interval_node_extent *e2){ return (e1->start <= e2->end) && (e2->start <= e1->end);}static inline int node_compare(struct interval_node *n1, struct interval_node *n2){ return extent_compare(&n1->in_extent, &n2->in_extent);}static inline int node_equal(struct interval_node *n1, struct interval_node *n2){ return extent_equal(&n1->in_extent, &n2->in_extent);}static inline __u64 max_u64(__u64 x, __u64 y){ return x > y ? x : y;}static inline __u64 min_u64(__u64 x, __u64 y){ return x < y ? x : y;}#define interval_for_each(node, root) \for (node = interval_first(root); node != NULL; \ node = interval_next(node))#define interval_for_each_reverse(node, root) \for (node = interval_last(root); node != NULL; \ node = interval_prev(node))static struct interval_node *interval_first(struct interval_node *node){ ENTRY; if (!node) RETURN(NULL); while (node->in_left) node = node->in_left; RETURN(node);}static struct interval_node *interval_last(struct interval_node *node){ ENTRY; if (!node) RETURN(NULL); while (node->in_right) node = node->in_right; RETURN(node);}static struct interval_node *interval_next(struct interval_node *node){ ENTRY; if (!node) RETURN(NULL); if (node->in_right) RETURN(interval_first(node->in_right)); while (node->in_parent && node_is_right_child(node)) node = node->in_parent; RETURN(node->in_parent);}static struct interval_node *interval_prev(struct interval_node *node){ ENTRY; if (!node) RETURN(NULL); if (node->in_left) RETURN(interval_last(node->in_left)); while (node->in_parent && node_is_left_child(node)) node = node->in_parent; RETURN(node->in_parent);}enum interval_iter interval_iterate(struct interval_node *root, interval_callback_t func, void *data){ struct interval_node *node; enum interval_iter rc = INTERVAL_ITER_CONT; ENTRY; interval_for_each(node, root) { rc = func(node, data); if (rc == INTERVAL_ITER_STOP) break; } RETURN(rc);}EXPORT_SYMBOL(interval_iterate);enum interval_iter interval_iterate_reverse(struct interval_node *root, interval_callback_t func, void *data){ struct interval_node *node; enum interval_iter rc = INTERVAL_ITER_CONT; ENTRY; interval_for_each_reverse(node, root) { rc = func(node, data); if (rc == INTERVAL_ITER_STOP) break; } RETURN(rc);}EXPORT_SYMBOL(interval_iterate_reverse);/* try to find a node with same interval in the tree, * if found, return the pointer to the node, otherwise return NULL*/struct interval_node *interval_find(struct interval_node *root, struct interval_node_extent *ex){ struct interval_node *walk = root; int rc; ENTRY; while (walk) { rc = extent_compare(ex, &walk->in_extent); if (rc == 0) break; else if (rc < 0) walk = walk->in_left; else walk = walk->in_right; } RETURN(walk);}EXPORT_SYMBOL(interval_find);static void __rotate_change_maxhigh(struct interval_node *node, struct interval_node *rotate){ __u64 left_max, right_max; rotate->in_max_high = node->in_max_high; left_max = node->in_left ? node->in_left->in_max_high : 0; right_max = node->in_right ? node->in_right->in_max_high : 0; node->in_max_high = max_u64(interval_high(node), max_u64(left_max,right_max));}/* The left rotation "pivots" around the link from node to node->right, and * - node will be linked to node->right's left child, and * - node->right's left child will be linked to node's right child. */static void __rotate_left(struct interval_node *node, struct interval_node **root){ struct interval_node *right = node->in_right; struct interval_node *parent = node->in_parent; node->in_right = right->in_left; if (node->in_right) right->in_left->in_parent = node; right->in_left = node; right->in_parent = parent; if (parent) { if (node_is_left_child(node)) parent->in_left = right; else parent->in_right = right; } else { *root = right; } node->in_parent = right; /* update max_high for node and right */ __rotate_change_maxhigh(node, right);}/* The right rotation "pivots" around the link from node to node->left, and * - node will be linked to node->left's right child, and * - node->left's right child will be linked to node's left child. */static void __rotate_right(struct interval_node *node, struct interval_node **root){ struct interval_node *left = node->in_left; struct interval_node *parent = node->in_parent; node->in_left = left->in_right; if (node->in_left) left->in_right->in_parent = node; left->in_right = node; left->in_parent = parent; if (parent) { if (node_is_right_child(node)) parent->in_right = left; else parent->in_left = left; } else { *root = left; } node->in_parent = left; /* update max_high for node and left */ __rotate_change_maxhigh(node, left);}#define interval_swap(a, b) do { \ struct interval_node *c = a; a = b; b = c; \} while (0)/* * Operations INSERT and DELETE, when run on a tree with n keys, * take O(logN) time.Because they modify the tree, the result * may violate the red-black properties.To restore these properties, * we must change the colors of some of the nodes in the tree * and also change the pointer structure. */static void interval_insert_color(struct interval_node *node, struct interval_node **root){ struct interval_node *parent, *gparent; ENTRY; while ((parent = node->in_parent) && node_is_red(parent)) { gparent = parent->in_parent; /* Parent is RED, so gparent must not be NULL */ if (node_is_left_child(parent)) { struct interval_node *uncle; uncle = gparent->in_right; if (uncle && node_is_red(uncle)) { uncle->in_color = INTERVAL_BLACK; parent->in_color = INTERVAL_BLACK; gparent->in_color = INTERVAL_RED; node = gparent; continue; } if (parent->in_right == node) { __rotate_left(parent, root); interval_swap(node, parent); } parent->in_color = INTERVAL_BLACK; gparent->in_color = INTERVAL_RED; __rotate_right(gparent, root); } else { struct interval_node *uncle; uncle = gparent->in_left; if (uncle && node_is_red(uncle)) { uncle->in_color = INTERVAL_BLACK; parent->in_color = INTERVAL_BLACK; gparent->in_color = INTERVAL_RED; node = gparent; continue; } if (node_is_left_child(node)) { __rotate_right(parent, root); interval_swap(node, parent); } parent->in_color = INTERVAL_BLACK; gparent->in_color = INTERVAL_RED; __rotate_left(gparent, root); } } (*root)->in_color = INTERVAL_BLACK; EXIT;}struct interval_node *interval_insert(struct interval_node *node, struct interval_node **root) { struct interval_node **p, *parent = NULL; ENTRY;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?