private FileEntry allocate ( int len ) { synchronized ( freeList ) { // lookup a free entry of sufficient size SortedSet < FileEntry > candidates = freeList . tailSet ( new FileEntry ( 0 , len ) ) ; for ( Iterator < FileEntry > it = candidates . iterator ( ) ; it . hasNext ( ) ; ) { FileEntry free = it . next ( ) ; // ignore entries that are still in use by concurrent readers if ( free . isLocked ( ) ) continue ; // There's no race condition risk between locking the entry on // loading and checking whether it's locked (or store allocation), // because for the entry to be lockable, it needs to be in the // entries collection, in which case it's not in the free list. // The only way an entry can be found in the free list is if it's // been removed, and to remove it, lock on "entries" needs to be // acquired, which is also a pre-requisite for loading data. // found one, remove from freeList it . remove ( ) ; return allocateExistingEntry ( free , len ) ; } // no appropriate free section available, append at end of file FileEntry fe = new FileEntry ( filePos , len ) ; filePos += len ; if ( trace ) log . tracef ( "New entry allocated at %d:%d, %d free entries, file size is %d" , fe . offset , fe . size , freeList . size ( ) , filePos ) ; return fe ; } }
Allocates the requested space in the file .