Skip to content

Instantly share code, notes, and snippets.

@tonyhutter
Last active November 12, 2020 18:11
Show Gist options
  • Save tonyhutter/b4d27af13d297137e7d7fb88d7752ab6 to your computer and use it in GitHub Desktop.
Save tonyhutter/b4d27af13d297137e7d7fb88d7752ab6 to your computer and use it in GitHub Desktop.
/////////////
// seg_tree.c
/////////////
/* Return the number of segments in the segment tree */
unsigned long seg_tree_count(struct seg_tree* seg_tree)
{
    seg_tree_rdlock(seg_tree);
    unsigned long count = seg_tree->count;
    seg_tree_unlock(seg_tree);
    return count;
}

/* Return the maximum ending logical offset in the tree */
unsigned long seg_tree_max(struct seg_tree* seg_tree)
{
    seg_tree_rdlock(seg_tree);
    unsigned long max = seg_tree->max;
    seg_tree_unlock(seg_tree);
    return max;
}


////////////////
// extent_tree.c
////////////////
/* Return the number of segments in the segment tree */
unsigned long extent_tree_count(struct extent_tree* extent_tree)
{
    extent_tree_rdlock(extent_tree);
    unsigned long count = extent_tree->count;
    extent_tree_unlock(extent_tree);
    return count;
}

/* Return the maximum ending logical offset in the tree */
unsigned long extent_tree_max_offset(struct extent_tree* extent_tree)
{
    extent_tree_rdlock(extent_tree);
    unsigned long max = extent_tree->max;
    extent_tree_unlock(extent_tree);
    return max;
}
/////////////
// seg_tree.c
/////////////

#ifndef MIN
#define MIN(a, b) ((a) < (b) ? (a) : (b))
#endif

#ifndef MAX
#define MAX(a, b) ((a) > (b) ? (a) : (b))
#endif

static int
compare_func(struct seg_tree_node* node1, struct seg_tree_node* node2)
{
    if (node1->start > node2->end) {
        return 1;
    } else if (node1->end < node2->start) {
        return -1;
    } else {
        return 0;
    }
}
////////////////
// extent_tree.c
////////////////
#undef MIN
#define MIN(a, b) (a < b ? a : b)
#undef MAX
#define MAX(a, b) (a > b ? a : b)

int compare_func(
    struct extent_tree_node* node1,
    struct extent_tree_node* node2)
{
    if (node1->start > node2->end) {
        return 1;
    } else if (node1->end < node2->start) {
        return -1;
    } else {
        return 0;
    }
}
//////////////////
// unifyfs_inode.c
//////////////////
/**
 * @brief read lock the inode for ro access.
 *
 * @param ino inode structure to get access
 *
 * @return 0 on success, errno otherwise
 */
static inline
int unifyfs_inode_rdlock(struct unifyfs_inode* ino)
{
    return pthread_rwlock_rdlock(&ino->rwlock);
}

/**
 * @brief write lock the inode for w+r access.
 *
 * @param ino inode structure to get access
 *
 * @return 0 on success, errno otherwise
 */
static inline
int unifyfs_inode_wrlock(struct unifyfs_inode* ino)
{
    return pthread_rwlock_wrlock(&ino->rwlock);
}

/**
 * @brief unlock the inode.
 *
 * @param ino inode structure to unlock
 */
static inline
void unifyfs_inode_unlock(struct unifyfs_inode* ino)
{
    pthread_rwlock_unlock(&ino->rwlock);
}


////////////////
// extent_tree.c
////////////////
/*
 * Lock a extent_tree for reading.  This should only be used for calling
 * extent_tree_iter().  All the other extent_tree functions provide their
 * own locking.
 */
void extent_tree_rdlock(struct extent_tree* extent_tree)
{
    int rc = pthread_rwlock_rdlock(&extent_tree->rwlock);
    if (rc) {
        LOGERR("pthread_rwlock_rdlock() failed - rc=%d", rc);
    }
}

/*
 * Lock a extent_tree for read/write.  This should only be used for calling
 * extent_tree_iter().  All the other extent_tree functions provide their
 * own locking.
 */
void extent_tree_wrlock(struct extent_tree* extent_tree)
{
    int rc = pthread_rwlock_wrlock(&extent_tree->rwlock);
    if (rc) {
        LOGERR("pthread_rwlock_wrlock() failed - rc=%d", rc);
    }
}

/*
 * Unlock a extent_tree for read/write.  This should only be used for calling
 * extent_tree_iter().  All the other extent_tree functions provide their
 * own locking.
 */
void extent_tree_unlock(struct extent_tree* extent_tree)
{
    int rc = pthread_rwlock_unlock(&extent_tree->rwlock);
    if (rc) {
        LOGERR("pthread_rwlock_unlock() failed - rc=%d", rc);
    }
}

  
/////////////
// seg_tree.c
/////////////
/*
 * Lock a seg_tree for reading.  This should only be used for calling
 * seg_tree_iter().  All the other seg_tree functions provide their
 * own locking.
 */
void
seg_tree_rdlock(struct seg_tree* seg_tree)
{
    int rc = pthread_rwlock_rdlock(&seg_tree->rwlock);
    if (rc) {
        LOGERR("pthread_rwlock_rdlock() failed - rc=%d", rc);
    }
}

/*
 * Lock a seg_tree for read/write.  This should only be used for calling
 * seg_tree_iter().  All the other seg_tree functions provide their
 * own locking.
 */
void
seg_tree_wrlock(struct seg_tree* seg_tree)
{
    int rc = pthread_rwlock_wrlock(&seg_tree->rwlock);
    if (rc) {
        LOGERR("pthread_rwlock_wrlock() failed - rc=%d", rc);
    }
}

/*
 * Unlock a seg_tree for read/write.  This should only be used for calling
 * seg_tree_iter().  All the other seg_tree functions provide their
 * own locking.
 */
void
seg_tree_unlock(struct seg_tree* seg_tree)
{
    int rc = pthread_rwlock_unlock(&seg_tree->rwlock);
    if (rc) {
        LOGERR("pthread_rwlock_unlock() failed - rc=%d", rc);
    }
}
////////////////
// extent_tree.c
////////////////
/*
 * Given a range tree and a starting node, iterate though all the nodes
 * in the tree, returning the next one each time.  If start is NULL, then
 * start with the first node in the tree.
 *
 * This is meant to be called in a loop, like:
 *
 *    extent_tree_rdlock(extent_tree);
 *
 *    struct extent_tree_node *node = NULL;
 *    while ((node = extent_tree_iter(extent_tree, node))) {
 *       printf("[%d-%d]", node->start, node->end);
 *    }
 *
 *    extent_tree_unlock(extent_tree);
 *
 * Note: this function does no locking, and assumes you're properly locking
 * and unlocking the extent_tree before doing the iteration (see
 * extent_tree_rdlock()/extent_tree_wrlock()/extent_tree_unlock()).
 */
struct extent_tree_node* extent_tree_iter(
    struct extent_tree* extent_tree,
    struct extent_tree_node* start)
{
    struct extent_tree_node* next = NULL;
    if (start == NULL) {
        /* Initial case, no starting node */
        next = RB_MIN(inttree, &extent_tree->head);
        return next;
    }

    /*
     * We were given a valid start node.  Look it up to start our traversal
     * from there.
     */
    next = RB_FIND(inttree, &extent_tree->head, start);
    if (!next) {
        /* Some kind of error */
        return NULL;
    }

    /* Look up our next node */
    next = RB_NEXT(inttree, &extent_tree->head, start);

    return next;
}

/////////////
// seg_tree.c
/////////////
/*
 * Given a range tree and a starting node, iterate though all the nodes
 * in the tree, returning the next one each time.  If start is NULL, then
 * start with the first node in the tree.
 *
 * This is meant to be called in a loop, like:
 *
 *    seg_tree_rdlock(seg_tree);
 *
 *    struct seg_tree_node *node = NULL;
 *    while ((node = seg_tree_iter(seg_tree, node))) {
 *       printf("[%d-%d]", node->start, node->end);
 *    }
 *
 *    seg_tree_unlock(seg_tree);
 *
 * Note: this function does no locking, and assumes you're properly locking
 * and unlocking the seg_tree before doing the iteration (see
 * seg_tree_rdlock()/seg_tree_wrlock()/seg_tree_unlock()).
 */
struct seg_tree_node*
seg_tree_iter(struct seg_tree* seg_tree, struct seg_tree_node* start)
{
    struct seg_tree_node* next = NULL;
    struct seg_tree_node* tmp = NULL;
    if (start == NULL) {
        /* Initial case, no starting node */
        next = RB_MIN(inttree, &seg_tree->head);
        return next;
    }

    /*
     * We were given a valid start node.  Look it up to start our traversal
     * from there.
     */
    tmp = RB_FIND(inttree, &seg_tree->head, start);
    if (!tmp) {
        /* Some kind of error */
        return NULL;
    }

    /* Look up our next node */
    next = RB_NEXT(inttree, &seg_tree->head, start);

    return next;
}
/////////////
// seg_tree.c
/////////////
/*
 * Remove all nodes in seg_tree, but keep it initialized so you can
 * seg_tree_add() to it.
 */
void seg_tree_clear(struct seg_tree* seg_tree)
{
    struct seg_tree_node* node = NULL;
    struct seg_tree_node* oldnode = NULL;

    seg_tree_wrlock(seg_tree);

    if (RB_EMPTY(&seg_tree->head)) {
        /* seg_tree is empty, nothing to do */
        seg_tree_unlock(seg_tree);
        return;
    }

    /* Remove and free each node in the tree */
    while ((node = seg_tree_iter(seg_tree, node))) {
        if (oldnode) {
            RB_REMOVE(inttree, &seg_tree->head, oldnode);
            free(oldnode);
        }
        oldnode = node;
    }
    if (oldnode) {
        RB_REMOVE(inttree, &seg_tree->head, oldnode);
        free(oldnode);
    }

    seg_tree->count = 0;
    seg_tree->max = 0;
    seg_tree_unlock(seg_tree);
}


////////////////
// extent_tree.c 
////////////////
/*
 * Remove all nodes in extent_tree, but keep it initialized so you can
 * extent_tree_add() to it.
 */
void extent_tree_clear(struct extent_tree* extent_tree)
{
    struct extent_tree_node* node = NULL;
    struct extent_tree_node* oldnode = NULL;

    extent_tree_wrlock(extent_tree);

    if (RB_EMPTY(&extent_tree->head)) {
        /* extent_tree is empty, nothing to do */
        extent_tree_unlock(extent_tree);
        return;
    }

    /* Remove and free each node in the tree */
    while ((node = extent_tree_iter(extent_tree, node))) {
        if (oldnode) {
            RB_REMOVE(inttree, &extent_tree->head, oldnode);
            free(oldnode);
        }
        oldnode = node;
    }
    if (oldnode) {
        RB_REMOVE(inttree, &extent_tree->head, oldnode);
        free(oldnode);
    }

    extent_tree->count = 0;
    extent_tree->max   = 0;
    extent_tree_unlock(extent_tree);
}
///////////////////////
// unifyfs_inode_tree.c
///////////////////////
/* Returns 0 on success, positive non-zero error code otherwise */
int unifyfs_inode_tree_init(
    struct unifyfs_inode_tree* tree)
{
    int ret = 0;

    if (!tree) {
        return EINVAL;
    }

    memset(tree, 0, sizeof(*tree));
    ret = pthread_rwlock_init(&tree->rwlock, NULL);
    RB_INIT(&tree->head);

    return ret;
}

////////////////
// extent_tree.c
////////////////
/* Returns 0 on success, positive non-zero error code otherwise */
int extent_tree_init(struct extent_tree* extent_tree)
{
    memset(extent_tree, 0, sizeof(*extent_tree));
    pthread_rwlock_init(&extent_tree->rwlock, NULL);
    RB_INIT(&extent_tree->head);
    return 0;
}


/////////////
// seg_tree.c
/////////////
/* Returns 0 on success, positive non-zero error code otherwise */
int seg_tree_init(struct seg_tree* seg_tree)
{
    memset(seg_tree, 0, sizeof(*seg_tree));
    pthread_rwlock_init(&seg_tree->rwlock, NULL);
    RB_INIT(&seg_tree->head);

    return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment