root/OpenSceneGraph/trunk/src/osgDB/FileCache.cpp @ 13041

Revision 13041, 18.4 kB (checked in by robert, 2 years ago)

Ran script to remove trailing spaces and tabs

  • Property svn:eol-style set to native
Line 
1/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield
2 *
3 * This library is open source and may be redistributed and/or modified under
4 * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
5 * (at your option) any later version.  The full license is in LICENSE file
6 * included with this distribution, and on the openscenegraph.org website.
7 *
8 * This library is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11 * OpenSceneGraph Public License for more details.
12*/
13
14#include <osgDB/FileCache>
15#include <osgDB/FileUtils>
16#include <osgDB/FileNameUtils>
17#include <osgDB/ReadFile>
18#include <osgDB/WriteFile>
19
20using namespace osgDB;
21
22////////////////////////////////////////////////////////////////////////////////////////////
23//
24// FileCache
25//
26FileCache::FileCache(const std::string& path):
27    osg::Referenced(true),
28    _fileCachePath(path)
29{
30    OSG_INFO<<"Constructed FileCache : "<<path<<std::endl;
31}
32
33FileCache::~FileCache()
34{
35    OSG_INFO<<"Destructed FileCache "<<std::endl;
36}
37
38bool FileCache::isFileAppropriateForFileCache(const std::string& originalFileName) const
39{
40    return osgDB::containsServerAddress(originalFileName);
41}
42
43std::string FileCache::createCacheFileName(const std::string& originalFileName) const
44{
45    std::string serverAddress = osgDB::getServerAddress(originalFileName);
46    std::string cacheFileName = _fileCachePath + "/" +
47                                serverAddress + (serverAddress.empty()?"":"/") +
48                                osgDB::getServerFileName(originalFileName);
49
50    OSG_INFO<<"FileCache::createCacheFileName("<<originalFileName<<") = "<<cacheFileName<<std::endl;
51
52    return cacheFileName;
53}
54
55bool FileCache::existsInCache(const std::string& originalFileName) const
56{
57    if (osgDB::fileExists(createCacheFileName(originalFileName)))
58    {
59        return !isCachedFileBlackListed(originalFileName);
60    }
61    return false;
62}
63
64ReaderWriter::ReadResult FileCache::readObject(const std::string& originalFileName, const osgDB::Options* options) const
65{
66    std::string cacheFileName = createCacheFileName(originalFileName);
67    if (!cacheFileName.empty() && osgDB::fileExists(cacheFileName))
68    {
69        OSG_INFO<<"FileCache::readObjectFromCache("<<originalFileName<<") as "<<cacheFileName<<std::endl;
70        return osgDB::Registry::instance()->readObject(cacheFileName, options);
71    }
72    else
73    {
74        return 0;
75    }
76}
77
78ReaderWriter::WriteResult FileCache::writeObject(const osg::Object& object, const std::string& originalFileName, const osgDB::Options* options) const
79{
80    std::string cacheFileName = createCacheFileName(originalFileName);
81    if (!cacheFileName.empty())
82    {
83        std::string path = osgDB::getFilePath(cacheFileName);
84
85        if (!osgDB::fileExists(path) && !osgDB::makeDirectory(path))
86        {
87            OSG_NOTICE<<"Could not create cache directory: "<<path<<std::endl;
88            return ReaderWriter::WriteResult::ERROR_IN_WRITING_FILE;
89        }
90
91        OSG_INFO<<"FileCache::writeObjectToCache("<<originalFileName<<") as "<<cacheFileName<<std::endl;
92        ReaderWriter::WriteResult result = osgDB::Registry::instance()->writeObject(object, cacheFileName, options);
93        if (result.success())
94        {
95            removeFileFromBlackListed(originalFileName);
96        }
97        return result;
98    }
99    return ReaderWriter::WriteResult::FILE_NOT_HANDLED;
100}
101
102ReaderWriter::ReadResult FileCache::readImage(const std::string& originalFileName, const osgDB::Options* options) const
103{
104    std::string cacheFileName = createCacheFileName(originalFileName);
105    if (!cacheFileName.empty() && osgDB::fileExists(cacheFileName))
106    {
107        OSG_INFO<<"FileCache::readImageFromCache("<<originalFileName<<") as "<<cacheFileName<<std::endl;
108        return osgDB::Registry::instance()->readImage(cacheFileName, options);
109    }
110    else
111    {
112        return 0;
113    }
114}
115
116ReaderWriter::WriteResult FileCache::writeImage(const osg::Image& image, const std::string& originalFileName, const osgDB::Options* options) const
117{
118    std::string cacheFileName = createCacheFileName(originalFileName);
119    if (!cacheFileName.empty())
120    {
121        std::string path = osgDB::getFilePath(cacheFileName);
122
123        if (!osgDB::fileExists(path) && !osgDB::makeDirectory(path))
124        {
125            OSG_NOTICE<<"Could not create cache directory: "<<path<<std::endl;
126            return ReaderWriter::WriteResult::ERROR_IN_WRITING_FILE;
127        }
128
129        OSG_INFO<<"FileCache::writeImageToCache("<<originalFileName<<") as "<<cacheFileName<<std::endl;
130        ReaderWriter::WriteResult result = osgDB::Registry::instance()->writeImage(image, cacheFileName, options);
131        if (result.success())
132        {
133            removeFileFromBlackListed(originalFileName);
134        }
135        return result;
136    }
137    return ReaderWriter::WriteResult::FILE_NOT_HANDLED;
138}
139
140ReaderWriter::ReadResult FileCache::readHeightField(const std::string& originalFileName, const osgDB::Options* options) const
141{
142    std::string cacheFileName = createCacheFileName(originalFileName);
143    if (!cacheFileName.empty() && osgDB::fileExists(cacheFileName))
144    {
145        OSG_INFO<<"FileCache::readHeightFieldFromCache("<<originalFileName<<") as "<<cacheFileName<<std::endl;
146        return osgDB::Registry::instance()->readHeightField(cacheFileName, options);
147    }
148    else
149    {
150        return 0;
151    }
152}
153
154ReaderWriter::WriteResult FileCache::writeHeightField(const osg::HeightField& hf, const std::string& originalFileName, const osgDB::Options* options) const
155{
156    std::string cacheFileName = createCacheFileName(originalFileName);
157    if (!cacheFileName.empty())
158    {
159        std::string path = osgDB::getFilePath(cacheFileName);
160
161        if (!osgDB::fileExists(path) && !osgDB::makeDirectory(path))
162        {
163            OSG_NOTICE<<"Could not create cache directory: "<<path<<std::endl;
164            return ReaderWriter::WriteResult::ERROR_IN_WRITING_FILE;
165        }
166
167        OSG_INFO<<"FileCache::writeHeightFieldToCache("<<originalFileName<<") as "<<cacheFileName<<std::endl;
168        ReaderWriter::WriteResult result = osgDB::Registry::instance()->writeHeightField(hf, cacheFileName, options);
169        if (result.success())
170        {
171            removeFileFromBlackListed(originalFileName);
172        }
173        return result;
174    }
175    return ReaderWriter::WriteResult::FILE_NOT_HANDLED;
176}
177
178ReaderWriter::ReadResult FileCache::readNode(const std::string& originalFileName, const osgDB::Options* options, bool buildKdTreeIfRequired) const
179{
180    std::string cacheFileName = createCacheFileName(originalFileName);
181    if (!cacheFileName.empty() && osgDB::fileExists(cacheFileName))
182    {
183        OSG_INFO<<"FileCache::readNodeFromCache("<<originalFileName<<") as "<<cacheFileName<<std::endl;
184        return osgDB::Registry::instance()->readNode(cacheFileName, options, buildKdTreeIfRequired);
185    }
186    else
187    {
188        return 0;
189    }
190}
191
192ReaderWriter::WriteResult FileCache::writeNode(const osg::Node& node, const std::string& originalFileName, const osgDB::Options* options) const
193{
194    std::string cacheFileName = createCacheFileName(originalFileName);
195    if (!cacheFileName.empty())
196    {
197        std::string path = osgDB::getFilePath(cacheFileName);
198
199        if (!osgDB::fileExists(path) && !osgDB::makeDirectory(path))
200        {
201            OSG_NOTICE<<"Could not create cache directory: "<<path<<std::endl;
202            return ReaderWriter::WriteResult::ERROR_IN_WRITING_FILE;
203        }
204
205        OSG_INFO<<"FileCache::writeNodeToCache("<<originalFileName<<") as "<<cacheFileName<<std::endl;
206        ReaderWriter::WriteResult result = osgDB::Registry::instance()->writeNode(node, cacheFileName, options);
207        if (result.success())
208        {
209            removeFileFromBlackListed(originalFileName);
210        }
211        return result;
212    }
213    return ReaderWriter::WriteResult::FILE_NOT_HANDLED;
214}
215
216
217ReaderWriter::ReadResult FileCache::readShader(const std::string& originalFileName, const osgDB::Options* options) const
218{
219    std::string cacheFileName = createCacheFileName(originalFileName);
220    if (!cacheFileName.empty() && osgDB::fileExists(cacheFileName))
221    {
222        OSG_INFO<<"FileCache::readShaderFromCache("<<originalFileName<<") as "<<cacheFileName<<std::endl;
223        return osgDB::Registry::instance()->readShader(cacheFileName, options);
224    }
225    else
226    {
227        return 0;
228    }
229}
230
231ReaderWriter::WriteResult FileCache::writeShader(const osg::Shader& shader, const std::string& originalFileName, const osgDB::Options* options) const
232{
233    std::string cacheFileName = createCacheFileName(originalFileName);
234    if (!cacheFileName.empty())
235    {
236        std::string path = osgDB::getFilePath(cacheFileName);
237
238        if (!osgDB::fileExists(path) && !osgDB::makeDirectory(path))
239        {
240            OSG_NOTICE<<"Could not create cache directory: "<<path<<std::endl;
241            return ReaderWriter::WriteResult::ERROR_IN_WRITING_FILE;
242        }
243
244        OSG_INFO<<"FileCache::writeShaderToCache("<<originalFileName<<") as "<<cacheFileName<<std::endl;
245        ReaderWriter::WriteResult result = osgDB::Registry::instance()->writeShader(shader, cacheFileName, options);
246        if (result.success())
247        {
248            removeFileFromBlackListed(originalFileName);
249        }
250        return result;
251    }
252    return ReaderWriter::WriteResult::FILE_NOT_HANDLED;
253}
254
255
256bool FileCache::isCachedFileBlackListed(const std::string& originalFileName) const
257{
258    for(DatabaseRevisionsList::const_iterator itr = _databaseRevisionsList.begin();
259        itr != _databaseRevisionsList.end();
260        ++itr)
261    {
262        if ((*itr)->isFileBlackListed(originalFileName)) return true;
263    }
264    return false;
265}
266
267bool FileCache::removeFileFromBlackListed(const std::string& originalFileName) const
268{
269    for(DatabaseRevisionsList::const_iterator dr_itr = _databaseRevisionsList.begin();
270        dr_itr != _databaseRevisionsList.end();
271        ++dr_itr)
272    {
273        DatabaseRevisions* dr = dr_itr->get();
274
275        if (dr->getDatabasePath().length()>=originalFileName.length()) continue;
276        if (originalFileName.compare(0,dr->getDatabasePath().length(), dr->getDatabasePath())!=0) continue;
277
278        std::string localPath(originalFileName,
279                            dr->getDatabasePath().empty() ? 0 : dr->getDatabasePath().length()+1,
280                            std::string::npos);
281
282        for(DatabaseRevisions::DatabaseRevisionList::const_iterator itr = dr->getDatabaseRevisionList().begin();
283            itr != dr->getDatabaseRevisionList().end();
284            ++itr)
285        {
286            DatabaseRevision* revision = const_cast<DatabaseRevision*>(itr->get());
287
288            if (revision->getFilesAdded() && revision->getFilesAdded()->removeFile(localPath))
289            {
290                std::string cacheFileName = revision->getFilesAdded()->getName();
291                if (containsServerAddress(cacheFileName)) cacheFileName = createCacheFileName(cacheFileName);
292                if (!cacheFileName.empty()) writeObjectFile(*(revision->getFilesAdded()), cacheFileName);
293            }
294
295            if (revision->getFilesRemoved() && revision->getFilesRemoved()->removeFile(localPath))
296            {
297                std::string cacheFileName = revision->getFilesRemoved()->getName();
298                if (containsServerAddress(cacheFileName)) cacheFileName = createCacheFileName(cacheFileName);
299                if (!cacheFileName.empty()) writeObjectFile(*(revision->getFilesRemoved()), cacheFileName);
300            }
301
302            if (revision->getFilesModified() && revision->getFilesModified()->removeFile(localPath))
303            {
304                std::string cacheFileName = revision->getFilesModified()->getName();
305                if (containsServerAddress(cacheFileName)) cacheFileName = createCacheFileName(cacheFileName);
306                if (!cacheFileName.empty()) writeObjectFile(*(revision->getFilesModified()), cacheFileName);
307            }
308        }
309    }
310    return false;
311}
312
313bool FileCache::loadDatabaseRevisionsForFile(const std::string& originalFileName)
314{
315    OSG_INFO<<"FileCache::loadDatabaseRevisionsForFile("<<originalFileName<<")"<<std::endl;
316
317    std::string revisionsFileName = originalFileName;
318    if (getLowerCaseFileExtension(revisionsFileName)!="revisions") revisionsFileName += ".revisions";
319
320    OSG_INFO<<"   revisionsFileName("<<revisionsFileName<<")"<<std::endl;
321
322    osg::ref_ptr<DatabaseRevisions> dr_local;
323
324    std::string cacheFileName = createCacheFileName(revisionsFileName);
325
326    // check to see if revion file is already loaded.
327    DatabaseRevisionsList::iterator ritr = _databaseRevisionsList.begin();
328    for(;
329        ritr != _databaseRevisionsList.end() && !dr_local;
330        ++ritr)
331    {
332        OSG_INFO<<"   comparing "<<(*ritr)->getName()<<" to "<<revisionsFileName<<std::endl;
333
334        if ((*ritr)->getName()==revisionsFileName)
335        {
336            OSG_INFO<<"Already loaded"<<std::endl;
337            dr_local = *ritr;
338        }
339    }
340
341    if (!dr_local)
342    {
343        if (!cacheFileName.empty() && osgDB::fileExists(cacheFileName))
344        {
345            OSG_INFO<<"   found revisions file in local cache, now loading it"<<std::endl;
346            osg::ref_ptr<osg::Object> object = osgDB::readObjectFile(cacheFileName);
347            dr_local = dynamic_cast<DatabaseRevisions*>(object.get());
348            if (dr_local)
349            {
350                OSG_INFO<<"   loaded local revisions File("<<cacheFileName<<")"<<std::endl;
351            }
352        }
353        else
354        {
355            OSG_INFO<<"   could not load found revisions file from local cache."<<std::endl;
356        }
357    }
358
359    // now load revision file from remote server
360    osg::ref_ptr<osg::Object> object = osgDB::readObjectFile(revisionsFileName+".curl");
361    osg::ref_ptr<DatabaseRevisions> dr_remote = dynamic_cast<DatabaseRevisions*>(object.get());
362
363    if (dr_remote.valid())
364    {
365        bool needToWriteRevisionsFileToDisk = true;
366        if (dr_local.valid())
367        {
368            if (dr_local->getDatabaseRevisionList().size()==dr_remote->getDatabaseRevisionList().size())
369            {
370                unsigned int i;
371                for(i=0; i<dr_local->getDatabaseRevisionList().size(); ++i)
372                {
373                    DatabaseRevision* revision_local = dr_local->getDatabaseRevision(i);
374                    DatabaseRevision* revision_remote = dr_remote->getDatabaseRevision(i);
375                    OSG_INFO<<"   Comparing local "<<revision_local->getName()<<" to remote "<<revision_remote->getName()<<std::endl;
376                    if (revision_local->getName()!=revision_remote->getName()) break;
377                }
378                needToWriteRevisionsFileToDisk = (i!=dr_local->getDatabaseRevisionList().size());
379                OSG_INFO<<"Local and remote revisions are different "<<needToWriteRevisionsFileToDisk<<std::endl;
380            }
381        }
382
383        if (needToWriteRevisionsFileToDisk)
384        {
385            OSG_INFO<<"Need to write DatabaseRevions "<<revisionsFileName<<" to local FileCache"<<std::endl;
386            if (!cacheFileName.empty()) writeObjectFile(*dr_remote, cacheFileName);
387        }
388        else
389        {
390            OSG_INFO<<"No need to write DatabaseRevions "<<revisionsFileName<<" to local FileCache"<<std::endl;
391        }
392
393    }
394
395
396    osg::ref_ptr<DatabaseRevisions> dr = dr_remote.valid() ? dr_remote : dr_local;
397
398    if (dr.valid())
399    {
400        OSG_INFO<<"   loaded remote revisions File("<<revisionsFileName<<")"<<std::endl;
401
402        if (ritr != _databaseRevisionsList.end())
403        {
404            // replace already loaded DatabaseRevisions object
405            OSG_INFO<<"Replacing already loaded DatabaseRevisions object"<<std::endl;
406            *ritr = dr;
407        }
408        else
409        {
410            OSG_INFO<<"Added newly loaded DatabaseRevisions object "<<dr->getName()<<std::endl;
411            _databaseRevisionsList.push_back(dr);
412        }
413
414        // now need to load the individual FileLists
415        for(DatabaseRevisions::DatabaseRevisionList::iterator itr = dr->getDatabaseRevisionList().begin();
416            itr != dr->getDatabaseRevisionList().end();
417            ++itr)
418        {
419            DatabaseRevision* revision = itr->get();
420
421            OSG_INFO<<"     now loaded DatabaseRevisions "<<revision->getName()<<" FileList contents"<<std::endl;
422            if (revision->getFilesAdded())
423            {
424                FileList* fileList = readFileList(osgDB::concatPaths(revision->getDatabasePath(), revision->getFilesAdded()->getName()));
425                if (fileList)
426                {
427                    revision->setFilesAdded(fileList);
428                }
429            }
430
431            if (revision->getFilesRemoved())
432            {
433                FileList* fileList = readFileList(osgDB::concatPaths(revision->getDatabasePath(), revision->getFilesRemoved()->getName()));
434                if (fileList)
435                {
436                    revision->setFilesRemoved(fileList);
437                }
438            }
439
440            if (revision->getFilesModified())
441            {
442                FileList* fileList = readFileList(osgDB::concatPaths(revision->getDatabasePath(), revision->getFilesModified()->getName()));
443                if (fileList)
444                {
445                    revision->setFilesModified(fileList);
446                }
447            }
448        }
449
450        return true;
451    }
452    else
453    {
454        OSG_NOTICE<<"   failed to read revisions File, object.get()="<<object.get()<<std::endl;
455        return false;
456    }
457}
458
459FileList* FileCache::readFileList(const std::string& originalFileName) const
460{
461    osg::ref_ptr<FileList> fileList;
462
463    std::string cacheFileListName = createCacheFileName(originalFileName);
464    if (!cacheFileListName.empty() && osgDB::fileExists(cacheFileListName))
465    {
466        osg::ref_ptr<osg::Object> object = osgDB::readObjectFile(cacheFileListName);
467        fileList = dynamic_cast<osgDB::FileList*>(object.get());
468        if (fileList) OSG_INFO<<"     loadeded FileList from local cache "<<fileList->getName()<<std::endl;
469    }
470
471    if (!fileList)
472    {
473        OSG_INFO<<"       complete_path="<<originalFileName<<std::endl;
474        osg::ref_ptr<osg::Object> object = osgDB::readObjectFile(originalFileName+".curl");
475        fileList = dynamic_cast<osgDB::FileList*>(object.get());
476        if (fileList)
477        {
478            OSG_INFO<<"     loadeded FileList from remote system "<<fileList->getName()<<std::endl;
479            OSG_INFO<<"     Need to write to local file cache "<<fileList->getName()<<std::endl;
480            if (!cacheFileListName.empty()) writeObjectFile(*fileList, cacheFileListName);
481        }
482    }
483    return fileList.release();
484}
Note: See TracBrowser for help on using the browser.