/* load response from cache instead of query from server * input: url, response data pointer * return: response data size */ int web_load(char *url, char* response) { PCACHE_LINE pCache = pCacheHeader; int i = 0; if(response == NULL) return -1; for(i = 0; i < SET_ENTRY; i++) { pCache = cache_lines[i]; if(pCache == NULL) { printf("cache internal error!\n"); return -1; } if(pCache->in_use && (strcmp(pCache->tag, url) == 0)) { /* cache hit */ strcpy(response, pCache->block); update_lru(i); return 0; } } return -1; }
// Return non-NULL if success, NULL if object does not exist struct ZSTLMapEntry *ZSTLMapUpdate(struct ZSTLMap *pm, char *pkey, uint32_t keylen, char *pdata, uint64_t datalen) { ZSTLMapEntry_t *pme; do_lock(&(pm->mutex)); #ifdef SANDISK_PRINTSTUFF fprintf(stderr, "ZSTLMapUpdate: pm=%p, key=0x%lx, keylen=%d, pdata=%p, datalen=%ld\n", pm, *((uint64_t *) pkey), keylen, pdata, datalen); #endif pme = find_pme(pm, pkey, keylen, NULL); if (pme == NULL) { do_unlock(&(pm->mutex)); return(NULL); } /* Update an existing entry. */ // update the LRU list if necessary if (pm->max_entries != 0) { update_lru(pm, pme); } if (pm->replacement_callback) { // return NULL for key so that it is not freed! (pm->replacement_callback)(pm->replacement_callback_data, pme->key, pme->keylen, pme->contents, pme->datalen); } pme->contents = pdata; pme->datalen = datalen; do_unlock(&(pm->mutex)); return(pme); }
/*store response in cache for future request*/ int web_store(char *url, char *response) { PCACHE_LINE pCache = pCacheHeader; int i = 0; for(i = 0; i < SET_ENTRY; i++) { pCache = cache_lines[i]; if(pCache == NULL) { printf("cache internal error!\n"); return -1; } if(pCache->in_use == 0) { strcpy(pCache->tag, url); strcpy(pCache->block, response); pCache->in_use = 1; return 0; } } /* miss, will do evication*/ if(i == SET_ENTRY) { update_lru(SET_ENTRY-1); pCache = cache_lines[0]; pCache->in_use = 1; strcpy(pCache->tag, url); strcpy(pCache->block, response); return 0; } return -1; }
static int lfs_mknod(const char *path, mode_t mode, dev_t rdev) { int res; int mdata_file_res; char file_mdata_path[500]; strcpy(load_path,LOAD_PATH); strcat(load_path,path); #ifdef DEBUG printf("\n\n\n In lfs_mknod\n"); #endif /* struct stat stBuf; int tmpRes = stat(load_path,&stBuf) ; printf("Result of stat : %d for path : %s \n",tmpRes,load_path); if ( tmpRes != -1 ) { lfs_unlink(path); } */ if (S_ISREG(mode)) { #ifdef DEBUG printf("\nIn regular file mode\n"); #endif res = open(load_path, O_CREAT | O_EXCL | O_WRONLY, mode); strcpy(file_mdata_path,MDATA_PATH); strcat(file_mdata_path,path); // mdata_file_res=open(file_mdata_path,O_CREAT|O_RDWR,0777); int result; CBLK new_block = get_free_cache_block(meta_data_cache,&result); strcpy(new_block->mdata->file_name,path+1); new_block->mdata->num_paths = 0; new_block->mdata->size = 0; update_lru(meta_data_cache,new_block); write_metadata_to_disk(new_block->mdata,MDATA_PATH); // if(mdata_file_res < 0) // perror("file_metadata_open_error"); // else // close(mdata_file_res); if (res >= 0) res = close(res); } else if (S_ISFIFO(mode)) res = mkfifo(path, mode); else res = mknod(path, mode, rdev); if (res == -1) return -errno; return 0; }
// Returns non-NULL if successful, NULL otherwise struct ZSTLMapEntry *ZSTLMapGet(struct ZSTLMap *pm, char *key, uint32_t keylen, char **pdata, uint64_t *pdatalen) { uint64_t datalen; ZSTLMapEntry_t *pme; char *data; do_lock(&(pm->mutex)); pme = find_pme(pm, key, keylen, NULL); if (pme != NULL) { data = pme->contents; datalen = pme->datalen; // update the LRU list if necessary if (pm->max_entries != 0) { update_lru(pm, pme); } } else { data = NULL; datalen = 0; } #ifdef SANDISK_PRINTSTUFF if (pme != NULL) { fprintf(stderr, "ZSTLMapGet: pm=%p, key=0x%lx, keylen=%d, pdata=%p, datalen=%ld, refcnt=%d, pme=%p\n", pm, *((uint64_t *) key), keylen, data, datalen, pme->refcnt, pme); } else { fprintf(stderr, "ZSTLMapGet: pm=%p, key=0x%lx, keylen=%d, pdata=%p, datalen=%ld, pme=%p\n", pm, *((uint64_t *) key), keylen, data, datalen, pme); } #ifdef notdef void* tracePtrs[100]; int count = backtrace( tracePtrs, 100 ); char** funcNames = backtrace_symbols( tracePtrs, count ); // Print the stack trace printf("---------------------------------------------------------------------------\n"); for( int ii = 0; ii < count; ii++ ) { printf( "%s\n", funcNames[ii] ); } printf("---------------------------------------------------------------------------\n"); // Free the string pointers free( funcNames ); #endif #endif do_unlock(&(pm->mutex)); *pdatalen = datalen; *pdata = data; return(pme); }
/* A function to pin a page when a user starts using it. */ RC pinPage (BM_BufferPool *const bm, BM_PageHandle *const page, const PageNumber pageNum) { // read header from mgmtData // if pageNum already in mgmtData retrieve page pointer to page handler (page) // else apply strategy // of course, pin the Page, that is write the info to the buffer header // and increment fix count RC rc_code = RC_OK; page->pageNum = pageNum; BM_PoolInfo *pi = (BM_PoolInfo *)bm->mgmtData; int index = searchArray(pageNum, pi->map, bm->numPages); if (pageNum > 1000) { printf("Pinning P A G E (%d) ! ! !\n", pageNum); raise(SIGINT); } if (index < 0) { if (searchArray(0, pi->fixCounter, pi->numPages) < 0) { return RC_PINNED_PAGES; } // Apply strategy switch (bm->strategy) { case RS_FIFO: rc_code = readPageFIFO(pi, page, pageNum); break; case RS_LRU: rc_code = readPageLRU(pi, page, pageNum); break; default: printf("Strategy not implemented: %i\n", bm->strategy); break; } } else { // Page already on buffer frame! page->data = pi->frames[index]; pi->fixCounter[index]++; if (bm->strategy == RS_LRU) { update_lru(index, pi->lru_stamp, pi->numPages); } } // printf("buffer_mgr: pinning page (%d) with fixcounter (%d)\n", pageNum, pi->fixCounter[index]); return rc_code; }
/* * Move a successfully used entry to level2. If already at level2, * move it to the end of the LRU queue.. */ static inline void move_to_level2(struct dir_cache_entry * old_de, struct hash_list * hash) { struct dir_cache_entry * de; if (old_de->lru_head == &level2_head) { update_lru(old_de); return; } de = level2_head; level2_head = de->next_lru; remove_hash(de); COPYDATA(old_de, de); add_hash(de, hash); }
static int lfs_link(const char *from, const char *to) { int res; #ifdef DEBUG printf("\n\n\n In lfs_link from:%s to:%s\n",from,to); #endif char fromPath[MAX_PATH_NAME_SIZE]; char toPath[MAX_PATH_NAME_SIZE]; strcpy(fromPath,MDATA_PATH); strcat(fromPath,from); strcpy(toPath,MDATA_PATH); strcat(toPath,to); res = link(fromPath, toPath); if (res <0 ) return -errno; strcpy(load_path,LOAD_PATH); strcat(load_path,to); res = open(load_path, O_CREAT | O_EXCL | O_WRONLY); if (res == -1) return -errno; res = close(res); CBLK meta_data_block = find_meta_data_block(meta_data_cache,to+1); if ( meta_data_block == NULL ) { meta_data_block = mdata_from_disk_to_memory(to); assert(meta_data_block); #ifdef DEBUG printf("LINK : meta_data_block is not found in cache , hence allocating new\n"); #endif } else { update_lru(meta_data_cache,meta_data_block); } strcpy(meta_data_block->mdata->link_names[meta_data_block->mdata->num_links],to+1); meta_data_block->mdata->num_links += 1; write_metadata_to_disk(meta_data_block->mdata,MDATA_PATH); if(res <0) return -errno; return 0; }
/* A function to update the lru page information when needed. */ RC readPageLRU(BM_PoolInfo *const pi, BM_PageHandle *const page, const PageNumber pageNum) { RC rc_code; int index = searchLowest(pi->lru_stamp, pi->numPages); SM_FileHandle *fh = pi->fh; SM_PageHandle memPage = pi->frames[index]; if (pi->fixCounter[index] > 0) return RC_PINNED_LRU; if (pi->dirtys[index]) { writeBlock(pi->map[index], fh, memPage); NumWriteIO++; pi->dirtys[index] = false; } if (pageNum >= fh->totalNumPages) { // printf("Append for (%d) when total is (%d)\n", pageNum, fh->totalNumPages); rc_code = appendEmptyBlock(fh); // NumWriteIO++; if (rc_code != RC_OK) return rc_code; } rc_code = readBlock(pageNum, fh, memPage); NumReadIO++; page->data = memPage; // update fix count and lru array pi->map[index] = pageNum; pi->fixCounter[index]++; update_lru(index, pi->lru_stamp, pi->numPages); return rc_code; }
void dcache_add(struct inode * dir, const char * name, int len, unsigned long ino) { struct hash_list * hash; struct dir_cache_entry *de; if (len > DCACHE_NAME_LEN) return; hash = hash_table + hash_fn(dir->i_dev, dir->i_ino, namehash(name,len)); if ((de = find_entry(dir, name, len, hash)) != NULL) { de->ino = ino; update_lru(de); return; } de = level1_head; level1_head = de->next_lru; remove_hash(de); de->dev = dir->i_dev; de->dir = dir->i_ino; de->version = dir->i_version; de->ino = ino; de->name_len = len; memcpy(de->name, name, len); add_hash(de, hash); }
// Return non-NULL if success, NULL if object exists struct ZSTLMapEntry *ZSTLMapSet(struct ZSTLMap *pm, char *pkey, uint32_t keylen, char *pdata, uint64_t datalen, char **old_pdata, uint64_t *old_datalen) { ZSTLMapEntry_t *pme; ZSTLMapBucket_t *pb; do_lock(&(pm->mutex)); #ifdef SANDISK_PRINTSTUFF fprintf(stderr, "ZSTLMapSet: pm=%p, key=0x%lx, keylen=%d, pdata=%p, datalen=%ld\n", pm, *((uint64_t *) pkey), keylen, pdata, datalen); #endif pme = find_pme(pm, pkey, keylen, &pb); if (pme != NULL) { /* Update an existing entry. */ if (pm->replacement_callback) { // return NULL for key so that it is not freed! (pm->replacement_callback)(pm->replacement_callback_data, NULL, 0, pme->contents, pme->datalen); } *old_pdata = pme->contents; *old_datalen = pme->datalen; pme->contents = pdata; pme->datalen = datalen; /* update the lru list if necessary */ if (pm->max_entries != 0) { update_lru(pm, pme); } } else { /* Create a new entry. */ pme = create_pme(pm, pkey, keylen, pdata, datalen); *old_pdata = NULL; *old_datalen = 0; /* put myself on the bucket list */ pme->bucket = pb; pme->next = pb->entry; pb->entry = pme; #ifdef LISTCHECK check_list(pb, pme); #endif pm->n_entries++; /* put myself on the lru list */ { insert_lru(pm, pme); if ((pm->max_entries != 0) && (pm->n_entries > pm->max_entries)) { // do an LRU replacement replace_lru(pm, pme); } } } do_unlock(&(pm->mutex)); return(pme); }
void read(FILE *fp, FILE *fp_out) { int i=0, j=0, n=0, offset=0, size=0; char chr, name[5], type_tav, *place_incache, *place_inram; fseek(fp,1,1); chr = getc(fp); if (chr == '*') { fseek(fp,1,1); for (i=0 ; i < 4 ; i++) { chr = getc(fp); name[i] = chr; } place_incache = is_inCache(name); place_inram = is_inRam(name); if (place_incache == NULL && place_inram == NULL) { name[4] = '\0'; fprintf(fp_out, "The variable %s could not be found in memory!\n", name); return; } fseek(fp,1,1); offset = txt2int(fp, ')'); while ((chr=getc(fp)!='\n') && (chr != EOF)); for (i=0 ; i<sizeofmapArray ; i++) { if (is_name(mapArray[i]->name, name)) break; } type_tav = mapArray[i]->type[0]; size = mapArray[i]->size; if (type_tav == 'i') offset *= 4; if (offset>size-1) { fprintf(fp_out, "Memory Corruption!\n"); return; } switch (type_tav) { case 'i': if (place_incache == NULL) { fprintf(fp_out, "%d\n", *(int*)((mapArray[i]->addressInRam)+offset)); place_incache = place_in_cache(size); while (place_incache == NULL) { delete_item(); place_incache = place_in_cache(size); } create_cache_item(place_incache, i); } else { place_incache = update_lru(place_incache, offset); fprintf(fp_out, "%d\n", *(int*)(place_incache)); } return; case 'c': if (place_incache == NULL) { fprintf(fp_out, "%c\n", *(place_inram+offset)); place_incache = place_in_cache(size); while (place_incache == NULL) { delete_item(); place_incache = place_in_cache(size); } create_cache_item(place_incache, i); } else { place_incache = update_lru(place_incache, offset); fprintf(fp_out, "%c\n", *(place_incache)); } return; } } else { fseek(fp,-1,1); for (i=0 ; i < 4 ; i++) { chr = getc(fp); name[i] = chr; } name[4] = '\0'; place_incache = is_inCache(name); place_inram = is_inRam(name); if (place_incache == NULL && place_inram == NULL) { name[4] = '\0'; fprintf(fp_out, "The variable %s could not be found in memory!\n", name); return; } fseek(fp,1,1); offset = txt2int(fp, ' '); n = txt2int(fp, '\n'); for (i=0 ; i<sizeofmapArray ; i++) { if (is_name(mapArray[i]->name, name)) break; } size = mapArray[i]->size; if (offset+n > size) { fprintf(fp_out, "Memory Corruption!\n"); return; } if (place_incache == NULL) { for (j=0 ; j<n ; j++) { fprintf(fp_out, "%c", *(place_inram+offset+j)); } fprintf(fp_out, "\n"); place_incache = place_in_cache(size); while (place_incache == NULL) { delete_item(); place_incache = place_in_cache(size); } create_cache_item(place_incache, i); } else { place_incache = update_lru(place_incache, offset); for (j=0 ; j<n ; j++) { fprintf(fp_out, "%c", *(place_incache+j)); } fprintf(fp_out, "\n"); } return; } }
CBLK mdata_from_disk_to_memory(char *filepath) { int result; char mdata_file_path[MAX_PATH_NAME_SIZE]; strcpy(mdata_file_path,MDATA_PATH); strcat(mdata_file_path,filepath); CBLK new_mdata_block; int fd; fd = open(mdata_file_path,O_RDONLY); if(fd<0) { perror("mdata_from_disk_to_memory:fd:"); exit(1); } #ifdef DEBUG printf("\nmdata file path : %s\n",mdata_file_path); #endif char buf[MAX_MDATA_FILE_SIZE]; int bytes_read; char fileName[MAX_FILE_NAME_SIZE ]; bytes_read = read(fd,buf,MAX_MDATA_FILE_SIZE); #ifdef DEBUG printf("\nBytes read: %d\n",bytes_read); #endif if(bytes_read < 0) return NULL; else { if(sscanf(buf,"Filename:%s\n%*s",fileName) == 1 ) { new_mdata_block = find_meta_data_block(meta_data_cache,fileName ); if(new_mdata_block == NULL) { new_mdata_block = get_free_cache_block(meta_data_cache,&result); if(result == WRITE_BACK) { write_metadata_to_disk(new_mdata_block->mdata,MDATA_PATH); } } else { // Meta block is already found in cache because of hard link update_lru(meta_data_cache,new_mdata_block); return new_mdata_block; } } else { printf("Fetching filename failed\n"); return NULL; } char paths[MAX_MDATA_FILE_SIZE]; char link_names[MAX_LINKS * MAX_FILE_NAME_SIZE ]; if ( sscanf(buf,"Filename:%s\nNumPaths:%d\nSize:%d\nPaths:%s\nLinks:%s\nNumLinks:%d",new_mdata_block->mdata->file_name,&(new_mdata_block->mdata->num_paths),&(new_mdata_block->mdata->size),paths,link_names,new_mdata_block->mdata->num_links ) != 6 ) { printf("parsing metadata file failed\n"); return NULL; } else { #ifdef DEBUG printf("Metadata parsed for file:%s , numpaths : %d all paths:%s\n",new_mdata_block->mdata->file_name,&(new_mdata_block->mdata->num_paths),paths); #endif } int i=0; int j=0; int offset=0; for(i=0;i < new_mdata_block->mdata->num_paths;i++) { offset=0; while(paths[j]!= ';') { new_mdata_block->mdata->path[i][offset] = paths[j]; offset++; j++; } j++; new_mdata_block->mdata->path[i][offset] = '\0'; } j=0; for(i=0;i < new_mdata_block->mdata->num_links;i++) { offset=0; while(link_names[j]!= ';') { new_mdata_block->mdata->link_names[i][offset] = link_names[j]; offset++; j++; } j++; new_mdata_block->mdata->link_names[i][offset] = '\0'; } update_lru(meta_data_cache,new_mdata_block); return new_mdata_block; } }
static int lfs_write(const char *path, const char *buf, size_t size, off_t offset, struct fuse_file_info *fi) { int fd; int res,result; strcat(load_path,path); CBLK meta_data_block = find_meta_data_block(meta_data_cache,path+1); if( meta_data_block == NULL ) { meta_data_block = mdata_from_disk_to_memory(path); assert(meta_data_block); #ifdef DEBUG printf("meta_data_block is not found in cache , hence allocating new\n"); print_cache_block(meta_data_block); #endif } else { #ifdef DEBUG printf("meta_data_block already found in cache\n"); #endif update_lru(meta_data_cache,meta_data_block); } CBLK wbuf_data_block = find_meta_data_block(buffer_cache,path+1); if(wbuf_data_block == NULL) { #ifdef DEBUG printf("wbuf is not found in cache and hence allocating new\n"); #endif wbuf_data_block = get_free_cache_block(buffer_cache,&result); assert(wbuf_data_block); if(result == WRITE_BACK) { pthread_mutex_lock(&buffer_cache_lock); write_buffer_to_disk(wbuf_data_block,CHUNK_PATH,buffer_cache); pthread_mutex_unlock(&buffer_cache_lock); #ifdef MDATA_CBLK_WRITE_THROUGH write_metadata_to_disk(wbuf_data_block->mdata,MDATA_PATH); #endif #ifdef DEBUG printf("Evicting old cache block\n"); #endif } wbuf_data_block->mdata = meta_data_block->mdata; } else { printf("wbuf already found in cache\n"); } if(wbuf_data_block->offset + strlen(buf) > buffer_cache->cache_block_size) { #ifdef DEBUG printf("cache_block buffer full and is written to disk\n"); #endif pthread_mutex_lock(&buffer_cache_lock); write_buffer_to_disk(wbuf_data_block,CHUNK_PATH,buffer_cache); pthread_mutex_unlock(&buffer_cache_lock); #ifdef MDATA_CBLK_WRITE_THROUGH write_metadata_to_disk(wbuf_data_block->mdata,MDATA_PATH); #endif } else { #ifdef DEBUG printf("appending to cache block buffer\n"); #endif } update_lru(buffer_cache,wbuf_data_block); //strcat(wbuf_data_block->buf,buf); memcpy(wbuf_data_block->buf + wbuf_data_block->offset,buf,size); wbuf_data_block->offset += size ; #ifdef DEBUG printf("Offset : %d \nBuffer contents after writing to disk:%s********\n",wbuf_data_block->offset ,wbuf_data_block->buf); #endif (void) fi; //fd = open(path, O_WRONLY); //if (fd == -1) // return -errno; //res = pwrite(fd, buf, size, offset); //if (res == -1) // res = -errno; //close(fd); #ifdef DEBUG printf("Actual received size : %d Length of buf : %d\n",size,strlen(buf)); #endif return size;//strlen(buf); }
static int lfs_read(const char *path, char *buf, size_t size, off_t offset, struct fuse_file_info *fi) { int fd; int res; char temp1[1000]; (void) fi; //#ifdef DEBUG printf("\n\n\nIn lfs_read. size %d offset %d \n\n",size,offset); //#endif CBLK meta_data_block = find_meta_data_block(meta_data_cache,path+1); if ( meta_data_block == NULL ) { meta_data_block = mdata_from_disk_to_memory(path); assert(meta_data_block); #ifdef DEBUG printf("GETATTR : meta_data_block is not found in cache , hence allocating new\n"); #endif } else { update_lru(meta_data_cache,meta_data_block); } // print_cache_block(meta_data_block); // print_cache(buffer_cache); FILE *fptr; int numBytes = 0; int bufOffset = 0; int i; for(i=0;i<meta_data_block->mdata->num_paths;i++) { fptr = fopen(meta_data_block->mdata->path[i],"r"); #ifdef DEBUG printf("\nbufOffset : %d\n",bufOffset); #endif numBytes = fread(buf+bufOffset,1,meta_data_block->mdata->size,fptr); // buf[bufOffset+numBytes] = '\n'; // buf[bufOffset+numBytes+1] = '\0'; bufOffset += numBytes; // +1 ; fclose(fptr); } buf[bufOffset] = '\0'; CBLK wbuf_data_block = find_meta_data_block(buffer_cache,path+1); if(wbuf_data_block != NULL) { strcat(buf,wbuf_data_block->buf); bufOffset += strlen(wbuf_data_block->buf); } return bufOffset; /* char spath[500]; strcpy(spath,"/home/vino/Desktop/serverfilesystem"); strcat(spath,path); // fd = open(spath, O_RDONLY); // if (fd == -1) // return -errno; //strcpy(temp1,"vinoprasanna"); // res = pread(fd, buf, size, offset); // printf("\nres is %d\n",res); printf("\n\n%s\n\n",buf); printf("offset is %d\n",offset); printf("size is %d\n",size); printf("\nstrlen(buf) is %d\n",strlen(buf)); char temp2[4096]; strcpy(temp1,"_padding_"); strcpy(temp2,buf); //buf=(char*)malloc(1000); strcat(temp1,temp2); printf("now temp1 is %s and has len: %d\n",temp1,strlen(temp1)); memcpy(buf,temp1,strlen(temp1)); printf("now content in buf is %s and has len: %d ",buf,strlen(buf)); printf("size is %d",size); if (res == -1) res = -errno; memset(buf,0,40); strcpy(buf,"helllllllllllllllllllllllllllllllllo"); //close(fd); return strlen(buf); */ }
static int lfs_getattr(const char *path, struct stat *stbuf) { int res; char final_path[MAX_PATH_NAME_SIZE]; strcpy(final_path,MDATA_PATH); strcat(final_path,path); res = lstat(final_path, stbuf); if(S_IFDIR == (stbuf->st_mode & S_IFDIR)) { #ifdef DEBUG printf("Inside directory \n"); #endif return 0; } if (res == -1) return -errno; if(strcmp(path,"/") == 0 ) return 0; if(path[1] == '.' ) // For all special files starting with '.' just return the stbuf that is returned from lstat return 0; CBLK meta_data_block = find_meta_data_block(meta_data_cache,path+1); if ( meta_data_block == NULL ) { meta_data_block = mdata_from_disk_to_memory(path); assert(meta_data_block); #ifdef DEBUG printf("GETATTR : meta_data_block is not found in cache , hence allocating new\n"); #endif } else { update_lru(meta_data_cache,meta_data_block); } // print_cache_block(meta_data_block); #ifdef DEBUG print_cache(meta_data_cache); #endif // print_cache(buffer_cache); CBLK wbuf_data_block = find_meta_data_block(buffer_cache,path+1); if( wbuf_data_block == NULL ) { stbuf->st_size = meta_data_block->mdata->size; } else { update_lru(buffer_cache,wbuf_data_block); #ifdef DEBUG printf("GETATTR: wbuf_data_block already found in cache\n"); print_cache_block(wbuf_data_block); #endif stbuf->st_size = meta_data_block->mdata->size + wbuf_data_block->offset; } // stbuf->st_size += meta_data_block->mdata->num_paths; needed only if \n has to be appended manually after each chunk #ifdef DEBUG printf("ST_BUF_SIZE : %d\n",stbuf->st_size); #endif return 0; }