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.
34 int CountFiles(reuse::TarFile
&tar
,
35 const Barry::Restore::DBListType
&restoreList
,
39 std::string name
, last_name
;
42 while( tar
.ReadNextFilenameOnly(name
) ) {
43 std::string::size_type pos
= name
.rfind('/');
44 if( pos
== std::string::npos
)
46 std::string dbname
= name
.substr(0, pos
);
48 if( dbname
!= last_name
) {
50 good
= (default_all_db
&& restoreList
.size() == 0) ||
51 restoreList
.IsSelected(dbname
);
61 //////////////////////////////////////////////////////////////////////////////
62 // Static Restore members
64 /// Splits a tarpath of the form "DBName/DBID" into separate string values.
65 /// Returns true if successful, false if tarpath is a bad name.
66 bool Restore::SplitTarPath(const std::string
&tarpath
,
68 std::string
&dbid_text
,
72 std::string::size_type pos
= tarpath
.rfind('/');
73 if( pos
== std::string::npos
)
74 return false; // bad name
76 dbname
= tarpath
.substr(0, pos
);
77 dbid_text
= tarpath
.substr(pos
+ 1);
78 if( dbname
.size() == 0 || dbid_text
.size() == 0 )
79 return false; // bad name
81 std::istringstream
iss(dbid_text
);
83 iss
>> std::hex
>> dbid
>> temp
;
84 dbrectype
= (uint8_t) temp
;
90 //////////////////////////////////////////////////////////////////////////////
91 // Restore - constructors
93 Restore::Restore(const std::string
&tarpath
, bool default_all_db
)
94 : m_default_all_db(default_all_db
)
96 , m_tar_record_loaded(false)
101 m_tar
.reset( new reuse::TarFile(tarpath
.c_str(), false,
102 &reuse::gztar_ops_nonthread
, true) );
104 catch( reuse::TarFile::TarError
&te
) {
105 throw Barry::RestoreError(te
.what());
114 //////////////////////////////////////////////////////////////////////////////
115 // Restore - Protected helpers
117 bool Restore::IsSelected(const std::string
&dbName
) const
119 // if nothing is in the list, default to all
120 if( m_dbList
.size() == 0 )
123 return m_dbList
.IsSelected(dbName
);
127 //////////////////////////////////////////////////////////////////////////////
128 // Restore - Public API
130 void Restore::AddDB(const std::string
&dbName
)
132 m_dbList
.push_back(dbName
);
135 void Restore::SkipCurrentDB()
137 // skip all records until next DB
139 while( Retrieve() ) {
140 std::cerr
<< "Skipping: "
141 << m_current_dbname
<< "/"
142 << m_tar_id_text
<< std::endl
;
143 m_tar_record_loaded
= false;
146 catch( reuse::TarFile::TarError
& ) {
151 unsigned int Restore::GetRecordTotal(const std::string
&tarpath
) const
153 unsigned int count
= 0;
155 std::auto_ptr
<reuse::TarFile
> tar
;
158 // do a scan through the tar file
159 tar
.reset( new reuse::TarFile(tarpath
.c_str(), false,
160 &reuse::gztar_ops_nonthread
, true) );
161 count
= CountFiles(*tar
, m_dbList
, m_default_all_db
);
163 catch( reuse::TarFile::TarError
&te
) {
164 throw Barry::RestoreError(te
.what());
170 //////////////////////////////////////////////////////////////////////////////
171 // Barry::Builder overrides
173 bool Restore::Retrieve()
178 // if loaded, we are likely on a database
179 // boundary, and the last read crossed it, so don't load again
180 if( m_tar_record_loaded
)
183 // search for a valid record
185 // load record data from tar file
186 std::string filename
;
187 if( !m_tar
->ReadNextFile(filename
, m_record_data
) ) {
188 // assume end of file
192 m_tar_record_loaded
= true;
194 // split record filename into dbname and ID
196 if( !SplitTarPath(filename
, dbname
, m_tar_id_text
, m_rec_type
, m_unique_id
) ) {
197 // invalid filename, skip it
198 std::cerr
<< "Skipping invalid tar record: " << filename
<< std::endl
;
202 // are we working on the same dbname as last time?
204 if( m_current_dbname
== dbname
) {
208 // DIFFERENT DBNAME from here on down!
210 // does the filter allow this record?
211 // if not, skip it and continue looking
212 if( !IsSelected(dbname
) ) {
213 m_tar_record_loaded
= false;
217 // all checks pass, load the new dbname, and return false
218 // if we are on a dbname boundary
220 if( m_current_dbname
.size() == 0 ) {
221 // this is the first time through Retrieve, so ok
225 m_current_dbname
= dbname
;
230 std::string
Restore::GetDBName() const
232 return m_current_dbname
;
235 uint8_t Restore::GetRecType() const
240 uint32_t Restore::GetUniqueId() const
245 void Restore::BuildHeader(Barry::Data
&data
, size_t &offset
)
250 void Restore::BuildFields(Barry::Data
&data
, size_t &offset
,
251 const Barry::IConverter
*ic
)
253 int packet_size
= offset
+ m_record_data
.size();
254 unsigned char *buf
= data
.GetBuffer(packet_size
);
255 memcpy(buf
+ offset
, m_record_data
.data(), m_record_data
.size());
256 offset
+= m_record_data
.size();
257 data
.ReleaseBuffer(packet_size
);
259 // clear loaded flag, as it has now been used
260 m_tar_record_loaded
= false;