コード例 #1
0
ファイル: AvlNode.cpp プロジェクト: Rjoydip/wot-arduino
AvlIndex AvlNode::balance(AvlIndex tree)
{
    int balance, lh, rh;

    balance = get_balance(tree);

    if (balance < -1)
    {
        balance = get_balance(AVLNODE(tree)->left);

        if (balance > 0)
            tree = left_right(tree);
        else
            tree = left_left(tree);
    }
    else if (balance > 1)
    {
        balance = get_balance(AVLNODE(tree)->right);

        if (balance < 0)
            tree = right_left(tree);
        else
            tree = right_right(tree);
    }

    lh = node_height(AVLNODE(tree)->left);
    rh = node_height(AVLNODE(tree)->right);
    AVLNODE(tree)->height = (lh > rh ? lh : rh) + 1;
    return tree;
}
コード例 #2
0
ファイル: market_records.cpp プロジェクト: abitmore/bitshares
asset market_order::get_quantity( const price& relative )const
{
  switch( order_type_enum( type ) )
  {
     case relative_bid_order:
     case bid_order:
     { // balance is in USD  divide by price
        return get_balance() * get_price(relative);
     }
     case relative_ask_order:
     case ask_order:
     { // balance is in USD  divide by price
        return get_balance();
     }
     case short_order:
     {
        return get_balance();
     }
     case cover_order:
     {
        return asset( (*collateral * BTS_BLOCKCHAIN_MCALL_D2C_NUMERATOR) / BTS_BLOCKCHAIN_MCALL_D2C_DENOMINATOR );
     }
     default:
        FC_ASSERT( false, "Not Implemented" );
  }
  // NEVER GET HERE.....
  //return get_balance() * get_price();
}
コード例 #3
0
ファイル: market_records.cpp プロジェクト: abitmore/bitshares
asset market_order::get_quote_quantity( const price& relative )const
{
  switch( order_type_enum( type ) )
  {
     case relative_bid_order:
     case bid_order:
     { // balance is in USD  divide by price
        return get_balance();
     }
     case relative_ask_order:
     case ask_order:
     { // balance is in USD  divide by price
        return get_balance() * get_price(relative);
     }
     case short_order:
     {
        return get_balance() * get_price(relative);
     }
     case cover_order:
     {
        return get_balance();
     }
     default:
        FC_ASSERT( false, "Not Implemented" );
  }
  // NEVER GET HERE.....
 // return get_balance() * get_price();
}
コード例 #4
0
ファイル: height.c プロジェクト: rumidier/Bit
NODE *balance_tree (NODE **node)
{
	int height_diff;
	height_diff = get_balance(*node);
	printf("밸런스값 %d\n", height_diff);

	if (height_diff > 1)
	{
		if (get_balance((*node)->left) > 0) {
			*node = rotate_LL(*node);
		}else {
			*node = rotate_LR(*node);
		}
	}

	else if (height_diff < -1)
	{
		if (get_balance((*node)->right) < 0)
		{
			*node = rotate_RR(*node);
		}
		else {
			*node = rotate_LL(*node);
		}
	}

	return *node;
}
コード例 #5
0
ファイル: node.cpp プロジェクト: azelick/cs202p1-2
void Node::balance_function(Node *&root)
{
    if(!root)
        return;

    int balance_factor = get_balance(root);

    //TODO remove
    //cout << "balance_factor at : " << root->word 
    //    << " is " << balance_factor << endl;

    if(balance_factor == 2)
    {
        int left_balance = get_balance(root->left);
        //left has more than right
        //so left should become root
        if(left_balance == 0)
        {
            cout << "this shouldn't happen, if it does we have a problem" << endl;

        }
        if(left_balance == 1)
        {
            rotate_clockwise(root);
        }
        if(left_balance == -1)
        {
            rotate_counter_clockwise(root->left);
            rotate_clockwise(root);
        }
    }
    if(balance_factor == -2)
    {
        int right_balance = get_balance(root->right);
        //right has more than left
        if(right_balance == 0)
        {
            cout << "this shouldn't happen, if it does we have a problem" << endl;
        }
        if(right_balance == 1)
        {
            rotate_clockwise(root->right);
            rotate_counter_clockwise(root);
        }
        if(right_balance == -1)
        {
            rotate_counter_clockwise(root);
        }
    } 
    return;
}
コード例 #6
0
    limit_order_id_type trigger_swan(share_type amount1, share_type amount2) {
        set_expiration( db, trx );
        // starting out with price 1:1
        set_feed( 1, 1 );
        // start out with 2:1 collateral
        borrow(borrower(), swan().amount(amount1), back().amount(2*amount1));
        borrow(borrower2(), swan().amount(amount2), back().amount(4*amount2));

        FC_ASSERT( get_balance(borrower(),  swan()) == amount1 );
        FC_ASSERT( get_balance(borrower2(), swan()) == amount2 );
        FC_ASSERT( get_balance(borrower() , back()) == init_balance - 2*amount1 );
        FC_ASSERT( get_balance(borrower2(), back()) == init_balance - 4*amount2 );

        set_feed( 1, 2 );
        // this sell order is designed to trigger a black swan
        limit_order_id_type oid = create_sell_order( borrower2(), swan().amount(1), back().amount(3) )->id;

        FC_ASSERT( get_balance(borrower(),  swan()) == amount1 );
        FC_ASSERT( get_balance(borrower2(), swan()) == amount2 - 1 );
        FC_ASSERT( get_balance(borrower() , back()) == init_balance - 2*amount1 );
        FC_ASSERT( get_balance(borrower2(), back()) == init_balance - 2*amount2 );

        BOOST_CHECK( swan().bitasset_data(db).has_settlement() );

        return oid;
    }
コード例 #7
0
ファイル: avl.c プロジェクト: bjornxiong/libtree
/*
 * 'pparent', 'unbalanced' and 'is_left' are only used for
 * insertions. Normally GCC will notice this and get rid of them for
 * lookups.
 */
static inline struct avltree_node *do_lookup(const struct avltree_node *key,
					     const struct avltree *tree,
					     struct avltree_node **pparent,
					     struct avltree_node **unbalanced,
					     int *is_left)
{
	struct avltree_node *node = tree->root;
	int res = 0;

	*pparent = NULL;
	*unbalanced = node;
	*is_left = 0;

	while (node) {
		if (get_balance(node) != 0)
			*unbalanced = node;

		res = tree->cmp_fn(node, key);
		if (res == 0)
			return node;
		*pparent = node;
		if ((*is_left = res > 0))
			node = node->left;
		else
			node = node->right;
	}
	return NULL;
}
コード例 #8
0
ファイル: fw_avltree.c プロジェクト: BMNLabs/snort
static inline struct FwAvlNode* do_lookup(const uint32_t key,
        const struct FwAvlTree* tree, struct FwAvlNode** pparent,
        struct FwAvlNode** unbalanced, int* is_left)
{
    struct FwAvlNode* node = tree->root;

    *pparent = NULL;
    *unbalanced = node;
    *is_left = 0;

    while (node != NULL)
    {
        if(get_balance(node) != 0)
        {
            *unbalanced = node;
        }

        *pparent = node;

        if(key == node->key)
        {
            return node;
        }
        else
        {
            if((*is_left = node->key > key) != 0)
                node = node->left;
            else
                node = node->right;
        }
    }
    return NULL;
}
コード例 #9
0
int cx25840_audio_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
{
	struct i2c_client *client = v4l2_get_subdevdata(sd);

	switch (ctrl->id) {
	case V4L2_CID_AUDIO_VOLUME:
		ctrl->value = get_volume(client);
		break;
	case V4L2_CID_AUDIO_BASS:
		ctrl->value = get_bass(client);
		break;
	case V4L2_CID_AUDIO_TREBLE:
		ctrl->value = get_treble(client);
		break;
	case V4L2_CID_AUDIO_BALANCE:
		ctrl->value = get_balance(client);
		break;
	case V4L2_CID_AUDIO_MUTE:
		ctrl->value = get_mute(client);
		break;
	default:
		return -EINVAL;
	}
	return 0;
}
コード例 #10
0
ファイル: scaler.cpp プロジェクト: GallagherCommaJack/lean
template <typename T, typename X>    bool scaler<T, X>::scale_with_log_balance() {
    T balance = get_balance();
    T balance_before_scaling = balance;
    // todo : analyze the scale order : rows-columns, or columns-rows. Iterate if needed
    for (int i = 0; i < 10; i++) {
        scale_rows();
        scale_columns();
        T nb = get_balance();
        if (nb < T(0.9) * balance) {
            balance = nb;
        } else {
            balance = nb;
            break;
        }
    }
    return balance <= balance_before_scaling;
}
コード例 #11
0
uint64_t database_fixture::fund(
   const account_object& account,
   const asset& amount /* = asset(500000) */
   )
{
   transfer(account_id_type()(db), account, amount);
   return get_balance(account, amount.asset_id(db));
}
コード例 #12
0
int cx25840_audio(struct i2c_client *client, unsigned int cmd, void *arg)
{
	struct v4l2_control *ctrl = arg;

	switch (cmd) {
	case VIDIOC_INT_AUDIO_CLOCK_FREQ:
		return set_audclk_freq(client, *(u32 *)arg);

	case VIDIOC_G_CTRL:
		switch (ctrl->id) {
		case V4L2_CID_AUDIO_VOLUME:
			ctrl->value = get_volume(client);
			break;
		case V4L2_CID_AUDIO_BASS:
			ctrl->value = get_bass(client);
			break;
		case V4L2_CID_AUDIO_TREBLE:
			ctrl->value = get_treble(client);
			break;
		case V4L2_CID_AUDIO_BALANCE:
			ctrl->value = get_balance(client);
			break;
		case V4L2_CID_AUDIO_MUTE:
			ctrl->value = get_mute(client);
			break;
		default:
			return -EINVAL;
		}
		break;

	case VIDIOC_S_CTRL:
		switch (ctrl->id) {
		case V4L2_CID_AUDIO_VOLUME:
			set_volume(client, ctrl->value);
			break;
		case V4L2_CID_AUDIO_BASS:
			set_bass(client, ctrl->value);
			break;
		case V4L2_CID_AUDIO_TREBLE:
			set_treble(client, ctrl->value);
			break;
		case V4L2_CID_AUDIO_BALANCE:
			set_balance(client, ctrl->value);
			break;
		case V4L2_CID_AUDIO_MUTE:
			set_mute(client, ctrl->value);
			break;
		default:
			return -EINVAL;
		}
		break;

	default:
		return -EINVAL;
	}

	return 0;
}
コード例 #13
0
ファイル: AVLtree_height.c プロジェクト: kimhoki/BIT
NODE *balance_tree(NODE **node){
	int height_diff;
	height_diff = get_balance(*node);
	printf("밸런스 값 : %d\n", height_diff);
	if(height_diff > 1){
		if(get_balance((*node)->left) > 0)
			*node = rotate_LL(node);
		else
			*node = rotate_LR(node);
	}

	else if(height_diff <-1){
		if(get_balance((*node)->left) >0)
			*node = rotate_RR(node);
		else
			*node = rotate_RL(node);

	}
	return *node;
}	
コード例 #14
0
ファイル: avl3.c プロジェクト: hardfist/geeksforgeeks
node *fixup(node *root)
{
  int balance = get_balance(root);
  if(balance >1 && get_balance(root->left)>=0)
  {
    return right_rotate(root);
  }
  if(balance >1 && get_balance(root->left)<0)
  {
    root->left = left_rotate(root->left);
    return right_rotate(root);
  }
  if(balance < -1 && get_balance(root->right)<=0)
  {
    return left_rotate(root);
  }
  if(balance < -1 && get_balance(root->right)>0)
  {
    root->right = right_rotate(root->right);
    return left_rotate(root);
  }
  return root;
}
コード例 #15
0
ファイル: AVLtree_height.c プロジェクト: kimhoki/BIT
int main(){
	NODE *node = 0;
	int i;
	int height;
	int in;
	NODE *temp = 0;

	int a[] = {6,3,1,5,7,12};
	display(root);
	for(i=0; i<6; i++){
		insert_data(a[i]);
		display(root);
	}
	insert_data(9);
	display(root);
	printf("Tree height test\n");
	getchar();

	//height = get_height(root);
	//printf("root height : %d\n", height);
	
/*	while(1){
		printf("input the node data(exit -1):");
		scanf("%d",&in));
		if(in == -1){
			printf("exit\n");
			break;
		}	
		temp->data = in;
		height = get_height(temp);
		printf("%d의 높이: %d\n", temp->data, height);
		temp = 0;
		height = 0;
	}*/
	while(1){
		printf("input the node data(exit -1) : ");
		scanf("%d", &in);
		fflush(stdin);
		if(in==-1) break;
		node = search(root, in);
		height = get_height(node);
		printf("%d의 높이는 %d\n", in, height);
		height = get_balance(node);
		printf("%d의 밸런스 값 : %d\n", in ,height);
		getchar();
	}
	return 0;	
}
コード例 #16
0
static switch_status_t process_hangup(switch_core_session_t *session)
{
	const char* billaccount;
	switch_channel_t *channel = NULL;

	channel = switch_core_session_get_channel(session);
	
	/* Resume any paused billings, just in case */
	/*  nibblebill_resume(session); */

	/* Now go handle like normal billing */
	do_billing(session);

	billaccount = switch_channel_get_variable(channel, "nibble_account");
	if (billaccount) {
		switch_channel_set_variable_printf(channel, "nibble_current_balance", "%f", get_balance(billaccount, channel));
	}			
	
	return SWITCH_STATUS_SUCCESS;
}
コード例 #17
0
int cx18_av_audio_g_ctrl(struct cx18 *cx, struct v4l2_control *ctrl)
{
	switch (ctrl->id) {
	case V4L2_CID_AUDIO_VOLUME:
		ctrl->value = get_volume(cx);
		break;
	case V4L2_CID_AUDIO_BASS:
		ctrl->value = get_bass(cx);
		break;
	case V4L2_CID_AUDIO_TREBLE:
		ctrl->value = get_treble(cx);
		break;
	case V4L2_CID_AUDIO_BALANCE:
		ctrl->value = get_balance(cx);
		break;
	case V4L2_CID_AUDIO_MUTE:
		ctrl->value = get_mute(cx);
		break;
	default:
		return -EINVAL;
	}
	return 0;
}
コード例 #18
0
ファイル: listing_c.7.cpp プロジェクト: jasonblog/note
 void wait_for_action()
 {
     interface_hardware.send(display_withdrawal_options());
     incoming.wait()
     .handle<withdraw_pressed>(
     [&](withdraw_pressed const & msg) {
         withdrawal_amount = msg.amount;
         bank.send(withdraw(account, msg.amount, incoming));
         state = &atm::process_withdrawal;
     }
     )
     .handle<balance_pressed>(
     [&](balance_pressed const & msg) {
         bank.send(get_balance(account, incoming));
         state = &atm::process_balance;
     }
     )
     .handle<cancel_pressed>(
     [&](cancel_pressed const & msg) {
         state = &atm::done_processing;
     }
     );
 }
コード例 #19
0
ファイル: avl_tree.c プロジェクト: vshan/DSA-Stuff
node insert(node n, int e) {
  if (!n)
    return new_Node(e);

  if (e < n->element)
    n->left = insert(n->left, e);
  else
    n->right = insert(n->right, e);

  n->height = max(height(n->left), height(n->right)) + 1;

  int balance = get_balance(n);

  // Left-Left case
  if (balance > 1 && e < n->left->element)
    return right_rotate(n);

  // Left-Right case
  if (balance > 1 && e > n->left->element) {
    n->left = left_rotate(n->left);
    return right_rotate(n);
  }

  // Right-Right case
  if (balance < -1 && e > n->right->element)
    return left_rotate(n);

  // Right-Left case
  if (balance < -1 && e < n->right->element) {
    n->right = right_rotate(n->right);
    return left_rotate(n);
  }

  return n;

}
コード例 #20
0
ファイル: avl.c プロジェクト: caizongchao/librcd
/* Insertion never needs more than 2 rotations */
struct avltree_node *avltree_insert(struct avltree_node *node, struct avltree *tree) {
    struct avltree_node *parent = 0, *unbalanced = tree->root;
    bool is_left;

    // Find a suitable parent.
    for (struct avltree_node *next_parent = tree->root; next_parent != 0;) {
        parent = next_parent;
        if (get_balance(parent) != 0)
            unbalanced = parent;
        int cmp_r = tree->cmp_fn(parent, node);
        if (cmp_r == 0) {
            if (tree->unique_index)
                return parent;
            // For non unique indexes any insert direction is acceptable.
            if (parent->left == 0) {
                is_left = true;
                break;
            } else if (parent->right == 0) {
                is_left = false;
                break;
            } else {
                // Be smart and travel to the least balanced subtree to minimize balancing overhead.
                next_parent = (get_balance(parent) <= 0)? parent->left: parent->right;
            }
        } else {
            is_left = (cmp_r > 0);
            next_parent = is_left? parent->left: parent->right;
        }
    }

    INIT_NODE(node);

    if (!parent) {
        tree->root = node;
        tree->first = tree->last = node;
        tree->height++;
        return 0;
    }
    if (is_left) {
        if (parent == tree->first)
            tree->first = node;
    } else {
        if (parent == tree->last)
            tree->last = node;
    }
    set_parent(parent, node);
    set_child(node, parent, is_left);

    for (;;) {
        if (parent->left == node)
            dec_balance(parent);
        else
            inc_balance(parent);

        if (parent == unbalanced) {
            for (;;) {
                node = parent;
                node->count++;
                if (is_root(node))
                    break;
                parent = get_parent(parent);
            }
            break;
        }
        node = parent;
        node->count++;
        parent = get_parent(parent);
    }

    switch (get_balance(unbalanced)) {
        case 1: case -1:
            tree->height++;
            /* fall through */
        case 0:
            break;
        case 2:
        {
            struct avltree_node *right = unbalanced->right;

            if (get_balance(right) == 1) {
                set_balance(0, unbalanced);
                set_balance(0, right);
            } else {
                switch (get_balance(right->left)) {
                    case 1:
                        set_balance(-1, unbalanced);
                        set_balance(0, right);
                        break;
                    case 0:
                        set_balance(0, unbalanced);
                        set_balance(0, right);
                        break;
                    case -1:
                        set_balance(0, unbalanced);
                        set_balance(1, right);
                        break;
                }
                set_balance(0, right->left);

                rotate_right(right, tree);
            }
            rotate_left(unbalanced, tree);
            break;
        }
        case -2:
        {
            struct avltree_node *left = unbalanced->left;

            if (get_balance(left) == -1) {
                set_balance(0, unbalanced);
                set_balance(0, left);
            } else {
                switch (get_balance(left->right)) {
                    case 1:
                        set_balance(0, unbalanced);
                        set_balance(-1, left);
                        break;
                    case 0:
                        set_balance(0, unbalanced);
                        set_balance(0, left);
                        break;
                    case -1:
                        set_balance(1, unbalanced);
                        set_balance(0, left);
                        break;
                }
                set_balance(0, left->right);

                rotate_left(left, tree);
            }
            rotate_right(unbalanced, tree);
            break;
        }
    }
    return 0;
}
コード例 #21
0
/*
**Insert node in the binary tree whose root is root. The innsertion is made 
to create an AVL binary tree.
**Returns 1 if the word was inserted or 0 if the word already existed.
*/
int insert_word(AVL_Node *&root, string word, string translation) {
    if(root == NULL) {
        root = new_node(word, translation, NULL);
        return 1;
    }

    AVL_Node *aux = root;

    while(1) {
        int comparison = word.compare(aux->word);
        if(comparison < 0) {
            if(aux->son_left == NULL) {
                //insert new node to the left of the subtree
                aux->son_left = new_node(word, translation, aux);
                break;
            }
            aux = aux->son_left;
        }
        else if(comparison > 0) {
            if(aux->son_right == NULL) {
                //insert new node to the right of the subtree
                aux->son_right = new_node(word, translation, aux); 
                break;
            }
            aux = aux->son_right;
        }
        else {
            //There's a node with that word
            return 0;
        }
    }

    //Go up the tree and correct the heights. If the height is changed then check
    //if rebalance is needed. Notice that aux begins in the parent of the new node
    while(aux != NULL) {
        update_height(aux);
        int balance = get_balance(aux);
        if(balance == 2) {
            if(get_balance(aux->son_right) == -1) {
                rotate_right(aux->son_right);//Double rotation
            }
            rotate_left(aux);
            if(aux == root) {
                //Updates the root of the tree if it shifts
                root = aux->parent;
            }
        }
        else if(balance == -2) {
            if(get_balance(aux->son_left) == 1) {
                rotate_left(aux->son_left);//Double rotation
            }
            rotate_right(aux);
            if(aux == root) {
                //Updates the root of the tree if it shifts
                root = aux->parent;
            }
        }
        aux = aux->parent;
    }
    return 1;
}
コード例 #22
0
ファイル: db_init.cpp プロジェクト: clar/graphene
void database::init_genesis(const genesis_state_type& genesis_state)
{ try {
   FC_ASSERT( genesis_state.initial_timestamp != time_point_sec(), "Must initialize genesis timestamp." );
   FC_ASSERT( genesis_state.initial_timestamp.sec_since_epoch() % GRAPHENE_DEFAULT_BLOCK_INTERVAL == 0,
              "Genesis timestamp must be divisible by GRAPHENE_DEFAULT_BLOCK_INTERVAL." );
   FC_ASSERT(genesis_state.initial_witness_candidates.size() > 0,
             "Cannot start a chain with zero witnesses.");
   FC_ASSERT(genesis_state.initial_active_witnesses <= genesis_state.initial_witness_candidates.size(),
             "initial_active_witnesses is larger than the number of candidate witnesses.");

   _undo_db.disable();
   struct auth_inhibitor {
      auth_inhibitor(database& db) : db(db), old_flags(db.node_properties().skip_flags)
      { db.node_properties().skip_flags |= skip_authority_check; }
      ~auth_inhibitor()
      { db.node_properties().skip_flags = old_flags; }
   private:
      database& db;
      uint32_t old_flags;
   } inhibitor(*this);

   transaction_evaluation_state genesis_eval_state(this);

   flat_index<block_summary_object>& bsi = get_mutable_index_type< flat_index<block_summary_object> >();
   bsi.resize(0xffff+1);

   // Create blockchain accounts
   fc::ecc::private_key null_private_key = fc::ecc::private_key::regenerate(fc::sha256::hash(string("null_key")));
   create<account_balance_object>([](account_balance_object& b) {
      b.balance = GRAPHENE_MAX_SHARE_SUPPLY;
   });
   const account_object& committee_account =
      create<account_object>( [&](account_object& n) {
         n.membership_expiration_date = time_point_sec::maximum();
         n.network_fee_percentage = GRAPHENE_DEFAULT_NETWORK_PERCENT_OF_FEE;
         n.lifetime_referrer_fee_percentage = GRAPHENE_100_PERCENT - GRAPHENE_DEFAULT_NETWORK_PERCENT_OF_FEE;
         n.owner.weight_threshold = 1;
         n.active.weight_threshold = 1;
         n.name = "committee-account";
         n.statistics = create<account_statistics_object>( [&](account_statistics_object& s){ s.owner = n.id; }).id;
      });
   FC_ASSERT(committee_account.get_id() == GRAPHENE_COMMITTEE_ACCOUNT);
   FC_ASSERT(create<account_object>([this](account_object& a) {
       a.name = "witness-account";
       a.statistics = create<account_statistics_object>([&](account_statistics_object& s){s.owner = a.id;}).id;
       a.owner.weight_threshold = 1;
       a.active.weight_threshold = 1;
       a.registrar = a.lifetime_referrer = a.referrer = GRAPHENE_WITNESS_ACCOUNT;
       a.membership_expiration_date = time_point_sec::maximum();
       a.network_fee_percentage = GRAPHENE_DEFAULT_NETWORK_PERCENT_OF_FEE;
       a.lifetime_referrer_fee_percentage = GRAPHENE_100_PERCENT - GRAPHENE_DEFAULT_NETWORK_PERCENT_OF_FEE;
   }).get_id() == GRAPHENE_WITNESS_ACCOUNT);
   FC_ASSERT(create<account_object>([this](account_object& a) {
       a.name = "relaxed-committee-account";
       a.statistics = create<account_statistics_object>([&](account_statistics_object& s){s.owner = a.id;}).id;
       a.owner.weight_threshold = 1;
       a.active.weight_threshold = 1;
       a.registrar = a.lifetime_referrer = a.referrer = GRAPHENE_RELAXED_COMMITTEE_ACCOUNT;
       a.membership_expiration_date = time_point_sec::maximum();
       a.network_fee_percentage = GRAPHENE_DEFAULT_NETWORK_PERCENT_OF_FEE;
       a.lifetime_referrer_fee_percentage = GRAPHENE_100_PERCENT - GRAPHENE_DEFAULT_NETWORK_PERCENT_OF_FEE;
   }).get_id() == GRAPHENE_RELAXED_COMMITTEE_ACCOUNT);
   FC_ASSERT(create<account_object>([this](account_object& a) {
       a.name = "null-account";
       a.statistics = create<account_statistics_object>([&](account_statistics_object& s){s.owner = a.id;}).id;
       a.owner.weight_threshold = 1;
       a.active.weight_threshold = 1;
       a.registrar = a.lifetime_referrer = a.referrer = GRAPHENE_NULL_ACCOUNT;
       a.membership_expiration_date = time_point_sec::maximum();
       a.network_fee_percentage = 0;
       a.lifetime_referrer_fee_percentage = GRAPHENE_100_PERCENT;
   }).get_id() == GRAPHENE_NULL_ACCOUNT);
   FC_ASSERT(create<account_object>([this](account_object& a) {
       a.name = "temp-account";
       a.statistics = create<account_statistics_object>([&](account_statistics_object& s){s.owner = a.id;}).id;
       a.owner.weight_threshold = 0;
       a.active.weight_threshold = 0;
       a.registrar = a.lifetime_referrer = a.referrer = GRAPHENE_TEMP_ACCOUNT;
       a.membership_expiration_date = time_point_sec::maximum();
       a.network_fee_percentage = GRAPHENE_DEFAULT_NETWORK_PERCENT_OF_FEE;
       a.lifetime_referrer_fee_percentage = GRAPHENE_100_PERCENT - GRAPHENE_DEFAULT_NETWORK_PERCENT_OF_FEE;
   }).get_id() == GRAPHENE_TEMP_ACCOUNT);
   FC_ASSERT(create<account_object>([this](account_object& a) {
       a.name = "proxy-to-self";
       a.statistics = create<account_statistics_object>([&](account_statistics_object& s){s.owner = a.id;}).id;
       a.owner.weight_threshold = 1;
       a.active.weight_threshold = 1;
       a.registrar = a.lifetime_referrer = a.referrer = GRAPHENE_NULL_ACCOUNT;
       a.membership_expiration_date = time_point_sec::maximum();
       a.network_fee_percentage = 0;
       a.lifetime_referrer_fee_percentage = GRAPHENE_100_PERCENT;
   }).get_id() == GRAPHENE_PROXY_TO_SELF_ACCOUNT);

   // Create more special accounts
   while( true )
   {
      uint64_t id = get_index<account_object>().get_next_id().instance();
      if( id >= genesis_state.immutable_parameters.num_special_accounts )
         break;
      const account_object& acct = create<account_object>([&](account_object& a) {
          a.name = "special-account-" + std::to_string(id);
          a.statistics = create<account_statistics_object>([&](account_statistics_object& s){s.owner = a.id;}).id;
          a.owner.weight_threshold = 1;
          a.active.weight_threshold = 1;
          a.registrar = a.lifetime_referrer = a.referrer = id;
          a.membership_expiration_date = time_point_sec::maximum();
          a.network_fee_percentage = GRAPHENE_DEFAULT_NETWORK_PERCENT_OF_FEE;
          a.lifetime_referrer_fee_percentage = GRAPHENE_100_PERCENT - GRAPHENE_DEFAULT_NETWORK_PERCENT_OF_FEE;
      });
      FC_ASSERT( acct.get_id() == account_id_type(id) );
      remove( acct );
   }

   // Create core asset
   const asset_dynamic_data_object& dyn_asset =
      create<asset_dynamic_data_object>([&](asset_dynamic_data_object& a) {
         a.current_supply = GRAPHENE_MAX_SHARE_SUPPLY;
      });
   const asset_object& core_asset =
     create<asset_object>( [&]( asset_object& a ) {
         a.symbol = GRAPHENE_SYMBOL;
         a.options.max_supply = genesis_state.max_core_supply;
         a.precision = GRAPHENE_BLOCKCHAIN_PRECISION_DIGITS;
         a.options.flags = 0;
         a.options.issuer_permissions = 0;
         a.issuer = GRAPHENE_NULL_ACCOUNT;
         a.options.core_exchange_rate.base.amount = 1;
         a.options.core_exchange_rate.base.asset_id = 0;
         a.options.core_exchange_rate.quote.amount = 1;
         a.options.core_exchange_rate.quote.asset_id = 0;
         a.dynamic_asset_data_id = dyn_asset.id;
      });
   assert( asset_id_type(core_asset.id) == asset().asset_id );
   assert( get_balance(account_id_type(), asset_id_type()) == asset(dyn_asset.current_supply) );
   // Create more special assets
   while( true )
   {
      uint64_t id = get_index<asset_object>().get_next_id().instance();
      if( id >= genesis_state.immutable_parameters.num_special_assets )
         break;
      const asset_dynamic_data_object& dyn_asset =
         create<asset_dynamic_data_object>([&](asset_dynamic_data_object& a) {
            a.current_supply = 0;
         });
      const asset_object& asset_obj = create<asset_object>( [&]( asset_object& a ) {
         a.symbol = "SPECIAL" + std::to_string( id );
         a.options.max_supply = 0;
         a.precision = GRAPHENE_BLOCKCHAIN_PRECISION_DIGITS;
         a.options.flags = 0;
         a.options.issuer_permissions = 0;
         a.issuer = GRAPHENE_NULL_ACCOUNT;
         a.options.core_exchange_rate.base.amount = 1;
         a.options.core_exchange_rate.base.asset_id = 0;
         a.options.core_exchange_rate.quote.amount = 1;
         a.options.core_exchange_rate.quote.asset_id = 0;
         a.dynamic_asset_data_id = dyn_asset.id;
      });
      FC_ASSERT( asset_obj.get_id() == asset_id_type(id) );
      remove( asset_obj );
   }

   chain_id_type chain_id = genesis_state.compute_chain_id();

   // Create global properties
   create<global_property_object>([&](global_property_object& p) {
       p.parameters = genesis_state.initial_parameters;
       // Set fees to zero initially, so that genesis initialization needs not pay them
       // We'll fix it at the end of the function
       p.parameters.current_fees->zero_all_fees();

   });
   create<dynamic_global_property_object>([&](dynamic_global_property_object& p) {
      p.time = genesis_state.initial_timestamp;
      p.dynamic_flags = 0;
      p.witness_budget = 0;
      p.recent_slots_filled = fc::uint128::max_value();
   });

   FC_ASSERT( (genesis_state.immutable_parameters.min_witness_count & 1) == 1, "min_witness_count must be odd" );
   FC_ASSERT( (genesis_state.immutable_parameters.min_committee_member_count & 1) == 1, "min_committee_member_count must be odd" );

   create<chain_property_object>([&](chain_property_object& p)
   {
      p.chain_id = chain_id;
      p.immutable_parameters = genesis_state.immutable_parameters;
   } );
   create<block_summary_object>([&](block_summary_object&) {});

   // Create initial accounts
   for( const auto& account : genesis_state.initial_accounts )
   {
      account_create_operation cop;
      cop.name = account.name;
      cop.registrar = GRAPHENE_TEMP_ACCOUNT;
      cop.owner = authority(1, account.owner_key, 1);
      if( account.active_key == public_key_type() )
      {
         cop.active = cop.owner;
         cop.options.memo_key = account.owner_key;
      }
      else
      {
         cop.active = authority(1, account.active_key, 1);
         cop.options.memo_key = account.active_key;
      }
      account_id_type account_id(apply_operation(genesis_eval_state, cop).get<object_id_type>());

      if( account.is_lifetime_member )
      {
          account_upgrade_operation op;
          op.account_to_upgrade = account_id;
          op.upgrade_to_lifetime_member = true;
          apply_operation(genesis_eval_state, op);
      }
   }

   // Helper function to get account ID by name
   const auto& accounts_by_name = get_index_type<account_index>().indices().get<by_name>();
   auto get_account_id = [&accounts_by_name](const string& name) {
      auto itr = accounts_by_name.find(name);
      FC_ASSERT(itr != accounts_by_name.end(),
                "Unable to find account '${acct}'. Did you forget to add a record for it to initial_accounts?",
                ("acct", name));
      return itr->get_id();
   };

   // Helper function to get asset ID by symbol
   const auto& assets_by_symbol = get_index_type<asset_index>().indices().get<by_symbol>();
   const auto get_asset_id = [&assets_by_symbol](const string& symbol) {
      auto itr = assets_by_symbol.find(symbol);

      // TODO: This is temporary for handling BTS snapshot
      if( symbol == "BTS" )
          itr = assets_by_symbol.find(GRAPHENE_SYMBOL);

      FC_ASSERT(itr != assets_by_symbol.end(),
                "Unable to find asset '${sym}'. Did you forget to add a record for it to initial_assets?",
                ("sym", symbol));
      return itr->get_id();
   };

   map<asset_id_type, share_type> total_supplies;
   map<asset_id_type, share_type> total_debts;

   // Create initial assets
   for( const genesis_state_type::initial_asset_type& asset : genesis_state.initial_assets )
   {
      asset_id_type new_asset_id = get_index_type<asset_index>().get_next_id();
      total_supplies[ new_asset_id ] = 0;

      asset_dynamic_data_id_type dynamic_data_id;
      optional<asset_bitasset_data_id_type> bitasset_data_id;
      if( asset.is_bitasset )
      {
         int collateral_holder_number = 0;
         total_debts[ new_asset_id ] = 0;
         for( const auto& collateral_rec : asset.collateral_records )
         {
            account_create_operation cop;
            cop.name = asset.symbol + "-collateral-holder-" + std::to_string(collateral_holder_number);
            boost::algorithm::to_lower(cop.name);
            cop.registrar = GRAPHENE_TEMP_ACCOUNT;
            cop.owner = authority(1, collateral_rec.owner, 1);
            cop.active = cop.owner;
            account_id_type owner_account_id = apply_operation(genesis_eval_state, cop).get<object_id_type>();

            modify( owner_account_id(*this).statistics(*this), [&]( account_statistics_object& o ) {
                    o.total_core_in_orders = collateral_rec.collateral;
                    });

            create<call_order_object>([&](call_order_object& c) {
               c.borrower = owner_account_id;
               c.collateral = collateral_rec.collateral;
               c.debt = collateral_rec.debt;
               c.call_price = price::call_price(chain::asset(c.debt, new_asset_id),
                                                chain::asset(c.collateral, core_asset.id),
                                                GRAPHENE_DEFAULT_MAINTENANCE_COLLATERAL_RATIO);
            });

            total_supplies[ 0 ] += collateral_rec.collateral;
            total_debts[ new_asset_id ] += collateral_rec.debt;
            ++collateral_holder_number;
         }

         bitasset_data_id = create<asset_bitasset_data_object>([&](asset_bitasset_data_object& b) {
            b.options.short_backing_asset = core_asset.id;
            b.options.minimum_feeds = GRAPHENE_DEFAULT_MINIMUM_FEEDS;
         }).id;
      }

      dynamic_data_id = create<asset_dynamic_data_object>([&](asset_dynamic_data_object& d) {
         d.accumulated_fees = asset.accumulated_fees;
      }).id;

      total_supplies[ new_asset_id ] += asset.accumulated_fees;

      create<asset_object>([&](asset_object& a) {
         a.symbol = asset.symbol;
         a.options.description = asset.description;
         a.precision = asset.precision;
         string issuer_name = asset.issuer_name;
         a.issuer = get_account_id(issuer_name);
         a.options.max_supply = asset.max_supply;
         a.options.flags = witness_fed_asset;
         a.options.issuer_permissions = charge_market_fee | global_settle | witness_fed_asset | committee_fed_asset;
         a.dynamic_asset_data_id = dynamic_data_id;
         a.bitasset_data_id = bitasset_data_id;
      });
   }

   // Create initial balances
   share_type total_allocation;
   for( const auto& handout : genesis_state.initial_balances )
   {
      const auto asset_id = get_asset_id(handout.asset_symbol);
      create<balance_object>([&handout,&get_asset_id,total_allocation,asset_id](balance_object& b) {
         b.balance = asset(handout.amount, asset_id);
         b.owner = handout.owner;
      });

      total_supplies[ asset_id ] += handout.amount;
   }

   // Create initial vesting balances
   for( const genesis_state_type::initial_vesting_balance_type& vest : genesis_state.initial_vesting_balances )
   {
      const auto asset_id = get_asset_id(vest.asset_symbol);
      create<balance_object>([&](balance_object& b) {
         b.owner = vest.owner;
         b.balance = asset(vest.amount, asset_id);

         linear_vesting_policy policy;
         policy.begin_timestamp = vest.begin_timestamp;
         policy.vesting_cliff_seconds = 0;
         policy.vesting_duration_seconds = vest.vesting_duration_seconds;
         policy.begin_balance = vest.begin_balance;

         b.vesting_policy = std::move(policy);
      });

      total_supplies[ asset_id ] += vest.amount;
   }

   if( total_supplies[ 0 ] > 0 )
   {
       adjust_balance(GRAPHENE_COMMITTEE_ACCOUNT, -get_balance(GRAPHENE_COMMITTEE_ACCOUNT,{}));
   }
   else
   {
       total_supplies[ 0 ] = GRAPHENE_MAX_SHARE_SUPPLY;
   }

   const auto& idx = get_index_type<asset_index>().indices().get<by_symbol>();
   auto it = idx.begin();
   bool has_imbalanced_assets = false;

   while( it != idx.end() )
   {
      if( it->bitasset_data_id.valid() )
      {
         auto supply_itr = total_supplies.find( it->id );
         auto debt_itr = total_debts.find( it->id );
         FC_ASSERT( supply_itr != total_supplies.end() );
         FC_ASSERT( debt_itr != total_debts.end() );
         if( supply_itr->second != debt_itr->second )
         {
            has_imbalanced_assets = true;
            elog( "Genesis for asset ${aname} is not balanced\n"
                  "   Debt is ${debt}\n"
                  "   Supply is ${supply}\n",
                  ("debt", debt_itr->second)
                  ("supply", supply_itr->second)
                );
         }
      }
      ++it;
   }
   FC_ASSERT( !has_imbalanced_assets );

   // Save tallied supplies
   for( const auto& item : total_supplies )
   {
       const auto asset_id = item.first;
       const auto total_supply = item.second;

       modify( get( asset_id ), [ & ]( asset_object& asset ) {
           modify( get( asset.dynamic_asset_data_id ), [ & ]( asset_dynamic_data_object& asset_data ) {
               asset_data.current_supply = total_supply;
           } );
       } );
   }

   // Create special witness account
   const witness_object& wit = create<witness_object>([&](witness_object& w) {});
   FC_ASSERT( wit.id == GRAPHENE_NULL_WITNESS );
   remove(wit);

   // Create initial witnesses
   std::for_each(genesis_state.initial_witness_candidates.begin(), genesis_state.initial_witness_candidates.end(),
                 [&](const genesis_state_type::initial_witness_type& witness) {
      witness_create_operation op;
      op.witness_account = get_account_id(witness.owner_name);
      op.block_signing_key = witness.block_signing_key;
      apply_operation(genesis_eval_state, op);
   });

   // Create initial committee members
   std::for_each(genesis_state.initial_committee_candidates.begin(), genesis_state.initial_committee_candidates.end(),
                 [&](const genesis_state_type::initial_committee_member_type& member) {
      committee_member_create_operation op;
      op.committee_member_account = get_account_id(member.owner_name);
      apply_operation(genesis_eval_state, op);
   });

   // Create initial workers
   std::for_each(genesis_state.initial_worker_candidates.begin(), genesis_state.initial_worker_candidates.end(),
                  [&](const genesis_state_type::initial_worker_type& worker)
   {
       worker_create_operation op;
       op.owner = get_account_id(worker.owner_name);
       op.work_begin_date = genesis_state.initial_timestamp;
       op.work_end_date = time_point_sec::maximum();
       op.daily_pay = worker.daily_pay;
       op.name = "Genesis-Worker-" + worker.owner_name;
       op.initializer = vesting_balance_worker_initializer{uint16_t(0)};

       apply_operation(genesis_eval_state, std::move(op));
   });

   // Set active witnesses
   modify(get_global_properties(), [&](global_property_object& p) {
      for( uint32_t i = 1; i <= genesis_state.initial_active_witnesses; ++i )
      {
         p.active_witnesses.insert(i);
         p.witness_accounts.insert(get(witness_id_type(i)).witness_account);
      }
   });

   // Enable fees
   modify(get_global_properties(), [&genesis_state](global_property_object& p) {
      p.parameters.current_fees = genesis_state.initial_parameters.current_fees;
   });

   // Create witness scheduler
   create<witness_schedule_object>([&]( witness_schedule_object& wso )
   {
      for( const witness_id_type& wid : get_global_properties().active_witnesses )
         wso.current_shuffled_witnesses.push_back( wid );
   });

   debug_dump();

   _undo_db.enable();
} FC_CAPTURE_AND_RETHROW() }
コード例 #23
0
/* This is where we actually charge the guy 
  This can be called anytime a call is in progress or at the end of a call before the session is destroyed */
static switch_status_t do_billing(switch_core_session_t *session)
{
	/* FS vars we will use */
	switch_channel_t *channel;
	switch_caller_profile_t *profile;

	/* Local vars */
	nibble_data_t *nibble_data;
	switch_time_t ts = switch_micro_time_now();
	double billamount;
	char date[80] = "";
	char *uuid;
	switch_size_t retsize;
	switch_time_exp_t tm;
	const char *billrate;
	const char *billincrement;
	const char *billaccount;
	double nobal_amt = globals.nobal_amt;
	double lowbal_amt = globals.lowbal_amt;
	double balance;

	if (!session) {
		/* Why are we here? */
		return SWITCH_STATUS_SUCCESS;
	}

	uuid = switch_core_session_get_uuid(session);

	/* Get channel var */
	if (!(channel = switch_core_session_get_channel(session))) {
		return SWITCH_STATUS_SUCCESS;
	}

	/* Variables kept in FS but relevant only to this module */
	billrate = switch_channel_get_variable(channel, "nibble_rate");
	billincrement = switch_channel_get_variable(channel, "nibble_increment");
	billaccount = switch_channel_get_variable(channel, "nibble_account");
	
	if (!zstr(switch_channel_get_variable(channel, "nobal_amt"))) {
		nobal_amt = atof(switch_channel_get_variable(channel, "nobal_amt"));
	}
	
	if (!zstr(switch_channel_get_variable(channel, "lowbal_amt"))) {
		lowbal_amt = atof(switch_channel_get_variable(channel, "lowbal_amt"));
	}
	
	/* Return if there's no billing information on this session */
	if (!billrate || !billaccount) {
		return SWITCH_STATUS_SUCCESS;
	}

	switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Attempting to bill at $%s per minute to account %s\n", billrate,
					  billaccount);

	/* Get caller profile info from channel */
	profile = switch_channel_get_caller_profile(channel);

	if (!profile || !profile->times) {
		/* No caller profile (why would this happen?) */
		return SWITCH_STATUS_SUCCESS;
	}

	if (profile->times->answered < 1) {
		switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Not billing %s - call is not in answered state\n", billaccount);

		/* See if this person has enough money left to continue the call */
		balance = get_balance(billaccount, channel);
		switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Comparing %f to hangup balance of %f\n", balance, nobal_amt);
		if (balance <= nobal_amt) {
			/* Not enough money - reroute call to nobal location */
			switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Balance of %f fell below allowed amount of %f! (Account %s)\n",
							  balance, nobal_amt, billaccount);

			transfer_call(session, globals.nobal_action);
		}

		return SWITCH_STATUS_SUCCESS;
	}

	/* Lock this session's data for this module while we tinker with it */
	if (globals.mutex) {
		switch_mutex_lock(globals.mutex);
	}

	/* Get our nibble data var. This will be NULL if it's our first call here for this session */
	nibble_data = (nibble_data_t *) switch_channel_get_private(channel, "_nibble_data_");

	/* Are we in paused mode? If so, we don't do anything here - go back! */
	if (nibble_data && (nibble_data->pausets > 0)) {
		if (globals.mutex) {
			switch_mutex_unlock(globals.mutex);
		}
		switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Received heartbeat, but we're paused - ignoring\n");
		return SWITCH_STATUS_SUCCESS;
	}

	/* Have we done any billing on this channel yet? If no, set up vars for doing so */
	if (!nibble_data) {
		nibble_data = switch_core_session_alloc(session, sizeof(*nibble_data));
		memset(nibble_data, 0, sizeof(*nibble_data));

		/* Setup new billing data (based on call answer time, in case this module started late with active calls) */
		nibble_data->lastts = profile->times->answered;	/* Set the initial answer time to match when the call was really answered */
		switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_INFO, "Beginning new billing on %s\n", uuid);
	}

	switch_time_exp_lt(&tm, nibble_data->lastts);
	switch_strftime_nocheck(date, &retsize, sizeof(date), "%Y-%m-%d %T", &tm);

	switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "%d seconds passed since last bill time of %s\n",
					  (int) ((ts - nibble_data->lastts) / 1000000), date);

	if ((ts - nibble_data->lastts) >= 0) {
		/* If billincrement is set we bill by it and not by time elapsed */
		if (!(switch_strlen_zero(billincrement))) {
			switch_time_t chargedunits = (ts - nibble_data->lastts) / 1000000 <= atol(billincrement) ? atol(billincrement) * 1000000 : (switch_time_t)(ceil((ts - nibble_data->lastts) / (atol(billincrement) * 1000000.0))) * atol(billincrement) * 1000000;
			billamount = (atof(billrate) / 1000000 / 60) * chargedunits - nibble_data->bill_adjustments;
			/* Account for the prepaid amount */
			nibble_data->lastts += chargedunits;
		} else {		
			/* Convert billrate into microseconds and multiply by # of microseconds that have passed since last *successful* bill */
			billamount = (atof(billrate) / 1000000 / 60) * ((ts - nibble_data->lastts)) - nibble_data->bill_adjustments;
			/* Update the last time we billed */
			nibble_data->lastts = ts;
		}

		switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Billing $%f to %s (Call: %s / %f so far)\n", billamount, billaccount,
						  uuid, nibble_data->total);

		/* DO ODBC BILLING HERE and reset counters if it's successful! */
		if (bill_event(billamount, billaccount, channel) == SWITCH_STATUS_SUCCESS) {
			/* Increment total cost */
			nibble_data->total += billamount;

			/* Reset manual billing adjustments from pausing */
			nibble_data->bill_adjustments = 0;

			/* Update channel variable with current billing */
			switch_channel_set_variable_printf(channel, "nibble_total_billed", "%f", nibble_data->total);
		} else {
			switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_CRIT, "Failed to log to database!\n");
		}
	} else {
		if (switch_strlen_zero(billincrement))
			switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_WARNING, "Just tried to bill %s negative minutes! That should be impossible.\n", uuid);
	}

	/* Save this location */
	if (channel) {
		switch_channel_set_private(channel, "_nibble_data_", nibble_data);

		/* don't verify balance and transfer to nobal if we're done with call */
		if (switch_channel_get_state(channel) != CS_REPORTING && switch_channel_get_state(channel) != CS_HANGUP) {
			
			balance = get_balance(billaccount, channel);
			
			/* See if we've achieved low balance */
			if (!nibble_data->lowbal_action_executed && balance <= lowbal_amt) {
				switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_DEBUG, "Balance of %f fell below low balance amount of %f! (Account %s)\n",
								  balance, lowbal_amt, billaccount);

				if (exec_app(session, globals.lowbal_action) != SWITCH_STATUS_SUCCESS)
					switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_ERROR, "Low balance action didn't execute\n");
				else
					nibble_data->lowbal_action_executed = 1;
			}

			/* See if this person has enough money left to continue the call */
			if (balance <= nobal_amt) {
				/* Not enough money - reroute call to nobal location */
				switch_log_printf(SWITCH_CHANNEL_SESSION_LOG(session), SWITCH_LOG_CRIT, "Balance of %f fell below allowed amount of %f! (Account %s)\n",
								  balance, nobal_amt, billaccount);

				/* IMPORTANT: Billing must be paused before the transfer occurs! This prevents infinite loops, since the transfer will result */
				/* in nibblebill checking the call again in the routing process for an allowed balance! */
				/* If you intend to give the user the option to re-up their balance, you must clear & resume billing once the balance is updated! */
				nibblebill_pause(session);
				transfer_call(session, globals.nobal_action);
			}
		}
	}


	/* Done changing - release lock */
	if (globals.mutex) {
		switch_mutex_unlock(globals.mutex);
	}

	/* Go check if this call is allowed to continue */

	return SWITCH_STATUS_SUCCESS;
}
コード例 #24
0
ファイル: db_init.cpp プロジェクト: juanfranblanco/graphene
void database::init_genesis(const genesis_allocation& initial_allocation)
{ try {
   _undo_db.disable();

   fc::ecc::private_key genesis_private_key = fc::ecc::private_key::regenerate(fc::sha256::hash(string("genesis")));
   const key_object& genesis_key =
      create<key_object>( [&genesis_private_key](key_object& k) {
         k.key_data = public_key_type(genesis_private_key.get_public_key());
      });
   const account_statistics_object& genesis_statistics =
      create<account_statistics_object>( [&](account_statistics_object& b){
      });
   create<account_balance_object>( [](account_balance_object& b) {
      b.balance = GRAPHENE_INITIAL_SUPPLY;
   });
   const account_object& genesis_account =
      create<account_object>( [&](account_object& n) {
         n.name = "genesis";
         n.owner.add_authority(genesis_key.get_id(), 1);
         n.owner.weight_threshold = 1;
         n.active = n.owner;
         n.memo_key = genesis_key.id;
         n.statistics = genesis_statistics.id;
      });

   vector<delegate_id_type> init_delegates;
   vector<witness_id_type> init_witnesses;
   flat_set<witness_id_type> init_witness_set;

   auto delegates_and_witnesses = std::max(GRAPHENE_MIN_WITNESS_COUNT, GRAPHENE_MIN_DELEGATE_COUNT);
   for( int i = 0; i < delegates_and_witnesses; ++i )
   {
      const account_statistics_object& stats_obj =
         create<account_statistics_object>( [&](account_statistics_object&){
         });
      const account_object& delegate_account =
         create<account_object>( [&](account_object& a) {
            a.active = a.owner = genesis_account.owner;
            a.name = string("init") + fc::to_string(i);
            a.statistics = stats_obj.id;
         });
      const delegate_object& init_delegate = create<delegate_object>( [&](delegate_object& d) {
         d.delegate_account = delegate_account.id;
         d.vote_id = i * 2;
      });
      init_delegates.push_back(init_delegate.id);

      const witness_object& init_witness = create<witness_object>( [&](witness_object& d) {
            d.witness_account = delegate_account.id;
            d.vote_id = i * 2 + 1;
            secret_hash_type::encoder enc;
            fc::raw::pack( enc, genesis_private_key );
            fc::raw::pack( enc, d.last_secret );
            d.next_secret = secret_hash_type::hash(enc.result());
      });
      init_witnesses.push_back(init_witness.id);
      init_witness_set.insert(init_witness.id);

   }
   create<block_summary_object>( [&](block_summary_object& p) {
   });

   const witness_schedule_object& wso =
   create<witness_schedule_object>( [&]( witness_schedule_object& _wso )
   {
      memset( _wso.rng_seed.begin(), 0, _wso.rng_seed.size() );

      witness_scheduler_rng rng( _wso.rng_seed.begin(), GRAPHENE_NEAR_SCHEDULE_CTR_IV );

      _wso.scheduler = witness_scheduler();
      _wso.scheduler._min_token_count = init_witnesses.size() / 2;
      _wso.scheduler.update( init_witness_set );

      for( int i=0; i<init_witnesses.size(); i++ )
         _wso.scheduler.produce_schedule( rng );

      _wso.last_scheduling_block = 0;
   } ) ;
   assert( wso.id == witness_schedule_id_type() );

   const global_property_object& properties =
      create<global_property_object>( [&](global_property_object& p) {
         p.active_delegates = init_delegates;
         for( const witness_id_type& wit : init_witnesses )
            p.active_witnesses.insert( wit );
         p.next_available_vote_id = delegates_and_witnesses * 2;
         p.chain_id = fc::digest(initial_allocation);
      });
   (void)properties;

   create<dynamic_global_property_object>( [&](dynamic_global_property_object& p) {
      p.time = fc::time_point_sec( GRAPHENE_GENESIS_TIMESTAMP );
      });

   const asset_dynamic_data_object& dyn_asset =
      create<asset_dynamic_data_object>( [&]( asset_dynamic_data_object& a ) {
         a.current_supply = GRAPHENE_INITIAL_SUPPLY;
      });

   const asset_object& core_asset =
     create<asset_object>( [&]( asset_object& a ) {
         a.symbol = GRAPHENE_SYMBOL;
         a.options.max_supply = GRAPHENE_INITIAL_SUPPLY;
         a.precision = GRAPHENE_BLOCKCHAIN_PRECISION_DIGITS;
         a.options.flags = 0;
         a.options.issuer_permissions = 0;
         a.issuer = genesis_account.id;
         a.options.core_exchange_rate.base.amount = 1;
         a.options.core_exchange_rate.base.asset_id = 0;
         a.options.core_exchange_rate.quote.amount = 1;
         a.options.core_exchange_rate.quote.asset_id = 0;
         a.dynamic_asset_data_id = dyn_asset.id;
      });
   assert( asset_id_type(core_asset.id) == asset().asset_id );
   assert( get_balance(account_id_type(), asset_id_type()) == asset(dyn_asset.current_supply) );
   (void)core_asset;

   if( !initial_allocation.empty() )
   {
      share_type total_allocation = 0;
      for( const auto& handout : initial_allocation )
         total_allocation += handout.second;

      auto mangle_to_name = [](const fc::static_variant<public_key_type, address>& key) {
         string addr = string(key.which() == std::decay<decltype(key)>::type::tag<address>::value? key.get<address>()
                                                                                                 : key.get<public_key_type>());
         string result = "bts";
         string key_string = string(addr).substr(sizeof(GRAPHENE_ADDRESS_PREFIX)-1);
         for( char c : key_string )
         {
            if( isupper(c) )
               result += string("-") + char(tolower(c));
            else
               result += c;
         }
         return result;
      };

      fc::time_point start_time = fc::time_point::now();

      for( const auto& handout : initial_allocation )
      {
         asset amount(handout.second);
         amount.amount = ((fc::uint128(amount.amount.value) * GRAPHENE_INITIAL_SUPPLY)/total_allocation.value).to_uint64();
         if( amount.amount == 0 )
         {
            wlog("Skipping zero allocation to ${k}", ("k", handout.first));
            continue;
         }

         signed_transaction trx;
         trx.operations.emplace_back(key_create_operation({asset(), genesis_account.id, handout.first}));
         relative_key_id_type key_id(0);
         authority account_authority(1, key_id, 1);
         account_create_operation cop;
         cop.name = mangle_to_name(handout.first);
         cop.registrar = account_id_type(1);
         cop.active = account_authority;
         cop.owner = account_authority;
         cop.memo_key = key_id;
         trx.operations.push_back(cop);
         trx.validate();
         auto ptrx = apply_transaction(trx, ~0);
         trx = signed_transaction();
         account_id_type account_id(ptrx.operation_results.back().get<object_id_type>());
         trx.operations.emplace_back(transfer_operation({  asset(),
                                                           genesis_account.id,
                                                           account_id,
                                                           amount,
                                                           memo_data()//vector<char>()
                                                        }));
         trx.validate();
         apply_transaction(trx, ~0);
      }

      asset leftovers = get_balance(account_id_type(), asset_id_type());
      if( leftovers.amount > 0 )
      {
         modify(*get_index_type<account_balance_index>().indices().get<by_balance>().find(boost::make_tuple(account_id_type(), asset_id_type())),
                [](account_balance_object& b) {
            b.adjust_balance(-b.get_balance());
         });
         modify(core_asset.dynamic_asset_data_id(*this), [&leftovers](asset_dynamic_data_object& d) {
            d.accumulated_fees += leftovers.amount;
         });
      }

      fc::microseconds duration = fc::time_point::now() - start_time;
      ilog("Finished allocating to ${n} accounts in ${t} milliseconds.",
           ("n", initial_allocation.size())("t", duration.count() / 1000));
   }

   _undo_db.enable();
} FC_LOG_AND_RETHROW() }
コード例 #25
0
ファイル: cx25840-audio.c プロジェクト: PennPanda/linux-repo
int cx25840_audio(struct i2c_client *client, unsigned int cmd, void *arg)
{
	struct cx25840_state *state = i2c_get_clientdata(client);
	struct v4l2_control *ctrl = arg;
	int retval;

	switch (cmd) {
	case VIDIOC_INT_AUDIO_CLOCK_FREQ:
		if (!state->is_cx25836)
			cx25840_and_or(client, 0x810, ~0x1, 1);
		if (state->aud_input != CX25840_AUDIO_SERIAL) {
			cx25840_and_or(client, 0x803, ~0x10, 0);
			cx25840_write(client, 0x8d3, 0x1f);
		}
		retval = set_audclk_freq(client, *(u32 *)arg);
		if (state->aud_input != CX25840_AUDIO_SERIAL) {
			cx25840_and_or(client, 0x803, ~0x10, 0x10);
		}
		if (!state->is_cx25836)
			cx25840_and_or(client, 0x810, ~0x1, 0);
		return retval;

	case VIDIOC_G_CTRL:
		switch (ctrl->id) {
		case V4L2_CID_AUDIO_VOLUME:
			ctrl->value = get_volume(client);
			break;
		case V4L2_CID_AUDIO_BASS:
			ctrl->value = get_bass(client);
			break;
		case V4L2_CID_AUDIO_TREBLE:
			ctrl->value = get_treble(client);
			break;
		case V4L2_CID_AUDIO_BALANCE:
			ctrl->value = get_balance(client);
			break;
		case V4L2_CID_AUDIO_MUTE:
			ctrl->value = get_mute(client);
			break;
		default:
			return -EINVAL;
		}
		break;

	case VIDIOC_S_CTRL:
		switch (ctrl->id) {
		case V4L2_CID_AUDIO_VOLUME:
			set_volume(client, ctrl->value);
			break;
		case V4L2_CID_AUDIO_BASS:
			set_bass(client, ctrl->value);
			break;
		case V4L2_CID_AUDIO_TREBLE:
			set_treble(client, ctrl->value);
			break;
		case V4L2_CID_AUDIO_BALANCE:
			set_balance(client, ctrl->value);
			break;
		case V4L2_CID_AUDIO_MUTE:
			set_mute(client, ctrl->value);
			break;
		default:
			return -EINVAL;
		}
		break;

	default:
		return -EINVAL;
	}

	return 0;
}
コード例 #26
0
ファイル: avl.c プロジェクト: bjornxiong/libtree
/* Deletion might require up to log(n) rotations */
void avltree_remove(struct avltree_node *node, struct avltree *tree)
{
	struct avltree_node *parent = get_parent(node);
	struct avltree_node *left = node->left;
	struct avltree_node *right = node->right;
	struct avltree_node *next;
	int is_left = is_left;

	if (node == tree->first)
		tree->first = avltree_next(node);
	if (node == tree->last)
		tree->last = avltree_prev(node);

	if (!left)
		next = right;
	else if (!right)
		next = left;
	else
		next = get_first(right);

	if (parent) {
		is_left = parent->left == node;
		set_child(next, parent, is_left);
	} else
		tree->root = next;

	if (left && right) {
		set_balance(get_balance(node), next);

		next->left = left;
		set_parent(next, left);

		if (next != right) {
			parent = get_parent(next);
			set_parent(get_parent(node), next);

			node = next->right;
			parent->left = node;
			is_left = 1;

			next->right = right;
			set_parent(next, right);
		} else {
			set_parent(parent, next);
			parent = next;
			node = parent->right;
			is_left = 0;
		}
		assert(parent != NULL);
	} else
		node = next;

	if (node)
		set_parent(parent, node);

	/*
	 * At this point, 'parent' can only be null, if 'node' is the
	 * tree's root and has at most one child.
	 *
	 * case 1: the subtree is now balanced but its height has
	 * decreased.
	 *
	 * case 2: the subtree is mostly balanced and its height is
	 * unchanged.
	 *
	 * case 3: the subtree is unbalanced and its height may have
	 * been changed during the rebalancing process, see below.
	 *
	 * case 3.1: after a left rotation, the subtree becomes mostly
	 * balanced and its height is unchanged.
	 *
	 * case 3.2: after a left rotation, the subtree becomes
	 * balanced but its height has decreased.
	 *
	 * case 3.3: after a left and a right rotation, the subtree
	 * becomes balanced or mostly balanced but its height has
	 * decreased for all cases.
	 */
	while (parent) {
		int balance;
		node   = parent;
		parent = get_parent(parent);

		if (is_left) {
			is_left = parent && parent->left == node;

			balance = inc_balance(node);
			if (balance == 0)		/* case 1 */
				continue;
			if (balance == 1)		/* case 2 */
				return;
			right = node->right;		/* case 3 */
			switch (get_balance(right)) {
			case 0:				/* case 3.1 */
				set_balance( 1, node);
				set_balance(-1, right);
				rotate_left(node, tree);
				return;
			case 1:				/* case 3.2 */
				set_balance(0, node);
				set_balance(0, right);
				break;
			case -1:			/* case 3.3 */
				switch (get_balance(right->left)) {
				case 1:
					set_balance(-1, node);
					set_balance( 0, right);
					break;
				case 0:
					set_balance(0, node);
					set_balance(0, right);
					break;
				case -1:
					set_balance(0, node);
					set_balance(1, right);
					break;
				}
				set_balance(0, right->left);

				rotate_right(right, tree);
			}
			rotate_left(node, tree);
		} else {
			is_left = parent && parent->left == node;

			balance = dec_balance(node);
			if (balance == 0)
				continue;
			if (balance == -1)
				return;
			left = node->left;
			switch (get_balance(left)) {
			case 0:
				set_balance(-1, node);
				set_balance(1, left);
				rotate_right(node, tree);
				return;
			case -1:
				set_balance(0, node);
				set_balance(0, left);
				break;
			case 1:
				switch (get_balance(left->right)) {
				case 1:
					set_balance(0, node);
					set_balance(-1, left);
					break;
				case 0:
					set_balance(0, node);
					set_balance(0, left);
					break;
				case -1:
					set_balance(1, node);
					set_balance(0, left);
					break;
				}
				set_balance(0, left->right);

				rotate_left(left, tree);
			}
			rotate_right(node, tree);
		}
	}
	tree->height--;
}
コード例 #27
0
ファイル: main.c プロジェクト: hanshenrik/dbank-server
int main(int argc, char **argv) {
  // MPI variables
  int my_rank, NP;
  int source, dest;
  int tag;
  int length;
  char name[MPI_MAX_PROCESSOR_NAME + 1];
  char message[MESSAGE_SIZE];
  MPI_Status status;
  
  MPI_Init(&argc, &argv); // argc and argv passed by address to all MPI processes
  MPI_Comm_rank(MPI_COMM_WORLD, &my_rank); // returns taskID = rank of calling process
  MPI_Comm_size(MPI_COMM_WORLD, &NP); // returns total no of MPI processes available

  if (my_rank == MASTER) { // Head Office (master)
    // Print startup info
    printf("HO: started\n");
    MPI_Get_processor_name(name, &length);
    printf("HO: name = %s, my_rank = %d\n", name, my_rank);

    // Socket stuff
    int socket_descriptor, client_sock, c, *new_sock;
    struct sockaddr_in server, client;
    void *thread_status = 0;
    
    // Create socket
    socket_descriptor = socket(AF_INET, SOCK_STREAM, 0);
    if (socket_descriptor == -1) {
      printf("HO: Could not create socket");
    }
    puts("HO: Socket created");
    
    // Prepare sockaddr_in structure
    server.sin_family = AF_INET;
    server.sin_addr.s_addr = INADDR_ANY;
    server.sin_port = htons( PORT_NUMBER );
    
    // Bind
    if ( bind(socket_descriptor, (struct sockaddr *)&server, sizeof(server)) < 0 ) {
      perror("HO: Socket bind failed. Error");
      return 1;
    }
    puts("HO: Socket bind done");
    
    // Listen for new requests
    listen(socket_descriptor, MAX_CONN_REQ_IN_QUEUE);
    puts("HO: Waiting for incoming connections...");
    
    // Accept incoming connection
    c = sizeof(struct sockaddr_in);
    while ( (client_sock = accept(socket_descriptor, (struct sockaddr *)&client, (socklen_t*)&c)) ) {
      puts("HO: Connection accepted!");
      
      pthread_t sniffer_thread;
      new_sock = malloc(1);
      *new_sock = client_sock;
      
      // Start a new thread with connection_handler
      if ( pthread_create(&sniffer_thread, NULL, connection_handler, (void*) new_sock) < 0) {
        perror("HO: Could not create thread");
        return 1;
      }
      
      // Join the thread, so that MASTER doesn't terminate before the thread
      pthread_join(sniffer_thread, &thread_status);

      if (thread_status == 42) {
        printf("HO: Killing signal sent, shutdown system!\n");
        // What to do here?
        // MPI_Abort?
        // MPI_Finalize?
        // break should get us down to MPI_Finalize and return 0, but doesn't work..
        break;
      }
      puts("HO: Socket handler thread exited");
    }
     
    if (client_sock < 0) {
      perror("HO: Connection accept failed");
      return 1;
    }
    
    // for (source = 1; source < NP; source++) {
    //   MPI_Recv(message, MESSAGE_SIZE, MPI_CHAR, MPI_ANY_SOURCE, tag, MPI_COMM_WORLD, &status);
    //   printf("HO received: %s\n", message);
    // }
  }

  else { // Branch Office (slave)
    // Branch variables
    pid_t pid = 0;
    int account_status = 0, wpid;

    // sqlite3 variables
    sqlite3 *db;
    int rc;
    char query[QUERY_SIZE];

    MPI_Get_processor_name(name, &length);
    printf("BO %d: starting on name = %s\n", my_rank, name);

    // Get the number of accounts to start from DB 
    rc = sqlite3_open_v2("accounts.db", &db, SQLITE_OPEN_READONLY, NULL);

    if (rc) {
      fprintf(stderr, "BO %d: Can't open database: %s\n", my_rank, sqlite3_errmsg(db));
      sqlite3_close(db);
      return(1);
    }

    // Find all account ids for this branch
    sqlite3_stmt *statement;
    sprintf(query, "SELECT id, balance FROM accounts WHERE branch = %d", my_rank);
    sqlite3_prepare_v2(db, query, strlen(query) + 1, &statement, NULL);
    
    // For each account, start a new process
    while (1) {
      int row = sqlite3_step(statement);
      if (row == SQLITE_ROW) {
        int account_id;
        account_id = sqlite3_column_int(statement, 0);
        balance = sqlite3_column_double(statement, 1);
        pid = fork();

        if (pid < 0 ) {
          printf("BO %d: pid < 0, fork failed!\n", my_rank);
          continue;
        }

        if (pid == 0) { // Inside bank account process
          printf("BO %d: account_id = %d, balance = %f\n", my_rank, account_id, balance);
          // RPC
          // printf("BO %d_%d: before execl", my_rank, account_id);
          // execl("rpc/accounts/account_server", "account_server", (char*)NULL);
          // printf("BO %d_%d: after execl", my_rank, account_id);
          //
          return 0;
        } else {
          printf("BO %d: created pid = %d\n", my_rank, pid);
        }
      } else if (row == SQLITE_DONE) {
        printf("BO %d: Done creating account processes.\n", my_rank);
        break;
      } else {
        fprintf(stderr, "BO : sqlite row failed..\n");
        return 1;
      }
    }
    sqlite3_finalize(statement);
    sqlite3_close(db);

    // Let Head Office know Branch up and is running
    // sprintf(message, "Branch %d successfully started on processor %s", my_rank, name);
    // MPI_Send(message, strlen(message) + 1, MPI_CHAR, MASTER, tag, MPI_COMM_WORLD);

    // Wait for messages from Head Office for eternity
    while (1) {
      printf("BO %d waiting for MPI_Recv again\n", my_rank);
      MPI_Recv(message, MESSAGE_SIZE, MPI_CHAR, MASTER, MPI_ANY_TAG, MPI_COMM_WORLD, &status);
      printf("BO %d MPI_Recv from master with tag %d: %s\n", my_rank, status.MPI_TAG, message);
      
      char *token, *params[3];
      int account_id, to_account_id;
      double amount, result;
      int j = 0;
      
      // Separate message parameters
      token = strtok(message, separator);
      while (token != NULL) {
        params[j++] = token;
        token = strtok(NULL, separator);
      }

      account_id = atoi(params[0]);
      amount = atof(params[1]);
      to_account_id = atoi(params[2]);

      // Query process for account...
      // RPC not working, use DB instead
      // Operation sent as TAG, get it from status
      switch (status.MPI_TAG) {
        case GET_BALANCE_OPERATION:
          result = get_balance(account_id);
          printf("%f\n", result);
          if (result < 0) {
            sprintf(message, "Couldn't get balance...\n");
          } else {
            sprintf(message, "Balance is £%.2f\n", result);
          }
          break;
        case DEPOSIT_OPERATION:
          result = deposit(account_id, amount);
          if (result < 0) {
            sprintf(message, "Couldn't make deposit...\n");
          } else {
            sprintf(message, "New balance is £%.2f\n", result);
          }
          break;
        case WITHDRAW_OPERATION:
          result = withdraw(account_id, amount);
          if (result < 0) {
            sprintf(message, "Couldn't make withdraw...\n");
          } else {
            sprintf(message, "New balance is £%.2f\n", result);
          }
          break;
        case TRANSFER_OPERATION:
          sprintf(message, transfer(account_id, to_account_id, amount));
          break;
      }

      MPI_Send(message, MESSAGE_SIZE, MPI_CHAR, MASTER, status.MPI_TAG, MPI_COMM_WORLD);
      printf("BO %d sent: %s\n", my_rank, message);
    }

    printf("BO %d: shutting down\n", my_rank);

    // RPC
    // wait for all children to exit
    // while ( (wpid = wait(&account_status) ) > 0) {}
  }

  MPI_Finalize();
  return 0;
}
コード例 #28
0
ファイル: cx18-av-audio.c プロジェクト: E-LLP/n900
int cx18_av_audio(struct cx18 *cx, unsigned int cmd, void *arg)
{
	struct cx18_av_state *state = &cx->av_state;
	struct v4l2_control *ctrl = arg;
	int retval;

	switch (cmd) {
	case VIDIOC_INT_AUDIO_CLOCK_FREQ:
		if (state->aud_input > CX18_AV_AUDIO_SERIAL2) {
			cx18_av_and_or(cx, 0x803, ~0x10, 0);
			cx18_av_write(cx, 0x8d3, 0x1f);
		}
		cx18_av_and_or(cx, 0x810, ~0x1, 1);
		retval = set_audclk_freq(cx, *(u32 *)arg);
		cx18_av_and_or(cx, 0x810, ~0x1, 0);
		if (state->aud_input > CX18_AV_AUDIO_SERIAL2)
			cx18_av_and_or(cx, 0x803, ~0x10, 0x10);
		return retval;

	case VIDIOC_G_CTRL:
		switch (ctrl->id) {
		case V4L2_CID_AUDIO_VOLUME:
			ctrl->value = get_volume(cx);
			break;
		case V4L2_CID_AUDIO_BASS:
			ctrl->value = get_bass(cx);
			break;
		case V4L2_CID_AUDIO_TREBLE:
			ctrl->value = get_treble(cx);
			break;
		case V4L2_CID_AUDIO_BALANCE:
			ctrl->value = get_balance(cx);
			break;
		case V4L2_CID_AUDIO_MUTE:
			ctrl->value = get_mute(cx);
			break;
		default:
			return -EINVAL;
		}
		break;

	case VIDIOC_S_CTRL:
		switch (ctrl->id) {
		case V4L2_CID_AUDIO_VOLUME:
			set_volume(cx, ctrl->value);
			break;
		case V4L2_CID_AUDIO_BASS:
			set_bass(cx, ctrl->value);
			break;
		case V4L2_CID_AUDIO_TREBLE:
			set_treble(cx, ctrl->value);
			break;
		case V4L2_CID_AUDIO_BALANCE:
			set_balance(cx, ctrl->value);
			break;
		case V4L2_CID_AUDIO_MUTE:
			set_mute(cx, ctrl->value);
			break;
		default:
			return -EINVAL;
		}
		break;

	default:
		return -EINVAL;
	}

	return 0;
}
コード例 #29
0
ファイル: fw_avltree.c プロジェクト: BMNLabs/snort
int fwAvlInsert(uint32_t key, void* data, struct FwAvlTree* tree)
{
    int is_left;
    struct FwAvlNode* parent;
    struct FwAvlNode* right;
    struct FwAvlNode* left;
    struct FwAvlNode* unbalanced;
    struct FwAvlNode* node;

    if(do_lookup(key, tree, &parent, &unbalanced, &is_left) != NULL)
        return 1;

    if(!(node = new_node(key, data)))
        return -1;

    tree->count++;
    if(parent == NULL)
    {
        tree->root = node;
        tree->first = node;
        tree->last = node;
        return 0;
    }

    if(is_left != 0)
    {
        if(parent == tree->first)
            tree->first = node;
    }
    else
    {
        if(parent == tree->last)
            tree->last = node;
    }
    set_parent(parent, node);
    set_child(node, parent, is_left);

    while(1)
    {
        if(parent->left == node)
            dec_balance(parent);
        else
            inc_balance(parent);

        if(parent == unbalanced)
            break;

        node = parent;
        parent = get_parent(node);
    }

    switch(get_balance(unbalanced))
    {
        case 1:
        case -1:
            tree->height++;
            break;
        case 0:
            break;
        case 2:
            right = unbalanced->right;

            if(get_balance(right) == 1)
            {
                set_balance(0, unbalanced);
                set_balance(0, right);
            }
            else
            {
                switch(get_balance(right->left))
                {
                    case 1:
                        set_balance(-1, unbalanced);
                        set_balance(0, right);
                        break;
                    case 0:
                        set_balance(0, unbalanced);
                        set_balance(0, right);
                        break;
                    case -1:
                        set_balance(0, unbalanced);
                        set_balance(1, right);
                        break;
                }
                set_balance(0, right->left);
                rotate_right(right, tree);
            }
            rotate_left(unbalanced, tree);
            break;
        case -2:
            left = unbalanced->left;

            if(get_balance(left) == -1)
            {
                set_balance(0, unbalanced);
                set_balance(0, left);
            }
            else
            {
                switch(get_balance(left->right))
                {
                    case 1:
                        set_balance(0, unbalanced);
                        set_balance(-1, left);
                        break;
                    case 0:
                        set_balance(0, unbalanced);
                        set_balance(0, left);
                        break;
                    case -1:
                        set_balance(1, unbalanced);
                        set_balance(0, left);
                        break;
                }
                set_balance(0, left->right);
                rotate_left(left, tree);
            }
            rotate_right(unbalanced, tree);
            break;
    }
    return 0;
}
コード例 #30
0
ファイル: avl.c プロジェクト: bjornxiong/libtree
/* Insertion never needs more than 2 rotations */
struct avltree_node *avltree_insert(struct avltree_node *node, struct avltree *tree)
{
	struct avltree_node *key, *parent, *unbalanced;
	int is_left;

	key = do_lookup(node, tree, &parent, &unbalanced, &is_left);
	if (key)
		return key;

	INIT_NODE(node);

	if (!parent) {
		tree->root = node;
		tree->first = tree->last = node;
		tree->height++;
		return NULL;
	}
	if (is_left) {
		if (parent == tree->first)
			tree->first = node;
	} else {
		if (parent == tree->last)
			tree->last = node;
	}
	set_parent(parent, node);
	set_child(node, parent, is_left);

	for (;;) {
		if (parent->left == node)
			dec_balance(parent);
		else
			inc_balance(parent);

		if (parent == unbalanced)
			break;
		node = parent;
		parent = get_parent(parent);
	}

	switch (get_balance(unbalanced)) {
	case  1: case -1:
		tree->height++;
		/* fall through */
	case 0:
		break;
	case 2: {
		struct avltree_node *right = unbalanced->right;

		if (get_balance(right) == 1) {
			set_balance(0, unbalanced);
			set_balance(0, right);
		} else {
			switch (get_balance(right->left)) {
			case 1:
				set_balance(-1, unbalanced);
				set_balance( 0, right);
				break;
			case 0:
				set_balance(0, unbalanced);
				set_balance(0, right);
				break;
			case -1:
				set_balance(0, unbalanced);
				set_balance(1, right);
				break;
			}
			set_balance(0, right->left);

			rotate_right(right, tree);
		}
		rotate_left(unbalanced, tree);
		break;
	}
	case -2: {
		struct avltree_node *left = unbalanced->left;

		if (get_balance(left) == -1) {
			set_balance(0, unbalanced);
			set_balance(0, left);
		} else {
			switch (get_balance(left->right)) {
			case 1:
				set_balance( 0, unbalanced);
				set_balance(-1, left);
				break;
			case 0:
				set_balance(0, unbalanced);
				set_balance(0, left);
				break;
			case -1:
				set_balance(1, unbalanced);
				set_balance(0, left);
				break;
			}
			set_balance(0, left->right);

			rotate_left(left, tree);
		}
		rotate_right(unbalanced, tree);
		break;
	}
	}
	return NULL;
}