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 /*
10  * Helpers for calling a function with a data handle in session->dhandle
11  * then restoring afterwards.
12  */
13 #define	WT_WITH_DHANDLE(s, d, e) do {					\
14 	WT_DATA_HANDLE *__saved_dhandle = (s)->dhandle;			\
15 	(s)->dhandle = (d);						\
16 	e;								\
17 	(s)->dhandle = __saved_dhandle;					\
18 } while (0)
19 
20 #define	WT_WITH_BTREE(s, b, e)	WT_WITH_DHANDLE(s, (b)->dhandle, e)
21 
22 /* Call a function without the caller's data handle, restore afterwards. */
23 #define	WT_WITHOUT_DHANDLE(s, e) WT_WITH_DHANDLE(s, NULL, e)
24 
25 /*
26  * Call a function with the caller's data handle, restore it afterwards in case
27  * it is overwritten.
28  */
29 #define	WT_SAVE_DHANDLE(s, e) WT_WITH_DHANDLE(s, (s)->dhandle, e)
30 
31 /* Check if a handle is inactive. */
32 #define	WT_DHANDLE_INACTIVE(dhandle)					\
33 	(F_ISSET(dhandle, WT_DHANDLE_DEAD) ||				\
34 	!F_ISSET(dhandle, WT_DHANDLE_EXCLUSIVE | WT_DHANDLE_OPEN))
35 
36 /* Check if a handle could be reopened. */
37 #define	WT_DHANDLE_CAN_REOPEN(dhandle)					\
38 	(!WT_DHANDLE_INACTIVE(dhandle) &&				\
39 	F_ISSET(dhandle, WT_DHANDLE_OPEN) &&				\
40 	!F_ISSET(dhandle, WT_DHANDLE_DROPPED))
41 
42 /* The metadata cursor's data handle. */
43 #define	WT_SESSION_META_DHANDLE(s)					\
44 	(((WT_CURSOR_BTREE *)((s)->meta_cursor))->btree->dhandle)
45 
46 #define	WT_DHANDLE_ACQUIRE(dhandle)					\
47     (void)__wt_atomic_add32(&(dhandle)->session_ref, 1)
48 
49 #define	WT_DHANDLE_RELEASE(dhandle)					\
50     (void)__wt_atomic_sub32(&(dhandle)->session_ref, 1)
51 
52 #define	WT_DHANDLE_NEXT(session, dhandle, head, field) do {		\
53 	WT_ASSERT(session, F_ISSET(session, WT_SESSION_LOCKED_HANDLE_LIST));\
54 	if ((dhandle) == NULL)						\
55 		(dhandle) = TAILQ_FIRST(head);				\
56 	else {								\
57 		WT_DHANDLE_RELEASE(dhandle);				\
58 		(dhandle) = TAILQ_NEXT(dhandle, field);			\
59 	}								\
60 	if ((dhandle) != NULL)						\
61 		WT_DHANDLE_ACQUIRE(dhandle);				\
62 } while (0)
63 
64 /*
65  * WT_DATA_HANDLE --
66  *	A handle for a generic named data source.
67  */
68 struct __wt_data_handle {
69 	WT_RWLOCK rwlock;		/* Lock for shared/exclusive ops */
70 	TAILQ_ENTRY(__wt_data_handle) q;
71 	TAILQ_ENTRY(__wt_data_handle) hashq;
72 
73 	const char *name;		/* Object name as a URI */
74 	uint64_t name_hash;		/* Hash of name */
75 	const char *checkpoint;		/* Checkpoint name (or NULL) */
76 	const char **cfg;		/* Configuration information */
77 	const char *meta_base;		/* Base metadata configuration */
78 
79 	/*
80 	 * Sessions holding a connection's data handle will have a non-zero
81 	 * reference count; sessions using a connection's data handle will
82 	 * have a non-zero in-use count. Instances of cached cursors referencing
83 	 * the data handle appear in session_cache_ref.
84 	 */
85 	uint32_t session_ref;		/* Sessions referencing this handle */
86 	int32_t	 session_inuse;		/* Sessions using this handle */
87 	uint32_t excl_ref;		/* Refs of handle by excl_session */
88 	time_t	 timeofdeath;		/* Use count went to 0 */
89 	WT_SESSION_IMPL *excl_session;	/* Session with exclusive use, if any */
90 
91 	WT_DATA_SOURCE *dsrc;		/* Data source for this handle */
92 	void *handle;			/* Generic handle */
93 
94 	enum {
95 		WT_DHANDLE_TYPE_BTREE,
96 		WT_DHANDLE_TYPE_TABLE
97 	} type;
98 
99 	bool compact_skip;		/* If the handle failed to compact */
100 
101 	/*
102 	 * Data handles can be closed without holding the schema lock; threads
103 	 * walk the list of open handles, operating on them (checkpoint is the
104 	 * best example).  To avoid sources disappearing underneath checkpoint,
105 	 * lock the data handle when closing it.
106 	 */
107 	WT_SPINLOCK	close_lock;	/* Lock to close the handle */
108 
109 					/* Data-source statistics */
110 	WT_DSRC_STATS *stats[WT_COUNTER_SLOTS];
111 	WT_DSRC_STATS *stat_array;
112 
113 	/* Flags values over 0xff are reserved for WT_BTREE_* */
114 /* AUTOMATIC FLAG VALUE GENERATION START */
115 #define	WT_DHANDLE_DEAD		        0x01u	/* Dead, awaiting discard */
116 #define	WT_DHANDLE_DISCARD	        0x02u	/* Close on release */
117 #define	WT_DHANDLE_DISCARD_KILL		0x04u	/* Mark dead on release */
118 #define	WT_DHANDLE_DROPPED	        0x08u	/* Handle is dropped */
119 #define	WT_DHANDLE_EXCLUSIVE	        0x10u	/* Exclusive access */
120 #define	WT_DHANDLE_IS_METADATA		0x20u	/* Metadata handle */
121 #define	WT_DHANDLE_LOCK_ONLY	        0x40u	/* Handle only used as a lock */
122 #define	WT_DHANDLE_OPEN		        0x80u	/* Handle is open */
123 /* AUTOMATIC FLAG VALUE GENERATION STOP */
124 	uint32_t flags;
125 };
126