Exemple #1
0
/*
 * reduce a subtree into a single leaf node
 */
static void
_reduce(aguri_t *tp, anode_t *np, int depth) {
	if (depth > 0) {
		/* nodes to be deleted */
		if (np->tn_left == NULL) {
			/* leaf node */
			assert(np->tn_right == NULL);
			TAILQ_REMOVE(&tp->tr_lru, np, tn_chain);
		} else {
			/* internal node */
			assert(np->tn_right != NULL);
			_reduce(tp, np->tn_left, depth + 1);
			_reduce(tp, np->tn_right, depth + 1);
		}

		np->tn_parent->tn_count += np->tn_count;
		if (np->tn_parent->tn_left == np)
			np->tn_parent->tn_left = NULL;
		else
			np->tn_parent->tn_right = NULL;
		np->tn_intree = 0;
		TAILQ_INSERT_TAIL(&tp->tr_lru, np, tn_chain);
		tp->tr_nfree++;
		return;
	}

	/* remaining node, converted from an internal node to a leaf */
	assert(np->tn_left != NULL && np->tn_right != NULL);
	_reduce(tp, np->tn_left, depth + 1);
	_reduce(tp, np->tn_right, depth + 1);
	assert(np->tn_left == NULL && np->tn_right == NULL);
	TAILQ_INSERT_HEAD(&tp->tr_lru, np, tn_chain);
}
Exemple #2
0
        /**
         * Reduces a list of tuple object (key, value) to a single tuple {_id: key, value: val}
         * Also applies a finalizer method if present.
         */
        BSONObj JSReducer::finalReduce( const BSONList& tuples , Finalizer * finalizer ) {

            BSONObj res;
            BSONObj key;

            if (tuples.size() == 1) {
                // 1 obj, just use it
                key = tuples[0];
                BSONObjBuilder b(key.objsize());
                BSONObjIterator it(key);
                b.appendAs( it.next() , "_id" );
                b.appendAs( it.next() , "value" );
                res = b.obj();
            }
            else {
                // need to reduce
                int endSizeEstimate = 16;
                _reduce( tuples , key , endSizeEstimate );
                BSONObjBuilder b(endSizeEstimate);
                b.appendAs( key.firstElement() , "_id" );
                _func.scope()->append( b , "value" , "return" );
                res = b.obj();
            }

            if ( finalizer ) {
                res = finalizer->finalize( res );
            }

            return res;
        }
Exemple #3
0
void __init() {
    const_0 = new str("*** ERROR! *** reduce() called with empty sequence and no initial value");

    __name__ = new str("__main__");

    acc = __lambda0__;
    score = (new list<__ss_int>(4,1,2,3,4));
    print2(NULL,0,1, ___box(_reduce(acc, score, 0)));
}
Exemple #4
0
        BSONObj JSReducer::reduce( const BSONList& tuples ) {
            BSONObj key;
            int endSizeEstimate = 16;

            _reduce( tuples , key , endSizeEstimate );

            BSONObjBuilder b(endSizeEstimate);
            b.appendAs( key.firstElement() , "0" );
            _func.scope()->append( b , "1" , "return" );
            return b.obj();
        }
Exemple #5
0
        BSONObj JSReducer::reduce( const BSONList& tuples , Finalizer * finalizer ) {

            BSONObj key;
            int endSizeEstimate = 16;

            _reduce( tuples , key , endSizeEstimate );

            BSONObjBuilder b(endSizeEstimate);
            b.appendAs( key.firstElement() , "_id" );
            _func.scope()->append( b , "value" , "return" );
            BSONObj res = b.obj();

            if ( finalizer ) {
                res = finalizer->finalize( res );
            }

            return res;
        }
Exemple #6
0
void
aguri_release(aguri_t **tpp) {
	aguri_t *tp = *tpp;	
	anode_t *np = NULL;

	*tpp = NULL;

	/* first, remove nodes from the tree */
	if (tp->tr_top->tn_left != NULL)
		_reduce(tp, tp->tr_top, 0);

	/*
	 * at this point, only top is remaining in the tree,
	 * and all nodes are in the LRU list.
	 */
	assert(tp->tr_top->tn_left == NULL && tp->tr_top->tn_right == NULL);
	while ((np = TAILQ_FIRST(&tp->tr_lru)) != NULL) {
		TAILQ_REMOVE(&tp->tr_lru, np, tn_chain);
		free(np);
	}

	free(tp);
}
Exemple #7
0
        /**
         * actually applies a reduce, to a list of tuples (key, value).
         * After the call, tuples will hold a single tuple {"0": key, "1": value}
         */
        void JSReducer::_reduce( const BSONList& tuples , BSONObj& key , int& endSizeEstimate ) {
            uassert( 10074 ,  "need values" , tuples.size() );

            int sizeEstimate = ( tuples.size() * tuples.begin()->getField( "value" ).size() ) + 128;

            // need to build the reduce args: ( key, [values] )
            BSONObjBuilder reduceArgs( sizeEstimate );
            boost::scoped_ptr<BSONArrayBuilder>  valueBuilder;
            int sizeSoFar = 0;
            unsigned n = 0;
            for ( ; n<tuples.size(); n++ ) {
                BSONObjIterator j(tuples[n]);
                BSONElement keyE = j.next();
                if ( n == 0 ) {
                    reduceArgs.append( keyE );
                    key = keyE.wrap();
                    sizeSoFar = 5 + keyE.size();
                    valueBuilder.reset(new BSONArrayBuilder( reduceArgs.subarrayStart( "tuples" ) ));
                }

                BSONElement ee = j.next();

                uassert( 13070 , "value too large to reduce" , ee.size() < ( BSONObjMaxUserSize / 2 ) );

                if ( sizeSoFar + ee.size() > BSONObjMaxUserSize ) {
                    assert( n > 1 ); // if not, inf. loop
                    break;
                }

                valueBuilder->append( ee );
                sizeSoFar += ee.size();
            }
            assert(valueBuilder);
            valueBuilder->done();
            BSONObj args = reduceArgs.obj();

            Scope * s = _func.scope();

            s->invokeSafe( _func.func() , args );

            if ( s->type( "return" ) == Array ) {
                uasserted( 10075 , "reduce -> multiple not supported yet");
                return;
            }

            endSizeEstimate = key.objsize() + ( args.objsize() / tuples.size() );

            if ( n == tuples.size() )
                return;

            // the input list was too large, add the rest of elmts to new tuples and reduce again
            // note: would be better to use loop instead of recursion to avoid stack overflow
            BSONList x;
            for ( ; n < tuples.size(); n++ ) {
                x.push_back( tuples[n] );
            }
            BSONObjBuilder temp( endSizeEstimate );
            temp.append( key.firstElement() );
            s->append( temp , "1" , "return" );
            x.push_back( temp.obj() );
            _reduce( x , key , endSizeEstimate );
        }
Exemple #8
0
 Purse(int p=0, int n=0, int d=0, int q=0)
  : _p(p), _n(n), _d(d), _q(q) { _reduce(); }
Exemple #9
0
 void remove(int n) { _p -= n; _reduce(); }
Exemple #10
0
 void insert(int n) { _p += n; _reduce(); }
inline void base_string<basic_allocate_size>::shrink()
{
	_reduce(__len);
}//_shrink()
Exemple #12
0
/*
 * reclaim leaf nodes using the LRU replacement algorithm.
 * we don't select a node as a possible victim if the node is
 *  - already reclaimed
 *  - the counter value is larger than the threshold
 *  - both of its parent and sibling's subtree are larger than the threshold
 * then, we compare parent's count with sibling's subtree sum.
 * - if parent is larger, reduce the subtree into parent.
 * - otherwise, reclaim this node and parent, and leave the sibling's subtree.
 */
static void
_reclaim(aguri_t *tp, int n) {
	anode_t *np, *after, *parent, *sibling;
	u_int64_t thresh, sum, moved_to_head;

	thresh = tp->tr_count / 64;
	if (thresh == 0)
		thresh = 1;
	while (tp->tr_nfree < n) {
		/*
		 * select a victim from the LRU list.
		 * exclude nodes whose count is more than the threshold.
		 */
		moved_to_head = 0;
		np = TAILQ_LAST(&tp->tr_lru, _lru);
		while (np != NULL) {
			if (np->tn_intree == 0) {
				/* free node */
				np =  TAILQ_PREV(np, _lru, tn_chain);
				continue;
			} else if (np->tn_count > thresh) {
				/* if bigger than thresh, move it to head */
				after = np;
				np = TAILQ_PREV(np, _lru, tn_chain);
				if (moved_to_head > 3)
					continue;
				TAILQ_REMOVE(&tp->tr_lru, after, tn_chain);
				TAILQ_INSERT_HEAD(&tp->tr_lru, after, tn_chain);
				moved_to_head++;
				continue;
			}
			/*
			 * a possible victim found.
			 * see if either its parent or sibling's subtree is
			 * smaller than the threshold.
			 * also check if parent is not the top node.
			 */
			parent = np->tn_parent;
			if (parent->tn_left == np)
				sibling = parent->tn_right;
			else
				sibling = parent->tn_left;
			sum = _subsum(sibling);
			if (sum > thresh && (parent->tn_count > thresh
			    || parent == tp->tr_top)) {
				after = np;
				np =  TAILQ_PREV(np, _lru, tn_chain);
				if (moved_to_head > 3)
					continue;
				TAILQ_REMOVE(&tp->tr_lru, after, tn_chain);
				TAILQ_INSERT_HEAD(&tp->tr_lru, after, tn_chain);
				moved_to_head++;
				continue;
			}

			/*
			 * at this point, we are about to reclaim this victim.
			 * compare parent's count with sibling's subtree sum.
			 * if parent is larger, reduce the subtree into parent.
			 * otherwise, reclaim this node and parent, and leave
			 * sibling.
			 */
			if (parent->tn_count > sum || parent == tp->tr_top)
				_reduce(tp, np->tn_parent, 0);
			else
				_free(tp, np);
			break;
		}

		if (np == NULL) {
			thresh *= 2;
#if 0
			fprintf(stderr, "thresh increased to %llu\n", thresh);
#endif
		}
	}
}