void CNodeLiveWriter::Done() { assert( !m_done && m_valid ); m_done = true; int numChildren = m_children.size(); for (int i = 0; i < numChildren; ++i) { CNodeLiveWriter* pChild = m_Writer.GetNodeLive( m_children[i] ); if (!pChild->IsDone()) pChild->Done(); } if (!m_childrenAreCompacted) { CompactPendingChildren(); m_childrenAreCompacted = true; } if (m_IDParent != XMLCPB_INVALID_ID) { CNodeLiveWriter* pParent = m_Writer.GetNodeLive( m_IDParent ); pParent->ChildIsDone(); } else { Compact(); } }
void CWriter::Init( const char* pNameRootNode, const char* pFileName ) { m_isSavingIntoFile = pFileName!=NULL; bool useStreaming = m_isSavingIntoFile; m_mainBuffer.Init( this, useStreaming ); m_tableTags.Init( this ); m_tableAttrNames.Init( this ); m_tableStrData.Init( this ); m_tableStrDataConstants.Init( this ); m_tableAttrSets.Init( this ); if (m_isSavingIntoFile) { #ifdef XMLCPB_DEBUGUTILS CDebugUtils::SetLastFileNameSaved( pFileName ); #endif #ifdef XMLCPB_COLLECT_STATS CNodeLiveWriter::m_stats.Reset(); CAttrWriter::m_statistics.Reset(); #endif m_tableStrDataConstants.CreateStringsFromConstants(); { ScopedSwitchToGlobalHeap switchToGlobalHeap; // This object may live beyond the end of level shutdown. Use global heap for allocations m_compressor = new CZLibCompressor(pFileName); // Don't delete this when finished, it is held by the compressor thread until finished with and destroyed by it. } } CNodeLiveWriter* pRoot = CreateAndAddLiveNode( pNameRootNode ); assert( pRoot->GetID()==XMLCPB_ROOTNODE_ID ); }
bool CNodeLiveWriterRef::IsValid() const { if (m_nodeId == XMLCPB_INVALID_ID) return false; CNodeLiveWriter* pNode = m_Writer.GetNodeLive( m_nodeId ); return (pNode->IsValid() && pNode->GetSafeCheckID() == m_safecheckID); }
void CNodeLiveWriter::CompactPendingChildren() { int numChildren = m_children.size(); if (numChildren == 0) return; for (int i = 0; i < numChildren; ++i) { CNodeLiveWriter* pChild = m_Writer.GetNodeLive( m_children[i] ); pChild->Compact(); } m_globalIdLastChildInBlock.push_back( m_Writer.GetLastUsedGlobalId()); // the global id is just the order of the node in the final big buffer m_children.clear(); }
CNodeLiveWriter* CNodeLiveWriterRef::GetNode() const { if (m_nodeId == XMLCPB_INVALID_ID) return NULL; CNodeLiveWriter* pNode = m_Writer.GetNodeLive( m_nodeId ); if (!pNode->IsValid() || pNode->GetSafeCheckID() != m_safecheckID) { assert( false ); return NULL; } return pNode; }
void CNodeLiveWriterRef::CopyFrom( const CNodeLiveWriterRef &other ) { m_nodeId = other.m_nodeId; m_pNode_Debug = other.m_pNode_Debug; m_safecheckID = other.m_safecheckID; if (m_nodeId != XMLCPB_INVALID_ID) { CNodeLiveWriter* pNode = m_Writer.GetNodeLive( m_nodeId ); if (!pNode->IsValid() || pNode->GetSafeCheckID() != m_safecheckID) { assert( false ); m_nodeId = XMLCPB_INVALID_ID; m_pNode_Debug = NULL; } } }
CNodeLiveWriterRef CNodeLiveWriter::AddChildNode( const char* pChildName ) { assert( !m_done && m_valid ); m_totalAmountChildren++; // only 1 child can be not done at any time if (!m_children.empty()) { CNodeLiveWriter* pPreviousChild = m_Writer.GetNodeLive( m_children.back()); if (!pPreviousChild->IsDone()) pPreviousChild->Done(); } assert( m_children.size() <= CHILDREN_PER_BLOCK ); if (m_children.size() == CHILDREN_PER_BLOCK) CompactPendingChildren(); // CNodeLiveWriter* pChild = m_Writer.CreateAndAddLiveNode( pChildName ); m_children.push_back( pChild->GetID()); pChild->SetParent( GetID()); return CNodeLiveWriterRef( m_Writer, pChild->GetID()); }
CNodeLiveWriterRef::CNodeLiveWriterRef( CWriter &Writer, NodeLiveID nodeId ) : m_Writer(Writer) { m_nodeId = nodeId; m_pNode_Debug = NULL; if (m_nodeId == XMLCPB_INVALID_ID) return; CNodeLiveWriter* pNode = m_Writer.GetNodeLive( m_nodeId ); if (!pNode->IsValid()) { assert( false ); return; } m_pNode_Debug = pNode; m_safecheckID = pNode->GetSafeCheckID(); }
void CWriter::LogStatistics() { CryLog("-----------Binary SaveGame Writer statistics--------------"); //// live nodes info { int nodesCreated = 0; int children = 0; int attrs = 0; for (int i=0; i<m_liveNodes.size(); ++i) { CNodeLiveWriter* pNode = m_liveNodes[i]; if (pNode) { assert( !pNode->IsValid() ); nodesCreated++; children += pNode->m_children.capacity(); attrs += pNode->m_attrs.capacity(); } } CryLog("live nodes. created: %d/%d children: %d attrs: %d", nodesCreated, MAX_NUM_LIVE_NODES, children, attrs ); } CryLog( "stringtables. Tags: %d/%d (%d kb) AttrNames: %d/%d (%d kb) stringsData: %d/%d (%d kb) total memory string tables: %d kb", m_tableTags.GetNumStrings(), MAX_NUM_TAGS, m_tableTags.GetDataSize()/1024, m_tableAttrNames.GetNumStrings(), MAX_NUM_NAMES, m_tableAttrNames.GetDataSize()/1024, m_tableStrData.GetNumStrings(), MAX_NUM_STRDATA, m_tableStrData.GetDataSize()/1024, ( m_tableTags.GetDataSize() + m_tableAttrNames.GetDataSize() + m_tableStrData.GetDataSize() )/1024 ); CryLog("Nodes. total: %d maxNumChildrenPerNode: %d total children: %d maxAttrsPerNode:%d total attrs: %d AttrSets: %d (%d kb)", CNodeLiveWriter::m_stats.m_totalNodesCreated, CNodeLiveWriter::m_stats.m_maxNumChildren, CNodeLiveWriter::m_stats.m_totalChildren, CNodeLiveWriter::m_stats.m_maxNumAttrs, CNodeLiveWriter::m_stats.m_totalAttrs, m_tableAttrSets.GetNumSets(), m_tableAttrSets.GetDataSize()/1024 ); { uint32 totalSize = m_mainBuffer.GetDataSize() + m_tableAttrNames.GetDataSize() + m_tableStrData.GetDataSize() + m_tableTags.GetDataSize() + sizeof( SFileHeader ) + m_tableAttrSets.GetDataSize(); CryLog("size: total: %d (%d kb) nodes basic info: %d attr: %d tagsStringTable: %d attrStringTable: %d dataStringTable: %d attrSets: %d", totalSize, totalSize/1024, CNodeLiveWriter::m_stats.m_totalSizeNodeData, CNodeLiveWriter::m_stats.m_totalSizeAttrData, m_tableTags.GetDataSize(), m_tableAttrNames.GetDataSize(), m_tableStrData.GetDataSize(), m_tableAttrSets.GetDataSize() ); } CryLog("-------------------"); }
CNodeLiveWriter* CWriter::CreateAndAddLiveNode( const char* pName ) { assert( m_firstFreeLiveNode<m_liveNodes.size() ); // create and place in vector NodeLiveID ID = m_firstFreeLiveNode; StringID stringID = m_tableTags.GetStringID( pName ); CNodeLiveWriter* pNode = m_liveNodes[ID]; if (!pNode) { pNode = new CNodeLiveWriter( *this, ID, stringID, m_safecheckIDCounter ); m_liveNodes[ID] = pNode; } else pNode->Reuse( stringID, m_safecheckIDCounter ); m_safecheckIDCounter++; // find the now first free live node bool found = false; for (int i=m_firstFreeLiveNode+1; i<m_liveNodes.size(); ++i) { CNodeLiveWriter* pNodeIter = m_liveNodes[i]; if (pNodeIter==NULL || !pNodeIter->IsValid()) { found = true; m_firstFreeLiveNode = i; break; } } assert( found ); return pNode; }
void CWriter::Done() { CNodeLiveWriter* pRoot = GetNodeLive( XMLCPB_ROOTNODE_ID ); if (!pRoot->IsDone()) pRoot->Done(); }