PhraseNode::PhraseNode(UINT64 filePos, OnDiskWrapper &onDiskWrapper)
  :m_counts(onDiskWrapper.GetNumCounts())
{
  // load saved node
  m_filePos = filePos;

  size_t countSize = onDiskWrapper.GetNumCounts();

  std::fstream &file = onDiskWrapper.GetFileSource();
  file.seekg(filePos);
  CHECK(filePos == (UINT64)file.tellg());

  file.read((char*) &m_numChildrenLoad, sizeof(UINT64));
  
  size_t memAlloc = GetNodeSize(m_numChildrenLoad, onDiskWrapper.GetSourceWordSize(), countSize);
  m_memLoad = (char*) malloc(memAlloc);

  // go to start of node again
  file.seekg(filePos);
  CHECK(filePos == (UINT64)file.tellg());

  // read everything into memory
  file.read(m_memLoad, memAlloc);
  CHECK(filePos + memAlloc == (UINT64)file.tellg());

  // get value
  m_value = ((UINT64*)m_memLoad)[1];

  // get counts
  float *memFloat = (float*) (m_memLoad + sizeof(UINT64) * 2);

  CHECK(countSize == 1);
  m_counts[0] = memFloat[0];

  m_memLoadLast = m_memLoad + memAlloc;
}
void PhraseNode::Save(OnDiskWrapper &onDiskWrapper, size_t pos, size_t tableLimit)
{
  CHECK(!m_saved);

  // save this node
  m_targetPhraseColl.Sort(tableLimit);
  m_targetPhraseColl.Save(onDiskWrapper);
  m_value = m_targetPhraseColl.GetFilePos();

  size_t numCounts = onDiskWrapper.GetNumCounts();

  size_t memAlloc = GetNodeSize(GetSize(), onDiskWrapper.GetSourceWordSize(), numCounts);
  char *mem = (char*) malloc(memAlloc);
  //memset(mem, 0xfe, memAlloc);

  size_t memUsed = 0;
  UINT64 *memArray = (UINT64*) mem;
  memArray[0] = GetSize(); // num of children
  memArray[1] = m_value;   // file pos of corresponding target phrases
  memUsed += 2 * sizeof(UINT64);

  // count info
  float *memFloat = (float*) (mem + memUsed);
  CHECK(numCounts == 1);
  memFloat[0] = (m_counts.size() == 0) ? DEFAULT_COUNT : m_counts[0]; // if count = 0, put in very large num to make sure its still used. HACK
  memUsed += sizeof(float) * numCounts;

  // recursively save chm_countsildren
  ChildColl::iterator iter;
  for (iter = m_children.begin(); iter != m_children.end(); ++iter) {
    const Word &childWord = iter->first;
    PhraseNode &childNode = iter->second;

    // recursive
    if (!childNode.Saved())
      childNode.Save(onDiskWrapper, pos + 1, tableLimit);

    char *currMem = mem + memUsed;
    size_t wordMemUsed = childWord.WriteToMemory(currMem);
    memUsed += wordMemUsed;

    UINT64 *memArray = (UINT64*) (mem + memUsed);
    memArray[0] = childNode.GetFilePos();
    memUsed += sizeof(UINT64);

  }

  // save this node
  //Moses::DebugMem(mem, memAlloc);
  CHECK(memUsed == memAlloc);

  std::fstream &file = onDiskWrapper.GetFileSource();
  m_filePos = file.tellp();
  file.seekp(0, ios::end);
  file.write(mem, memUsed);

  UINT64 endPos = file.tellp();
  CHECK(m_filePos + memUsed == endPos);

  free(mem);

  m_children.clear();
  m_saved = true;
}