Back to index

lightning-sunbird  0.9+nobinonly
morkWriter.h
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-  */
00002 /* ***** BEGIN LICENSE BLOCK *****
00003  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00004  *
00005  * The contents of this file are subject to the Mozilla Public License Version
00006  * 1.1 (the "License"); you may not use this file except in compliance with
00007  * the License. You may obtain a copy of the License at
00008  * http://www.mozilla.org/MPL/
00009  *
00010  * Software distributed under the License is distributed on an "AS IS" basis,
00011  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00012  * for the specific language governing rights and limitations under the
00013  * License.
00014  *
00015  * The Original Code is mozilla.org code.
00016  *
00017  * The Initial Developer of the Original Code is
00018  * Netscape Communications Corporation.
00019  * Portions created by the Initial Developer are Copyright (C) 1999
00020  * the Initial Developer. All Rights Reserved.
00021  *
00022  * Contributor(s):
00023  *
00024  * Alternatively, the contents of this file may be used under the terms of
00025  * either of the GNU General Public License Version 2 or later (the "GPL"),
00026  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00027  * in which case the provisions of the GPL or the LGPL are applicable instead
00028  * of those above. If you wish to allow use of your version of this file only
00029  * under the terms of either the GPL or the LGPL, and not to allow others to
00030  * use your version of this file under the terms of the MPL, indicate your
00031  * decision by deleting the provisions above and replace them with the notice
00032  * and other provisions required by the GPL or the LGPL. If you do not delete
00033  * the provisions above, a recipient may use your version of this file under
00034  * the terms of any one of the MPL, the GPL or the LGPL.
00035  *
00036  * ***** END LICENSE BLOCK ***** */
00037 
00038 #ifndef _MORKWRITER_
00039 #define _MORKWRITER_ 1
00040 
00041 #ifndef _MORK_
00042 #include "mork.h"
00043 #endif
00044 
00045 #ifndef _MORKNODE_
00046 #include "morkNode.h"
00047 #endif
00048 
00049 #ifndef _MORKMAP_
00050 #include "morkMap.h"
00051 #endif
00052 
00053 #ifndef _MORKROWMAP_
00054 #include "morkRowMap.h"
00055 #endif
00056 
00057 #ifndef _MORKTABLE_
00058 #include "morkTable.h"
00059 #endif
00060 
00061 #ifndef _MORKATOMMAP_
00062 #include "morkAtomMap.h"
00063 #endif
00064 
00065 #ifndef _MORKATOMSPACE_
00066 #include "morkAtomSpace.h"
00067 #endif
00068 
00069 #ifndef _MORKROWSPACE_
00070 #include "morkRowSpace.h"
00071 #endif
00072 
00073 #ifndef _MORKSTREAM_
00074 #include "morkStream.h"
00075 #endif
00076 
00077 //3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789
00078 
00079 
00080 #define morkWriter_kStreamBufSize /*i*/ (16 * 1024) /* buffer size for stream */ 
00081 
00082 #define morkDerived_kWriter  /*i*/ 0x5772 /* ascii 'Wr' */
00083 
00084 #define morkWriter_kPhaseNothingDone          0 /* nothing has yet been done */
00085 #define morkWriter_kPhaseDirtyAllDone         1 /* DirtyAll() is done */
00086 #define morkWriter_kPhasePutHeaderDone        2 /* PutHeader() is done */
00087 
00088 #define morkWriter_kPhaseRenumberAllDone      3 /* RenumberAll() is done */
00089 
00090 #define morkWriter_kPhaseStoreAtomSpaces      4 /*mWriter_StoreAtomSpacesIter*/
00091 #define morkWriter_kPhaseAtomSpaceAtomAids    5 /*mWriter_AtomSpaceAtomAidsIter*/
00092 
00093 #define morkWriter_kPhaseStoreRowSpacesTables 6 /*mWriter_StoreRowSpacesIter*/
00094 #define morkWriter_kPhaseRowSpaceTables       7 /*mWriter_RowSpaceTablesIter*/
00095 #define morkWriter_kPhaseTableRowArray        8 /*mWriter_TableRowArrayPos */
00096 
00097 #define morkWriter_kPhaseStoreRowSpacesRows   9 /*mWriter_StoreRowSpacesIter*/
00098 #define morkWriter_kPhaseRowSpaceRows        10 /*mWriter_RowSpaceRowsIter*/
00099 
00100 #define morkWriter_kPhaseContentDone         11 /* all content written */
00101 #define morkWriter_kPhaseWritingDone         12 /* everthing has been done */
00102 
00103 #define morkWriter_kCountNumberOfPhases      13 /* part of mWrite_TotalCount */
00104 
00105 #define morkWriter_kMaxColumnNameSize        128 /* longest writable col name */
00106 
00107 #define morkWriter_kMaxIndent 66 /* default value for mWriter_MaxIndent */
00108 #define morkWriter_kMaxLine   78 /* default value for mWriter_MaxLine */
00109 
00110 #define morkWriter_kYarnEscapeSlop  4 /* guess average yarn escape overhead */
00111 
00112 #define morkWriter_kTableMetaCellDepth 4 /* */
00113 #define morkWriter_kTableMetaCellValueDepth 6 /* */
00114 
00115 #define morkWriter_kDictMetaCellDepth 4 /* */
00116 #define morkWriter_kDictMetaCellValueDepth 6 /* */
00117 
00118 #define morkWriter_kDictAliasDepth 2 /* */
00119 #define morkWriter_kDictAliasValueDepth 4 /* */
00120 
00121 #define morkWriter_kRowDepth 2 /* */
00122 #define morkWriter_kRowCellDepth 4 /* */
00123 #define morkWriter_kRowCellValueDepth 6 /* */
00124 
00125 #define morkWriter_kGroupBufSize 64 /* */
00126 
00127 // v=1.1 retired on 23-Mar-99 (for metainfo one char column names)
00128 // v=1.2 retired on 20-Apr-99 (for ":c" suffix on table kind hex refs)
00129 // v=1.3 retired on 20-Apr-99 (for 1CE:m instead of ill-formed 1CE:^6D)
00130 #define morkWriter_kFileHeader "// <!-- <mdb:mork:z v=\"1.4\"/> -->"
00131 
00132 class morkWriter : public morkNode { // row iterator
00133 
00134 // public: // slots inherited from morkObject (meant to inform only)
00135   // nsIMdbHeap*     mNode_Heap;
00136   // mork_able    mNode_Mutable; // can this node be modified?
00137   // mork_load    mNode_Load;    // is this node clean or dirty?
00138   // mork_base    mNode_Base;    // must equal morkBase_kNode
00139   // mork_derived mNode_Derived; // depends on specific node subclass
00140   // mork_access  mNode_Access;  // kOpen, kClosing, kShut, or kDead
00141   // mork_usage   mNode_Usage;   // kHeap, kStack, kMember, kGlobal, kNone
00142   // mork_uses    mNode_Uses;    // refcount for strong refs
00143   // mork_refs    mNode_Refs;    // refcount for strong refs + weak refs
00144 
00145 public: // state is public because the entire Mork system is private
00146 
00147   morkStore*   mWriter_Store;      // weak ref to committing store
00148   nsIMdbFile*  mWriter_File;       // strong ref to store's file
00149   nsIMdbFile*  mWriter_Bud;        // strong ref to bud of mWriter_File
00150   morkStream*  mWriter_Stream;     // strong ref to stream on bud file
00151   nsIMdbHeap*  mWriter_SlotHeap;   // strong ref to slot heap
00152 
00153   // GroupIdentity should be based on mStore_CommitGroupIdentity:
00154   mork_gid     mWriter_CommitGroupIdentity; // transaction ID number
00155   
00156   // GroupBuf holds a hex version of mWriter_CommitGroupIdentity:
00157   char         mWriter_GroupBuf[ morkWriter_kGroupBufSize ];
00158   mork_fill    mWriter_GroupBufFill; // actual bytes in GroupBuf
00159   
00160   mork_count   mWriter_TotalCount;  // count of all things to be written
00161   mork_count   mWriter_DoneCount;   // count of things already written
00162   
00163   mork_size    mWriter_LineSize;  // length of current line being written
00164   mork_size    mWriter_MaxIndent; // line size forcing a line break
00165   mork_size    mWriter_MaxLine;   // line size forcing a value continuation
00166   
00167   mork_cscode  mWriter_TableForm;     // current charset metainfo
00168   mork_scope   mWriter_TableAtomScope;   // current atom scope
00169   mork_scope   mWriter_TableRowScope;    // current row scope
00170   mork_kind    mWriter_TableKind;        // current table kind
00171   
00172   mork_cscode  mWriter_RowForm;         // current charset metainfo
00173   mork_scope   mWriter_RowAtomScope;    // current atom scope
00174   mork_scope   mWriter_RowScope;        // current row scope
00175   
00176   mork_cscode  mWriter_DictForm;      // current charset metainfo
00177   mork_scope   mWriter_DictAtomScope;    // current atom scope
00178  
00179   mork_bool    mWriter_NeedDirtyAll;  // need to call DirtyAll()
00180   mork_bool    mWriter_Incremental;   // opposite of mWriter_NeedDirtyAll
00181   mork_bool    mWriter_DidStartDict;  // true when a dict has been started
00182   mork_bool    mWriter_DidEndDict;    // true when a dict has been ended
00183 
00184   mork_bool    mWriter_SuppressDirtyRowNewline; // for table meta rows
00185   mork_bool    mWriter_DidStartGroup; // true when a group has been started
00186   mork_bool    mWriter_DidEndGroup;    // true when a group has been ended
00187   mork_u1      mWriter_Phase;         // status of writing process
00188 
00189   mork_bool    mWriter_BeVerbose; // driven by env and table verbose settings:
00190   // mWriter_BeVerbose equals ( ev->mEnv_BeVerbose || table->IsTableVerbose() )
00191   
00192   mork_u1      mWriter_Pad[ 3 ];  // for u4 alignment
00193 
00194   mork_pos     mWriter_TableRowArrayPos;  // index into mTable_RowArray
00195    
00196   char         mWriter_SafeNameBuf[ (morkWriter_kMaxColumnNameSize * 2) + 4 ];
00197   // Note: extra four bytes in ColNameBuf means we can always append to yarn
00198 
00199   char         mWriter_ColNameBuf[ morkWriter_kMaxColumnNameSize + 4 ];
00200   // Note: extra four bytes in ColNameBuf means we can always append to yarn
00201   
00202   mdbYarn      mWriter_ColYarn; // a yarn to describe space in ColNameBuf:
00203   // mYarn_Buf == mWriter_ColNameBuf, mYarn_Size == morkWriter_kMaxColumnNameSize
00204   
00205   mdbYarn      mWriter_SafeYarn; // a yarn to describe space in ColNameBuf:
00206   // mYarn_Buf == mWriter_SafeNameBuf, mYarn_Size == (kMaxColumnNameSize * 2)
00207 
00208   morkAtomSpaceMapIter  mWriter_StoreAtomSpacesIter;   // for mStore_AtomSpaces
00209   morkAtomAidMapIter  mWriter_AtomSpaceAtomAidsIter; // for AtomSpace_AtomAids
00210   
00211   morkRowSpaceMapIter  mWriter_StoreRowSpacesIter;    // for mStore_RowSpaces
00212   morkTableMapIter  mWriter_RowSpaceTablesIter;    // for mRowSpace_Tables
00213   
00214 #ifdef MORK_ENABLE_PROBE_MAPS
00215   morkRowProbeMapIter  mWriter_RowSpaceRowsIter; // for mRowSpace_Rows
00216 #else /*MORK_ENABLE_PROBE_MAPS*/
00217   morkRowMapIter  mWriter_RowSpaceRowsIter;      // for mRowSpace_Rows
00218 #endif /*MORK_ENABLE_PROBE_MAPS*/
00219    
00220 // { ===== begin morkNode interface =====
00221 public: // morkNode virtual methods
00222   virtual void CloseMorkNode(morkEnv* ev); // CloseWriter()
00223   virtual ~morkWriter(); // assert that close executed earlier
00224   
00225 public: // morkWriter construction & destruction
00226   morkWriter(morkEnv* ev, const morkUsage& inUsage,
00227     nsIMdbHeap* ioHeap, morkStore* ioStore, nsIMdbFile* ioFile,
00228     nsIMdbHeap* ioSlotHeap);
00229   void CloseWriter(morkEnv* ev); // called by CloseMorkNode();
00230 
00231 private: // copying is not allowed
00232   morkWriter(const morkWriter& other);
00233   morkWriter& operator=(const morkWriter& other);
00234 
00235 public: // dynamic type identification
00236   mork_bool IsWriter() const
00237   { return IsNode() && mNode_Derived == morkDerived_kWriter; }
00238 // } ===== end morkNode methods =====
00239 
00240 public: // typing & errors
00241   static void NonWriterTypeError(morkEnv* ev);
00242   static void NilWriterStoreError(morkEnv* ev);
00243   static void NilWriterBudError(morkEnv* ev);
00244   static void NilWriterStreamError(morkEnv* ev);
00245   static void NilWriterFileError(morkEnv* ev);
00246   static void UnsupportedPhaseError(morkEnv* ev);
00247 
00248 public: // utitlities
00249   void ChangeRowForm(morkEnv* ev, mork_cscode inNewForm);
00250   void ChangeDictForm(morkEnv* ev, mork_cscode inNewForm);
00251   void ChangeDictAtomScope(morkEnv* ev, mork_scope inScope);
00252 
00253 public: // inlines
00254   mork_bool DidStartDict() const { return mWriter_DidStartDict; }
00255   mork_bool DidEndDict() const { return mWriter_DidEndDict; }
00256   
00257   void IndentAsNeeded(morkEnv* ev, mork_size inDepth)
00258   { 
00259     if ( mWriter_LineSize > mWriter_MaxIndent )
00260       mWriter_LineSize = mWriter_Stream->PutIndent(ev, inDepth);
00261   }
00262   
00263   void IndentOverMaxLine(morkEnv* ev,
00264     mork_size inPendingSize, mork_size inDepth)
00265   { 
00266     if ( mWriter_LineSize + inPendingSize > mWriter_MaxLine )
00267       mWriter_LineSize = mWriter_Stream->PutIndent(ev, inDepth);
00268   }
00269 
00270 public: // delayed construction
00271 
00272   void MakeWriterStream(morkEnv* ev); // give writer a suitable stream
00273 
00274 public: // iterative/asynchronous writing
00275   
00276   mork_bool WriteMore(morkEnv* ev); // call until IsWritingDone() is true
00277   
00278   mork_bool IsWritingDone() const // don't call WriteMore() any longer?
00279   { return mWriter_Phase == morkWriter_kPhaseWritingDone; }
00280 
00281 public: // marking all content dirty
00282   mork_bool DirtyAll(morkEnv* ev);
00283   // DirtyAll() visits every store sub-object and marks 
00284   // them dirty, including every table, row, cell, and atom.  The return
00285   // equals ev->Good(), to show whether any error happened.  This method is
00286   // intended for use in the beginning of a "compress commit" which writes
00287   // all store content, whether dirty or not.  We dirty everything first so
00288   // that later iterations over content can mark things clean as they are
00289   // written, and organize the process of serialization so that objects are
00290   // written only at need (because of being dirty).  Note the method can 
00291   // stop early when any error happens, since this will abort any commit.
00292 
00293 public: // group commit transactions
00294 
00295   mork_bool StartGroup(morkEnv* ev);
00296   mork_bool CommitGroup(morkEnv* ev);
00297   mork_bool AbortGroup(morkEnv* ev);
00298 
00299 public: // phase methods
00300   mork_bool OnNothingDone(morkEnv* ev);
00301   mork_bool OnDirtyAllDone(morkEnv* ev);
00302   mork_bool OnPutHeaderDone(morkEnv* ev);
00303 
00304   mork_bool OnRenumberAllDone(morkEnv* ev);
00305 
00306   mork_bool OnStoreAtomSpaces(morkEnv* ev);
00307   mork_bool OnAtomSpaceAtomAids(morkEnv* ev);
00308 
00309   mork_bool OnStoreRowSpacesTables(morkEnv* ev);
00310   mork_bool OnRowSpaceTables(morkEnv* ev);
00311   mork_bool OnTableRowArray(morkEnv* ev);
00312 
00313   mork_bool OnStoreRowSpacesRows(morkEnv* ev);
00314   mork_bool OnRowSpaceRows(morkEnv* ev);
00315 
00316   mork_bool OnContentDone(morkEnv* ev);
00317   mork_bool OnWritingDone(morkEnv* ev);
00318 
00319 public: // writing dict items first pass
00320   mork_bool PutTableDict(morkEnv* ev, morkTable* ioTable);
00321   mork_bool PutRowDict(morkEnv* ev, morkRow* ioRow);
00322 
00323 public: // writing node content second pass
00324   mork_bool PutTable(morkEnv* ev, morkTable* ioTable);
00325   mork_bool PutRow(morkEnv* ev, morkRow* ioRow);
00326   mork_bool PutRowCells(morkEnv* ev, morkRow* ioRow);
00327   mork_bool PutVerboseRowCells(morkEnv* ev, morkRow* ioRow);
00328   
00329   mork_bool PutCell(morkEnv* ev, morkCell* ioCell, mork_bool inWithVal);
00330   mork_bool PutVerboseCell(morkEnv* ev, morkCell* ioCell, mork_bool inWithVal);
00331   
00332   mork_bool PutTableChange(morkEnv* ev, const morkTableChange* inChange);
00333 
00334 public: // other writer methods
00335 
00336   mork_bool IsYarnAllValue(const mdbYarn* inYarn);
00337 
00338   mork_size WriteYarn(morkEnv* ev, const mdbYarn* inYarn);
00339   // return number of atom bytes written on the current line (which
00340   // implies that escaped line breaks will make the size value smaller
00341   // than the entire yarn's size, since only part goes on a last line).
00342 
00343   mork_size WriteAtom(morkEnv* ev, const morkAtom* inAtom);
00344   // return number of atom bytes written on the current line (which
00345   // implies that escaped line breaks will make the size value smaller
00346   // than the entire atom's size, since only part goes on a last line).
00347 
00348   void WriteAllStoreTables(morkEnv* ev);
00349   void WriteAtomSpaceAsDict(morkEnv* ev, morkAtomSpace* ioSpace);
00350   
00351   void WriteTokenToTokenMetaCell(morkEnv* ev, mork_token inCol,
00352     mork_token inValue);
00353   void WriteStringToTokenDictCell(morkEnv* ev, const char* inCol, 
00354     mork_token inValue);
00355   // Note inCol should begin with '(' and end with '=', with col in between.
00356 
00357   void StartDict(morkEnv* ev);
00358   void EndDict(morkEnv* ev);
00359 
00360   void StartTable(morkEnv* ev, morkTable* ioTable);
00361   void EndTable(morkEnv* ev);
00362 
00363 public: // typesafe refcounting inlines calling inherited morkNode methods
00364   static void SlotWeakWriter(morkWriter* me,
00365     morkEnv* ev, morkWriter** ioSlot)
00366   { morkNode::SlotWeakNode((morkNode*) me, ev, (morkNode**) ioSlot); }
00367   
00368   static void SlotStrongWriter(morkWriter* me,
00369     morkEnv* ev, morkWriter** ioSlot)
00370   { morkNode::SlotStrongNode((morkNode*) me, ev, (morkNode**) ioSlot); }
00371 };
00372 
00373 //3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789
00374 
00375 #endif /* _MORKTABLEROWCURSOR_ */