Пример #1
0
void
ngx_http_lua_shdict_rbtree_insert_value(ngx_rbtree_node_t *temp,
    ngx_rbtree_node_t *node, ngx_rbtree_node_t *sentinel)
{
    ngx_rbtree_node_t          **p;
    ngx_http_lua_shdict_node_t   *sdn, *sdnt;

    for ( ;; ) {

        if (node->key < temp->key) {

            p = &temp->left;

        } else if (node->key > temp->key) {

            p = &temp->right;

        } else { /* node->key == temp->key */

            sdn = (ngx_http_lua_shdict_node_t *) &node->color;
            sdnt = (ngx_http_lua_shdict_node_t *) &temp->color;

            p = ngx_memn2cmp(sdn->data, sdnt->data, sdn->key_len,
                             sdnt->key_len) < 0 ? &temp->left : &temp->right;
        }

        if (*p == sentinel) {
            break;
        }

        temp = *p;
    }

    *p = node;
    node->parent = temp;
    node->left = sentinel;
    node->right = sentinel;
    ngx_rbt_red(node);
}
Пример #2
0
static void
ngx_http_limit_req_rbtree_insert_value(ngx_rbtree_node_t *temp,
    ngx_rbtree_node_t *node, ngx_rbtree_node_t *sentinel)
{
    ngx_rbtree_node_t          **p;
    ngx_http_limit_req_node_t   *lrn, *lrnt;

    for ( ;; ) {

        if (node->key < temp->key) {

            p = &temp->left;

        } else if (node->key > temp->key) {

            p = &temp->right;

        } else { /* node->key == temp->key */

            lrn = (ngx_http_limit_req_node_t *) &node->color;
            lrnt = (ngx_http_limit_req_node_t *) &temp->color;

            p = (ngx_memn2cmp(lrn->data, lrnt->data, lrn->len, lrnt->len) < 0)
                ? &temp->left : &temp->right;
        }

        if (*p == sentinel) {
            break;
        }

        temp = *p;
    }

    *p = node;
    node->parent = temp;
    node->left = sentinel;
    node->right = sentinel;
    ngx_rbt_red(node);
}
Пример #3
0
void
ngx_rbtree_insert_timer_value(ngx_rbtree_node_t *temp, ngx_rbtree_node_t *node,
    ngx_rbtree_node_t *sentinel)
{
    ngx_rbtree_node_t  **p;

    for ( ;; ) {

        /*
         * Timer values
         * 1) are spread in small range, usually several minutes,
         * 2) and overflow each 49 days, if milliseconds are stored in 32 bits.
         * The comparison takes into account that overflow.
         */

        /*  node->key < temp->key */
        //*  
        //*   要比较的两个timer值通常相差不大,大概几分钟而已
        //*   而0xFFFFFFFF小于50天的毫秒数,所以当值超过50天时就会溢出
        //*   所以0xFFFFFFF0和0x0000000F的timer值比较,应该认为0x0000000F值溢出
        //*    其本来值应该大于0xFFFFFFF0,所以才有此区别。
        //*/

        p = ((ngx_rbtree_key_int_t) (node->key - temp->key) < 0)
            ? &temp->left : &temp->right;

        if (*p == sentinel) {
            break;
        }

        temp = *p;
    }

    *p = node;
    node->parent = temp;
    node->left = sentinel;
    node->right = sentinel;
    ngx_rbt_red(node);
}
static void
ngx_open_file_cache_rbtree_insert_value(ngx_rbtree_node_t *temp,
    ngx_rbtree_node_t *node, ngx_rbtree_node_t *sentinel)
{
    ngx_rbtree_node_t       **p;
    ngx_cached_open_file_t    *file, *file_temp;

    for ( ;; ) {

        if (node->key < temp->key) {

            p = &temp->left;

        } else if (node->key > temp->key) {

            p = &temp->right;

        } else { /* node->key == temp->key */

            file = (ngx_cached_open_file_t *) node;
            file_temp = (ngx_cached_open_file_t *) temp;

            p = (ngx_strcmp(file->name, file_temp->name) < 0)
                    ? &temp->left : &temp->right;
        }

        if (*p == sentinel) {
            break;
        }

        temp = *p;
    }

    *p = node;
    node->parent = temp;
    node->left = sentinel;
    node->right = sentinel;
    ngx_rbt_red(node);
}
static void
ngx_http_req_status_rbtree_insert_value(ngx_rbtree_node_t *temp,
        ngx_rbtree_node_t *node, ngx_rbtree_node_t *sentinel)
{
    ngx_rbtree_node_t               **p;
    ngx_http_req_status_node_t      *cn, *cnt;

    for ( ;; ) {

        if (node->key < temp->key) {

            p = &temp->left;

        } else if (node->key > temp->key) {

            p = &temp->right;

        } else { /* node->key == temp->key */

            cn = (ngx_http_req_status_node_t *) node;
            cnt = (ngx_http_req_status_node_t *) temp;

            p = (ngx_memn2cmp(cn->key, cnt->key, cn->len, cnt->len) < 0)
                ? &temp->left : &temp->right;
        }

        if (*p == sentinel) {
            break;
        }

        temp = *p;
    }

    *p = node;
    node->parent = temp;
    node->left = sentinel;
    node->right = sentinel;
    ngx_rbt_red(node);
}
static void
ngx_http_vhost_traffic_status_rbtree_insert_value(ngx_rbtree_node_t *temp,
        ngx_rbtree_node_t *node, ngx_rbtree_node_t *sentinel)
{
    ngx_rbtree_node_t                       **p;
    ngx_http_vhost_traffic_status_node_t    *vtsn, *vtsnt;

    for ( ;; ) {

        if (node->key < temp->key) {

            p = &temp->left;

        } else if (node->key > temp->key) {

            p = &temp->right;

        } else { /* node->key == temp->key */

            vtsn = (ngx_http_vhost_traffic_status_node_t *) &node->color;
            vtsnt = (ngx_http_vhost_traffic_status_node_t *) &temp->color;

            p = (ngx_memn2cmp(vtsn->data, vtsnt->data, vtsn->len, vtsnt->len) < 0)
                ? &temp->left : &temp->right;
        }

        if (*p == sentinel) {
            break;
        }

        temp = *p;
    }

    *p = node;
    node->parent = temp;
    node->left = sentinel;
    node->right = sentinel;
    ngx_rbt_red(node);
}
Пример #7
0
void
ngx_http_variable_value_rbtree_insert(ngx_rbtree_node_t *temp,
    ngx_rbtree_node_t *node, ngx_rbtree_node_t *sentinel)
{
    ngx_rbtree_node_t               **p;
    ngx_http_variable_value_node_t   *vvn, *vvt;

    for ( ;; ) {

        vvn = (ngx_http_variable_value_node_t *) node;
        vvt = (ngx_http_variable_value_node_t *) temp;

        if (node->key != temp->key) {

            p = (node->key < temp->key) ? &temp->left : &temp->right;

        } else if (vvn->len != vvt->len) {

            p = (vvn->len < vvt->len) ? &temp->left : &temp->right;

        } else {
            p = (ngx_memcmp(vvn->value->data, vvt->value->data, vvn->len) < 0)
                 ? &temp->left : &temp->right;
        }

        if (*p == sentinel) {
            break;
        }

        temp = *p;
    }

    *p = node;
    node->parent = temp;
    node->left = sentinel;
    node->right = sentinel;
    ngx_rbt_red(node);
}
Пример #8
0
// Note: code taken from ngx_str_rbtree_insert_value, updated the node comparison
static void
ngx_buffer_cache_rbtree_insert_value(
	ngx_rbtree_node_t *temp, 
	ngx_rbtree_node_t *node, 
	ngx_rbtree_node_t *sentinel)
{
	ngx_buffer_cache_entry_t *n, *t;
	ngx_rbtree_node_t **p;

	for (;;) 
	{
		n = (ngx_buffer_cache_entry_t *)node;
		t = (ngx_buffer_cache_entry_t *)temp;

		if (node->key != temp->key) 
		{
			p = (node->key < temp->key) ? &temp->left : &temp->right;
		}
		else 
		{
			p = (ngx_memcmp(n->key, t->key, BUFFER_CACHE_KEY_SIZE) < 0)
				? &temp->left : &temp->right;
		}

		if (*p == sentinel) 
		{
			break;
		}

		temp = *p;
	}

	*p = node;
	node->parent = temp;
	node->left = sentinel;
	node->right = sentinel;
	ngx_rbt_red(node);
}
Пример #9
0
void
ngx_rbtree_insert_value(ngx_rbtree_node_t *temp, ngx_rbtree_node_t *node,
    ngx_rbtree_node_t *sentinel)
{
    ngx_rbtree_node_t  **p;

    for ( ;; ) {

        p = (node->key < temp->key) ? &temp->left : &temp->right;

        if (*p == sentinel) {
            break;
        }

        temp = *p;
    }

    *p = node;
    node->parent = temp;
    node->left = sentinel;
    node->right = sentinel;
    ngx_rbt_red(node);
}
Пример #10
0
void ngx_rbtree_insert(ngx_rbtree_t **root, ngx_rbtree_t *sentinel,
             ngx_rbtree_t *node)
{
  ngx_rbtree_t  *temp;

  /* a binary tree insert */

  if (*root == sentinel) {
    node->parent = NULL;
    node->left = sentinel;
    node->right = sentinel;
    ngx_rbt_black(node);
    *root = node;

    return;
  }

  temp = *root;

  for ( ;; ) {
    if (node->key < temp->key) {
      if (temp->left == sentinel) {
        temp->left = node;
        break;
      }

      temp = temp->left;
      continue;
    }

    if (temp->right == sentinel) {
      temp->right = node;
      break;
    }

    temp = temp->right;
    continue;
  }

  node->parent = temp;
  node->left = sentinel;
  node->right = sentinel;


  /* re-balance tree */

  ngx_rbt_red(node);

  while (node != *root && ngx_rbt_is_red(node->parent)) {

    if (node->parent == node->parent->parent->left) {
      temp = node->parent->parent->right;

      if (ngx_rbt_is_red(temp)) {
        ngx_rbt_black(node->parent);
        ngx_rbt_black(temp);
        ngx_rbt_red(node->parent->parent);
        node = node->parent->parent;

      } else {
        if (node == node->parent->right) {
          node = node->parent;
          ngx_rbtree_left_rotate(root, sentinel, node);
        }

        ngx_rbt_black(node->parent);
        ngx_rbt_red(node->parent->parent);
        ngx_rbtree_right_rotate(root, sentinel, node->parent->parent);
      }

    } else {
      temp = node->parent->parent->left;

      if (ngx_rbt_is_red(temp)) {
        ngx_rbt_black(node->parent);
        ngx_rbt_black(temp);
        ngx_rbt_red(node->parent->parent);
        node = node->parent->parent;

      } else {
        if (node == node->parent->left) {
          node = node->parent;
          ngx_rbtree_right_rotate(root, sentinel, node);
        }

        ngx_rbt_black(node->parent);
        ngx_rbt_red(node->parent->parent);
        ngx_rbtree_left_rotate(root, sentinel, node->parent->parent);
      }
    }

  }

  ngx_rbt_black(*root);
}
Пример #11
0
void ngx_rbtree_delete(ngx_rbtree_t **root, ngx_rbtree_t *sentinel,
             ngx_rbtree_t *node)
{
  ngx_int_t      is_red;
  ngx_rbtree_t  *subst, *temp, *w;

  /* a binary tree delete */

  if (node->left == sentinel) {
    temp = node->right;
    subst = node;

  } else if (node->right == sentinel) {
    temp = node->left;
    subst = node;

  } else {
    subst = ngx_rbtree_min(node->right, sentinel);

    if (subst->left != sentinel) {
      temp = subst->left;
    } else {
      temp = subst->right;
    }
  }

  if (subst == *root) {
    *root = temp;
    ngx_rbt_black(temp);

    /* DEBUG stuff */
    node->left = NULL;
    node->right = NULL;
    node->parent = NULL;
    node->key = 0;

    return;
  }

  is_red = ngx_rbt_is_red(subst);

  if (subst == subst->parent->left) {
    subst->parent->left = temp;

  } else {
    subst->parent->right = temp;
  }

  if (subst == node) {

    temp->parent = subst->parent;

  } else {

    if (subst->parent == node) {
      temp->parent = subst;

    } else {
      temp->parent = subst->parent;
    }

    subst->left = node->left;
    subst->right = node->right;
    subst->parent = node->parent;
    ngx_rbt_copy_color(subst, node);

    if (node == *root) {
      *root = subst;

    } else {
      if (node == node->parent->left) {
        node->parent->left = subst;
      } else {
        node->parent->right = subst;
      }
    }

    if (subst->left != sentinel) {
      subst->left->parent = subst;
    }

    if (subst->right != sentinel) {
      subst->right->parent = subst;
    }

    /* DEBUG stuff */
    node->left = NULL;
    node->right = NULL;
    node->parent = NULL;
    node->key = 0;
  }

  if (is_red) {
    return;
  }

  /* a delete fixup */

  while (temp != *root && ngx_rbt_is_black(temp)) {

    if (temp == temp->parent->left) {
      w = temp->parent->right;

      if (ngx_rbt_is_red(w)) {
        ngx_rbt_black(w);
        ngx_rbt_red(temp->parent);
        ngx_rbtree_left_rotate(root, sentinel, temp->parent);
        w = temp->parent->right;
      }

      if (ngx_rbt_is_black(w->left) && ngx_rbt_is_black(w->right)) {
        ngx_rbt_red(w);
        temp = temp->parent;

      } else {
        if (ngx_rbt_is_black(w->right)) {
          ngx_rbt_black(w->left);
          ngx_rbt_red(w);
          ngx_rbtree_right_rotate(root, sentinel, w);
          w = temp->parent->right;
        }

        ngx_rbt_copy_color(w, temp->parent);
        ngx_rbt_black(temp->parent);
        ngx_rbt_black(w->right);
        ngx_rbtree_left_rotate(root, sentinel, temp->parent);
        temp = *root;
      }

    } else {
      w = temp->parent->left;

      if (ngx_rbt_is_red(w)) {
        ngx_rbt_black(w);
        ngx_rbt_red(temp->parent);
        ngx_rbtree_right_rotate(root, sentinel, temp->parent);
        w = temp->parent->left;
      }

      if (ngx_rbt_is_black(w->left) && ngx_rbt_is_black(w->right)) {
        ngx_rbt_red(w);
        temp = temp->parent;

      } else {
        if (ngx_rbt_is_black(w->left)) {
          ngx_rbt_black(w->right);
          ngx_rbt_red(w);
          ngx_rbtree_left_rotate(root, sentinel, w);
          w = temp->parent->left;
        }

        ngx_rbt_copy_color(w, temp->parent);
        ngx_rbt_black(temp->parent);
        ngx_rbt_black(w->left);
        ngx_rbtree_right_rotate(root, sentinel, temp->parent);
        temp = *root;
      }
    }
  }

  ngx_rbt_black(temp);
}
Пример #12
0
void
ngx_rbtree_insert(ngx_thread_volatile ngx_rbtree_t *tree,
    ngx_rbtree_node_t *node)
{
    ngx_rbtree_node_t  **root, *temp, *sentinel;

    /* a binary tree insert */

    root = (ngx_rbtree_node_t **) &tree->root;
    sentinel = tree->sentinel;

    if (*root == sentinel) {
        node->parent = NULL;
        node->left = sentinel;
        node->right = sentinel;
        ngx_rbt_black(node);
        *root = node;

        return;
    }

    tree->insert(*root, node, sentinel);

    /* re-balance tree */

    while (node != *root && ngx_rbt_is_red(node->parent)) {

        if (node->parent == node->parent->parent->left) {
            temp = node->parent->parent->right;

            if (ngx_rbt_is_red(temp)) {
                ngx_rbt_black(node->parent);
                ngx_rbt_black(temp);
                ngx_rbt_red(node->parent->parent);
                node = node->parent->parent;

            } else {
                if (node == node->parent->right) {
                    node = node->parent;
                    ngx_rbtree_left_rotate(root, sentinel, node);
                }

                ngx_rbt_black(node->parent);
                ngx_rbt_red(node->parent->parent);
                ngx_rbtree_right_rotate(root, sentinel, node->parent->parent);
            }

        } else {
            temp = node->parent->parent->left;

            if (ngx_rbt_is_red(temp)) {
                ngx_rbt_black(node->parent);
                ngx_rbt_black(temp);
                ngx_rbt_red(node->parent->parent);
                node = node->parent->parent;

            } else {
                if (node == node->parent->left) {
                    node = node->parent;
                    ngx_rbtree_right_rotate(root, sentinel, node);
                }

                ngx_rbt_black(node->parent);
                ngx_rbt_red(node->parent->parent);
                ngx_rbtree_left_rotate(root, sentinel, node->parent->parent);
            }
        }
    }

    ngx_rbt_black(*root);
}
Пример #13
0
void
ngx_rbtree_insert(ngx_thread_volatile ngx_rbtree_t *tree,//插入节点
    ngx_rbtree_node_t *node)//插入的节点
{
    ngx_rbtree_node_t  **root, *temp, *sentinel;//树节点 root temp 哨兵

    /* a binary tree insert */

    root = (ngx_rbtree_node_t **) &tree->root;//定位root
    sentinel = tree->sentinel;//定位哨兵

    if (*root == sentinel) {//如果树为空
        node->parent = NULL;//节点的父亲节点是空
        node->left = sentinel;//左
        node->right = sentinel;
        ngx_rbt_black(node);//父节点一定得是黑色的
        *root = node;

        return;
    }

    tree->insert(*root, node, sentinel);//如果不是空的树进行插入 按照二叉搜索树插入节点

    /* re-balance tree */

    while (node != *root && ngx_rbt_is_red(node->parent)) {//重新平衡树 当父节点是红色的 并且不是根节点

        if (node->parent == node->parent->parent->left) {//如果是正向的
            temp = node->parent->parent->right;//父节点的兄弟节点

            if (ngx_rbt_is_red(temp)) {//I3 x为red p为red s为red 导出pp为black
                ngx_rbt_black(node->parent);//p设为黑 
                ngx_rbt_black(temp);//s 设为黑
                ngx_rbt_red(node->parent->parent);//pp设置为红
                node = node->parent->parent;//当前节点指向pp 不需要旋转

            } else {
                if (node == node->parent->right) {//I2 x为red p为red s为black 右节点 
                    node = node->parent;//当前节点指向p
                    ngx_rbtree_left_rotate(root, sentinel, node);//进行左旋 即插入的节点替代p p转成插入节点的左节点
                }

                ngx_rbt_black(node->parent);//I1 x为red p为red s为black pp为black 设置p为黑
                ngx_rbt_red(node->parent->parent);//设置pp为红
                ngx_rbtree_right_rotate(root, sentinel, node->parent->parent);//右旋
            }

        } else {//反向同理 方向相反
            temp = node->parent->parent->left;

            if (ngx_rbt_is_red(temp)) {
                ngx_rbt_black(node->parent);
                ngx_rbt_black(temp);
                ngx_rbt_red(node->parent->parent);
                node = node->parent->parent;

            } else {
                if (node == node->parent->left) {
                    node = node->parent;
                    ngx_rbtree_right_rotate(root, sentinel, node);
                }

                ngx_rbt_black(node->parent);
                ngx_rbt_red(node->parent->parent);
                ngx_rbtree_left_rotate(root, sentinel, node->parent->parent);
            }
        }
    }

    ngx_rbt_black(*root);//无脑设置根节点为黑
}
Пример #14
0
//http://www.360doc.com/content/15/082609/10504424_494791577.shtml
void
ngx_rbtree_delete(ngx_thread_volatile ngx_rbtree_t *tree,
    ngx_rbtree_node_t *node)
{
    ngx_uint_t           red;
    ngx_rbtree_node_t  **root, *sentinel, *subst, *temp, *w;

    /* a binary tree delete */

    root = (ngx_rbtree_node_t **) &tree->root;
    sentinel = tree->sentinel;

    if (node->left == sentinel) {//zuo情况1 2 删除节点y为单支节点或者叶子节点
        temp = node->right;
        subst = node;

    } else if (node->right == sentinel) {//情况1 2 删除节点y为单支节点或者叶子节点
        temp = node->left;
        subst = node;

    } else {//情况1 3 删除节点y为双支节点
        subst = ngx_rbtree_min(node->right, sentinel);

        if (subst->left != sentinel) {
            temp = subst->left;
        } else {
            temp = subst->right;
        }
    }

    if (subst == *root) {
        *root = temp;
        ngx_rbt_black(temp);

        /* DEBUG stuff */
        node->left = NULL;
        node->right = NULL;
        node->parent = NULL;
        node->key = 0;

        return;
    }

    red = ngx_rbt_is_red(subst);//记录y的颜色

    if (subst == subst->parent->left) {//这里按照二叉树的性质,删除节点后重新生成二叉搜索树
        subst->parent->left = temp;

    } else {
        subst->parent->right = temp;
    }

    if (subst == node) {

        temp->parent = subst->parent;

    } else {

        if (subst->parent == node) {
            temp->parent = subst;

        } else {
            temp->parent = subst->parent;
        }

        subst->left = node->left;
        subst->right = node->right;
        subst->parent = node->parent;
        ngx_rbt_copy_color(subst, node);

        if (node == *root) {
            *root = subst;

        } else {
            if (node == node->parent->left) {
                node->parent->left = subst;
            } else {
                node->parent->right = subst;
            }
        }

        if (subst->left != sentinel) {
            subst->left->parent = subst;
        }

        if (subst->right != sentinel) {
            subst->right->parent = subst;
        }
    }

    /* DEBUG stuff */
    node->left = NULL;
    node->right = NULL;
    node->parent = NULL;
    node->key = 0;

    if (red) {//如果删除的节点y为red 直接退出
        return;
    }

    /* a delete fixup */

    while (temp != *root && ngx_rbt_is_black(temp)) {//temp就是上文中的x,开始平衡红黑节点,知道x为红色,或者到达root

        if (temp == temp->parent->left) {
            w = temp->parent->right;

            if (ngx_rbt_is_red(w)) {//D1
                ngx_rbt_black(w);
                ngx_rbt_red(temp->parent);
                ngx_rbtree_left_rotate(root, sentinel, temp->parent);
                w = temp->parent->right;
            }

            if (ngx_rbt_is_black(w->left) && ngx_rbt_is_black(w->right)) {//d2
                ngx_rbt_red(w);
                temp = temp->parent;

            } else {//d3
                if (ngx_rbt_is_black(w->right)) {
                    ngx_rbt_black(w->left);
                    ngx_rbt_red(w);
                    ngx_rbtree_right_rotate(root, sentinel, w);
                    w = temp->parent->right;
                }

                ngx_rbt_copy_color(w, temp->parent);//d4
                ngx_rbt_black(temp->parent);
                ngx_rbt_black(w->right);
                ngx_rbtree_left_rotate(root, sentinel, temp->parent);
                temp = *root;
            }

        } else {
            w = temp->parent->left;

            if (ngx_rbt_is_red(w)) {
                ngx_rbt_black(w);
                ngx_rbt_red(temp->parent);
                ngx_rbtree_right_rotate(root, sentinel, temp->parent);
                w = temp->parent->left;
            }

            if (ngx_rbt_is_black(w->left) && ngx_rbt_is_black(w->right)) {
                ngx_rbt_red(w);
                temp = temp->parent;

            } else {
                if (ngx_rbt_is_black(w->left)) {
                    ngx_rbt_black(w->right);
                    ngx_rbt_red(w);
                    ngx_rbtree_left_rotate(root, sentinel, w);
                    w = temp->parent->left;
                }

                ngx_rbt_copy_color(w, temp->parent);
                ngx_rbt_black(temp->parent);
                ngx_rbt_black(w->left);
                ngx_rbtree_right_rotate(root, sentinel, temp->parent);
                temp = *root;
            }
        }
    }

    ngx_rbt_black(temp);
}
Пример #15
0
void
ngx_rbtree_insert(ngx_thread_volatile ngx_rbtree_t *tree,
    ngx_rbtree_node_t *node)                                        /*插入一个节点*/
{
    ngx_rbtree_node_t  **root, *temp, *sentinel;

    /* a binary tree insert */

    root = (ngx_rbtree_node_t **) &tree->root;                     /*为什么要转换成 ngx_rbtree_node_t **类型,??todo*/
    sentinel = tree->sentinel;

    if (*root == sentinel) {                                        /**/
        node->parent = NULL;
        node->left = sentinel;
        node->right = sentinel;
        ngx_rbt_black(node);
        *root = node;

        return;
    }

    tree->insert(*root, node, sentinel);        /*??todo*/

    /* re-balance tree */

    while (node != *root && ngx_rbt_is_red(node->parent)) {

        if (node->parent == node->parent->parent->left) {       /*node的父亲节点为左节点*/
            temp = node->parent->parent->right;                  /*叔节点*/

            if (ngx_rbt_is_red(temp)) {/*叔节点为红色*/
                ngx_rbt_black(node->parent);
                ngx_rbt_black(temp);
                ngx_rbt_red(node->parent->parent);
                node = node->parent->parent;

            } else { /*叔节点为黑色*/
                if (node == node->parent->right) { /*node为右孩子*/
                    node = node->parent;
                    ngx_rbtree_left_rotate(root, sentinel, node);
                }
                /*node为左孩子*/
                ngx_rbt_black(node->parent);
                ngx_rbt_red(node->parent->parent);
                ngx_rbtree_right_rotate(root, sentinel, node->parent->parent);
            }

        } else {                                                        /*node的父亲节点为右节点*/
            temp = node->parent->parent->left;

            if (ngx_rbt_is_red(temp)) {
                ngx_rbt_black(node->parent);
                ngx_rbt_black(temp);
                ngx_rbt_red(node->parent->parent);
                node = node->parent->parent;

            } else {
                if (node == node->parent->left) {
                    node = node->parent;
                    ngx_rbtree_right_rotate(root, sentinel, node);
                }

                ngx_rbt_black(node->parent);
                ngx_rbt_red(node->parent->parent);
                ngx_rbtree_left_rotate(root, sentinel, node->parent->parent);
            }
        }
    }

    ngx_rbt_black(*root);
}
Пример #16
0
void
ngx_rbtree_delete(ngx_thread_volatile ngx_rbtree_t *tree,
    ngx_rbtree_node_t *node)
{
    ngx_uint_t           red;
    ngx_rbtree_node_t  **root, *sentinel, *subst, *temp, *w;

    /* a binary tree delete */

    root = (ngx_rbtree_node_t **) &tree->root;      /*why  ??todo*/
    sentinel = tree->sentinel;

    if (node->left == sentinel) {                    /* 左节点为nil */
        temp = node->right;
        subst = node;

    } else if (node->right == sentinel) {           /* 右节点为nil */
        temp = node->left;
        subst = node;

    } else {                                           /*左/右节点都有孩子*/
        subst = ngx_rbtree_min(node->right, sentinel);

        if (subst->left != sentinel) {
            temp = subst->left;
        } else {
            temp = subst->right;
        }
    }

    if (subst == *root) {
        *root = temp;
        ngx_rbt_black(temp);

        /* DEBUG stuff */
        node->left = NULL;
        node->right = NULL;
        node->parent = NULL;
        node->key = 0;

        return;
    }

    red = ngx_rbt_is_red(subst);

    if (subst == subst->parent->left) {  /**/
        subst->parent->left = temp;

    } else {
        subst->parent->right = temp;
    }

    if (subst == node) {

        temp->parent = subst->parent;

    } else {  /*subst为node后继*/

        if (subst->parent == node) {
            temp->parent = subst;       /**/

        } else {
            temp->parent = subst->parent;
        }

        subst->left = node->left;
        subst->right = node->right;
        subst->parent = node->parent;
        ngx_rbt_copy_color(subst, node);

        if (node == *root) {
            *root = subst;

        } else {
            if (node == node->parent->left) {
                node->parent->left = subst;
            } else {
                node->parent->right = subst;
            }
        }

        if (subst->left != sentinel) {
            subst->left->parent = subst;
        }

        if (subst->right != sentinel) {
            subst->right->parent = subst;
        }
    }

    /* DEBUG stuff */
    node->left = NULL;
    node->right = NULL;
    node->parent = NULL;
    node->key = 0;

    if (red) {
        return;
    }

    /* a delete fixup */

    while (temp != *root && ngx_rbt_is_black(temp)) {

        if (temp == temp->parent->left) {
            w = temp->parent->right;

            if (ngx_rbt_is_red(w)) {
                ngx_rbt_black(w);
                ngx_rbt_red(temp->parent);
                ngx_rbtree_left_rotate(root, sentinel, temp->parent);
                w = temp->parent->right;
            }

            if (ngx_rbt_is_black(w->left) && ngx_rbt_is_black(w->right)) {
                ngx_rbt_red(w);
                temp = temp->parent;

            } else {
                if (ngx_rbt_is_black(w->right)) {
                    ngx_rbt_black(w->left);
                    ngx_rbt_red(w);
                    ngx_rbtree_right_rotate(root, sentinel, w);
                    w = temp->parent->right;
                }

                ngx_rbt_copy_color(w, temp->parent);
                ngx_rbt_black(temp->parent);
                ngx_rbt_black(w->right);
                ngx_rbtree_left_rotate(root, sentinel, temp->parent);
                temp = *root;
            }

        } else {
            w = temp->parent->left;

            if (ngx_rbt_is_red(w)) {
                ngx_rbt_black(w);
                ngx_rbt_red(temp->parent);
                ngx_rbtree_right_rotate(root, sentinel, temp->parent);
                w = temp->parent->left;
            }

            if (ngx_rbt_is_black(w->left) && ngx_rbt_is_black(w->right)) {
                ngx_rbt_red(w);
                temp = temp->parent;

            } else {
                if (ngx_rbt_is_black(w->left)) {
                    ngx_rbt_black(w->right);
                    ngx_rbt_red(w);
                    ngx_rbtree_left_rotate(root, sentinel, w);
                    w = temp->parent->left;
                }

                ngx_rbt_copy_color(w, temp->parent);
                ngx_rbt_black(temp->parent);
                ngx_rbt_black(w->left);
                ngx_rbtree_right_rotate(root, sentinel, temp->parent);
                temp = *root;
            }
        }
    }

    ngx_rbt_black(temp);
}