1 /*------------------------------------------------------------------------------
2  *
3  * Copyright (c) 2011-2021, EURid vzw. All rights reserved.
4  * The YADIFA TM software product is provided under the BSD 3-clause license:
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  *
10  *        * Redistributions of source code must retain the above copyright
11  *          notice, this list of conditions and the following disclaimer.
12  *        * Redistributions in binary form must reproduce the above copyright
13  *          notice, this list of conditions and the following disclaimer in the
14  *          documentation and/or other materials provided with the distribution.
15  *        * Neither the name of EURid nor the names of its contributors may be
16  *          used to endorse or promote products derived from this software
17  *          without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
23  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29  * POSSIBILITY OF SUCH DAMAGE.
30  *
31  *------------------------------------------------------------------------------
32  *
33  */
34 
35 /** @defgroup dnsdbzone Zone related functions
36  *  @ingroup dnsdb
37  *  @brief Functions used to manipulate a zone
38  *
39  *  Functions used to manipulate a zone
40  *
41  * @{
42  */
43 
44 #pragma once
45 
46 #include <dnsdb/zdb_types.h>
47 
48 #ifdef	__cplusplus
49 extern "C"
50 {
51 #endif
52 
53 /**
54  * Zone locking
55  *
56  * Sets the owner of a zone.
57  *
58  * The owner id has a format: the msb is reserved to say that the access is
59  * exclusive to only one instance of the owner.
60  * The remaining bits are the id.
61  *
62  * Mostly used for the simple reader and various writers.
63  *
64  * A new feature needs to be added: being able to pre-lock for an owner.
65  *
66  * Explanation: I want to lock for the signing process.  But that process
67  * is done in two or three phases.  The first phase is read-only (thus allowing
68  * the server to work normally).  But I don't want somebody else, say, a dynamic
69  * update, to lock the zone in the mean time. (Which would happen when the lock
70  * is transferred from the reader to the signer (at the commit phase).
71  * So I'll add a secondary owner, meant to tell "I lock as a reader BUT I also
72  * reserve the right for myself later".  And later a transfer can be done to
73  * the secondary as soon as the last reader unlocks.
74  *
75  * zdb_zone_double_lock(zone, owner, secondary owner)
76  * zdb_zone_try_double_lock(zone, owner, secondary owner)
77  * zdb_zone_transfer_lock(zone, secondary owner)
78  *
79  * The parameter would need to be repeated to detect inconsistencies (bugs)
80  *
81  * This should have no effect on the normal locking mechanism, thus ensuring
82  * no loss of speed.  The only goal is to avoid a race changing the owner.
83  *
84  * Having only zdb_zone_transfer_lock(zone, old owner, new owner) cannot work
85  * because nothing prevents two soon-to-be writers to lock and work in tandem.
86  *
87  */
88 
89 void zdb_zone_lock(zdb_zone *zone, u8 owner);
90 
91 bool zdb_zone_trylock(zdb_zone *zone, u8 owner);
92 
93 bool zdb_zone_trylock_wait(zdb_zone *zone, u64 usec, u8 owner);
94 
95 void zdb_zone_unlock(zdb_zone *zone, u8 owner);
96 
97 bool zdb_zone_islocked(zdb_zone *zone);
98 
99 /**
100  * Functions for internal testing, do not use.
101  *
102  * @param zone
103  * @return
104  */
105 
106 bool zdb_zone_islocked_weak(const zdb_zone *zone);
107 
108 /**
109  * Functions for internal testing, do not use.
110  *
111  * @param zone
112  * @return
113  */
114 
115 bool zdb_zone_islocked_weak(const zdb_zone *zone);
116 
117 /**
118  * Functions for internal testing, do not use.
119  *
120  * @param zone
121  * @return
122  */
123 
124 bool zdb_zone_islocked_weak(const zdb_zone *zone);
125 
126 /**
127  * Functions for internal testing, do not use.
128  *
129  * @param zone
130  * @return
131  */
132 
133 bool zdb_zone_islocked_weak(const zdb_zone *zone);
134 
135 /**
136  * Returns TRUE iff the zone is locked by a writer (any other owner value than nobody and simple reader)
137  *
138  * @param zone
139  * @return
140  */
141 
142 bool zdb_zone_iswritelocked(zdb_zone *zone);
143 
144 /**
145  * Reserves the secondary owner and to locks for the owner
146  *
147  * @param zone
148  * @param owner
149  * @param secondary_owner
150  */
151 
152 void zdb_zone_double_lock(zdb_zone *zone, u8 owner, u8 secondary_owner);
153 
154 /**
155  * Tries to reserve the secondary owner and to lock for the owner
156  *
157  * @param zone
158  * @param owner
159  * @param secondary_owner
160  */
161 
162 bool zdb_zone_try_double_lock(zdb_zone *zone, u8 owner, u8 secondary_owner);
163 
164 /**
165  * Tries to reserve the secondary owner and to lock for the owner.
166  * Gets the current owner if the lock fails.
167  * If the lock succeeds the current_ownerp and current_reserved_ownerp poited values's content is undefined.
168  *
169  * @param zone
170  * @param owner
171  * @param secondary_owner
172  * @param current_ownerp
173  * @param current_reserved_ownerp
174  */
175 
176 bool zdb_zone_try_double_lock_ex(zdb_zone *zone, u8 owner, u8 secondary_owner, u8 *current_ownerp, u8 *current_reserved_ownerp);
177 
178 /**
179  *
180  * Unlocks one owner and sets the secondary owner to nobody
181  *
182  * @param zone
183  * @param owner
184  * @param secondary_owner
185  */
186 
187 void zdb_zone_double_unlock(zdb_zone *zone, u8 owner, u8 secondary_owner);
188 
189 /**
190  *
191  * Puts the secondary lock in place of the lock when the locker count reaches 1
192  * Followed by a zdb_zone_unlock
193  *
194  * @param zone
195  * @param owner
196  * @param secondary_owner
197  */
198 
199 void zdb_zone_transfer_lock(zdb_zone *zone, u8 owner, u8 secondary_owner);
200 
201 /**
202  *
203  * Puts the secondary lock in place of the lock when the locker count reaches 1
204  * Followed by a zdb_zone_unlock
205  *
206  * @param zone
207  * @param owner
208  * @param secondary_owner
209  */
210 
211 bool zdb_zone_try_transfer_lock(zdb_zone *zone, u8 owner, u8 secondary_owner);
212 
213 /**
214  *
215  * Exchange the primary and secondary locks when the locker count reaches 1
216  * Followed by a zdb_zone_unlock
217  *
218  * @param zone
219  * @param owner
220  * @param secondary_owner
221  */
222 
223 void zdb_zone_exchange_locks(zdb_zone *zone, u8 owner, u8 secondary_owner);
224 
225 #if DNSCORE_HAS_MUTEX_DEBUG_SUPPORT
226 void zdb_zone_lock_set_monitor();
227 #endif
228 
229 /** @} */
230