sc_result sc_storage_set_link_content(sc_addr addr, const sc_stream *stream) { sc_element *el = sc_storage_get_element(addr, SC_TRUE); sc_check_sum check_sum; sc_result result = SC_RESULT_ERROR; g_assert(stream != nullptr); if (el == nullptr) return SC_RESULT_ERROR_INVALID_PARAMS; if (!(el->type & sc_type_link)) return SC_RESULT_ERROR_INVALID_TYPE; // calculate checksum for data if (sc_link_calculate_checksum(stream, &check_sum) == SC_TRUE) { result = sc_fs_storage_write_content(addr, &check_sum, stream); memcpy(el->content.data, check_sum.data, check_sum.len); el->content.len = check_sum.len; g_assert(check_sum.len > 0); sc_event_emit(addr, SC_EVENT_CHANGE_LINK_CONTENT, addr); result = SC_RESULT_OK; } g_assert(result == SC_RESULT_OK); return result; }
sc_element* get_random_element(sc_type type) { sc_addr id; id.seg = g_random_int() % sc_storage_get_segments_count(); id.offset = g_random_int() % SEGMENT_SIZE; return sc_storage_get_element(id, SC_FALSE); }
sc_bool sc_storage_is_element(sc_addr addr) { sc_element *el = sc_storage_get_element(addr, SC_TRUE); if (el == 0) return SC_FALSE; if (el->type == 0) return SC_FALSE; if (el->delete_time_stamp > 0) return SC_FALSE; return SC_TRUE; }
sc_result sc_storage_get_element_type(sc_addr addr, sc_type *result) { sc_element *el = sc_storage_get_element(addr, SC_TRUE); if (el == 0) return SC_RESULT_ERROR; *result = el->type; return SC_RESULT_OK; }
sc_result sc_storage_get_arc_end(sc_addr addr, sc_addr *result) { sc_element *el = sc_storage_get_element(addr, SC_TRUE); if (el->type & sc_type_arc_mask) { *result = el->arc.end; return SC_RESULT_OK; } return SC_RESULT_ERROR_INVALID_TYPE; }
sc_result sc_storage_get_link_content(sc_addr addr, sc_stream **stream) { sc_element *el = sc_storage_get_element(addr, SC_TRUE); sc_check_sum checksum; if (el == nullptr) return SC_RESULT_ERROR_INVALID_PARAMS; if (!(el->type & sc_type_link)) return SC_RESULT_ERROR_INVALID_TYPE; // prepare checksum checksum.len = el->content.len; memcpy(checksum.data, el->content.data, checksum.len); return sc_fs_storage_get_checksum_content(&checksum, stream); }
sc_addr sc_storage_arc_new(sc_type type, sc_addr beg, sc_addr end) { sc_addr addr; sc_element el, *beg_el, *end_el, *tmp_el; #if USE_TWO_ORIENTED_ARC_LIST sc_element *tmp_arc; #endif memset(&el, 0, sizeof(el)); g_assert( !(sc_type_node & type) ); el.type = (type & sc_type_arc_mask) ? type : (sc_type_arc_common | type); el.arc.begin = beg; el.arc.end = end; // get new element tmp_el = sc_storage_append_el_into_segments(&el, &addr); g_assert(tmp_el != 0); // get begin and end elements beg_el = sc_storage_get_element(beg, SC_TRUE); end_el = sc_storage_get_element(end, SC_TRUE); // emit events sc_event_emit(beg, SC_EVENT_ADD_OUTPUT_ARC, addr); sc_event_emit(end, SC_EVENT_ADD_INPUT_ARC, addr); // if (type & sc_type_edge_common) // { // sc_event_emit(end, SC_EVENT_ADD_OUTPUT_ARC, addr); // sc_event_emit(beg, SC_EVENT_ADD_INPUT_ARC, addr); // } // check values g_assert(beg_el != nullptr && end_el != nullptr); g_assert(beg_el->type != 0 && end_el->type != 0); // set next output arc for our created arc tmp_el->arc.next_out_arc = beg_el->first_out_arc; tmp_el->arc.next_in_arc = end_el->first_in_arc; #if USE_TWO_ORIENTED_ARC_LIST if (SC_ADDR_IS_NOT_EMPTY(beg_el->first_out_arc)) { tmp_arc = sc_storage_get_element(beg_el->first_out_arc, SC_TRUE); tmp_arc->arc.prev_out_arc = addr; } if (SC_ADDR_IS_NOT_EMPTY(end_el->first_in_arc)) { tmp_arc = sc_storage_get_element(end_el->first_in_arc, SC_TRUE); tmp_arc->arc.prev_in_arc = addr; } #endif // set our arc as first output/input at begin/end elements beg_el->first_out_arc = addr; end_el->first_in_arc = addr; return addr; }
sc_result sc_storage_element_free(sc_addr addr) { sc_element *el, *el2; sc_addr _addr; sc_uint addr_int; GSList *remove_list = 0; el = el2 = 0; if (sc_storage_is_element(addr) == SC_FALSE) return SC_RESULT_ERROR; if (sc_iterator_has_any_timestamp()) storage_time_stamp++; remove_list = g_slist_append(remove_list, GUINT_TO_POINTER(SC_ADDR_LOCAL_TO_INT(addr))); while (remove_list != 0) { // get sc-addr for removing addr_int = GPOINTER_TO_UINT(remove_list->data); _addr.seg = SC_ADDR_LOCAL_SEG_FROM_INT(addr_int); _addr.offset = SC_ADDR_LOCAL_OFFSET_FROM_INT(addr_int); // go to next sc-addr in list remove_list = g_slist_delete_link(remove_list, remove_list); el = sc_storage_get_element(_addr, SC_TRUE); g_assert(el != 0 && el->type != 0); // remove registered events before deletion sc_event_notify_element_deleted(_addr); el->delete_time_stamp = storage_time_stamp; if (el->type & sc_type_arc_mask) { sc_event_emit(el->arc.begin, SC_EVENT_REMOVE_OUTPUT_ARC, _addr); sc_event_emit(el->arc.end, SC_EVENT_REMOVE_INPUT_ARC, _addr); } // Iterate all connectors for deleted element and append them into remove_list _addr = el->first_out_arc; while (SC_ADDR_IS_NOT_EMPTY(_addr)) { el2 = sc_storage_get_element(_addr, SC_TRUE); // do not append elements, that have delete_time_stamp != 0 if (el2->delete_time_stamp == 0) remove_list = g_slist_append(remove_list, GUINT_TO_POINTER(SC_ADDR_LOCAL_TO_INT(_addr))); _addr = el2->arc.next_out_arc; } _addr = el->first_in_arc; while (SC_ADDR_IS_NOT_EMPTY(_addr)) { el2 = sc_storage_get_element(_addr, SC_TRUE); // do not append elements, that have delete_time_stamp != 0 if (el2->delete_time_stamp == 0) remove_list = g_slist_append(remove_list, GUINT_TO_POINTER(SC_ADDR_LOCAL_TO_INT(_addr))); _addr = el2->arc.next_in_arc; } // clean temp addr SC_ADDR_MAKE_EMPTY(_addr); } return SC_RESULT_OK; }
sc_uint32 sc_segment_free_garbage(sc_segment *seg, sc_uint32 oldest_time_stamp) { sc_uint32 free_count = 0; sc_uint32 idx = 0; //sc_uint32 newest_time_stamp = sc_storage_get_time_stamp(); #if USE_TWO_ORIENTED_ARC_LIST sc_element *el = 0, *el2 = 0, *el_arc = 0, *next_el_arc = 0, *prev_el_arc = 0; sc_addr prev_arc, next_arc; sc_addr self_addr; #else sc_element *el = 0, *el2 = 0, *el_arc = 0, *prev_el_arc = 0; sc_addr prev_arc, current_arc; sc_addr self_addr; #endif #if USE_SEGMENT_EMPTY_SLOT_BUFFER seg->empty_slot_buff_head = 0; #endif self_addr.seg = seg->num; for (idx = 0; idx < SEGMENT_SIZE; ++idx) { el = &(seg->elements[idx]); self_addr.offset = idx; // skip element that wasn't deleted if (el->delete_time_stamp <= oldest_time_stamp && el->delete_time_stamp != 0) { // delete arcs from output and intpu lists // @todo two oriented lists support if (el->type & sc_type_arc_mask) { #if USE_TWO_ORIENTED_ARC_LIST prev_arc = el->arc.prev_out_arc; next_arc = el->arc.next_out_arc; if (SC_ADDR_IS_NOT_EMPTY(prev_arc)) { prev_el_arc = sc_storage_get_element(prev_arc, SC_TRUE); prev_el_arc->arc.next_out_arc = next_arc; } if (SC_ADDR_IS_NOT_EMPTY(next_arc)) { next_el_arc = sc_storage_get_element(next_arc, SC_TRUE); next_el_arc->arc.prev_out_arc = prev_arc; } #else SC_ADDR_MAKE_EMPTY(prev_arc); // output list el2 = sc_storage_get_element(el->arc.begin, SC_TRUE); current_arc = el2->first_out_arc; while (SC_ADDR_IS_NOT_EMPTY(current_arc) && SC_ADDR_IS_NOT_EQUAL(self_addr, current_arc)) { prev_arc = current_arc; prev_el_arc = el_arc; el_arc = sc_storage_get_element(current_arc, SC_TRUE); current_arc = el->arc.next_out_arc; } if (SC_ADDR_IS_NOT_EMPTY(prev_arc) && SC_ADDR_IS_NOT_EMPTY(current_arc)) prev_el_arc->arc.next_out_arc = el_arc->arc.next_out_arc; prev_el_arc = 0; el_arc = 0; SC_ADDR_MAKE_EMPTY(prev_arc); // input list el2 = sc_storage_get_element(el->arc.end, SC_TRUE); current_arc = el2->first_in_arc; while (SC_ADDR_IS_NOT_EMPTY(current_arc) && SC_ADDR_IS_NOT_EQUAL(self_addr, current_arc)) { prev_arc = current_arc; prev_el_arc = el_arc; el_arc = sc_storage_get_element(current_arc, SC_TRUE); current_arc = el->arc.next_in_arc; } if (SC_ADDR_IS_NOT_EMPTY(prev_arc) && SC_ADDR_IS_NOT_EMPTY(current_arc)) prev_el_arc->arc.next_in_arc = el_arc->arc.next_in_arc; #endif } el->type = 0; free_count ++; } // collect empty cells if (el->type == 0 && !(idx == 0 && seg->num == 0)) { #if USE_SEGMENT_EMPTY_SLOT_BUFFER if (seg->empty_slot_buff_head < SEGMENT_EMPTY_BUFFER_SIZE) seg->empty_slot_buff[seg->empty_slot_buff_head++] = idx; #else seg->empty_slot = idx; #endif } } return free_count; }