gagan%netscape.com 2c6d5481f0 Merge from NuCache_BRANCH. Will not affect the build process.
git-svn-id: svn://10.0.0.236/trunk@8529 18797224-902f-48f8-a5cc-f745e15eee43
1998-08-26 18:35:28 +00:00

262 lines
7.8 KiB
C++

/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
#include "nsTOC.h"
#include "plstr.h"
#include "memory.h"
#include "prlog.h"
static const PRUint32 kTOC_FLAT_FILE_VERSION = 1;
static const PRUint32 kTOC_MAGIC_NUMBER = 19712809;
static const PRUint32 kTOC_HEADER_SIZE = 2* sizeof(PRUint32);
//TODO change this to a memory mapped file!
nsTOC::nsTOC(const char* i_pFilename, nsFlatFile* i_pFlatFile):
m_pFilename( new char[PL_strlen(i_pFilename) + 1]),
m_pFD(0),
m_bIsValid(PR_FALSE),
m_pFlatFile(i_pFlatFile),
m_Entries(1)
{
PL_strcpy(m_pFilename, i_pFilename);
Init();
}
nsTOC::~nsTOC()
{
delete[] m_pFilename;
if (m_pFD)
{
PR_Close(m_pFD);
m_pFD = 0;
}
}
/*
nsrefcnt nsTOC::AddRef(void)
{
return ++m_RefCnt;
}
nsrefcnt nsTOC::Release(void)
{
if (--m_RefCnt == 0)
{
delete this;
return 0;
}
return m_RefCnt;
}
nsresult nsTOC::QueryInterface(const nsIID& aIID,
void** aInstancePtrResult)
{
return NS_OK;
}
*/
void nsTOC::Init(void)
{
if (m_pFilename)
{
m_pFD = PR_Open(m_pFilename, PR_CREATE_FILE | PR_RDWR, 0600);
if (!m_pFD)
{
return;
}
PRFileInfo info;
// if the file is just being created then write magic number
// and flat file version, else verify
if (PR_SUCCESS == PR_GetOpenFileInfo(m_pFD, &info))
{
PRInt32 status;
if (info.size > 0)
{
char buf[kTOC_HEADER_SIZE];
//verify
status = PR_Read(m_pFD, &buf, kTOC_HEADER_SIZE);
if (status > 0)
{
char* cur_ptr = &buf[0];
PRUint32 test;
COPY_INT32(&test, cur_ptr);
if (test != kTOC_MAGIC_NUMBER)
{
PR_Close(m_pFD);
m_pFD = 0;
//PR_ASSERT(!"Bad TOC file!");
return;
}
cur_ptr += sizeof(PRUint32);
COPY_INT32(&test, cur_ptr);
if (test != kTOC_FLAT_FILE_VERSION)
{
PR_Close(m_pFD);
m_pFD = 0;
//PR_ASSERT(!"Bad version of TOC file!");
return;
}
// Number of entries in the TOC
status = PR_Read(m_pFD, &buf, sizeof(PRUint32));
if (status > 0)
{
cur_ptr = &buf[0];
COPY_INT32(&m_Entries, cur_ptr);
}
//Read in the list of entries
nsFFEntry* pCurrent;
Serialize(pCurrent, PR_TRUE);
//There has got to be a free entry.
PR_ASSERT(pCurrent /*&& pCurrent->IsValid() TODO*/);
m_pContents = pCurrent;
PRUint32 count = 1; //Definitely one!
Serialize(pCurrent, PR_TRUE);
while (pCurrent)
{
count++;
m_pContents->AddEntry(pCurrent);
Serialize(pCurrent, PR_TRUE);
}
PR_ASSERT(count == m_Entries);
//Everything was as expected so
m_bIsValid = PR_TRUE;
}
}
else
{
//write out
char* buf = new char[kTOC_HEADER_SIZE];
char* cur_ptr = buf;
COPY_INT32((void*) cur_ptr, &kTOC_MAGIC_NUMBER);
cur_ptr += sizeof(PRUint32);
COPY_INT32((void*) cur_ptr, &kTOC_FLAT_FILE_VERSION);
status = PR_Write(m_pFD, buf, kTOC_HEADER_SIZE);
// Number of entries in the TOC
COPY_INT32((void*)buf, &m_Entries);
status = PR_Write(m_pFD, buf, sizeof(PRUint32));
delete[] buf;
//Since the TOC is being created afresh, reset the flat file with everything marked as
//free.
m_pContents = new nsFFEntry(
0,
m_pFlatFile->HeaderSize(),
m_pFlatFile->Size()-m_pFlatFile->HeaderSize());
//Serialize the only entry-
Serialize(m_pContents);
m_bIsValid = PR_TRUE;
}
}
}
}
nsFFEntry* nsTOC::AddEntry(PRUint32 i_Size)
{
if (i_Size > FreeEntry()->Size())
{
//Garbage collect
}
nsFFEntry* pEntry = new nsFFEntry(
NextID(),
FreeEntry()->FirstObject()->Offset(),
i_Size);
return pEntry;
}
PRBool nsTOC::Serialize(nsFFEntry* io_Entry, PRBool bRead )
{
PR_ASSERT(m_pFD);
if (bRead)
{
io_Entry = new nsFFEntry();
if (!io_Entry)
return PR_FALSE;
char* buf = new char[sizeof(PRUint32)];
PRUint32 temp, objects, size;
//Read ID
PR_Read(m_pFD, buf, sizeof(PRUint32));
COPY_INT32(&temp, buf);
io_Entry->ID(temp);
//Read number of objects
PR_Read(m_pFD, buf, sizeof(PRUint32));
COPY_INT32(&objects, buf);
//Read objects
for (int i= objects; i>0; --i)
{
PR_Read(m_pFD, buf, sizeof(PRUint32));
COPY_INT32(&temp, buf);
PR_Read(m_pFD, buf, sizeof(PRUint32));
COPY_INT32(&size, buf);
io_Entry->AddObject(new nsFFObject(io_Entry->ID(), temp, size));
}
delete[] buf;
PR_ASSERT(io_Entry->Objects() == objects);
if (io_Entry->Objects() != objects)
return PR_FALSE;
return PR_TRUE;
}
else
{
PR_ASSERT(io_Entry);
if (!io_Entry)
return PR_FALSE;
//TODO speed this up by increasing the buffer size to write out
//more than one int at a time!
char* buf = new char[sizeof(PRUint32)];
PRUint32 temp;
//Write ID
temp = io_Entry->ID();
COPY_INT32((void*) buf, &temp);
PR_Write(m_pFD, buf, sizeof(PRUint32));
//Write number of Objects
temp = io_Entry->Objects();
COPY_INT32((void*) buf, &temp);
PR_Write(m_pFD, buf, sizeof(PRUint32));
//Write Objects
if (temp > 0)
{
nsFFObject* current = io_Entry->FirstObject();
while (current)
{
PR_ASSERT(current->ID() == io_Entry->ID());
//Offset
temp = current->Offset();
COPY_INT32((void*) buf, &temp);
PR_Write(m_pFD, buf, sizeof(PRUint32));
//size
temp = current->Size();
COPY_INT32((void*) buf, &temp);
PR_Write(m_pFD, buf, sizeof(PRUint32));
current = current->Next();
}
}
delete[] buf;
return PR_TRUE;
}
return PR_FALSE;
}