8 #include "filedata.hpp"
12 unsigned long long current_time() {
13 unsigned long long rc = 0;
14 time_t now_tt = time( 0 );
15 tm *now = localtime( &now_tt );
16 rc += ( now->tm_year + 1900ULL ) * 10000000000ULL;
17 rc += ( now->tm_mon + 1ULL ) * 100000000ULL;
18 rc += now->tm_mday * 1000000ULL;
19 rc += now->tm_hour * 10000ULL;
20 rc += now->tm_min * 100ULL;
26 template<class I, class O>
27 bool copy_until_full( I begin, I end, O out, unsigned long long &space ) {
28 const unsigned long long block_size = 0x200ULL;
32 while( 0 != space && i != end ) {
33 unsigned long long size = (*i)->getFileSize();
34 unsigned long long blocks = size & ( ~(block_size-1) );
35 if( blocks < size ) blocks += block_size;
37 if( blocks <= space ) {
42 // We missed a file that should be included so the backup is not complete
51 void populate_set( istream &in, SET &files ) {
53 FileData *data = new FileData();
55 if( data->getFileName().size() ) {
60 } while( ! in.eof() );
64 void partition_sets( const SET ¤t, const SET &old,
65 SET &added, SET &common, SET &deleted ) {
68 set_difference( current.begin(), current.end(),
69 old.begin(), old.end(),
70 inserter( added, added.begin() ),
73 set_difference( old.begin(), old.end(),
74 current.begin(), current.end(),
75 inserter( deleted, deleted.begin() ),
78 set_union( current.begin(), current.end(),
79 old.begin(), old.end(),
80 inserter( common, common.begin() ),
85 // Parse the list of current files on stdin
87 populate_set( cin, current );
90 ifstream db( "test.db" );
91 if( db && db.good() ) {
92 populate_set( db, backed_up );
95 // Now divide the two sets into three sets (added, deleted and common )
96 file_set added, deleted, common;
97 partition_sets( current, backed_up, added, common, deleted );
99 { // This little block will copy the last_backup_date from the second set to the first
102 file_set common_with_dates;
103 set_union( backed_up.begin(), backed_up.end(),
104 current.begin(), current.end(),
105 inserter( common_with_dates, common_with_dates.begin() ),
108 file_set::iterator i = common.begin(), j = common_with_dates.begin();
109 for( ; i != common.end(); ++i, ++j ) {
110 (*i)->setLastBackupDate( (*j)->getLastBackupDate() );
114 // Now find the list of files to backup.
117 // backup all added files
118 copy( added.begin(), added.end(), inserter( backups, backups.begin() ) );
120 // backup common files that have changed since the last backup date.
121 for( file_set::iterator i = common.begin(); i != common.end(); ++i ) {
122 if( (*i)->getLastBackupDate() < (*i)->getModifiedDate() ) {
123 backups.insert( *i );
127 // Now, sort the backups by filesize and build a list of up to SIZE
128 file_vector backups_s;
129 copy( backups.begin(), backups.end(), back_inserter( backups_s ) );
131 FileDataSizeCmp sizecmp;
132 sort( backups_s.begin(), backups_s.end(), sizecmp );
135 unsigned long long space = 0x107c00000ULL; // 4220 MBytes
137 insert_iterator<file_set> final_i( final, final.begin() );
139 // Copy files over until full or out of files
140 bool complete = copy_until_full( backups_s.rbegin(),
145 // Now, sort the non-backed-up list by last_backup_date and back-fill
147 file_vector leftovers;
149 set_difference( current.begin(), current.end(),
150 final.begin(), final.end(),
151 back_inserter( leftovers ),
154 FileDataLastBackupCmp lastbackupcmp;
155 sort( leftovers.begin(), leftovers.end(), lastbackupcmp );
157 copy_until_full( leftovers.begin(), leftovers.end(), final_i, space );
160 unsigned long long now = current_time();
161 for( file_set::iterator k = final.begin(); k != final.end(); ++k ) {
162 (*k)->setLastBackupDate( now );
165 // Write the 'current' list to the dbfile
166 ofstream dbout( "test.db" );
167 copy( current.begin(), current.end(), ostream_iterator<FileData*>( dbout, "" ) );
169 // Write the 'final' list to stdout
170 copy( final.begin(), final.end(), ostream_iterator<FileData*>( cout, "" ) );
172 if( ! complete ) { cerr << "incomplete" << endl; }
175 for( file_set::iterator i = backed_up.begin(); i != backed_up.end(); ++i ) { delete *i; }
176 for( file_set::iterator i = current.begin(); i != current.end(); ++i ) { delete *i; }