Thu Jun 7 06:01:12 PDT 2007
- Previous message: [Slony1-commit] slony1-engine/src/ducttape test_1_pgbench.in
- Next message: [Slony1-commit] slony1-engine/src/slon remote_worker.c
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
Update of /home/cvsd/slony1/slony1-engine/src/misc
In directory main.slony.info:/tmp/cvs-serv25549/src/misc
Added Files:
avl_tree.c avl_tree.h
Log Message:
Attempt to remove the sl_seqlog flood.
This patch adds a new function seqtrack(seqid,seqvalue) that will return
NULL if called with the same seqvalue before, the seqvalue instead. This
function is used to suppress sl_seqlog rows of sequences that didn't change
since the last SYNC.
Jan
--- NEW FILE: avl_tree.c ---
/* ----------------------------------------------------------------------
* avl_tree.c
*
* AVL style self balancing tree support.
*
* Copyright (c) 2007, PostgreSQL Global Development Group
* Author: Jan Wieck, Afilias USA INC.
*
* $Id: avl_tree.c,v 1.1 2007-06-07 13:01:10 wieck Exp $
* ----------------------------------------------------------------------
*/
#include "avl_tree.h"
/* ----
* local function declarations
* ----
*/
static AVLnode *avl_makenode(void);
static void avl_reset_node(AVLnode *node, AVLfreefunc *freefunc);
static int avl_insertinto(AVLtree *tree, AVLnode **node,
void *cdata, AVLnode **result);
static void avl_rotate_left(AVLnode **node);
static void avl_rotate_right(AVLnode **node);
/* ----
* avl_init() -
*
* Initilize an AVL tree structure.
*
* compfunc is a user supplied tri-state comparision function that compares
* two tree elements and returns <0, 0 or >0 (like strcmp).
*
* If freefunc is specified, it is called to free no longer used elements.
* Note that the element will not immediately be free'd on avl_delete(),
* but only on a avl_delete, avl_insert sequence using the same key.
* ----
*/
void
avl_init(AVLtree *tree, AVLcompfunc *compfunc, AVLfreefunc *freefunc)
{
tree->root = NULL;
tree->compfunc = compfunc;
tree->freefunc = freefunc;
}
/* ----
* avl_reset() -
*
* Reset an AVL tree to empty. This will call the user defined
* free function for all elements in the tree, destroy all nodes
* and declare the tree empty again.
* ----
*/
void
avl_reset(AVLtree *tree)
{
avl_reset_node(tree->root, tree->freefunc);
tree->root = NULL;
}
/* ----
* avl_reset_node() -
*
* avl_reset()'s workhorse.
* ----
*/
void
avl_reset_node(AVLnode *node, AVLfreefunc *freefunc)
{
if (node == NULL)
return;
avl_reset_node(node->lnode, freefunc);
avl_reset_node(node->rnode, freefunc);
if (freefunc != NULL)
freefunc(node->cdata);
free(node);
}
/* ----
* avl_insert() -
*
* Insert an element into an AVL tree. On return AVL_DATA(node) might
* point to an existing entry with the same key. If the caller replaces
* the entry, it must free the existing one since AVL will no longer
* keep track of it.
* ----
*/
AVLnode *
avl_insert(AVLtree *tree, void *cdata)
{
AVLnode *result;
int depth;
/*
* If this is an empty tree, create the root node.
*/
if (tree->root == NULL)
return (tree->root = avl_makenode());
/*
* Traverse the tree to find the insert point.
*/
result = NULL;
depth = avl_insertinto(tree, &(tree->root), cdata, &result);
return result;
}
/* ----
* avl_lookup() -
*
* Search for an existing key in the tree.
* ----
*/
AVLnode *
avl_lookup(AVLtree *tree, void *cdata)
{
AVLnode *node;
int cmp;
node = tree->root;
while (node != NULL)
{
cmp = tree->compfunc(cdata, node->cdata);
if (cmp == 0)
{
/*
* Found the node. If it is marked deleted, return NULL
* anyway. Otherwise return this node.
*/
if (node->deleted)
return NULL;
return node;
}
/*
* Search on ...
*/
if (cmp < 0)
node = node->lnode;
else
node = node->rnode;
}
/*
* No such element found
*/
return NULL;
}
/* ----
* avl_delete() -
*
* Mark a given element as deleted. Subsequent lookups for the element
* will return NULL. Note that the caller should NOT free the memory
* of the element, as it is AVL's property altogether after the delete.
*
* avl_delete() returns 1 on success, 0 if no such element was found.
* ----
*/
int
avl_delete(AVLtree *tree, void *cdata)
{
AVLnode *node;
if ((node = avl_lookup(tree, cdata)) == NULL)
return 0;
node->deleted = 1;
return 1;
}
/* ----
* avl_insertinto() -
*
* The heart of avl_insert().
* ----
*/
static int
avl_insertinto(AVLtree *tree, AVLnode **node,
void *cdata, AVLnode **result)
{
int cmp;
/*
* Compare the node at hand with the new elements key.
*/
cmp = (tree->compfunc)(cdata, (*node)->cdata);
if (cmp > 0)
{
/*
* New element is > than node. Insert to the right.
*/
if ((*node)->rnode == NULL)
{
/*
* Right side of current node is empty. Create a new node
* there and return new maximum depth. Note that this can
* only be 1 because otherwise this node would have been
* unbalanced before.
*/
(*node)->rnode = *result = avl_makenode();
(*node)->rdepth = 1;
return 1;
}
/*
* Right hand node exists. Recurse into that and remember the
* new right hand side depth.
*/
(*node)->rdepth = avl_insertinto(tree, &((*node)->rnode),
cdata, result) + 1;
/*
* A right hand side insert can unbalance this node only to the
* right.
*/
if (AVL_BALANCE(*node) > 1)
{
if (AVL_BALANCE((*node)->rnode) > 0)
{
/*
* RR situation, rebalance the tree by left rotating
* this node.
*/
avl_rotate_left(node);
}
else
{
/*
* RL situation, rebalance the tree by first right
* rotating the right hand side, then left rotating
* this node.
*/
avl_rotate_right(&((*node)->rnode));
avl_rotate_left(node);
}
}
return AVL_MAXDEPTH(*node);
}
else if (cmp < 0)
{
/*
* New element is < than node. Insert to the left.
*/
if ((*node)->lnode == NULL)
{
/*
* Left side of current node is empty. Create a new node
* there and return new maximum depth. Note that this can
* only be 1 because otherwise this node would have been
* unbalanced before.
*/
(*node)->lnode = *result = avl_makenode();
(*node)->ldepth = 1;
return AVL_MAXDEPTH(*node);
}
/*
* Left hand node exists. Recurse into that and remember the
* new left hand side depth.
*/
(*node)->ldepth = avl_insertinto(tree, &((*node)->lnode),
cdata, result) + 1;
/*
* A left hand side insert can unbalance this node only to the
* left.
*/
if (AVL_BALANCE(*node) < -1)
{
if (AVL_BALANCE((*node)->lnode) < 0)
{
/*
* LL situation, rebalance the tree by right rotating
* this node.
*/
avl_rotate_right(node);
}
else
{
/*
* LR situation, rebalance the tree by first left rotating
* the left node, then right rotating this node.
*/
avl_rotate_left(&((*node)->lnode));
avl_rotate_right(node);
}
}
return AVL_MAXDEPTH(*node);
}
else {
/*
* The new element is equal to this node. If it is marked
* for deletion, free the user element data now. The caller
* is supposed to replace it with a new element having the
* the key.
*/
if ((*node)->deleted && tree->freefunc != NULL)
{
(tree->freefunc)((*node)->cdata);
(*node)->cdata = NULL;
(*node)->deleted = 0;
}
*result = *node;
return AVL_MAXDEPTH(*node);
}
}
/* ----
* avl_makenode() -
*
* Create a new empty node.
* ----
*/
static AVLnode *
avl_makenode(void)
{
AVLnode *new;
new = (AVLnode *)malloc(sizeof(AVLnode));
memset(new, 0, sizeof(AVLnode));
return new;
}
/* ----
* avl_rotate_left() -
*
* Rebalance a node to the left.
* ----
*/
static void
avl_rotate_left(AVLnode **node)
{
AVLnode *rtmp;
/*
* save right node
*/
rtmp = (*node)->rnode;
/*
* move right nodes left side to this nodes right
*/
(*node)->rnode = rtmp->lnode;
if (rtmp->lnode != NULL)
(*node)->rdepth = AVL_MAXDEPTH(rtmp->lnode) + 1;
else
(*node)->rdepth = 0;
/*
* Move this node to right nodes left side
*/
rtmp->lnode = *node;
rtmp->ldepth = AVL_MAXDEPTH(*node) + 1;
/*
* Let parent point to right node
*/
*node = rtmp;
}
/* ----
* avl_rotate_right() -
*
* Rebalance a node to the right.
* ----
*/
static void
avl_rotate_right(AVLnode **node)
{
AVLnode *ltmp;
/*
* save left node
*/
ltmp = (*node)->lnode;
/*
* move left nodes right side to this nodes left
*/
(*node)->lnode = ltmp->rnode;
if (ltmp->rnode != NULL)
(*node)->ldepth = AVL_MAXDEPTH(ltmp->rnode) + 1;
else
(*node)->ldepth = 0;
/*
* Move this node to left nodes right side
*/
ltmp->rnode = *node;
ltmp->rdepth = AVL_MAXDEPTH(*node) + 1;
/*
* Let parent point to left node
*/
*node = ltmp;
}
--- NEW FILE: avl_tree.h ---
/* ----------------------------------------------------------------------
* avl_tree.h
*
* Declarations for AVL style balanced tree support.
*
* Copyright (c) 2003-2007, PostgreSQL Global Development Group
* Author: Jan Wieck, Afilias USA INC.
*
* $Id: avl_tree.h,v 1.1 2007-06-07 13:01:10 wieck Exp $
* ----------------------------------------------------------------------
*/
#ifndef _AVL_TREE_H_INCLUDED_
#define _AVL_TREE_H_INCLUDED_
/* ----
* Callback function type declarations
* ----
*/
typedef int (AVLcompfunc) (void *, void *);
typedef void (AVLfreefunc) (void *);
/* ----
* Data structures
* ----
*/
typedef struct AVLnode_s {
struct AVLnode_s *lnode, *rnode;
int ldepth, rdepth;
void *cdata;
int deleted;
} AVLnode;
typedef struct AVLtree_s {
AVLnode *root;
AVLcompfunc *compfunc;
AVLfreefunc *freefunc;
} AVLtree;
/* ----
* Macros
* ----
*/
#define AVL_DATA(n) (n)->cdata
#define AVL_SETDATA(n,p) ((n)->cdata = (p))
#define AVL_MAXDEPTH(n) (((n)->ldepth > (n)->rdepth) ? (n)->ldepth : (n)->rdepth)
#define AVL_BALANCE(n) ((n)->rdepth - (n)->ldepth)
#define AVL_INITIALIZER(cmp,free) {NULL, (cmp), (free)}
/* ----
* Public functions
* ----
*/
void avl_init(AVLtree *tree, AVLcompfunc *compfunc,
AVLfreefunc *freefunc);
void avl_reset(AVLtree *tree);
AVLnode *avl_insert(AVLtree *tree, void *cdata);
AVLnode *avl_lookup(AVLtree *tree, void *cdata);
int avl_delete(AVLtree *tree, void *cdata);
#endif /* _AVL_TREE_H_INCLUDED_ */
- Previous message: [Slony1-commit] slony1-engine/src/ducttape test_1_pgbench.in
- Next message: [Slony1-commit] slony1-engine/src/slon remote_worker.c
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
More information about the Slony1-commit mailing list