Merged revision(s) 58452-58584 from trunk/blender into soc-2013-dingto.
[blender-staging.git] / intern / cycles / util / util_cache.cpp
1 /*
2  * Copyright 2011, Blender Foundation.
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  */
18
19 #include <stdio.h>
20
21 #include "util_cache.h"
22 #include "util_debug.h"
23 #include "util_foreach.h"
24 #include "util_map.h"
25 #include "util_md5.h"
26 #include "util_path.h"
27 #include "util_types.h"
28
29 #include <boost/version.hpp>
30
31 #if (BOOST_VERSION < 104400)
32 #  define BOOST_FILESYSTEM_VERSION 2
33 #endif
34
35 #include <boost/filesystem.hpp> 
36 #include <boost/algorithm/string.hpp>
37
38 CCL_NAMESPACE_BEGIN
39
40 /* CacheData */
41
42 CacheData::CacheData(const string& name_)
43 {
44         name = name_;
45         f = NULL;
46         have_filename = false;
47 }
48
49 CacheData::~CacheData()
50 {
51         if(f)
52                 fclose(f);
53 }
54
55 const string& CacheData::get_filename()
56 {
57         if(!have_filename) {
58                 MD5Hash hash;
59
60                 foreach(const CacheBuffer& buffer, buffers)
61                         if(buffer.size)
62                                 hash.append((uint8_t*)buffer.data, buffer.size);
63                 
64                 filename = name + "_" + hash.get_hex();
65                 have_filename = true;
66         }
67
68         return filename;
69 }
70
71 /* Cache */
72
73 Cache Cache::global;
74
75 string Cache::data_filename(CacheData& key)
76 {
77         return path_user_get(path_join("cache", key.get_filename()));
78 }
79
80 void Cache::insert(CacheData& key, CacheData& value)
81 {
82         string filename = data_filename(key);
83         path_create_directories(filename);
84         FILE *f = fopen(filename.c_str(), "wb");
85
86         if(!f) {
87                 fprintf(stderr, "Failed to open file %s for writing.\n", filename.c_str());
88                 return;
89         }
90
91         foreach(CacheBuffer& buffer, value.buffers) {
92                 if(!fwrite(&buffer.size, sizeof(buffer.size), 1, f))
93                         fprintf(stderr, "Failed to write to file %s.\n", filename.c_str());
94                 if(buffer.size)
95                         if(!fwrite(buffer.data, buffer.size, 1, f))
96                                 fprintf(stderr, "Failed to write to file %s.\n", filename.c_str());
97         }
98         
99         fclose(f);
100 }
101
102 bool Cache::lookup(CacheData& key, CacheData& value)
103 {
104         string filename = data_filename(key);
105         FILE *f = fopen(filename.c_str(), "rb");
106
107         if(!f)
108                 return false;
109         
110         value.name = key.name;
111         value.f = f;
112
113         return true;
114 }
115
116 void Cache::clear_except(const string& name, const set<string>& except)
117 {
118         string dir = path_user_get("cache");
119
120         if(boost::filesystem::exists(dir)) {
121                 boost::filesystem::directory_iterator it(dir), it_end;
122
123                 for(; it != it_end; it++) {
124 #if (BOOST_FILESYSTEM_VERSION == 2)
125                         string filename = it->path().filename();
126 #else
127                         string filename = it->path().filename().string();
128 #endif
129
130                         if(boost::starts_with(filename, name))
131                                 if(except.find(filename) == except.end())
132                                         boost::filesystem::remove(it->path());
133                 }
134         }
135 }
136
137 CCL_NAMESPACE_END
138