sc_bool sc_fs_storage_shutdown(sc_segment **segments) { g_message("Shutdown sc-storage"); g_message("Write segments"); sc_fs_storage_write_to_path(segments); g_message("Save file memory state"); if (sc_fm_save(fm_engine) != SC_RESULT_OK) g_critical("Error while saves file memory"); g_free(repo_path); return SC_TRUE; }
sc_bool sc_fs_storage_write_to_path(sc_segment **segments) { sc_uint32 idx = 0, header_size = 0; const sc_segment *segment = 0; sc_fs_storage_segments_header header; GChecksum * checksum = null_ptr; GIOChannel * output = null_ptr; gchar * tmp_filename = null_ptr; gsize bytes; sc_bool result = SC_TRUE; if (!g_file_test(repo_path, G_FILE_TEST_IS_DIR)) { g_error("%s isn't a directory.", repo_path); return SC_FALSE; } // create temporary file output = _open_tmp_file(&tmp_filename); memset(&header, 0, sizeof(sc_fs_storage_segments_header)); header.segments_num = 0; header.timestamp = g_get_real_time(); header.version = sc_version_to_int(&SC_VERSION); g_io_channel_set_encoding(output, null_ptr, null_ptr); checksum = g_checksum_new(_checksum_type()); g_checksum_reset(checksum); for (idx = 0; idx < SC_ADDR_SEG_MAX; idx++) { segment = segments[idx]; if (segment == null_ptr) break; // stop save, because we allocate segment in order g_checksum_update(checksum, (guchar*)segment->elements, SC_SEG_ELEMENTS_SIZE_BYTE); } header.segments_num = idx; bytes = SC_STORAGE_SEG_CHECKSUM_SIZE; g_checksum_get_digest(checksum, header.checksum, &bytes); header_size = sizeof(header); if (g_io_channel_write_chars(output, (gchar*)&header_size, sizeof(header_size), &bytes, null_ptr) != G_IO_STATUS_NORMAL || bytes != sizeof(header_size)) { g_error("Can't write header size: %s", tmp_filename); result = SC_FALSE; goto clean; } if (g_io_channel_write_chars(output, (gchar*)&header, header_size, &bytes, null_ptr) != G_IO_STATUS_NORMAL || bytes != header_size) { g_error("Can't write header: %s", tmp_filename); result = SC_FALSE; goto clean; } for (idx = 0; idx < header.segments_num; ++idx) { segment = segments[idx]; g_assert(segment != null_ptr); if (g_io_channel_write_chars(output, (gchar*)segment->elements, SC_SEG_ELEMENTS_SIZE_BYTE, &bytes, null_ptr) != G_IO_STATUS_NORMAL || bytes != SC_SEG_ELEMENTS_SIZE_BYTE) { g_error("Can't write segment %d into %s", idx, tmp_filename); result = SC_FALSE; goto clean; } } if (result == SC_TRUE) { // rename main file if (g_file_test(tmp_filename, G_FILE_TEST_IS_REGULAR)) { g_io_channel_shutdown(output, TRUE, NULL); output = null_ptr; if (g_rename(tmp_filename, segments_path) != 0) { g_error("Can't rename %s -> %s", tmp_filename, segments_path); result = SC_FALSE; } } // save file memory g_message("Save file memory state"); if (sc_fm_save(fm_engine) != SC_RESULT_OK) g_critical("Error while saves file memory"); } clean: { if (tmp_filename) g_free(tmp_filename); if (checksum) g_checksum_free(checksum); if (output) g_io_channel_shutdown(output, TRUE, null_ptr); } return result; }