int32 OsclFileCache::Open(uint32 mode, uint32 size)
//Called to open the cache for a newly opened file.
//The NativeOpen was just called prior to this and was successful.
{
    //should not be called with zero-size cache.
    OSCL_ASSERT(size > 0);

    //Save the mode
    _mode = mode;

    //open logger object only if logging is enabled on this
    //file
    if (iContainer.iLogger)
        iLogger = PVLogger::GetLoggerObject("OsclFileCache");
    else
        iLogger = NULL;

    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_DEBUG,
                    (0, "OsclFileCache(0x%x)::Open mode %d size %d", this, mode, size));

    // Create the movable cache.
    // Re-allocate it if the size has changed.
    if (_movableCache.pBuffer
            && size != _movableCache.capacity)
    {
        OSCL_FREE(_movableCache.pBuffer);
        _movableCache.pBuffer = NULL;
    }
    if (!_movableCache.pBuffer
            && size > 0)
    {
        _movableCache.pBuffer = (uint8*)OSCL_MALLOC(size);
    }
    if (!_movableCache.pBuffer)
    {
        PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_DEBUG,
                        (0, "OsclFileCache(0x%x)::Open ERROR no memory %d", this));
        return (-1);//error
    }
    _movableCache.capacity = _movableCache.usableSize = size;
    _movableCache.filePosition = 0;
    _movableCache.updateStart = _movableCache.updateEnd = 0;
    _movableCache.currentPos = _movableCache.endPos = 0;

    //Position the cache at zero.
    SetCachePosition(0);

    //get initial file size & native position
    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_DEBUG,
                    (0, "OsclFileCache(0x%x)::Open CallingNativeSize", this));
    _fileSize = iContainer.CallNativeSize();
    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_DEBUG,
                    (0, "OsclFileCache(0x%x)::Open CallingNativeTell", this));
    _nativePosition = iContainer.CallNativeTell();

    return 0;
}
예제 #2
0
void OsclFileCache::Close()
{
    //flush any cache updates
    SetCachePosition(0);

    //free the memory for cache buffer
    if (_pCacheBufferStart)
    {
        OSCL_FREE(_pCacheBufferStart);
        _pCacheBufferStart = NULL;
    }
}
/**
 * Seek
 *
 * @param [in] offset from origin
 * @param [in] origin: either SEEKSET, SEEKCUR, or SEEKEND
 *
 * @return 0 for success.
 */
int32 OsclFileCache::Seek(TOsclFileOffset offset, Oscl_File::seek_type origin)
{
    //figure out the file position we're trying to seek to
    TOsclFileOffset pos;
    switch (origin)
    {
        case Oscl_File::SEEKCUR:
            pos = Tell() + offset;
            break;
        case Oscl_File::SEEKSET:
            pos = 0 + offset;
            break;
        case Oscl_File::SEEKEND:
            pos = FileSize() + offset;
            break;
        default:
            PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_DEBUG,
                            (0, "OsclFileCache(0x%x)::Seek ERROR invalid origin %d", this, origin));
            return (-1);//error-- invalid origin!
    }

    //don't allow seeking outside valid file size
    if (pos < 0 || pos > FileSize())
    {
        PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_DEBUG,
                        (0, "OsclFileCache(0x%x)::Seek ERROR invalid seek position %d", this, pos));
        return -1;//error
    }

    if (_curCache->Contains(pos))
    {
        //Seek in cur cache
        _curCache->currentPos = (uint32)(pos - _curCache->filePosition);
    }
    else
    {
        //Seek outside cache
        int32 retval = SetCachePosition(pos);
        if (retval != 0)
        {
            PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_DEBUG,
                            (0, "OsclFileCache(0x%x)::Seek ERROR SetPosition error %d", this, retval));
            return retval;//error
        }
    }
    return 0;
}
예제 #4
0
/**
 * FillCacheFromFile
 *
 * Fill cache from current virtual position.
 * Flush any updated data first.
 * This will return a full cache, or
 *  if at EOF, a partial or empty cache.
 *
 * @param void
 *
 * @return 0 on success.
 */
int32 OsclFileCache::FillCacheFromFile()
{
    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_DEBUG,
                    (0, "OsclFileCache(0x%x)::FillCacheFromFile vpos %d", this, Tell()));

    //flush and relocate cache to current virtual
    //position if needed
    TOsclFileOffset newpos = Tell();
    if (_cacheFilePosition != newpos
            || (_cacheUpdateEnd - _cacheUpdateStart) > 0)
    {
        int32 retval = SetCachePosition(newpos);
        if (retval != 0)
        {
            PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_DEBUG,
                            (0, "OsclFileCache(0x%x)::FillCacheFromFile ERROR SetCachePosition failed", this));
            return retval;//error!
        }
    }

    //Now seek to the read position if needed.
    if (_nativePosition != newpos)
    {
        int32 result = iContainer.CallNativeSeek(newpos, Oscl_File::SEEKSET);
        if (result != 0)
        {
            PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_DEBUG,
                            (0, "OsclFileCache(0x%x)::FillCacheFromFile ERROR CallNativeSeek failed", this));
            return result;//error!
        }

        //keep track of the native file position
        _nativePosition = newpos;
    }

    //try to fill the cache.  If we hit EOF we won't get a full cache.
    _endCachePos = iContainer.CallNativeRead((void*)_pCacheBufferStart, 1, _cacheSize);

    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_DEBUG,
                    (0, "OsclFileCache(0x%x)::FillCacheFromFile got %d bytes", this, _endCachePos));

    //update native position
    _nativePosition += _endCachePos;

    return 0;//success
}
예제 #5
0
int32 OsclFileCache::Open(uint32 mode, uint32 size)
//Called to open the cache for a newly opened file.
//The NativeOpen was just called prior to this and was successful.
{
    //should not be called with zero-size cache.
    OSCL_ASSERT(size > 0);

    //Save the open parameters
    _cacheSize = size;
    _mode = mode;

    //open logger object only if logging is enabled on this
    //file
    if (iContainer.iLogger)
        iLogger = PVLogger::GetLoggerObject("OsclFileCache");
    else
        iLogger = NULL;

    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_DEBUG,
                    (0, "OsclFileCache(0x%x)::Open mode %d size %d", this, mode, size));

    // allocate memory for cache
    // free any old buffer since its size may be different
    if (_pCacheBufferStart)
    {
        OSCL_FREE(_pCacheBufferStart);
        _pCacheBufferStart = NULL;
    }
    _pCacheBufferStart = (uint8*)OSCL_MALLOC(_cacheSize);
    if (!_pCacheBufferStart)
    {
        PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_DEBUG,
                        (0, "OsclFileCache(0x%x)::Open ERROR no memory %d", this));
        return (-1);//error
    }

    //initialise the cache variables
    SetCachePosition(0);

    //get initial file size & native position
    _fileSize = iContainer.CallNativeSize();
    _nativePosition = iContainer.CallNativeTell();

    return 0;
}
/**
 * Write
 * Writes data from the input buffer into
 * the buffer supplied (inputBuffer)
 *
 * @param inputBuffer pointer to buffer of type void
 * @param size   element size in bytes
 * @param numelements
 *               number of elements to write
 *
 * @return returns the number of elements written
 */
uint32 OsclFileCache::Write(const void* inputBuffer, uint32 size, uint32 numelements)
{
    if (inputBuffer == NULL)
    {
        PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_DEBUG,
                        (0, "OsclFileCache(0x%x)::Write ERROR invalid arg ", this));
        return 0;
    }

    //write the data only in the mode we are permitted to write
    if ((_mode & Oscl_File::MODE_READWRITE)
            || (_mode & Oscl_File::MODE_APPEND)
            || (_mode & Oscl_File::MODE_READ_PLUS))
    {
        ;//ok to write
    }
    else
    {
        PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_DEBUG,
                        (0, "OsclFileCache(0x%x)::Write ERROR invalid mode for writing ", this));
        return 0;//invalid mode.
    }

    //In Append mode, write always happens at the end of file,
    //so relocate the cache now if needed.
    if ((_mode & Oscl_File::MODE_APPEND)
            && (Tell() != FileSize()))
    {
        int32 result = SetCachePosition(FileSize());
        if (result != 0)
        {
            PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_DEBUG,
                            (0, "OsclFileCache(0x%x)::Write ERROR SetCachePosition failed. ", this));
            return 0;
        }
    }

    //prep current cache for writing
    int32 result = _curCache->PrepWrite();
    if (result != 0)
    {
        PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_DEBUG,
                        (0, "OsclFileCache(0x%x)::Write ERROR PrepWrite failed. ", this));
        return 0;
    }

    uint8* srcBuf = (uint8*)(inputBuffer);
    uint32 bytesToWrite = size * numelements;

    //write into cache, flushing as needed when it fills up.

    while (bytesToWrite > 0)
    {
        OSCL_ASSERT(_curCache->usableSize >= _curCache->currentPos);
        uint32 spaceInCache = _curCache->usableSize - _curCache->currentPos;
        if (spaceInCache > 0)
        {
            //write to cache
            uint32 thisWrite = (spaceInCache > bytesToWrite) ? bytesToWrite : spaceInCache;

            oscl_memcpy((_curCache->pBuffer + _curCache->currentPos), srcBuf, thisWrite);
            bytesToWrite -= thisWrite;
            srcBuf += thisWrite;

            //keep track of the range of data in the cache that has been updated.
            if (_curCache->updateEnd == _curCache->updateStart)
            {
                //first update in this cache
                _curCache->updateStart = _curCache->currentPos;
                _curCache->updateEnd = _curCache->currentPos + thisWrite;
            }
            else
            {
                //cache has already been updated.  Expand the updated range
                //to include this update.

                if (_curCache->currentPos < _curCache->updateStart)
                    _curCache->updateStart = _curCache->currentPos;

                if ((_curCache->currentPos + thisWrite) > _curCache->updateEnd)
                    _curCache->updateEnd = _curCache->currentPos + thisWrite;
            }

            //update the virtual position.
            _curCache->currentPos += thisWrite;

            //extend the end of cache data if needed
            if (_curCache->endPos < _curCache->currentPos)
                _curCache->endPos = _curCache->currentPos;

            //extend the virtual file size if needed.
            if (_fileSize < (TOsclFileOffset)(_curCache->filePosition + _curCache->endPos))
                _fileSize = _curCache->filePosition + _curCache->endPos;

            //consistency checks.  if these asserts fire, there is
            //a logic error.
            OSCL_ASSERT(_curCache->updateEnd >= _curCache->updateStart);
            OSCL_ASSERT(_curCache->endPos >= _curCache->currentPos);
        }
        else
        {
            //entire cache is full-- re-set cache to current vpos and prep
            //for write
            int32 retval = SetCachePosition(Tell());
            if (retval != 0)
            {
                PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_DEBUG,
                                (0, "OsclFileCache(0x%x)::Write ERROR SetCachePosition failed ", this));
                break;//error!
            }
            retval = _curCache->PrepWrite();
            if (retval != 0)
            {
                PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_DEBUG,
                                (0, "OsclFileCache(0x%x)::Write ERROR PrepWrite failed ", this));
                break;//error!
            }
        }
    }

    //return number of whole elements written.
    return (size) ? ((size*numelements - bytesToWrite) / size) : 0;

}
/**
 * Read
 * Reads data from the file cache buffer and copies into
 * the buffer supplied (outputBuffer)
 *
 * @param outputBuffer pointer to buffer of type void
 * @param size   element size in bytes
 * @param numelements
 *               max number of elements to read
 *
 * @return returns the number of full elements actually read, which
 *         may be less than count if an error occurs or if the end
 *         of the file is encountered before reaching count.
 */
uint32 OsclFileCache::Read(void* outputBuffer, uint32 size, uint32 numelements)
{
    if (!outputBuffer)
    {
        PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_DEBUG,
                        (0, "OsclFileCache(0x%x)::Read ERROR invalid arg ", this));
        return 0;
    }

    //check for a valid read mode
    if ((_mode & Oscl_File::MODE_READWRITE)
            || (_mode & Oscl_File::MODE_READ)
            || (_mode & Oscl_File::MODE_APPEND)
            || (_mode & Oscl_File::MODE_READ_PLUS))
    {
        ;//ok to write
    }
    else
    {
        PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_DEBUG,
                        (0, "OsclFileCache(0x%x)::Read ERROR invalid mode for reading ", this));
        return 0;//invalid mode.
    }

    uint8* destBuf = (uint8*)(outputBuffer);

    uint32 bytesToRead = numelements * size;

    // If file is smaller than requested data amount, reduce bytesToRead to the lowest multiple
    // of size that we can read
    uint32 bytesLeftInFile = (uint32)(FileSize() - Tell());
    if (bytesToRead > bytesLeftInFile)
    {
        numelements = bytesLeftInFile / size;
        bytesToRead = numelements * size;
    }

    if (bytesToRead)
    {
        //prep current cache for reading
        int32 retval = _curCache->PrepRead();
        if (retval != 0)
        {
            PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_DEBUG,
                            (0, "OsclFileCache(0x%x)::Read ERROR PrepRead failed ", this));
            return 0;
        }
    }

    //pull data out of the cache until we run out, then re-fill the cache
    //as needed until we get the desired amount.

    while (bytesToRead > 0)
    {
        OSCL_ASSERT(_curCache->endPos >= _curCache->currentPos);
        uint32 bytesInCache = (uint32)(_curCache->endPos - _curCache->currentPos);

        if (bytesInCache > 0)
        {
            //pull out either all data in cache, or number of bytes required,
            //whichever is less
            uint32 thisRead = (bytesInCache > bytesToRead) ? bytesToRead : bytesInCache;

            oscl_memcpy(destBuf, _curCache->pBuffer + _curCache->currentPos, thisRead);
            bytesToRead -= thisRead;
            destBuf += thisRead;

            //update virtual position
            _curCache->currentPos += thisRead;
        }
        else
        {
            //no more data-- reposition & refill the cache
            int32 retval = SetCachePosition(Tell());
            if (retval != 0)
            {
                PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_DEBUG,
                                (0, "OsclFileCache(0x%x)::Read ERROR SetCachePosition failed ", this));
                break;//error!
            }
            retval = _curCache->PrepRead();
            if (retval != 0)
            {
                PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_DEBUG,
                                (0, "OsclFileCache(0x%x)::Read ERROR PrepRead failed ", this));
                break;//error!
            }

            //When at EOF, cache will be empty after fillcache,
            //so break out of loop.
            if (_curCache->endPos - _curCache->currentPos == 0)
                break;
        }
    }

    //return number of whole elements read.
    return (size) ? ((size*numelements - bytesToRead) / size) : 0;

}
예제 #8
0
/**
 * WriteCacheToFile
 *
 * Writes any updated data in the cache to disk, but does not
 * otherwise alter cache position or contents.  Existing cache
 * data is still available for read.
 *
 * Has a side effect of adjusting the native file position.
 *
 * @param void
 *
 * @return 0 if successful and a non-zero value otherwise
 */
int32 OsclFileCache::WriteCacheToFile()
{
    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_DEBUG,
                    (0, "OsclFileCache(0x%x)::WriteCacheToFile vpos %d", this, Tell()));

    if (_cacheUpdateEnd > _cacheUpdateStart)
    {
        uint32 bytesToWrite = (_cacheUpdateEnd - _cacheUpdateStart);

        PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_DEBUG,
                        (0, "OsclFileCache(0x%x)::WriteCacheToFile nbytes %d filepos %d start %d end %d "
                         , this, bytesToWrite, _cacheFilePosition, _cacheUpdateStart, _cacheUpdateEnd));

        //Seek to the correct write location in the file if needed

        TOsclFileOffset pos = _cacheFilePosition + _cacheUpdateStart;

        if (_nativePosition != pos)
        {
            if (_mode & Oscl_File::MODE_APPEND)
            {
                //In Append mode, writes automatically happen at the end of file so there is no
                //need to seek.
                ;
            }
            else
            {
                //seek to the write location
                int32 retval = iContainer.CallNativeSeek(pos, Oscl_File::SEEKSET);
                if (retval != 0)
                {
                    PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_DEBUG,
                                    (0, "OsclFileCache(0x%x)::WriteCacheToFile ERROR CallNativeSeek failed", this));
                    return retval;//error!
                }
            }

            _nativePosition = pos;
        }

        //write the updated data range.
        int32 retval = iContainer.CallNativeWrite(_pCacheBufferStart + _cacheUpdateStart, 1, bytesToWrite);

        //keep track of the native file position.
        _nativePosition += retval;

        //clear the updated data range.
        _cacheUpdateStart = _cacheUpdateEnd = 0;

        if ((uint32)retval == bytesToWrite)
            return 0;//success!

        PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_DEBUG,
                        (0, "OsclFileCache(0x%x)::WriteCacheToFile ERROR CallNativeWrite only wrote %d of %d", this, retval, bytesToWrite));

        //At this point, the cache is corrupt, since we lost data.
        //Recover by checking actual native file values, emptying the cache,
        //and locating it as close as possible to the desired position.
        _fileSize = iContainer.CallNativeSize();
        _nativePosition = iContainer.CallNativeTell();
        TOsclFileOffset newpos = Tell();
        if (newpos > _fileSize)
            newpos = _fileSize;
        SetCachePosition(newpos);

        return (-1); //error
    }
    return 0;//success-- nothing to do
}
예제 #9
0
/**
 * Seek
 *
 * @param [in] offset from origin
 * @param [in] origin: either SEEKSET, SEEKCUR, or SEEKEND
 *
 * @return 0 for success.
 */
int32 OsclFileCache::Seek(TOsclFileOffset offset, Oscl_File::seek_type origin)
{
    //figure out the file position we're trying to seek to
    TOsclFileOffset pos;
    switch (origin)
    {
        case Oscl_File::SEEKCUR:
            pos = Tell() + offset;
            break;
        case Oscl_File::SEEKSET:
            pos = 0 + offset;
            break;
        case Oscl_File::SEEKEND:
            pos = FileSize() + offset;
            break;
        default:
            PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_DEBUG,
                            (0, "OsclFileCache(0x%x)::Seek ERROR invalid origin %d", this, origin));
            return (-1);//error-- invalid origin!
    }

    //don't allow seeking outside valid file size
    if ((uint32)pos < 0 || (uint32)pos > (uint32)FileSize())
    {
        PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_DEBUG,
                        (0, "OsclFileCache(0x%x)::Seek ERROR invalid seek position %d", this, pos));
        return -1;//error
    }

    //when seek is in current cache range, just update the
    //virtual position.
    if ((uint32)_cacheFilePosition <= (uint32)pos && (uint32)pos <= (uint32)(_cacheFilePosition + _endCachePos))
    {
        _currentCachePos = (uint32)(pos - _cacheFilePosition);
        return 0;//success
    }

    //else seeking outside cache

    //Seek to the real target location.
    //Always use SEEKSET because the actual file end or current
    //position may not be accurate at this point.
    int32 retval;
    retval = iContainer.CallNativeSeek(pos, Oscl_File::SEEKSET);
    if (retval != 0)
    {
        PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_DEBUG,
                        (0, "OsclFileCache(0x%x)::Seek ERROR CallNativeSeek failed", this));
        return retval;//error
    }

    //update native position
    _nativePosition = pos;

    //Relocate the cache & virtual position
    retval = SetCachePosition(pos);

    if (retval != 0)
    {
        PVLOGGER_LOGMSG(PVLOGMSG_INST_LLDBG, iLogger, PVLOGMSG_DEBUG,
                        (0, "OsclFileCache(0x%x)::Seek ERROR SetCachePosition failed", this));
    }

    return retval;
}