Ejemplo n.º 1
0
// Writing the indirect block to disk
void update_inode_pointers(int inode_index, int *array_blockptr, int num_pointers){
	if(num_pointers <= INODE_POINTERS-1){
		//direct pointers only 1-12
		int i;
		for(i=0;i<num_pointers-1;i++){
			inodes[inode_index].pointers[i]=array_blockptr[i];
		}
	}
	else{//hanles the indirect pointer
		int i;
		for(i=0;i<INODE_POINTERS-1;i++){
			inodes[inode_index].pointers[i]=array_blockptr[i];
		}
		int buffer[BLOCKSIZE/sizeof(int)];
		memset(buffer,0,BLOCKSIZE);
		if(inodes[inode_index].pointers[INODE_POINTERS-1]!=0){
		//append indirect pointer
			read_blocks(inodes[inode_index].pointers[INODE_POINTERS-1],1,buffer);
			int initial_number_of_indirects=get_num_pointers_inode(inode_index)-INODE_POINTERS;
			int final_number_of_indirects=num_pointers-INODE_POINTERS+1;
			int k;
			for(k=0;k<(final_number_of_indirects-initial_number_of_indirects)-1;k++){
				buffer[k+initial_number_of_indirects]=array_blockptr[(INODE_POINTERS-1)+initial_number_of_indirects+k];
			}
			write_blocks(inodes[inode_index].pointers[INODE_POINTERS-1],1,buffer);
		}
		else
		{
			//find a free block for indirect pointer
			int free_block=findfreeblock();
			inodes[inode_index].pointers[INODE_POINTERS-1]=free_block;
			markfreeblock(free_block); //mark it as occupied
 			//write inodes pointer into that block
			int j;
			for(j=0;j<(num_pointers-INODE_POINTERS+1)-1;j++){
				buffer[j]=array_blockptr[(INODE_POINTERS-1)+j];
			}	
			write_blocks(free_block,1,buffer);
		}
	}
}
Ejemplo n.º 2
0
int sfs_fwrite(int fileID, const char *buf, int length){

	int inode_index = dir_table[fileID].inode_number;
	int num_bytes_to_be_written=0;
	
	//index of rw pointers which points to the current block of inode
	int rw_index = file_des_t[fileID].rw_pointer/BLOCKSIZE+1; 
	//rw pointer offset within its current block
	int rw_offset = file_des_t[fileID].rw_pointer%BLOCKSIZE; 
	//calculate number of blocks to be written
	int num_blocks;
	if(length<BLOCKSIZE-rw_offset){
		num_blocks=1;
	}
	else{
		num_blocks=(length-(BLOCKSIZE-rw_offset))/BLOCKSIZE+2; //+2 for the first & last partial blocks
	}

	//writing to an empty file.
	if(inodes[inode_index].pointers[0]==0){
	//If file is empty all inode pointers will be zero 
	int num_bytes_to_be_written = 0;
	int inode_index=dir_table[fileID].inode_number;
	int num_blocks=length/(BLOCKSIZE)+1;
	
		if(num_blocks<=(INODE_POINTERS-1)){ 
			//don't need the indirect pointer
			int j;
			char write_block_buffer[BLOCKSIZE];
			for(j=0;j<num_blocks-1;j++){
				//reset buffer
				memset(write_block_buffer,0,BLOCKSIZE); 
				memcpy(write_block_buffer,buf,BLOCKSIZE); 
				inodes[inode_index].pointers[j]=findfreeblock();
				
				int flag = write_blocks(inodes[inode_index].pointers[j],1,write_block_buffer);
				if(flag){ 
				//if write into disk successfully,count the number of bytes written
					num_bytes_to_be_written = num_bytes_to_be_written + BLOCKSIZE;
				}
				//upodate the bitmap
				markfreeblock(inodes[inode_index].pointers[j]);
			}
			
			//last block could be a partial block
			char direct_pointer_buf_last[BLOCKSIZE];
			memset(direct_pointer_buf_last,0,BLOCKSIZE);
			memcpy(direct_pointer_buf_last, buf+(num_blocks-1)*BLOCKSIZE, length % BLOCKSIZE);
			//find a free block for the last direct pointer
			int last_direct_pointer = findfreeblock();
			markfreeblock(last_direct_pointer);
			inodes[inode_index].pointers[num_blocks-1] = last_direct_pointer;
			//if write into disk successfully then count the number of bytes
			int flag = write_blocks(last_direct_pointer,1,direct_pointer_buf_last);
			if(flag){
				num_bytes_to_be_written = num_bytes_to_be_written + length%BLOCKSIZE;
			}
			//update the information in file descriptor table
			file_des_t[fileID].rw_pointer = file_des_t[fileID].rw_pointer + length;
			inodes[inode_index].size = inodes[inode_index].size + num_bytes_to_be_written;
			
			//update info on the disk
			int inode_number = inode_index;
			int block_of_inode=inode_number/8+1; 
			char inode_update_buf[BLOCKSIZE];
			memset(inode_update_buf,0, BLOCKSIZE);
			read_blocks(block_of_inode, 1, inode_update_buf);
			memcpy((void *)inode_update_buf+(inode_number%8)*sizeof(INODE),(const void *) &inodes[inode_number], sizeof(INODE));
			write_blocks(block_of_inode, 1, inode_update_buf);	
			write_blocks(TOTAL_NUM_BLOCKS-1,1,free_bitmap);
			return num_bytes_to_be_written;
		}
		else{	
				//else need the indirect pointer
				int m;
				char write_block_buffer[BLOCKSIZE];
				//handle all the direct pointer firstly,similar as the above 
				for(m=0;m<INODE_POINTERS-1;m++){
				memset(write_block_buffer,0,BLOCKSIZE); 
				memcpy(write_block_buffer,buf,BLOCKSIZE); 
				inodes[inode_index].pointers[m]=findfreeblock();
				int flag=write_blocks(inodes[inode_index].pointers[m],1,write_block_buffer);
				if(flag){num_bytes_to_be_written+=BLOCKSIZE;}
				markfreeblock(inodes[inode_index].pointers[m]);
			}
			//now let's handle the indirect pointer
			int num_indirect_pointers = num_blocks-(INODE_POINTERS-1);
			//get free blocks for indirect pointer
			int freeblock_indirect = findfreeblock(); 
			markfreeblock(freeblock_indirect);
			int arr_of_indirectptr[num_indirect_pointers];
			int k;
			//write the remaining data to the indirect blocks
			char indirect_pointer_buf[BLOCKSIZE];
			for(k=0;k<num_indirect_pointers-1;k++){
				arr_of_indirectptr[k] = findfreeblock();
				memset(indirect_pointer_buf,0,BLOCKSIZE);
				memcpy(indirect_pointer_buf, buf+(INODE_POINTERS-1)*BLOCKSIZE + k*BLOCKSIZE, BLOCKSIZE);
				int flag=write_blocks(arr_of_indirectptr[k],1,indirect_pointer_buf);
				if(flag){num_bytes_to_be_written+=BLOCKSIZE;}
				markfreeblock(arr_of_indirectptr[k]);
			}
			//handle partial indirect block
			int last_indirect_pointers = findfreeblock();
			arr_of_indirectptr[num_indirect_pointers-1] = last_indirect_pointers;
			markfreeblock(last_indirect_pointers);
			char last_indirect_pointer_buf[BLOCKSIZE];
			memset(last_indirect_pointer_buf,0,BLOCKSIZE);
			memcpy(last_indirect_pointer_buf,buf+(INODE_POINTERS-1)*BLOCKSIZE+(num_indirect_pointers-1)*BLOCKSIZE,length%BLOCKSIZE);
			int flag = write_blocks(arr_of_indirectptr[num_indirect_pointers-1],1,last_indirect_pointer_buf);
			if(flag){
				num_bytes_to_be_written = num_bytes_to_be_written + length%BLOCKSIZE;
			}
			
			//Write the indirect pointers to the indirect block
			char indirect_buffer[BLOCKSIZE];
			memset(indirect_buffer,0,BLOCKSIZE);
			memcpy(indirect_buffer,arr_of_indirectptr,num_indirect_pointers*sizeof(int));
			write_blocks(freeblock_indirect,1,indirect_buffer); 
			inodes[inode_index].pointers[INODE_POINTERS-1]=freeblock_indirect;
			file_des_t[fileID].rw_pointer = file_des_t[fileID].rw_pointer + length;
			inodes[inode_index].size = inodes[inode_index].size + num_bytes_to_be_written;
			
			//update all the info into the disk
			int inode_number = inode_index;
			int block_of_inode = inode_number/8+1; 
			char inode_update_buf[BLOCKSIZE];
			memset(inode_update_buf,0, BLOCKSIZE);
			read_blocks(block_of_inode, 1, inode_update_buf);
			memcpy((void *)inode_update_buf+(inode_number%8)*sizeof(INODE),(const void *) &inodes[inode_number], sizeof(INODE));
			write_blocks(block_of_inode, 1, inode_update_buf);	
			write_blocks(TOTAL_NUM_BLOCKS-1,1,free_bitmap);
			return num_bytes_to_be_written;
			}	
		}

	//file not empty
	int number_pointers;
	if(get_num_pointers_inode(inode_index)>INODE_POINTERS-1){
		//first ignore the indrect pointers if it is used
		number_pointers = get_num_pointers_inode(inode_index)-1; 
	}
	else{
		number_pointers = get_num_pointers_inode(inode_index);
	}
	
	int array_blockptr[number_pointers];
	get_pointers(inode_index,array_blockptr,number_pointers);

	int num_unchanged_blocks = rw_index;
	//Update all those blocks	
	int updated_array_blockptr[num_blocks + num_unchanged_blocks];
	memset(updated_array_blockptr,0,num_blocks*sizeof(int));
	//Copy the unchanged blocks
	int p;
	for(p = 0; p < rw_index-1; p++){		
		updated_array_blockptr[p] = array_blockptr[p];
	}

	int s;
	for(s=rw_index-1; s<((num_blocks+num_unchanged_blocks)-1); s++){
		//Allocate additional free blocks when s>total intial blocks
		if(s>number_pointers-1){
			//free block is not enough, find more
				if(s==(num_blocks+num_unchanged_blocks-2)){
				//last block need to do a partial write
				int free_block = findfreeblock();
				updated_array_blockptr[s] = free_block;
				markfreeblock(free_block);
				if(num_blocks==1){
					update_block(updated_array_blockptr[s],(char*)(buf+(BLOCKSIZE-rw_offset)+BLOCKSIZE*(s-rw_index-1)),0,length);
					num_bytes_to_be_written=num_bytes_to_be_written+length;
				}
				else{
					if((BLOCKSIZE-rw_offset)+BLOCKSIZE*(s-rw_index)<0){
						return -1;//write in last block
					}
					update_block(updated_array_blockptr[s],(char*)(buf+(BLOCKSIZE-rw_offset)+BLOCKSIZE*(s-rw_index)),0,(length-(BLOCKSIZE-rw_offset))%BLOCKSIZE);	
					num_bytes_to_be_written = num_bytes_to_be_written + (length-(BLOCKSIZE-rw_offset)) % BLOCKSIZE;
				}			
			}
			else{				
				int free_block = findfreeblock();
				updated_array_blockptr[s] = free_block;
				markfreeblock(free_block);
				update_block(updated_array_blockptr[s],(char*)(buf+(BLOCKSIZE-rw_offset)+BLOCKSIZE*(s-rw_index)),0,BLOCKSIZE);	
				num_bytes_to_be_written = num_bytes_to_be_written + BLOCKSIZE;
			}	
		}
		else{
			markfreeblock(array_blockptr[s]);
			updated_array_blockptr[s] = array_blockptr[s];	
			if(s==rw_index-1){
				//Overwriting the first block of write
				if(num_blocks==1){	
					//if only updating one block - will not be filling the first block of the write.
					update_block(array_blockptr[s],(char*)buf,rw_offset,length);
					num_bytes_to_be_written = num_bytes_to_be_written + length;
				}
				else{
					update_block(array_blockptr[s],(char*)buf,rw_offset,BLOCKSIZE-rw_offset);
					num_bytes_to_be_written = num_bytes_to_be_written + BLOCKSIZE-rw_offset;
				}
			}
			else if(s==(num_blocks + num_unchanged_blocks-2)){
				//last block may be partial
				if(num_blocks==1){
					//special case for one block write.
					update_block(updated_array_blockptr[s],(char*)(buf+(BLOCKSIZE-rw_offset)+BLOCKSIZE*(s-rw_index-1)),0,length);
					num_bytes_to_be_written = num_bytes_to_be_written+length;
				}
				else{
					update_block(updated_array_blockptr[s],(char*)(buf+(BLOCKSIZE-rw_offset)+BLOCKSIZE*(s-rw_index-1)),0,(length-(BLOCKSIZE-rw_offset))%BLOCKSIZE);
					num_bytes_to_be_written = num_bytes_to_be_written+(length-(BLOCKSIZE-rw_offset))%BLOCKSIZE;
				}
			}
			else{
				//overwriting a full block
				update_block(array_blockptr[s],(char *)(buf+(BLOCKSIZE-rw_offset)+BLOCKSIZE*(s-rw_index-1)),0,BLOCKSIZE);
				num_bytes_to_be_written = num_bytes_to_be_written+BLOCKSIZE;
			}
		}
	}


	//storing the block pointers and put updated_array_blockptr into inode
	update_inode_pointers(inode_index,updated_array_blockptr,num_blocks+num_unchanged_blocks);
	int f_num_pointers = get_num_pointers_inode(inode_index);
	if(f_num_pointers > INODE_POINTERS-1){
		//exclude superblock if it is used
		f_num_pointers--;
	}
	int final_inode_pointers[f_num_pointers];
	get_pointers(inode_index,final_inode_pointers,f_num_pointers);
	file_des_t[fileID].rw_pointer+=length;
	inodes[inode_index].size = return_filesize(inode_index);
	
	//writing into disk
	int inode_number = inode_index;
	int block_of_inode=inode_number/8+1; 
	char inode_update_buf[BLOCKSIZE];
	memset(inode_update_buf,0, BLOCKSIZE);
	read_blocks(block_of_inode, 1, inode_update_buf);
	memcpy((void *)inode_update_buf+(inode_number%8)*sizeof(INODE),(const void *) &inodes[inode_number], sizeof(INODE));
	write_blocks(block_of_inode, 1, inode_update_buf);	
	write_blocks(TOTAL_NUM_BLOCKS-1,1,free_bitmap);
	return num_bytes_to_be_written;
}
OSCL_EXPORT_REF void OsclMemPoolResizableAllocator::deallocate(OsclAny* aPtr)
{
    // Check that the returned pointer is from the memory pool
    if (validateblock(aPtr) == false)
    {
        OSCL_LEAVE(OsclErrArgument);
    }

    // Retrieve the block info header and validate the info
    uint8* byteptr = (uint8*)aPtr;
    MemPoolBlockInfo* retblock = (MemPoolBlockInfo*)(byteptr - iBlockInfoAlignedSize);
    OSCL_ASSERT(retblock != NULL);
    OSCL_ASSERT(retblock->iBlockPreFence == OSCLMEMPOOLRESIZABLEALLOCATOR_PREFENCE_PATTERN);
    OSCL_ASSERT(retblock->iBlockPostFence == OSCLMEMPOOLRESIZABLEALLOCATOR_POSTFENCE_PATTERN);

    // Return the block to the memory pool buffer
    deallocateblock(*retblock);
    --(retblock->iParentBuffer->iNumOutstanding);

    // Check if user needs to be notified when block becomes available
    if (iCheckNextAvailable)
    {
        // Check if user is waiting for certain size
        if (iRequestedNextAvailableSize == 0)
        {
            // No so just make the callback
            iCheckNextAvailable = false;
            if (iObserver)
            {
                iObserver->freeblockavailable(iNextAvailableContextData);
            }
        }
        else
        {
            // Check if the requested size is available now
            if (findfreeblock(iRequestedNextAvailableSize + iBlockInfoAlignedSize) != NULL)
            {
                iCheckNextAvailable = false;
                if (iObserver)
                {
                    iObserver->freeblockavailable(iNextAvailableContextData);
                }
            }
            else if (iRequestedNextAvailableSize > iMemPoolBufferSize)
            {
                // The requested size is bigger than the set buffer size

                // Check if there is space to grow the buffer,
                if (iMemPoolBufferNumLimit == 0 || iMemPoolBufferList.size() < iMemPoolBufferNumLimit)
                {
                    // Available
                    iCheckNextAvailable = false;
                    if (iObserver)
                    {
                        iObserver->freeblockavailable(iNextAvailableContextData);
                    }
                }
                else
                {
                    // Not available so see if there is a buffer with
                    // no outstanding buffers which can be destroyed
                    // in the next allocate() call.
                    bool emptybufferfound = false;
                    for (uint32 j = 0; j < iMemPoolBufferList.size(); ++j)
                    {
                        if (iMemPoolBufferList[j]->iNumOutstanding == 0)
                        {
                            emptybufferfound = true;
                            break;
                        }
                    }

                    if (emptybufferfound)
                    {
                        iCheckNextAvailable = false;
                        if (iObserver)
                        {
                            iObserver->freeblockavailable(iNextAvailableContextData);
                        }
                    }
                }
            }
        }
    }
    if (iCheckFreeMemoryAvailable)
    {
        if (iRequestedAvailableFreeMemSize == 0)
        {
            // No so just make the callback
            iCheckFreeMemoryAvailable = false;
            if (iFreeMemPoolObserver)
            {
                iFreeMemPoolObserver->freememoryavailable(iFreeMemContextData);
            }
        }
        else
        {
            // Check if the requested size is available now
            if (getAvailableSize() >= iRequestedAvailableFreeMemSize)
            {
                iCheckFreeMemoryAvailable = false;
                if (iFreeMemPoolObserver)
                {
                    iFreeMemPoolObserver->freememoryavailable(iFreeMemContextData);
                }
            }
        }
    }

    // Decrement the refcount since deallocating succeeded
    removeRef();
}
OSCL_EXPORT_REF OsclAny* OsclMemPoolResizableAllocator::allocate(const uint32 aNumBytes)
{
    MemPoolBlockInfo* freeblock = NULL;
    uint32 alignednumbytes = oscl_mem_aligned_size(aNumBytes);

    if (aNumBytes == 0)
    {
        OSCL_LEAVE(OsclErrArgument);
        // OSCL_UNUSED_RETURN(NULL);    This statement was removed to avoid compiler warning for Unreachable Code
    }

    // Find a free block that would accomodate the requested size with a block info header
    freeblock = findfreeblock(alignednumbytes + iBlockInfoAlignedSize);
    if (freeblock == NULL)
    {
        //We could not find a free buffer of requested size. This could be due to:
        //1) We have not created even a single parent chunk (or in other words this is the first allocation)
        //2) We are out of memory and might need to expand


        // Check if the requested size is bigger than the specified buffer size
        // Some of the users of this allocator, count on the allocator to expand beyond the original size
        // specified in the constructor. These users do NOT use setMaxSzForNewMemPoolBuffer to control expansion size.
        // If they did then it is wrong usage and we fail the allocation.
        // For example the allocator was intialized with 200KB size,
        // and overtime a request is made for say 300KB. Users of the allocator expect the allocator to do one of the following:
        // 1) If iMemPoolBufferNumLimit has been set and it has been reached then see
        // if one of older blocks can be freed up and we allocate a new block of 300KB. If we cannot then alloc will fail.
        // 2) If iMemPoolBufferNumLimit has not set then simply allocate a new block of 300 KB. Note that if iMemPoolBufferNumLimit
        // is not set allocator expands indefinitely.
        if (alignednumbytes > iMemPoolBufferSize)
        {
            if (iMaxNewMemPoolBufferSz != 0)
            {
                //wrong usage - fail allocation
                if (iEnableNullPtrReturn)
                {
                    return NULL;
                }
                else
                {
                    // Leave with resource limitation
                    OSCL_LEAVE(OsclErrNoResources);
                }
            }
            // Would need to create a new buffer to accomodate this request
            // Check if another buffer can be created
            if (iMemPoolBufferNumLimit > 0 && iMemPoolBufferList.size() >= iMemPoolBufferNumLimit)
            {
                // Check if there is a memory pool buffer that has no outstanding buffers
                // If present then remove it so a new one can be added
                bool emptybufferfound = false;
                for (uint32 j = 0; j < iMemPoolBufferList.size(); ++j)
                {
                    if (iMemPoolBufferList[j]->iNumOutstanding == 0)
                    {
                        // Free the memory
                        if (iMemPoolBufferAllocator)
                        {
                            iMemPoolBufferAllocator->deallocate((OsclAny*)iMemPoolBufferList[j]);
                        }
                        else
                        {
                            OSCL_FREE((OsclAny*)iMemPoolBufferList[j]);
                        }

                        // Remove the mempool buffer from the list
                        iMemPoolBufferList.erase(iMemPoolBufferList.begin() + j);
                        emptybufferfound = true;
                        break;
                    }
                }
                // Need to leave and return if empty buffer not found
                if (!emptybufferfound)
                {
                    if (iEnableNullPtrReturn)
                    {
                        return NULL;
                    }
                    else
                    {
                        // Leave with resource limitation
                        OSCL_LEAVE(OsclErrNoResources);
                    }
                }
                // Continue on to create a new buffer
                OSCL_ASSERT(iMemPoolBufferList.size() < iMemPoolBufferNumLimit);
            }
            // Determine the size of memory pool buffer and create one
            uint32 buffersize = alignednumbytes + iBufferInfoAlignedSize;
            if (iExpectedNumBlocksPerBuffer > 0)
            {
                buffersize += (iExpectedNumBlocksPerBuffer * iBlockInfoAlignedSize);
            }
            else
            {
                buffersize += (OSCLMEMPOOLRESIZABLEALLOCATOR_DEFAULT_NUMBLOCKPERBUFFER * iBlockInfoAlignedSize);
            }

            MemPoolBufferInfo* newbuffer = addnewmempoolbuffer(buffersize);
            OSCL_ASSERT(newbuffer != NULL);
            OSCL_ASSERT(newbuffer->iNextFreeBlock != NULL);
            freeblock = (MemPoolBlockInfo*)(newbuffer->iNextFreeBlock);
            OSCL_ASSERT(freeblock != NULL);
            OSCL_ASSERT(freeblock->iBlockSize >= alignednumbytes);
        }
        else
        {
            // Check if another buffer can be created
            if (iMemPoolBufferNumLimit > 0 && iMemPoolBufferList.size() >= iMemPoolBufferNumLimit)
            {
                if (iEnableNullPtrReturn)
                {
                    return NULL;
                }
                else
                {
                    // Leave with resource limitation
                    OSCL_LEAVE(OsclErrNoResources);
                }
            }
            // Determine the size of memory pool buffer and create one
            // By default this allocator expands by iMemPoolBufferSize.
            // iMaxNewMemPoolBufferSz could specify the amount by which this allocator expands.
            // setMaxSzForNewMemPoolBuffer API can be used to control the expansion size.
            uint32 expansion_size = iMemPoolBufferSize;
            if (iMaxNewMemPoolBufferSz != 0)
            {
                expansion_size = iMaxNewMemPoolBufferSz;
            }
            //if alignednumbytes is larger than expansion_size, we cannot satisfy the request, so fail the allocation
            if (alignednumbytes > expansion_size)
            {
                if (iEnableNullPtrReturn)
                {
                    return NULL;
                }
                else
                {
                    // Leave with resource limitation
                    OSCL_LEAVE(OsclErrNoResources);
                }
            }
            uint32 buffersize = oscl_mem_aligned_size(expansion_size) + iBufferInfoAlignedSize;
            if (iExpectedNumBlocksPerBuffer > 0)
            {
                buffersize += (iExpectedNumBlocksPerBuffer * iBlockInfoAlignedSize);
            }
            else
            {
                buffersize += (OSCLMEMPOOLRESIZABLEALLOCATOR_DEFAULT_NUMBLOCKPERBUFFER * iBlockInfoAlignedSize);
            }

            MemPoolBufferInfo* newbuffer = addnewmempoolbuffer(buffersize);
            OSCL_ASSERT(newbuffer != NULL);
            OSCL_ASSERT(newbuffer->iNextFreeBlock != NULL);
            freeblock = (MemPoolBlockInfo*)(newbuffer->iNextFreeBlock);
            OSCL_ASSERT(freeblock != NULL);
            OSCL_ASSERT(freeblock->iBlockSize >= alignednumbytes);
        }

    }

    // Use the free block and return the buffer pointer
    OsclAny* bufptr = allocateblock(*freeblock, alignednumbytes);
    if (bufptr)
    {
        addRef();
        ++(freeblock->iParentBuffer->iNumOutstanding);
    }
    return bufptr;
}