]> git.saurik.com Git - apple/configd.git/blob - configd.tproj/_SCD.c
57bdaad0123197a1479a9cc3f8680f89b9841558
[apple/configd.git] / configd.tproj / _SCD.c
1 /*
2 * Copyright (c) 2000-2003 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
7 *
8 * This file contains Original Code and/or Modifications of Original Code
9 * as defined in and that are subject to the Apple Public Source License
10 * Version 2.0 (the 'License'). You may not use this file except in
11 * compliance with the License. Please obtain a copy of the License at
12 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * file.
14 *
15 * The Original Code and all software distributed under the License are
16 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
17 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
18 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
20 * Please see the License for the specific language governing rights and
21 * limitations under the License.
22 *
23 * @APPLE_LICENSE_HEADER_END@
24 */
25
26 /*
27 * Modification History
28 *
29 * June 1, 2001 Allan Nathanson <ajn@apple.com>
30 * - public API conversion
31 *
32 * June 2, 2000 Allan Nathanson <ajn@apple.com>
33 * - initial revision
34 */
35
36
37 #include "configd.h"
38
39
40 __private_extern__ CFMutableDictionaryRef sessionData = NULL;
41
42 __private_extern__ CFMutableDictionaryRef storeData = NULL;
43 __private_extern__ CFMutableDictionaryRef storeData_s = NULL;
44
45 __private_extern__ CFMutableDictionaryRef patternData = NULL;
46 __private_extern__ CFMutableDictionaryRef patternData_s = NULL;
47
48 __private_extern__ CFMutableSetRef changedKeys = NULL;
49 __private_extern__ CFMutableSetRef changedKeys_s = NULL;
50
51 __private_extern__ CFMutableSetRef deferredRemovals = NULL;
52 __private_extern__ CFMutableSetRef deferredRemovals_s = NULL;
53
54 __private_extern__ CFMutableSetRef removedSessionKeys = NULL;
55 __private_extern__ CFMutableSetRef removedSessionKeys_s = NULL;
56
57 __private_extern__ CFMutableSetRef needsNotification = NULL;
58
59 __private_extern__ int storeLocked = 0; /* > 0 if dynamic store locked */
60
61
62 __private_extern__
63 void
64 _swapLockedStoreData()
65 {
66 void *temp;
67
68 temp = storeData;
69 storeData = storeData_s;
70 storeData_s = temp;
71
72 temp = patternData;
73 patternData = patternData_s;
74 patternData_s = temp;
75
76 temp = changedKeys;
77 changedKeys = changedKeys_s;
78 changedKeys_s = temp;
79
80 temp = deferredRemovals;
81 deferredRemovals = deferredRemovals_s;
82 deferredRemovals_s = temp;
83
84 temp = removedSessionKeys;
85 removedSessionKeys = removedSessionKeys_s;
86 removedSessionKeys_s = temp;
87
88 return;
89 }
90
91
92 __private_extern__
93 void
94 _addWatcher(CFNumberRef sessionNum, CFStringRef watchedKey)
95 {
96 CFDictionaryRef dict;
97 CFMutableDictionaryRef newDict;
98 CFArrayRef watchers;
99 CFMutableArrayRef newWatchers;
100 CFArrayRef watcherRefs;
101 CFMutableArrayRef newWatcherRefs;
102 CFIndex i;
103 int refCnt;
104 CFNumberRef refNum;
105
106 /*
107 * Get the dictionary associated with this key out of the store
108 */
109 dict = CFDictionaryGetValue(storeData, watchedKey);
110 if (dict) {
111 newDict = CFDictionaryCreateMutableCopy(NULL, 0, dict);
112 } else {
113 newDict = CFDictionaryCreateMutable(NULL,
114 0,
115 &kCFTypeDictionaryKeyCallBacks,
116 &kCFTypeDictionaryValueCallBacks);
117 }
118
119 /*
120 * Get the set of watchers out of the keys dictionary
121 */
122 watchers = CFDictionaryGetValue(newDict, kSCDWatchers);
123 watcherRefs = CFDictionaryGetValue(newDict, kSCDWatcherRefs);
124 if (watchers) {
125 newWatchers = CFArrayCreateMutableCopy(NULL, 0, watchers);
126 newWatcherRefs = CFArrayCreateMutableCopy(NULL, 0, watcherRefs);
127 } else {
128 newWatchers = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
129 newWatcherRefs = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
130 }
131
132 /*
133 * Add my session to the set of watchers
134 */
135 i = CFArrayGetFirstIndexOfValue(newWatchers,
136 CFRangeMake(0, CFArrayGetCount(newWatchers)),
137 sessionNum);
138 if (i == -1) {
139 /* if this is the first instance of this session watching this key */
140 CFArrayAppendValue(newWatchers, sessionNum);
141 refCnt = 1;
142 refNum = CFNumberCreate(NULL, kCFNumberIntType, &refCnt);
143 CFArrayAppendValue(newWatcherRefs, refNum);
144 CFRelease(refNum);
145 } else {
146 /* if this is another instance of this session watching this key */
147 refNum = CFArrayGetValueAtIndex(newWatcherRefs, i);
148 CFNumberGetValue(refNum, kCFNumberIntType, &refCnt);
149 refCnt++;
150 refNum = CFNumberCreate(NULL, kCFNumberIntType, &refCnt);
151 CFArraySetValueAtIndex(newWatcherRefs, i, refNum);
152 CFRelease(refNum);
153 }
154
155 /*
156 * Update the keys dictionary
157 */
158 CFDictionarySetValue(newDict, kSCDWatchers, newWatchers);
159 CFRelease(newWatchers);
160 CFDictionarySetValue(newDict, kSCDWatcherRefs, newWatcherRefs);
161 CFRelease(newWatcherRefs);
162
163 /*
164 * Update the store for this key
165 */
166 CFDictionarySetValue(storeData, watchedKey, newDict);
167 CFRelease(newDict);
168
169 SCLog(_configd_verbose, LOG_DEBUG, CFSTR(" _addWatcher: %@, %@"), sessionNum, watchedKey);
170
171 return;
172 }
173
174
175 __private_extern__
176 void
177 _removeWatcher(CFNumberRef sessionNum, CFStringRef watchedKey)
178 {
179 CFDictionaryRef dict;
180 CFMutableDictionaryRef newDict;
181 CFArrayRef watchers;
182 CFMutableArrayRef newWatchers;
183 CFArrayRef watcherRefs;
184 CFMutableArrayRef newWatcherRefs;
185 CFIndex i;
186 int refCnt;
187 CFNumberRef refNum;
188
189 /*
190 * Get the dictionary associated with this key out of the store
191 */
192 dict = CFDictionaryGetValue(storeData, watchedKey);
193 if ((dict == NULL) || (CFDictionaryContainsKey(dict, kSCDWatchers) == FALSE)) {
194 /* key doesn't exist (isn't this really fatal?) */
195 SCLog(_configd_verbose, LOG_DEBUG, CFSTR(" _removeWatcher: %@, %@, key not watched"), sessionNum, watchedKey);
196 return;
197 }
198 newDict = CFDictionaryCreateMutableCopy(NULL, 0, dict);
199
200 /*
201 * Get the set of watchers out of the keys dictionary and
202 * remove this session from the list.
203 */
204 watchers = CFDictionaryGetValue(newDict, kSCDWatchers);
205 newWatchers = CFArrayCreateMutableCopy(NULL, 0, watchers);
206
207 watcherRefs = CFDictionaryGetValue(newDict, kSCDWatcherRefs);
208 newWatcherRefs = CFArrayCreateMutableCopy(NULL, 0, watcherRefs);
209
210 /* locate the session reference */
211 i = CFArrayGetFirstIndexOfValue(newWatchers,
212 CFRangeMake(0, CFArrayGetCount(newWatchers)),
213 sessionNum);
214 if (i == -1) {
215 SCLog(_configd_verbose, LOG_DEBUG, CFSTR(" _removeWatcher: %@, %@, session not watching"), sessionNum, watchedKey);
216 CFRelease(newDict);
217 CFRelease(newWatchers);
218 CFRelease(newWatcherRefs);
219 return;
220 }
221
222 /* remove one session reference */
223 refNum = CFArrayGetValueAtIndex(newWatcherRefs, i);
224 CFNumberGetValue(refNum, kCFNumberIntType, &refCnt);
225 if (--refCnt > 0) {
226 refNum = CFNumberCreate(NULL, kCFNumberIntType, &refCnt);
227 CFArraySetValueAtIndex(newWatcherRefs, i, refNum);
228 CFRelease(refNum);
229 } else {
230 /* if this was the last reference */
231 CFArrayRemoveValueAtIndex(newWatchers, i);
232 CFArrayRemoveValueAtIndex(newWatcherRefs, i);
233 }
234
235 if (CFArrayGetCount(newWatchers) > 0) {
236 /* if this key is still being "watched" */
237 CFDictionarySetValue(newDict, kSCDWatchers, newWatchers);
238 CFDictionarySetValue(newDict, kSCDWatcherRefs, newWatcherRefs);
239 } else {
240 /* no watchers left, remove the empty set */
241 CFDictionaryRemoveValue(newDict, kSCDWatchers);
242 CFDictionaryRemoveValue(newDict, kSCDWatcherRefs);
243 }
244 CFRelease(newWatchers);
245 CFRelease(newWatcherRefs);
246
247 if (CFDictionaryGetCount(newDict) > 0) {
248 /* if this key is still active */
249 CFDictionarySetValue(storeData, watchedKey, newDict);
250 } else {
251 /* no information left, remove the empty dictionary */
252 CFDictionaryRemoveValue(storeData, watchedKey);
253 }
254 CFRelease(newDict);
255
256 SCLog(_configd_verbose, LOG_DEBUG, CFSTR(" _removeWatcher: %@, %@"), sessionNum, watchedKey);
257
258 return;
259 }