1 // **********************************************************************
3 // Copyright (c) 2003-2011 ZeroC, Inc. All rights reserved.
5 // This copy of Ice is licensed to you under the terms described in the
6 // ICE_LICENSE file included in this distribution.
8 // **********************************************************************
10 #include <Ice/Communicator.h>
11 #include <Ice/Properties.h>
13 #include <IceUtil/FileUtil.h>
15 #include <IceGrid/FileCache.h>
16 #include <IceGrid/Exception.h>
21 using namespace IceGrid
;
23 FileCache::FileCache(const Ice::CommunicatorPtr
& com
) :
24 _messageSizeMax(com
->getProperties()->getPropertyAsIntWithDefault("Ice.MessageSizeMax", 1024) * 1024 - 256)
29 FileCache::getOffsetFromEnd(const string
& file
, int originalCount
)
31 IceUtilInternal::ifstream
is(file
); // file is a UTF-8 string
34 throw FileNotAvailableException("failed to open file `" + file
+ "'");
42 is
.seekg(0, ios::end
);
43 streampos endOfFile
= is
.tellg();
44 if(originalCount
== 0)
49 streamoff blockSize
= 16 * 1024; // Start reading a block of 16K from the end of the file.
50 streampos lastBlockOffset
= endOfFile
;
53 deque
<pair
<streampos
, string
> > lines
;
59 // Move the current position of the stream to the new block to
63 if(lastBlockOffset
- blockSize
> streamoff(0))
65 is
.seekg(lastBlockOffset
- blockSize
);
66 getline(is
, line
); // Ignore the first line as it's most likely not complete.
70 is
.seekg(0, ios::beg
); // We've reach the begining of the file.
74 // Read the block and count the number of lines in the block
75 // If we found the "first last N lines", we start throwing out
76 // the lines read at the begining of the file.
78 int count
= originalCount
- totalCount
; // Number of lines left to find.
79 while(is
.good() && is
.tellg() <= streamoff(lastBlockOffset
))
81 streampos beg
= is
.tellg();
83 if(is
.eof() && line
.empty()) // Don't count the last line if it's empty.
88 lines
.push_back(make_pair(beg
, line
));
90 if(lines
.size() == static_cast<unsigned int>(count
+ 1))
97 if(lastBlockOffset
- blockSize
< streamoff(0))
99 break; // We're done if the block started at the begining of the file.
101 else if(totalCount
< originalCount
)
104 // Otherwise, it we still didn't find the required number of lines,
105 // read another block of text before this block.
107 lastBlockOffset
-= blockSize
; // Position of the block we just read.
108 blockSize
*= 2; // Read a bigger block.
111 while(totalCount
< originalCount
&& !is
.bad());
115 throw FileNotAvailableException("unrecoverable error occured while reading file `" + file
+ "'");
124 return lines
[0].first
;
129 FileCache::read(const string
& file
, Ice::Long offset
, int size
, Ice::Long
& newOffset
, Ice::StringSeq
& lines
)
133 if(size
> _messageSizeMax
)
135 size
= _messageSizeMax
;
140 throw FileNotAvailableException("maximum bytes per read request is too low");
143 IceUtilInternal::ifstream
is(file
); // file is a UTF-8 string
146 throw FileNotAvailableException("failed to open file `" + file
+ "'");
150 // Check if the requested offset is past the end of the file, if
151 // that's the case return an empty sequence of lines and indicate
154 is
.seekg(0, ios::end
);
155 if(offset
>= is
.tellg())
157 newOffset
= is
.tellg();
158 lines
= Ice::StringSeq();
163 // Read lines from the file until we read enough or reached EOF.
166 lines
= Ice::StringSeq();
167 #if defined(_MSC_VER) && (_MSC_VER < 1300)
168 is
.seekg(static_cast<int>(offset
));
170 is
.seekg(static_cast<streamoff
>(offset
), ios::beg
);
175 for(int i
= 0; is
.good(); ++i
)
179 int lineSize
= static_cast<int>(line
.size()) + 5; // 5 bytes for the encoding of the string size (worst case)
180 if(lineSize
+ totalSize
> size
)
182 if(totalSize
+ 5 < size
)
184 // There's some room left for a part of the string, return a partial string
185 line
= line
.substr(0, size
- totalSize
- 5);
186 lines
.push_back(line
);
187 newOffset
+= line
.size();
193 return false; // We didn't reach the end of file, we've just reached the size limit!
196 totalSize
+= lineSize
;
197 lines
.push_back(line
);
198 #if defined(_MSC_VER) && (_MSC_VER < 1300)
201 newOffset
+= line
.size();
208 newOffset
= is
.tellg();
214 throw FileNotAvailableException("unrecoverable error occured while reading file `" + file
+ "'");