source: box/trunk/lib/backupstore/BackupStoreDirectory.cpp @ 3068

Revision 3068, 15.5 KB checked in by chris, 4 months ago (diff)

Rename the BackupStoreDirectory::AddEntry?'s AttributesModTime? parameter to AttributesHash? to avoid misleading the reader.

  • Property svn:eol-style set to native
Line 
1// --------------------------------------------------------------------------
2//
3// File
4//              Name:    BackupStoreDirectory.h
5//              Purpose: Representation of a backup directory
6//              Created: 2003/08/26
7//
8// --------------------------------------------------------------------------
9
10#include "Box.h"
11
12#include <sys/types.h>
13
14#include "BackupStoreDirectory.h"
15#include "IOStream.h"
16#include "BackupStoreException.h"
17#include "BackupStoreObjectMagic.h"
18
19#include "MemLeakFindOn.h"
20
21// set packing to one byte
22#ifdef STRUCTURE_PACKING_FOR_WIRE_USE_HEADERS
23#include "BeginStructPackForWire.h"
24#else
25BEGIN_STRUCTURE_PACKING_FOR_WIRE
26#endif
27
28typedef struct
29{
30        int32_t mMagicValue;    // also the version number
31        int32_t mNumEntries;
32        int64_t mObjectID;              // this object ID
33        int64_t mContainerID;   // ID of container
34        uint64_t mAttributesModTime;
35        int32_t mOptionsPresent;        // bit mask of optional sections / features present
36        // Then a StreamableMemBlock for attributes
37} dir_StreamFormat;
38
39typedef enum
40{
41        Option_DependencyInfoPresent = 1
42} dir_StreamFormatOptions;
43
44typedef struct
45{
46        uint64_t mModificationTime;
47        int64_t mObjectID;
48        int64_t mSizeInBlocks;
49        uint64_t mAttributesHash;
50        int16_t mFlags;                         // order smaller items after bigger ones (for alignment)
51        // Then a BackupStoreFilename
52        // Then a StreamableMemBlock for attributes
53} en_StreamFormat;
54
55typedef struct
56{
57        int64_t mDependsNewer;
58        int64_t mDependsOlder;
59} en_StreamFormatDepends;
60
61// Use default packing
62#ifdef STRUCTURE_PACKING_FOR_WIRE_USE_HEADERS
63#include "EndStructPackForWire.h"
64#else
65END_STRUCTURE_PACKING_FOR_WIRE
66#endif
67
68
69// --------------------------------------------------------------------------
70//
71// Function
72//              Name:    BackupStoreDirectory::BackupStoreDirectory()
73//              Purpose: Constructor
74//              Created: 2003/08/26
75//
76// --------------------------------------------------------------------------
77BackupStoreDirectory::BackupStoreDirectory()
78        : mRevisionID(0), mObjectID(0), mContainerID(0), mAttributesModTime(0), mUserInfo1(0)
79{
80        ASSERT(sizeof(u_int64_t) == sizeof(box_time_t));
81}
82
83
84// --------------------------------------------------------------------------
85//
86// File
87//              Name:    BackupStoreDirectory::BackupStoreDirectory(int64_t, int64_t)
88//              Purpose: Constructor giving object and container IDs
89//              Created: 2003/08/28
90//
91// --------------------------------------------------------------------------
92BackupStoreDirectory::BackupStoreDirectory(int64_t ObjectID, int64_t ContainerID)
93        : mRevisionID(0), mObjectID(ObjectID), mContainerID(ContainerID), mAttributesModTime(0), mUserInfo1(0)
94{
95}
96
97
98// --------------------------------------------------------------------------
99//
100// Function
101//              Name:    BackupStoreDirectory::~BackupStoreDirectory()
102//              Purpose: Destructor
103//              Created: 2003/08/26
104//
105// --------------------------------------------------------------------------
106BackupStoreDirectory::~BackupStoreDirectory()
107{
108        for(std::vector<Entry*>::iterator i(mEntries.begin()); i != mEntries.end(); ++i)
109        {
110                delete (*i);
111        }
112}
113
114// --------------------------------------------------------------------------
115//
116// Function
117//              Name:    BackupStoreDirectory::ReadFromStream(IOStream &, int)
118//              Purpose: Reads the directory contents from a stream.
119//                       Exceptions will result in incomplete reads.
120//              Created: 2003/08/26
121//
122// --------------------------------------------------------------------------
123void BackupStoreDirectory::ReadFromStream(IOStream &rStream, int Timeout)
124{
125        // Get the header
126        dir_StreamFormat hdr;
127        if(!rStream.ReadFullBuffer(&hdr, sizeof(hdr), 0 /* not interested in bytes read if this fails */, Timeout))
128        {
129                THROW_EXCEPTION(BackupStoreException, CouldntReadEntireStructureFromStream)
130        }
131
132        // Check magic value...
133        if(OBJECTMAGIC_DIR_MAGIC_VALUE != ntohl(hdr.mMagicValue))
134        {
135                THROW_EXCEPTION_MESSAGE(BackupStoreException, BadDirectoryFormat,
136                        "Wrong magic number in directory object " << 
137                        BOX_FORMAT_OBJECTID(mObjectID) << ": expected " <<
138                        BOX_FORMAT_HEX32(OBJECTMAGIC_DIR_MAGIC_VALUE) <<
139                        " but found " <<
140                        BOX_FORMAT_HEX32(ntohl(hdr.mMagicValue)));
141        }
142       
143        // Get data
144        mObjectID = box_ntoh64(hdr.mObjectID);
145        mContainerID = box_ntoh64(hdr.mContainerID);
146        mAttributesModTime = box_ntoh64(hdr.mAttributesModTime);
147       
148        // Options
149        int32_t options = ntohl(hdr.mOptionsPresent);
150       
151        // Get attributes
152        mAttributes.ReadFromStream(rStream, Timeout);
153       
154        // Decode count
155        int count = ntohl(hdr.mNumEntries);
156       
157        // Clear existing list
158        for(std::vector<Entry*>::iterator i = mEntries.begin(); 
159                i != mEntries.end(); i++)
160        {
161                delete (*i);
162        }
163        mEntries.clear();
164       
165        // Read them in!
166        for(int c = 0; c < count; ++c)
167        {
168                Entry *pen = new Entry;
169                try
170                {
171                        // Read from stream
172                        pen->ReadFromStream(rStream, Timeout);
173                       
174                        // Add to list
175                        mEntries.push_back(pen);
176                }
177                catch(...)
178                {
179                        delete pen;
180                        throw;
181                }
182        }
183       
184        // Read in dependency info?
185        if(options & Option_DependencyInfoPresent)
186        {
187                // Read in extra dependency data
188                for(int c = 0; c < count; ++c)
189                {
190                        mEntries[c]->ReadFromStreamDependencyInfo(rStream, Timeout);
191                }
192        }
193}
194
195// --------------------------------------------------------------------------
196//
197// Function
198//              Name:    BackupStoreDirectory::WriteToStream(IOStream &, int16_t, int16_t, bool, bool)
199//              Purpose: Writes a selection of entries to a stream
200//              Created: 2003/08/26
201//
202// --------------------------------------------------------------------------
203void BackupStoreDirectory::WriteToStream(IOStream &rStream, int16_t FlagsMustBeSet, int16_t FlagsNotToBeSet, bool StreamAttributes, bool StreamDependencyInfo) const
204{
205        // Get count of entries
206        int32_t count = mEntries.size();
207        if(FlagsMustBeSet != Entry::Flags_INCLUDE_EVERYTHING || FlagsNotToBeSet != Entry::Flags_EXCLUDE_NOTHING)
208        {
209                // Need to count the entries
210                count = 0;
211                Iterator i(*this);
212                while(i.Next(FlagsMustBeSet, FlagsNotToBeSet) != 0)
213                {
214                        count++;
215                }
216        }
217       
218        // Check that sensible IDs have been set
219        ASSERT(mObjectID != 0);
220        ASSERT(mContainerID != 0);
221       
222        // Need dependency info?
223        bool dependencyInfoRequired = false;
224        if(StreamDependencyInfo)
225        {
226                Iterator i(*this);
227                Entry *pen = 0;
228                while((pen = i.Next(FlagsMustBeSet, FlagsNotToBeSet)) != 0)
229                {
230                        if(pen->HasDependencies())
231                        {
232                                dependencyInfoRequired = true;
233                        }
234                }       
235        }
236       
237        // Options
238        int32_t options = 0;
239        if(dependencyInfoRequired) options |= Option_DependencyInfoPresent;
240
241        // Build header
242        dir_StreamFormat hdr;
243        hdr.mMagicValue = htonl(OBJECTMAGIC_DIR_MAGIC_VALUE);
244        hdr.mNumEntries = htonl(count);
245        hdr.mObjectID = box_hton64(mObjectID);
246        hdr.mContainerID = box_hton64(mContainerID);
247        hdr.mAttributesModTime = box_hton64(mAttributesModTime);
248        hdr.mOptionsPresent = htonl(options);
249       
250        // Write header
251        rStream.Write(&hdr, sizeof(hdr));
252       
253        // Write the attributes?
254        if(StreamAttributes)
255        {
256                mAttributes.WriteToStream(rStream);
257        }
258        else
259        {
260                // Write a blank header instead
261                StreamableMemBlock::WriteEmptyBlockToStream(rStream);
262        }
263
264        // Then write all the entries
265        Iterator i(*this);
266        Entry *pen = 0;
267        while((pen = i.Next(FlagsMustBeSet, FlagsNotToBeSet)) != 0)
268        {
269                pen->WriteToStream(rStream);
270        }
271       
272        // Write dependency info?
273        if(dependencyInfoRequired)
274        {
275                Iterator i(*this);
276                Entry *pen = 0;
277                while((pen = i.Next(FlagsMustBeSet, FlagsNotToBeSet)) != 0)
278                {
279                        pen->WriteToStreamDependencyInfo(rStream);
280                }       
281        }
282}
283
284// --------------------------------------------------------------------------
285//
286// Function
287//              Name:    BackupStoreDirectory::AddEntry(const Entry &)
288//              Purpose: Adds entry to directory (no checking)
289//              Created: 2003/08/27
290//
291// --------------------------------------------------------------------------
292BackupStoreDirectory::Entry *BackupStoreDirectory::AddEntry(const Entry &rEntryToCopy)
293{
294        Entry *pnew = new Entry(rEntryToCopy);
295        try
296        {
297                mEntries.push_back(pnew);
298        }
299        catch(...)
300        {
301                delete pnew;
302                throw;
303        }
304       
305        return pnew;
306}
307
308// --------------------------------------------------------------------------
309//
310// Function
311//              Name:    BackupStoreDirectory::AddEntry(const BackupStoreFilename &, int64_t, int64_t, int16_t)
312//              Purpose: Adds entry to directory (no checking)
313//              Created: 2003/08/27
314//
315// --------------------------------------------------------------------------
316BackupStoreDirectory::Entry *
317BackupStoreDirectory::AddEntry(const BackupStoreFilename &rName,
318        box_time_t ModificationTime, int64_t ObjectID, int64_t SizeInBlocks,
319        int16_t Flags, uint64_t AttributesHash)
320{
321        Entry *pnew = new Entry(rName, ModificationTime, ObjectID,
322                SizeInBlocks, Flags, AttributesHash);
323        try
324        {
325                mEntries.push_back(pnew);
326        }
327        catch(...)
328        {
329                delete pnew;
330                throw;
331        }
332       
333        return pnew;
334}
335
336// --------------------------------------------------------------------------
337//
338// Function
339//              Name:    BackupStoreDirectory::DeleteEntry(int64_t)
340//              Purpose: Deletes entry with given object ID (uses linear search, maybe a little inefficient)
341//              Created: 2003/08/27
342//
343// --------------------------------------------------------------------------
344void BackupStoreDirectory::DeleteEntry(int64_t ObjectID)
345{
346        for(std::vector<Entry*>::iterator i(mEntries.begin());
347                i != mEntries.end(); ++i)
348        {
349                if((*i)->mObjectID == ObjectID)
350                {
351                        // Delete
352                        delete (*i);
353                        // Remove from list
354                        mEntries.erase(i);
355                        // Done
356                        return;
357                }
358        }
359       
360        // Not found
361        THROW_EXCEPTION(BackupStoreException, CouldNotFindEntryInDirectory)
362}
363
364
365// --------------------------------------------------------------------------
366//
367// Function
368//              Name:    BackupStoreDirectory::FindEntryByID(int64_t)
369//              Purpose: Finds a specific entry. Returns 0 if the entry doesn't exist.
370//              Created: 12/11/03
371//
372// --------------------------------------------------------------------------
373BackupStoreDirectory::Entry *BackupStoreDirectory::FindEntryByID(int64_t ObjectID) const
374{
375        for(std::vector<Entry*>::const_iterator i(mEntries.begin());
376                i != mEntries.end(); ++i)
377        {
378                if((*i)->mObjectID == ObjectID)
379                {
380                        // Found
381                        return (*i);
382                }
383        }
384
385        // Not found
386        return 0;
387}
388
389
390// --------------------------------------------------------------------------
391//
392// Function
393//              Name:    BackupStoreDirectory::Entry::Entry()
394//              Purpose: Constructor
395//              Created: 2003/08/26
396//
397// --------------------------------------------------------------------------
398BackupStoreDirectory::Entry::Entry()
399        : mModificationTime(0),
400          mObjectID(0),
401          mSizeInBlocks(0),
402          mFlags(0),
403          mAttributesHash(0),
404          mMinMarkNumber(0),
405          mMarkNumber(0),
406          mDependsNewer(0),
407          mDependsOlder(0)
408{
409}
410
411// --------------------------------------------------------------------------
412//
413// Function
414//              Name:    BackupStoreDirectory::Entry::~Entry()
415//              Purpose: Destructor
416//              Created: 2003/08/26
417//
418// --------------------------------------------------------------------------
419BackupStoreDirectory::Entry::~Entry()
420{
421}
422
423// --------------------------------------------------------------------------
424//
425// Function
426//              Name:    BackupStoreDirectory::Entry::Entry(const Entry &)
427//              Purpose: Copy constructor
428//              Created: 2003/08/26
429//
430// --------------------------------------------------------------------------
431BackupStoreDirectory::Entry::Entry(const Entry &rToCopy)
432        : mName(rToCopy.mName),
433          mModificationTime(rToCopy.mModificationTime),
434          mObjectID(rToCopy.mObjectID),
435          mSizeInBlocks(rToCopy.mSizeInBlocks),
436          mFlags(rToCopy.mFlags),
437          mAttributesHash(rToCopy.mAttributesHash),
438          mAttributes(rToCopy.mAttributes),
439          mMinMarkNumber(rToCopy.mMinMarkNumber),
440          mMarkNumber(rToCopy.mMarkNumber),
441          mDependsNewer(rToCopy.mDependsNewer),
442          mDependsOlder(rToCopy.mDependsOlder)
443{
444}
445
446
447// --------------------------------------------------------------------------
448//
449// Function
450//              Name:    BackupStoreDirectory::Entry::Entry(const BackupStoreFilename &, int64_t, int64_t, int16_t)
451//              Purpose: Constructor from values
452//              Created: 2003/08/27
453//
454// --------------------------------------------------------------------------
455BackupStoreDirectory::Entry::Entry(const BackupStoreFilename &rName, box_time_t ModificationTime, int64_t ObjectID, int64_t SizeInBlocks, int16_t Flags, uint64_t AttributesHash)
456        : mName(rName),
457          mModificationTime(ModificationTime),
458          mObjectID(ObjectID),
459          mSizeInBlocks(SizeInBlocks),
460          mFlags(Flags),
461          mAttributesHash(AttributesHash),
462          mMinMarkNumber(0),
463          mMarkNumber(0),
464          mDependsNewer(0),
465          mDependsOlder(0)
466{
467}
468
469
470
471// --------------------------------------------------------------------------
472//
473// Function
474//              Name:    BackupStoreDirectory::Entry::TryReading(IOStream &, int)
475//              Purpose: Read an entry from a stream
476//              Created: 2003/08/26
477//
478// --------------------------------------------------------------------------
479void BackupStoreDirectory::Entry::ReadFromStream(IOStream &rStream, int Timeout)
480{
481        // Grab the raw bytes from the stream which compose the header
482        en_StreamFormat entry;
483        if(!rStream.ReadFullBuffer(&entry, sizeof(entry), 0 /* not interested in bytes read if this fails */, Timeout))
484        {
485                THROW_EXCEPTION(BackupStoreException, CouldntReadEntireStructureFromStream)
486        }
487
488        // Do reading first before modifying the variables, to be more exception safe
489       
490        // Get the filename
491        BackupStoreFilename name;
492        name.ReadFromStream(rStream, Timeout);
493       
494        // Get the attributes
495        mAttributes.ReadFromStream(rStream, Timeout);
496
497        // Store the rest of the bits
498        mModificationTime =             box_ntoh64(entry.mModificationTime);
499        mObjectID =                     box_ntoh64(entry.mObjectID);
500        mSizeInBlocks =                 box_ntoh64(entry.mSizeInBlocks);
501        mAttributesHash =               box_ntoh64(entry.mAttributesHash);
502        mFlags =                                ntohs(entry.mFlags);
503        mName =                                 name;
504}
505
506
507// --------------------------------------------------------------------------
508//
509// Function
510//              Name:    BackupStoreDirectory::Entry::WriteToStream(IOStream &)
511//              Purpose: Writes the entry to a stream
512//              Created: 2003/08/26
513//
514// --------------------------------------------------------------------------
515void BackupStoreDirectory::Entry::WriteToStream(IOStream &rStream) const
516{
517        // Build a structure
518        en_StreamFormat entry;
519        entry.mModificationTime =       box_hton64(mModificationTime);
520        entry.mObjectID =                       box_hton64(mObjectID);
521        entry.mSizeInBlocks =           box_hton64(mSizeInBlocks);
522        entry.mAttributesHash =         box_hton64(mAttributesHash);
523        entry.mFlags =                          htons(mFlags);
524       
525        // Write it
526        rStream.Write(&entry, sizeof(entry));
527       
528        // Write the filename
529        mName.WriteToStream(rStream);
530       
531        // Write any attributes
532        mAttributes.WriteToStream(rStream);
533}
534
535
536// --------------------------------------------------------------------------
537//
538// Function
539//              Name:    BackupStoreDirectory::Entry::ReadFromStreamDependencyInfo(IOStream &, int)
540//              Purpose: Read the optional dependency info from a stream
541//              Created: 13/7/04
542//
543// --------------------------------------------------------------------------
544void BackupStoreDirectory::Entry::ReadFromStreamDependencyInfo(IOStream &rStream, int Timeout)
545{
546        // Grab the raw bytes from the stream which compose the header
547        en_StreamFormatDepends depends;
548        if(!rStream.ReadFullBuffer(&depends, sizeof(depends), 0 /* not interested in bytes read if this fails */, Timeout))
549        {
550                THROW_EXCEPTION(BackupStoreException, CouldntReadEntireStructureFromStream)
551        }
552
553        // Store the data
554        mDependsNewer = box_ntoh64(depends.mDependsNewer);
555        mDependsOlder = box_ntoh64(depends.mDependsOlder);
556}
557
558
559// --------------------------------------------------------------------------
560//
561// Function
562//              Name:    BackupStoreDirectory::Entry::WriteToStreamDependencyInfo(IOStream &)
563//              Purpose: Write the optional dependency info to a stream
564//              Created: 13/7/04
565//
566// --------------------------------------------------------------------------
567void BackupStoreDirectory::Entry::WriteToStreamDependencyInfo(IOStream &rStream) const
568{
569        // Build structure
570        en_StreamFormatDepends depends; 
571        depends.mDependsNewer = box_hton64(mDependsNewer);
572        depends.mDependsOlder = box_hton64(mDependsOlder);
573        // Write
574        rStream.Write(&depends, sizeof(depends));
575}
576
577
578
Note: See TracBrowser for help on using the repository browser.