Beispiel #1
0
void SSDBProtocolRequest::appendStr(const std::string& str)
{
    char len[16];
    int num = snprintf(len, sizeof(len), "%d\n", (int)str.size());
    appendBlock(len, num);
    appendBlock(str.c_str(), str.length());
    appendBlock("\n", 1);
}
Beispiel #2
0
void SSDBProtocolRequest::appendStr(const char* str, size_t len)
{
    char lenstr[16];
    int num = snprintf(lenstr, sizeof(len), "%d\n", len);
    appendBlock(lenstr, num);
    appendBlock(str, len);
    appendBlock("\n", 1);
}
Beispiel #3
0
	void insertIntoBuffer(const Block & block, StorageBuffer::Buffer & buffer, std::unique_lock<std::mutex> && lock)
	{
		time_t current_time = time(0);

		/// Сортируем столбцы в блоке. Это нужно, чтобы было проще потом конкатенировать блоки.
		Block sorted_block = block.sortColumns();

		if (!buffer.data)
		{
			buffer.data = sorted_block.cloneEmpty();
		}
		else if (storage.checkThresholds(buffer, current_time, sorted_block.rowsInFirstColumn(), sorted_block.bytes()))
		{
			/** Если после вставки в буфер, ограничения будут превышены, то будем сбрасывать буфер.
			  * Это также защищает от неограниченного потребления оперативки, так как в случае невозможности записать в таблицу,
			  *  будет выкинуто исключение, а новые данные не будут добавлены в буфер.
			  */

			lock.unlock();
			storage.flushBuffer(buffer, false);
			lock.lock();
		}

		if (!buffer.first_write_time)
			buffer.first_write_time = current_time;

		appendBlock(sorted_block, buffer.data);
	}
Beispiel #4
0
    void insertIntoBuffer(const Block & block, StorageBuffer::Buffer & buffer, std::unique_lock<std::mutex> && lock)
    {
        time_t current_time = time(nullptr);

        /// Sort the columns in the block. This is necessary to make it easier to concatenate the blocks later.
        Block sorted_block = block.sortColumns();

        if (!buffer.data)
        {
            buffer.data = sorted_block.cloneEmpty();
        }
        else if (storage.checkThresholds(buffer, current_time, sorted_block.rows(), sorted_block.bytes()))
        {
            /** If, after inserting the buffer, the constraints are exceeded, then we will reset the buffer.
              * This also protects against unlimited consumption of RAM, since if it is impossible to write to the table,
              *  an exception will be thrown, and new data will not be added to the buffer.
              */

            lock.unlock();
            storage.flushBuffer(buffer, true);
            lock.lock();
        }

        if (!buffer.first_write_time)
            buffer.first_write_time = current_time;

        appendBlock(sorted_block, buffer.data);
    }
Beispiel #5
0
int VMemBuf::set( int type, int size )
{
    if (( type > VMBUF_FILE_MAP) || ( type < VMBUF_MALLOC ))
        return -1;

    char *pBuf;
    BlockBuf * pBlock = NULL;
    m_type = type;
    switch( type )
    {
    case VMBUF_MALLOC:
        if ( size > 0 )
        {
            size = (( size + 511 ) / 512) * 512;
            pBuf = ( char *)malloc( size );
            if ( !pBuf )
                return -1;
            pBlock = new MallocBlockBuf( pBuf, size );
            if ( !pBlock )
            {
                free( pBuf );
                return -1;
            }
        }
        break;
    case VMBUF_ANON_MAP:
        m_autoGrow = 1;
        if ( size > 0 )
        {
            if ( ( pBlock = getAnonMapBlock( size ) ) == NULL )
                return -1;
        }
        break;
    case VMBUF_FILE_MAP:
        m_autoGrow = 1;
        m_sFileName.setStr( s_sTmpFileTemplate );
        m_fd = mkstemp( m_sFileName.buf());
        if (m_fd == -1 )
        {
            char achBuf[1024];
            safe_snprintf( achBuf, 1024, "Failed to create swap file with mkstemp( %s ), please check 'Swap Directory' and permission", m_sFileName.c_str() );
            perror( achBuf );
            *m_sFileName.buf() = 0;
            m_sFileName.setLen(0);
            return -1;
        }
        fcntl( m_fd, F_SETFD, FD_CLOEXEC );
        break;
    }
    if ( pBlock )
    {
        appendBlock( pBlock );
        m_pCurRPos = m_pCurWPos = pBlock->getBuf();
        m_curTotalSize = m_curRBlkPos = m_curWBlkPos = pBlock->getBlockSize();
        m_pCurRBlock = m_pCurWBlock = m_bufList.begin();
    }
    return 0;
}
Beispiel #6
0
int VMemBuf::set( BlockBuf * pBlock )
{
    assert( pBlock );
    m_type = VMBUF_MALLOC;
    appendBlock( pBlock );
    m_pCurRBlock = m_pCurWBlock = m_bufList.begin();
    m_pCurRPos = m_pCurWPos = pBlock->getBuf();
    m_curTotalSize = m_curRBlkPos = m_curWBlkPos = pBlock->getBlockSize();
    return 0;
}
Beispiel #7
0
int VMemBuf::grow()
{
    char * pBuf;
    BlockBuf * pBlock;
    size_t oldPos = m_curTotalSize;
    switch( m_type )
    {
    case VMBUF_MALLOC:
        pBuf = ( char *)malloc( s_iBlockSize );
        if ( !pBuf )
            return -1;
        pBlock = new MallocBlockBuf( pBuf, s_iBlockSize );
        if ( !pBlock )
        {
            perror( "new MallocBlockBuf failed in grow()" );
            free( pBuf );
            return -1;
        }
        break;    
    case VMBUF_FILE_MAP:
        if ( ftruncate( m_fd, m_curTotalSize + s_iBlockSize ) == -1 )
        {
            perror( "Failed to increase temp file size with ftrancate()" );
            return -1;
        }
        pBuf = ( char*) mmap( NULL, s_iBlockSize, PROT_READ | PROT_WRITE,
                MAP_SHARED | MAP_FILE, m_fd, oldPos );
        if( pBuf == MAP_FAILED )
        {
            perror( "FS backed mmap() failed" );
            return -1;
        }
        pBlock = new MmapBlockBuf( pBuf, s_iBlockSize );
        if ( !pBlock )
        {
            perror( "new MmapBlockBuf failed in grow()" );
            munmap( pBuf, s_iBlockSize );
            return -1;
        }
        break;
    case VMBUF_ANON_MAP:
        if ( (pBlock = getAnonMapBlock( s_iBlockSize ) ))
            break;
	default:
		return -1;
    }
    appendBlock( pBlock );
    m_curTotalSize += s_iBlockSize;
    return 0;

}
Beispiel #8
0
int VMemBuf::convertFileBackedToInMemory()
{
    BlockBuf * pBlock;
    if ( m_type != VMBUF_FILE_MAP )
        return -1;
    if ( m_pCurWPos == (*m_pCurWBlock)->getBuf() )
    {
        if ( *m_pCurWBlock == m_bufList.back() )
        {
            m_bufList.pop_back();
            recycle( *m_pCurWBlock );
            if ( !m_bufList.empty() )
            {
                m_noRecycle = 1;
                s_iCurAnonMapBlocks += m_bufList.size();
                int i = 0;
                while( i < m_bufList.size())
                {
                    pBlock = m_bufList[i];
                    if ( !pBlock->getBuf() )
                    {
                        if ( remapBlock( pBlock, i * s_iBlockSize ) == -1 )
                            return -1;
                    }
                    ++i;
                }
            }
            unlink( m_sFileName.c_str() );
            ::close( m_fd );
            m_fd = -1;
            m_type = VMBUF_ANON_MAP;
            if ( !(pBlock = getAnonMapBlock( s_iBlockSize ) ))
                return -1;
            appendBlock( pBlock );
            if ( m_pCurRPos == m_pCurWPos )
                m_pCurRPos = (*m_pCurWBlock)->getBuf();
            m_pCurWPos = (*m_pCurWBlock)->getBuf();
            return 0;
        }
        
    }
    return -1;
}
Beispiel #9
0
/* create_block_tree:
 * Construct block tree by peeling nodes from block list in state.
 * When done, return root. The block list is empty
 * FIX: use largest block as root
 */
block_t *createBlocktree(Agraph_t * g, circ_state * state)
{
    block_t *bp;
    block_t *next;
    block_t *root;
    int min;
    /* int        ordercnt; */

    find_blocks(g, state);

    bp = state->bl.first;	/* if root chosen, will be first */
    /* Otherwise, just pick first as root */
    root = bp;

    /* Find node with minimum VAL value to find parent block */
    /* FIX: Should be some way to avoid search below.               */
    /* ordercnt = state->orderCount;  */
    for (bp = bp->next; bp; bp = next) {
	Agnode_t *n;
	Agnode_t *parent;
	Agnode_t *child;
	Agraph_t *subg = bp->sub_graph;

	child = n = agfstnode(subg);
	min = VAL(n);
	parent = PARENT(n);
	for (n = agnxtnode(subg, n); n; n = agnxtnode(subg, n)) {
	    if (VAL(n) < min) {
		child = n;
		min = VAL(n);
		parent = PARENT(n);
	    }
	}
	SET_PARENT(parent);
	CHILD(bp) = child;
	next = bp->next;	/* save next since list insertion destroys it */
	appendBlock(&(BLOCK(parent)->children), bp);
    }
    initBlocklist(&state->bl);	/* zero out list */
    return root;
}
Beispiel #10
0
void SSDBProtocolRequest::endl()
{
    appendBlock("\n", 1);
}
Beispiel #11
0
/* dfs:
 *
 * Current scheme adds articulation point to first non-trivial child
 * block. If none exists, it will be added to its parent's block, if
 * non-trivial, or else given its own block.
 *
 * FIX:
 * This should be modified to:
 *  - allow user to specify which block gets a node, perhaps on per-node basis.
 *  - if an articulation point is not used in one of its non-trivial blocks,
 *    dummy edges should be added to preserve biconnectivity
 *  - turn on user-supplied blocks.
 *
 */
static void dfs(Agraph_t * g, Agnode_t * n, circ_state * state, int isRoot)
{
    Agedge_t *e;
    Agnode_t *curtop;

    LOWVAL(n) = VAL(n) = state->orderCount++;

    stackPush(state->bcstack, n);

    for (e = agfstedge(g, n); e; e = agnxtedge(g, e, n)) {
	Agnode_t *neighbor = e->head;
	if (neighbor == n)
	    neighbor = e->tail;

	if (neighbor == PARENT(n))
	    continue;

	if (VAL(neighbor)) {
	    LOWVAL(n) = min_value(LOWVAL(n), VAL(neighbor));
	    continue;
	}
	if (!stackCheck(state->bcstack, n)) {
	    stackPush(state->bcstack, n);
	}

	PARENT(neighbor) = n;
	curtop = top(state->bcstack);
	dfs(g, neighbor, state, 0);

	LOWVAL(n) = min_value(LOWVAL(n), LOWVAL(neighbor));
	if (LOWVAL(neighbor) >= VAL(n)) {
	    block_t *block = NULL;
	    Agnode_t *np;
	    if (top(state->bcstack) != curtop)
		do {
		    np = stackPop(state->bcstack);
		    if (!BCDONE(np)) {
			if (!block)
			    block = makeBlock(g, state);
			addNode(block, np);
		    }
		} while (np != n);
	    if (block) {	/* If block != NULL, it's not empty */
		if (isRoot && (BLOCK(n) == block))
		    insertBlock(&state->bl, block);
		else
		    appendBlock(&state->bl, block);
	    }
	    if ((LOWVAL(n) < VAL(n)) && (!stackCheck(state->bcstack, n))) {
		stackPush(state->bcstack, n);
	    }
	}
    }
    if ((LOWVAL(n) == VAL(n)) && !BCDONE(n)) {
	block_t *block = makeBlock(g, state);
	stackPop(state->bcstack);
	addNode(block, n);
	if (isRoot)
	    insertBlock(&state->bl, block);
	else
	    appendBlock(&state->bl, block);
    }
}
Beispiel #12
0
/* find_blocks:
 */
static void find_blocks(Agraph_t * g, circ_state * state)
{
    Agnode_t *n;
    Agnode_t *root = NULL;
    block_t *rootBlock = NULL;
    blocklist_t ublks;
#ifdef USER_BLOCKS
    graph_t *clust_subg;
    graph_t *mg;
    edge_t *me;
    node_t *mm;
    int isRoot;
#endif

    initBlocklist(&ublks);

    /*      check to see if there is a node which is set to be the root
     */
    if (state->rootname) {
	root = agfindnode(g, state->rootname);
    }
    if (!root && state->N_root) {
	for (n = agfstnode(g); n; n = agnxtnode(g, n)) {
	    if (late_bool(ORIGN(n), state->N_root, 0)) {
		root = n;
		break;
	    }
	}
    }
#ifdef USER_BLOCKS
    /* process clusters first */
    /* by construction, all subgraphs are blocks and are non-empty */
    mm = g->meta_node;
    mg = mm->graph;
    for (me = agfstout(mg, mm); me; me = agnxtout(mg, me)) {
	block_t *block;

	clust_subg = agusergraph(me->head);

	isRoot = 0;
	block = mkBlock(clust_subg);
	/* block = makeBlock(g, state); */
	for (n = agfstnode(clust_subg); n; n = agnxtnode(clust_subg, n)) {
	    if (!BCDONE(n)) {	/* test not necessary if blocks disjoint */
		SET_BCDONE(n);
		BLOCK(n) = block;
		if (n == root)
		    isRoot = 1;
	    }
	}
	if (isRoot) {
	    /* Assume blocks are disjoint, so don't check if rootBlock is
	     * already assigned.
	     */
	    rootBlock = block;
	    insertBlock(&state->bl, block);
	} else {
	    appendBlock(&state->bl, block);
	}
    }
    ublks.first = state->bl.first;
    ublks.last = state->bl.last;
#endif

    if (!root)
	root = agfstnode(g);
    dfs(g, root, state, !rootBlock);

#ifdef USER_BLOCKS
    /* If g has user-supplied blocks, it may be disconnected.
     * We then fall into the following ugly loop.
     * We are guaranteed !VISITED(n) and PARENT(n) has been
     * set to a visited node.
     */
    if (ublks.first) {
	while (n = findUnvisited(&ublks)) {
	    dfs(g, n, state, 0);
	}
    }
#endif
}
QTextHtmlImporter::ProcessNodeResult QTextHtmlImporter::processSpecialNodes()
{
    switch (currentNode->id) {
        case Html_body:
            if (currentNode->charFormat.background().style() != Qt::NoBrush) {
                QTextFrameFormat fmt = doc->rootFrame()->frameFormat();
                fmt.setBackground(currentNode->charFormat.background());
                doc->rootFrame()->setFrameFormat(fmt);
                const_cast<QTextHtmlParserNode *>(currentNode)->charFormat.clearProperty(QTextFormat::BackgroundBrush);
            }
            break;

        case Html_ol:
        case Html_ul: {
            QTextListFormat::Style style = currentNode->listStyle;

            if (currentNode->id == Html_ul && !currentNode->hasOwnListStyle && currentNode->parent) {
                const QTextHtmlParserNode *n = &at(currentNode->parent);
                while (n) {
                    if (n->id == Html_ul) {
                        style = nextListStyle(currentNode->listStyle);
                    }
                    if (n->parent)
                        n = &at(n->parent);
                    else
                        n = 0;
                }
            }

            QTextListFormat listFmt;
            listFmt.setStyle(style);

            ++indent;
            if (currentNode->hasCssListIndent)
                listFmt.setIndent(currentNode->cssListIndent);
            else
                listFmt.setIndent(indent);

            List l;
            l.format = listFmt;
            l.listNode = currentNodeIdx;
            lists.append(l);
            compressNextWhitespace = true;

            // broken html: <ul>Text here<li>Foo
            const QString simpl = currentNode->text.simplified();
            if (simpl.isEmpty() || simpl.at(0).isSpace())
                return ContinueWithNextNode;
            break;
        }

        case Html_table: {
            Table t = scanTable(currentNodeIdx);
            tables.append(t);
            hasBlock = false;
            return ContinueWithNextNode;
        }

        case Html_tr:
            return ContinueWithNextNode;

        case Html_img: {
            QTextImageFormat fmt;
            fmt.setName(currentNode->imageName);

            fmt.merge(currentNode->charFormat);

            if (currentNode->imageWidth >= 0)
                fmt.setWidth(currentNode->imageWidth);
            if (currentNode->imageHeight >= 0)
                fmt.setHeight(currentNode->imageHeight);

            cursor.insertImage(fmt, QTextFrameFormat::Position(currentNode->cssFloat));

            cursor.movePosition(QTextCursor::Left, QTextCursor::KeepAnchor);
            cursor.mergeCharFormat(currentNode->charFormat);
            cursor.movePosition(QTextCursor::Right);

            hasBlock = false;
            return ContinueWithNextNode;
        }

        case Html_hr: {
            QTextBlockFormat blockFormat = currentNode->blockFormat;
            blockFormat.setTopMargin(topMargin(currentNodeIdx));
            blockFormat.setBottomMargin(bottomMargin(currentNodeIdx));
            blockFormat.setProperty(QTextFormat::BlockTrailingHorizontalRulerWidth, currentNode->width);
            if (hasBlock && importMode == ImportToDocument)
                cursor.mergeBlockFormat(blockFormat);
            else
                appendBlock(blockFormat);
            hasBlock = false;
            return ContinueWithNextNode;
        }

        default: break;
    }
    return ContinueWithCurrentNode;
}
bool QTextHtmlImporter::appendNodeText()
{
    const int initialCursorPosition = cursor.position();
    QTextCharFormat format = currentNode->charFormat;

    if (isPreservingWhitespaceMode(wsm))
        compressNextWhitespace = false;

    QString text = currentNode->text;

    QString textToInsert;
    textToInsert.reserve(text.size());

    for (int i = 0; i < text.length(); ++i) {
        QChar ch = text.at(i);

        if (ch.isSpace()
            && ch != QChar::Nbsp
            && ch != QChar::ParagraphSeparator) {

            if (compressNextWhitespace)
                continue;

            if (wsm == QTextHtmlParserNode::WhiteSpacePre
                || textEditMode
               ) {
                if (ch == QLatin1Char('\n')) {
                    if (textEditMode)
                        continue;
                } else if (ch == QLatin1Char('\r')) {
                    continue;
                }
            } else if (wsm != QTextHtmlParserNode::WhiteSpacePreWrap) {
                compressNextWhitespace = true;
                if (wsm == QTextHtmlParserNode::WhiteSpaceNoWrap)
                    ch = QChar::Nbsp;
                else
                    ch = QLatin1Char(' ');
            }
        } else {
            compressNextWhitespace = false;
        }

        if (ch == QLatin1Char('\n')
            || ch == QChar::ParagraphSeparator) {

            if (!textToInsert.isEmpty()) {
                cursor.insertText(textToInsert, format);
                textToInsert.clear();
            }

            QTextBlockFormat fmt = cursor.blockFormat();

            if (fmt.hasProperty(QTextFormat::BlockBottomMargin)) {
                QTextBlockFormat tmp = fmt;
                tmp.clearProperty(QTextFormat::BlockBottomMargin);
                cursor.setBlockFormat(tmp);
            }

            fmt.clearProperty(QTextFormat::BlockTopMargin);
            appendBlock(fmt, cursor.charFormat());
        } else {
            if (!namedAnchors.isEmpty()) {
                if (!textToInsert.isEmpty()) {
                    cursor.insertText(textToInsert, format);
                    textToInsert.clear();
                }

                format.setAnchor(true);
                format.setAnchorNames(namedAnchors);
                cursor.insertText(ch, format);
                namedAnchors.clear();
                format.clearProperty(QTextFormat::IsAnchor);
                format.clearProperty(QTextFormat::AnchorName);
            } else {
                textToInsert += ch;
            }
        }
    }

    if (!textToInsert.isEmpty()) {
        cursor.insertText(textToInsert, format);
    }

    return cursor.position() != initialCursorPosition;
}
void QTextHtmlImporter::import()
{
    cursor.beginEditBlock();
    hasBlock = true;
    forceBlockMerging = false;
    compressNextWhitespace = !textEditMode;
    blockTagClosed = false;
    for (currentNodeIdx = 0; currentNodeIdx < count(); ++currentNodeIdx) {
        currentNode = &at(currentNodeIdx);
        wsm = textEditMode ? QTextHtmlParserNode::WhiteSpacePreWrap : currentNode->wsm;

        /*
         * process each node in three stages:
         * 1) check if the hierarchy changed and we therefore passed the
         *    equivalent of a closing tag -> we may need to finish off
         *    some structures like tables
         *
         * 2) check if the current node is a special node like a
         *    <table>, <ul> or <img> tag that requires special processing
         *
         * 3) if the node should result in a QTextBlock create one and
         *    finally insert text that may be attached to the node
         */

        /* emit 'closing' table blocks or adjust current indent level
         * if we
         *  1) are beyond the first node
         *  2) the current node not being a child of the previous node
         *      means there was a tag closing in the input html
         */
        if (currentNodeIdx > 0 && (currentNode->parent != currentNodeIdx - 1)) {
            blockTagClosed = closeTag();
            // visually collapse subsequent block tags, but if the element after the closed block tag
            // is for example an inline element (!isBlock) we have to make sure we start a new paragraph by setting
            // hasBlock to false.
            if (blockTagClosed
                && !currentNode->isBlock()
                && currentNode->id != Html_unknown)
                hasBlock = false;
        }

        if (currentNode->displayMode == QTextHtmlElement::DisplayNone) {
            if (currentNode->id == Html_title)
                doc->setMetaInformation(QTextDocument::DocumentTitle, currentNode->text);
            // ignore explicitly 'invisible' elements
            continue;
        }

        if (processSpecialNodes() == ContinueWithNextNode)
            continue;

        // make sure there's a block for 'Blah' after <ul><li>foo</ul>Blah
        if (blockTagClosed
            && !hasBlock
            && !currentNode->isBlock()
            && !currentNode->text.isEmpty() && !currentNode->hasOnlyWhitespace()
            && currentNode->displayMode == QTextHtmlElement::DisplayInline) {

            QTextBlockFormat block = currentNode->blockFormat;
            block.setIndent(indent);

            appendBlock(block, currentNode->charFormat);

            hasBlock = true;
        }

        if (currentNode->isBlock()) {
            if (processBlockNode() == ContinueWithNextNode)
                continue;
        }

        if (currentNode->charFormat.isAnchor() && !currentNode->charFormat.anchorName().isEmpty()) {
            namedAnchors.append(currentNode->charFormat.anchorName());
        }

        if (appendNodeText())
            hasBlock = false; // if we actually appended text then we don't
                              // have an empty block anymore
    }

    cursor.endEditBlock();
}