/**************************************************************
 * 
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 * 
 *   http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 * 
 *************************************************************/



// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_store.hxx"

#include "stortree.hxx"

#include "sal/types.h"
#include "osl/diagnose.h"

#include "store/types.h"

#include "storbase.hxx"
#include "storbios.hxx"

using namespace store;

/*========================================================================
 *
 * OStoreBTreeNodeData implementation.
 *
 *======================================================================*/
/*
 * OStoreBTreeNodeData.
 */
OStoreBTreeNodeData::OStoreBTreeNodeData (sal_uInt16 nPageSize)
	: OStorePageData (nPageSize)
{
	base::m_aGuard.m_nMagic = store::htonl(self::theTypeId);
	base::m_aDescr.m_nUsed  = store::htons(self::thePageSize); // usageCount(0)
	self::m_aGuard.m_nMagic = store::htonl(0); // depth(0)

	sal_uInt16 const n = capacityCount();
	T const          t;

	for (sal_uInt16 i = 1; i < n; i++)
		m_pData[i] = t;
}

/*
 * find.
 */
sal_uInt16 OStoreBTreeNodeData::find (const T& t) const
{
	register sal_Int32 l = 0;
	register sal_Int32 r = usageCount() - 1;

	while (l < r)
	{
		register sal_Int32 const m = ((l + r) >> 1);

		if (t.m_aKey == m_pData[m].m_aKey)
			return ((sal_uInt16)(m));
		if (t.m_aKey < m_pData[m].m_aKey)
			r = m - 1;
		else
			l = m + 1;
	}

	sal_uInt16 const k = ((sal_uInt16)(r));
	if ((k < capacityCount()) && (t.m_aKey < m_pData[k].m_aKey))
		return(k - 1);
	else
		return(k);
}

/*
 * insert.
 */
void OStoreBTreeNodeData::insert (sal_uInt16 i, const T& t)
{
	sal_uInt16 const n = usageCount();
	sal_uInt16 const m = capacityCount();
	if ((n < m) && (i < m))
	{
		// shift right.
		memmove (&(m_pData[i + 1]), &(m_pData[i]), (n - i) * sizeof(T));

		// insert.
		m_pData[i] = t;
        usageCount (n + 1);
	}
}

/*
 * remove.
 */
void OStoreBTreeNodeData::remove (sal_uInt16 i)
{
	sal_uInt16 const n = usageCount();
	if (i < n)
	{
		// shift left.
		memmove (&(m_pData[i]), &(m_pData[i + 1]), (n - i - 1) * sizeof(T));

		// truncate.
		m_pData[n - 1] = T();
        usageCount (n - 1);
	}
}

#if 0  /* NYI */
/*
 * merge (with right page).
 */
void OStoreBTreeNodeData::merge (const self& rPageR)
{
    sal_uInt16 const n = usageCount();
    sal_uInt16 const m = rPageR.usageCount();
    if ((n + m) <= capacityCount())
	{
		memcpy (&(m_pData[n]), &(rPageR.m_pData[0]), m * sizeof(T));
		usageCount (n + m);
	}
}
#endif

/*
 * split (left half copied from right half of left page).
 */
void OStoreBTreeNodeData::split (const self& rPageL)
{
	sal_uInt16 const h = capacityCount() / 2;
	memcpy (&(m_pData[0]), &(rPageL.m_pData[h]), h * sizeof(T));
	truncate (h);
}

/*
 * truncate.
 */
void OStoreBTreeNodeData::truncate (sal_uInt16 n)
{
	sal_uInt16 const m = capacityCount();
	T const          t;

	for (sal_uInt16 i = n; i < m; i++)
		m_pData[i] = t;
	usageCount (n);
}

/*========================================================================
 *
 * OStoreBTreeNodeObject implementation.
 *
 *======================================================================*/
/*
 * guard.
 */
storeError OStoreBTreeNodeObject::guard (sal_uInt32 nAddr)
{
	return PageHolderObject< page >::guard (m_xPage, nAddr);
}

/*
 * verify.
 */
storeError OStoreBTreeNodeObject::verify (sal_uInt32 nAddr) const
{
	return PageHolderObject< page >::verify (m_xPage, nAddr);
}

/*
 * split.
 */
storeError OStoreBTreeNodeObject::split (
	sal_uInt16                 nIndexL,
	PageHolderObject< page > & rxPageL,
	OStorePageBIOS           & rBIOS)
{
    PageHolderObject< page > xPage (m_xPage);
    if (!xPage.is())
        return store_E_InvalidAccess;

	// Check left page usage.
    if (!rxPageL.is())
        return store_E_InvalidAccess;
	if (!rxPageL->querySplit())
		return store_E_None;

    // Construct right page.
    PageHolderObject< page > xPageR;
    if (!xPageR.construct (rBIOS.allocator()))
		return store_E_OutOfMemory;

	// Split right page off left page.
	xPageR->split (*rxPageL);
	xPageR->depth (rxPageL->depth());

	// Allocate right page.
    self aNodeR (xPageR.get());
	storeError eErrCode = rBIOS.allocate (aNodeR);
	if (eErrCode != store_E_None)
		return eErrCode;

	// Truncate left page.
	rxPageL->truncate (rxPageL->capacityCount() / 2);

	// Save left page.
	self aNodeL (rxPageL.get());
	eErrCode = rBIOS.saveObjectAt (aNodeL, aNodeL.location());
	if (eErrCode != store_E_None)
		return eErrCode;

	// Insert right page.
	OStorePageLink aLink (xPageR->location());
	xPage->insert (nIndexL + 1, T(xPageR->m_pData[0].m_aKey, aLink));

	// Save this page and leave.
	return rBIOS.saveObjectAt (*this, location());
}

/*
 * remove (down to leaf node, recursive).
 */
storeError OStoreBTreeNodeObject::remove (
	sal_uInt16         nIndexL,
	OStoreBTreeEntry & rEntryL,
	OStorePageBIOS &   rBIOS)
{
    PageHolderObject< page > xImpl (m_xPage);
    page & rPage = (*xImpl);

	// Check depth.
    storeError eErrCode = store_E_None;
	if (rPage.depth())
	{
		// Check link entry.
        T const aEntryL (rPage.m_pData[nIndexL]);
		if (!(rEntryL.compare (aEntryL) == T::COMPARE_EQUAL))
			return store_E_InvalidAccess;

		// Load link node.
		self aNodeL;
		eErrCode = rBIOS.loadObjectAt (aNodeL, aEntryL.m_aLink.location());
		if (eErrCode != store_E_None)
			return eErrCode;

		// Recurse: remove from link node.
		eErrCode = aNodeL.remove (0, rEntryL, rBIOS);
		if (eErrCode != store_E_None)
			return eErrCode;

		// Check resulting link node usage.
        PageHolderObject< page > xPageL (aNodeL.get());
		if (xPageL->usageCount() == 0)
		{
			// Free empty link node.
			eErrCode = rBIOS.free (xPageL->location());
			if (eErrCode != store_E_None)
				return eErrCode;

			// Remove index.
			rPage.remove (nIndexL);
			touch();
		}
		else
		{
#if 0   /* NYI */
			// Check for right sibling.
			sal_uInt16 const nIndexR = nIndexL + 1;
			if (nIndexR < rPage.usageCount())
			{
				// Load right link node.
				self aNodeR;
				eErrCode = rBIOS.loadObjectAt (aNodeR, rPage.m_pData[nIndexR].m_aLink.location());
				if (eErrCode == store_E_None)
				{
					if (rPageL.queryMerge (rPageR))
					{
						rPageL.merge (rPageR);

						eErrCode = rBIOS.free (rPageR.location());
					}
				}
			}
#endif  /* NYI */

			// Relink.
			rPage.m_pData[nIndexL].m_aKey = xPageL->m_pData[0].m_aKey;
			touch();
		}
	}
	else
	{
		// Check leaf entry.
		if (!(rEntryL.compare (rPage.m_pData[nIndexL]) == T::COMPARE_EQUAL))
			return store_E_NotExists;

		// Save leaf entry.
		rEntryL = rPage.m_pData[nIndexL];

		// Remove leaf index.
		rPage.remove (nIndexL);
		touch();
	}

	// Check for modified node.
	if (dirty())
	{
		// Save this page.
		eErrCode = rBIOS.saveObjectAt (*this, location());
	}

	// Done.
    return eErrCode;
}

/*========================================================================
 *
 * OStoreBTreeRootObject implementation.
 *
 *======================================================================*/
/*
 * testInvariant.
 * Precond: root node page loaded.
 */
bool OStoreBTreeRootObject::testInvariant (char const * message)
{
    OSL_PRECOND(m_xPage.get() != 0, "OStoreBTreeRootObject::testInvariant(): Null pointer");
    bool result = ((m_xPage->location() - m_xPage->size()) == 0);
    OSL_POSTCOND(result, message); (void) message;
    return result;
}

/*
 * loadOrCreate.
 */
storeError OStoreBTreeRootObject::loadOrCreate (
    sal_uInt32       nAddr,
    OStorePageBIOS & rBIOS)
{
    storeError eErrCode = rBIOS.loadObjectAt (*this, nAddr);
    if (eErrCode != store_E_NotExists)
        return eErrCode;

    eErrCode = construct<page>(rBIOS.allocator());
    if (eErrCode != store_E_None)
        return eErrCode;

    eErrCode = rBIOS.allocate (*this);
    if (eErrCode != store_E_None)
        return eErrCode;

    // Notify caller of the creation.
    (void) testInvariant("OStoreBTreeRootObject::loadOrCreate(): leave");
    return store_E_Pending;
}

/*
 * change.
 */
storeError OStoreBTreeRootObject::change (
	PageHolderObject< page > & rxPageL,
	OStorePageBIOS &           rBIOS)
{
    PageHolderObject< page > xPage (m_xPage);
    (void) testInvariant("OStoreBTreeRootObject::change(): enter");

    // Save root location.
    sal_uInt32 const nRootAddr = xPage->location();

    // Construct new root.
    if (!rxPageL.construct (rBIOS.allocator()))
		return store_E_OutOfMemory;

    // Save this as prev root.
    storeError eErrCode = rBIOS.allocate (*this);
    if (eErrCode != store_E_None)
		return store_E_OutOfMemory;

    // Setup new root.
    rxPageL->depth (xPage->depth() + 1);
    rxPageL->m_pData[0] = xPage->m_pData[0];
    rxPageL->m_pData[0].m_aLink = xPage->location();
    rxPageL->usageCount(1);

	// Change root.
    rxPageL.swap (xPage);
    {
        PageHolder tmp (xPage.get());
        tmp.swap (m_xPage);
    }

	// Save this as new root and finish.
	eErrCode = rBIOS.saveObjectAt (*this, nRootAddr);
    (void) testInvariant("OStoreBTreeRootObject::change(): leave");
    return eErrCode;
}

/*
 * find_lookup (w/o split()).
 * Precond: root node page loaded.
 */
storeError OStoreBTreeRootObject::find_lookup (
    OStoreBTreeNodeObject & rNode,  // [out]
    sal_uInt16 &            rIndex, // [out]
    OStorePageKey const &   rKey,
    OStorePageBIOS &        rBIOS)
{
    // Init node w/ root page.
    (void) testInvariant("OStoreBTreeRootObject::find_lookup(): enter");
    {
        PageHolder tmp (m_xPage);
        tmp.swap (rNode.get());
    }

    // Setup BTree entry.
    T const entry (rKey);

    // Check current page.
    PageHolderObject< page > xPage (rNode.get());
    for (; xPage->depth() > 0; xPage = rNode.makeHolder< page >())
    {
        // Find next page.
        page const & rPage = (*xPage);
        sal_uInt16 const i = rPage.find(entry);
        sal_uInt16 const n = rPage.usageCount();
        if (!(i < n))
        {
            // Path to entry not exists (Must not happen(?)).
            return store_E_NotExists;
        }

        // Check address.
        sal_uInt32 const nAddr = rPage.m_pData[i].m_aLink.location();
        if (nAddr == STORE_PAGE_NULL)
        {
            // Path to entry not exists (Must not happen(?)).
            return store_E_NotExists;
        }

        // Load next page.
        storeError eErrCode = rBIOS.loadObjectAt (rNode, nAddr);
        if (eErrCode != store_E_None)
            return eErrCode;
    }

    // Find index.
    page const & rPage = (*xPage);
    rIndex = rPage.find(entry);
    if (!(rIndex < rPage.usageCount()))
        return store_E_NotExists;

    // Compare entry.
    T::CompareResult eResult = entry.compare(rPage.m_pData[rIndex]);
    OSL_POSTCOND(eResult != T::COMPARE_LESS, "store::BTreeRoot::find_lookup(): sort error");
    if (eResult == T::COMPARE_LESS)
        return store_E_Unknown;

    // Greater or Equal.
    (void) testInvariant("OStoreBTreeRootObject::find_lookup(): leave");
    return store_E_None;
}

/*
 * find_insert (possibly with split()).
 * Precond: root node page loaded.
 */
storeError OStoreBTreeRootObject::find_insert (
    OStoreBTreeNodeObject & rNode,  // [out]
    sal_uInt16 &            rIndex, // [out]
    OStorePageKey const &   rKey,
    OStorePageBIOS &        rBIOS)
{
    (void) testInvariant("OStoreBTreeRootObject::find_insert(): enter");

    // Check for RootNode split.
    PageHolderObject< page > xRoot (m_xPage);
    if (xRoot->querySplit())
    {
        PageHolderObject< page > xPageL;

        // Change root.
        storeError eErrCode = change (xPageL, rBIOS);
        if (eErrCode != store_E_None)
            return eErrCode;

        // Split left page (prev root).
        eErrCode = split (0, xPageL, rBIOS);
        if (eErrCode != store_E_None)
            return eErrCode;
	}

    // Init node w/ root page.
    {
        PageHolder tmp (m_xPage);
        tmp.swap (rNode.get());
    }
    
    // Setup BTree entry.
    T const entry (rKey);

	// Check current Page.
    PageHolderObject< page > xPage (rNode.get());
    for (; xPage->depth() > 0; xPage = rNode.makeHolder< page >())
	{
		// Find next page.
        page const & rPage = (*xPage);
		sal_uInt16 const i = rPage.find (entry);
        sal_uInt16 const n = rPage.usageCount();
		if (!(i < n))
		{
			// Path to entry not exists (Must not happen(?)).
			return store_E_NotExists;
		}

		// Check address.
		sal_uInt32 const nAddr = rPage.m_pData[i].m_aLink.location();
		if (nAddr == STORE_PAGE_NULL)
		{
			// Path to entry not exists (Must not happen(?)).
			return store_E_NotExists;
		}

		// Load next page.
        OStoreBTreeNodeObject aNext;
		storeError eErrCode = rBIOS.loadObjectAt (aNext, nAddr);
		if (eErrCode != store_E_None)
			return eErrCode;

		// Check for next node split.
        PageHolderObject< page > xNext (aNext.get());
		if (xNext->querySplit())
		{
			// Split next node.
			eErrCode = rNode.split (i, xNext, rBIOS);
			if (eErrCode != store_E_None)
				return eErrCode;

			// Restart.
			continue;
		}

        // Let next page be current.
        PageHolder tmp (aNext.get());
        tmp.swap (rNode.get());
    }

	// Find index.
    page const & rPage = (*xPage);
	rIndex = rPage.find(entry);
	if (rIndex < rPage.usageCount())
	{
		// Compare entry.
		T::CompareResult result = entry.compare (rPage.m_pData[rIndex]);
		OSL_POSTCOND(result != T::COMPARE_LESS, "store::BTreeRoot::find_insert(): sort error");
		if (result == T::COMPARE_LESS)
			return store_E_Unknown;

		if (result == T::COMPARE_EQUAL)
			return store_E_AlreadyExists;
	}

    // Greater or not (yet) existing.
    (void) testInvariant("OStoreBTreeRootObject::find_insert(): leave");
    return store_E_None;
}
