2 * Copyright (C) 2018 Cisco Inc.
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License, version 2,
6 * as published by the Free Software Foundation.
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 // @author Changxue Deng <chadeng@cisco.com>
25 void DRMBase::ReadHeaderVersion(const std::string &header_path, uint16_t ver[4])
27 memset(ver, 0, sizeof(uint16_t)*4);
28 FILE *hdr_file = fopen(header_path.c_str(), "rb");
31 Logger::Log(LOG_LEVEL_ERROR, "failed to open header file %s", header_path.c_str());
32 throw (int) MBError::OPEN_FAILURE;
34 if(fread(ver, sizeof(uint16_t), 4, hdr_file) != 4)
37 throw (int) MBError::READ_ERROR;
42 void DRMBase::ReadHeader(const std::string &header_path, uint8_t *buff, int buf_size)
44 FILE *hdr_file = fopen(header_path.c_str(), "rb");
47 Logger::Log(LOG_LEVEL_ERROR, "failed to open header file %s", header_path.c_str());
48 throw (int) MBError::OPEN_FAILURE;
50 if(fread(buff, buf_size, 1, hdr_file) != 1)
53 throw (int) MBError::READ_ERROR;
58 void DRMBase::WriteHeader(const std::string &header_path, uint8_t *buff, int queue_buff_size)
60 FILE *hdr_file = fopen(header_path.c_str(), "wb");
63 Logger::Log(LOG_LEVEL_ERROR, "failed to open header file %s", header_path.c_str());
64 throw (int) MBError::OPEN_FAILURE;
66 if(fwrite(buff, RollableFile::page_size, 1, hdr_file) != 1)
69 throw (int) MBError::WRITE_ERROR;
71 memset(buff, 0, RollableFile::page_size);
72 for(int i = 0; i < queue_buff_size / RollableFile::page_size; i++)
74 if(fwrite(buff, RollableFile::page_size, 1, hdr_file) != 1)
77 throw (int) MBError::WRITE_ERROR;
80 size_t size_left = queue_buff_size % RollableFile::page_size;
83 if(fwrite(buff, size_left, 1, hdr_file) != 1)
86 throw (int) MBError::WRITE_ERROR;
92 void DRMBase::ValidateHeaderFile(const std::string &header_path, int mode,
93 int queue_buff_size, bool &update_header)
96 ReadHeaderVersion(header_path, hdr_ver);
97 if(hdr_ver[0] >= 1 && hdr_ver[1] >= 2) return;
98 if(!(mode & CONSTS::ACCESS_MODE_WRITER))
99 throw (int) MBError::VERSION_MISMATCH;
101 Logger::Log(LOG_LEVEL_INFO, "header version: %u.%u.%u does not match "
102 "library version: %u.%u.%u",
103 hdr_ver[0], hdr_ver[1], hdr_ver[2],
104 version[0], version[1], version[2]);
105 // Load the old header first
106 uint8_t buff[RollableFile::page_size];
107 ReadHeader(header_path, buff, RollableFile::page_size);
108 // Update version field
109 uint16_t *curr_version = reinterpret_cast<uint16_t*>(buff);
110 memcpy(curr_version, version, 4*sizeof(uint16_t));
112 // Write the new header file
113 std::string tmp_header_path = header_path + ".tmp";
114 Logger::Log(LOG_LEVEL_INFO, "updating header to newer version %s", tmp_header_path.c_str());
115 WriteHeader(tmp_header_path, buff, queue_buff_size);
118 std::string old_header_path = header_path + "_" + std::to_string(hdr_ver[0]) + "_"
119 + std::to_string(hdr_ver[1]) + "_" + std::to_string(hdr_ver[2]);
120 if(rename(header_path.c_str(), old_header_path.c_str()) != 0)
122 Logger::Log(LOG_LEVEL_ERROR, "failed to move file %s to %s", header_path.c_str(),
123 old_header_path.c_str());
124 throw (int) MBError::OPEN_FAILURE;
126 if(rename(tmp_header_path.c_str(), header_path.c_str()) != 0)
128 Logger::Log(LOG_LEVEL_ERROR, "failed to move file %s to %s", tmp_header_path.c_str(),
129 header_path.c_str());
130 throw (int) MBError::OPEN_FAILURE;
133 update_header = true;
136 void DRMBase::PrintHeader(std::ostream &out_stream) const
141 out_stream << "---------------- START OF HEADER ----------------" << std::endl;
142 out_stream << "version: " << header->version[0] << "." <<
143 header->version[1] << "." <<
144 header->version[2] << std::endl;
145 out_stream << "data size: " << header->data_size << std::endl;
146 out_stream << "db count: " << header->count << std::endl;
147 out_stream << "max data offset: " << header->m_data_offset << std::endl;
148 out_stream << "max index offset: " << header->m_index_offset << std::endl;
149 out_stream << "pending data buffer size: " << header->pending_data_buff_size << std::endl;
150 out_stream << "pending index buffer size: " << header->pending_index_buff_size << std::endl;
151 out_stream << "node count: " << header->n_states << std::endl;
152 out_stream << "edge count: " << header->n_edges << std::endl;
153 out_stream << "edge string size: " << header->edge_str_size << std::endl;
154 out_stream << "writer count: " << header->num_writer << std::endl;
155 out_stream << "reader count: " << header->num_reader << std::endl;
156 out_stream << "data sliding start: " << header->shm_data_sliding_start << std::endl;
157 out_stream << "index sliding start: " << header->shm_index_sliding_start << std::endl;
158 out_stream << "data block size: " << header->data_block_size << std::endl;
159 out_stream << "index block size: " << header->index_block_size << std::endl;
160 out_stream << "lock free data: " << std::endl;
161 out_stream << "\tcounter: " << header->lock_free.counter << std::endl;
162 out_stream << "\toffset: " << header->lock_free.offset << std::endl;
163 out_stream << "number of updates: " << header->num_update << std::endl;
164 out_stream << "entry count per bucket: " << header->entry_per_bucket << std::endl;
165 out_stream << "eviction bucket index: " << header->eviction_bucket_index << std::endl;
166 out_stream << "exception data: " << std::endl;
167 out_stream << "\tupdating status: " << header->excep_updating_status << std::endl;
168 out_stream << "\texception data buffer: ";
169 char data_str_buff[MB_EXCEPTION_BUFF_SIZE*3 + 1];
170 for(int i = 0; i < MB_EXCEPTION_BUFF_SIZE; i++)
172 sprintf(data_str_buff + 3*i, "%2x ", header->excep_buff[i]);
174 data_str_buff[MB_EXCEPTION_BUFF_SIZE*3] = '\0';
175 out_stream << data_str_buff << std::endl;
176 out_stream << "\toffset: " << header->excep_offset << std::endl;
177 out_stream << "\tlock free offset: " << header->excep_lf_offset << std::endl;
178 out_stream << "max index offset before rc: " << header->rc_m_index_off_pre << std::endl;
179 out_stream << "max data offset before rc: " << header->rc_m_data_off_pre << std::endl;
180 out_stream << "rc root offset: " << header->rc_root_offset << std::endl;
181 out_stream << "rc count: " << header->rc_count << std::endl;
182 out_stream << "shared memory queue size: " << header->async_queue_size << std::endl;
183 out_stream << "shared memory queue index: " << header->queue_index << std::endl;
184 out_stream << "shared memory writer index: " << header->writer_index << std::endl;
185 out_stream << "resource flag: " << header->rc_flag << std::endl;
186 out_stream << "---------------- END OF HEADER ----------------" << std::endl;