source: box/trunk/lib/backupstore/BackupStoreAccountDatabase.cpp @ 2530

Revision 2530, 10.0 KB checked in by chris, 3 years ago (diff)

Make BackupStoreAccountDatabase::AddEntry? and
BackupStoreAccountDatabase::GetEntry? return a copy of the new entry.

  • Property svn:eol-style set to native
Line 
1// --------------------------------------------------------------------------
2//
3// File
4//              Name:    BackupStoreAccountDatabase.cpp
5//              Purpose: Database of accounts for the backup store
6//              Created: 2003/08/20
7//
8// --------------------------------------------------------------------------
9
10#include "Box.h"
11
12#include <stdlib.h>
13#include <string>
14#include <map>
15#include <stdio.h>
16#include <sys/stat.h>
17
18#include "BackupStoreAccountDatabase.h"
19#include "Guards.h"
20#include "FdGetLine.h"
21#include "BackupStoreException.h"
22#include "CommonException.h"
23#include "FileModificationTime.h"
24
25#include "MemLeakFindOn.h"
26
27class _BackupStoreAccountDatabase
28{
29public:
30        std::string mFilename;
31        std::map<int32_t, BackupStoreAccountDatabase::Entry> mDatabase;
32        box_time_t mModificationTime;
33};
34
35// --------------------------------------------------------------------------
36//
37// Function
38//              Name:    BackupStoreAccountDatabase::BackupStoreAccountDatabase(const char *)
39//              Purpose: Constructor
40//              Created: 2003/08/20
41//
42// --------------------------------------------------------------------------
43BackupStoreAccountDatabase::BackupStoreAccountDatabase(const char *Filename)
44        : pImpl(new _BackupStoreAccountDatabase)
45{
46        pImpl->mFilename = Filename;
47        pImpl->mModificationTime = 0;
48}
49
50// --------------------------------------------------------------------------
51//
52// Function
53//              Name:    BackupStoreAccountDatabase::~BackupStoreAccountDatabase()
54//              Purpose: Destructor
55//              Created: 2003/08/20
56//
57// --------------------------------------------------------------------------
58BackupStoreAccountDatabase::~BackupStoreAccountDatabase()
59{
60        delete pImpl;
61}
62
63
64// --------------------------------------------------------------------------
65//
66// Function
67//              Name:    BackupStoreAccountDatabase::Entry::Entry()
68//              Purpose: Default constructor
69//              Created: 2003/08/21
70//
71// --------------------------------------------------------------------------
72BackupStoreAccountDatabase::Entry::Entry()
73        : mID(-1),
74          mDiscSet(-1)
75{
76}
77
78// --------------------------------------------------------------------------
79//
80// Function
81//              Name:    BackupStoreAccountDatabase::Entry::Entry(int32_t, int)
82//              Purpose: Constructor
83//              Created: 2003/08/21
84//
85// --------------------------------------------------------------------------
86BackupStoreAccountDatabase::Entry::Entry(int32_t ID, int DiscSet)
87        : mID(ID),
88          mDiscSet(DiscSet)
89{
90}
91
92// --------------------------------------------------------------------------
93//
94// Function
95//              Name:    BackupStoreAccountDatabase::Entry::Entry(const Entry &)
96//              Purpose: Copy constructor
97//              Created: 2003/08/21
98//
99// --------------------------------------------------------------------------
100BackupStoreAccountDatabase::Entry::Entry(const Entry &rEntry)
101        : mID(rEntry.mID),
102          mDiscSet(rEntry.mDiscSet)
103{
104}
105
106// --------------------------------------------------------------------------
107//
108// Function
109//              Name:    BackupStoreAccountDatabase::Entry::~Entry()
110//              Purpose: Destructor
111//              Created: 2003/08/21
112//
113// --------------------------------------------------------------------------
114BackupStoreAccountDatabase::Entry::~Entry()
115{
116}
117
118// --------------------------------------------------------------------------
119//
120// Function
121//              Name:    BackupStoreAccountDatabase::Read(const char *)
122//              Purpose: Read in a database from disc
123//              Created: 2003/08/21
124//
125// --------------------------------------------------------------------------
126std::auto_ptr<BackupStoreAccountDatabase> BackupStoreAccountDatabase::Read(const char *Filename)
127{
128        // Database object to use
129        std::auto_ptr<BackupStoreAccountDatabase> db(new BackupStoreAccountDatabase(Filename));
130       
131        // Read in the file
132        db->ReadFile();
133
134        // Return to called
135        return db;
136}
137
138
139// --------------------------------------------------------------------------
140//
141// Function
142//              Name:    BackupStoreAccountDatabase::ReadFile()
143//              Purpose: Read the file off disc
144//              Created: 21/1/04
145//
146// --------------------------------------------------------------------------
147void BackupStoreAccountDatabase::ReadFile() const
148{
149        // Open file
150        FileHandleGuard<> file(pImpl->mFilename.c_str());
151
152        // Clear existing entries
153        pImpl->mDatabase.clear();
154
155        // Read in lines
156        FdGetLine getLine(file);
157       
158        while(!getLine.IsEOF())
159        {
160                // Read and split up line
161                std::string l(getLine.GetLine(true));
162
163                if(!l.empty())
164                {
165                        // Check...
166                        int32_t id;
167                        int discSet;
168                        if(::sscanf(l.c_str(), "%x:%d", &id, &discSet) != 2)
169                        {
170                                THROW_EXCEPTION(BackupStoreException, BadAccountDatabaseFile)
171                        }
172
173                        // Make a new entry
174                        pImpl->mDatabase[id] = Entry(id, discSet);
175                }
176        }
177       
178        // Store the modification time of the file
179        pImpl->mModificationTime = GetDBFileModificationTime();
180}
181
182
183// --------------------------------------------------------------------------
184//
185// Function
186//              Name:    BackupStoreAccountDatabase::CheckUpToDate()
187//              Purpose: Private. Ensure that the in memory database matches the one on disc
188//              Created: 21/1/04
189//
190// --------------------------------------------------------------------------
191void BackupStoreAccountDatabase::CheckUpToDate() const
192{
193        if(pImpl->mModificationTime != GetDBFileModificationTime())
194        {
195                // File has changed -- load it in again
196                ReadFile();
197        }
198}
199
200
201// --------------------------------------------------------------------------
202//
203// Function
204//              Name:    BackupStoreAccountDatabase::GetDBFileModificationTime()
205//              Purpose: Get the current modification time of the database
206//              Created: 21/1/04
207//
208// --------------------------------------------------------------------------
209box_time_t BackupStoreAccountDatabase::GetDBFileModificationTime() const
210{
211        EMU_STRUCT_STAT st;
212        if(EMU_STAT(pImpl->mFilename.c_str(), &st) == -1)
213        {
214                THROW_EXCEPTION(CommonException, OSFileError)
215        }
216       
217        return FileModificationTime(st);
218}
219
220
221// --------------------------------------------------------------------------
222//
223// Function
224//              Name:    BackupStoreAccountDatabase::Write()
225//              Purpose: Write the database back to disc after modifying it
226//              Created: 2003/08/21
227//
228// --------------------------------------------------------------------------
229void BackupStoreAccountDatabase::Write()
230{
231        // Open file for writing
232        // Would use this...
233        //      FileHandleGuard<O_WRONLY | O_TRUNC> file(pImpl->mFilename.c_str());
234        // but gcc fails randomly on it on some platforms. Weird.
235       
236        int file = ::open(pImpl->mFilename.c_str(), O_WRONLY | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
237        if(file == -1)
238        {
239                THROW_EXCEPTION(CommonException, OSFileOpenError)
240        }
241       
242        try
243        {
244                // Then write each entry
245                for(std::map<int32_t, BackupStoreAccountDatabase::Entry>::const_iterator i(pImpl->mDatabase.begin());
246                        i != pImpl->mDatabase.end(); ++i)
247                {
248                        // Write out the entry
249                        char line[256]; // more than enough for a couple of integers in string form
250                        int s = ::sprintf(line, "%x:%d\n", i->second.GetID(), i->second.GetDiscSet());
251                        if(::write(file, line, s) != s)
252                        {
253                                THROW_EXCEPTION(CommonException, OSFileError)
254                        }
255                }
256               
257                ::close(file);
258        }
259        catch(...)
260        {
261                ::close(file);
262                throw;
263        }
264       
265        // Done.
266}
267
268// --------------------------------------------------------------------------
269//
270// Function
271//              Name:    BackupStoreAccountDatabase::EntryExists(int32_t)
272//              Purpose: Does an entry exist in the database?
273//              Created: 2003/08/21
274//
275// --------------------------------------------------------------------------
276bool BackupStoreAccountDatabase::EntryExists(int32_t ID) const
277{
278        // Check that we're using the latest version of the database
279        CheckUpToDate();
280
281        return pImpl->mDatabase.find(ID) != pImpl->mDatabase.end();
282}
283
284// --------------------------------------------------------------------------
285//
286// Function
287//              Name:    BackupStoreAccountDatabase::GetEntry(int32_t)
288//              Purpose: Retrieve an entry
289//              Created: 2003/08/21
290//
291// --------------------------------------------------------------------------
292BackupStoreAccountDatabase::Entry BackupStoreAccountDatabase::GetEntry(
293        int32_t ID) const
294{
295        // Check that we're using the latest version of the database
296        CheckUpToDate();
297
298        std::map<int32_t, BackupStoreAccountDatabase::Entry>::const_iterator i(pImpl->mDatabase.find(ID));
299        if(i == pImpl->mDatabase.end())
300        {
301                THROW_EXCEPTION(BackupStoreException, AccountDatabaseNoSuchEntry)
302        }
303       
304        return i->second;
305}
306
307// --------------------------------------------------------------------------
308//
309// Function
310//              Name:    BackupStoreAccountDatabase::AddEntry(int32_t, int)
311//              Purpose: Add a new entry to the database
312//              Created: 2003/08/21
313//
314// --------------------------------------------------------------------------
315BackupStoreAccountDatabase::Entry BackupStoreAccountDatabase::AddEntry(
316        int32_t ID, int DiscSet)
317{
318        // Check that we're using the latest version of the database
319        CheckUpToDate();
320
321        pImpl->mDatabase[ID] = Entry(ID, DiscSet);
322        return pImpl->mDatabase[ID];
323}
324
325
326// --------------------------------------------------------------------------
327//
328// Function
329//              Name:    BackupStoreAccountDatabase::DeleteEntry(int32_t)
330//              Purpose: Delete an entry from the database
331//              Created: 2003/08/21
332//
333// --------------------------------------------------------------------------
334void BackupStoreAccountDatabase::DeleteEntry(int32_t ID)
335{
336        // Check that we're using the latest version of the database
337        CheckUpToDate();
338
339        std::map<int32_t, BackupStoreAccountDatabase::Entry>::iterator i(pImpl->mDatabase.find(ID));
340        if(i == pImpl->mDatabase.end())
341        {
342                THROW_EXCEPTION(BackupStoreException, AccountDatabaseNoSuchEntry)
343        }
344
345        pImpl->mDatabase.erase(i);
346}
347
348// --------------------------------------------------------------------------
349//
350// Function
351//              Name:    BackupStoreAccountDatabase::GetAllAccountIDs(std::vector<int32_t>)
352//              Purpose:
353//              Created: 11/12/03
354//
355// --------------------------------------------------------------------------
356void BackupStoreAccountDatabase::GetAllAccountIDs(std::vector<int32_t> &rIDsOut)
357{
358        // Check that we're using the latest version of the database
359        CheckUpToDate();
360
361        // Delete everything in the output list
362        rIDsOut.clear();
363
364        std::map<int32_t, BackupStoreAccountDatabase::Entry>::iterator i(pImpl->mDatabase.begin());
365        for(; i != pImpl->mDatabase.end(); ++i)
366        {
367                rIDsOut.push_back(i->first);
368        }
369}
370
371
372
373
Note: See TracBrowser for help on using the repository browser.