inital commit
[c11concurrency-benchmarks.git] / mabain / src / mb_backup.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 Shridhar Bhalerao <shbhaler@cisco.com>
18
19 #include <iostream>
20 #include <fstream>
21 #include <limits.h>
22 #include <sstream>
23
24 #include "mb_backup.h"
25 #include "mb_data.h"
26 #include "integer_4b_5b.h"
27
28 namespace mabain {
29
30 DBBackup::DBBackup(const DB &db) : db_ref(db)
31 {
32     if(!(db.GetDBOptions() & CONSTS::ACCESS_MODE_WRITER))
33         throw (int) MBError::NOT_ALLOWED;
34
35     Dict *dict = db_ref.GetDictPtr();
36     if(dict == NULL)
37         throw (int) MBError::NOT_INITIALIZED;
38     
39     header = dict->GetHeaderPtr();
40     if(header == NULL)
41         throw (int) MBError::NOT_INITIALIZED;
42
43 }
44
45 DBBackup::~DBBackup()
46 {
47 }
48
49
50 void DBBackup::copy_file (const std::string &src_path, const std::string &dest_path,
51                           char *buffer, int buffer_size)
52 {
53     FILE *fp_read, *fp_write;
54
55     if ((fp_read = fopen (src_path.c_str(),"rb")) == NULL)
56     {
57         Logger::Log(LOG_LEVEL_ERROR, "Backup failed: Could not open file %s", src_path.c_str()); 
58         throw MBError::OPEN_FAILURE;
59     }
60     if ((fp_write = fopen(dest_path.c_str(),"wb")) == NULL)
61     {
62         fclose(fp_read);
63         Logger::Log(LOG_LEVEL_ERROR, "Backup failed: Could not open file %s", dest_path.c_str()); 
64         throw MBError::OPEN_FAILURE;
65     }
66     
67     int rval = MBError::SUCCESS;
68     int read_count, write_count;
69
70     while(true)
71     {
72         read_count = fread(buffer, buffer_size, 1, fp_read);
73
74         if(feof(fp_read) && read_count == 0)
75              break;
76         if (read_count != 1)
77         {
78             rval = MBError::READ_ERROR;
79             break;
80         }
81
82         write_count = fwrite(buffer,buffer_size, 1, fp_write);
83         if(write_count != 1)
84         {
85             rval = MBError::WRITE_ERROR;
86             break;
87         }
88     }
89     fclose(fp_read);
90     fclose(fp_write);
91     
92     if(rval != MBError::SUCCESS)
93     {
94         Logger::Log(LOG_LEVEL_ERROR, "Backup failed %s", MBError::get_error_str(rval)); 
95         throw rval;
96     }
97 }
98
99 int DBBackup::Backup(const char * bk_dir)
100 {
101     if(bk_dir == NULL)
102         throw (int) MBError::INVALID_ARG;
103
104     std::string bk_header_path = std::string(bk_dir) + "/_mabain_h";
105     if(access(bk_header_path.c_str(), R_OK) == 0)
106         throw (int) MBError::OPEN_FAILURE;
107     
108     if(!db_ref.is_open())
109         throw (int) db_ref.Status();
110    
111     if(header->m_data_offset > MAX_6B_OFFSET || header->m_index_offset > MAX_6B_OFFSET)
112         throw (int) MBError::INVALID_SIZE;
113     if(header->data_block_size == 0 || header->data_block_size % BLOCK_SIZE_ALIGN != 0)
114         throw (int) MBError::INVALID_SIZE;
115     if(header->index_block_size == 0 || header->index_block_size % BLOCK_SIZE_ALIGN != 0)
116         throw (int) MBError::INVALID_SIZE;
117     
118     db_ref.Flush();
119
120     int num_data_files, num_index_files;
121     // get the number of files from the header: max_bytes/number_of_bytes_per_file
122     num_data_files = (header->m_data_offset/header->data_block_size) + 1; 
123     num_index_files = (header->m_index_offset/header->index_block_size) + 1;
124     
125     char *buffer = (char *) malloc(BLOCK_SIZE_ALIGN);
126     if(buffer == NULL)
127         throw (int) MBError::NO_MEMORY;
128     
129     // loop through all data files
130     const std::string &orig_dir = db_ref.GetDBDir();
131     std::string read_file_path_base = orig_dir + "/_mabain_d";
132     std::string write_file_path_base = std::string(bk_dir) + "/_mabain_d";
133     std::string read_file_path;
134     std::string write_file_path;
135     
136     for (int i = 0; i < num_data_files; i++)
137     {
138         read_file_path = read_file_path_base + std::to_string(i);
139         write_file_path = write_file_path_base + std::to_string(i);
140         copy_file(read_file_path, write_file_path, buffer, BLOCK_SIZE_ALIGN);
141     }
142     
143     read_file_path_base = orig_dir + "/_mabain_i";
144     write_file_path_base = std::string(bk_dir) + "/_mabain_i";
145     for (int i = 0; i < num_index_files; i++)
146     {
147         read_file_path = read_file_path_base + std::to_string(i);
148         write_file_path = write_file_path_base + std::to_string(i);
149         copy_file(read_file_path, write_file_path, buffer, BLOCK_SIZE_ALIGN);
150     }
151     
152     read_file_path = orig_dir + "/_mabain_h";
153     write_file_path = std::string(bk_dir) + "/_mabain_h";
154     //header is size of page_size
155     copy_file(read_file_path, write_file_path, buffer, RollableFile::page_size);
156     
157     free(buffer);
158     
159     //reset number readers/writers in backed up DB.
160     int rval;
161     DB db = DB(bk_dir, CONSTS::ACCESS_MODE_READER, 0, 0);
162     rval = db.UpdateNumHandlers(CONSTS::ACCESS_MODE_WRITER, -1);
163     if(rval != MBError::SUCCESS)
164         Logger::Log(LOG_LEVEL_WARN,"failed to reset number of writer for DB %s", bk_dir);
165     
166     rval = db.UpdateNumHandlers(CONSTS::ACCESS_MODE_READER, INT_MIN);
167     if(rval != MBError::SUCCESS)
168         Logger::Log(LOG_LEVEL_WARN,"failed to reset number of writer for DB %s", bk_dir);
169     db.Close();
170     return MBError::SUCCESS;
171 }
172
173 }