~ubuntu-branches/ubuntu/vivid/mariadb-5.5/vivid-proposed

« back to all changes in this revision

Viewing changes to storage/tokudb/ft-index/ft/cachetable-internal.h

  • Committer: Package Import Robot
  • Author(s): Otto Kekäläinen
  • Date: 2014-11-14 21:04:24 UTC
  • mfrom: (1.1.6)
  • Revision ID: package-import@ubuntu.com-20141114210424-xlyna0ozl11647o5
Tags: 5.5.40-0ubuntu0.14.10.1
* SECURITY UPDATE: Update to 5.5.40 to fix security issues (LP: #1391676)
  - CVE-2014-6507
  - CVE-2014-6491
  - CVE-2014-6500
  - CVE-2014-6469
  - CVE-2014-6555
  - CVE-2014-6559
  - CVE-2014-6494
  - CVE-2014-6496
  - CVE-2014-6464
* Add bsdutils as mariadb-server dependency like upstream does in 5.5.40.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* -*- mode: C++; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2
 
// vim: ft=cpp:expandtab:ts=8:sw=4:softtabstop=4:
3
 
 
4
 
#ifndef TokuDB_cachetable_internal_h
5
 
#define TokuDB_cachetable_internal_h
6
 
 
7
 
#ident "$Id$"
8
 
/*
9
 
COPYING CONDITIONS NOTICE:
10
 
 
11
 
  This program is free software; you can redistribute it and/or modify
12
 
  it under the terms of version 2 of the GNU General Public License as
13
 
  published by the Free Software Foundation, and provided that the
14
 
  following conditions are met:
15
 
 
16
 
      * Redistributions of source code must retain this COPYING
17
 
        CONDITIONS NOTICE, the COPYRIGHT NOTICE (below), the
18
 
        DISCLAIMER (below), the UNIVERSITY PATENT NOTICE (below), the
19
 
        PATENT MARKING NOTICE (below), and the PATENT RIGHTS
20
 
        GRANT (below).
21
 
 
22
 
      * Redistributions in binary form must reproduce this COPYING
23
 
        CONDITIONS NOTICE, the COPYRIGHT NOTICE (below), the
24
 
        DISCLAIMER (below), the UNIVERSITY PATENT NOTICE (below), the
25
 
        PATENT MARKING NOTICE (below), and the PATENT RIGHTS
26
 
        GRANT (below) in the documentation and/or other materials
27
 
        provided with the distribution.
28
 
 
29
 
  You should have received a copy of the GNU General Public License
30
 
  along with this program; if not, write to the Free Software
31
 
  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
32
 
  02110-1301, USA.
33
 
 
34
 
COPYRIGHT NOTICE:
35
 
 
36
 
  TokuDB, Tokutek Fractal Tree Indexing Library.
37
 
  Copyright (C) 2007-2013 Tokutek, Inc.
38
 
 
39
 
DISCLAIMER:
40
 
 
41
 
  This program is distributed in the hope that it will be useful, but
42
 
  WITHOUT ANY WARRANTY; without even the implied warranty of
43
 
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
44
 
  General Public License for more details.
45
 
 
46
 
UNIVERSITY PATENT NOTICE:
47
 
 
48
 
  The technology is licensed by the Massachusetts Institute of
49
 
  Technology, Rutgers State University of New Jersey, and the Research
50
 
  Foundation of State University of New York at Stony Brook under
51
 
  United States of America Serial No. 11/760379 and to the patents
52
 
  and/or patent applications resulting from it.
53
 
 
54
 
PATENT MARKING NOTICE:
55
 
 
56
 
  This software is covered by US Patent No. 8,185,551.
57
 
  This software is covered by US Patent No. 8,489,638.
58
 
 
59
 
PATENT RIGHTS GRANT:
60
 
 
61
 
  "THIS IMPLEMENTATION" means the copyrightable works distributed by
62
 
  Tokutek as part of the Fractal Tree project.
63
 
 
64
 
  "PATENT CLAIMS" means the claims of patents that are owned or
65
 
  licensable by Tokutek, both currently or in the future; and that in
66
 
  the absence of this license would be infringed by THIS
67
 
  IMPLEMENTATION or by using or running THIS IMPLEMENTATION.
68
 
 
69
 
  "PATENT CHALLENGE" shall mean a challenge to the validity,
70
 
  patentability, enforceability and/or non-infringement of any of the
71
 
  PATENT CLAIMS or otherwise opposing any of the PATENT CLAIMS.
72
 
 
73
 
  Tokutek hereby grants to you, for the term and geographical scope of
74
 
  the PATENT CLAIMS, a non-exclusive, no-charge, royalty-free,
75
 
  irrevocable (except as stated in this section) patent license to
76
 
  make, have made, use, offer to sell, sell, import, transfer, and
77
 
  otherwise run, modify, and propagate the contents of THIS
78
 
  IMPLEMENTATION, where such license applies only to the PATENT
79
 
  CLAIMS.  This grant does not include claims that would be infringed
80
 
  only as a consequence of further modifications of THIS
81
 
  IMPLEMENTATION.  If you or your agent or licensee institute or order
82
 
  or agree to the institution of patent litigation against any entity
83
 
  (including a cross-claim or counterclaim in a lawsuit) alleging that
84
 
  THIS IMPLEMENTATION constitutes direct or contributory patent
85
 
  infringement, or inducement of patent infringement, then any rights
86
 
  granted to you under this License shall terminate as of the date
87
 
  such litigation is filed.  If you or your agent or exclusive
88
 
  licensee institute or order or agree to the institution of a PATENT
89
 
  CHALLENGE, then Tokutek may terminate any rights granted to you
90
 
  under this License.
91
 
*/
92
 
 
93
 
#ident "Copyright (c) 2007-2013 Tokutek Inc.  All rights reserved."
94
 
#ident "The technology is licensed by the Massachusetts Institute of Technology, Rutgers State University of New Jersey, and the Research Foundation of State University of New York at Stony Brook under United States of America Serial No. 11/760379 and to the patents and/or patent applications resulting from it."
95
 
 
96
 
#include "background_job_manager.h"
97
 
#include <portability/toku_random.h>
98
 
#include <util/frwlock.h>
99
 
#include <util/kibbutz.h>
100
 
#include <util/nb_mutex.h>
101
 
#include <util/partitioned_counter.h>
102
 
 
103
 
//////////////////////////////////////////////////////////////////////////////
104
 
//
105
 
// This file contains the classes and structs that make up the cachetable.
106
 
// The structs are:
107
 
//  - cachefile
108
 
//  - ctpair
109
 
//  - pair_list
110
 
//  - cachefile_list
111
 
//  - checkpointer
112
 
//  - evictor
113
 
//  - cleaner
114
 
//
115
 
// The rest of this comment assumes familiarity with the locks used in these
116
 
// classes/structs and what the locks protect. Nevertheless, here is 
117
 
// a list of the locks that we have:
118
 
//  - pair_list->list_lock
119
 
//  - pair_list->pending_lock_expensive
120
 
//  - pair_list->pending_lock_cheap
121
 
//  - cachefile_list->lock
122
 
//  - PAIR->mutex
123
 
//  - PAIR->value_rwlock
124
 
//  - PAIR->disk_nb_mutex
125
 
//
126
 
// Here are rules for how the locks interact:
127
 
//  - To grab any of the pair_list's locks, or the cachefile_list's lock,
128
 
//      the cachetable must be in existence
129
 
//  - To grab the PAIR mutex, we must know the PAIR will not dissappear:
130
 
//   - the PAIR must be pinned (value_rwlock or disk_nb_mutex is held)
131
 
//   - OR, the pair_list's list lock is held
132
 
//  - As a result, to get rid of a PAIR from the pair_list, we must hold
133
 
//     both the pair_list's list_lock and the PAIR's mutex
134
 
//  - To grab PAIR->value_rwlock, we must hold the PAIR's mutex
135
 
//  - To grab PAIR->disk_nb_mutex, we must hold the PAIR's mutex
136
 
//      and hold PAIR->value_rwlock
137
 
//
138
 
// Now let's talk about ordering. Here is an order from outer to inner (top locks must be grabbed first)
139
 
//  - pair_list->pending_lock_expensive
140
 
//  - pair_list->list_lock
141
 
//  - cachefile_list->lock
142
 
//  - PAIR->mutex
143
 
//  - pair_list->pending_lock_cheap <-- after grabbing this lock, 
144
 
//                                      NO other locks 
145
 
//                                      should be grabbed.
146
 
//  - when grabbing PAIR->value_rwlock or PAIR->disk_nb_mutex,
147
 
//     if the acquisition will not block, then it does not matter if any other locks held,
148
 
//     BUT if the acquisition will block, then NO other locks may be held besides
149
 
//     PAIR->mutex.
150
 
// 
151
 
// HERE ARE TWO EXAMPLES:
152
 
// To pin a PAIR on a client thread, the following must be done:
153
 
//  - first grab the list lock and find the PAIR
154
 
//  - with the list lock grabbed, grab PAIR->mutex
155
 
//  - with PAIR->mutex held:
156
 
//   - release list lock
157
 
//   - pin PAIR
158
 
//   - with PAIR pinned, grab pending_lock_cheap,
159
 
//   - copy and clear PAIR->checkpoint_pending,
160
 
//   - resolve checkpointing if necessary
161
 
//   - return to user.
162
 
//  The list lock may be held while pinning the PAIR if 
163
 
//  the PAIR has no contention. Otherwise, we may have
164
 
//  get a deadlock with another thread that has the PAIR pinned,
165
 
//  tries to pin some other PAIR, and in doing so, grabs the list lock.
166
 
//
167
 
// To unpin a PAIR on a client thread:
168
 
//  - because the PAIR is pinned, we don't need the pair_list's list_lock
169
 
//  - so, simply acquire PAIR->mutex
170
 
//  - unpin the PAIR
171
 
//  - return
172
 
//
173
 
//////////////////////////////////////////////////////////////////////////////
174
 
class evictor;
175
 
class pair_list;
176
 
 
177
 
///////////////////////////////////////////////////////////////////////////////
178
 
//
179
 
// Maps to a file on disk.
180
 
//
181
 
struct cachefile {
182
 
    CACHEFILE next;
183
 
    CACHEFILE prev;
184
 
    // these next two fields are protected by cachetable's list lock
185
 
    // they are managed whenever we add or remove a pair from
186
 
    // the cachetable. As of Riddler, this linked list is only used to
187
 
    // make cachetable_flush_cachefile more efficient
188
 
    PAIR cf_head; // doubly linked list that is NOT circular
189
 
    uint32_t num_pairs; // count on number of pairs in the cachetable belong to this cachefile
190
 
 
191
 
    bool for_checkpoint; //True if part of the in-progress checkpoint
192
 
 
193
 
    // If set and the cachefile closes, the file will be removed.
194
 
    // Clients must not operate on the cachefile after setting this,
195
 
    // nor attempt to open any cachefile with the same fname (dname)
196
 
    // until this cachefile has been fully closed and unlinked.
197
 
    bool unlink_on_close;
198
 
    int fd;       /* Bug: If a file is opened read-only, then it is stuck in read-only.  If it is opened read-write, then subsequent writers can write to it too. */
199
 
    CACHETABLE cachetable;
200
 
    struct fileid fileid;
201
 
    // the filenum is used as an identifer of the cachefile
202
 
    // for logging and recovery
203
 
    FILENUM filenum;
204
 
    // number used to generate hashes for blocks in the cachefile
205
 
    // used in toku_cachetable_hash
206
 
    // this used to be the filenum.fileid, but now it is separate
207
 
    uint32_t hash_id;
208
 
    char *fname_in_env; /* Used for logging */
209
 
 
210
 
    void *userdata;
211
 
    void (*log_fassociate_during_checkpoint)(CACHEFILE cf, void *userdata); // When starting a checkpoint we must log all open files.
212
 
    void (*close_userdata)(CACHEFILE cf, int fd, void *userdata, bool lsnvalid, LSN); // when closing the last reference to a cachefile, first call this function. 
213
 
    void (*free_userdata)(CACHEFILE cf, void *userdata); // when closing the last reference to a cachefile, first call this function. 
214
 
    void (*begin_checkpoint_userdata)(LSN lsn_of_checkpoint, void *userdata); // before checkpointing cachefiles call this function.
215
 
    void (*checkpoint_userdata)(CACHEFILE cf, int fd, void *userdata); // when checkpointing a cachefile, call this function.
216
 
    void (*end_checkpoint_userdata)(CACHEFILE cf, int fd, void *userdata); // after checkpointing cachefiles call this function.
217
 
    void (*note_pin_by_checkpoint)(CACHEFILE cf, void *userdata); // add a reference to the userdata to prevent it from being removed from memory
218
 
    void (*note_unpin_by_checkpoint)(CACHEFILE cf, void *userdata); // add a reference to the userdata to prevent it from being removed from memory
219
 
    BACKGROUND_JOB_MANAGER bjm;
220
 
};
221
 
 
222
 
 
223
 
///////////////////////////////////////////////////////////////////////////////
224
 
//
225
 
//  The pair represents the data stored in the cachetable.
226
 
//
227
 
struct ctpair {
228
 
    // these fields are essentially constants. They do not change.
229
 
    CACHEFILE cachefile;
230
 
    CACHEKEY key;
231
 
    uint32_t fullhash;
232
 
    CACHETABLE_FLUSH_CALLBACK flush_callback;
233
 
    CACHETABLE_PARTIAL_EVICTION_EST_CALLBACK pe_est_callback;
234
 
    CACHETABLE_PARTIAL_EVICTION_CALLBACK pe_callback;
235
 
    CACHETABLE_CLEANER_CALLBACK cleaner_callback;
236
 
    CACHETABLE_CLONE_CALLBACK clone_callback;
237
 
    CACHETABLE_CHECKPOINT_COMPLETE_CALLBACK checkpoint_complete_callback;
238
 
    void *write_extraargs;
239
 
 
240
 
    // access to these fields are protected by disk_nb_mutex
241
 
    void* cloned_value_data; // cloned copy of value_data used for checkpointing
242
 
    long cloned_value_size; // size of cloned_value_data, used for accounting of size_current
243
 
    void* disk_data; // data used to fetch/flush value_data to and from disk.
244
 
 
245
 
    // access to these fields are protected by value_rwlock
246
 
    void* value_data; // data used by client threads, FTNODEs and ROLLBACK_LOG_NODEs
247
 
    PAIR_ATTR attr;
248
 
    enum cachetable_dirty dirty;
249
 
 
250
 
    // protected by PAIR->mutex
251
 
    uint32_t count;        // clock count
252
 
    uint32_t refcount; // if > 0, then this PAIR is referenced by
253
 
                       // callers to the cachetable, and therefore cannot 
254
 
                       // be evicted
255
 
    uint32_t num_waiting_on_refs; // number of threads waiting on refcount to go to zero
256
 
    toku_cond_t refcount_wait; // cond used to wait for refcount to go to zero
257
 
 
258
 
    // locks
259
 
    toku::frwlock value_rwlock;
260
 
    struct nb_mutex disk_nb_mutex; // single writer, protects disk_data, is used for writing cloned nodes for checkpoint
261
 
    toku_mutex_t* mutex; // gotten from the pair list
262
 
 
263
 
    // Access to checkpoint_pending is protected by two mechanisms,
264
 
    // the value_rwlock and the pair_list's pending locks (expensive and cheap).
265
 
    // checkpoint_pending may be true of false. 
266
 
    // Here are the rules for reading/modifying this bit.
267
 
    //  - To transition this field from false to true during begin_checkpoint,
268
 
    //   we must be holding both of the pair_list's pending locks.
269
 
    //  - To transition this field from true to false during end_checkpoint,
270
 
    //   we must be holding the value_rwlock.
271
 
    //  - For a non-checkpoint thread to read the value, we must hold both the
272
 
    //   value_rwlock and one of the pair_list's pending locks
273
 
    //  - For the checkpoint thread to read the value, we must 
274
 
    //   hold the value_rwlock
275
 
    //
276
 
    bool checkpoint_pending; // If this is on, then we have got to resolve checkpointing modifying it.
277
 
 
278
 
    // these are variables that are only used to transfer information to background threads
279
 
    // we cache them here to avoid a malloc. In the future, we should investigate if this
280
 
    // is necessary, as having these fields here is not technically necessary
281
 
    long size_evicting_estimate;
282
 
    evictor* ev;
283
 
    pair_list* list;
284
 
 
285
 
    // A PAIR is stored in a pair_list (which happens to be PAIR->list).
286
 
    // These variables are protected by the list lock in the pair_list
287
 
    //
288
 
    // clock_next,clock_prev represent a circular doubly-linked list.
289
 
    PAIR clock_next,clock_prev; // In clock.
290
 
    PAIR hash_chain;
291
 
 
292
 
    // pending_next,pending_next represent a non-circular doubly-linked list.
293
 
    PAIR pending_next;
294
 
    PAIR pending_prev;
295
 
 
296
 
    // cf_next, cf_prev represent a non-circular doubly-linked list.
297
 
    // entries in linked list for PAIRs in a cachefile, these are protected
298
 
    // by the list lock of the PAIR's pair_list. They are used to make
299
 
    // cachetable_flush_cachefile cheaper so that we don't need
300
 
    // to search the entire cachetable to find a particular cachefile's
301
 
    // PAIRs
302
 
    PAIR cf_next;
303
 
    PAIR cf_prev;
304
 
};
305
 
 
306
 
//
307
 
// This initializes the fields and members of the pair.
308
 
//
309
 
void pair_init(PAIR p,
310
 
    CACHEFILE cachefile,
311
 
    CACHEKEY key,
312
 
    void *value,
313
 
    PAIR_ATTR attr,
314
 
    enum cachetable_dirty dirty,
315
 
    uint32_t fullhash,
316
 
    CACHETABLE_WRITE_CALLBACK write_callback,
317
 
    evictor *ev,
318
 
    pair_list *list);
319
 
 
320
 
 
321
 
///////////////////////////////////////////////////////////////////////////////
322
 
//
323
 
//  The pair list maintains the set of PAIR's that make up
324
 
//  the cachetable.
325
 
//
326
 
class pair_list {
327
 
public:
328
 
    //
329
 
    // the following fields are protected by the list lock
330
 
    // 
331
 
    uint32_t m_n_in_table; // number of pairs in the hash table
332
 
    uint32_t m_table_size; // number of buckets in the hash table
333
 
    uint32_t m_num_locks;
334
 
    PAIR *m_table; // hash table
335
 
    toku_mutex_aligned_t *m_mutexes; 
336
 
    // 
337
 
    // The following fields are the heads of various linked lists.
338
 
    // They also protected by the list lock, but their 
339
 
    // usage is not as straightforward. For each of them,
340
 
    // only ONE thread is allowed iterate over them with 
341
 
    // a read lock on the list lock. All other threads
342
 
    // that want to modify elements in the lists or iterate over
343
 
    // the lists must hold the write list lock. Here is the
344
 
    // association between what threads may hold a read lock
345
 
    // on the list lock while iterating:
346
 
    //  - clock_head -> eviction thread (evictor)
347
 
    //  - cleaner_head -> cleaner thread (cleaner)
348
 
    //  - pending_head -> checkpoint thread (checkpointer)
349
 
    //
350
 
    PAIR m_clock_head; // of clock . head is the next thing to be up for decrement. 
351
 
    PAIR m_cleaner_head; // for cleaner thread. head is the next thing to look at for possible cleaning.
352
 
    PAIR m_checkpoint_head; // for begin checkpoint to iterate over PAIRs and mark as pending_checkpoint
353
 
    PAIR m_pending_head; // list of pairs marked with checkpoint_pending
354
 
 
355
 
    // this field is public so we are still POD
356
 
 
357
 
    // usage of this lock is described above
358
 
    toku_pthread_rwlock_t m_list_lock;
359
 
    //
360
 
    // these locks are the "pending locks" referenced 
361
 
    // in comments about PAIR->checkpoint_pending. There
362
 
    // are two of them, but both serve the same purpose, which
363
 
    // is to protect the transition of a PAIR's checkpoint pending
364
 
    // value from false to true during begin_checkpoint.
365
 
    // We use two locks, because threads that want to read the
366
 
    // checkpoint_pending value may hold a lock for varying periods of time.
367
 
    // Threads running eviction may need to protect checkpoint_pending
368
 
    // while writing a node to disk, which is an expensive operation,
369
 
    // so it uses pending_lock_expensive. Client threads that
370
 
    // want to pin PAIRs will want to protect checkpoint_pending
371
 
    // just long enough to read the value and wipe it out. This is
372
 
    // a cheap operation, and as a result, uses pending_lock_cheap.
373
 
    //
374
 
    // By having two locks, and making begin_checkpoint first 
375
 
    // grab pending_lock_expensive and then pending_lock_cheap,
376
 
    // we ensure that threads that want to pin nodes can grab
377
 
    // only pending_lock_cheap, and never block behind threads
378
 
    // holding pending_lock_expensive and writing a node out to disk
379
 
    //
380
 
    toku_pthread_rwlock_t m_pending_lock_expensive;
381
 
    toku_pthread_rwlock_t m_pending_lock_cheap;
382
 
    void init();
383
 
    void destroy();
384
 
    void evict_completely(PAIR pair);
385
 
    void evict_from_cachetable(PAIR pair);
386
 
    void evict_from_cachefile(PAIR pair);
387
 
    void add_to_cachetable_only(PAIR p);
388
 
    void put(PAIR pair);
389
 
    PAIR find_pair(CACHEFILE file, CACHEKEY key, uint32_t hash);
390
 
    void pending_pairs_remove (PAIR p);
391
 
    void verify();
392
 
    void get_state(int *num_entries, int *hash_size);
393
 
    void read_list_lock();
394
 
    void read_list_unlock();
395
 
    void write_list_lock();
396
 
    void write_list_unlock();
397
 
    void read_pending_exp_lock();
398
 
    void read_pending_exp_unlock();
399
 
    void write_pending_exp_lock();
400
 
    void write_pending_exp_unlock();
401
 
    void read_pending_cheap_lock();
402
 
    void read_pending_cheap_unlock();
403
 
    void write_pending_cheap_lock();
404
 
    void write_pending_cheap_unlock();
405
 
    toku_mutex_t* get_mutex_for_pair(uint32_t fullhash);
406
 
    void pair_lock_by_fullhash(uint32_t fullhash);
407
 
    void pair_unlock_by_fullhash(uint32_t fullhash);
408
 
 
409
 
private:
410
 
    void pair_remove (PAIR p);
411
 
    void remove_from_hash_chain(PAIR p);
412
 
    void add_to_cf_list (PAIR p);
413
 
    void add_to_clock (PAIR p);
414
 
    void add_to_hash_chain(PAIR p);
415
 
};
416
 
 
417
 
///////////////////////////////////////////////////////////////////////////////
418
 
//
419
 
// Wrapper for the head of our cachefile list.
420
 
//
421
 
class cachefile_list {
422
 
public:
423
 
    void init();
424
 
    void destroy();
425
 
    void read_lock();
426
 
    void read_unlock();
427
 
    void write_lock();
428
 
    void write_unlock();
429
 
    int cachefile_of_iname_in_env(const char *iname_in_env, CACHEFILE *cf);
430
 
    int cachefile_of_filenum(FILENUM filenum, CACHEFILE *cf);
431
 
    void add_cf_unlocked(CACHEFILE newcf);
432
 
    void add_stale_cf(CACHEFILE newcf);
433
 
    void remove_cf(CACHEFILE cf);
434
 
    void remove_stale_cf_unlocked(CACHEFILE cf);
435
 
    FILENUM reserve_filenum();
436
 
    uint32_t get_new_hash_id_unlocked();
437
 
    CACHEFILE find_cachefile_unlocked(struct fileid* fileid);
438
 
    CACHEFILE find_stale_cachefile_unlocked(struct fileid* fileid);
439
 
    void verify_unused_filenum(FILENUM filenum);
440
 
    bool evict_some_stale_pair(evictor* ev);
441
 
    void free_stale_data(evictor* ev);
442
 
    // access to these fields are protected by the lock
443
 
    CACHEFILE m_active_head; // head of CACHEFILEs that are active
444
 
    CACHEFILE m_stale_head; // head of CACHEFILEs that are stale
445
 
    CACHEFILE m_stale_tail; // tail of CACHEFILEs that are stale
446
 
    FILENUM m_next_filenum_to_use;
447
 
    uint32_t m_next_hash_id_to_use;
448
 
    toku_pthread_rwlock_t m_lock; // this field is publoc so we are still POD
449
 
    toku::omt<CACHEFILE> m_active_filenum;
450
 
    toku::omt<CACHEFILE> m_active_fileid;
451
 
private:    
452
 
    CACHEFILE find_cachefile_in_list_unlocked(CACHEFILE start, struct fileid* fileid);
453
 
};
454
 
 
455
 
 
456
 
///////////////////////////////////////////////////////////////////////////////
457
 
//
458
 
//  The checkpointer handles starting and finishing checkpoints of the 
459
 
//  cachetable's data.
460
 
//
461
 
class checkpointer {
462
 
public:
463
 
    int init(pair_list *_pl, TOKULOGGER _logger, evictor *_ev, cachefile_list *files);
464
 
    void destroy();
465
 
    void set_checkpoint_period(uint32_t new_period);
466
 
    uint32_t get_checkpoint_period();
467
 
    int shutdown();
468
 
    bool has_been_shutdown();
469
 
    void begin_checkpoint();
470
 
    void add_background_job();
471
 
    void remove_background_job();
472
 
    void end_checkpoint(void (*testcallback_f)(void*),  void* testextra);
473
 
    TOKULOGGER get_logger();
474
 
    // used during begin_checkpoint
475
 
    void increment_num_txns();
476
 
private:
477
 
    uint32_t m_checkpoint_num_txns;   // how many transactions are in the checkpoint
478
 
    TOKULOGGER m_logger;
479
 
    LSN m_lsn_of_checkpoint_in_progress;
480
 
    uint32_t m_checkpoint_num_files; // how many cachefiles are in the checkpoint
481
 
    struct minicron m_checkpointer_cron; // the periodic checkpointing thread
482
 
    cachefile_list *m_cf_list;
483
 
    pair_list *m_list;
484
 
    evictor *m_ev;
485
 
    bool m_checkpointer_cron_init;
486
 
    bool m_checkpointer_init;
487
 
    
488
 
    // variable used by the checkpoint thread to know
489
 
    // when all work induced by cloning on client threads is done
490
 
    BACKGROUND_JOB_MANAGER m_checkpoint_clones_bjm;
491
 
    // private methods for begin_checkpoint    
492
 
    void update_cachefiles();
493
 
    void log_begin_checkpoint();
494
 
    void turn_on_pending_bits();
495
 
    // private methods for end_checkpoint    
496
 
    void fill_checkpoint_cfs(CACHEFILE* checkpoint_cfs);
497
 
    void checkpoint_pending_pairs();
498
 
    void checkpoint_userdata(CACHEFILE* checkpoint_cfs);
499
 
    void log_end_checkpoint();
500
 
    void end_checkpoint_userdata(CACHEFILE* checkpoint_cfs);
501
 
    void remove_cachefiles(CACHEFILE* checkpoint_cfs);
502
 
    
503
 
    // Unit test struct needs access to private members.
504
 
    friend struct checkpointer_test;
505
 
};
506
 
 
507
 
//
508
 
// This is how often we want the eviction thread
509
 
// to run, in seconds.
510
 
//
511
 
const int EVICTION_PERIOD = 1;
512
 
 
513
 
///////////////////////////////////////////////////////////////////////////////
514
 
//
515
 
// The evictor handles the removal of pairs from the pair list/cachetable.
516
 
//
517
 
class evictor {
518
 
public:
519
 
    int init(long _size_limit, pair_list* _pl, cachefile_list* _cf_list, KIBBUTZ _kibbutz, uint32_t eviction_period);
520
 
    void destroy();
521
 
    void add_pair_attr(PAIR_ATTR attr);
522
 
    void remove_pair_attr(PAIR_ATTR attr);    
523
 
    void change_pair_attr(PAIR_ATTR old_attr, PAIR_ATTR new_attr);
524
 
    void add_to_size_current(long size);
525
 
    void remove_from_size_current(long size);
526
 
    uint64_t reserve_memory(double fraction, uint64_t upper_bound);
527
 
    void release_reserved_memory(uint64_t reserved_memory);
528
 
    void run_eviction_thread();
529
 
    void do_partial_eviction(PAIR p);
530
 
    void evict_pair(PAIR p, bool checkpoint_pending);
531
 
    void wait_for_cache_pressure_to_subside();
532
 
    void signal_eviction_thread();
533
 
    bool should_client_thread_sleep();
534
 
    bool should_client_wake_eviction_thread();
535
 
    // function needed for testing
536
 
    void get_state(long *size_current_ptr, long *size_limit_ptr);
537
 
    void fill_engine_status();
538
 
private:
539
 
    void run_eviction();
540
 
    bool run_eviction_on_pair(PAIR p);
541
 
    void try_evict_pair(PAIR p);
542
 
    void decrease_size_evicting(long size_evicting_estimate);
543
 
    bool should_sleeping_clients_wakeup();
544
 
    bool eviction_needed();
545
 
 
546
 
    // We have some intentional races with these variables because we're ok with reading something a little bit old.
547
 
    // Provide some hooks for reading variables in an unsafe way so that there are function names we can stick in a valgrind suppression.
548
 
    int64_t unsafe_read_size_current(void) const;
549
 
    int64_t unsafe_read_size_evicting(void) const;
550
 
 
551
 
    pair_list* m_pl;
552
 
    cachefile_list* m_cf_list;
553
 
    int64_t m_size_current;            // the sum of the sizes of the pairs in the cachetable
554
 
    // changes to these two values are protected
555
 
    // by ev_thread_lock
556
 
    int64_t m_size_reserved;           // How much memory is reserved (e.g., by the loader)
557
 
    int64_t m_size_evicting;           // the sum of the sizes of the pairs being written
558
 
 
559
 
    // these are constants
560
 
    int64_t m_low_size_watermark; // target max size of cachetable that eviction thread aims for
561
 
    int64_t m_low_size_hysteresis; // if cachetable grows to this size, client threads wake up eviction thread upon adding data
562
 
    int64_t m_high_size_watermark; // if cachetable grows to this size, client threads sleep upon adding data
563
 
    int64_t m_high_size_hysteresis; // if > cachetable size, then sleeping client threads may wake up
564
 
 
565
 
    // used to calculate random numbers
566
 
    struct random_data m_random_data;
567
 
    char m_random_statebuf[64];
568
 
 
569
 
    // mutex that protects fields listed immedietly below
570
 
    toku_mutex_t m_ev_thread_lock;
571
 
    // the eviction thread
572
 
    toku_pthread_t m_ev_thread;
573
 
    // condition variable that controls the sleeping period
574
 
    // of the eviction thread
575
 
    toku_cond_t m_ev_thread_cond;
576
 
    // number of client threads that are currently sleeping
577
 
    // due to an over-subscribed cachetable
578
 
    uint32_t m_num_sleepers;
579
 
    // states if the eviction thread should run. set to true
580
 
    // in init, set to false during destroy
581
 
    bool m_run_thread;
582
 
    // bool that states if the eviction thread is currently running
583
 
    bool m_ev_thread_is_running;
584
 
    // period which the eviction thread sleeps
585
 
    uint32_t m_period_in_seconds;
586
 
    // condition variable on which client threads wait on when sleeping
587
 
    // due to an over-subscribed cachetable
588
 
    toku_cond_t m_flow_control_cond;
589
 
 
590
 
    // variables for engine status
591
 
    PARTITIONED_COUNTER m_size_nonleaf;
592
 
    PARTITIONED_COUNTER m_size_leaf;
593
 
    PARTITIONED_COUNTER m_size_rollback;
594
 
    PARTITIONED_COUNTER m_size_cachepressure;
595
 
    PARTITIONED_COUNTER m_wait_pressure_count;
596
 
    PARTITIONED_COUNTER m_wait_pressure_time;
597
 
    PARTITIONED_COUNTER m_long_wait_pressure_count;
598
 
    PARTITIONED_COUNTER m_long_wait_pressure_time;
599
 
    
600
 
    KIBBUTZ m_kibbutz;
601
 
 
602
 
    // this variable is ONLY used for testing purposes
603
 
    uint64_t m_num_eviction_thread_runs;
604
 
 
605
 
    bool m_ev_thread_init;
606
 
    bool m_evictor_init;
607
 
 
608
 
    friend class evictor_test_helpers;
609
 
    friend class evictor_unit_test;
610
 
};
611
 
 
612
 
///////////////////////////////////////////////////////////////////////////////
613
 
//
614
 
// Iterates over the clean head in the pair list, calling the cleaner
615
 
// callback on each node in that list.
616
 
//
617
 
class cleaner {
618
 
public:
619
 
    int init(uint32_t cleaner_iterations, pair_list* _pl, CACHETABLE _ct);
620
 
    void destroy(void);
621
 
    uint32_t get_iterations(void);
622
 
    void set_iterations(uint32_t new_iterations);
623
 
    uint32_t get_period_unlocked(void);
624
 
    void set_period(uint32_t new_period);
625
 
    int run_cleaner(void);
626
 
    
627
 
private:
628
 
    pair_list* m_pl;
629
 
    CACHETABLE m_ct;
630
 
    struct minicron m_cleaner_cron; // the periodic cleaner thread
631
 
    uint32_t m_cleaner_iterations; // how many times to run the cleaner per
632
 
                                  // cleaner period (minicron has a
633
 
                                  // minimum period of 1s so if you want
634
 
                                  // more frequent cleaner runs you must
635
 
                                  // use this)
636
 
    bool m_cleaner_cron_init;
637
 
    bool m_cleaner_init;
638
 
};
639
 
 
640
 
///////////////////////////////////////////////////////////////////////////////
641
 
//
642
 
// The cachetable is as close to an ENV as we get.
643
 
//
644
 
struct cachetable {
645
 
    pair_list list;
646
 
    cleaner cl;
647
 
    evictor ev;
648
 
    checkpointer cp;
649
 
    cachefile_list cf_list;
650
 
    
651
 
    KIBBUTZ client_kibbutz; // pool of worker threads and jobs to do asynchronously for the client.
652
 
    KIBBUTZ ct_kibbutz; // pool of worker threads and jobs to do asynchronously for the cachetable
653
 
    KIBBUTZ checkpointing_kibbutz; // small pool for checkpointing cloned pairs
654
 
 
655
 
    char *env_dir;
656
 
};
657
 
 
658
 
#endif // End of header guardian.