void Table::serializeTo(SerializeOutput &serialOutput) { // The table is serialized as: // [(int) total size] // [(int) header size] [num columns] [column types] [column names] // [(int) num tuples] [tuple data] /* NOTE: VoltDBEngine uses a binary template to create tables of single integers. It's called m_templateSingleLongTable and if you are seeing a serialization bug in tables of single integers, make sure that's correct. */ // a placeholder for the total table size std::size_t pos = serialOutput.position(); serialOutput.writeInt(-1); serializeColumnHeaderTo(serialOutput); // active tuple counts serialOutput.writeInt(static_cast<int32_t>(m_tupleCount)); int64_t written_count = 0; TableIterator titer = iterator(); TableTuple tuple(m_schema); while (titer.next(tuple)) { tuple.serializeTo(serialOutput); ++written_count; } assert(written_count == m_tupleCount); // length prefix is non-inclusive int32_t sz = static_cast<int32_t>(serialOutput.position() - pos - sizeof(int32_t)); assert(sz > 0); serialOutput.writeIntAt(pos, sz); }
void Table::serializeColumnHeaderTo(SerializeOutput &serialOutput) { /* NOTE: VoltDBEngine uses a binary template to create tables of single integers. It's called m_templateSingleLongTable and if you are seeing a serialization bug in tables of single integers, make sure that's correct. */ // skip header position std::size_t start; // use a cache if (m_columnHeaderData) { assert(m_columnHeaderSize != -1); serialOutput.writeBytes(m_columnHeaderData, m_columnHeaderSize); return; } assert(m_columnHeaderSize == -1); start = serialOutput.position(); // skip header position serialOutput.writeInt(-1); //status code serialOutput.writeByte(-128); // column counts as a short serialOutput.writeShort(static_cast<int16_t>(m_columnCount)); // write an array of column types as bytes for (int i = 0; i < m_columnCount; ++i) { ValueType type = m_schema->columnType(i); serialOutput.writeByte(static_cast<int8_t>(type)); } // write the array of column names as voltdb strings // NOTE: strings are ASCII only in metadata (UTF-8 in table storage) for (int i = 0; i < m_columnCount; ++i) { // column name: write (offset, length) for column definition, and string to string table const string& name = columnName(i); // column names can't be null, so length must be >= 0 int32_t length = static_cast<int32_t>(name.size()); assert(length >= 0); // this is standard string serialization for voltdb serialOutput.writeInt(length); serialOutput.writeBytes(name.data(), length); } // write the header size which is a non-inclusive int size_t position = serialOutput.position(); m_columnHeaderSize = static_cast<int32_t>(position - start); int32_t nonInclusiveHeaderSize = static_cast<int32_t>(m_columnHeaderSize - sizeof(int32_t)); serialOutput.writeIntAt(start, nonInclusiveHeaderSize); // cache the results m_columnHeaderData = new char[m_columnHeaderSize]; memcpy(m_columnHeaderData, static_cast<const char*>(serialOutput.data()) + start, m_columnHeaderSize); }
bool Table::serializeTo(int32_t offset, int32_t limit, SerializeOutput &serialize_io) { // The table is serialized as: // [(int) total size] // [(int) header size] [num columns] [column types] [column names] // [(int) num tuples] [tuple data] /* NOTE: VoltDBEngine uses a binary template to create tables of single integers. It's called m_templateSingleLongTable and if you are seeing a serialization bug in tables of single integers, make sure that's correct. */ // a placeholder for the total table size std::size_t pos = serialize_io.position(); serialize_io.writeInt(-1); if (!serializeColumnHeaderTo(serialize_io)) return false; // active tuple counts uint32_t output_size = m_tupleCount; if (limit != -1 || offset != -1) { if (offset == -1) { output_size = (limit < m_tupleCount ? limit : m_tupleCount); } else if (offset > m_tupleCount) { output_size = 0; } else { output_size = m_tupleCount - offset; if (limit != -1 && limit < output_size) output_size = limit; } } serialize_io.writeInt(static_cast<int32_t>(output_size)); // fprintf(stderr, "SERIALIZE(output=%d, offset=%d, limit=%d, total=%d)\n", output_size, offset, limit, m_tupleCount); int64_t written_count = 0; int64_t read_count = 0; TableIterator titer(this); TableTuple tuple(m_schema); while (titer.next(tuple)) { if (offset == -1 || read_count >= offset) { tuple.serializeTo(serialize_io); if (limit != -1 && ++written_count == limit) break; } read_count++; } // assert(written_count == m_tupleCount); // length prefix is non-inclusive int32_t sz = static_cast<int32_t>(serialize_io.position() - pos - sizeof(int32_t)); assert(sz > 0); serialize_io.writeIntAt(pos, sz); return true; }
/** * Serialized the table, but only includes the tuples specified (columns data and all). * Used by the exception stuff Ariel put in. */ void Table::serializeTupleTo(SerializeOutput &serialOutput, voltdb::TableTuple *tuples, int numTuples) { //assert(m_schema->equals(tuples[0].getSchema())); std::size_t pos = serialOutput.position(); serialOutput.writeInt(-1); assert(!tuples[0].isNullTuple()); serializeColumnHeaderTo(serialOutput); serialOutput.writeInt(static_cast<int32_t>(numTuples)); for (int ii = 0; ii < numTuples; ii++) { tuples[ii].serializeTo(serialOutput); } serialOutput.writeIntAt(pos, static_cast<int32_t>(serialOutput.position() - pos - sizeof(int32_t))); }