diff options
Diffstat (limited to 'db/mork/src/morkWriter.h')
-rw-r--r-- | db/mork/src/morkWriter.h | 343 |
1 files changed, 343 insertions, 0 deletions
diff --git a/db/mork/src/morkWriter.h b/db/mork/src/morkWriter.h new file mode 100644 index 000000000..dea0ced83 --- /dev/null +++ b/db/mork/src/morkWriter.h @@ -0,0 +1,343 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef _MORKWRITER_ +#define _MORKWRITER_ 1 + +#ifndef _MORK_ +#include "mork.h" +#endif + +#ifndef _MORKNODE_ +#include "morkNode.h" +#endif + +#ifndef _MORKMAP_ +#include "morkMap.h" +#endif + +#ifndef _MORKROWMAP_ +#include "morkRowMap.h" +#endif + +#ifndef _MORKTABLE_ +#include "morkTable.h" +#endif + +#ifndef _MORKATOMMAP_ +#include "morkAtomMap.h" +#endif + +#ifndef _MORKATOMSPACE_ +#include "morkAtomSpace.h" +#endif + +#ifndef _MORKROWSPACE_ +#include "morkRowSpace.h" +#endif + +#ifndef _MORKSTREAM_ +#include "morkStream.h" +#endif + +//3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789 + + +#define morkWriter_kStreamBufSize /*i*/ (16 * 1024) /* buffer size for stream */ + +#define morkDerived_kWriter /*i*/ 0x5772 /* ascii 'Wr' */ + +#define morkWriter_kPhaseNothingDone 0 /* nothing has yet been done */ +#define morkWriter_kPhaseDirtyAllDone 1 /* DirtyAll() is done */ +#define morkWriter_kPhasePutHeaderDone 2 /* PutHeader() is done */ + +#define morkWriter_kPhaseRenumberAllDone 3 /* RenumberAll() is done */ + +#define morkWriter_kPhaseStoreAtomSpaces 4 /*mWriter_StoreAtomSpacesIter*/ +#define morkWriter_kPhaseAtomSpaceAtomAids 5 /*mWriter_AtomSpaceAtomAidsIter*/ + +#define morkWriter_kPhaseStoreRowSpacesTables 6 /*mWriter_StoreRowSpacesIter*/ +#define morkWriter_kPhaseRowSpaceTables 7 /*mWriter_RowSpaceTablesIter*/ +#define morkWriter_kPhaseTableRowArray 8 /*mWriter_TableRowArrayPos */ + +#define morkWriter_kPhaseStoreRowSpacesRows 9 /*mWriter_StoreRowSpacesIter*/ +#define morkWriter_kPhaseRowSpaceRows 10 /*mWriter_RowSpaceRowsIter*/ + +#define morkWriter_kPhaseContentDone 11 /* all content written */ +#define morkWriter_kPhaseWritingDone 12 /* everthing has been done */ + +#define morkWriter_kCountNumberOfPhases 13 /* part of mWrite_TotalCount */ + +#define morkWriter_kMaxColumnNameSize 128 /* longest writable col name */ + +#define morkWriter_kMaxIndent 66 /* default value for mWriter_MaxIndent */ +#define morkWriter_kMaxLine 78 /* default value for mWriter_MaxLine */ + +#define morkWriter_kYarnEscapeSlop 4 /* guess average yarn escape overhead */ + +#define morkWriter_kTableMetaCellDepth 4 /* */ +#define morkWriter_kTableMetaCellValueDepth 6 /* */ + +#define morkWriter_kDictMetaCellDepth 4 /* */ +#define morkWriter_kDictMetaCellValueDepth 6 /* */ + +#define morkWriter_kDictAliasDepth 2 /* */ +#define morkWriter_kDictAliasValueDepth 4 /* */ + +#define morkWriter_kRowDepth 2 /* */ +#define morkWriter_kRowCellDepth 4 /* */ +#define morkWriter_kRowCellValueDepth 6 /* */ + +#define morkWriter_kGroupBufSize 64 /* */ + +// v=1.1 retired on 23-Mar-99 (for metainfo one char column names) +// v=1.2 retired on 20-Apr-99 (for ":c" suffix on table kind hex refs) +// v=1.3 retired on 20-Apr-99 (for 1CE:m instead of ill-formed 1CE:^6D) +#define morkWriter_kFileHeader "// <!-- <mdb:mork:z v=\"1.4\"/> -->" + +class morkWriter : public morkNode { // row iterator + +// public: // slots inherited from morkObject (meant to inform only) + // nsIMdbHeap* mNode_Heap; + // mork_able mNode_Mutable; // can this node be modified? + // mork_load mNode_Load; // is this node clean or dirty? + // mork_base mNode_Base; // must equal morkBase_kNode + // mork_derived mNode_Derived; // depends on specific node subclass + // mork_access mNode_Access; // kOpen, kClosing, kShut, or kDead + // mork_usage mNode_Usage; // kHeap, kStack, kMember, kGlobal, kNone + // mork_uses mNode_Uses; // refcount for strong refs + // mork_refs mNode_Refs; // refcount for strong refs + weak refs + +public: // state is public because the entire Mork system is private + + morkStore* mWriter_Store; // weak ref to committing store + nsIMdbFile* mWriter_File; // strong ref to store's file + nsIMdbFile* mWriter_Bud; // strong ref to bud of mWriter_File + morkStream* mWriter_Stream; // strong ref to stream on bud file + nsIMdbHeap* mWriter_SlotHeap; // strong ref to slot heap + + // GroupIdentity should be based on mStore_CommitGroupIdentity: + mork_gid mWriter_CommitGroupIdentity; // transaction ID number + + // GroupBuf holds a hex version of mWriter_CommitGroupIdentity: + char mWriter_GroupBuf[ morkWriter_kGroupBufSize ]; + mork_fill mWriter_GroupBufFill; // actual bytes in GroupBuf + + mork_count mWriter_TotalCount; // count of all things to be written + mork_count mWriter_DoneCount; // count of things already written + + mork_size mWriter_LineSize; // length of current line being written + mork_size mWriter_MaxIndent; // line size forcing a line break + mork_size mWriter_MaxLine; // line size forcing a value continuation + + mork_cscode mWriter_TableForm; // current charset metainfo + mork_scope mWriter_TableAtomScope; // current atom scope + mork_scope mWriter_TableRowScope; // current row scope + mork_kind mWriter_TableKind; // current table kind + + mork_cscode mWriter_RowForm; // current charset metainfo + mork_scope mWriter_RowAtomScope; // current atom scope + mork_scope mWriter_RowScope; // current row scope + + mork_cscode mWriter_DictForm; // current charset metainfo + mork_scope mWriter_DictAtomScope; // current atom scope + + mork_bool mWriter_NeedDirtyAll; // need to call DirtyAll() + mork_bool mWriter_Incremental; // opposite of mWriter_NeedDirtyAll + mork_bool mWriter_DidStartDict; // true when a dict has been started + mork_bool mWriter_DidEndDict; // true when a dict has been ended + + mork_bool mWriter_SuppressDirtyRowNewline; // for table meta rows + mork_bool mWriter_DidStartGroup; // true when a group has been started + mork_bool mWriter_DidEndGroup; // true when a group has been ended + mork_u1 mWriter_Phase; // status of writing process + + mork_bool mWriter_BeVerbose; // driven by env and table verbose settings: + // mWriter_BeVerbose equals ( ev->mEnv_BeVerbose || table->IsTableVerbose() ) + + mork_u1 mWriter_Pad[ 3 ]; // for u4 alignment + + mork_pos mWriter_TableRowArrayPos; // index into mTable_RowArray + + char mWriter_SafeNameBuf[ (morkWriter_kMaxColumnNameSize * 2) + 4 ]; + // Note: extra four bytes in ColNameBuf means we can always append to yarn + + char mWriter_ColNameBuf[ morkWriter_kMaxColumnNameSize + 4 ]; + // Note: extra four bytes in ColNameBuf means we can always append to yarn + + mdbYarn mWriter_ColYarn; // a yarn to describe space in ColNameBuf: + // mYarn_Buf == mWriter_ColNameBuf, mYarn_Size == morkWriter_kMaxColumnNameSize + + mdbYarn mWriter_SafeYarn; // a yarn to describe space in ColNameBuf: + // mYarn_Buf == mWriter_SafeNameBuf, mYarn_Size == (kMaxColumnNameSize * 2) + + morkAtomSpaceMapIter mWriter_StoreAtomSpacesIter; // for mStore_AtomSpaces + morkAtomAidMapIter mWriter_AtomSpaceAtomAidsIter; // for AtomSpace_AtomAids + + morkRowSpaceMapIter mWriter_StoreRowSpacesIter; // for mStore_RowSpaces + morkTableMapIter mWriter_RowSpaceTablesIter; // for mRowSpace_Tables + +#ifdef MORK_ENABLE_PROBE_MAPS + morkRowProbeMapIter mWriter_RowSpaceRowsIter; // for mRowSpace_Rows +#else /*MORK_ENABLE_PROBE_MAPS*/ + morkRowMapIter mWriter_RowSpaceRowsIter; // for mRowSpace_Rows +#endif /*MORK_ENABLE_PROBE_MAPS*/ + +// { ===== begin morkNode interface ===== +public: // morkNode virtual methods + virtual void CloseMorkNode(morkEnv* ev) override; // CloseWriter() + virtual ~morkWriter(); // assert that close executed earlier + +public: // morkWriter construction & destruction + morkWriter(morkEnv* ev, const morkUsage& inUsage, + nsIMdbHeap* ioHeap, morkStore* ioStore, nsIMdbFile* ioFile, + nsIMdbHeap* ioSlotHeap); + void CloseWriter(morkEnv* ev); // called by CloseMorkNode(); + +private: // copying is not allowed + morkWriter(const morkWriter& other); + morkWriter& operator=(const morkWriter& other); + +public: // dynamic type identification + mork_bool IsWriter() const + { return IsNode() && mNode_Derived == morkDerived_kWriter; } +// } ===== end morkNode methods ===== + +public: // typing & errors + static void NonWriterTypeError(morkEnv* ev); + static void NilWriterStoreError(morkEnv* ev); + static void NilWriterBudError(morkEnv* ev); + static void NilWriterStreamError(morkEnv* ev); + static void NilWriterFileError(morkEnv* ev); + static void UnsupportedPhaseError(morkEnv* ev); + +public: // utitlities + void ChangeRowForm(morkEnv* ev, mork_cscode inNewForm); + void ChangeDictForm(morkEnv* ev, mork_cscode inNewForm); + void ChangeDictAtomScope(morkEnv* ev, mork_scope inScope); + +public: // inlines + mork_bool DidStartDict() const { return mWriter_DidStartDict; } + mork_bool DidEndDict() const { return mWriter_DidEndDict; } + + void IndentAsNeeded(morkEnv* ev, mork_size inDepth) + { + if ( mWriter_LineSize > mWriter_MaxIndent ) + mWriter_LineSize = mWriter_Stream->PutIndent(ev, inDepth); + } + + void IndentOverMaxLine(morkEnv* ev, + mork_size inPendingSize, mork_size inDepth) + { + if ( mWriter_LineSize + inPendingSize > mWriter_MaxLine ) + mWriter_LineSize = mWriter_Stream->PutIndent(ev, inDepth); + } + +public: // delayed construction + + void MakeWriterStream(morkEnv* ev); // give writer a suitable stream + +public: // iterative/asynchronous writing + + mork_bool WriteMore(morkEnv* ev); // call until IsWritingDone() is true + + mork_bool IsWritingDone() const // don't call WriteMore() any longer? + { return mWriter_Phase == morkWriter_kPhaseWritingDone; } + +public: // marking all content dirty + mork_bool DirtyAll(morkEnv* ev); + // DirtyAll() visits every store sub-object and marks + // them dirty, including every table, row, cell, and atom. The return + // equals ev->Good(), to show whether any error happened. This method is + // intended for use in the beginning of a "compress commit" which writes + // all store content, whether dirty or not. We dirty everything first so + // that later iterations over content can mark things clean as they are + // written, and organize the process of serialization so that objects are + // written only at need (because of being dirty). Note the method can + // stop early when any error happens, since this will abort any commit. + +public: // group commit transactions + + mork_bool StartGroup(morkEnv* ev); + mork_bool CommitGroup(morkEnv* ev); + mork_bool AbortGroup(morkEnv* ev); + +public: // phase methods + mork_bool OnNothingDone(morkEnv* ev); + mork_bool OnDirtyAllDone(morkEnv* ev); + mork_bool OnPutHeaderDone(morkEnv* ev); + + mork_bool OnRenumberAllDone(morkEnv* ev); + + mork_bool OnStoreAtomSpaces(morkEnv* ev); + mork_bool OnAtomSpaceAtomAids(morkEnv* ev); + + mork_bool OnStoreRowSpacesTables(morkEnv* ev); + mork_bool OnRowSpaceTables(morkEnv* ev); + mork_bool OnTableRowArray(morkEnv* ev); + + mork_bool OnStoreRowSpacesRows(morkEnv* ev); + mork_bool OnRowSpaceRows(morkEnv* ev); + + mork_bool OnContentDone(morkEnv* ev); + mork_bool OnWritingDone(morkEnv* ev); + +public: // writing dict items first pass + mork_bool PutTableDict(morkEnv* ev, morkTable* ioTable); + mork_bool PutRowDict(morkEnv* ev, morkRow* ioRow); + +public: // writing node content second pass + mork_bool PutTable(morkEnv* ev, morkTable* ioTable); + mork_bool PutRow(morkEnv* ev, morkRow* ioRow); + mork_bool PutRowCells(morkEnv* ev, morkRow* ioRow); + mork_bool PutVerboseRowCells(morkEnv* ev, morkRow* ioRow); + + mork_bool PutCell(morkEnv* ev, morkCell* ioCell, mork_bool inWithVal); + mork_bool PutVerboseCell(morkEnv* ev, morkCell* ioCell, mork_bool inWithVal); + + mork_bool PutTableChange(morkEnv* ev, const morkTableChange* inChange); + +public: // other writer methods + + mork_bool IsYarnAllValue(const mdbYarn* inYarn); + + mork_size WriteYarn(morkEnv* ev, const mdbYarn* inYarn); + // return number of atom bytes written on the current line (which + // implies that escaped line breaks will make the size value smaller + // than the entire yarn's size, since only part goes on a last line). + + mork_size WriteAtom(morkEnv* ev, const morkAtom* inAtom); + // return number of atom bytes written on the current line (which + // implies that escaped line breaks will make the size value smaller + // than the entire atom's size, since only part goes on a last line). + + void WriteAllStoreTables(morkEnv* ev); + void WriteAtomSpaceAsDict(morkEnv* ev, morkAtomSpace* ioSpace); + + void WriteTokenToTokenMetaCell(morkEnv* ev, mork_token inCol, + mork_token inValue); + void WriteStringToTokenDictCell(morkEnv* ev, const char* inCol, + mork_token inValue); + // Note inCol should begin with '(' and end with '=', with col in between. + + void StartDict(morkEnv* ev); + void EndDict(morkEnv* ev); + + void StartTable(morkEnv* ev, morkTable* ioTable); + void EndTable(morkEnv* ev); + +public: // typesafe refcounting inlines calling inherited morkNode methods + static void SlotWeakWriter(morkWriter* me, + morkEnv* ev, morkWriter** ioSlot) + { morkNode::SlotWeakNode((morkNode*) me, ev, (morkNode**) ioSlot); } + + static void SlotStrongWriter(morkWriter* me, + morkEnv* ev, morkWriter** ioSlot) + { morkNode::SlotStrongNode((morkNode*) me, ev, (morkNode**) ioSlot); } +}; + +//3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789 + +#endif /* _MORKTABLEROWCURSOR_ */ |