File: cacheman.h

package info (click to toggle)
apt-cacher-ng 2-2
  • links: PTS, VCS
  • area: main
  • in suites: stretch
  • size: 2,032 kB
  • ctags: 1,705
  • sloc: cpp: 16,869; sh: 536; ansic: 404; perl: 377; makefile: 124
file content (274 lines) | stat: -rw-r--r-- 9,209 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
#ifndef _CACHEMAN_H_
#define _CACHEMAN_H_

#include "config.h"
#include "meta.h"
#include "acfg.h"
#include "dirwalk.h"
#include "maintenance.h"
#include "lockable.h"
#include "csmapping.h"
#include "bgtask.h"
#include "fileitem.h"
#include <unordered_map>
#include <unordered_set>

// #define USEDUPEFILTER

namespace acng
{

class dlcon;

// XXX: specific declarations, maybe move to a namespace
class tDlJobHints;
class tFileGroups;
struct tContentKey;

static cmstring sAbortMsg("<span class=\"ERROR\">Found errors during processing, "
		"aborting as requested.</span>");

static cmstring sIndex("Index");
static cmstring sslIndex("/Index");

static cmstring sfxXzBz2GzLzma[] = { ".xz", ".bz2", ".gz", ".lzma"};
static cmstring sfxXzBz2GzLzmaNone[] = { ".xz", ".bz2", ".gz", ".lzma", ""};

bool CompDebVerLessThan(cmstring &s1, cmstring s2);
extern time_t m_gMaintTimeNow;

void DelTree(const string &what);

class cacheman :
	public IFileHandler,
	public tSpecOpDetachable
{

public:
	cacheman(const tSpecialRequest::tRunParms& parms);
	virtual ~cacheman();

	enum enumMetaType
		: uint8_t
		{
			EIDX_NOTREFINDEX = 0,
		EIDX_RELEASE,
		EIDX_PACKAGES,
		EIDX_SOURCES,
		EIDX_DIFFIDX,
		EIDX_ARCHLXDB,
		EIDX_CYGSETUP,
		EIDX_SUSEREPO,
		EIDX_XMLRPMLIST,
		EIDX_RFC822WITHLISTS,
		EIDX_TRANSIDX, // XXX: in the old times, there were special i18n/Index files, are they gone for good now?
		EIDX_MD5DILIST,
		EIDX_SHA256DILIST
	};
	struct tIfileAttribs
	{
		bool vfile_ondisk:1, uptodate:1, parseignore:1, hideDlErrors:1,
				forgiveDlErrors:1, alreadyparsed:1;
		enumMetaType eIdxType = EIDX_NOTREFINDEX;
		tIfileAttribs *bro; // point to a related descriptor, circled single-linked list
		off_t space = 0;
		inline tIfileAttribs() :
				vfile_ondisk(false), uptodate(false),
				parseignore(false), hideDlErrors(false),
				forgiveDlErrors(false), alreadyparsed(false)
		{
			bro = this;
		};
#ifdef DEBUG
		inline tSS toString() const
		{
			return tSS() << alreadyparsed << "|"
					<< forgiveDlErrors << "|"
					<< hideDlErrors << "|"
					<< parseignore << "|"
					<< space << "|"
					<< uptodate << "|"
					<< vfile_ondisk;
		}
#endif
	};

	// helpers to keep the code cleaner and more readable
	const tIfileAttribs &GetFlags(cmstring &sPathRel) const;

protected:
	// this is not unordered because sometimes we make use of iterator references while
	// doing modification of the map
	std::map<mstring,tIfileAttribs> m_metaFilesRel;
	tIfileAttribs &SetFlags(cmstring &sPathRel);

	// evil shortcut, might point to read-only dummy... to be used with care
	tIfileAttribs &GetRWFlags(cmstring &sPathRel);
	void UpdateVolatileFiles();
	void _BusyDisplayLogs();
	void _Usermsg(mstring m);
	bool AddIFileCandidate(const mstring &sFileRel);

	// NOOP, implemented here for convenience
	bool ProcessOthers(const mstring &sPath, const struct stat &);
	bool ProcessDirAfter(const mstring &sPath, const struct stat &);

	/*!
	 * As the name saids, processes all index files and calls a callback
	 * function maintenence::_HandlePkgEntry on each entry.
	 * 
	 * If a string set object is passed then a little optimization might be 
	 * enabled internally, which avoid repeated processing of a file when another
	 * one with the same contents was already processed. This is only applicable 
	 * having strict path checking disabled, though.
	 *   
	 * */

	void ProcessSeenIndexFiles(std::function<void(tRemoteFileInfo)> pkgHandler);

	void StartDlder();

	enum eDlMsgPrio
	{
		eMsgHideAll,
		eMsgHideErrors,
		eMsgShow
	};
	bool Download(cmstring& sFilePathRel, bool bIsVolatileFile,
			eDlMsgPrio msgLevel, tFileItemPtr pForcedItem=tFileItemPtr(),
			const tHttpUrl *pForcedURL=nullptr, unsigned hints=0, cmstring* sGuessedFrom = nullptr);
#define DL_HINT_GUESS_REPLACEMENT 0x1
#define DL_HINT_NOTAG 0x2

	// common helper variables
	bool m_bErrAbort, m_bVerbose, m_bForceDownload, m_bSkipIxUpdate = false;
	bool m_bScanInternals, m_bByPath, m_bByChecksum, m_bSkipHeaderChecks;
	bool m_bTruncateDamaged;
	int m_nErrorCount;

	enumMetaType GuessMetaTypeFromURL(const mstring &sPath);

	unsigned int m_nProgIdx, m_nProgTell;

	void TellCount(unsigned nCount, off_t nSize);

	/**
	 * @param collectAllCsTypes If set, will send callbacks for all identified checksum types. In addition, will set the value of Acquire-By-Hash to the pointed boolean.
	 */
	bool ParseAndProcessMetaFile(std::function<void(const tRemoteFileInfo&)> output_receiver,
			const mstring &sPath, enumMetaType idxType, bool byHashMode = false);

	std::unordered_map<mstring,bool> m_forceKeepInTrash;

	bool GetAndCheckHead(cmstring & sHeadfile, cmstring &sFilePathRel, off_t nWantedSize);
	bool Inject(cmstring &fromRel, cmstring &toRel,
			bool bSetIfileFlags=true, const header *pForcedHeader=nullptr, bool bTryLink=false);

	void PrintStats(cmstring &title);
	mstring m_processedIfile;

	void ProgTell();
	void AddDelCbox(cmstring &sFileRel, cmstring& reason, bool bExtraFile = false);

	// add certain files to the kill bill, to be removed after the activity is done
	virtual void MarkObsolete(cmstring&) {};

	// for compressed map of special stuff
	inline mstring AddLookupGetKey(cmstring &sFilePathRel, cmstring& errorReason)
	{
		unsigned id = m_pathMemory.size();
		auto it = m_pathMemory.find(sFilePathRel);
		if(it==m_pathMemory.end())
			m_pathMemory[sFilePathRel] = {errorReason, id};
		else
			id = it->second.id;
		char buf[30];
		return mstring(buf, snprintf(buf, sizeof(buf), " name=\"kf\" value=\"%x\"", id));
	}

	// stuff in those directories must be managed by some top-level index files
	// whitelist patterns do not apply there!
	tStrSet m_managedDirs;

private:

	void ExtractAllRawReleaseDataFixStrandedPatchIndex(tFileGroups& ret, const tStrDeq& releaseFilesRel);
	void FilterGroupData(tFileGroups& idxGroups);
	void SortAndInterconnectGroupData(tFileGroups& idxGroups);

	/**
	 * Adjust the configuration of related paths (relative to updatePath) to prevent
	 * smart downloads later, how exactly depends on current execution mode.
	 *
	 * If strict path checks are used the content may also be copied over.
	 */
	void SyncSiblings(cmstring &srcPathRel, const tStrDeq& targets);

	cacheman(const cacheman&);
	cacheman& operator=(const cacheman&);

	dlcon *m_pDlcon = nullptr;
	cmstring& GetFirstPresentPath(const tFileGroups& groups, const tContentKey& ckey);

	/*
	 * Analyze patch base candidate, fetch patch files as suggested by index, patch, distribute result
	 */
	void PatchOne(cmstring& pindexPathRel, const tStrDeq& patchBaseCandidates);
	void ParseGenericRfc822File(filereader& reader, cmstring& sExtListFilter,
			map<string, deque<string> >& contents);
	bool ParseDebianIndexLine(tRemoteFileInfo& info, cmstring& fline);

protected:
	bool CalculateBaseDirectories(cmstring& sPath, enumMetaType idxType, mstring& sBaseDir, mstring& sBasePkgDir);
	bool IsDeprecatedArchFile(cmstring &sFilePathRel);
	/**
	 * @brief Process key:val type files, handling multiline values as lists
	 * @param ixInflatedChecksum Pass through as struct attribute to ret callback
	 * @param sExtListFilter If set to non-empty, will only extract value(s) for that key
	 * @param byHashMode Return without calbacks if AcquireByHash is not set to yes. Not setting list filter also makes sense in this mode.
	 */
	bool ParseDebianRfc822Index(filereader& reader, std::function<void(const tRemoteFileInfo&)> &ret,
			cmstring& sCurFilesReferenceDirRel,
			cmstring& sPkgBaseDir,
			enumMetaType ixType, CSTYPES csType,
			cmstring& sExtListFilter,
			bool byHashMode);
	const tIfileAttribs attr_dummy_pure = tIfileAttribs();
	tIfileAttribs attr_dummy;

	/* Little helper to check existence of specific name on disk, either in cache or replacement directory, depending on what the srcPrefix defines */
	virtual bool _checkSolidHashOnDisk(cmstring& hexname, const tRemoteFileInfo &entry,
			cmstring& srcPrefix);

	// "can return false negatives" thing
	// to be implemented in subclasses
	virtual bool _QuickCheckSolidFileOnDisk(cmstring& /* sFilePathRel */) { return false; }
	void BuildCacheFileList();
	/**
	 * This is supposed to restore references to files that are no longer
	 * downloaded by apt directly but via semi-static files identified by hash
	 * value in their name.
	 *
	 * Without this link, the index processing would not be able to parse the
	 * lists correctly and expiration would eventually "expire" good data.
	 *
	 * The code identify the original location of the index
	 * file by Release file analysis. */
	bool FixMissingByHashLinks(std::unordered_set<std::string> &oldReleaseFiles);

	/**
	 * If the specified (In)Release file has By-Hash enabled, look for paths that match
	 * the hash reference and if found, restore the data contents on the location of the
	 * file that the by-hash blobs originated from.
	 * @param releasePathRel cache-relative location of InRelease file
	 * @param stripPrefix Optional prefix to prepend to releasePathRel but not to referenced files
	 */
	bool ProcessByHashReleaseFileRestoreFiles(cmstring& releasePathRel, cmstring& stripPrefix);

	// simple helper for use by others as well, and let compiler do RVO
	tStrDeq GetGoodReleaseFiles();
};

}

#endif /*_CACHEMAN_H_*/