source: box/trunk/lib/raidfile/RaidFileUtil.cpp @ 2460

Revision 2460, 5.2 KB checked in by chris, 3 years ago (diff)

Fix tests (hopefully) on Win32 for struct stat ino_t change from 16 to
64 bits.

  • Property svn:eol-style set to native
Line 
1// --------------------------------------------------------------------------
2//
3// File
4//              Name:    RaidFileUtil.cpp
5//              Purpose: Utilities for raid files
6//              Created: 2003/07/11
7//
8// --------------------------------------------------------------------------
9
10#include "Box.h"
11
12#include <sys/types.h>
13#include <sys/stat.h>
14
15#include "RaidFileUtil.h"
16#include "FileModificationTime.h"
17#include "RaidFileRead.h"       // for type definition
18
19#include "MemLeakFindOn.h"
20
21
22// --------------------------------------------------------------------------
23//
24// Function
25//              Name:    RaidFileUtil::RaidFileExists(RaidFileDiscSet &,
26//                       const std::string &, int *, int *, int64_t *)
27//              Purpose: Check to see the state of a RaidFile on disc
28//                       (doesn't look at contents, just at existence of
29//                       files)
30//              Created: 2003/07/11
31//
32// --------------------------------------------------------------------------
33RaidFileUtil::ExistType RaidFileUtil::RaidFileExists(RaidFileDiscSet &rDiscSet,
34        const std::string &rFilename, int *pStartDisc, int *pExistingFiles,
35        int64_t *pRevisionID)
36{
37        if(pExistingFiles)
38        {
39                *pExistingFiles = 0;
40        }
41       
42        // For stat call, although the results are not examined
43        struct stat st;
44
45        // check various files
46        int startDisc = 0;
47        {
48                std::string writeFile(RaidFileUtil::MakeWriteFileName(rDiscSet, rFilename, &startDisc));
49                if(pStartDisc)
50                {
51                        *pStartDisc = startDisc;
52                }
53                if(::stat(writeFile.c_str(), &st) == 0)
54                {
55                        // write file exists, use that
56                       
57                        // Get unique ID
58                        if(pRevisionID != 0)
59                        {
60                                #ifdef WIN32
61                                        *pRevisionID = st.st_mtime;
62                                #else
63                                        *pRevisionID = FileModificationTime(st);
64                                #endif
65
66#ifdef BOX_RELEASE_BUILD
67                                // The resolution of timestamps may be very
68                                // low, e.g. 1 second. So add the size to it
69                                // to give a bit more chance of it changing.
70                                // TODO: Make this better.
71                                // Disabled in debug mode, to simulate
72                                // filesystem with 1-second timestamp
73                                // resolution, e.g. MacOS X HFS, Linux.
74                                (*pRevisionID) += st.st_size;
75#endif
76                        }
77                       
78                        // return non-raid file
79                        return NonRaid;
80                }
81        }
82       
83        // Now see how many of the raid components exist
84        int64_t revisionID = 0;
85        int setSize = rDiscSet.size();
86        int rfCount = 0;
87
88        // TODO: replace this with better linux revision ID detection
89        int64_t revisionIDplus = 0;
90
91        for(int f = 0; f < setSize; ++f)
92        {
93                std::string componentFile(RaidFileUtil::MakeRaidComponentName(rDiscSet, rFilename, (f + startDisc) % setSize));
94                if(::stat(componentFile.c_str(), &st) == 0)
95                {
96                        // Component file exists, add to count
97                        rfCount++;
98                        // Set flags for existance?
99                        if(pExistingFiles)
100                        {
101                                (*pExistingFiles) |= (1 << f);
102                        }
103                        // Revision ID
104                        if(pRevisionID != 0)
105                        {
106                                #ifdef WIN32
107                                        int64_t rid = st.st_mtime;
108                                #else
109                                        int64_t rid = FileModificationTime(st);
110                                #endif
111
112                                if(rid > revisionID) revisionID = rid;
113                                revisionIDplus += st.st_size;
114                        }
115                }
116        }
117        if(pRevisionID != 0)
118        {
119                (*pRevisionID) = revisionID;
120#ifdef BOX_RELEASE_BUILD
121                // The resolution of timestamps may be very low, e.g.
122                // 1 second. So add the size to it to give a bit more
123                // chance of it changing.
124                // TODO: Make this better.
125                // Disabled in debug mode, to simulate filesystem with
126                // 1-second timestamp resolution, e.g. MacOS X HFS, Linux.
127                (*pRevisionID) += revisionIDplus;
128#endif
129        }
130       
131        // Return a status based on how many parts are available
132        if(rfCount == setSize)
133        {
134                return AsRaid;
135        }
136        else if((setSize > 1) && rfCount == (setSize - 1))
137        {
138                return AsRaidWithMissingReadable;
139        }
140        else if(rfCount > 0)
141        {
142                return AsRaidWithMissingNotRecoverable;
143        }
144       
145        return NoFile;  // Obviously doesn't exist
146}
147
148
149// --------------------------------------------------------------------------
150//
151// Function
152//              Name:    RaidFileUtil::DiscUsageInBlocks(int64_t, const RaidFileDiscSet &)
153//              Purpose: Returns the size of the file in blocks, given the file size and disc set
154//              Created: 2003/09/03
155//
156// --------------------------------------------------------------------------
157int64_t RaidFileUtil::DiscUsageInBlocks(int64_t FileSize, const RaidFileDiscSet &rDiscSet)
158{
159        // Get block size
160        int blockSize = rDiscSet.GetBlockSize();
161
162        // OK... so as the size of the file is always sizes of stripe1 + stripe2, we can
163        // do a very simple calculation for the main data.
164        int64_t blocks = (FileSize + (((int64_t)blockSize) - 1)) / ((int64_t)blockSize);
165       
166        // It's just that simple calculation for non-RAID disc sets
167        if(rDiscSet.IsNonRaidSet())
168        {
169                return blocks;
170        }
171
172        // It's the parity which is mildly complex.
173        // First of all, add in size for all but the last two blocks.
174        int64_t parityblocks = (FileSize / ((int64_t)blockSize)) / 2;
175        blocks += parityblocks;
176       
177        // Work out how many bytes are left
178        int bytesOver = (int)(FileSize - (parityblocks * ((int64_t)(blockSize*2))));
179       
180        // Then... (let compiler optimise this out)
181        if(bytesOver == 0)
182        {
183                // Extra block for the size info
184                blocks++;
185        }
186        else if(bytesOver == sizeof(RaidFileRead::FileSizeType))
187        {
188                // For last block of parity, plus the size info
189                blocks += 2;
190        }
191        else if(bytesOver < blockSize)
192        {
193                // Just want the parity block
194                blocks += 1;
195        }
196        else if(bytesOver == blockSize || bytesOver >= ((blockSize*2)-((int)sizeof(RaidFileRead::FileSizeType))))
197        {
198                // Last block, plus size info
199                blocks += 2;
200        }
201        else
202        {
203                // Just want parity block
204                blocks += 1;
205        }
206       
207        return blocks;
208}
209
210
Note: See TracBrowser for help on using the repository browser.