]> git.tdb.fi Git - builder.git/blob - source/cache.cpp
Add some logging and remove a stray debug statement
[builder.git] / source / cache.cpp
1 #include <msp/core/maputils.h>
2 #include <msp/fs/stat.h>
3 #include <msp/io/file.h>
4 #include <msp/io/print.h>
5 #include <msp/strings/utils.h>
6 #include "builder.h"
7 #include "cache.h"
8 #include "sourcepackage.h"
9 #include "target.h"
10
11 using namespace std;
12 using namespace Msp;
13
14 namespace {
15
16 unsigned read_count(IO::Base &in)
17 {
18         unsigned char head = in.get();
19         if((head&0xC0)==0xC0)
20         {
21                 unsigned char tail = in.get();
22                 return (head&0x3F)<<8 | tail;
23         }
24         else
25                 return head;
26 }
27
28 string read_string(IO::Base &in)
29 {
30         unsigned len = read_count(in);
31         char buf[0x4000];
32         len = in.read(buf, len);
33         return string(buf, len);
34 }
35
36 void write_count(IO::Base &out, unsigned count)
37 {
38         if(count<0xC0)
39                 out.put(count);
40         else if(count<0x4000)
41         {
42                 out.put(0xC0 | (count>>8));
43                 out.put(count&0xFF);
44         }
45         else
46                 throw invalid_argument("write_count");
47 }
48
49 void write_string(IO::Base &out, const string &str)
50 {
51         write_count(out, str.size());
52         out.write(str);
53 }
54
55 }
56
57
58 Cache::Cache(SourcePackage &p):
59         package(p),
60         filename(package.get_temp_dir()/"../cache"),
61         changed(false)
62 { }
63
64 void Cache::set_value(const Target *tgt, const string &k, const string &v)
65 {
66         ValueList vl;
67         vl.push_back(v);
68         set_values(tgt, k, vl);
69 }
70
71 void Cache::append_value(const Target *tgt, const string &k, const string &v)
72 {
73         Key key(tgt->get_name(), k);
74         DataMap::iterator i = data.find(key);
75         if(i==data.end())
76                 i = data.insert(DataMap::value_type(key, ValueList())).first;
77         i->second.push_back(v);
78         changed = true;
79         package.get_builder().get_logger().log("cache", format("Updated key %s %s+ %s", tgt->get_name(), k, v));
80 }
81
82 void Cache::set_values(const Target *tgt, const string &k, const ValueList &v)
83 {
84         data[Key(tgt->get_name(), k)] = v;
85         changed = true;
86         package.get_builder().get_logger().log("cache", format("Updated key %s %s: %s", tgt->get_name(), k, join(v.begin(), v.end())));
87 }
88
89 const string &Cache::get_value(const Target *tgt, const string &k)
90 {
91         const ValueList &values = get_values(tgt, k);
92         if(values.empty())
93                 throw logic_error("values.empty()");
94         return values.front();
95 }
96
97 const Cache::ValueList &Cache::get_values(const Target *tgt, const string &k)
98 {
99         return get_item(data, Key(tgt->get_name(), k));
100 }
101
102 bool Cache::has_key(const Target *tgt, const string &k)
103 {
104         return data.count(Key(tgt->get_name(), k));
105 }
106
107 void Cache::load()
108 {
109         if(FS::Stat st = FS::stat(filename))
110         {
111                 package.get_builder().get_logger().log("files", format("Reading %s", filename));
112                 IO::BufferedFile in(filename.str());
113
114                 while(!in.eof())
115                 {
116                         Key key;
117                         key.first = read_string(in);
118                         key.second = read_string(in);
119                         if(key.first.empty() || key.second.empty())
120                                 break;
121                         ValueList &values = data[key];
122                         for(unsigned count = read_count(in); count; --count)
123                                 values.push_back(read_string(in));
124                         package.get_builder().get_logger().log("cache", format("Loaded key %s %s: %s", key.first, key.second, join(values.begin(), values.end())));
125                 }
126
127                 mtime = st.get_modify_time();
128         }
129 }
130
131 void Cache::save() const
132 {
133         if(data.empty() || !changed)
134                 return;
135
136         package.get_builder().get_logger().log("files", format("Writing %s", filename));
137         IO::BufferedFile out(filename.str(), IO::M_WRITE);
138
139         for(DataMap::const_iterator i=data.begin(); i!=data.end(); ++i)
140         {
141                 write_string(out, i->first.first);
142                 write_string(out, i->first.second);
143                 write_count(out, i->second.size());
144                 for(ValueList::const_iterator j=i->second.begin(); j!=i->second.end(); ++j)
145                         write_string(out, *j);
146         }
147 }