• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * libwebsockets - small server side websockets and web server implementation
3  *
4  * Copyright (C) 2010 - 2019 Andy Green <andy@warmcat.com>
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a copy
7  * of this software and associated documentation files (the "Software"), to
8  * deal in the Software without restriction, including without limitation the
9  * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10  * sell copies of the Software, and to permit persons to whom the Software is
11  * furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included in
14  * all copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
22  * IN THE SOFTWARE.
23  */
24 
25 /*! \defgroup diskcache LWS disk cache
26  * ## Disk cache API
27  *
28  * Lws provides helper apis useful if you need a disk cache containing hashed
29  * files and need to delete files from it on an LRU basis to keep it below some
30  * size limit.
31  *
32  * The API `lws_diskcache_prepare()` deals with creating the cache dir and
33  * 256 subdirs, which are used according to the first two chars of the hex
34  * hash of the cache file.
35  *
36  * `lws_diskcache_create()` and `lws_diskcache_destroy()` allocate and free
37  * an opaque struct that represents the disk cache.
38  *
39  * `lws_diskcache_trim()` should be called at eg, 1s intervals to perform the
40  * cache dir monitoring and LRU autodelete in the background lazily.  It can
41  * be done in its own thread or on a timer... it monitors the directories in a
42  * stateful way that stats one or more file in the cache per call, and keeps
43  * a list of the oldest files as it goes.  When it completes a scan, if the
44  * aggregate size is over the limit, it will delete oldest files first to try
45  * to keep it under the limit.
46  *
47  * The cache size monitoring is extremely efficient in time and memory even when
48  * the cache directory becomes huge.
49  *
50  * `lws_diskcache_query()` is used to determine if the file already exists in
51  * the cache, or if it must be created.  If it must be created, then the file
52  * is opened using a temp name that must be converted to a findable name with
53  * `lws_diskcache_finalize_name()` when the generation of the file contents are
54  * complete.  Aborted cached files that did not complete generation will be
55  * flushed by the LRU eventually.  If the file already exists, it is 'touched'
56  * to make it new again and the fd returned.
57  *
58  */
59 ///@{
60 
61 struct lws_diskcache_scan;
62 
63 /**
64  * lws_diskcache_create() - creates an opaque struct representing the disk cache
65  *
66  * \param cache_dir_base: The cache dir path, eg `/var/cache/mycache`
67  * \param cache_size_limit: maximum size on disk the cache is allowed to use
68  *
69  * This returns an opaque `struct lws_diskcache_scan *` which represents the
70  * disk cache, the trim scanning state and so on.  You should use
71  * `lws_diskcache_destroy()` to free it to destroy it.
72  */
73 LWS_VISIBLE LWS_EXTERN struct lws_diskcache_scan *
74 lws_diskcache_create(const char *cache_dir_base, uint64_t cache_size_limit);
75 
76 /**
77  * lws_diskcache_destroy() - destroys the pointer returned by ...create()
78  *
79  * \param lds: pointer to the pointer returned by lws_diskcache_create()
80  *
81  * Frees *lds and any allocations it did, and then sets *lds to NULL and
82  * returns.
83  */
84 LWS_VISIBLE LWS_EXTERN void
85 lws_diskcache_destroy(struct lws_diskcache_scan **lds);
86 
87 /**
88  * lws_diskcache_prepare() - ensures the cache dir structure exists on disk
89  *
90  * \param cache_base_dir: The cache dir path, eg `/var/cache/mycache`
91  * \param mode: octal dir mode to enforce, like 0700
92  * \param uid: uid the cache dir should belong to
93  *
94  * This should be called while your app is still privileged.  It will create
95  * the cache directory structure on disk as necessary, enforce the given access
96  * mode on it and set the given uid as the owner.  It won't make any trouble
97  * if the cache already exists.
98  *
99  * Typically the mode is 0700 and the owner is the user that your application
100  * will transition to use when it drops root privileges.
101  */
102 LWS_VISIBLE LWS_EXTERN int
103 lws_diskcache_prepare(const char *cache_base_dir, int mode, uid_t uid);
104 
105 #define LWS_DISKCACHE_QUERY_NO_CACHE	0
106 #define LWS_DISKCACHE_QUERY_EXISTS	1
107 #define LWS_DISKCACHE_QUERY_CREATING	2
108 #define LWS_DISKCACHE_QUERY_ONGOING	3 /* something else is creating it */
109 
110 /**
111  * lws_diskcache_query() - ensures the cache dir structure exists on disk
112  *
113  * \param lds: The opaque struct representing the disk cache
114  * \param is_bot: nonzero means the request is from a bot.  Don't create new cache contents if so.
115  * \param hash_hex: hex string representation of the cache object hash
116  * \param _fd: pointer to the fd to be set
117  * \param cache: destination string to take the cache filepath
118  * \param cache_len: length of the buffer at `cache`
119  * \param extant_cache_len: pointer to a size_t to take any extant cached file size
120  *
121  * This function is called when you want to find if the hashed name already
122  * exists in the cache.  The possibilities for the return value are
123  *
124  *  - LWS_DISKCACHE_QUERY_NO_CACHE: It's not in the cache and you can't create
125  *    it in the cache for whatever reason.
126  *  - LWS_DISKCACHE_QUERY_EXISTS: It exists in the cache.  It's open RDONLY and
127  *    *_fd has been set to the file descriptor.  *extant_cache_len has been set
128  *    to the size of the cached file in bytes.  cache has been set to the
129  *    full filepath of the cached file.  Closing _fd is your responsibility.
130  *  - LWS_DISKCACHE_QUERY_CREATING: It didn't exist, but a temp file has been
131  *    created in the cache and *_fd set to a file descriptor opened on it RDWR.
132  *    You should create the contents, and call `lws_diskcache_finalize_name()`
133  *    when it is done.  Closing _fd is your responsibility.
134  *  - LWS_DISKCACHE_QUERY_ONGOING: not returned by this api, but you may find it
135  *    desirable to make a wrapper function which can handle another asynchronous
136  *    process that is already creating the cached file.  This can be used to
137  *    indicate that situation externally... how to determine the same thing is
138  *    already being generated is out of scope of this api.
139  */
140 LWS_VISIBLE LWS_EXTERN int
141 lws_diskcache_query(struct lws_diskcache_scan *lds, int is_bot,
142 		    const char *hash_hex, int *_fd, char *cache, int cache_len,
143 		    size_t *extant_cache_len);
144 
145 /**
146  * lws_diskcache_query() - ensures the cache dir structure exists on disk
147  *
148  * \param cache: The cache file temp name returned with LWS_DISKCACHE_QUERY_CREATING
149  *
150  * This renames the cache file you are creating to its final name.  It should
151  * be called on the temp name returned by `lws_diskcache_query()` if it gave a
152  * LWS_DISKCACHE_QUERY_CREATING return, after you have filled the cache file and
153  * closed it.
154  */
155 LWS_VISIBLE LWS_EXTERN int
156 lws_diskcache_finalize_name(char *cache);
157 
158 /**
159  * lws_diskcache_trim() - performs one or more file checks in the cache for size management
160  *
161  * \param lds: The opaque object representing the cache
162  *
163  * This should be called periodically to statefully walk the cache on disk
164  * collecting the oldest files.  When it has visited every file, if the cache
165  * is oversize it will delete the oldest files until it's back under size again.
166  *
167  * Each time it's called, it will look at one or more dir in the cache.  If
168  * called when the cache is oversize, it increases the amount of work done each
169  * call until it is reduced again.  Typically it will take 256 calls before it
170  * deletes anything, so if called once per second, it will delete files once
171  * every 4 minutes.  Each call is very inexpensive both in memory and time.
172  */
173 LWS_VISIBLE LWS_EXTERN int
174 lws_diskcache_trim(struct lws_diskcache_scan *lds);
175 
176 
177 /**
178  * lws_diskcache_secs_to_idle() - see how long to idle before calling trim
179  *
180  * \param lds: The opaque object representing the cache
181  *
182  * If the cache is undersize, there's no need to monitor it immediately.  This
183  * suggests how long to "sleep" before calling `lws_diskcache_trim()` again.
184  */
185 LWS_VISIBLE LWS_EXTERN int
186 lws_diskcache_secs_to_idle(struct lws_diskcache_scan *lds);
187 ///@}
188