Ejemplo n.º 1
0
/**********************************************************************
 *                          DumpMapFileBlocks()
 *
 * Read and dump a .MAP file... simply dump all blocks sequentially.
 **********************************************************************/
static int DumpMapFileBlocks(const char *pszFname)
{
    FILE        *fp;
    TABRawBinBlock *poBlock;
    int         nOffset = 0;
    VSIStatBuf  sStatBuf;

    /*---------------------------------------------------------------------
     * Try to open source file
     * Note: we use stat() to fetch the file size.
     *--------------------------------------------------------------------*/
    if ( VSIStat(pszFname, &sStatBuf) == -1 )
    {
        printf("stat() failed for %s\n", pszFname);
        return -1;
    }

    fp = fopen(pszFname, "rb");
    if (fp == NULL)
    {
        printf("Failed to open %s\n", pszFname);
        return -1;
    }


    /*---------------------------------------------------------------------
     * Read/Dump blocks until EOF is reached
     *--------------------------------------------------------------------*/
    while (nOffset < sStatBuf.st_size )
    {
        poBlock = TABCreateMAPBlockFromFile(fp, nOffset, 512);

        if (poBlock)
        {
            poBlock->Dump();
            printf("\n");
            delete poBlock;
        }
        else
        {
            // An error happened (could be EOF)... abort now.
            break;
        }

        nOffset += 512;
    }

    /*---------------------------------------------------------------------
     * Cleanup and exit.
     *--------------------------------------------------------------------*/
    fclose(fp);

    return 0;
}
Ejemplo n.º 2
0
/**********************************************************************
 *                          DumpMapFileBlockDetails()
 *
 * Read and dump specified map file block.
 **********************************************************************/
static int DumpMapFileBlockDetails(const char *pszFname, int nOffset)
{
    FILE        *fp;
    TABRawBinBlock *poBlock;

    /*---------------------------------------------------------------------
     * Try to open source file
     * Note: we use stat() to fetch the file size.
     *--------------------------------------------------------------------*/
    fp = fopen(pszFname, "rb");
    if (fp == NULL)
    {
        printf("Failed to open %s\n", pszFname);
        return -1;
    }

    /*---------------------------------------------------------------------
     * Read/Dump blocks until EOF is reached
     *--------------------------------------------------------------------*/
    poBlock = TABCreateMAPBlockFromFile(fp, nOffset, 512);

    if (poBlock)
    {
        switch(poBlock->GetBlockClass())
        {
          case TABMAP_OBJECT_BLOCK:
            ((TABMAPObjectBlock*)poBlock)->Dump(NULL, TRUE);
            break;
          default:
            poBlock->Dump(NULL);
        }

        printf("\n");
        delete poBlock;
    }

    /*---------------------------------------------------------------------
     * Cleanup and exit.
     *--------------------------------------------------------------------*/
    fclose(fp);

    return 0;
}
Ejemplo n.º 3
0
/**********************************************************************
 *                   TABMAPIndexBlock::AddEntry()
 *
 * Recursively search the tree until we encounter the best leaf to
 * contain the specified object MBR and add the new entry to it.
 *
 * In the even that the selected leaf node would be full, then it will be
 * split and this split can propagate up to its parent, etc.
 *
 * If bAddInThisNodeOnly=TRUE, then the entry is added only locally and
 * we do not try to update the child node.  This is used when the parent 
 * of a node that is being splitted has to be updated.
 *
 * Returns 0 on success, -1 on error.
 **********************************************************************/
int     TABMAPIndexBlock::AddEntry(GInt32 nXMin, GInt32 nYMin,
                                   GInt32 nXMax, GInt32 nYMax,
                                   GInt32 nBlockPtr,
                                   GBool bAddInThisNodeOnly /*=FALSE*/)
{
    int i;
    GBool bFound = FALSE;

    if (m_eAccess != TABWrite && m_eAccess != TABReadWrite)
    {
        CPLError(CE_Failure, CPLE_AssertionFailed,
               "Failed adding index entry: File not opened for write access.");
        return -1;
    }

    /*-----------------------------------------------------------------
     * Update MBR now... even if we're going to split current node later.
     *----------------------------------------------------------------*/
    if (nXMin < m_nMinX)
        m_nMinX = nXMin;
    if (nXMax > m_nMaxX)
        m_nMaxX = nXMax;
    
    if (nYMin < m_nMinY)
        m_nMinY = nYMin;
    if (nYMax > m_nMaxY)
        m_nMaxY = nYMax;

    /*-----------------------------------------------------------------
     * Look for the best candidate to contain the new entry
     * __TODO__ For now we'll just look for the first entry that can 
     *          contain the MBR, but we could probably have a better
     *          search criteria to optimize the resulting tree
     *----------------------------------------------------------------*/

    /*-----------------------------------------------------------------
     * If bAddInThisNodeOnly=TRUE then we add the entry only locally
     * and do not need to look for the proper leaf to insert it.
     *----------------------------------------------------------------*/
    if (bAddInThisNodeOnly)
        bFound = TRUE;

    /*-----------------------------------------------------------------
     * First check if current child could be a valid candidate.
     *----------------------------------------------------------------*/
    if (!bFound &&
        m_poCurChild && (m_asEntries[m_nCurChildIndex].XMin <= nXMin &&
                         m_asEntries[m_nCurChildIndex].XMax >= nXMax &&
                         m_asEntries[m_nCurChildIndex].YMin <= nYMin &&
                         m_asEntries[m_nCurChildIndex].YMax >= nYMax ) )
    {

        bFound = TRUE;
    }

    /*-----------------------------------------------------------------
     * Scan all entries to find a valid candidate
     * We look for the entry whose center is the closest to the center
     * of the object to add.
     *----------------------------------------------------------------*/
    if (!bFound)
    {
        int nObjCenterX = (nXMin + nXMax)/2;
        int nObjCenterY = (nYMin + nYMax)/2;

        // Make sure blocks currently in memory are written to disk.
        if (m_poCurChild)
        {
            m_poCurChild->CommitToFile();
            delete m_poCurChild;
            m_poCurChild = NULL;
            m_nCurChildIndex = -1;
        }

        // Look for entry whose center is closest to center of new object
        int nBestCandidate = -1;
        int nMinDist = 2000000000;

        for(i=0; i<m_numEntries; i++)
        {
            int nX = (m_asEntries[i].XMin + m_asEntries[i].XMax)/2;
            int nY = (m_asEntries[i].YMin + m_asEntries[i].YMax)/2;

            int nDist = (nX-nObjCenterX)*(nX-nObjCenterX) +
                             (nY-nObjCenterY)*(nY-nObjCenterY);

            if (nBestCandidate==-1 || nDist < nMinDist)
            {
                nBestCandidate = i;
                nMinDist = nDist;
            }
        }
        
        if (nBestCandidate != -1)
        {
            // Try to load corresponding child... if it fails then we are
            // likely in a leaf node, so we'll add the new entry in the current
            // node.
            TABRawBinBlock *poBlock = NULL;

            // Prevent error message if referred block not committed yet.
            CPLPushErrorHandler(CPLQuietErrorHandler);

            if ((poBlock = TABCreateMAPBlockFromFile(m_fp, 
                                       m_asEntries[nBestCandidate].nBlockPtr,
                                       512, TRUE, TABReadWrite)) &&
                poBlock->GetBlockClass() == TABMAP_INDEX_BLOCK)
            {
                m_poCurChild = (TABMAPIndexBlock*)poBlock;
                poBlock = NULL;
                m_nCurChildIndex = nBestCandidate;
                m_poCurChild->SetParentRef(this);
                m_poCurChild->SetMAPBlockManagerRef(m_poBlockManagerRef);
                bFound = TRUE;
            }
                
            if (poBlock)
                delete poBlock;
            
            CPLPopErrorHandler();
            CPLErrorReset();
        }
    }

    if (bFound && !bAddInThisNodeOnly)
    {
        /*-------------------------------------------------------------
         * Found a child leaf... pass the call to it.
         *------------------------------------------------------------*/
        if (m_poCurChild->AddEntry(nXMin, nYMin, nXMax, nYMax, nBlockPtr) != 0)
            return -1;
    }
    else
    {
        /*-------------------------------------------------------------
         * Found no child to store new object... we're likely at the leaf
         * level so we'll store new object in current node
         *------------------------------------------------------------*/

        /*-------------------------------------------------------------
         * First thing to do is make sure that there is room for a new
         * entry in this node, and to split it if necessary.
         *------------------------------------------------------------*/
        if (GetNumFreeEntries() < 1)
        {
            if (m_poParentRef == NULL)
            {
                /*-----------------------------------------------------
                 * Splitting the root node adds one level to the tree, so
                 * after splitting we just redirect the call to the new
                 * child that's just been created.
                 *----------------------------------------------------*/
                if (SplitRootNode((nXMin+nXMax)/2, (nYMin+nYMax)/2) != 0)
                    return -1;  // Error happened and has already been reported

                CPLAssert(m_poCurChild);
                return m_poCurChild->AddEntry(nXMin, nYMin, nXMax, nYMax,
                                              nBlockPtr, TRUE);
            }
            else
            {
                /*-----------------------------------------------------
                 * Splitting a regular node
                 *----------------------------------------------------*/
                if (SplitNode((nXMin+nXMax)/2, (nYMin+nYMax)/2) != 0)
                    return -1; 
            }
        }

        if (InsertEntry(nXMin, nYMin, nXMax, nYMax, nBlockPtr) != 0)
            return -1;
    }

    /*-----------------------------------------------------------------
     * Update current node MBR and the reference to it in our parent.
     *----------------------------------------------------------------*/
    RecomputeMBR();

    return 0;
}