summaryrefslogtreecommitdiffstats
path: root/comm/mailnews/db/mork/morkWriter.h
diff options
context:
space:
mode:
Diffstat (limited to 'comm/mailnews/db/mork/morkWriter.h')
-rw-r--r--comm/mailnews/db/mork/morkWriter.h340
1 files changed, 340 insertions, 0 deletions
diff --git a/comm/mailnews/db/mork/morkWriter.h b/comm/mailnews/db/mork/morkWriter.h
new file mode 100644
index 0000000000..7e716bec6a
--- /dev/null
+++ b/comm/mailnews/db/mork/morkWriter.h
@@ -0,0 +1,340 @@
+/* -*- 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 "// <!-- <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);
+ }
+};
+
+// 456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789
+
+#endif /* _MORKTABLEROWCURSOR_ */