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); }
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); }
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); }
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); }
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; }
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; }
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; }
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; }
/* 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; }
void SSDBProtocolRequest::endl() { appendBlock("\n", 1); }
/* 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); } }
/* 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(); }