]> err.no Git - sope/blob - sope-core/NGExtensions/EOExt.subproj/EOCacheDataSource.m
fixed gcc 4.1 warnings
[sope] / sope-core / NGExtensions / EOExt.subproj / EOCacheDataSource.m
1 /*
2   Copyright (C) 2000-2005 SKYRIX Software AG
3
4   This file is part of SOPE.
5
6   SOPE is free software; you can redistribute it and/or modify it under
7   the terms of the GNU Lesser General Public License as published by the
8   Free Software Foundation; either version 2, or (at your option) any
9   later version.
10
11   SOPE is distributed in the hope that it will be useful, but WITHOUT ANY
12   WARRANTY; without even the implied warranty of MERCHANTABILITY or
13   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
14   License for more details.
15
16   You should have received a copy of the GNU Lesser General Public
17   License along with SOPE; see the file COPYING.  If not, write to the
18   Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
19   02111-1307, USA.
20 */
21
22 //#define PROFILE 1
23
24 #include "EOCacheDataSource.h"
25 #import <EOControl/EOControl.h>
26 #import "EODataSource+NGExtensions.h"
27 #import "common.h"
28 #include <sys/time.h>
29
30 @interface EOCacheDataSource(Private)
31 - (void)_registerForSource:(id)_source;
32 - (void)_removeObserverForSource:(id)_source;
33 - (void)_clearCache;
34 @end
35
36 @implementation EOCacheDataSource
37
38 - (id)initWithDataSource:(EODataSource *)_ds {
39   if ((self = [super init])) {
40     self->source  = [_ds retain];
41     self->timeout = 0;
42     self->timer   = nil;
43     self->time    = 0;
44     [self _registerForSource:self->source];
45   }
46   return self;
47 }
48
49 - (void)dealloc {
50   [self _removeObserverForSource:self->source];
51   [self->timer invalidate];
52   [self->timer  release];
53   [self->source release];
54   [self->cache  release];
55   [super dealloc];
56 }
57
58 /* accessors */
59
60 - (void)setSource:(EODataSource *)_source {
61   [self _removeObserverForSource:self->source];
62   ASSIGN(self->source, _source);
63   [self _registerForSource:self->source];
64   [self _clearCache];
65 }
66
67 - (EODataSource *)source {
68   return self->source;
69 }
70
71 - (void)setTimeout:(NSTimeInterval)_timeout {
72   self->timeout = _timeout;
73 }
74 - (NSTimeInterval)timeout {
75   return self->timeout;
76 }
77
78 /* operations */
79
80 - (NSArray *)fetchObjects {
81   BEGIN_PROFILE;
82
83   self->_isFetching = YES;
84   
85   if (self->time > 0) {
86     if (self->time < [[NSDate date] timeIntervalSinceReferenceDate]) {
87       [self->cache release]; self->cache = nil;
88     }
89   }
90   if (self->cache == nil) {
91     self->time = 0;
92     if (self->timer != nil) {
93       [self->timer invalidate];
94       [self->timer release]; self->timer = nil;
95     }
96     
97     self->cache = [[self->source fetchObjects] retain];
98     
99     if (self->timeout > 0) {
100       self->time =
101         [[NSDate date] timeIntervalSinceReferenceDate] + self->timeout;
102       
103       self->timer = [NSTimer scheduledTimerWithTimeInterval:self->timeout
104                              target:self
105                              selector:@selector(clear)
106                              userInfo:nil repeats:NO];
107       self->timer = [self->timer retain];
108     }
109     PROFILE_CHECKPOINT("cache miss");
110   }
111   else {
112     PROFILE_CHECKPOINT("cache hit");
113   }
114   
115   self->_isFetching = NO;
116   END_PROFILE;
117   return self->cache;
118 }
119
120 - (void)setFetchSpecification:(EOFetchSpecification *)_fetchSpec {
121   [self->source setFetchSpecification:_fetchSpec];
122 }
123 - (EOFetchSpecification *)fetchSpecification {
124   return [self->source fetchSpecification];
125 }
126
127 /* operations */
128
129 - (void)insertObject:(id)_obj {
130   [self _clearCache];
131   [self->source insertObject:_obj];
132 }
133
134 - (void)deleteObject:(id)_obj {
135   [self _clearCache];
136   [self->source deleteObject:_obj];
137 }
138
139 - (id)createObject {
140   return [self->source createObject];
141 }
142
143 - (void)updateObject:(id)_obj {
144   [self->source updateObject:_obj];
145   [self _clearCache];  
146 }
147
148 - (EOClassDescription *)classDescriptionForObjects {
149   return [[self source] classDescriptionForObjects];
150 }
151
152 - (void)clear {
153   [self _clearCache];
154 }
155
156 /* description */
157
158 - (NSString *)description {
159   NSString *fmt;
160
161   fmt = [NSString stringWithFormat:@"<%@[0x%p]: source=%@>",
162                     NSStringFromClass([self class]), self,
163                     self->source];
164   return fmt;
165 }
166
167 /* private methods */
168
169 - (void)_registerForSource:(id)_source {
170   static NSNotificationCenter *nc = nil;
171
172   if (_source != nil) {
173     if (nc == nil)
174       nc = [[NSNotificationCenter defaultCenter] retain];
175     
176     [nc addObserver:self selector:@selector(_clearCache)
177         name:EODataSourceDidChangeNotification object:_source];
178   }
179 }
180
181 - (void)_removeObserverForSource:(id)_source {
182   static NSNotificationCenter *nc = nil;
183
184   if (_source != nil) {
185     if (nc == nil)
186       nc = [NSNotificationCenter defaultCenter];
187     [nc removeObserver:self name:EODataSourceDidChangeNotification
188         object:_source];
189   }
190 }
191
192  
193 - (void)_clearCache {
194 #if DEBUG && 0
195   NSLog(@"clearing cache (%s)...", self->_isFetching?"fetching":"");
196   if (fgetc(stdin) == 'a')
197     abort();
198 #endif
199   
200   self->time = 0;
201   
202   if (self->timer) {
203     [self->timer invalidate];
204     [self->timer release]; self->timer = nil;
205   }
206   
207   if (self->cache) {
208     [self->cache release]; self->cache = nil;
209     [self postDataSourceChangedNotification];
210   }
211 }
212
213 @end /* EOCacheDataSource */