/* -*- 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 // 456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789 /* buffer size for stream */ #define morkWriter_kStreamBufSize /*i*/ (16 * 1024) #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 /* everything 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 "// " 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); } }; // 456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789 #endif /* _MORKTABLEROWCURSOR_ */