error_code replica_init_info::store(const char* file) { std::string ffile = std::string(file); std::string tmp_file = ffile + ".tmp"; std::ofstream os(tmp_file.c_str(), (std::ofstream::out | std::ios::binary | std::ofstream::trunc)); if (!os.is_open()) { derror("open file %s failed", tmp_file.c_str()); return ERR_FILE_OPERATION_FAILED; } // compute crc crc = 0; crc = dsn_crc32_compute((const void*)this, sizeof(*this), 0); os.write((const char*)this, sizeof(*this)); os.close(); if (!utils::filesystem::rename_path(tmp_file, ffile)) { return ERR_FILE_OPERATION_FAILED; } ddebug("update app init info in %s, ballot = %" PRId64 ", decree = %" PRId64 ", log_offset<S,P> = <%" PRId64 ",%" PRId64 ">", ffile.c_str(), init_ballot, init_decree, init_offset_in_shared_log, init_offset_in_private_log ); return ERR_OK; }
error_code replica_init_info::load(const char* file) { std::ifstream is(file, std::ios::binary); if (!is.is_open()) { derror("open file %s failed", file); return ERR_FILE_OPERATION_FAILED; } magic = 0x0; is.read((char*)this, sizeof(*this)); is.close(); if (magic != 0xdeadbeef) { derror("data in file %s is invalid (magic)", file); return ERR_INVALID_DATA; } auto fcrc = crc; crc = 0; // set for crc computation auto lcrc = dsn_crc32_compute((const void*)this, sizeof(*this), 0); crc = fcrc; // recover if (lcrc != fcrc) { derror("data in file %s is invalid (crc)", file); return ERR_INVALID_DATA; } return ERR_OK; }
/*static*/ bool message_ex::is_right_header(char* hdr) { int32_t crc32 = *(int32_t*)hdr; if (crc32 != CRC_INVALID) { //dassert (*(int32_t*)data == hdr_crc32, "HeaderCrc must be put at the beginning of the buffer"); *(int32_t*)hdr = CRC_INVALID; bool r = ((uint32_t)crc32 == dsn_crc32_compute(hdr, sizeof(message_header), 0)); *(int32_t*)hdr = crc32; return r; } // crc is not enabled else { return true; } }
bool message_ex::is_right_body(bool is_write_msg) const { if (header->body_crc32 != CRC_INVALID) { int i_max = (int)buffers.size() - 1; uint32_t crc32 = 0; size_t len = 0; for (int i = 0; i <= i_max; i++) { uint32_t lcrc; const void* ptr; size_t sz; if (i == 0 && is_write_msg) { ptr = (const void*)(buffers[i].data() + sizeof(message_header)); sz = (size_t)buffers[i].length() - sizeof(message_header); } else { ptr = (const void*)buffers[i].data(); sz = (size_t)buffers[i].length(); } lcrc = dsn_crc32_compute(ptr, sz, crc32); crc32 = dsn_crc32_concatenate( 0, 0, crc32, len, crc32, lcrc, sz ); len += sz; } dassert(len == (size_t)header->body_length, "data length is wrong"); return header->body_crc32 == crc32; } // crc is not enabled else { return true; } }
void message_ex::seal(bool fill_crc) { dassert (!_is_read && _rw_committed, "seal can only be applied to write mode messages"); //dbg_dassert(header->body_length > 0, "message %s is empty!", header->rpc_name); if (fill_crc) { // compute data crc if necessary if (header->body_crc32 == CRC_INVALID) { int i_max = (int)buffers.size() - 1; uint32_t crc32 = 0; size_t len = 0; for (int i = 0; i <= i_max; i++) { uint32_t lcrc; const void* ptr; size_t sz; if (i == 0) { ptr = (const void*)(buffers[i].data() + sizeof(message_header)); sz = (size_t)buffers[i].length() - sizeof(message_header); } else { ptr = (const void*)buffers[i].data(); sz = (size_t)buffers[i].length(); } lcrc = dsn_crc32_compute(ptr, sz, crc32); crc32 = dsn_crc32_concatenate( 0, 0, crc32, len, crc32, lcrc, sz ); len += sz; } dassert (len == (size_t)header->body_length, "data length is wrong"); header->body_crc32 = crc32; } header->hdr_crc32 = CRC_INVALID; header->hdr_crc32 = dsn_crc32_compute(header, sizeof(message_header), 0); } else { #ifndef NDEBUG int i_max = (int)buffers.size() - 1; size_t len = 0; for (int i = 0; i <= i_max; i++) { len += (size_t)buffers[i].length(); } dassert(len == (size_t)header->body_length + sizeof(message_header), "data length is wrong"); #endif } }