//we are assumed to be in a mutex here
PBYTE DBRead(DWORD ofs,int bytesRequired,int *bytesAvail)
{

    int part1sect;
    int part2sect;


    part1sect = FindSectionForOffset(ofs);
    if (ofs%CACHESECTIONSIZE+bytesRequired<CACHESECTIONSIZE) {
        //only one section required
        if(part1sect==-1) {
            part1sect=FindLRUSection();
            LoadSection(part1sect,ofs);
        }
        cacheSectionInfo[part1sect].lastUsed=++lastUseCounter;
        if(bytesAvail!=NULL) *bytesAvail=cacheSectionInfo[part1sect].ofsBase+CACHESECTIONSIZE-ofs;
        return pDbCache+part1sect*CACHESECTIONSIZE+(ofs-cacheSectionInfo[part1sect].ofsBase);
    }
    //two sections are required
    part2sect=FindSectionForOffset(ofs+CACHESECTIONSIZE);
    if(part1sect!=-1) {
        if(part2sect==-1) {  //first part in cache, but not second part
            if(part1sect==CACHESECTIONCOUNT-1) MoveSection(&part1sect,0);
            LoadSection(part1sect+1,ofs+CACHESECTIONSIZE);
        }
        else if(part2sect!=part1sect+1) {   //both parts are in cache, but not already consecutive
            if(part1sect==CACHESECTIONCOUNT-1) {
                //first part is at end, move to before second part
                if(part2sect==0) //second part is at start: need to move both
                    MoveSection(&part2sect,1);
                MoveSection(&part1sect,part2sect-1);
            }
            else  //move second part to after first part
                MoveSection(&part2sect,part1sect+1);
        }
    }
    else {
        if(part2sect==-1) {  //neither section is in cache
            part1sect=0;
            part2sect=1;
            LoadSection(part1sect,ofs);
            LoadSection(part2sect,ofs+CACHESECTIONSIZE);
        }
        else {    //part 2 is in cache, but not part 1
            if(part2sect==0) MoveSection(&part2sect,1);
            part1sect=part2sect-1;
            LoadSection(part1sect,ofs);
        }
    }
    //both sections are now consecutive, starting at part1sect
    cacheSectionInfo[part1sect].lastUsed=++lastUseCounter;
    cacheSectionInfo[part1sect+1].lastUsed=++lastUseCounter;
    if(bytesAvail!=NULL) *bytesAvail=cacheSectionInfo[part1sect+1].ofsBase+CACHESECTIONSIZE-ofs;
    return pDbCache+part1sect*CACHESECTIONSIZE+(ofs-cacheSectionInfo[part1sect].ofsBase);
}
void UMovieSceneSection::InitialPlacement(const TArray<UMovieSceneSection*>& Sections, float InStartTime, float InEndTime, bool bAllowMultipleRows)
{
	check(StartTime <= EndTime);

	StartTime = InStartTime;
	EndTime = InEndTime;
	RowIndex = 0;

	if (bAllowMultipleRows)
	{
		while (OverlapsWithSections(Sections) != nullptr)
		{
			++RowIndex;
		}
	}
	else
	{
		for (;;)
		{
			const UMovieSceneSection* OverlappedSection = OverlapsWithSections(Sections);

			if (OverlappedSection == nullptr)
			{
				break;
			}

			TSet<FKeyHandle> KeyHandles;
			MoveSection(OverlappedSection->GetEndTime() - StartTime, KeyHandles);
		}
	}
}