Example #1
0
int mydisk_write_block(int block_id, void *buffer)
{
	/* TODO: this one is similar to read_block() except that
	 * you need to mark it dirty
	 */
	printf("\n--- Start write block ---\n");
	// printf("block id = %d\n", block_id);
	
	if (block_id >= max_blocks) {
		printf("ERROR: block id greater than max blocks");
		return 1;
	}

	if (cache_enabled) {
		printf("cache enabled for write\n");
		int i;
		// char tmp[BLOCK_SIZE];
		// char *x;
		// x = &tmp;

		// char *x = malloc(BLOCK_SIZE);
		// print();
		// *x = get_cached_block(block_id);

		char *y[BLOCK_SIZE];
		*y = get_cached_block(block_id);

		if (*y == NULL) {
			printf("cache miss for write\n");
			
			mark_dirty(block_id);
			memcpy(create_cached_block(block_id), buffer, BLOCK_SIZE);
printf("_______________\n");
char *z = get_cached_block(block_id);
for(i=0; i<BLOCK_SIZE; i++) {
	printf("%c", z[i]);
}
printf("________________\n");
			return 0;
		} else {
printf("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\n");
			printf("cache hit for write\n");
printf("+++++++++ write this ++++++++\n");
for(i=0; i<BLOCK_SIZE; i++) {
	printf("%c", ((char*)buffer)[i]);
}
printf("\n+++++++++++++++++\n");
			memcpy(get_cached_block(block_id), buffer, BLOCK_SIZE);
printf("_______ should be same as top ________\n");
get_cached_block(block_id);
printf("\n________________\n");
			return -1;
		}

	} else {
		int i;
		char ch;

		fseek(thefile, block_id * BLOCK_SIZE, SEEK_SET);
		if(fwrite(buffer, BLOCK_SIZE, 1, thefile) != 1) {
			printf("ERROR\n");
			return 1;
		} else {
			return 0;
		}
	}
	// fseek(thefile, 0, SEEK_SET);
	// i = 0;
	// while( ( ch = fgetc(thefile) ) != EOF ) {
 //    	printf("%c",ch);
 //    	if (i % BLOCK_SIZE == 0 && (i!=0)) {
 //    		printf("\n");
 //    	}
 //    	i++;
 //  	}

	// printf("\n--- End write block ---\n");
	return 0;
}
Example #2
0
int mydisk_read_block(int block_id, void *buffer)
{
	printf("\n*** Start read block ***\n");
	// printf("block id = %d\n", block_id);

	if (block_id >= max_blocks) {
		printf("ERROR: block id greater than max blocks");
		return 1;
	}

	if (cache_enabled) {
		/* TODO: 1. check if the block is cached
		 * 2. if not create a new entry for the block and read from disk
		 * 3. fill the requested buffer with the data in the entry 
		 * 4. return proper return code
		 */
		printf("cache enabled for read\n");
		int i;

		// char *x = get_cached_block(block_id);
		if (get_cached_block(block_id) == NULL) {
			printf("Cache miss\n");

			fseek(thefile, block_id * BLOCK_SIZE, SEEK_SET);
			fread(buffer, BLOCK_SIZE, 1, thefile);
printf("before-->\n");
print();
			memcpy(create_cached_block(block_id), buffer, BLOCK_SIZE);
printf("EEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEE\n");
print();
// char *x = get_cached_block(block_id);
// for (i=0; i<BLOCK_SIZE; i++) {
// 	printf("%c", x[i]);
// }
// printf("\n");
			// Cache miss
			return 0;
		} else {
			printf("Cache hit\n");
char *x = get_cached_block(block_id);
for(i=0;i<BLOCK_SIZE;i++){
	printf("%c", x[i]);
}
printf("\n");
			memcpy(buffer, get_cached_block(block_id), BLOCK_SIZE);

			// Cache hit
			return -1;
		}
	} else {
		/* TODO: use standard C functiosn to read from disk
		 */

		fseek(thefile, block_id * BLOCK_SIZE, SEEK_SET);
		fread(buffer, BLOCK_SIZE, 1, thefile);

		// int i;
		// for(i=0; i<BLOCK_SIZE; i++) {
		// 	printf("%c", ((char*)buffer)[i]);
		// 	if(i%BLOCK_SIZE == 0 && i!=0) {
		// 		printf("\n");
		// 	}
		// }

		// printf("\n*** End read block ***\n");
		return 0;
	}
}
/*!	Returns the writable block data for the requested blockNumber.
	If \a cleared is true, the block is not read from disk; an empty block
	is returned.

	This is the only method to insert a block into a transaction. It makes
	sure that the previous block contents are preserved in that case.
*/
static void*
get_writable_cached_block(block_cache* cache, fssh_off_t blockNumber, fssh_off_t base,
	fssh_off_t length, int32_t transactionID, bool cleared)
{
	TRACE(("get_writable_cached_block(blockNumber = %Ld, transaction = %d)\n",
		blockNumber, transactionID));

	if (blockNumber < 0 || blockNumber >= cache->max_blocks) {
		fssh_panic("get_writable_cached_block: invalid block number %"
			FSSH_B_PRIdOFF " (max %" FSSH_B_PRIdOFF ")", blockNumber,
			cache->max_blocks - 1);
	}

	bool allocated;
	cached_block* block = get_cached_block(cache, blockNumber, &allocated,
		!cleared);
	if (block == NULL)
		return NULL;

	block->discard = false;

	// if there is no transaction support, we just return the current block
	if (transactionID == -1) {
		if (cleared)
			fssh_memset(block->current_data, 0, cache->block_size);

		block->is_dirty = true;
			// mark the block as dirty

		return block->current_data;
	}

	cache_transaction* transaction = block->transaction;

	if (transaction != NULL && transaction->id != transactionID) {
		// TODO: we have to wait here until the other transaction is done.
		//	Maybe we should even panic, since we can't prevent any deadlocks.
		fssh_panic("get_writable_cached_block(): asked to get busy writable block (transaction %d)\n", (int)transaction->id);
		put_cached_block(cache, block);
		return NULL;
	}
	if (transaction == NULL && transactionID != -1) {
		// get new transaction
		transaction = lookup_transaction(cache, transactionID);
		if (transaction == NULL) {
			fssh_panic("get_writable_cached_block(): invalid transaction %d!\n",
				(int)transactionID);
			put_cached_block(cache, block);
			return NULL;
		}
		if (!transaction->open) {
			fssh_panic("get_writable_cached_block(): transaction already done!\n");
			put_cached_block(cache, block);
			return NULL;
		}

		block->transaction = transaction;

		// attach the block to the transaction block list
		block->transaction_next = transaction->first_block;
		transaction->first_block = block;
		transaction->num_blocks++;
	}

	bool wasUnchanged = block->original_data == NULL
		|| block->previous_transaction != NULL;

	if (!(allocated && cleared) && block->original_data == NULL) {
		// we already have data, so we need to preserve it
		block->original_data = cache->Allocate();
		if (block->original_data == NULL) {
			FATAL(("could not allocate original_data\n"));
			put_cached_block(cache, block);
			return NULL;
		}

		fssh_memcpy(block->original_data, block->current_data, cache->block_size);
	}
	if (block->parent_data == block->current_data) {
		// remember any previous contents for the parent transaction
		block->parent_data = cache->Allocate();
		if (block->parent_data == NULL) {
			// TODO: maybe we should just continue the current transaction in this case...
			FATAL(("could not allocate parent\n"));
			put_cached_block(cache, block);
			return NULL;
		}

		fssh_memcpy(block->parent_data, block->current_data, cache->block_size);
		transaction->sub_num_blocks++;
	} else if (transaction != NULL && transaction->has_sub_transaction
		&& block->parent_data == NULL && wasUnchanged)
		transaction->sub_num_blocks++;

	if (cleared)
		fssh_memset(block->current_data, 0, cache->block_size);

	block->is_dirty = true;

	return block->current_data;
}