inital commit
[c11concurrency-benchmarks.git] / mabain / src / drm_base.cpp
1 /**
2  * Copyright (C) 2018 Cisco Inc.
3  *
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.
7  *
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.
12  *
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/>.
15  */
16
17 // @author Changxue Deng <chadeng@cisco.com>
18
19 #include "error.h"
20 #include "drm_base.h"
21 #include "version.h"
22
23 namespace mabain {
24
25 void DRMBase::ReadHeaderVersion(const std::string &header_path, uint16_t ver[4])
26 {
27     memset(ver, 0, sizeof(uint16_t)*4);
28     FILE *hdr_file = fopen(header_path.c_str(), "rb");
29     if(hdr_file == NULL)
30     {
31         Logger::Log(LOG_LEVEL_ERROR, "failed to open header file %s", header_path.c_str());
32         throw (int) MBError::OPEN_FAILURE;
33     }
34     if(fread(ver, sizeof(uint16_t), 4, hdr_file) != 4)
35     {
36         fclose(hdr_file);
37         throw (int) MBError::READ_ERROR; 
38     }
39     fclose(hdr_file);
40 }
41
42 void DRMBase::ReadHeader(const std::string &header_path, uint8_t *buff, int buf_size)
43 {
44     FILE *hdr_file = fopen(header_path.c_str(), "rb");
45     if(hdr_file == NULL)
46     {   
47         Logger::Log(LOG_LEVEL_ERROR, "failed to open header file %s", header_path.c_str());
48         throw (int) MBError::OPEN_FAILURE;
49     }
50     if(fread(buff, buf_size, 1, hdr_file) != 1)
51     {
52         fclose(hdr_file);
53         throw (int) MBError::READ_ERROR; 
54     }
55     fclose(hdr_file);
56 }
57
58 void DRMBase::WriteHeader(const std::string &header_path, uint8_t *buff, int queue_buff_size)
59 {
60     FILE *hdr_file = fopen(header_path.c_str(), "wb");
61     if(hdr_file == NULL)
62     {
63         Logger::Log(LOG_LEVEL_ERROR, "failed to open header file %s", header_path.c_str());
64         throw (int) MBError::OPEN_FAILURE;
65     }
66     if(fwrite(buff, RollableFile::page_size, 1, hdr_file) != 1)
67     {
68         fclose(hdr_file);
69         throw (int) MBError::WRITE_ERROR;
70     }
71     memset(buff, 0, RollableFile::page_size);
72     for(int i = 0; i < queue_buff_size / RollableFile::page_size; i++)
73     {
74         if(fwrite(buff, RollableFile::page_size, 1, hdr_file) != 1)
75         {
76             fclose(hdr_file);
77             throw (int) MBError::WRITE_ERROR;
78         }
79     }
80     size_t size_left = queue_buff_size % RollableFile::page_size;
81     if(size_left > 0)
82     {
83         if(fwrite(buff, size_left, 1, hdr_file) != 1)
84         {
85             fclose(hdr_file);
86             throw (int) MBError::WRITE_ERROR;
87         }
88     }
89     fclose(hdr_file);
90 }
91
92 void DRMBase::ValidateHeaderFile(const std::string &header_path, int mode,
93                                  int queue_buff_size, bool &update_header)
94 {
95     uint16_t hdr_ver[4];
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;
100
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));
111
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);
116
117     // Swap header files
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)
121     {
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;
125     }
126     if(rename(tmp_header_path.c_str(), header_path.c_str()) != 0)
127     {
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;
131     }
132
133     update_header = true;
134 }
135
136 void DRMBase::PrintHeader(std::ostream &out_stream) const
137 {   
138     if(header == NULL)
139         return;
140     
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++)
171     {   
172         sprintf(data_str_buff + 3*i, "%2x ", header->excep_buff[i]);
173     }
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;
187 }
188
189 }