2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * The contents of this file constitute Original Code as defined in and
7 * are subject to the Apple Public Source License Version 1.1 (the
8 * "License"). You may not use this file except in compliance with the
9 * License. Please obtain a copy of the License at
10 * http://www.apple.com/publicsource and read it before using this file.
12 * This Original Code and all software distributed under the License are
13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17 * License for the specific language governing rights and limitations
20 * @APPLE_LICENSE_HEADER_END@
27 _SCDSet(SCDSessionRef session
, CFStringRef key
, SCDHandleRef handle
)
29 SCDSessionPrivateRef sessionPrivate
= (SCDSessionPrivateRef
)session
;
30 SCDStatus scd_status
= SCD_OK
;
33 CFMutableDictionaryRef newDict
;
36 CFStringRef sessionKey
;
37 CFStringRef cacheSessionKey
;
39 SCDLog(LOG_DEBUG
, CFSTR("_SCDSet:"));
40 SCDLog(LOG_DEBUG
, CFSTR(" key = %@"), key
);
41 SCDLog(LOG_DEBUG
, CFSTR(" data = %@"), SCDHandleGetData(handle
));
42 SCDLog(LOG_DEBUG
, CFSTR(" instance = %d"), SCDHandleGetInstance(handle
));
44 if ((session
== NULL
) || (sessionPrivate
->server
== MACH_PORT_NULL
)) {
45 return SCD_NOSESSION
; /* you can't do anything with a closed session */
49 * 1. Determine if the cache lock is currently held
50 * and acquire the lock if necessary.
52 wasLocked
= SCDOptionGet(NULL
, kSCDOptionIsLocked
);
54 scd_status
= _SCDLock(session
);
55 if (scd_status
!= SCD_OK
) {
56 SCDLog(LOG_DEBUG
, CFSTR(" _SCDLock(): %s"), SCDError(scd_status
));
62 * 2. Grab the current (or establish a new) dictionary for this key.
65 dict
= CFDictionaryGetValue(cacheData
, key
);
67 newDict
= CFDictionaryCreateMutableCopy(NULL
,
71 newDict
= CFDictionaryCreateMutable(NULL
,
73 &kCFTypeDictionaryKeyCallBacks
,
74 &kCFTypeDictionaryValueCallBacks
);
78 * 3. Make sure that we're not updating the cache with potentially
82 if ((num
= CFDictionaryGetValue(newDict
, kSCDInstance
)) == NULL
) {
83 /* if first instance */
85 _SCDHandleSetInstance(handle
, dictInstance
);
87 (void) CFNumberGetValue(num
, kCFNumberIntType
, &dictInstance
);
89 if (SCDHandleGetInstance(handle
) != dictInstance
) {
90 /* data may be based on old information */
92 scd_status
= SCD_STALE
;
97 * 4. Update the dictionary entry (data & instance) to be saved to
101 CFDictionarySetValue(newDict
, kSCDData
, SCDHandleGetData(handle
));
104 num
= CFNumberCreate(NULL
, kCFNumberIntType
, &dictInstance
);
105 CFDictionarySetValue(newDict
, kSCDInstance
, num
);
107 _SCDHandleSetInstance(handle
, dictInstance
);
108 SCDLog(LOG_DEBUG
, CFSTR(" new instance = %d"), SCDHandleGetInstance(handle
));
111 * 5. Since we are updating this key we need to check and, if
112 * necessary, remove the indication that this key is on
113 * another session's remove-on-close list.
115 sessionKey
= CFStringCreateWithFormat(NULL
, NULL
, CFSTR("%d"), sessionPrivate
->server
);
116 if (CFDictionaryGetValueIfPresent(newDict
, kSCDSession
, (void *)&cacheSessionKey
) &&
117 !CFEqual(sessionKey
, cacheSessionKey
)) {
118 CFStringRef removedKey
;
120 /* We are no longer a session key! */
121 CFDictionaryRemoveValue(newDict
, kSCDSession
);
123 /* add this session key to the (session) removal list */
124 removedKey
= CFStringCreateWithFormat(NULL
, 0, CFSTR("%@:%@"), cacheSessionKey
, key
);
125 CFSetAddValue(removedSessionKeys
, removedKey
);
126 CFRelease(removedKey
);
128 CFRelease(sessionKey
);
131 * 6. Update the dictionary entry in the cache.
134 CFDictionarySetValue(cacheData
, key
, newDict
);
138 * 7. For "new" entries to the cache, check the deferred cleanup
139 * list. If the key is flagged for removal, remove it from the
140 * list since any defined regex's for this key are still defined
141 * and valid. If the key is not flagged then iterate over the
142 * sessionData dictionary looking for regex keys which match the
143 * updated key. If a match is found then we mark those keys as
147 if (dictInstance
== 1) {
148 if (CFSetContainsValue(deferredRemovals
, key
)) {
149 CFSetRemoveValue(deferredRemovals
, key
);
151 CFDictionaryApplyFunction(sessionData
,
152 (CFDictionaryApplierFunction
)_addRegexWatchersBySession
,
158 * 8. Mark this key as "changed". Any "watchers" will be notified
159 * as soon as the lock is released.
161 CFSetAddValue(changedKeys
, key
);
164 * 9. Release the lock if we acquired it as part of this request.
175 _configset(mach_port_t server
,
176 xmlData_t keyRef
, /* raw XML bytes */
177 mach_msg_type_number_t keyLen
,
178 xmlData_t dataRef
, /* raw XML bytes */
179 mach_msg_type_number_t dataLen
,
185 kern_return_t status
;
186 serverSessionRef mySession
= getSession(server
);
187 CFDataRef xmlKey
; /* key (XML serialized) */
188 CFStringRef key
; /* key (un-serialized) */
189 CFDataRef xmlData
; /* data (XML serialized) */
190 CFPropertyListRef data
; /* data (un-serialized) */
192 CFStringRef xmlError
;
194 SCDLog(LOG_DEBUG
, CFSTR("Set key to configuration database."));
195 SCDLog(LOG_DEBUG
, CFSTR(" server = %d"), server
);
197 /* un-serialize the key */
198 xmlKey
= CFDataCreate(NULL
, keyRef
, keyLen
);
199 status
= vm_deallocate(mach_task_self(), (vm_address_t
)keyRef
, keyLen
);
200 if (status
!= KERN_SUCCESS
) {
201 SCDLog(LOG_DEBUG
, CFSTR("vm_deallocate(): %s"), mach_error_string(status
));
202 /* non-fatal???, proceed */
204 key
= CFPropertyListCreateFromXMLData(NULL
,
206 kCFPropertyListImmutable
,
210 SCDLog(LOG_DEBUG
, CFSTR("CFPropertyListCreateFromXMLData() key: %s"), xmlError
);
211 *scd_status
= SCD_FAILED
;
215 /* un-serialize the data */
216 xmlData
= CFDataCreate(NULL
, dataRef
, dataLen
);
217 status
= vm_deallocate(mach_task_self(), (vm_address_t
)dataRef
, dataLen
);
218 if (status
!= KERN_SUCCESS
) {
219 SCDLog(LOG_DEBUG
, CFSTR("vm_deallocate(): %s"), mach_error_string(status
));
220 /* non-fatal???, proceed */
222 data
= CFPropertyListCreateFromXMLData(NULL
,
224 kCFPropertyListImmutable
,
228 SCDLog(LOG_DEBUG
, CFSTR("CFPropertyListCreateFromXMLData() data: %s"), xmlError
);
230 *scd_status
= SCD_FAILED
;
234 handle
= SCDHandleInit();
235 SCDHandleSetData(handle
, data
);
236 _SCDHandleSetInstance(handle
, oldInstance
);
237 *scd_status
= _SCDSet(mySession
->session
, key
, handle
);
238 if (*scd_status
== SCD_OK
) {
239 *newInstance
= SCDHandleGetInstance(handle
);
241 SCDHandleRelease(handle
);