GNUstep Core Data  0.1
GSPersistentStore.m
00001 /* Implementation of the GSPersistentStore class for the GNUstep
00002    Core Data framework.
00003    Copyright (C) 2005 Free Software Foundation, Inc.
00004 
00005    Written by:  Saso Kiselkov <diablos@manga.sk>
00006    Date: August 2005
00007 
00008    This file is part of the GNUstep Core Data framework.
00009 
00010    This library is free software; you can redistribute it and/or
00011    modify it under the terms of the GNU Lesser General Public
00012    License as published by the Free Software Foundation; either
00013    version 2.1 of the License, or (at your option) any later version.
00014 
00015    This library is distributed in the hope that it will be useful,
00016    but WITHOUT ANY WARRANTY; without even the implied warranty of
00017    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00018    Lesser General Public License for more details.
00019 
00020    You should have received a copy of the GNU Lesser General Public
00021    License along with this library; if not, write to the Free
00022    Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111 USA.
00023 */
00024 
00025 #import "CoreDataHeaders.h"
00026 #import "GSPersistentStore.h"
00027 
00028 #include <stdlib.h>
00029 #include <time.h>
00030 
00031 #ifdef HAVE_NATIVE_OBJC_EXCEPTIONS
00032 # define SUBCLASS_OVERRIDE_ERROR \
00033    @throw [NSException exceptionWithName: NSInternalInconsistencyException \
00034                                   reason: [NSString stringWithFormat: \
00035      _(@"Subclass %@ didn't override `%@'."), [self className], \
00036      NSStringFromSelector(_cmd)] \
00037                                 userInfo: nil]
00038 #else
00039 # define SUBCLASS_OVERRIDE_ERROR \
00040    [NSException raise: NSInternalInconsistencyException \
00041                format: _(@"Subclass %@ didn't override `%@'."), \
00042      [self className], NSStringFromSelector(_cmd)]
00043 #endif
00044 
00045 // the lock with which we protect access to the randomizer's
00046 // state setup.
00047 static NSRecursiveLock * randomizerLock = nil;
00048 static struct drand48_data randomizerSetup;
00049 
00050 // store UUIDs are 256-bits long
00051 #define STORE_UUID_SIZE   (256 / 8) /* bits */
00052 
00059 static NSString *
00060 GenerateNewRandomUUID (void)
00061 {
00062   NSString * hexaValue = @"";
00063   unsigned int i;
00064 
00065   [randomizerLock lock];
00066 
00067   // Generate a random number which may be up to 256-bits (i.e. up to
00068   // 64 hexa-digits) long.
00069   for (i = 0; i < (STORE_UUID_SIZE / sizeof(long int)); i++)
00070     {
00071       long int result;
00072       lrand48_r (&randomizerSetup, &result);
00073       hexaValue = [NSString stringWithFormat: @"%@%X", hexaValue, result];
00074     }
00075 
00076   [randomizerLock unlock];
00077 
00078   return hexaValue;
00079 }
00080 
00123 @implementation GSPersistentStore
00124 
00125 + (void) initialize
00126 {
00127   if (randomizerLock == nil)
00128     {
00129       // initialize the randomizerSetup protection lock
00130       randomizerLock = [NSRecursiveLock new];
00131 
00132       // setup the randomizer
00133       srand48_r(time(NULL), &randomizerSetup);
00134     }
00135 }
00136 
00137 - (void) dealloc
00138 {
00139   TEST_RELEASE(_URL);
00140   TEST_RELEASE(_model);
00141   TEST_RELEASE(_configuration);
00142   TEST_RELEASE(_metadata);
00143   TEST_RELEASE(_versionNumbers);
00144 
00145   [super dealloc];
00146 }
00147 
00156 -       initWithURL: (NSURL *) URL
00157  managedObjectModel: (NSManagedObjectModel *) model
00158       configuration: (NSString *) configuration
00159             options: (NSDictionary *) options
00160 {
00161   if ([self init])
00162     {
00163       ASSIGN(_URL, URL);
00164       ASSIGN(_model, model);
00165       ASSIGN(_configuration, configuration);
00166 
00167       _metadata = [[NSDictionary alloc]
00168         initWithObjectsAndKeys:
00169         GenerateNewRandomUUID(), NSStoreUUIDKey,
00170         [self storeType], NSStoreTypeKey,
00171         nil];
00172 
00173       _versionNumbers = [NSMutableDictionary new];
00174 
00175       return self;
00176     }
00177   else
00178     {
00179       return nil;
00180     }
00181 }
00182 
00188 - (NSURL *) URL
00189 {
00190   return _URL;
00191 }
00192 
00198 - (NSString *) configuration
00199 {
00200   return _configuration;
00201 }
00202 
00208 - (void) setUUID: (NSString *) UUID
00209 {
00210   NSMutableDictionary * metadata;
00211 
00212   metadata = [[_metadata mutableCopy] autorelease];
00213   [metadata setObject: UUID
00214                forKey: NSStoreUUIDKey];
00215   ASSIGN(_metadata, [[metadata copy] autorelease]);
00216 }
00217 
00225 - (void) setMetadata: (NSDictionary *) metadata
00226 {
00227   NSMutableDictionary * newMetadata = [[metadata mutableCopy] autorelease];
00228 
00229   // copy the old values
00230   [newMetadata setObject: [_metadata objectForKey: NSStoreUUIDKey]
00231                   forKey: NSStoreUUIDKey];
00232   [newMetadata setObject: [self storeType] forKey: NSStoreTypeKey];
00233 
00234   ASSIGN(_metadata, [[newMetadata copy] autorelease]);
00235 }
00236 
00243 - (NSDictionary *) metadata
00244 {
00245   return _metadata;
00246 }
00247 
00248 - (BOOL) saveObjects: (NSSet *) objects
00249                error: (NSError **) error
00250 {
00251   NSEnumerator * e = [objects objectEnumerator];
00252   NSManagedObject * managedObject;
00253 
00254   // increment the storage number for non-fault objects
00255   while ((managedObject = [e nextObject]) != nil)
00256     {
00257       if (![managedObject isFault])
00258         {
00259           unsigned long long version;
00260           NSManagedObjectID * objectID = [managedObject objectID];
00261 
00262           NSAssert([objectID persistentStore] == self, _(@"Tried to store "
00263             @"a managed object in a different persistent store than where "
00264             @"it belongs."));
00265 
00266           version = [[_versionNumbers objectForKey: objectID]
00267             unsignedLongLongValue];
00268           version++;
00269           [_versionNumbers
00270             setObject: [NSNumber numberWithUnsignedLongLong: version]
00271                forKey: objectID];
00272         }
00273     }
00274 
00275   // and write the objects
00276 //  return [self writeWithObjects: objects error: error];
00277   return NO;
00278 }
00279 
00280 - (unsigned long long) storageNumberForObjectID: (NSManagedObjectID *) objectID
00281 {
00282   return [[_versionNumbers objectForKey: objectID] unsignedLongLongValue];
00283 }
00284 
00292 - (NSString *) storeType
00293 {
00294   SUBCLASS_OVERRIDE_ERROR;
00295 
00296   return nil;
00297 }
00298 
00343 - (NSDictionary *) fetchObjectsWithEntity: (NSEntityDescription *) entity
00344                                 predicate: (NSPredicate *) predicate
00345                                     error: (NSError **) error
00346 {
00347   SUBCLASS_OVERRIDE_ERROR;
00348 
00349   return nil;
00350 }
00351 
00367 - (NSDictionary *) fetchObjectWithID: (NSManagedObjectID *) objectID
00368                      fetchProperties: (NSSet *) properties
00369                                error: (NSError **) error
00370 {
00371   SUBCLASS_OVERRIDE_ERROR;
00372 
00373   return nil;
00374 }
00375 
00406 - (BOOL) writeSavingObjects: (NSSet *) objectsToWrite
00407             deletingObjects: (NSSet *) objectIDsToDelete
00408                       error: (NSError **) error
00409 {
00410   SUBCLASS_OVERRIDE_ERROR;
00411 
00412   return NO;
00413 }
00414 
00415 @end