7 #include "filedata.hpp"
11 template<class ISTREAM, class SET>
12 void populate_set( ISTREAM &in, SET &files ) {
14 FileData *data = new FileData();
17 } while( ! in.eof() );
21 void partition_sets( const SET ¤t, const SET &old,
22 SET &added, SET &common, SET &deleted ) {
25 set_difference( current.begin(), current.end(),
26 old.begin(), old.end(),
27 inserter( added, added.begin() ),
30 set_difference( old.begin(), old.end(),
31 current.begin(), current.end(),
32 inserter( deleted, deleted.begin() ),
35 set_union( current.begin(), current.end(),
36 old.begin(), old.end(),
37 inserter( common, common.begin() ),
42 // Parse the list of current files on stdin
44 populate_set( cin, current );
47 ifstream db( "test.db" );
48 populate_set( db, backed_up);
50 // Now divide the two sets into three sets (added, deleted and common )
51 file_set added, deleted, common;
52 partition_sets( current, backed_up, added, common, deleted );
54 { // This little block will copy the last_backup_date from the second set to the first
57 file_set updated_mirror;
58 set_union( current.begin(), current.end(),
59 backed_up.begin(), backed_up.end(),
60 inserter( updated_mirror, updated_mirror.begin() ),
63 // TODO Now we need to copy the last_backup_date from
64 file_set::iterator i = common.begin(), j = updated_mirror.begin();
65 for( ; i != common.end(); ++i, ++j ) {
66 (*i)->setLastBackupDate( (*j)->getLastBackupDate() );
70 // Now find the list of files to backup.
73 // backup all added files
74 copy( added.begin(), added.end(), inserter( backup_set, backup_set.begin() ) );
76 // backup common files that have changed since the last backup date.
77 for( file_set::iterator i = common.begin(); i != common.end(); ++i ) {
78 if( (*i)->getLastBackupDate() < (*i)->getModifiedDate() ) {
79 backup_set.insert( *i );
83 // Now, sort the backup_set by filesize and build a list of up to SIZE
84 file_vector backups_bysize;
85 copy( backup_set.begin(), backup_set.end(), back_inserter( backups_bysize ) );
86 FileDataSizeCmp sizecmp;
87 sort( backups_bysize.begin(), backups_bysize.end(), sizecmp );
90 unsigned long long bytes_available = 4700000000ULL; // 4.3 GBytes
92 unsigned long long block_size = 512ULL;
96 // Copy files over until full or out of files
97 file_vector::reverse_iterator i = backups_bysize.rbegin();
98 while( 0 != bytes_available && i != backups_bysize.rend() ) {
99 unsigned long long size = (*i)->getFileSize();
100 unsigned long long blocks = size & ( ~(block_size-1) );
101 if( blocks < size ) blocks += block_size;
102 if( blocks <= bytes_available ) {
103 bytes_available -= blocks;
104 final_set.insert( *i );
111 // Now, sort the non-backed-up list by last_backup_date and back-fill
112 if( 0 != bytes_available ) {
113 file_vector leftovers;
115 set_difference( current.begin(), current.end(),
116 final_set.begin(), final_set.end(),
117 back_inserter( leftovers ),
120 FileDataLastBackupCmp lastbackupcmp;
121 sort( leftovers.begin(), leftovers.end(), lastbackupcmp );
123 // Copy files over until full or out of files
124 file_vector::const_iterator j = leftovers.begin();
125 while( 0 != bytes_available && j != leftovers.end() ) {
126 unsigned long long size = (*j)->getFileSize();
127 unsigned long long blocks = size & ( ~(block_size-1) );
129 if( blocks < size ) blocks += block_size;
131 if( blocks <= bytes_available ) {
132 bytes_available -= blocks;
133 final_set.insert( *j );
139 // TODO Get 'now' from time clock
140 unsigned long long now = 20051019211200ULL;
141 for( file_set::iterator k = final_set.begin(); k != final_set.end(); ++k ) {
142 (*k)->setLastBackupDate( now );
145 // Write the 'current' list to the dbfile
146 // Write the 'final_set' list to stdout
148 // If ! finished then write a flag to /tmp
151 for( file_set::iterator i = backed_up.begin(); i != backed_up.end(); ++i ) { delete *i; }
152 for( file_set::iterator i = current.begin(); i != current.end(); ++i ) { delete *i; }