#include #include #include #include #include #include #include #include #define MAX_REGIONS 64 typedef struct PINT_Request_result { PVFS_offset *offset_array;/* array of offsets for each segment output */ PVFS_size *size_array; /* array of sizes for each segment output */ int32_t segmax; /* maximum number of segments to output */ int32_t segs; /* number of segments output */ PVFS_size bytemax; /* maximum number of bytes to output */ PVFS_size bytes; /* number of bytes output */ } PINT_Request_result; struct PINT_thread_mgr_trove_callback { void (*fn)(void* data, PVFS_error error_code); void* data; }; struct result_chain_entry { PVFS_id_gen_t posted_id; char *buffer_offset; PINT_Request_result result; PVFS_size size_list[MAX_REGIONS]; PVFS_offset offset_list[MAX_REGIONS]; struct result_chain_entry *next; struct fp_queue_item *q_item; struct PINT_thread_mgr_trove_callback trove_callback; }; /* include the file descriptor in this hash fn */ #define HASH_FUNC(offset, size) (((unsigned int)(offset)<<16)^((unsigned int)(size))) typedef struct _prefetch_queue { struct _prefetch_queue *next; unsigned int hashval; struct result_chain_entry *res_prefetch; struct _prefetch_queue *prev; } prefetch_queue; /* header node is a special node containing no data ** when it is empty it points to itself ** the next ptr of header points to the first node in q ** the prev ptr of header points to the last node in q ** the next ptr of last node points to the header ** */ prefetch_queue *prefetch_q_head = NULL; /* function prototypes */ prefetch_queue* alloc_prefetch_element(struct result_chain_entry *element); prefetch_queue* prefetch_init_queue(void); int prefetch_q_empty(prefetch_queue *head); int prefetch_data_present(prefetch_queue *head, struct result_chain_entry *chk, prefetch_queue *qdata); void add_prefetch_data(prefetch_queue *head, struct result_chain_entry *data); prefetch_queue* remove_prefetch_data(prefetch_queue *head, prefetch_queue *qdata); prefetch_queue* ret_prefetch_data(prefetch_queue *head, struct result_chain_entry *data); /* function definions */ prefetch_queue * alloc_prefetch_element(struct result_chain_entry *data) { prefetch_queue *element = NULL; element = (prefetch_queue*)malloc(sizeof(prefetch_queue)); if(!element) goto alloc_ret; element->next = element->prev = NULL; element->res_prefetch = (struct result_chain_entry*)malloc(sizeof(struct result_chain_entry)); if(!element->res_prefetch) { free(element); element = NULL; goto alloc_ret; } memcpy(element->res_prefetch, data, sizeof(struct result_chain_entry)); element->res_prefetch->result.offset_array = element->res_prefetch->offset_list; element->res_prefetch->result.size_array = element->res_prefetch->size_list; if(data->result.segs >= 1) element->hashval = HASH_FUNC(data->offset_list[0], data->size_list[0]); else element->hashval = 0; alloc_ret: return element; } prefetch_queue * prefetch_init_queue(void) { prefetch_queue *head = NULL; head = (prefetch_queue*)malloc(sizeof(prefetch_queue)); if(!head) fprintf(stderr, "file: %s, func: %s, line:%d malloc error: %d\n", __FILE__, __func__, __LINE__, errno); else { head->res_prefetch = NULL; head->next = head->prev = head; } return head; } int prefetch_q_empty(prefetch_queue *head) { if(head->next == head && head->prev == head) return 1; return 0; } int prefetch_data_present(prefetch_queue *head, struct result_chain_entry *chk, prefetch_queue *qdata) { prefetch_queue *temp = NULL; unsigned int hashval = 0; int i; qdata = NULL; if(prefetch_q_empty(head)) return 0; temp = head->next; while(temp != head) { if(temp->res_prefetch->result.segs >= 1) hashval = HASH_FUNC(temp->res_prefetch->offset_list[0], temp->res_prefetch->size_list[0]); else hashval = 0; if(hashval == temp->hashval) { /* if hash is a match, check to if offsets and sizes match */ if(chk->result.segs != temp->res_prefetch->result.segs) goto next; for(i = 0; i < chk->result.segs; i++) { if(chk->size_list[i] != temp->res_prefetch->size_list[i]) goto next; if(chk->offset_list[i] != temp->res_prefetch->offset_list[i]) goto next; } /* if we arrive here, it means there is a match */ qdata = temp; return 1; } next: temp = temp->next; } return 0; } void add_prefetch_data(prefetch_queue *head, struct result_chain_entry *data) { prefetch_queue *qdata = NULL, *last = NULL; qdata = alloc_prefetch_element(data); assert(qdata); last = head->prev; qdata->next = last->next; qdata->prev = last->prev; last->next = qdata; head->prev = qdata; } /* assume that caller will free node ** */ prefetch_queue * remove_prefetch_data(prefetch_queue *head, prefetch_queue *qdata) { if(prefetch_q_empty(head)) return NULL; qdata->next->prev = qdata->prev; qdata->prev->next = qdata->next; qdata->next = qdata->prev = NULL; return qdata; } /* assume that caller will free node */ prefetch_queue * ret_prefetch_data(prefetch_queue *head, struct result_chain_entry *data) { prefetch_queue *qdata = NULL; if(prefetch_data_present(head, data, qdata)) remove_prefetch_data(head, qdata); return qdata; } int main(int argc, char *argv[]) { prefetch_queue *prefetch_q_head = NULL; struct result_chain_entry result_tmp; assert((prefetch_q_head = prefetch_init_queue())); add_prefetch_data(prefetch_q_head, &result_tmp); return 0; }