/** * @author Dejan Sambolić updated by Dražen Bandić * @brief Function initializes the global redo log memory (variable redo_log) * @return EXIT_SUCCESS if the redo log memory has been initialized, EXIT_ERROR otherwise */ int AK_redo_log_AK_malloc() { AK_PRO; if ((redo_log = (AK_redo_log *) AK_malloc(sizeof ( AK_redo_log))) == NULL) { AK_EPI; return EXIT_ERROR; } redo_log->number = 0; redo_log->table_name = AK_malloc(MAX_REDO_LOG_ENTRIES * sizeof(char*)); redo_log->command = AK_malloc(MAX_REDO_LOG_ENTRIES * sizeof(char*)); redo_log->attributes = AK_malloc(MAX_REDO_LOG_ENTRIES * sizeof(char*)); int i = 0; for (i = 0; i < MAX_REDO_LOG_ENTRIES; i++) { redo_log->table_name[i] = AK_calloc(MAX_VARCHAR_LENGTH, sizeof(char)); redo_log->command[i] = AK_calloc(MAX_VARCHAR_LENGTH, sizeof(char)); redo_log->attributes[i] = AK_calloc(MAX_VARCHAR_LENGTH, sizeof(char)); } AK_EPI; return EXIT_SUCCESS; }
/** * @author Dino Laktašić. * @brief Break conjunctive conditions to individual conditions * (currently not used - commented in main AK_rel_eq_selection function), it can be usefull in some optimization cases * <ol> * <li>For each delimited item (' AND ') insert item to the struct list_node</li> * <li>Remove unused pointers and return the conditions list</li> * </ol> * @param *cond condition expression * @result conditions list */ struct list_node *AK_rel_eq_split_condition(char *cond) { AK_PRO; struct list_node *list_attr = (struct list_node *) AK_malloc(sizeof (struct list_node)); Ak_Init_L3(&list_attr); int token_id = 0; int attr_address = 0; int len_token; char *token_cond, *save_token_cond; //it's much safe to allocate MAX_VARCHAR_LENGHT, and remove all AK_realloc from function char *temp_attr = (char *) AK_calloc(1, sizeof (char)); //memset(temp_attr, '\0', MAX_VARCHAR_LENGHT); char *temp_cond = (char *) AK_calloc(strlen(cond), sizeof (char)); memcpy(temp_cond, cond, strlen(cond)); for ((token_cond = strtok_r(temp_cond, " ", &save_token_cond)); token_cond; (token_cond = strtok_r(NULL, " ", &save_token_cond)), token_id++) { if (token_id < MAX_TOKENS - 1) { len_token = strlen(token_cond); if (strcmp(token_cond, "AND") == 0) { Ak_InsertAtEnd_L3(TYPE_CONDITION, temp_attr, strlen(temp_attr), list_attr); attr_address = 0; AK_free(temp_attr); temp_attr = (char *) AK_calloc(1, sizeof (char)); } else { if (attr_address > 0) { temp_attr = (char *) AK_realloc(temp_attr, attr_address + len_token + 2); //memcpy(temp_attr + attr_address, " ", 1); strcpy(temp_attr + attr_address, " "); //memcpy(temp_attr + ++attr_address, "\0", 1); attr_address++; } else { temp_attr = (char *) AK_realloc(temp_attr, attr_address + len_token + 1); } strcpy(temp_attr + attr_address, token_cond); //memcpy(temp_attr + attr_address, token_cond, len_token); attr_address += len_token; } } } //memcpy(temp_attr + attr_address, "\0", 1); Ak_InsertAtEnd_L3(TYPE_CONDITION, temp_attr, strlen(temp_attr), list_attr); AK_free(temp_cond); AK_free(temp_attr); AK_EPI; return list_attr; }
/** * @author Ivan Pusic * @brief Function for initialization of AK_observer_lock type * * @return Pointer to new AK_observer_lock instance */ AK_observer_lock * AK_init_observer_lock() { AK_PRO; AK_observer_lock *self; self = AK_calloc(1, sizeof(AK_observer_lock)); self->observer = AK_init_observer(self, &AK_on_observable_notify); AK_EPI; return self; }
/** * @author Ivan Pusic * @brief Function for initialization of AK_observable_transaction type * * @return Pointer to new AK_observable_transaction instance */ AK_observable_transaction * AK_init_observable_transaction() { AK_PRO; observable_transaction = AK_calloc(1, sizeof(AK_observable_transaction)); observable_transaction->AK_transaction_register_observer = &AK_transaction_register_observer; observable_transaction->AK_transaction_unregister_observer = &AK_transaction_unregister_observer; observable_transaction->AK_lock_released = &AK_lock_released; observable_transaction->AK_transaction_finished = &AK_transaction_finished; observable_transaction->AK_all_transactions_finished = &AK_all_transactions_finished; observable_transaction->observable = AK_init_observable(observable_transaction, AK_TRANSACTION, &AK_handle_observable_transaction_action); AK_EPI; return observable_transaction; }
/** * @author Dino Laktašić. * @brief Get all permutations without repetition (currently not used, but it can be helpful) * @param arr array of chars to permute * @return char pointer to array of pointers to permuted char arrays */ char *AK_get_array_perms(char *arr) { int div, num_perms = 1; int next_perm, next_chr; int len_arr = strlen(arr); AK_PRO; //Get total permutation without repetition number for (next_chr = 1; next_chr <= len_arr; num_perms *= next_chr++); char *res_perm, *perms[num_perms]; for (next_perm = 0; next_perm < num_perms; next_perm++) { char *perm = (char *) AK_calloc(len_arr, sizeof (char)); memcpy(perm, arr, len_arr); res_perm = (char *) AK_calloc(len_arr, sizeof (char)); for (next_chr = len_arr, div = num_perms; next_chr > 0; next_chr--) { div /= next_chr; int index = (next_perm / div) % next_chr; //printf("%c", perm[index] ); memcpy(res_perm + (len_arr - next_chr), &perm[index], 1); memmove(perm + index, perm + index + 1, len_arr - index); } //printf("\n"); perms[next_perm] = res_perm; //printf("%s\n", perms[next_perm]); AK_free(perm); //perm = NULL; } res_perm = (char *) AK_calloc(num_perms, sizeof (char*)); memcpy(res_perm, perms, sizeof (perms)); AK_EPI; return res_perm; }
/** * @author Dino Laktašić. * @brief Check if two sets share one or more of it's attributes * <ol> * <li>If is empty set or subset returns EXIT_FAILURE</li> * <li>For each attribute in one set check if there is same attribute in the second set</li> * <li>If there is the same attribute return EXIT_SUCCESS</li> * <li>else remove unused pointers and return EXIT_FAILURE</li> * </ol> * @param *set first set of attributes delimited by ";" (ATTR_DELIMITER) * @param *subset second set of attributes delimited by ";" (ATTR_DELIMITER) * @result EXIT_SUCCESS if set and subset share at least one attribute, else returns EXIT_FAILURE */ int AK_rel_eq_share_attributes(char *set, char *subset) { AK_PRO; if (set == NULL || subset == NULL) { AK_EPI; return EXIT_FAILURE; } char *temp, *temp_set, *temp_subset; char *token_set, *token_subset; char *save_token_set, *save_token_subset; temp = (char *) AK_calloc(strlen(subset), sizeof (char)); temp_set = (char *) AK_calloc(strlen(set), sizeof (char)); temp_subset = (char *) AK_calloc(strlen(subset), sizeof (char)); memcpy(temp, subset, strlen(subset)); memcpy(temp_set, set, strlen(set)); memcpy(temp_subset, subset, strlen(subset)); for ((token_set = strtok_r(temp_set, ATTR_DELIMITER, &save_token_set)); token_set; (token_set = strtok_r(NULL, ATTR_DELIMITER, &save_token_set))) { for ((token_subset = strtok_r(temp_subset, ATTR_DELIMITER, &save_token_subset)); token_subset; (token_subset = strtok_r(NULL, ATTR_DELIMITER, &save_token_subset))) { if (memcmp(token_set, token_subset, strlen(token_set)) == 0) { AK_free(temp); AK_EPI; return EXIT_SUCCESS; } } temp_subset = temp; } AK_free(temp); AK_EPI; return EXIT_FAILURE; }
/** * @author Matija Šestak. * @brief Function that fetches the table header * <ol> * <li>Read addresses of extents</li> * <li>If there is no extents in the table, return 0</li> * <li>else read the first block</li> * <li>allocate array</li> * <li>copy table header to the array</li> * </ol> * @param *tblName table name * @result array of table header */ AK_header *AK_get_header(char *tblName) { AK_PRO; table_addresses *addresses = (table_addresses*) AK_get_table_addresses(tblName); if (addresses->address_from[0] == 0){ AK_EPI; return EXIT_WARNING + 2; } AK_mem_block *temp = (AK_mem_block*) AK_get_block(addresses->address_from[0]); int num_attr = AK_num_attr(tblName); AK_header *head = (AK_header*) AK_calloc(num_attr, sizeof (AK_header)); memcpy(head, temp->block->header, num_attr * sizeof (AK_header)); AK_free(addresses); AK_EPI; return head; }
char* AK_get_table_atribute_types(char* tblName){ int len_attr, num_attr, next_attr, attr_type; int next_address = 0; char attr_buffer[4]; AK_PRO; num_attr = AK_num_attr(tblName); if (num_attr == EXIT_WARNING) { AK_EPI; return NULL; } char *attr = (char *) AK_calloc(1, sizeof (char)); AK_header *table_header = (AK_header *) AK_get_header(tblName); for (next_attr = 0; next_attr < num_attr; next_attr++) { attr_type = (table_header + next_attr)->type; len_attr = sprintf(attr_buffer,"%d",attr_type); attr = (char *) AK_realloc(attr, len_attr + next_address + 1); memcpy(attr + next_address, attr_buffer, len_attr); next_address += len_attr; if (next_attr < num_attr - 1) { memcpy(attr + next_address, ATTR_DELIMITER, 1); next_address++; } else { memcpy(attr + next_address, "\0", 1); } } AK_free(table_header); if (next_address > 0) { AK_EPI; return attr; } else { AK_free(attr); AK_EPI; return NULL; } AK_EPI; }
/** * @author Matija Šestak, modified for indexes by Lovro Predovan * @brief Function that getts index table header * <ol> * <li>Read addresses of extents</li> * <li>If there is no extents in the table, return -1</li> * <li>else read the first block</li> * <li>allocate array</li> * <li>copy table header to the array</li> * </ol> * @param *tblName table name * @result array of table header */ AK_header *AK_get_index_header(char *indexTblName) { AK_PRO; table_addresses *addresses = (table_addresses*) AK_get_index_addresses(indexTblName); if (addresses->address_from[0] == 0){ AK_EPI; return 0; } AK_mem_block *temp = (AK_mem_block*) AK_get_block(addresses->address_from[0]); int num_attr = AK_num_index_attr(indexTblName); AK_header *head = (AK_header*) AK_calloc(num_attr, sizeof (AK_header)); memcpy(head, temp->block->header, num_attr * sizeof (AK_header)); AK_EPI; return head; }
/** * @author Marko Sinko * @brief Initializes an AK_synchronization_info structure and returns an owned * pointer that must later be passed to AK_destroy_critical_section. * @return Initialized synchronization object */ AK_synchronization_info* AK_init_critical_section() { AK_synchronization_info* info = AK_calloc(1, sizeof(AK_synchronization_info)); if (info == NULL) return NULL; #ifdef _WIN32 if (InitializeCriticalSectionAndSpinCount( &info->critical_section, 0x00000400) == 0){ free(info); return NULL; } #endif #ifdef __linux__ pthread_mutex_init(&info->mutex, NULL); #endif info->init = 1; info->ready = 1; return info; }
/** * @author Markus Schatten, Matija Šestak. * @brief Function that fetches all values in some row and put on the list * @param num zero-based row index * @param * tblName table name * @return row values list */ struct list_node *AK_get_row(int num, char * tblName) { AK_PRO; table_addresses *addresses = (table_addresses*) AK_get_table_addresses(tblName); struct list_node *row_root = (struct list_node *)AK_calloc(1, sizeof (struct list_node)); Ak_Init_L3(&row_root); int num_attr = AK_num_attr(tblName); int i, j, k, l, counter; i = 0; char data[MAX_VARCHAR_LENGTH]; counter = -1; while (addresses->address_from[i] != 0) { for (j = addresses->address_from[i]; j < addresses->address_to[i]; j++) { AK_mem_block *temp = (AK_mem_block*) AK_get_block(j); if (temp->block->last_tuple_dict_id == 0) break; for (k = 0; k < DATA_BLOCK_SIZE; k += num_attr) { if (temp->block->tuple_dict[k].size > 0) counter++; if (counter == num) { for (l = 0; l < num_attr; l++) { int type = temp->block->tuple_dict[k + l].type; int size = temp->block->tuple_dict[k + l].size; int address = temp->block->tuple_dict[k + l].address; memcpy(data, &(temp->block->data[address]), size); data[size] = '\0'; Ak_InsertAtEnd_L3(type, data, size, row_root); } AK_free(addresses); AK_EPI; return row_root; } } } i++; } AK_free(addresses); Ak_DeleteAll_L3(&row_root); AK_free(row_root); AK_EPI; return NULL; }
/** * @author Dino Laktašić * @brief Function that prints the table row * update by Luka Rajcevic * @param col_len[] array of max lengths for each attribute * @param *row list with row elements * @return No return value */ void AK_print_row_to_file(int col_len[], struct list_node * row) { char* FILEPATH = "table_test.txt"; FILE *fp; AK_PRO; fp = fopen(FILEPATH, "a"); struct list_node *el = (struct list_node *) Ak_First_L2(row); int i = 0; void *data = (void *) AK_calloc(MAX_VARCHAR_LENGTH, sizeof (void)); fprintf(fp, "\n|"); while (el != NULL) { memset(data, 0, MAX_VARCHAR_LENGTH); switch (el->type) { case FREE_CHAR: //case FREE_INT: fprintf(fp, " %-*s|", col_len[i] + TBL_BOX_OFFSET, "null"); break; case TYPE_INT: memcpy(data, el->data, sizeof (int)); fprintf(fp, "%*i |", col_len[i] + TBL_BOX_OFFSET, *((int *) data)); break; case TYPE_FLOAT: memcpy(data, el->data, sizeof (float)); fprintf(fp, "%*.3f |", col_len[i] + TBL_BOX_OFFSET, *((float *) data)); break; case TYPE_VARCHAR: default: memcpy(data, el->data, el->size); fprintf(fp, " %-*s|", col_len[i] + TBL_BOX_OFFSET, (const char *) data); break; } el = el->next; i++; } fprintf(fp, "\n"); fclose(fp); AK_free(data); AK_EPI; }
/** * @author Dino Laktašić. * @brief Get attributes for a given table and store them to the char array * <ol> * <li>Get the number of attributes in a given table</li> * <li>If there is no attributes return NULL</li> * <li>Get the table header for a given table</li> * <li>Initialize struct list_node</li> * <li>For each attribute in table header, insert attribute in the array</li> * <li>Delimit each new attribute with ";" (ATTR_DELIMITER)</li> * <li>return pointer to char array</li> * </ol> * @param *tblName name of the table * @result pointer to char array */ char *AK_rel_eq_get_atrributes_char(char *tblName) { int len_attr, num_attr, next_attr; int next_address = 0; char *attr_name; AK_PRO; num_attr = AK_num_attr(tblName); if (num_attr == -1) { AK_EPI; return NULL; } char *attr = (char *) AK_calloc(1, sizeof (char)); AK_header *table_header = (AK_header *) AK_get_header(tblName); for (next_attr = 0; next_attr < num_attr; next_attr++) { attr_name = (table_header + next_attr)->att_name; len_attr = strlen(attr_name); attr = (char *) AK_realloc(attr, len_attr + next_address + 1); memcpy(attr + next_address, attr_name, len_attr); next_address += len_attr; if (next_attr < num_attr - 1) { memcpy(attr + next_address, ATTR_DELIMITER, 1); next_address++; } else { memcpy(attr + next_address, "\0", 1); } } AK_free(table_header); if (next_address > 0) { AK_EPI; return attr; } else { AK_free(attr); AK_EPI; return NULL; } }
/** * @author Dino Laktašić * @brief Function that prints table row * @param col_len[] array of max lengths for each attribute * @param *row list with row elements * @return No return value */ void AK_print_row(int col_len[], struct list_node *row) { AK_PRO; struct list_node *el = (struct list_node *) Ak_First_L2(row); int i = 0; void *data = (void *) AK_calloc(MAX_VARCHAR_LENGTH, sizeof (void)); printf("\n|"); while (el != NULL) { memset(data, 0, MAX_VARCHAR_LENGTH); switch (el->type) { case FREE_CHAR: //case FREE_INT: printf(" %-*s|", col_len[i] + TBL_BOX_OFFSET, "null"); break; case TYPE_INT: memcpy(data, el->data, sizeof (int)); printf("%*i |", col_len[i] + TBL_BOX_OFFSET, *((int *) data)); break; case TYPE_FLOAT: memcpy(data, el->data, sizeof (float)); printf("%*.3f |", col_len[i] + TBL_BOX_OFFSET, *((float *) data)); break; //Currently this header types are handled like TYPE_VARCHAR (print as string left aligned) case TYPE_VARCHAR: default: memcpy(data, el->data, el->size); printf(" %-*s|", col_len[i] + TBL_BOX_OFFSET, (const char *) data); break; } el = el->next; i++; } printf("\n"); AK_free(data); AK_EPI; }
/** * @author Dino Laktašić. * @brief Check if some set of attributes is subset of larger set * <ol> * <li>Tokenize set and subset of projection attributes and store each of them to it's own array</li> * <li>Check if the size of subset array is larger than the size of set array</li> * <li>if the subset array is larger return 0</li> * <li>else sort both arrays ascending</li> * <li>Compare the subset and set items at the same positions, starting from 0</li> * <li>if there is an item in the subset array that doesn't match attribute at the same position in the set array return 0</li> * <li>else continue comparing until final item in the subset array is ritched</li> * <li>on loop exit return EXIT_SUCCESS</li> * </ol> * @param *set set array * @param *subset subset array * @return EXIT_SUCCESS if some set of attributes is subset of larger set, else returns EXIT_FAILURE */ int AK_rel_eq_is_attr_subset(char *set, char *subset) { int len_set, len_subset; int set_id = 0; int subset_id = 0; char *temp_set, *temp_subset; char *token_set, *token_subset; char *save_token_set, *save_token_subset; char *tokens_set[MAX_TOKENS] = {NULL}; char *tokens_subset[MAX_TOKENS] = {NULL}; AK_PRO; if (set == NULL || subset == NULL) { AK_EPI; return EXIT_FAILURE; } len_set = len_subset = 0; temp_set = (char *) AK_calloc(strlen(set), sizeof (char)); temp_subset = (char *) AK_calloc(strlen(subset), sizeof (char)); memcpy(temp_set, set, strlen(set)); memcpy(temp_subset, subset, strlen(subset)); Ak_dbg_messg(HIGH, REL_EQ, "RULE - is (%s) subset of set (%s) in rel_eq_selection\n", subset, set); for ((token_set = strtok_r(temp_set, ATTR_DELIMITER, &save_token_set)); token_set; (token_set = strtok_r(NULL, ATTR_DELIMITER, &save_token_set)), set_id++) { if (set_id < MAX_TOKENS - 1) { tokens_set[set_id] = token_set; len_set++; } } for ((token_subset = strtok_r(temp_subset, ATTR_DELIMITER, &save_token_subset)); token_subset; (token_subset = strtok_r(NULL, ATTR_DELIMITER, &save_token_subset)), subset_id++) { if (subset_id < MAX_TOKENS - 1) { tokens_subset[subset_id] = token_subset; len_subset++; } } if (len_set < len_subset) { Ak_dbg_messg(HIGH, REL_EQ, "RULE - failed (%s) isn't subset of set (%s)!\n", subset, set); AK_EPI; return EXIT_FAILURE; } qsort(tokens_set, len_set, sizeof (char *), AK_strcmp); qsort(tokens_subset, len_subset, sizeof (char *), AK_strcmp); len_set = 0; for (subset_id = 0; tokens_subset[subset_id] != NULL; subset_id++) { for (set_id = 0; tokens_set[set_id] != NULL; set_id++) { if (strcmp(tokens_set[set_id], tokens_subset[subset_id]) == 0) { len_set++; } } } if (len_set != len_subset) { Ak_dbg_messg(HIGH, REL_EQ, "RULE - failed (%s) isn't subset of set (%s)!\n", subset, set); AK_EPI; return EXIT_FAILURE; } AK_free(temp_set); AK_free(temp_subset); Ak_dbg_messg(HIGH, REL_EQ, "RULE - succeed (%s) is subset of set (%s).\n", subset, set); AK_EPI; return EXIT_SUCCESS; }