3 /// Builder class for restoring from Barry Backup files
7 Copyright (C) 2010, Net Direct Inc. (http://www.netdirect.ca/)
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
18 See the GNU General Public License in the COPYING file at the
19 root directory of this project for more details.
37 int CountFiles(reuse::TarFile
&tar
,
38 const Barry::Restore::DBListType
&restoreList
,
42 std::string name
, last_name
;
45 while( tar
.ReadNextFilenameOnly(name
) ) {
46 std::string::size_type pos
= name
.rfind('/');
47 if( pos
== std::string::npos
)
49 std::string dbname
= name
.substr(0, pos
);
51 if( dbname
!= last_name
) {
53 good
= (default_all_db
&& restoreList
.size() == 0) ||
54 restoreList
.IsSelected(dbname
);
64 //////////////////////////////////////////////////////////////////////////////
65 // Static Restore members
67 /// Splits a tarpath of the form "DBName/DBID" into separate string values.
68 /// Returns true if successful, false if tarpath is a bad name.
69 bool Restore::SplitTarPath(const std::string
&tarpath
,
71 std::string
&dbid_text
,
75 std::string::size_type pos
= tarpath
.rfind('/');
76 if( pos
== std::string::npos
)
77 return false; // bad name
79 dbname
= tarpath
.substr(0, pos
);
80 dbid_text
= tarpath
.substr(pos
+ 1);
81 if( dbname
.size() == 0 || dbid_text
.size() == 0 )
82 return false; // bad name
84 std::istringstream
iss(dbid_text
);
86 iss
>> std::hex
>> dbid
>> temp
;
87 dbrectype
= (uint8_t) temp
;
93 //////////////////////////////////////////////////////////////////////////////
94 // Restore - constructors
96 Restore::Restore(const std::string
&tarpath
, bool default_all_db
)
98 , m_default_all_db(default_all_db
)
100 , m_tar_record_loaded(false)
105 m_tar
.reset( new reuse::TarFile(tarpath
.c_str(), false,
106 &reuse::gztar_ops_nonthread
, true) );
108 catch( reuse::TarFile::TarError
&te
) {
109 throw Barry::RestoreError(te
.what());
118 //////////////////////////////////////////////////////////////////////////////
119 // Restore - Protected helpers
121 bool Restore::IsSelected(const std::string
&dbName
) const
123 // if nothing is in the list, use default
124 if( m_dbList
.size() == 0 )
125 return m_default_all_db
;
127 return m_dbList
.IsSelected(dbName
);
131 //////////////////////////////////////////////////////////////////////////////
132 // Restore - Public API
134 void Restore::AddDB(const std::string
&dbName
)
136 if( find(m_dbList
.begin(), m_dbList
.end(), dbName
) == m_dbList
.end() ) {
137 // only add it if it is not already in the list
138 m_dbList
.push_back(dbName
);
142 void Restore::Add(const DBListType
&dbList
)
144 for( DBListType::const_iterator i
= dbList
.begin();
152 void Restore::SkipCurrentDB()
154 // skip all records until next DB
156 while( Retrieve(m_record_data
) ) {
157 std::cerr
<< "Skipping: "
158 << m_current_dbname
<< "/"
159 << m_tar_id_text
<< std::endl
;
160 m_tar_record_loaded
= false;
163 catch( reuse::TarFile::TarError
& ) {
168 unsigned int Restore::GetRecordTotal() const
170 return GetRecordTotal(m_tarpath
, m_dbList
, m_default_all_db
);
173 unsigned int Restore::GetRecordTotal(const std::string
&tarpath
,
174 const DBListType
&dbList
,
177 unsigned int count
= 0;
179 std::auto_ptr
<reuse::TarFile
> tar
;
182 // do a scan through the tar file
183 tar
.reset( new reuse::TarFile(tarpath
.c_str(), false,
184 &reuse::gztar_ops_nonthread
, true) );
185 count
= CountFiles(*tar
, dbList
, default_all_db
);
187 catch( reuse::TarFile::TarError
&te
) {
188 throw Barry::RestoreError(te
.what());
194 //////////////////////////////////////////////////////////////////////////////
195 // Barry::Builder overrides
197 bool Restore::Retrieve(Data
&record_data
)
202 // if loaded, we are likely on a database
203 // boundary, and the last read crossed it, so don't load again
204 if( m_tar_record_loaded
)
207 // search for a valid record
209 // load record data from tar file
210 std::string filename
;
211 if( !m_tar
->ReadNextFile(filename
, record_data
) ) {
212 // assume end of file
216 m_tar_record_loaded
= true;
218 // split record filename into dbname and ID
220 if( !SplitTarPath(filename
, dbname
, m_tar_id_text
, m_rec_type
, m_unique_id
) ) {
221 // invalid filename, skip it
222 std::cerr
<< "Skipping invalid tar record: " << filename
<< std::endl
;
226 // are we working on the same dbname as last time?
228 if( m_current_dbname
== dbname
) {
232 // DIFFERENT DBNAME from here on down!
234 // does the filter allow this record?
235 // if not, skip it and continue looking
236 if( !IsSelected(dbname
) ) {
237 m_tar_record_loaded
= false;
241 // all checks pass, load the new dbname, and return false
242 // if we are on a dbname boundary
244 if( m_current_dbname
.size() == 0 ) {
245 // this is the first time through Retrieve, so ok
249 m_current_dbname
= dbname
;
254 bool Restore::BuildRecord(Barry::DBData
&data
,
256 const Barry::IConverter
*ic
)
258 if( !Retrieve(m_record_data
) )
261 data
.SetVersion(Barry::DBData::REC_VERSION_1
);
262 data
.SetDBName(m_current_dbname
);
263 data
.SetIds(m_rec_type
, m_unique_id
);
264 data
.SetOffset(offset
);
266 int packet_size
= offset
+ m_record_data
.GetSize();
267 unsigned char *buf
= data
.UseData().GetBuffer(packet_size
);
268 memcpy(buf
+ offset
, m_record_data
.GetData(), m_record_data
.GetSize());
269 offset
+= m_record_data
.GetSize();
270 data
.UseData().ReleaseBuffer(packet_size
);
272 // clear loaded flag, as it has now been used
273 m_tar_record_loaded
= false;
277 bool Restore::FetchRecord(Barry::DBData
&data
, const Barry::IConverter
*ic
)
279 if( !Retrieve(data
.UseData()) )
282 data
.SetVersion(Barry::DBData::REC_VERSION_1
);
283 data
.SetDBName(m_current_dbname
);
284 data
.SetIds(m_rec_type
, m_unique_id
);
287 // clear loaded flag, as it has now been used
288 m_tar_record_loaded
= false;
292 bool Restore::EndOfFile() const