summaryrefslogtreecommitdiff
path: root/include/cache.h
blob: 68f1cbaf6f6baaad4bd5fa41fc338205f3a26bcd (plain) (blame)
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
#ifndef NEWSBOAT_CACHE_H_
#define NEWSBOAT_CACHE_H_

#include <memory>
#include <mutex>
#include <sqlite3.h>
#include <unordered_set>

#include "configcontainer.h"

namespace newsboat {

class RssFeed;
class RssIgnores;
class RssItem;

struct SchemaVersion {
	unsigned int major, minor;

	friend bool operator<(const SchemaVersion& l, const SchemaVersion& r)
	{
		return std::tie(l.major, l.minor) < std::tie(r.major, r.minor);
	}
	friend bool operator>(const SchemaVersion& l, const SchemaVersion& r)
	{
		return r < l;
	}
	friend bool operator<=(const SchemaVersion& l, const SchemaVersion& r)
	{
		return !(l > r);
	}
	friend bool operator>=(const SchemaVersion& l, const SchemaVersion& r)
	{
		return !(l < r);
	}
};

const SchemaVersion unknown_version = {0, 0};

using schema_patches = std::map<SchemaVersion, std::vector<std::string>>;

class Cache {
public:
	Cache(const std::string& cachefile, ConfigContainer* c);
	~Cache();
	void externalize_rssfeed(std::shared_ptr<RssFeed> feed,
		bool reset_unread);
	std::shared_ptr<RssFeed> internalize_rssfeed(std::string rssurl,
		RssIgnores* ign);
	void update_rssitem_unread_and_enqueued(std::shared_ptr<RssItem> item,
		const std::string& feedurl);
	void update_rssitem_unread_and_enqueued(RssItem* item,
		const std::string& feedurl);
	/// if requested, removes unreachable data stored in cache.
	/// returns a count of unreachable feeds and items.
	std::uint64_t cleanup_cache(std::vector<std::shared_ptr<RssFeed>> feeds,
		bool always_clean = false);
	void do_vacuum();
	std::vector<std::shared_ptr<RssItem>> search_for_items(
			const std::string& querystr,
			const std::string& feedurl,
			RssIgnores& ign);
	std::unordered_set<std::string> search_in_items(
		const std::string& querystr,
		const std::unordered_set<std::string>& guids);
	void mark_all_read(const std::string& feedurl = "");
	void mark_all_read(std::shared_ptr<RssFeed> feed);
	void update_rssitem_flags(RssItem* item);
	void fetch_lastmodified(const std::string& uri,
		time_t& t,
		std::string& etag);
	void update_lastmodified(const std::string& uri,
		time_t t,
		const std::string& etag);
	void mark_item_deleted(const std::string& guid, bool b);
	void remove_old_deleted_items(RssFeed* feed);
	void mark_items_read_by_guid(const std::vector<std::string>& guids);
	std::vector<std::string> get_read_item_guids();
	void fetch_descriptions(RssFeed* feed);
	std::string fetch_description(const RssItem& item);

private:
	SchemaVersion get_schema_version();
	void populate_tables();
	void set_pragmas();
	void delete_item(const std::shared_ptr<RssItem>& item);
	void clean_old_articles();
	void update_rssitem_unlocked(std::shared_ptr<RssItem> item,
		const std::string& feedurl,
		bool reset_unread);

	std::string prepare_query(const std::string& format);
	template<typename... Args>
	std::string prepare_query(const std::string& format,
		const std::string& arg,
		Args... args);
	template<typename T, typename... Args>
	std::string prepare_query(const std::string& format, const T& arg,
		Args... args);

	void run_sql(const std::string& query,
		int (*callback)(void*, int, char**, char**) = nullptr,
		void* callback_argument = nullptr);
	void run_sql_nothrow(const std::string& query,
		int (*callback)(void*, int, char**, char**) = nullptr,
		void* callback_argument = nullptr);
	void run_sql_impl(const std::string& query,
		int (*callback)(void*, int, char**, char**),
		void* callback_argument,
		bool do_throw);

	sqlite3* db;
	ConfigContainer* cfg;
	std::mutex mtx;
};

} // namespace newsboat

#endif /* NEWSBOAT_CACHE_H_ */