1 |
|
|
/** |
2 |
|
|
* This file is part of the CernVM File System. |
3 |
|
|
*/ |
4 |
|
|
|
5 |
|
|
#ifndef CVMFS_CATALOG_COUNTERS_H_ |
6 |
|
|
#define CVMFS_CATALOG_COUNTERS_H_ |
7 |
|
|
|
8 |
|
|
#include <gtest/gtest_prod.h> |
9 |
|
|
#include <stdint.h> |
10 |
|
|
|
11 |
|
|
#include <map> |
12 |
|
|
#include <string> |
13 |
|
|
|
14 |
|
|
namespace swissknife { |
15 |
|
|
class CommandCheck; |
16 |
|
|
} |
17 |
|
|
|
18 |
|
|
namespace catalog { |
19 |
|
|
|
20 |
|
|
class DirectoryEntry; |
21 |
|
|
class CatalogDatabase; |
22 |
|
|
|
23 |
|
|
struct LegacyMode { |
24 |
|
|
enum Type { // TODO(rmeusel): C++11 typed enum |
25 |
|
|
kNoLegacy, |
26 |
|
|
kNoSpecials, |
27 |
|
|
kNoExternals, |
28 |
|
|
kNoXattrs, |
29 |
|
|
kLegacy |
30 |
|
|
}; |
31 |
|
|
}; |
32 |
|
|
|
33 |
|
|
// FieldT is either int64_t (DeltaCounters) or uint64_t (Counters) |
34 |
|
|
template<typename FieldT> |
35 |
|
236 |
class TreeCountersBase { |
36 |
|
|
friend class swissknife::CommandCheck; |
37 |
|
|
FRIEND_TEST(T_CatalogCounters, FieldsCombinations); |
38 |
|
|
FRIEND_TEST(T_CatalogCounters, FieldsMap); |
39 |
|
|
|
40 |
|
|
protected: |
41 |
|
|
typedef std::map<std::string, const FieldT*> FieldsMap; |
42 |
|
|
struct Fields { |
43 |
|
474 |
Fields() |
44 |
|
|
: regular_files(0) |
45 |
|
|
, symlinks(0) |
46 |
|
|
, specials(0) |
47 |
|
|
, directories(0) |
48 |
|
|
, nested_catalogs(0) |
49 |
|
|
, chunked_files(0) |
50 |
|
|
, file_chunks(0) |
51 |
|
|
, file_size(0) |
52 |
|
|
, chunked_file_size(0) |
53 |
|
|
, xattrs(0) |
54 |
|
|
, externals(0) |
55 |
|
474 |
, external_file_size(0) { } |
56 |
|
|
|
57 |
|
|
// typname U is another TreeCountersBase (eg: add DeltaCounters to Counters) |
58 |
|
|
template<typename U> |
59 |
|
33 |
void Add(const U &other) { |
60 |
|
33 |
Combine<U, 1>(other); |
61 |
|
33 |
} |
62 |
|
|
|
63 |
|
|
template<typename U> |
64 |
|
24 |
void Subtract(const U &other) { |
65 |
|
24 |
Combine<U, -1>(other); |
66 |
|
24 |
} |
67 |
|
|
|
68 |
|
|
template<typename U, int factor> |
69 |
|
57 |
void Combine(const U &other) { |
70 |
|
57 |
regular_files += factor * other.regular_files; |
71 |
|
57 |
symlinks += factor * other.symlinks; |
72 |
|
57 |
specials += factor * other.specials; |
73 |
|
57 |
directories += factor * other.directories; |
74 |
|
57 |
nested_catalogs += factor * other.nested_catalogs; |
75 |
|
57 |
chunked_files += factor * other.chunked_files; |
76 |
|
57 |
file_chunks += factor * other.file_chunks; |
77 |
|
57 |
file_size += factor * other.file_size; |
78 |
|
57 |
chunked_file_size += factor * other.chunked_file_size; |
79 |
|
57 |
xattrs += factor * other.xattrs; |
80 |
|
57 |
externals += factor * other.externals; |
81 |
|
57 |
external_file_size += factor * other.external_file_size; |
82 |
|
57 |
} |
83 |
|
|
|
84 |
|
426 |
void FillFieldsMap(const std::string &prefix, FieldsMap *map) const { |
85 |
|
426 |
(*map)[prefix + "regular"] = ®ular_files; |
86 |
|
852 |
(*map)[prefix + "symlink"] = &symlinks; |
87 |
|
852 |
(*map)[prefix + "special"] = &specials; |
88 |
|
852 |
(*map)[prefix + "dir"] = &directories; |
89 |
|
852 |
(*map)[prefix + "nested"] = &nested_catalogs; |
90 |
|
852 |
(*map)[prefix + "chunked"] = &chunked_files; |
91 |
|
852 |
(*map)[prefix + "chunks"] = &file_chunks; |
92 |
|
852 |
(*map)[prefix + "file_size"] = &file_size; |
93 |
|
852 |
(*map)[prefix + "chunked_size"] = &chunked_file_size; |
94 |
|
852 |
(*map)[prefix + "xattr"] = &xattrs; |
95 |
|
852 |
(*map)[prefix + "external"] = &externals; |
96 |
|
852 |
(*map)[prefix + "external_file_size"] = &external_file_size; |
97 |
|
426 |
} |
98 |
|
|
|
99 |
|
|
FieldT regular_files; |
100 |
|
|
FieldT symlinks; |
101 |
|
|
FieldT specials; |
102 |
|
|
FieldT directories; |
103 |
|
|
FieldT nested_catalogs; |
104 |
|
|
FieldT chunked_files; |
105 |
|
|
FieldT file_chunks; |
106 |
|
|
FieldT file_size; |
107 |
|
|
FieldT chunked_file_size; |
108 |
|
|
FieldT xattrs; |
109 |
|
|
FieldT externals; |
110 |
|
|
FieldT external_file_size; |
111 |
|
|
}; |
112 |
|
|
|
113 |
|
|
public: |
114 |
|
|
FieldT Get(const std::string &key) const; |
115 |
|
120 |
bool ReadFromDatabase(const CatalogDatabase &database, |
116 |
|
|
const LegacyMode::Type legacy = LegacyMode::kNoLegacy); |
117 |
|
22 |
bool WriteToDatabase(const CatalogDatabase &database) const; |
118 |
|
64 |
bool InsertIntoDatabase(const CatalogDatabase &database) const; |
119 |
|
|
|
120 |
|
7 |
void SetZero(); |
121 |
|
|
|
122 |
|
|
protected: |
123 |
|
213 |
FieldsMap GetFieldsMap() const; |
124 |
|
|
|
125 |
|
|
public: |
126 |
|
|
Fields self; |
127 |
|
|
Fields subtree; |
128 |
|
|
}; |
129 |
|
|
|
130 |
|
|
|
131 |
|
|
typedef int64_t DeltaCounters_t; |
132 |
|
59 |
class DeltaCounters : public TreeCountersBase<DeltaCounters_t> { |
133 |
|
|
friend class Counters; |
134 |
|
|
|
135 |
|
|
public: |
136 |
|
|
void PopulateToParent(DeltaCounters *parent) const; |
137 |
|
201 |
void Increment(const DirectoryEntry &dirent) { ApplyDelta(dirent, 1); } |
138 |
|
41 |
void Decrement(const DirectoryEntry &dirent) { ApplyDelta(dirent, -1); } |
139 |
|
|
|
140 |
|
|
private: |
141 |
|
|
void ApplyDelta(const DirectoryEntry &dirent, const int delta); |
142 |
|
|
}; |
143 |
|
|
|
144 |
|
|
|
145 |
|
|
typedef uint64_t Counters_t; |
146 |
|
177 |
class Counters : public TreeCountersBase<Counters_t> { |
147 |
|
|
public: |
148 |
|
|
static DeltaCounters Diff(const Counters &from, const Counters &to); |
149 |
|
|
|
150 |
|
|
void ApplyDelta(const DeltaCounters &delta); |
151 |
|
|
void AddAsSubtree(DeltaCounters *delta) const; |
152 |
|
|
void MergeIntoParent(DeltaCounters *parent_delta) const; |
153 |
|
|
Counters_t GetSelfEntries() const; |
154 |
|
|
Counters_t GetSubtreeEntries() const; |
155 |
|
|
Counters_t GetAllEntries() const; |
156 |
|
|
}; |
157 |
|
|
|
158 |
|
|
} // namespace catalog |
159 |
|
|
|
160 |
|
|
#include "catalog_counters_impl.h" |
161 |
|
|
|
162 |
|
|
#endif // CVMFS_CATALOG_COUNTERS_H_ |