diff --git a/python/obitools3/obidms/_obidms.pxd b/python/obitools3/obidms/_obidms.pxd index 0b5480b..908c9e3 100644 --- a/python/obitools3/obidms/_obidms.pxd +++ b/python/obitools3/obidms/_obidms.pxd @@ -91,5 +91,5 @@ cdef class OBIDMS: cpdef OBIView open_view(self, str view_name) cpdef OBIView new_view(self, str view_name, object view_to_clone=*, list line_selection=*, str view_type=*, str comments=*) cpdef dict read_view_infos(self, str view_name) - cpdef dict read_views(self) +# cpdef dict read_views(self) TODO diff --git a/python/obitools3/obidms/_obidms.pyx b/python/obitools3/obidms/_obidms.pyx index c74e7ca..2b516e7 100644 --- a/python/obitools3/obidms/_obidms.pyx +++ b/python/obitools3/obidms/_obidms.pyx @@ -44,7 +44,8 @@ from ._obidmscolumn_bool cimport OBIDMS_column_bool, \ from ._obidmscolumn_char cimport OBIDMS_column_char, \ OBIDMS_column_multi_elts_char -from ._obidmscolumn_qual cimport OBIDMS_column_qual +from ._obidmscolumn_qual cimport OBIDMS_column_qual, \ + OBIDMS_column_multi_elts_qual from ._obidmscolumn_str cimport OBIDMS_column_str, \ OBIDMS_column_multi_elts_str @@ -53,16 +54,15 @@ from ._obidmscolumn_seq cimport OBIDMS_column_seq, \ OBIDMS_column_multi_elts_seq from .capi.obiview cimport Obiview_p, \ - Obiviews_infos_all_p, \ Obiview_infos_p, \ Column_reference_p, \ obi_new_view_nuc_seqs, \ obi_new_view, \ obi_new_view_cloned_from_name, \ obi_new_view_nuc_seqs_cloned_from_name, \ + obi_view_map_file, \ + obi_view_unmap_file, \ obi_open_view, \ - obi_read_view_infos, \ - obi_close_view_infos, \ obi_view_delete_column, \ obi_view_add_column, \ obi_view_get_column, \ @@ -194,8 +194,8 @@ cdef class OBIDMS_column : elif col_type == OBI_QUAL : if col_one_element_per_line : subclass = OBIDMS_column_qual -# else : # TODO -# subclass = OBIDMS_column_multi_elts_qual + else : + subclass = OBIDMS_column_multi_elts_qual elif col_type == OBI_STR : if col_one_element_per_line : subclass = OBIDMS_column_str @@ -290,11 +290,11 @@ cdef class OBIView : raise Exception("Error creating/opening a view") self.pointer = view - self.name = bytes2str(view.name) + self.name = bytes2str(view.infos.name) # Go through columns to build list of corresponding python instances self.columns = {} - for i in range(view.column_count) : + for i in range(view.infos.column_count) : column_p = (view.columns)[i] header = (column_p).header col_name = bytes2str(header.name) @@ -304,7 +304,7 @@ cdef class OBIView : def __repr__(self) : cdef str s - s = str(self.name) + ", " + str(self.comments) + ", " + str(self.pointer.line_count) + " lines\n" + s = str(self.name) + ", " + str(self.comments) + ", " + str(self.pointer.infos.line_count) + " lines\n" for column_name in self.columns : s = s + self.columns[column_name].__repr__() + '\n' return s @@ -313,7 +313,7 @@ cdef class OBIView : cpdef delete_column(self, str column_name) : cdef int i - cdef Obiview_p view + cdef Obiview_p view_p cdef OBIDMS_column column cdef OBIDMS_column_p column_p cdef OBIDMS_column_header_p header @@ -321,7 +321,7 @@ cdef class OBIView : view = self.pointer - if obi_view_delete_column(view, str2bytes(column_name)) < 0 : + if obi_view_delete_column(view_p, str2bytes(column_name)) < 0 : raise Exception("Problem deleting a column from a view") # Update the dictionaries of column pointers and column objects, and update pointers in column objects (make function?): @@ -329,7 +329,7 @@ cdef class OBIView : for column_n in self.columns : (self.columns[column_n]).update_pointer() - + cpdef add_column(self, str column_name, @@ -401,7 +401,7 @@ cdef class OBIView : cdef OBIView_line line # TODO Check that this works for NUC SEQ views # Yield each line - lines_used = (self.pointer).line_count + lines_used = self.pointer.infos.line_count for line_nb in range(lines_used) : line = self[line_nb] @@ -485,12 +485,12 @@ cdef class OBIView_NUC_SEQS(OBIView): raise Exception("Error creating/opening view") self.pointer = view - self.name = bytes2str(view.name) - self.comments = bytes2str(view.comments) + self.name = bytes2str(view.infos.name) + self.comments = bytes2str(view.infos.comments) # Go through columns to build list of corresponding python instances self.columns = {} - for i in range(view.column_count) : + for i in range(view.infos.column_count) : column_p = (view.columns)[i] header = (column_p).header col_name = bytes2str(header.name) @@ -501,28 +501,6 @@ cdef class OBIView_NUC_SEQS(OBIView): self.sequences = self.columns[bytes2str(NUC_SEQUENCE_COLUMN)] self.definitions = self.columns[bytes2str(DEFINITION_COLUMN)] self.qualities = self.columns[bytes2str(QUALITY_COLUMN)] - - - cpdef delete_column(self, str column_name) : - - cdef int i - cdef Obiview_p view_p - cdef OBIDMS_column column - cdef OBIDMS_column_p column_p - cdef OBIDMS_column_header_p header - cdef str column_n - - view_p = self.pointer - - if obi_view_delete_column(view_p, str2bytes(column_name)) < 0 : - raise Exception("Problem deleting a column from a view") - - # Remove instance from the dictionary - (self.columns).pop(column_name) - - for column_n in self.columns : - (self.columns[column_n]).update_pointer() - def __getitem__(self, object item) : if type(item) == str : @@ -530,7 +508,6 @@ cdef class OBIView_NUC_SEQS(OBIView): elif type(item) == int : return OBI_Nuc_Seq_Stored(self, item) - def __setitem__(self, index_t line_idx, OBI_Nuc_Seq sequence_obj) : for key in sequence_obj : self[line_idx][key] = sequence_obj[key] @@ -625,7 +602,7 @@ cdef class OBIDMS : view_class = OBIView_NUC_SEQS else : view_class = OBIView - + return view_class(self, view_name) @@ -643,54 +620,84 @@ cdef class OBIDMS : cpdef dict read_view_infos(self, str view_name) : - all_views = self.read_views() - return all_views[view_name] - - - cpdef dict read_views(self) : # TODO function that prints the dic nicely and function that prints 1 view nicely. Add column type in col ref - cdef Obiviews_infos_all_p all_views_p - cdef Obiview_infos_p view_p + cdef Obiview_infos_p view_infos_p + cdef dict view_infos_d cdef Column_reference_p column_refs - cdef int nb_views cdef int i, j - cdef str view_name cdef str column_name - cdef dict views - cdef bytes name_b + + view_infos_p = obi_view_map_file(self.pointer, str2bytes(view_name)) + view_infos_d = {} + view_infos_d["name"] = bytes2str(view_infos_p.name) + view_infos_d["comments"] = bytes2str(view_infos_p.comments) + view_infos_d["view_type"] = bytes2str(view_infos_p.view_type) + view_infos_d["column_count"] = view_infos_p.column_count + view_infos_d["line_count"] = view_infos_p.line_count + view_infos_d["created_from"] = bytes2str(view_infos_p.created_from) + view_infos_d["creation_date"] = bytes2str(obi_format_date(view_infos_p.creation_date)) + if (view_infos_p.all_lines) : + view_infos_d["line_selection"] = None + else : + view_infos_d["line_selection"] = {} + view_infos_d["line_selection"]["column_name"] = bytes2str((view_infos_p.line_selection).column_name) + view_infos_d["line_selection"]["version"] = (view_infos_p.line_selection).version + view_infos_d["column_references"] = {} + column_refs = view_infos_p.column_references + for j in range(view_infos_d["column_count"]) : + column_name = bytes2str((column_refs[j]).column_name) + view_infos_d["column_references"][column_name] = {} + view_infos_d["column_references"][column_name]["version"] = column_refs[j].version - views = {} - all_views_p = obi_read_view_infos(self.pointer) - if all_views_p == NULL : - raise Exception("No views to read") - nb_views = (all_views_p.header).view_count - for i in range(nb_views) : - view_p = ( (all_views_p.view_infos)) + i - view_name = bytes2str(view_p.name) - views[view_name] = {} - views[view_name]["comments"] = bytes2str(view_p.comments) - views[view_name]["view_type"] = bytes2str(view_p.view_type) - views[view_name]["column_count"] = view_p.column_count - views[view_name]["line_count"] = view_p.line_count - views[view_name]["view_number"] = view_p.view_number - views[view_name]["created_from"] = bytes2str(view_p.created_from) - views[view_name]["creation_date"] = bytes2str(obi_format_date(view_p.creation_date)) - if (view_p.all_lines) : - views[view_name]["line_selection"] = None - else : - views[view_name]["line_selection"] = {} - views[view_name]["line_selection"]["column_name"] = bytes2str((view_p.line_selection).column_name) - views[view_name]["line_selection"]["version"] = (view_p.line_selection).version - views[view_name]["column_references"] = {} - column_refs = view_p.column_references - for j in range(views[view_name]["column_count"]) : - column_name = bytes2str((column_refs[j]).column_name) - views[view_name]["column_references"][column_name] = {} - views[view_name]["column_references"][column_name]["version"] = column_refs[j].version - - obi_close_view_infos(all_views_p); - - return views + obi_view_unmap_file(self.pointer, view_infos_p) + + return view_infos_d + + +# cpdef dict read_views(self) : # TODO function that prints the dic nicely and function that prints 1 view nicely. Add column type in col ref +# +# cdef Obiviews_infos_all_p all_views_p +# cdef Obiview_infos_p view_p +# cdef Column_reference_p column_refs +# cdef int nb_views +# cdef int i, j +# cdef str view_name +# cdef str column_name +# cdef dict views +# cdef bytes name_b +# +# views = {} +# all_views_p = obi_read_view_infos(self.pointer) +# if all_views_p == NULL : +# raise Exception("No views to read") +# nb_views = (all_views_p.header).view_count +# for i in range(nb_views) : +# view_p = ( (all_views_p.view_infos)) + i +# view_name = bytes2str(view_p.name) +# views[view_name] = {} +# views[view_name]["comments"] = bytes2str(view_p.comments) +# views[view_name]["view_type"] = bytes2str(view_p.view_type) +# views[view_name]["column_count"] = view_p.column_count +# views[view_name]["line_count"] = view_p.line_count +# views[view_name]["view_number"] = view_p.view_number +# views[view_name]["created_from"] = bytes2str(view_p.created_from) +# views[view_name]["creation_date"] = bytes2str(obi_format_date(view_p.creation_date)) +# if (view_p.all_lines) : +# views[view_name]["line_selection"] = None +# else : +# views[view_name]["line_selection"] = {} +# views[view_name]["line_selection"]["column_name"] = bytes2str((view_p.line_selection).column_name) +# views[view_name]["line_selection"]["version"] = (view_p.line_selection).version +# views[view_name]["column_references"] = {} +# column_refs = view_p.column_references +# for j in range(views[view_name]["column_count"]) : +# column_name = bytes2str((column_refs[j]).column_name) +# views[view_name]["column_references"][column_name] = {} +# views[view_name]["column_references"][column_name]["version"] = column_refs[j].version +# +# obi_close_view_infos(all_views_p); +# +# return views diff --git a/python/obitools3/obidms/_obidmscolumn_qual.pxd b/python/obitools3/obidms/_obidmscolumn_qual.pxd index 6384431..5015a52 100644 --- a/python/obitools3/obidms/_obidmscolumn_qual.pxd +++ b/python/obitools3/obidms/_obidmscolumn_qual.pxd @@ -1,7 +1,7 @@ #cython: language_level=3 from .capi.obitypes cimport index_t -from ._obidms cimport OBIDMS_column #, OBIDMS_column_multi_elts +from ._obidms cimport OBIDMS_column , OBIDMS_column_multi_elts cdef class OBIDMS_column_qual(OBIDMS_column): @@ -11,7 +11,10 @@ cdef class OBIDMS_column_qual(OBIDMS_column): cpdef set_str_line(self, index_t line_nb, object value) -# cdef class OBIDMS_column_multi_elts_qual(OBIDMS_column_multi_elts): -# cpdef object get_item(self, index_t line_nb, str element_name) -# cpdef object get_line(self, index_t line_nb) -# cpdef set_item(self, index_t line_nb, str element_name, object value) +cdef class OBIDMS_column_multi_elts_qual(OBIDMS_column_multi_elts): + cpdef object get_item(self, index_t line_nb, str element_name) + cpdef object get_str_item(self, index_t line_nb, str element_name) + cpdef object get_line(self, index_t line_nb) + cpdef object get_str_line(self, index_t line_nb) + cpdef set_item(self, index_t line_nb, str element_name, object value) + cpdef set_str_item(self, index_t line_nb, str element_name, object value) diff --git a/python/obitools3/obidms/_obidmscolumn_qual.pyx b/python/obitools3/obidms/_obidmscolumn_qual.pyx index a6e4a6b..7b6f74a 100644 --- a/python/obitools3/obidms/_obidmscolumn_qual.pyx +++ b/python/obitools3/obidms/_obidmscolumn_qual.pyx @@ -32,7 +32,7 @@ cdef class OBIDMS_column_qual(OBIDMS_column): value = obi_column_get_obiqual_int_with_elt_idx_in_view(self.view.pointer, (self.pointer)[0], line_nb, 0, &value_length) if obi_errno > 0 : raise IndexError(line_nb) - if value == NULL : # TODO + if value == OBIQual_int_NA : result = None else : result = [] @@ -47,7 +47,7 @@ cdef class OBIDMS_column_qual(OBIDMS_column): value = obi_column_get_obiqual_char_with_elt_idx_in_view(self.view.pointer, (self.pointer)[0], line_nb, 0) if obi_errno > 0 : raise IndexError(line_nb) - if strcmp(value, OBIQual_char_NA) == 0 : + if value == OBIQual_char_NA : result = None else : result = bytes2str(value) @@ -58,94 +58,127 @@ cdef class OBIDMS_column_qual(OBIDMS_column): cdef uint8_t* value_b cdef int value_length if value is None : - value_b = NULL # TODO - value_length = 0 + if obi_column_set_obiqual_int_with_elt_idx_in_view(self.view.pointer, (self.pointer)[0], line_nb, 0, OBIQual_int_NA, 0) < 0: + raise Exception("Problem setting a value in a column") else : value_length = len(value) value_b = malloc(value_length * sizeof(uint8_t)) for i in range(value_length) : value_b[i] = value[i] - if obi_column_set_obiqual_int_with_elt_idx_in_view(self.view.pointer, (self.pointer)[0], line_nb, 0, value_b, value_length) < 0: - raise Exception("Problem setting a value in a column") - if value is not None : + if obi_column_set_obiqual_int_with_elt_idx_in_view(self.view.pointer, (self.pointer)[0], line_nb, 0, value_b, value_length) < 0: + raise Exception("Problem setting a value in a column") free(value_b) cpdef set_str_line(self, index_t line_nb, object value): - cdef bytes value_b if value is None : - value_b = OBIQual_char_NA + if obi_column_set_obiqual_char_with_elt_idx_in_view(self.view.pointer, (self.pointer)[0], line_nb, 0, OBIQual_char_NA) < 0: + raise Exception("Problem setting a value in a column") else : - value_b = str2bytes(value) - if obi_column_set_obiqual_char_with_elt_idx_in_view(self.view.pointer, (self.pointer)[0], line_nb, 0, value_b) < 0: - raise Exception("Problem setting a value in a column") + if obi_column_set_obiqual_char_with_elt_idx_in_view(self.view.pointer, (self.pointer)[0], line_nb, 0, str2bytes(value)) < 0: + raise Exception("Problem setting a value in a column") -# TODO OR NOT? -# cdef class OBIDMS_column_multi_elts_qual(OBIDMS_column_multi_elts): -# -# -# cpdef object get_item(self, index_t line_nb, str element_name): -# cdef const uint8_t* value -# cdef int value_length -# cdef object result -# cdef int i -# value = obi_column_get_obiqual_int_with_elt_name_in_view(self.view.pointer, (self.pointer)[0], line_nb, str2bytes(element_name), &value_length) -# if obi_errno > 0 : -# raise IndexError(line_nb, element_name) -# if value == NULL: # TODO -# result = None -# else : -# result = [] -# for i in range(value_length) : -# result.append(value[i]) -# return result -# -# # cpdef object get_str_item(self, index_t line_nb, str element_name): -# # pass -# # cdef char* value -# # cdef object result -# # value = obi_column_get_obiseq_with_elt_name_in_view(self.view.pointer, (self.pointer)[0], line_nb, str2bytes(element_name)) -# # if obi_errno > 0 : -# # raise IndexError(line_nb, element_name) -# # if strcmp(value, OBISeq_NA) == 0 : -# # result = None -# # else : -# # result = bytes2str(value) -# # free(value) -# # return result -# -# cpdef object get_line(self, index_t line_nb) : -# pass -# # cdef char* value -# # cdef object value_in_result -# # cdef dict result -# # cdef index_t i -# # cdef bint all_NA -# # result = {} -# # all_NA = True -# # for i in range(self.nb_elements_per_line) : -# # value = obi_column_get_obiseq_with_elt_idx_in_view(self.view.pointer, (self.pointer)[0], line_nb, i) -# # if obi_errno > 0 : -# # raise IndexError(line_nb) -# # if strcmp(value, OBISeq_NA) == 0 : -# # value_in_result = None -# # else : -# # value_in_result = bytes2str(value) -# # free(value) -# # result[self.elements_names[i]] = value_in_result -# # if all_NA and (value_in_result is not None) : -# # all_NA = False -# # if all_NA : -# # result = None -# # return result -# -# cpdef set_item(self, index_t line_nb, str element_name, object value): -# pass -# # cdef bytes value_b -# # if value is None : -# # value_b = OBISeq_NA -# # else : -# # value_b = str2bytes(value) -# # if obi_column_set_obiseq_with_elt_name_in_view(self.view.pointer, (self.pointer)[0], line_nb, str2bytes(element_name), value_b) < 0: -# # raise Exception("Problem setting a value in a column") -# # +cdef class OBIDMS_column_multi_elts_qual(OBIDMS_column_multi_elts): + + cpdef object get_item(self, index_t line_nb, str element_name): + cdef const uint8_t* value + cdef int value_length + cdef object result + cdef int i + value = obi_column_get_obiqual_int_with_elt_name_in_view(self.view.pointer, (self.pointer)[0], line_nb, str2bytes(element_name), &value_length) + if obi_errno > 0 : + raise IndexError(line_nb, element_name) + if value == OBIQual_int_NA : + result = None + else : + result = [] + for i in range(value_length) : + result.append(value[i]) + return result + + cpdef object get_str_item(self, index_t line_nb, str element_name): + cdef char* value + cdef object result + value = obi_column_get_obiqual_char_with_elt_name_in_view(self.view.pointer, (self.pointer)[0], line_nb, str2bytes(element_name)) + if obi_errno > 0 : + raise IndexError(line_nb, element_name) + if value == OBIQual_char_NA : + result = None + else : + result = bytes2str(value) + free(value) + return result + + cpdef object get_line(self, index_t line_nb) : + cdef const uint8_t* value + cdef int value_length + cdef object value_in_result + cdef dict result + cdef index_t i + cdef int j + cdef bint all_NA + result = {} + all_NA = True + for i in range(self.nb_elements_per_line) : + value = obi_column_get_obiqual_int_with_elt_idx_in_view(self.view.pointer, (self.pointer)[0], line_nb, i, &value_length) + if obi_errno > 0 : + raise IndexError(line_nb) + if value == OBIQual_int_NA : + value_in_result = None + else : + value_in_result = [] + for j in range(value_length) : + value_in_result.append(value[j]) + result[self.elements_names[i]] = value_in_result + if all_NA and (value_in_result is not None) : + all_NA = False + if all_NA : + result = None + return result + + cpdef object get_str_line(self, index_t line_nb) : + cdef char* value + cdef object value_in_result + cdef dict result + cdef index_t i + cdef bint all_NA + result = {} + all_NA = True + for i in range(self.nb_elements_per_line) : + value = obi_column_get_obiqual_char_with_elt_idx_in_view(self.view.pointer, (self.pointer)[0], line_nb, i) + if obi_errno > 0 : + raise IndexError(line_nb) + if value == OBIQual_char_NA : + value_in_result = None + else : + value_in_result = bytes2str(value) + free(value) + result[self.elements_names[i]] = value_in_result + if all_NA and (value_in_result is not None) : + all_NA = False + if all_NA : + result = None + return result + + cpdef set_item(self, index_t line_nb, str element_name, object value): + cdef uint8_t* value_b + cdef int value_length + if value is None : + if obi_column_set_obiqual_int_with_elt_name_in_view(self.view.pointer, (self.pointer)[0], line_nb, str2bytes(element_name), OBIQual_int_NA, 0) < 0: + raise Exception("Problem setting a value in a column") + else : + value_length = len(value) + value_b = malloc(value_length * sizeof(uint8_t)) + for i in range(value_length) : + value_b[i] = value[i] + if obi_column_set_obiqual_int_with_elt_name_in_view(self.view.pointer, (self.pointer)[0], line_nb, str2bytes(element_name), value_b, value_length) < 0: + raise Exception("Problem setting a value in a column") + free(value_b) + + cpdef set_str_item(self, index_t line_nb, str element_name, object value): + if value is None : + if obi_column_set_obiqual_char_with_elt_name_in_view(self.view.pointer, (self.pointer)[0], line_nb, str2bytes(element_name), OBIQual_char_NA) < 0: + raise Exception("Problem setting a value in a column") + else : + if obi_column_set_obiqual_char_with_elt_name_in_view(self.view.pointer, (self.pointer)[0], line_nb, str2bytes(element_name), str2bytes(value)) < 0: + raise Exception("Problem setting a value in a column") diff --git a/python/obitools3/obidms/_obidmscolumn_seq.pyx b/python/obitools3/obidms/_obidmscolumn_seq.pyx index 0819d82..2cf6b93 100644 --- a/python/obitools3/obidms/_obidmscolumn_seq.pyx +++ b/python/obitools3/obidms/_obidmscolumn_seq.pyx @@ -13,7 +13,6 @@ from ._obidms cimport OBIView from obitools3.utils cimport str2bytes, bytes2str from libc.stdlib cimport free -from libc.string cimport strcmp cdef class OBIDMS_column_seq(OBIDMS_column): @@ -24,7 +23,7 @@ cdef class OBIDMS_column_seq(OBIDMS_column): value = obi_column_get_obiseq_with_elt_idx_in_view(self.view.pointer, (self.pointer)[0], line_nb, 0) if obi_errno > 0 : raise IndexError(line_nb) - if strcmp(value, OBISeq_NA) == 0 : + if value == OBISeq_NA : result = None else : result = bytes2str(value) @@ -32,13 +31,12 @@ cdef class OBIDMS_column_seq(OBIDMS_column): return result cpdef set_line(self, index_t line_nb, object value): - cdef bytes value_b if value is None : - value_b = OBISeq_NA + if obi_column_set_obiseq_with_elt_idx_in_view(self.view.pointer, (self.pointer)[0], line_nb, 0, OBISeq_NA) < 0: + raise Exception("Problem setting a value in a column") else : - value_b = str2bytes(value) - if obi_column_set_obiseq_with_elt_idx_in_view(self.view.pointer, (self.pointer)[0], line_nb, 0, value_b) < 0: - raise Exception("Problem setting a value in a column") + if obi_column_set_obiseq_with_elt_idx_in_view(self.view.pointer, (self.pointer)[0], line_nb, 0, str2bytes(value)) < 0: + raise Exception("Problem setting a value in a column") # TODO choose alignment type (lcs or other) with supplementary argument cpdef align(self, @@ -61,7 +59,7 @@ cdef class OBIDMS_column_multi_elts_seq(OBIDMS_column_multi_elts): value = obi_column_get_obiseq_with_elt_name_in_view(self.view.pointer, (self.pointer)[0], line_nb, str2bytes(element_name)) if obi_errno > 0 : raise IndexError(line_nb, element_name) - if strcmp(value, OBISeq_NA) == 0 : + if value == OBISeq_NA : result = None else : result = bytes2str(value) @@ -80,7 +78,7 @@ cdef class OBIDMS_column_multi_elts_seq(OBIDMS_column_multi_elts): value = obi_column_get_obiseq_with_elt_idx_in_view(self.view.pointer, (self.pointer)[0], line_nb, i) if obi_errno > 0 : raise IndexError(line_nb) - if strcmp(value, OBISeq_NA) == 0 : + if value == OBISeq_NA : value_in_result = None else : value_in_result = bytes2str(value) diff --git a/python/obitools3/obidms/_obidmscolumn_str.pyx b/python/obitools3/obidms/_obidmscolumn_str.pyx index d3f4b90..2382ca9 100644 --- a/python/obitools3/obidms/_obidmscolumn_str.pyx +++ b/python/obitools3/obidms/_obidmscolumn_str.pyx @@ -9,8 +9,6 @@ from .capi.obitypes cimport OBIStr_NA, const_char_p from obitools3.utils cimport str2bytes, bytes2str -from libc.string cimport strcmp - cdef class OBIDMS_column_str(OBIDMS_column): @@ -20,7 +18,7 @@ cdef class OBIDMS_column_str(OBIDMS_column): value = obi_column_get_obistr_with_elt_idx_in_view(self.view.pointer, (self.pointer)[0], line_nb, 0) if obi_errno > 0 : raise IndexError(line_nb) - if strcmp(value, OBIStr_NA) == 0 : + if value == OBIStr_NA : result = None else : result = bytes2str(value) @@ -28,13 +26,12 @@ cdef class OBIDMS_column_str(OBIDMS_column): return result cpdef set_line(self, index_t line_nb, object value): - cdef bytes value_b if value is None : - value_b = OBIStr_NA + if obi_column_set_obistr_with_elt_idx_in_view(self.view.pointer, (self.pointer)[0], line_nb, 0, OBIStr_NA) < 0: + raise Exception("Problem setting a value in a column") else : - value_b = str2bytes(value) - if obi_column_set_obistr_with_elt_idx_in_view(self.view.pointer, (self.pointer)[0], line_nb, 0, value_b) < 0: - raise Exception("Problem setting a value in a column") + if obi_column_set_obistr_with_elt_idx_in_view(self.view.pointer, (self.pointer)[0], line_nb, 0, str2bytes(value)) < 0: + raise Exception("Problem setting a value in a column") cdef class OBIDMS_column_multi_elts_str(OBIDMS_column_multi_elts): @@ -45,7 +42,7 @@ cdef class OBIDMS_column_multi_elts_str(OBIDMS_column_multi_elts): value = obi_column_get_obistr_with_elt_name_in_view(self.view.pointer, (self.pointer)[0], line_nb, str2bytes(element_name)) if obi_errno > 0 : raise IndexError(line_nb, element_name) - if strcmp(value, OBIStr_NA) == 0 : + if value == OBIStr_NA : result = None else : result = bytes2str(value) @@ -64,7 +61,7 @@ cdef class OBIDMS_column_multi_elts_str(OBIDMS_column_multi_elts): value = obi_column_get_obistr_with_elt_idx_in_view(self.view.pointer, (self.pointer)[0], line_nb, i) if obi_errno > 0 : raise IndexError(line_nb) - if strcmp(value, OBIStr_NA) == 0 : + if value == OBIStr_NA : value_in_result = None else : value_in_result = bytes2str(value) diff --git a/python/obitools3/obidms/_obiseq.pxd b/python/obitools3/obidms/_obiseq.pxd index 8ba239a..4c79b1d 100644 --- a/python/obitools3/obidms/_obiseq.pxd +++ b/python/obitools3/obidms/_obiseq.pxd @@ -4,35 +4,35 @@ from ._obidms cimport OBIView_line cdef class OBI_Seq(dict) : - cdef str id - cdef str definition - cdef str sequence + cdef object id + cdef object definition + cdef object sequence - cpdef set_id(self, str id) - cpdef get_id(self) - cpdef set_definition(self, str definition) - cpdef get_definition(self) - cpdef get_sequence(self) + cpdef set_id(self, object id) + cpdef object get_id(self) + cpdef set_definition(self, object definition) + cpdef object get_definition(self) + cpdef object get_sequence(self) cdef class OBI_Nuc_Seq(OBI_Seq) : cdef object quality - #cpdef str reverse_complement(self) - cpdef set_sequence(self, str sequence) + #cpdef object reverse_complement(self) + cpdef set_sequence(self, object sequence) cpdef set_quality(self, object quality) - cpdef get_quality(self) + cpdef object get_quality(self) cdef class OBI_Nuc_Seq_Stored(OBIView_line) : - cpdef set_id(self, str id) - cpdef get_id(self) - cpdef set_definition(self, str definition) - cpdef get_definition(self) - cpdef set_sequence(self, str sequence) - cpdef get_sequence(self) + cpdef set_id(self, object id) + cpdef object get_id(self) + cpdef set_definition(self, object definition) + cpdef object get_definition(self) + cpdef set_sequence(self, object sequence) + cpdef object get_sequence(self) cpdef set_quality(self, object quality) - cpdef get_quality(self) - cpdef get_str_quality(self) + cpdef object get_quality(self) + cpdef object get_str_quality(self) - # cpdef str reverse_complement(self) + # cpdef object reverse_complement(self) diff --git a/python/obitools3/obidms/_obiseq.pyx b/python/obitools3/obidms/_obiseq.pyx index 8a09d4c..d649ebb 100644 --- a/python/obitools3/obidms/_obiseq.pyx +++ b/python/obitools3/obidms/_obiseq.pyx @@ -9,20 +9,20 @@ from .capi.obiview cimport NUC_SEQUENCE_COLUMN, \ cdef class OBI_Seq(dict) : - def __init__(self, str id, str seq, str definition=None) : + def __init__(self, object id, object seq, object definition=None) : self.set_id(id) self.set_sequence(seq) if definition is not None : self.set_definition(definition) - cpdef set_id(self, str id) : + cpdef set_id(self, object id) : self.id = id self[bytes2str(ID_COLUMN)] = id cpdef get_id(self) : return self.id - cpdef set_definition(self, str definition) : + cpdef set_definition(self, object definition) : self.definition = definition self[bytes2str(DEFINITION_COLUMN)] = definition @@ -38,7 +38,7 @@ cdef class OBI_Seq(dict) : cdef class OBI_Nuc_Seq(OBI_Seq) : - cpdef set_sequence(self, str sequence) : + cpdef set_sequence(self, object sequence) : self.sequence = sequence self[bytes2str(NUC_SEQUENCE_COLUMN)] = sequence @@ -57,34 +57,34 @@ cdef class OBI_Nuc_Seq_Stored(OBIView_line) : # TODO store the str version of column name macros - cpdef set_id(self, str id) : + cpdef set_id(self, object id) : self[bytes2str(ID_COLUMN)] = id - cpdef get_id(self) : + cpdef object get_id(self) : return self[bytes2str(ID_COLUMN)] - cpdef set_definition(self, str definition) : + cpdef set_definition(self, object definition) : self[bytes2str(DEFINITION_COLUMN)] = definition - cpdef get_definition(self) : + cpdef object get_definition(self) : return self[bytes2str(DEFINITION_COLUMN)] - cpdef set_sequence(self, str sequence) : + cpdef set_sequence(self, object sequence) : self[bytes2str(NUC_SEQUENCE_COLUMN)] = sequence - cpdef get_sequence(self) : + cpdef object get_sequence(self) : return self[bytes2str(NUC_SEQUENCE_COLUMN)] cpdef set_quality(self, object quality) : - if type(quality) == list : + if (type(quality) == list) or (quality is None) : self[bytes2str(QUALITY_COLUMN)] = quality else : # Quality is in str form (((self.view).columns)[bytes2str(QUALITY_COLUMN)]).set_str_line(self.index, quality) - cpdef get_quality(self) : + cpdef object get_quality(self) : return self[bytes2str(QUALITY_COLUMN)] - cpdef get_str_quality(self) : + cpdef object get_str_quality(self) : return ((self.view).columns)[bytes2str(QUALITY_COLUMN)].get_str_line(self.index) # def __str__(self) : diff --git a/python/obitools3/obidms/capi/obitypes.pxd b/python/obitools3/obidms/capi/obitypes.pxd index 6a83a26..d765629 100644 --- a/python/obitools3/obidms/capi/obitypes.pxd +++ b/python/obitools3/obidms/capi/obitypes.pxd @@ -1,7 +1,8 @@ #cython: language_level=3 -from libc.stdint cimport int32_t, int64_t +from libc.stdint cimport int32_t, int64_t, uint8_t + from posix.types cimport time_t @@ -47,8 +48,8 @@ cdef extern from "obitypes.h" nogil: extern obibool_t OBIBool_NA extern const_char_p OBISeq_NA extern const_char_p OBIStr_NA - extern const_char_p OBIQual_int_NA extern const_char_p OBIQual_char_NA + extern uint8_t* OBIQual_int_NA const_char_p name_data_type(int data_type) diff --git a/python/obitools3/obidms/capi/obiview.pxd b/python/obitools3/obidms/capi/obiview.pxd index 6c48de6..50cc56a 100644 --- a/python/obitools3/obidms/capi/obiview.pxd +++ b/python/obitools3/obidms/capi/obiview.pxd @@ -23,21 +23,6 @@ cdef extern from "obiview.h" nogil: extern const_char_p DEFINITION_COLUMN extern const_char_p QUALITY_COLUMN - struct Obiview_t : - OBIDMS_p dms - const_char_p name - const_char_p created_from - const_char_p view_type - bint read_only - OBIDMS_column_p line_selection - OBIDMS_column_p new_line_selection - index_t line_count - int column_count - OBIDMS_column_p columns - const_char_p comments - - ctypedef Obiview_t* Obiview_p - struct Column_reference_t : const_char_p column_name @@ -47,7 +32,6 @@ cdef extern from "obiview.h" nogil: struct Obiview_infos_t : - int view_number time_t creation_date const_char_p name const_char_p created_from @@ -62,19 +46,15 @@ cdef extern from "obiview.h" nogil: ctypedef Obiview_infos_t* Obiview_infos_p - struct Obiviews_header_t : - size_t header_size - size_t views_size - int view_count - - ctypedef Obiviews_header_t* Obiviews_header_p + struct Obiview_t : + Obiview_infos_p infos + OBIDMS_p dms + bint read_only + OBIDMS_column_p line_selection + OBIDMS_column_p new_line_selection + OBIDMS_column_p columns - - struct Obiviews_infos_all_t : - Obiviews_header_p header - Obiview_infos_p view_infos - - ctypedef Obiviews_infos_all_t* Obiviews_infos_all_p + ctypedef Obiview_t* Obiview_p Obiview_p obi_new_view_nuc_seqs(OBIDMS_p dms, const_char_p view_name, Obiview_p view_to_clone, index_t* line_selection, const_char_p comments) @@ -85,6 +65,10 @@ cdef extern from "obiview.h" nogil: Obiview_p obi_new_view_nuc_seqs_cloned_from_name(OBIDMS_p dms, const_char_p view_name, const_char_p view_to_clone_name, index_t* line_selection, const_char_p comments) + Obiview_infos_p obi_view_map_file(OBIDMS_p dms, const char* view_name) + + int obi_view_unmap_file(OBIDMS_p dms, Obiview_infos_p view_infos) + Obiview_p obi_open_view(OBIDMS_p dms, const_char_p view_name) int obi_view_add_column(Obiview_p view, @@ -113,10 +97,6 @@ cdef extern from "obiview.h" nogil: int obi_close_view(Obiview_p view) int obi_save_and_close_view(Obiview_p view) - - Obiviews_infos_all_p obi_read_view_infos(OBIDMS_p dms) - - int obi_close_view_infos(Obiviews_infos_all_p views) int obi_column_set_obiint_with_elt_name_in_view(Obiview_p view, OBIDMS_column_p column, diff --git a/src/obi_align.c b/src/obi_align.c index 2103529..4bdc214 100644 --- a/src/obi_align.c +++ b/src/obi_align.c @@ -25,7 +25,7 @@ // TODO -// use openMP pragmas : garder scores en memoire et ecrire a la fin? +// use openMP pragmas : garder scores en memoire et ecrire a la fin? (normalement c bon avec index) // tout ecrire en stdint? // check NUC_SEQS and score type (int or float if normalize) // what's with multiple sequence/line columns? diff --git a/src/obiavl.c b/src/obiavl.c index b8e10a2..8c68ae3 100644 --- a/src/obiavl.c +++ b/src/obiavl.c @@ -107,6 +107,42 @@ static char* build_avl_file_name(const char* avl_name); static char* build_avl_data_file_name(const char* avl_name); +/** + * @brief Internal function building the full path of an AVL tree file. + * + * @warning The returned pointer has to be freed by the caller. + * + * @param dms A pointer to the OBIDMS to which the AVL tree belongs. + * @param avl_name The name of the AVL tree. + * @param avl_idx The index of the AVL if it's part of an AVL group, or -1 if not. + * + * @returns A pointer to the full path of the file where the AVL tree is stored. + * @retval NULL if an error occurred. + * + * @since May 2016 + * @author Celine Mercier (celine.mercier@metabarcoding.org) + */ +static char* get_full_path_of_avl_file_name(OBIDMS_p dms, const char* avl_name, int avl_idx); + + +/** + * @brief Internal function building the file name for an AVL data file. + * + * @warning The returned pointer has to be freed by the caller. + * + * @param dms A pointer to the OBIDMS to which the AVL tree belongs. + * @param avl_name The name of the AVL tree. + * @param avl_idx The index of the AVL if it's part of an AVL group, or -1 if not. + * + * @returns A pointer to the full path of the file where the data referred to by the AVL tree is stored. + * @retval NULL if an error occurred. + * + * @since May 2016 + * @author Celine Mercier (celine.mercier@metabarcoding.org) + */ +static char* get_full_path_of_avl_data_file_name(OBIDMS_p dms, const char* avl_name, int avl_idx); + + /** * @brief Internal function returning the size of an AVL tree header on this platform, * including the size of the bloom filter associated with the AVL tree. @@ -253,9 +289,12 @@ int remap_an_avl(OBIDMS_avl_p avl); /** - * @brief Internal function (re)mapping the tree and data parts of an AVL tree structure. + * @brief Internal function creating and adding a new AVL in an AVL group. * - * @param avl A pointer to the AVL tree group structure. + * @warning The previous AVL in the list of the group is unmapped, + * if it's not the 1st AVL being added. + * + * @param avl A pointer on the AVL tree group structure. * * @retval 0 if the operation was successfully completed. * @retval -1 if an error occurred. @@ -547,6 +586,102 @@ static char* build_avl_data_file_name(const char* avl_name) } +static char* get_full_path_of_avl_file_name(OBIDMS_p dms, const char* avl_name, int avl_idx) +{ + char* complete_avl_name; + char* full_path; + char* avl_file_name; + + if (avl_idx >= 0) + { + complete_avl_name = build_avl_name_with_idx(avl_name, avl_idx); + if (complete_avl_name == NULL) + return NULL; + } + else + { + complete_avl_name = (char*) malloc((strlen(avl_name)+1)*sizeof(char)); + if (complete_avl_name == NULL) + { + obi_set_errno(OBI_MALLOC_ERROR); + obidebug(1, "\nError allocating memory for an AVL name"); + return NULL; + } + strcpy(complete_avl_name, avl_name); + } + + avl_file_name = build_avl_file_name(complete_avl_name); + if (avl_file_name == NULL) + { + free(complete_avl_name); + return NULL; + } + + full_path = get_full_path_of_avl_dir(dms, avl_name); + if (full_path == NULL) + { + free(complete_avl_name); + free(avl_file_name); + return NULL; + } + + strcat(full_path, "/"); + strcat(full_path, avl_file_name); + + free(complete_avl_name); + + return full_path; +} + + +static char* get_full_path_of_avl_data_file_name(OBIDMS_p dms, const char* avl_name, int avl_idx) +{ + char* complete_avl_name; + char* full_path; + char* avl_data_file_name; + + if (avl_idx >= 0) + { + complete_avl_name = build_avl_name_with_idx(avl_name, avl_idx); + if (complete_avl_name == NULL) + return NULL; + } + else + { + complete_avl_name = (char*) malloc((strlen(avl_name)+1)*sizeof(char)); + if (complete_avl_name == NULL) + { + obi_set_errno(OBI_MALLOC_ERROR); + obidebug(1, "\nError allocating memory for an AVL name"); + return NULL; + } + strcpy(complete_avl_name, avl_name); + } + + avl_data_file_name = build_avl_data_file_name(complete_avl_name); + if (avl_data_file_name == NULL) + { + free(complete_avl_name); + return NULL; + } + + full_path = get_full_path_of_avl_dir(dms, avl_name); + if (full_path == NULL) + { + free(complete_avl_name); + free(avl_data_file_name); + return NULL; + } + + strcat(full_path, "/"); + strcat(full_path, avl_data_file_name); + + free(complete_avl_name); + + return full_path; +} + + size_t get_avl_header_size() { size_t header_size; @@ -646,7 +781,6 @@ int truncate_avl_to_size_used(OBIDMS_avl_p avl) // TODO is it necessary to unmap file_descriptor, (avl->header)->header_size ); - if (avl->tree == MAP_FAILED) { obi_set_errno(OBI_AVL_ERROR); @@ -930,9 +1064,10 @@ int add_new_avl_in_group(OBIDMS_avl_group_p avl_group) return -1; } - // Unmap the previous AVL - if (unmap_an_avl((avl_group->sub_avls)[avl_group->last_avl_idx]) < 0) - return -1; + // Unmap the previous AVL if it's not the 1st + if (avl_group->last_avl_idx > 0) + if (unmap_an_avl((avl_group->sub_avls)[avl_group->last_avl_idx]) < 0) + return -1; // Increment current AVL index (avl_group->last_avl_idx)++; @@ -949,6 +1084,36 @@ int add_new_avl_in_group(OBIDMS_avl_group_p avl_group) } +// TODO doc +int add_existing_avl_in_group(OBIDMS_avl_group_p avl_group_dest, OBIDMS_avl_group_p avl_group_source, int avl_idx) +{ + if (link(get_full_path_of_avl_file_name(avl_group_source->dms, avl_group_source->name, avl_idx), get_full_path_of_avl_file_name(avl_group_dest->dms, avl_group_dest->name, avl_idx)) < 0) + { + obi_set_errno(OBI_AVL_ERROR); + obidebug(1, "\nError creating a hard link to an existing AVL tree file"); + return -1; + } + if (link(get_full_path_of_avl_data_file_name(avl_group_source->dms, avl_group_source->name, avl_idx), get_full_path_of_avl_data_file_name(avl_group_dest->dms, avl_group_dest->name, avl_idx)) < 0) + { + obi_set_errno(OBI_AVL_ERROR); + obidebug(1, "\nError creating a hard link to an existing AVL data file"); + return -1; + } + + // Increment current AVL index + (avl_group_dest->last_avl_idx)++; + + // Open AVL for that group TODO ideally not needed, but needed for now + avl_group_dest->sub_avls[avl_group_dest->last_avl_idx] = obi_open_avl(avl_group_source->dms, avl_group_source->name, avl_idx); + if ((avl_group_dest->sub_avls)[avl_group_dest->last_avl_idx] == NULL) + { + obidebug(1, "\nError opening an AVL to add in an AVL group"); + return -1; + } + + return 0; +} + int maybe_in_avl(OBIDMS_avl_p avl, Obi_blob_p value) { return (bloom_check(&((avl->header)->bloom_filter), value, obi_blob_sizeof(value))); @@ -1529,8 +1694,7 @@ OBIDMS_avl_p obi_create_avl(OBIDMS_p dms, const char* avl_name, int avl_idx) // Bloom filter bloom_init(&((avl->header)->bloom_filter), MAX_NODE_COUNT_PER_AVL); - if (avl_idx >= 0) - free(complete_avl_name); + free(complete_avl_name); return avl; } @@ -1777,8 +1941,7 @@ OBIDMS_avl_p obi_open_avl(OBIDMS_p dms, const char* avl_name, int avl_idx) avl->dir_fd = avl_dir_file_descriptor; avl->avl_fd = avl_file_descriptor; - if (avl_idx >= 0) - free(complete_avl_name); + free(complete_avl_name); return avl; } @@ -1806,6 +1969,7 @@ OBIDMS_avl_group_p obi_avl_group(OBIDMS_p dms, const char* avl_name) OBIDMS_avl_group_p obi_create_avl_group(OBIDMS_p dms, const char* avl_name) { OBIDMS_avl_group_p avl_group; + char* avl_dir_name; avl_group = (OBIDMS_avl_group_p) malloc(sizeof(OBIDMS_avl_group_t)); if (avl_group == NULL) @@ -1815,18 +1979,22 @@ OBIDMS_avl_group_p obi_create_avl_group(OBIDMS_p dms, const char* avl_name) return NULL; } - // Create 1st avl - (avl_group->sub_avls)[0] = obi_create_avl(dms, avl_name, 0); - if ((avl_group->sub_avls)[0] == NULL) - { - obidebug(1, "\nError creating the first AVL of an AVL group"); - return NULL; - } - - avl_group->last_avl_idx = 0; + avl_group->last_avl_idx = -1; + avl_group->dms = dms; strcpy(avl_group->name, avl_name); - avl_group->dms = dms; + // Create the directory for that AVL group + avl_dir_name = get_full_path_of_avl_dir(dms, avl_name); + if (avl_dir_name == NULL) + return NULL; + + if (mkdirat(dms->indexer_dir_fd, avl_dir_name, 00777) < 0) + { + obi_set_errno(OBI_AVL_ERROR); + obidebug(1, "\nError creating an AVL directory"); + free(avl_dir_name); + return NULL; + } // Add in the list of open indexers obi_dms_list_indexer(dms, avl_group); @@ -1926,20 +2094,23 @@ OBIDMS_avl_group_p obi_clone_avl_group(OBIDMS_avl_group_p avl_group, const char* // Create the new AVL group new_avl_group = obi_create_avl_group(avl_group->dms, new_avl_name); - // Copy the data from each old AVL to the new ones - for (i=0; i<=(avl_group->last_avl_idx); i++) + // Create hard links to all the full AVLs that won't be modified: all but the last one + for (i=0; i<(avl_group->last_avl_idx); i++) { - if (i > 0) // Don't need to create the 1st AVL - { - if (add_new_avl_in_group(new_avl_group) < 0) - { - obi_close_avl_group(new_avl_group); - return NULL; - } - } - obi_clone_avl((avl_group->sub_avls)[i], (new_avl_group->sub_avls)[i]); + if (add_existing_avl_in_group(new_avl_group, avl_group, i) < 0) + return NULL; } + // Create the last AVL to copy data in it + if (add_new_avl_in_group(new_avl_group) < 0) + { + obi_close_avl_group(new_avl_group); + return NULL; + } + + // Copy the data from the last AVL to a new one that can be modified + obi_clone_avl((avl_group->sub_avls)[avl_group->last_avl_idx], (new_avl_group->sub_avls)[new_avl_group->last_avl_idx]); + // Close old AVL group if (obi_close_avl_group(avl_group) < 0) { @@ -1959,7 +2130,7 @@ int obi_close_avl(OBIDMS_avl_p avl) ret_val = truncate_avl_to_size_used(avl); - if (munmap(avl->tree, (((avl->header)->nb_items_max) * sizeof(AVL_node_t))) < 0) + if (munmap(avl->tree, (avl->header)->avl_size) < 0) { obi_set_errno(OBI_AVL_ERROR); obidebug(1, "\nError munmapping the tree of an AVL tree file"); @@ -1996,9 +2167,17 @@ int obi_close_avl_group(OBIDMS_avl_group_p avl_group) ret_val = obi_dms_unlist_indexer(avl_group->dms, avl_group); // Close each AVL of the group - for (i=0; i < (avl_group->last_avl_idx); i++) + for (i=0; i <= (avl_group->last_avl_idx); i++) + { + // Remap all but the last AVL (already mapped) before closing to truncate and close properly + if (i < (avl_group->last_avl_idx)) + { + if (remap_an_avl((avl_group->sub_avls)[i]) < 0) + ret_val = -1; + } if (obi_close_avl((avl_group->sub_avls)[i]) < 0) ret_val = -1; + } free(avl_group); } @@ -2207,6 +2386,16 @@ index_t obi_avl_group_add(OBIDMS_avl_group_p avl_group, Obi_blob_p value) index_t index_with_avl; int i; + // Create 1st AVL if group is empty + if (avl_group->last_avl_idx == -1) + { + if (add_new_avl_in_group(avl_group) < 0) + { + obidebug(1, "\nError creating the first AVL of an AVL group"); + return -1; + } + } + if (maybe_in_avl((avl_group->sub_avls)[avl_group->last_avl_idx], value)) { index_in_avl = (int32_t) obi_avl_find((avl_group->sub_avls)[avl_group->last_avl_idx], value); @@ -2218,6 +2407,7 @@ index_t obi_avl_group_add(OBIDMS_avl_group_p avl_group, Obi_blob_p value) return index_with_avl; } } + for (i=0; i < (avl_group->last_avl_idx); i++) { if (maybe_in_avl((avl_group->sub_avls)[i], value)) diff --git a/src/obiavl.h b/src/obiavl.h index 6b05d4e..e3655f1 100644 --- a/src/obiavl.h +++ b/src/obiavl.h @@ -73,7 +73,7 @@ typedef struct AVL_node { * @brief OBIDMS AVL tree data header structure. */ typedef struct OBIDMS_avl_data_header { - int header_size; /**< Size of the header in bytes. + size_t header_size; /**< Size of the header in bytes. */ index_t data_size_used; /**< Size of the data used in bytes. */ @@ -105,7 +105,7 @@ typedef struct OBIDMS_avl_data { * @brief OBIDMS AVL tree header structure. */ typedef struct OBIDMS_avl_header { - int header_size; /**< Size of the header in bytes. + size_t header_size; /**< Size of the header in bytes. */ size_t avl_size; /**< Size of the AVL tree in bytes. */ @@ -160,7 +160,7 @@ typedef struct OBIDMS_avl { typedef struct OBIDMS_avl_group { OBIDMS_avl_p sub_avls[MAX_NB_OF_AVLS_IN_GROUP]; /**< Array containing the pointers to the AVL trees of the group. */ - int last_avl_idx; /**< Index in the sub_avls array of the AVL tree currently being filled. + int last_avl_idx; /**< Index in the sub_avls array of the AVL tree currently being filled. */ char name[AVL_MAX_NAME+1]; /**< Base name of the AVL group. The AVL trees in it have names of the form basename_idx. */ diff --git a/src/obidms.c b/src/obidms.c index 2ab190f..6f7eb23 100644 --- a/src/obidms.c +++ b/src/obidms.c @@ -252,7 +252,7 @@ OBIDMS_p obi_create_dms(const char* dms_path) return NULL; } - // Get file descriptor of DMS directory to create the indexer directory + // Get file descriptor of DMS directory to create other directories dms_dir = opendir(directory_name); if (dms_dir == NULL) { @@ -280,6 +280,14 @@ OBIDMS_p obi_create_dms(const char* dms_path) return NULL; } + // Create the view directory + if (mkdirat(dms_file_descriptor, VIEW_DIR_NAME, 00777) < 0) + { + obi_set_errno(OBIVIEW_ERROR); + obidebug(1, "\nProblem creating a view directory"); + return NULL; + } + // Isolate the dms name j = 0; for (i=0; iview_directory = opendir_in_dms(dms, VIEW_DIR_NAME); + if (dms->view_directory == NULL) + { + obi_set_errno(OBIDMS_UNKNOWN_ERROR); + obidebug(1, "\nError opening the view directory"); + closedir(dms->indexer_directory); + closedir(dms->directory); + free(dms); + return NULL; + } + + // Store the view directory's file descriptor + dms->view_dir_fd = dirfd(dms->view_directory); + if (dms->view_dir_fd < 0) + { + obi_set_errno(OBIDMS_UNKNOWN_ERROR); + obidebug(1, "\nError getting the file descriptor of the view directory"); + closedir(dms->view_directory); + closedir(dms->directory); + free(dms); + return NULL; + } + // Initialize the list of opened columns dms->opened_columns = (Opened_columns_list_p) malloc(sizeof(Opened_columns_list_t)); (dms->opened_columns)->nb_opened_columns = 0; @@ -486,7 +518,7 @@ int obi_close_dms(OBIDMS_p dms) while ((dms->opened_columns)->nb_opened_columns > 0) obi_close_column(*((dms->opened_columns)->columns)); - // Close dms and indexer directories + // Close dms, and view and indexer directories if (closedir(dms->directory) < 0) { obi_set_errno(OBIDMS_MEMORY_ERROR); @@ -501,6 +533,13 @@ int obi_close_dms(OBIDMS_p dms) free(dms); return -1; } + if (closedir(dms->view_directory) < 0) + { + obi_set_errno(OBIVIEW_ERROR); + obidebug(1, "\nError closing a view directory"); + free(dms); + return -1; + } free(dms); } diff --git a/src/obidms.h b/src/obidms.h index b44071b..494e851 100644 --- a/src/obidms.h +++ b/src/obidms.h @@ -30,6 +30,8 @@ */ #define INDEXER_DIR_NAME "OBIBLOB_INDEXERS" /**< The name of the Obiblob indexer directory. */ +#define VIEW_DIR_NAME "VIEWS" /**< The name of the view directory. + */ #define TAXONOMY_DIR_NAME "TAXONOMY" /**< The name of the taxonomy directory. */ #define MAX_NB_OPENED_COLUMNS (100) /**< The maximum number of columns open at the same time. @@ -98,6 +100,12 @@ typedef struct OBIDMS { int indexer_dir_fd; /**< The file descriptor of the directory entry * usable to refer and scan the indexer directory. */ + DIR* view_directory; /**< A directory entry usable to + * refer and scan the view directory. + */ + int view_dir_fd; /**< The file descriptor of the directory entry + * usable to refer and scan the view directory. + */ bool little_endian; /**< Endianness of the database. */ Opened_columns_list_p opened_columns; /**< List of opened columns. diff --git a/src/obidmscolumn.c b/src/obidmscolumn.c index bf6e54c..9f875df 100644 --- a/src/obidmscolumn.c +++ b/src/obidmscolumn.c @@ -940,8 +940,6 @@ OBIDMS_column_p obi_clone_column(OBIDMS_p dms, size_t line_size; index_t i, index; - obidebug(1, "\nline_selection == NULL = %d\n", (line_selection == NULL)); - column_to_clone = obi_open_column(dms, column_name, version_number); if (column_to_clone == NULL) { diff --git a/src/obidmscolumn_qual.c b/src/obidmscolumn_qual.c index a789f64..15b2039 100644 --- a/src/obidmscolumn_qual.c +++ b/src/obidmscolumn_qual.c @@ -33,16 +33,22 @@ int obi_column_set_obiqual_char_with_elt_idx(OBIDMS_column_p column, index_t lin int i; int ret_value; - int_value_length = strlen(value); - int_value = (uint8_t*) malloc(int_value_length * sizeof(uint8_t)); + // Check NA value + if (value == OBIQual_char_NA) + { + ret_value = obi_column_set_obiqual_int_with_elt_idx(column, line_nb, element_idx, OBIQual_int_NA, 0); + } + else + { + int_value_length = strlen(value); + int_value = (uint8_t*) malloc(int_value_length * sizeof(uint8_t)); - // Convert in uint8_t array to index in that format - for (i=0; iindexer, value, value_length); - if (idx == -1) // An error occurred + if (value == OBIQual_int_NA) { - if (obi_errno == OBI_READ_ONLY_INDEXER_ERROR) + idx = OBIIdx_NA; + } + else + { + // Add the value in the indexer + idx = obi_index_uint8(column->indexer, value, value_length); + if (idx == -1) // An error occurred { - // If the error is that the indexer is read-only, clone it - new_indexer_name = obi_build_indexer_name((column->header)->name, (column->header)->version); - if (new_indexer_name == NULL) - return -1; - column->indexer = obi_clone_indexer(column->indexer, new_indexer_name); // TODO Need to lock this somehow? - // Add the value in the new indexer - idx = obi_index_uint8(column->indexer, value, value_length); - if (idx == -1) + if (obi_errno == OBI_READ_ONLY_INDEXER_ERROR) + { + // TODO PUT IN A COLUMN FUNCTION + // If the error is that the indexer is read-only, clone it + new_indexer_name = obi_build_indexer_name((column->header)->name, (column->header)->version); + if (new_indexer_name == NULL) + return -1; + column->indexer = obi_clone_indexer(column->indexer, new_indexer_name); // TODO Need to lock this somehow? + strcpy((column->header)->indexer_name, new_indexer_name); + free(new_indexer_name); + obi_set_errno(0); + + // Add the value in the new indexer + idx = obi_index_uint8(column->indexer, value, value_length); + if (idx == -1) + return -1; + } + else return -1; } - else - return -1; } + // Add the value's index in the column *(((index_t*) (column->data)) + (line_nb * ((column->header)->nb_elements_per_line)) + element_idx) = idx; @@ -91,6 +110,10 @@ char* obi_column_get_obiqual_char_with_elt_idx(OBIDMS_column_p column, index_t l int_value = obi_column_get_obiqual_int_with_elt_idx(column, line_nb, element_idx, &int_value_length); + // Check NA + if (int_value == OBIQual_int_NA) + return OBIQual_char_NA; + value = (char*) malloc((int_value_length + 1) * sizeof(char)); // Encode int quality to char quality diff --git a/src/obidmscolumn_qual.h b/src/obidmscolumn_qual.h index 9057983..90178de 100644 --- a/src/obidmscolumn_qual.h +++ b/src/obidmscolumn_qual.h @@ -86,7 +86,7 @@ int obi_column_set_obiqual_int_with_elt_idx(OBIDMS_column_p column, index_t line * @param element_idx The index of the element that should be recovered in the line. * * @returns The recovered value, in the character string format. - * @retval OBIQual_str_NA the NA value of the type if an error occurred and obi_errno is set. + * @retval OBIQual_char_NA the NA value of the type if an error occurred and obi_errno is set. * * @since May 2016 * @author Celine Mercier (celine.mercier@metabarcoding.org) @@ -172,7 +172,7 @@ int obi_column_set_obiqual_int_with_elt_name(OBIDMS_column_p column, index_t lin * @param element_name The name of the element that should be recovered in the line. * * @returns The recovered value, in the character string format. - * @retval OBIQual_str_NA the NA value of the type if an error occurred and obi_errno is set. + * @retval OBIQual_char_NA the NA value of the type if an error occurred and obi_errno is set. * * @since May 2016 * @author Celine Mercier (celine.mercier@metabarcoding.org) diff --git a/src/obidmscolumn_seq.c b/src/obidmscolumn_seq.c index c7daadf..20069d8 100644 --- a/src/obidmscolumn_seq.c +++ b/src/obidmscolumn_seq.c @@ -32,25 +32,38 @@ int obi_column_set_obiseq_with_elt_idx(OBIDMS_column_p column, index_t line_nb, if (obi_column_prepare_to_set_value(column, line_nb) < 0) return -1; - // Add the value in the indexer - idx = obi_index_dna_seq(column->indexer, value); - if (idx == -1) // An error occurred + if (value == OBISeq_NA) { - if (obi_errno == OBI_READ_ONLY_INDEXER_ERROR) + idx = OBIIdx_NA; + } + else + { + // Add the value in the indexer + idx = obi_index_dna_seq(column->indexer, value); + if (idx == -1) // An error occurred { - // If the error is that the indexer is read-only, clone it - new_indexer_name = obi_build_indexer_name((column->header)->name, (column->header)->version); - if (new_indexer_name == NULL) - return -1; - column->indexer = obi_clone_indexer(column->indexer, new_indexer_name); // TODO Need to lock this somehow? - // Add the value in the new indexer - idx = obi_index_dna_seq(column->indexer, value); - if (idx == -1) + if (obi_errno == OBI_READ_ONLY_INDEXER_ERROR) + { + // TODO PUT IN A COLUMN FUNCTION + // If the error is that the indexer is read-only, clone it + new_indexer_name = obi_build_indexer_name((column->header)->name, (column->header)->version); + if (new_indexer_name == NULL) + return -1; + column->indexer = obi_clone_indexer(column->indexer, new_indexer_name); // TODO Need to lock this somehow? + strcpy((column->header)->indexer_name, new_indexer_name); + free(new_indexer_name); + obi_set_errno(0); + + // Add the value in the new indexer + idx = obi_index_dna_seq(column->indexer, value); + if (idx == -1) + return -1; + } + else return -1; } - else - return -1; } + // Add the value's index in the column *(((index_t*) (column->data)) + (line_nb * ((column->header)->nb_elements_per_line)) + element_idx) = idx; diff --git a/src/obidmscolumn_str.c b/src/obidmscolumn_str.c index 111ab8c..c092323 100644 --- a/src/obidmscolumn_str.c +++ b/src/obidmscolumn_str.c @@ -32,24 +32,36 @@ int obi_column_set_obistr_with_elt_idx(OBIDMS_column_p column, index_t line_nb, if (obi_column_prepare_to_set_value(column, line_nb) < 0) return -1; - // Add the value in the indexer - idx = obi_index_char_str(column->indexer, value); - if (idx == -1) // An error occurred + if (value == OBIStr_NA) { - if (obi_errno == OBI_READ_ONLY_INDEXER_ERROR) + idx = OBIIdx_NA; + } + else + { + // Add the value in the indexer + idx = obi_index_char_str(column->indexer, value); + if (idx == -1) // An error occurred { - // If the error is that the indexer is read-only, clone it - new_indexer_name = obi_build_indexer_name((column->header)->name, (column->header)->version); - if (new_indexer_name == NULL) - return -1; - column->indexer = obi_clone_indexer(column->indexer, new_indexer_name); // TODO Need to lock this somehow? - // Add the value in the new indexer - idx = obi_index_char_str(column->indexer, value); - if (idx == -1) + if (obi_errno == OBI_READ_ONLY_INDEXER_ERROR) + { + // TODO PUT IN A COLUMN FUNCTION + // If the error is that the indexer is read-only, clone it + new_indexer_name = obi_build_indexer_name((column->header)->name, (column->header)->version); + if (new_indexer_name == NULL) + return -1; + column->indexer = obi_clone_indexer(column->indexer, new_indexer_name); // TODO Need to lock this somehow? + strcpy((column->header)->indexer_name, new_indexer_name); + free(new_indexer_name); + obi_set_errno(0); + + // Add the value in the new indexer + idx = obi_index_char_str(column->indexer, value); + if (idx == -1) + return -1; + } + else return -1; } - else - return -1; } // Add the value's index in the column @@ -64,7 +76,7 @@ const char* obi_column_get_obistr_with_elt_idx(OBIDMS_column_p column, index_t l index_t idx; if (obi_column_prepare_to_get_value(column, line_nb) < 0) - return OBISeq_NA; + return OBIStr_NA; idx = *(((index_t*) (column->data)) + (line_nb * ((column->header)->nb_elements_per_line)) + element_idx); diff --git a/src/obitypes.h b/src/obitypes.h index b64dd46..a5399ea 100644 --- a/src/obitypes.h +++ b/src/obitypes.h @@ -22,10 +22,10 @@ #define OBIIdx_NA (INT64_MIN) /**< NA value for indices */ #define OBIFloat_NA (float_NA()) /**< NA value for the type OBI_FLOAT */ #define OBIChar_NA (0) /**< NA value for the type OBI_CHAR */ // TODO not sure about this one as it can be impossible to distinguish from uninitialized values -#define OBISeq_NA ("\0") /**< NA value for the type OBI_SEQ */ // TODO discuss -#define OBIStr_NA ("\0") /**< NA value for the type OBI_STR */ // TODO discuss -#define OBIQual_char_NA ("\0") /**< NA value for the type OBI_QUAL if the quality is in character string format */ // TODO test and discuss -#define OBIQual_int_NA (NULL) /**< NA value for the type OBI_QUAL if the quality is in integer format */ // TODO test and discuss +#define OBISeq_NA (NULL) /**< NA value for the type OBI_SEQ */ // TODO discuss +#define OBIStr_NA (NULL) /**< NA value for the type OBI_STR */ // TODO discuss +#define OBIQual_char_NA (NULL) /**< NA value for the type OBI_QUAL if the quality is in character string format */ +#define OBIQual_int_NA (NULL) /**< NA value for the type OBI_QUAL if the quality is in integer format */ /** diff --git a/src/obiview.c b/src/obiview.c index 7d14d83..da23357 100644 --- a/src/obiview.c +++ b/src/obiview.c @@ -44,39 +44,50 @@ /** - * Internal function building the file name where obiviews are stored. + * Internal function building the file name where the informations about an obiview are stored. * * @warning The returned pointer has to be freed by the caller. * * @returns A pointer to the file name. * @retval NULL if an error occurred. * - * @param dms_name The name of the OBIDMS. + * @param view_name The name of the view. * - * @since December 2015 + * @since June 2016 * @author Celine Mercier (celine.mercier@metabarcoding.org) */ -static char* build_obiview_file_name(); +static char* build_obiview_file_name(const char* view_name); // TODO delete after discussion -/** TODO public? - * Internal function creating the file containing basic informations on the OBIDMS. +/** + * @brief Internal function creating a file containing all the informations on a view. * - * This file contains: - * - The endianness of the platform + * The file is named with the name of the view. * - * @warning The returned pointer has to be freed by the caller. - * - * @param dms_file_descriptor The file descriptor for the OBIDMS directory. - * @param dms_name The name of the OBIDMS. + * @param dms The DMS to which the view belongs. + * @param view_name The name of the view. * * @retval 0 if the operation was successfully completed. * @retval -1 if an error occurred. * - * @since November 2015 + * @since June 2016 * @author Celine Mercier (celine.mercier@metabarcoding.org) */ -int create_obiview_file(int dms_file_descriptor); +int create_obiview_file(OBIDMS_p dms, const char* view_name); + + +/** + * @brief Internal function to update the column references of a view. + * + * The column references stored in the mapped view infos structures are updated + * to match the columns opened in the opened view structure. + * + * @param view A pointer on the view. + * + * @since June 2016 + * @author Celine Mercier (celine.mercier@metabarcoding.org) + */ +void update_column_refs(Obiview_p view); /** @@ -160,46 +171,31 @@ int prepare_to_get_value_from_column(Obiview_p view, index_t* line_nb_p); * ************************************************************************/ -static char* build_obiview_file_name() -{ - char* file_name; - - // Build file name - file_name = (char*) malloc((strlen(OBIVIEW_FILE_NAME) + 1)*sizeof(char)); - if (file_name == NULL) - { - obi_set_errno(OBI_MALLOC_ERROR); - obidebug(1, "\nError allocating memory for a view file name"); - return NULL; - } - if (sprintf(file_name, OBIVIEW_FILE_NAME) < 0) - { - obi_set_errno(OBIVIEW_ERROR); - obidebug(1, "\nProblem building an obiview file name"); - return NULL; - } - - return file_name; -} +// TODO +//static char* build_obiview_file_name(const char* view_name) +//{ +// char* file_name; +// +// // Build file name +// file_name = (char*) malloc((strlen(view_name) + 1)*sizeof(char)); +// if (file_name == NULL) +// { +// obi_set_errno(OBI_MALLOC_ERROR); +// obidebug(1, "\nError allocating memory for a view file name"); +// return NULL; +// } +// if (sprintf(file_name, view_name) < 0) +// { +// obi_set_errno(OBIVIEW_ERROR); +// obidebug(1, "\nProblem building an obiview file name"); +// return NULL; +// } +// +// return file_name; +//} -size_t get_platform_header_size() -{ - size_t header_size; - size_t rounded_header_size; - double multiple; - - header_size = sizeof(Obiviews_header_t); - - multiple = ceil((double) header_size / (double) getpagesize()); - - rounded_header_size = multiple * getpagesize(); - - return rounded_header_size; -} - - -size_t get_platform_views_size(int nb_of_views) +size_t get_platform_view_file_size() { size_t obiview_size; size_t rounded_obiview_size; @@ -207,7 +203,7 @@ size_t get_platform_views_size(int nb_of_views) obiview_size = sizeof(Obiview_infos_t); - multiple = ceil((double) (obiview_size*nb_of_views) / (double) getpagesize()); + multiple = ceil((double) (obiview_size) / (double) getpagesize()); rounded_obiview_size = multiple * getpagesize(); @@ -215,34 +211,32 @@ size_t get_platform_views_size(int nb_of_views) } -int create_obiview_file(int dms_file_descriptor) +int create_obiview_file(OBIDMS_p dms, const char* view_name) { - char* file_name; +// char* file_name; int obiview_file_descriptor; - size_t header_size; size_t file_size; - Obiviews_header_p header; - // Create file name - file_name = build_obiview_file_name(); - if (file_name == NULL) - return -1; + // TODO +// // Create file name +// file_name = build_obiview_file_name(view_name); +// if (file_name == NULL) +// return -1; // Create file - obiview_file_descriptor = openat(dms_file_descriptor, file_name, O_RDWR | O_CREAT | O_EXCL, 0777); + obiview_file_descriptor = openat(dms->view_dir_fd, view_name, O_RDWR | O_CREAT | O_EXCL, 0777); if (obiview_file_descriptor < 0) { obi_set_errno(OBIVIEW_ERROR); obidebug(1, "\nError creating an obiview file"); - free(file_name); +// free(file_name); TODO return -1; } - free(file_name); + //free(file_name); TODO // Truncate file to the right size - header_size = get_platform_header_size(); - file_size = header_size; + file_size = get_platform_view_file_size(); if (ftruncate(obiview_file_descriptor, file_size) < 0) { @@ -252,58 +246,41 @@ int create_obiview_file(int dms_file_descriptor) return -1; } - // Map the header - header = mmap(NULL, - header_size, - PROT_READ | PROT_WRITE, - MAP_SHARED, - obiview_file_descriptor, - 0 - ); - if (header == MAP_FAILED) - { - obi_set_errno(OBIVIEW_ERROR); - obidebug(1, "\nError mmapping an obiview file header"); - close(obiview_file_descriptor); - return -1; - } - - // Initialize the header - header->header_size = header_size; - header->views_size = 0; - header->view_count = 0; - - // Unmap the header - if (munmap(header, header_size) < 0) - { - obi_set_errno(OBIVIEW_ERROR); - obidebug(1, "\nError munmapping an obiview file header"); - close(obiview_file_descriptor); - return -1; - } - close(obiview_file_descriptor); return 0; } + +void update_column_refs(Obiview_p view) +{ + int i; + + for (i=0; i < (view->infos)->column_count; i++) + { + strcpy((((view->infos)->column_references)+i)->column_name, (((view->columns)[i])->header)->name); + (((view->infos)->column_references)+i)->version = (((view->columns)[i])->header)->version; + } +} + + int update_lines(Obiview_p view, index_t line_count) { int i; - for (i=0; i<(view->column_count); i++) + for (i=0; i<((view->infos)->column_count); i++) { while (line_count > (((view->columns)[i])->header)->line_count) { // Enlarge the column if (obi_enlarge_column((view->columns)[i]) < 0) return -1; - (((view->columns)[i])->header)->lines_used = line_count; // TODO Discuss, this means that columns are not truncated below the number of lines in the view. Maybe they should be to save place. + (((view->columns)[i])->header)->lines_used = line_count; } } - view->line_count = line_count; + (view->infos)->line_count = line_count; return 0; } @@ -329,7 +306,7 @@ OBIDMS_column_p clone_column_in_view(Obiview_p view, const char* column_name) else current_line_selection = view->line_selection; - for (i=0; i<(view->column_count); i++) + for (i=0; i<((view->infos)->column_count); i++) { if ((current_line_selection != NULL) || (!(strcmp((((view->columns)[i])->header)->name, column_name)))) { // Clone with the right line selection and replace (for all columns if there is a line selection) @@ -350,8 +327,9 @@ OBIDMS_column_p clone_column_in_view(Obiview_p view, const char* column_name) obi_close_column(column_buffer); if (!(strcmp((((view->columns)[i])->header)->name, column_name))) - // Found the column to return + { // Found the column to return column = (view->columns)[i]; + } } } @@ -360,6 +338,9 @@ OBIDMS_column_p clone_column_in_view(Obiview_p view, const char* column_name) { obi_close_column(view->line_selection); view->line_selection = NULL; + // Update line selection reference + (((view->infos)->line_selection).column_name)[0] = '\0'; + ((view->infos)->line_selection).version = -1; } if (view->new_line_selection != NULL) { @@ -367,12 +348,17 @@ OBIDMS_column_p clone_column_in_view(Obiview_p view, const char* column_name) view->new_line_selection = NULL; } + // Update column references in view infos + update_column_refs(view); + return column; } int prepare_to_set_value_in_column(Obiview_p view, OBIDMS_column_p* column_pp, index_t* line_nb_p) { + char* column_name; + // Check that the view is not read-only if (view->read_only) { @@ -389,15 +375,25 @@ int prepare_to_set_value_in_column(Obiview_p view, OBIDMS_column_p* column_pp, i if (view->line_selection != NULL) (*line_nb_p) = *(((index_t*) ((view->line_selection)->data)) + (*line_nb_p)); - (*column_pp) = clone_column_in_view(view, ((*column_pp)->header)->name); + column_name = (char*) malloc(strlen(((*column_pp)->header)->name) * sizeof(char)); + if (column_name == NULL) + { + obi_set_errno(OBI_MALLOC_ERROR); + obidebug(1, "\nError trying to allocate memory for a column name"); + return -1; + } + strcpy(column_name, ((*column_pp)->header)->name); + (*column_pp) = clone_column_in_view(view, column_name); if ((*column_pp) == NULL) { obidebug(1, "\nError trying to clone a column to modify it"); return -1; } + + free(column_name); } - if (((*line_nb_p)+1) > view->line_count) + if (((*line_nb_p)+1) > (view->infos)->line_count) { if (update_lines(view, ((*line_nb_p)+1)) < 0) return -1; @@ -409,7 +405,7 @@ int prepare_to_set_value_in_column(Obiview_p view, OBIDMS_column_p* column_pp, i int prepare_to_get_value_from_column(Obiview_p view, index_t* line_nb_p) { - if (((*line_nb_p)+1) > (view->line_count)) + if (((*line_nb_p)+1) > ((view->infos)->line_count)) { obi_set_errno(OBICOL_UNKNOWN_ERROR); obidebug(1, "\nError trying to get a value that is beyond the current line count of the view"); @@ -431,28 +427,25 @@ int prepare_to_get_value_from_column(Obiview_p view, index_t* line_nb_p) Obiview_p obi_new_view(OBIDMS_p dms, const char* view_name, Obiview_p view_to_clone, index_t* line_selection, const char* comments) { - Obiview_p view; - int i; - index_t line_nb; - Obiviews_infos_all_p views_infos; + Obiview_p view; + int i; + index_t line_nb; + struct dirent* dp; - // Check uniqueness of name TODO but problem if view not written yet has the same name. Save lists of open views in DMS ? - views_infos = obi_read_view_infos(dms); - if (views_infos != NULL) + // Check uniqueness of name + while ((dp = readdir(dms->view_directory)) != NULL) { - for (i=0; i<((views_infos->header)->view_count); i++) + if ((dp->d_name)[0] == '.') + continue; + if (strcmp(dp->d_name, view_name) == 0) // TODO change if view name building changes { - if (strcmp(((views_infos->view_infos)+i)->name, view_name) == 0) // TODO discuss what to do - { - obi_set_errno(OBIVIEW_ERROR); - obidebug(1, "\nView name already exists for a previous view"); - obi_close_view_infos(views_infos); - return NULL; - } + obi_set_errno(OBIVIEW_ERROR); + obidebug(1, "\nName of new view already exists"); + return NULL; } - obi_close_view_infos(views_infos); } + // Allocate memory for view structure view = (Obiview_p) malloc(sizeof(Obiview_t)); if (view == NULL) { @@ -461,6 +454,24 @@ Obiview_p obi_new_view(OBIDMS_p dms, const char* view_name, Obiview_p view_to_cl return NULL; } + view->dms = dms; + + // Create view file + if (create_obiview_file(dms, view_name) < 0) + { + free(view); + return NULL; + } + + // Map view file + view->infos = obi_view_map_file(dms, view_name); + if (view->infos == NULL) + { + obidebug(1, "\nError mapping the informations of a new view"); + free(view); + return NULL; + } + // Clone view to clone if there is one if (view_to_clone != NULL) { @@ -468,19 +479,22 @@ Obiview_p obi_new_view(OBIDMS_p dms, const char* view_name, Obiview_p view_to_cl { obi_set_errno(OBIVIEW_ERROR); obidebug(1, "\nA view can not be cloned if it is not read-only"); + obi_view_unmap_file(view->dms, view->infos); free(view); return NULL; } - view->dms = dms; - // If the view to clone has an associated line selection and there is no new line selection, open the associated line selection if ((view_to_clone->line_selection != NULL) && (line_selection == NULL)) { view->line_selection = obi_open_column(dms, ((view_to_clone->line_selection)->header)->name, ((view_to_clone->line_selection)->header)->version); if (view->line_selection == NULL) + { + obi_view_unmap_file(view->dms, view->infos); + free(view); return NULL; - view->line_count = view_to_clone->line_count; + } + (view->infos)->line_count = (view_to_clone->infos)->line_count; } // If there is a new line selection, build it by combining it with the one from the view to clone if there is one else if (line_selection != NULL) @@ -489,19 +503,23 @@ Obiview_p obi_new_view(OBIDMS_p dms, const char* view_name, Obiview_p view_to_cl if ((view->line_selection) == NULL) { obidebug(1, "\nError creating a column corresponding to a line selection"); + obi_view_unmap_file(view->dms, view->infos); + free(view); return NULL; } - view->line_count = 0; + (view->infos)->all_lines = false; + (view->infos)->line_count = 0; i = 0; for (i=0; line_selection[i] != -1; i++) { line_nb = line_selection[i]; - if (line_nb > view_to_clone->line_count) + if (line_nb > (view_to_clone->infos)->line_count) { obi_set_errno(OBIVIEW_ERROR); obidebug(1, "\nError trying to select a line for a new view that is beyond the line count of the view to clone"); obi_close_column(view->line_selection); + obi_view_unmap_file(view->dms, view->infos); free(view); return NULL; } @@ -512,54 +530,73 @@ Obiview_p obi_new_view(OBIDMS_p dms, const char* view_name, Obiview_p view_to_cl if (obi_column_set_index(view->line_selection, ((view->line_selection)->header)->lines_used, line_nb) < 0) { obi_close_column(view->line_selection); + obi_view_unmap_file(view->dms, view->infos); free(view); return NULL; } // Update view line count - (view->line_count)++; + ((view->infos)->line_count)++; } } else // If there is no line selection associated with the view to clone or the new view { view->line_selection = NULL; - view->line_count = view_to_clone->line_count; + (view->infos)->all_lines = true; + (view->infos)->line_count = (view_to_clone->infos)->line_count; } - for (i=0; i<(view_to_clone->column_count); i++) + for (i=0; i<((view_to_clone->infos)->column_count); i++) { (view->columns)[i] = obi_open_column(dms, (((view_to_clone->columns)[i])->header)->name, (((view_to_clone->columns)[i])->header)->version); if ((view->columns)[i] == NULL) { if (view->line_selection != NULL) obi_close_column(view->line_selection); + obi_view_unmap_file(view->dms, view->infos); free(view); return NULL; } } - view->column_count = view_to_clone->column_count; - strcpy(view->view_type, view_to_clone->view_type); - strcpy(view->created_from, view_to_clone->name); + (view->infos)->column_count = (view_to_clone->infos)->column_count; + strcpy((view->infos)->view_type, (view_to_clone->infos)->view_type); + strcpy((view->infos)->created_from, (view_to_clone->infos)->name); view->new_line_selection = NULL; } // Else, fill empty view structure else { - view->dms = dms; - view->column_count = 0; - view->line_count = 0; - view->line_selection = NULL; - view->new_line_selection = NULL; - (view->created_from)[0] = '\0'; - (view->view_type)[0] = '\0'; + (view->infos)->column_count = 0; + (view->infos)->line_count = 0; + (view->infos)->all_lines = true; + view->line_selection = NULL; + view->new_line_selection = NULL; + ((view->infos)->created_from)[0] = '\0'; + ((view->infos)->view_type)[0] = '\0'; //view->columns = NULL; // TODO } - strcpy(view->name, view_name); - strcpy(view->comments, comments); + strcpy((view->infos)->name, view_name); + strcpy((view->infos)->comments, comments); + (view->infos)->creation_date = time(NULL); view->read_only = 0; + // Store reference for line selection + if (view->line_selection == NULL) + { + (((view->infos)->line_selection).column_name)[0] = '\0'; + ((view->infos)->line_selection).version = -1; + } + else + { + strcpy(((view->infos)->line_selection).column_name, ((view->line_selection)->header)->name); + ((view->infos)->line_selection).version = ((view->line_selection)->header)->version; + } + + // Store references for columns + update_column_refs(view); + return view; } @@ -586,7 +623,7 @@ Obiview_p obi_new_view_nuc_seqs(OBIDMS_p dms, const char* view_name, Obiview_p v if (view_to_clone != NULL) { // Check that the view to clone is already a NUC_SEQS view (TODO discuss possibility of transforming type of a view) - if (strcmp(view_to_clone->view_type, VIEW_TYPE_NUC_SEQS)) + if (strcmp((view_to_clone->infos)->view_type, VIEW_TYPE_NUC_SEQS)) { obi_set_errno(OBIVIEW_ERROR); obidebug(1, "Trying to clone a non-NUC SEQS view to create a NUC SEQS view"); @@ -595,10 +632,10 @@ Obiview_p obi_new_view_nuc_seqs(OBIDMS_p dms, const char* view_name, Obiview_p v } view = obi_new_view(dms, view_name, view_to_clone, line_selection, comments); - if (view== NULL) + if (view == NULL) return NULL; - strcpy(view->view_type, VIEW_TYPE_NUC_SEQS); + strcpy((view->infos)->view_type, VIEW_TYPE_NUC_SEQS); if (view_to_clone == NULL) { @@ -648,160 +685,140 @@ Obiview_p obi_new_view_nuc_seqs_cloned_from_name(OBIDMS_p dms, const char* view_ } -Obiview_p obi_open_view(OBIDMS_p dms, const char* view_name) +Obiview_infos_p obi_view_map_file(OBIDMS_p dms, const char* view_name) { - Obiview_p view; - char* view_file_name; +// char* file_name; + Obiview_infos_p view_infos; int obiview_file_descriptor; - size_t header_size; - Obiviews_header_p header; - Obiview_infos_p views; - Obiview_infos_p view_infos; - OBIDMS_column_p column; - int i; - int view_number; + size_t file_size; - view_file_name = build_obiview_file_name(); - if (view_file_name == NULL) - return NULL; + // TODO +// // Create file name +// file_name = build_obiview_file_name(view_name); +// if (file_name == NULL) +// return -1; - // Open view file, read header size and map header and views - obiview_file_descriptor = openat(dms->dir_fd, view_file_name, O_RDWR, 0777); + // Open view file + obiview_file_descriptor = openat(dms->view_dir_fd, view_name, O_RDWR, 0777); if (obiview_file_descriptor < 0) { obi_set_errno(OBIVIEW_ERROR); obidebug(1, "\nError opening an obiview file"); - free(view_file_name); +// free(file_name); TODO return NULL; } - free(view_file_name); + //free(file_name); TODO - // Read the header size - if (read(obiview_file_descriptor, &header_size, sizeof(size_t)) < ((ssize_t) sizeof(size_t))) + // Map the view infos structure + file_size = get_platform_view_file_size(); + view_infos = mmap(NULL, + file_size, + PROT_READ | PROT_WRITE, + MAP_SHARED, + obiview_file_descriptor, + 0 + ); + if (view_infos == NULL) { obi_set_errno(OBIVIEW_ERROR); - obidebug(1, "\nError reading the header size of an obiview file (trying to open a view when there are none?)"); - close(obiview_file_descriptor); + obidebug(1, "\nError mapping an obiview file"); return NULL; } - // Map the header - header = mmap(NULL, - header_size, - PROT_READ | PROT_WRITE, - MAP_SHARED, - obiview_file_descriptor, - 0 - ); - if (header == MAP_FAILED) - { - obi_set_errno(OBIVIEW_ERROR); - obidebug(1, "\nError mmapping an obiview file header"); - close(obiview_file_descriptor); - return NULL; - } + close(obiview_file_descriptor); - // Map the views - views = mmap(NULL, - header->views_size, - PROT_READ | PROT_WRITE, - MAP_SHARED, - obiview_file_descriptor, - header_size - ); - if (views == MAP_FAILED) - { - obi_set_errno(OBIVIEW_ERROR); - obidebug(1, "\nError mmapping the views from an obiview file"); - munmap(header, header_size); - close(obiview_file_descriptor); - return NULL; - } + return view_infos; +} - // Find and open the view that should be read with the line selection associated - view_number = -1; - if (view_name == NULL) // If view name is NULL, open the latest view TODO discuss - view_number = (header->view_count) - 1; - else - { - for (i=0; i<(header->view_count); i++) + +int obi_view_unmap_file(OBIDMS_p dms, Obiview_infos_p view_infos) +{ + // char* file_name; + int obiview_file_descriptor; + size_t file_size; + + // TODO + // // Get file name + // file_name = build_obiview_file_name(view_name); + // if (file_name == NULL) + // return -1; + + // Open view file + obiview_file_descriptor = openat(dms->view_dir_fd, view_infos->name, O_RDWR, 0777); + if (obiview_file_descriptor < 0) { - if (!strcmp((views+i)->name, view_name)) - { // Found the view to open - view_number = i; - } + obi_set_errno(OBIVIEW_ERROR); + obidebug(1, "\nError opening an obiview file"); + // free(file_name); TODO + return -1; + } + + //free(file_name); TODO + + // Unmap the view infos structure + file_size = get_platform_view_file_size(); + if (munmap(view_infos, file_size) < 0) + { + obi_set_errno(OBIVIEW_ERROR); + obidebug(1, "\nError unmapping an obiview file"); + close(obiview_file_descriptor); + return -1; } - } - if (view_number == -1) - { - obi_set_errno(OBIVIEW_ERROR); - obidebug(1, "\nError: the view '%s' to open was not found", view_name); - munmap(views, header->views_size); - munmap(header, header_size); close(obiview_file_descriptor); - return NULL; - } - view_infos = views + view_number; + return 0; +} + +Obiview_p obi_open_view(OBIDMS_p dms, const char* view_name) +{ + Obiview_p view; + int i; + + // Alllocate the memory for the view structure view = (Obiview_p) malloc(sizeof(Obiview_t)); if (view == NULL) { - obi_set_errno(OBIVIEW_ERROR); + obi_set_errno(OBI_MALLOC_ERROR); obidebug(1, "\nError allocating memory for a view"); - munmap(views, header->views_size); - munmap(header, header_size); - close(obiview_file_descriptor); return NULL; } - if (view_infos->all_lines) + // Map view file + view->infos = obi_view_map_file(dms, view_name); + + // Open the line selection associated with the view + if ((view->infos)->all_lines) view->line_selection = NULL; else { - view->line_selection = obi_open_column(dms, (view_infos->line_selection).column_name, (view_infos->line_selection).version); + view->line_selection = obi_open_column(dms, ((view->infos)->line_selection).column_name, ((view->infos)->line_selection).version); if (view->line_selection == NULL) { - munmap(views, header->views_size); - munmap(header, header_size); - close(obiview_file_descriptor); + obidebug(1, "\nError opening a line selection for a view"); + obi_view_unmap_file(view->dms, view->infos); + free(view); + return NULL; + } + } + + // Open the columns to read + for (i=0; i < ((view->infos)->column_count); i++) + { + (view->columns)[i] = obi_open_column(dms, (((view->infos)->column_references)+i)->column_name, (((view->infos)->column_references)+i)->version); + if ((view->columns)[i] == NULL) + { + obidebug(1, "\nError opening a column for a view: column %d: %s, version %d", i, (((view->infos)->column_references)+i)->column_name, (((view->infos)->column_references)+i)->version); + obi_close_view(view); return NULL; } } view->dms = dms; view->new_line_selection = NULL; - view->read_only = 1; - view->column_count = 0; - view->line_count = view_infos->line_count; - strcpy(view->created_from, view_infos->created_from); - strcpy(view->name, view_infos->name); - strcpy(view->view_type, view_infos->view_type); - strcpy(view->comments, view_infos->comments); - - // Open the columns to read - for (i=0; i<(view_infos->column_count); i++) - { - column = obi_open_column(dms, ((view_infos->column_references)+i)->column_name, ((view_infos->column_references)+i)->version); - if (column == NULL) - { - obidebug(1, "\nError opening a column for a view: column %d: %s, version %d", i, ((view_infos->column_references)+i)->column_name, ((view_infos->column_references)+i)->version); - munmap(views, header->views_size); - munmap(header, header_size); - close(obiview_file_descriptor); - return NULL; - } - // Store column in the view - (view->columns)[view->column_count] = column; - view->column_count++; - } - - // Munmap and close things - munmap(views, header->views_size); - munmap(header, header_size); - close(obiview_file_descriptor); + view->read_only = true; return view; } @@ -839,7 +856,7 @@ int obi_view_add_column(Obiview_p view, if (current_line_selection != NULL) { - for (i=0; i<(view->column_count); i++) + for (i=0; i<((view->infos)->column_count); i++) { { // Clone with the right line selection and replace for all columns // Save pointer to close column after cloning @@ -865,6 +882,9 @@ int obi_view_add_column(Obiview_p view, { obi_close_column(view->line_selection); view->line_selection = NULL; + // Update line selection reference + (((view->infos)->line_selection).column_name)[0] = '\0'; + ((view->infos)->line_selection).version = -1; } if (view->new_line_selection != NULL) { @@ -873,9 +893,9 @@ int obi_view_add_column(Obiview_p view, } // Update the line count - if (view->line_count > nb_lines) - nb_lines = view->line_count; - else if (nb_lines > view->line_count) + if ((view->infos)->line_count > nb_lines) + nb_lines = (view->infos)->line_count; + else if (nb_lines > (view->infos)->line_count) update_lines(view, nb_lines); // Open or create the column @@ -895,10 +915,13 @@ int obi_view_add_column(Obiview_p view, } // Store column in the view - (view->columns)[view->column_count] = column; - view->column_count++; - if (view->column_count == 1) // first column in the view - view->line_count = (column->header)->lines_used; + (view->columns)[(view->infos)->column_count] = column; + (view->infos)->column_count++; + if ((view->infos)->column_count == 1) // first column in the view + (view->infos)->line_count = (column->header)->lines_used; + + // Update reference in view infos + update_column_refs(view); return 0; } @@ -921,7 +944,7 @@ int obi_view_delete_column(Obiview_p view, const char* column_name) found = 0; - for (i=0; i<(view->column_count); i++) + for (i=0; i<((view->infos)->column_count); i++) { if (!strcmp((((view->columns)[i])->header)->name, column_name)) { @@ -930,7 +953,7 @@ int obi_view_delete_column(Obiview_p view, const char* column_name) } if (found) { - if (i != ((view->column_count) - 1)) // not the last one + if (i != (((view->infos)->column_count) - 1)) // not the last one (view->columns)[i] = (view->columns)[i+1]; else // Last column (view->columns)[i] = NULL; @@ -940,7 +963,10 @@ int obi_view_delete_column(Obiview_p view, const char* column_name) if (!found) return -1; - (view->column_count)--; + ((view->infos)->column_count)--; + + // Update reference in view infos + update_column_refs(view); return 0; } @@ -950,7 +976,7 @@ OBIDMS_column_p obi_view_get_column(Obiview_p view, const char* column_name) { int i; - for (i=0; i<(view->column_count); i++) + for (i=0; i<((view->infos)->column_count); i++) { if (!(strcmp((((view->columns)[i])->header)->name, column_name))) return (view->columns)[i]; @@ -963,7 +989,7 @@ OBIDMS_column_p* obi_view_get_pointer_on_column_in_view(Obiview_p view, const ch { int i; - for (i=0; i<(view->column_count); i++) + for (i=0; i<((view->infos)->column_count); i++) { if (!(strcmp((((view->columns)[i])->header)->name, column_name))) return ((view->columns)+i); @@ -1046,20 +1072,6 @@ int obi_select_lines(Obiview_p view, index_t* line_nbs) int obi_save_view(Obiview_p view) { - int i; - struct stat buffer; - char* view_file_name; - char* full_path; - int check_file; - int obiview_file_descriptor; - size_t header_size; - size_t views_size; - size_t file_size; - Obiviews_header_p header; - Obiview_infos_p views; - Obiview_infos_p view_infos; - OBIDMS_column_p current_line_selection; - // Check that the view is not read-only if (view->read_only) { @@ -1068,142 +1080,28 @@ int obi_save_view(Obiview_p view) return -1; } - view_file_name = build_obiview_file_name(); - if (view_file_name == NULL) - return -1; - - // Get the full path for the column directory - full_path = obi_dms_get_full_path(view->dms, view_file_name); - if (full_path == NULL) - { - obi_set_errno(OBIVIEW_ERROR); - obidebug(1, "\nError getting the full path of an obiview file"); - free(view_file_name); - return -1; - } - - check_file = stat(full_path, &buffer); - if (check_file < 0) - { // 1st view: create view file - if (create_obiview_file((view->dms)->dir_fd) < 0) - return -1; - } - - // Open view file, read header size and map header and views - obiview_file_descriptor = openat((view->dms)->dir_fd, view_file_name, O_RDWR, 0777); - if (obiview_file_descriptor < 0) - { - obi_set_errno(OBIVIEW_ERROR); - obidebug(1, "\nError opening an obiview file"); - free(view_file_name); - return -1; - } - - free(view_file_name); - - // Read the header size - if (read(obiview_file_descriptor, &header_size, sizeof(size_t)) < ((ssize_t) sizeof(size_t))) - { - obi_set_errno(OBIVIEW_ERROR); - obidebug(1, "\nError reading the header size of an obiview file"); - close(obiview_file_descriptor); - return -1; - } - - // Map the header - header = mmap(NULL, - header_size, - PROT_READ | PROT_WRITE, - MAP_SHARED, - obiview_file_descriptor, - 0 - ); - if (header == MAP_FAILED) - { - obi_set_errno(OBIVIEW_ERROR); - obidebug(1, "\nError mmapping an obiview file header"); - close(obiview_file_descriptor); - return -1; - } - - // Truncate file to the right size to add a new view // TODO lock for multithreading - views_size = get_platform_views_size((header->view_count)+1); - file_size = header_size + views_size; - - if (ftruncate(obiview_file_descriptor, file_size) < 0) - { - obi_set_errno(OBIVIEW_ERROR); - obidebug(1, "\nError truncating an obiview file to the right size"); - munmap(header, header_size); - close(obiview_file_descriptor); - return -1; - } - - header->views_size = views_size; - - // Map the views - views = mmap(NULL, - header->views_size, - PROT_READ | PROT_WRITE, - MAP_SHARED, - obiview_file_descriptor, - header_size - ); - if (views == MAP_FAILED) - { - obi_set_errno(OBIVIEW_ERROR); - obidebug(1, "\nError mmapping the views from an obiview file"); - munmap(header, header_size); - close(obiview_file_descriptor); - return -1; - } - - // Write view infos - view_infos = views + (header->view_count); - view_infos->view_number = (header->view_count); - view_infos->column_count = view->column_count; - view_infos->creation_date = time(NULL); - strcpy(view_infos->created_from, view->created_from); - strcpy(view_infos->name, view->name); - strcpy(view_infos->view_type, view->view_type); - strcpy(view_infos->comments, view->comments); - - // Store reference for the line selection associated with that view + // Store reference for the line selection associated with that view if there is one if (view->new_line_selection != NULL) { - view_infos->line_count = ((view->new_line_selection)->header)->lines_used; - current_line_selection = view->new_line_selection; + (view->infos)->line_count = ((view->new_line_selection)->header)->lines_used; + strcpy(((view->infos)->line_selection).column_name, ((view->new_line_selection)->header)->name); + ((view->infos)->line_selection).version = ((view->new_line_selection)->header)->version; + (view->infos)->all_lines = false; } - else + else if (view->line_selection != NULL) // Unnecessary in theory { - view_infos->line_count = view->line_count; - current_line_selection = view->line_selection; + strcpy(((view->infos)->line_selection).column_name, ((view->line_selection)->header)->name); + ((view->infos)->line_selection).version = ((view->line_selection)->header)->version; + (view->infos)->all_lines = false; } - if (current_line_selection != NULL) + else // Necessary because line selection could have been deleted if a column was cloned { - view_infos->all_lines = 0; - strcpy((view_infos->line_selection).column_name, (current_line_selection->header)->name); - (view_infos->line_selection).version = (current_line_selection->header)->version; - } - else - { - view_infos->all_lines = 1; - ((view_infos->line_selection).column_name)[0] = '\0'; - (view_infos->line_selection).version = -1; - } - for (i=0; icolumn_count; i++) - { - strcpy(((view_infos->column_references)+i)->column_name, (((view->columns)[i])->header)->name); - ((view_infos->column_references)+i)->version = (((view->columns)[i])->header)->version; + (((view->infos)->line_selection).column_name)[0] = '\0'; + ((view->infos)->line_selection).version = -1; + (view->infos)->all_lines = true; } - // Increment view count - (header->view_count)++; - - // Unmap and close file - munmap(views, header->views_size); - munmap(header, header_size); - close(obiview_file_descriptor); + update_column_refs(view); return 0; } @@ -1212,15 +1110,48 @@ int obi_save_view(Obiview_p view) int obi_close_view(Obiview_p view) { int i; + int ret_value; - for (i=0; i < (view->column_count); i++) + ret_value = 0; + + for (i=0; i < ((view->infos)->column_count); i++) { - obi_close_column((view->columns)[i]); + if (obi_close_column((view->columns)[i]) < 0) + { + obidebug(1, "\nError closing a column while closing a view"); + ret_value = -1; + } + } + + // Close line selections if they exist + if (view->line_selection != NULL) + { + if (obi_close_column(view->line_selection) < 0) + { + obidebug(1, "\nError closing a line selection while closing a view"); + ret_value = -1; + } + } + + if (view->new_line_selection != NULL) + { + if (obi_close_column(view->new_line_selection) < 0) + { + obidebug(1, "\nError closing a new line selection while closing a view"); + ret_value = -1; + } + } + + // Unmap view file + if (obi_view_unmap_file(view->dms, view->infos) < 0) + { + obidebug(1, "\nError unmaping a view file while closing a view"); + ret_value = -1; } free(view); - return 0; + return ret_value; } @@ -1237,113 +1168,6 @@ int obi_save_and_close_view(Obiview_p view) } -Obiviews_infos_all_p obi_read_view_infos(OBIDMS_p dms) -{ - char* view_file_name; - int obiview_file_descriptor; - size_t header_size; - Obiviews_header_p header; - Obiview_infos_p view_infos; - Obiviews_infos_all_p views; - - view_file_name = build_obiview_file_name(); - if (view_file_name == NULL) - return NULL; - - // Open view file, read header size and map header and views - obiview_file_descriptor = openat(dms->dir_fd, view_file_name, O_RDWR, 0777); - if (obiview_file_descriptor < 0) - { // No views yet - free(view_file_name); - return NULL; - } - - free(view_file_name); - - // Read the header size - if (read(obiview_file_descriptor, &header_size, sizeof(size_t)) < ((ssize_t) sizeof(size_t))) - { - obi_set_errno(OBIVIEW_ERROR); - obidebug(1, "\nError reading the header size of an obiview file (trying to open a view when there are none?)"); - close(obiview_file_descriptor); - return NULL; - } - - // Map the header - header = mmap(NULL, - header_size, - PROT_READ | PROT_WRITE, - MAP_SHARED, - obiview_file_descriptor, - 0 - ); - if (header == MAP_FAILED) - { - obi_set_errno(OBIVIEW_ERROR); - obidebug(1, "\nError mmapping an obiview file header"); - close(obiview_file_descriptor); - return NULL; - } - - // Map the views - view_infos = mmap(NULL, - header->views_size, - PROT_READ | PROT_WRITE, - MAP_SHARED, - obiview_file_descriptor, - header_size - ); - if (view_infos == MAP_FAILED) - { - obi_set_errno(OBIVIEW_ERROR); - obidebug(1, "\nError mmapping the views from an obiview file"); - munmap(header, header_size); - close(obiview_file_descriptor); - return NULL; - } - - views = (Obiviews_infos_all_p) malloc(sizeof(Obiviews_infos_all_t)); - if (views == NULL) - { - obi_set_errno(OBIVIEW_ERROR); - obidebug(1, "\nError mmapping the views from an obiview file"); - munmap(view_infos, header->views_size); - munmap(header, header_size); - close(obiview_file_descriptor); - return NULL; - } - - views->header = header; - views->view_infos = view_infos; - - close(obiview_file_descriptor); - - return views; -} - - -int obi_close_view_infos(Obiviews_infos_all_p views) -{ - if (munmap(views->view_infos, (views->header)->views_size) < 0) - { - obi_set_errno(OBIVIEW_ERROR); - obidebug(1, "\nError unmapping the views of an obiview file"); - free(views); - return -1; - } - if (munmap(views->header, (views->header)->header_size) < 0) - { - obi_set_errno(OBIVIEW_ERROR); - obidebug(1, "\nError unmapping the header of an obiview file"); - free(views); - return -1; - - } - free(views); - return 0; -} - - /*********** FOR BOOL COLUMNS ***********/ int obi_column_set_obibool_with_elt_idx_in_view(Obiview_p view, OBIDMS_column_p column, index_t line_nb, index_t element_idx, obibool_t value) diff --git a/src/obiview.h b/src/obiview.h index cdaae51..1f018e3 100644 --- a/src/obiview.h +++ b/src/obiview.h @@ -34,8 +34,6 @@ */ #define VIEW_TYPE_MAX_LENGTH (1024) /**< The maximum length of the type name of a view. */ -#define OBIVIEW_FILE_NAME "obiviews" /**< The default name of a view file. - */ #define LINES_COLUMN_NAME "LINES" /**< The name of the column containing the line selections * in all views. */ @@ -56,45 +54,6 @@ */ -/** - * @brief Structure for an opened view. - */ -typedef struct Obiview { - - OBIDMS_p dms; /**< A pointer on the DMS to which the view belongs. - */ - char name[OBIVIEW_NAME_MAX_LENGTH+1]; /**< Name of the view. - */ - char created_from[OBIVIEW_NAME_MAX_LENGTH+1]; /**< Name of the view from which that view was cloned if the view was cloned. - */ - char view_type[VIEW_TYPE_MAX_LENGTH+1]; /**< Type of the view if there is one. - * Types existing: NUC_SEQS_VIEW. - */ - bool read_only; /**< Whether the view is read-only or can be modified. - */ - OBIDMS_column_p line_selection; /**< A pointer on the column containing the line selection - * associated with the view if there is one. - * This line selection is read-only, and when a line from the view is read, - * it is this line selection that is used. - */ - OBIDMS_column_p new_line_selection; /**< A pointer on the column containing the new line selection being built - * to associate with the view, if there is one. - * When a line is selected with obi_select_line() or obi_select_lines(), - * it is recorded in this line selection. - */ - index_t line_count; /**< The number of lines in the view. Refers to the number of lines in each - * column of the view if line_selection is NULL, or to the line count of - * line_selection if it is not NULL. - */ - int column_count; /**< The number of columns in the view. - */ - OBIDMS_column_p columns[MAX_NB_OPENED_COLUMNS]; /**< Array of pointers on all the columns of the view. - */ - char comments[OBIVIEW_COMMENTS_MAX_LENGTH+1]; /**< Comments, additional informations on the view. - */ -} Obiview_t, *Obiview_p; - - /** * @brief Structure referencing a column by its name and its version. */ @@ -112,8 +71,6 @@ typedef struct Column_reference { * Once a view has been written in the view file, it can not be modified and can only be read. */ typedef struct Obiview_infos { - int view_number; /**< Number of the view in the view file. - */ time_t creation_date; /**< Time at which the view was written in the view file. */ char name[OBIVIEW_NAME_MAX_LENGTH+1]; /**< Name of the view, used to identify it. @@ -138,7 +95,29 @@ typedef struct Obiview_infos { } Obiview_infos_t, *Obiview_infos_p; -// TODO : Combine the common elements of the Obiview_infos and Obiview structures in one structure used by both? +/** + * @brief Structure for an opened view. + */ +typedef struct Obiview { + Obiview_infos_p infos; /**< A pointer on the mapped view informations. + */ + OBIDMS_p dms; /**< A pointer on the DMS to which the view belongs. + */ + bool read_only; /**< Whether the view is read-only or can be modified. + */ + OBIDMS_column_p line_selection; /**< A pointer on the column containing the line selection + * associated with the view if there is one. + * This line selection is read-only, and when a line from the view is read, + * it is this line selection that is used. + */ + OBIDMS_column_p new_line_selection; /**< A pointer on the column containing the new line selection being built + * to associate with the view, if there is one. + * When a line is selected with obi_select_line() or obi_select_lines(), + * it is recorded in this line selection. + */ + OBIDMS_column_p columns[MAX_NB_OPENED_COLUMNS]; /**< Array of pointers on all the columns of the view. + */ +} Obiview_t, *Obiview_p; /** @@ -269,6 +248,37 @@ Obiview_p obi_new_view_nuc_seqs(OBIDMS_p dms, const char* view_name, Obiview_p v Obiview_p obi_new_view_nuc_seqs_cloned_from_name(OBIDMS_p dms, const char* view_name, const char* view_to_clone_name, index_t* line_selection, const char* comments); +/** + * @brief Maps a view file and returns the mapped structure stored in it. + * + * @param dms A pointer on the OBIDMS. + * @param view_name The unique name identifying the view. + * + * @returns A pointer on the mapped view infos structure. + * @retval NULL if an error occurred. + * + * @since June 2016 + * @author Celine Mercier (celine.mercier@metabarcoding.org) + */ +Obiview_infos_p obi_view_map_file(OBIDMS_p dms, const char* view_name); + + +/** + * @brief Unmaps a view file. + * + * @param dms A pointer on the OBIDMS. + * @param view_infos A pointer on the mapped view infos structure. + * + * @returns A value indicating the success of the operation. + * @retval 0 if the operation was successfully completed. + * @retval -1 if an error occurred. + * + * @since June 2016 + * @author Celine Mercier (celine.mercier@metabarcoding.org) + */ +int obi_view_unmap_file(OBIDMS_p dms, Obiview_infos_p view_infos); + + /** * @brief Opens a view identified by its name stored in the view file. * @@ -873,7 +883,7 @@ int obi_column_set_obiqual_int_with_elt_idx_in_view(Obiview_p view, OBIDMS_colum * @param element_idx The index of the element that should be recovered in the line. * * @returns The recovered value, in the character string format. - * @retval OBIQual_str_NA the NA value of the type if an error occurred and obi_errno is set. + * @retval OBIQual_char_NA the NA value of the type if an error occurred and obi_errno is set. * * @since May 2016 * @author Celine Mercier (celine.mercier@metabarcoding.org) @@ -967,7 +977,7 @@ int obi_column_set_obiqual_int_with_elt_name_in_view(Obiview_p view, OBIDMS_colu * @param element_name The name of the element that should be recovered in the line. * * @returns The recovered value, in the character string format. - * @retval OBIQual_str_NA the NA value of the type if an error occurred and obi_errno is set. + * @retval OBIQual_char_NA the NA value of the type if an error occurred and obi_errno is set. * * @since May 2016 * @author Celine Mercier (celine.mercier@metabarcoding.org)