1 /*- 2 * Copyright (c) 2014-2018 MongoDB, Inc. 3 * Copyright (c) 2008-2014 WiredTiger, Inc. 4 * All rights reserved. 5 * 6 * See the file LICENSE for redistribution information. 7 */ 8 9 #define MAX_ASYNC_SLEEP_USECS 100000 /* Maximum sleep waiting for work */ 10 #define MAX_ASYNC_YIELD 200 /* Maximum number of yields for work */ 11 12 #define O2C(op) ((WT_CONNECTION_IMPL *)(op)->iface.connection) 13 #define O2S(op) \ 14 (((WT_CONNECTION_IMPL *)(op)->iface.connection)->default_session) 15 /* 16 * WT_ASYNC_FORMAT -- 17 * The URI/config/format cache. 18 */ 19 struct __wt_async_format { 20 TAILQ_ENTRY(__wt_async_format) q; 21 const char *config; 22 uint64_t cfg_hash; /* Config hash */ 23 const char *uri; 24 uint64_t uri_hash; /* URI hash */ 25 const char *key_format; 26 const char *value_format; 27 }; 28 29 /* 30 * WT_ASYNC_OP_IMPL -- 31 * Implementation of the WT_ASYNC_OP. 32 */ 33 struct __wt_async_op_impl { 34 WT_ASYNC_OP iface; 35 36 WT_ASYNC_CALLBACK *cb; 37 38 uint32_t internal_id; /* Array position id. */ 39 uint64_t unique_id; /* Unique identifier. */ 40 41 WT_ASYNC_FORMAT *format; /* Format structure */ 42 43 #define WT_ASYNCOP_ENQUEUED 0 /* Placed on the work queue */ 44 #define WT_ASYNCOP_FREE 1 /* Able to be allocated to user */ 45 #define WT_ASYNCOP_READY 2 /* Allocated, ready for user to use */ 46 #define WT_ASYNCOP_WORKING 3 /* Operation in progress by worker */ 47 uint32_t state; 48 49 WT_ASYNC_OPTYPE optype; /* Operation type */ 50 }; 51 52 /* 53 * Definition of the async subsystem. 54 */ 55 struct __wt_async { 56 /* 57 * Ops array protected by the ops_lock. 58 */ 59 WT_SPINLOCK ops_lock; /* Locked: ops array */ 60 WT_ASYNC_OP_IMPL *async_ops; /* Async ops */ 61 #define OPS_INVALID_INDEX 0xffffffff 62 uint32_t ops_index; /* Active slot index */ 63 uint64_t op_id; /* Unique ID counter */ 64 WT_ASYNC_OP_IMPL **async_queue; /* Async ops work queue */ 65 uint32_t async_qsize; /* Async work queue size */ 66 /* 67 * We need to have two head and tail values. All but one is 68 * maintained as an ever increasing value to ease wrap around. 69 * 70 * alloc_head: the next one to allocate for producers. 71 * head: the current head visible to consumers. 72 * head is always <= alloc_head. 73 * alloc_tail: the next slot for consumers to dequeue. 74 * alloc_tail is always <= head. 75 * tail_slot: the last slot consumed. 76 * A producer may need wait for tail_slot to advance. 77 */ 78 uint64_t alloc_head; /* Next slot to enqueue */ 79 uint64_t head; /* Head visible to worker */ 80 uint64_t alloc_tail; /* Next slot to dequeue */ 81 uint64_t tail_slot; /* Worker slot consumed */ 82 83 TAILQ_HEAD(__wt_async_format_qh, __wt_async_format) formatqh; 84 uint32_t cur_queue; /* Currently enqueued */ 85 uint32_t max_queue; /* Maximum enqueued */ 86 87 #define WT_ASYNC_FLUSH_NONE 0 /* No flush in progress */ 88 #define WT_ASYNC_FLUSH_COMPLETE 1 /* Notify flush caller done */ 89 #define WT_ASYNC_FLUSH_IN_PROGRESS 2 /* Prevent other callers */ 90 #define WT_ASYNC_FLUSHING 3 /* Notify workers */ 91 uint32_t flush_state; 92 93 /* Notify any waiting threads when flushing is done. */ 94 WT_CONDVAR *flush_cond; 95 WT_ASYNC_OP_IMPL flush_op; /* Special flush op */ 96 uint32_t flush_count; /* Worker count */ 97 uint64_t flush_gen; /* Flush generation number */ 98 99 #define WT_ASYNC_MAX_WORKERS 20 100 WT_SESSION_IMPL *worker_sessions[WT_ASYNC_MAX_WORKERS]; 101 /* Async worker threads */ 102 wt_thread_t worker_tids[WT_ASYNC_MAX_WORKERS]; 103 104 uint32_t flags; /* Currently unused. */ 105 }; 106 107 /* 108 * WT_ASYNC_CURSOR -- 109 * Async container for a cursor. Each async worker thread 110 * has a cache of async cursors to reuse for operations. 111 */ 112 struct __wt_async_cursor { 113 TAILQ_ENTRY(__wt_async_cursor) q; /* Worker cache */ 114 uint64_t cfg_hash; /* Config hash */ 115 uint64_t uri_hash; /* URI hash */ 116 WT_CURSOR *c; /* WT cursor */ 117 }; 118 119 /* 120 * WT_ASYNC_WORKER_STATE -- 121 * State for an async worker thread. 122 */ 123 struct __wt_async_worker_state { 124 uint32_t id; 125 TAILQ_HEAD(__wt_cursor_qh, __wt_async_cursor) cursorqh; 126 uint32_t num_cursors; 127 }; 128