Example #1
0
int insertR(int key, Node r_child_of_key, Node node, stack path_stack, int tid) {
    if (node->is_leaf) {
        // set the $thread_on bit to indicate thread $tid is entering. 
        pthread_mutex_lock(&node->mutex);
        node->thread_on |= 0x01 << tid;
        pthread_mutex_unlock(&node->mutex);

        while (node->reorganize_bit & 0x01) {
            //pthread_mutex_lock(&node->mutex); //can u get this lock???
            //pthread_cond_wait(&node->is_under_reorganizing, &node->mutex);
            //pthread_mutex_unlock(&node->mutex);
        }

        // check its own region capacity; not full is safe, and release locks 
        // of ancestors, including parent.
        if (node->private_region_capacity[tid] != 0) {
            while (!path_stack->is_empty(path_stack)) {
                pthread_mutex_unlock(&((Node) path_stack->top(path_stack)->data)->mutex);
                path_stack->pop(path_stack);
            }
        }

        // search in organized region (linear)
        int i;
        for (i = 0; i < node->organized_keys; ++i) {
            if (key == node->keys[i])
                return 0;
            else if (key < node->keys[i])
                break;
        }
        // key is between [i - 1] and [i]; follow child[i]

        // if it is leaf, linear search in private region (in leaf); or insert.

        // path_stack only contains from root to the parent of this $node.
        // insert the key record when $capacity != 0
        if (node->private_region_capacity[tid] != 0) {
            int insert_position = node->private_region_index[tid] + node->private_region_keys[tid];
            node->keys[insert_position] = key;
            //node->values[insert_position] = val;
            node->private_region_keys[tid] += 1;

            // if two threads meet the same situation and wait for each other to 
            // complete the reorganization... $reorganize_bit $thread_on??? 
            // how to deal with them in here. 
            if (node->private_region_capacity[tid] == node->private_region_keys[tid]) {
                pthread_mutex_lock(&node->mutex);
                if (!(node->reorganize_bit & 0x01) && 
                        (node->private_region_capacity[tid] == node->private_region_keys[tid]) && 
                        (node->private_region_capacity[tid] != 0)) {
                    node->reorganize_bit |= 0x01;
                    reorganize(node);
                    node->reorganize_bit &= 0x00;
                    //pthread_cond_broadcast(&node->is_under_reorganizing);
                }
                pthread_mutex_unlock(&node->mutex);
            }
        }
        else { // split the $node
            //TODO:
            // check whether other threads are manipulating the node by
            // using the $thread_on in each node. And wait to lock the node. 
            pthread_mutex_lock(&node->mutex);
            while (node->thread_on ^ (0x01 << tid)) {
                //!!!careful: if it needs to reset the $thread_on 
                // and set it after condition wait.
                node->thread_on ^= 0x01 << tid; //!? right or wrong?
                pthread_cond_wait(&node->is_going_splitting, &node->mutex);
                node->thread_on |= 0x01 << tid; //!? right or wrong?
            }
            // start to split; reorganize first
            node->reorganize_bit |= 0x01;
            reorganize(node);
            node->reorganize_bit &= 0x00;

            Node u = node;
            Node v = createNode(1); // 1 => is leaf;
            Node r_subtree = r_child_of_key;
            int median = splitLeaf(u, v);
            int elem = key;
            int finish = 0;
            if (u == root) {
                root = createNode(0);
                root->keys[0] = median;
                root->organized_keys++;
                root->child[0] = u;
                root->child[1] = v;
                finish = 1;
            }
            else {
                elem = median;
                r_subtree = v;
                u = (Node) path_stack->top(path_stack)->data;
                path_stack->pop(path_stack);
            }
            pthread_mutex_unlock(&node->mutex);

            while (/*!path_stack->is_empty() && */!finish) {
                if (u->organized_keys < (order - 1)) {
                    insertElem(elem, r_subtree, u);
                    finish = 1;
                }
                else {
                    v = createNode(0);
                    median = splitNonleaf(elem, r_subtree, u, v);

                    if (u == root) {
                        root = createNode(0);
                        root->keys[0] = median;
                        root->organized_keys++;
                        root->child[0] = u;
                        root->child[1] = v;
                        finish = 1;
                    }
                    else {
                        pthread_mutex_unlock(&u->mutex);
                        elem = median;
                        r_subtree = v;
                        u = (Node) path_stack->top(path_stack)->data;
                        path_stack->pop(path_stack);
                    }
                }
            }
            pthread_mutex_unlock(&u->mutex);
        }

        pthread_mutex_lock(&node->mutex);
        node->thread_on ^= 0x01 << tid;
        pthread_cond_signal(&node->is_going_splitting);
        pthread_mutex_unlock(&node->mutex);
    }
    else { // lock this node, and follow child[i]
        pthread_mutex_lock(&node->mutex);

        // if current node is safe, then release all ancestors.
        if (node->organized_keys < (order - 1)) {
            while (!path_stack->is_empty()) {
                pthread_mutex_unlock(&((Node) path_stack->top(path_stack)->data)->mutex);
                path_stack->pop(path_stack);
            }
        }

        // search in organized region (linear)
        int i;
        for (i = 0; i < node->organized_keys; ++i) {
            if (key == node->keys[i])
                return 0;
            else if (key < node->keys[i])
                break;
        }
        // key is between [i - 1] and [i]; follow child[i]

        struct stack_node_struct stack_node;
        stack_node.data = node;
        path_stack->push(path_stack, &stack_node);
        insertR(key, r_child_of_key, node->child[i], path_stack);
    }
}