]> err.no Git - scalable-opengroupware.org/commitdiff
git-svn-id: http://svn.opengroupware.org/SOGo/trunk@129 d1b88da0-ebda-0310-925b-ed51d...
authorhelge <helge@d1b88da0-ebda-0310-925b-ed51d893ca5b>
Wed, 30 Jun 2004 21:46:12 +0000 (21:46 +0000)
committerhelge <helge@d1b88da0-ebda-0310-925b-ed51d893ca5b>
Wed, 30 Jun 2004 21:46:12 +0000 (21:46 +0000)
OGoContentStore/ChangeLog
OGoContentStore/OCSChannelManager.h
OGoContentStore/OCSChannelManager.m
SOGo/UI/Scheduler/ChangeLog
SOGo/UI/Scheduler/UIxCalMonthOverview.wox
SOGo/UI/Scheduler/UIxCalWeekOverview.wox

index d23be32946bc7383fa6f1f90c15618be22866c4c..8c9836338ea4ecf6bf6ecf197e1eac2d32262c87 100644 (file)
@@ -1,5 +1,7 @@
 2004-06-30  Helge Hess  <helge.hess@opengroupware.org>
 
+       * OCSChannelManager.m: implemented pooling
+
        * OCSFolder.m: added quick fetches
 
        * GNUmakefile.preamble: fix link path
index c95ccc9902fa98d47d5a73f30f0de304c8e727dd..c888ec3559e6f9668fb45b1b20cfbd04da3a631f 100644 (file)
   This object manages the connection pooling.
 */
 
-@class NSURL, NSMutableDictionary;
+@class NSURL, NSMutableDictionary, NSMutableArray, NSTimer;
 @class EOAdaptorChannel, EOAdaptor;
 
 @interface OCSChannelManager : NSObject
 {
   NSMutableDictionary *urlToAdaptor;
+
+  NSMutableArray *availableChannels;
+  NSMutableArray *busyChannels;
+  NSTimer        *gcTimer;
 }
 
 + (id)defaultChannelManager;
index 881f9c30f0bf0169af8d62c15923940d23dbf9cc..2b568c99499e9ce12e0a356e13ac644a9e3016c2 100644 (file)
 @interface OCSChannelHandle : NSObject
 {
 @public
+  NSURL            *url;
   EOAdaptorChannel *channel;
   NSDate           *creationTime;
   NSDate           *lastReleaseTime;
   NSDate           *lastAcquireTime;
 }
 
+- (EOAdaptorChannel *)channel;
+- (BOOL)canHandleURL:(NSURL *)_url;
+- (NSTimeInterval)age;
+
 @end
 
 @implementation OCSChannelManager
 
-static BOOL debugOn = YES;
+static BOOL debugOn    = YES;
+static BOOL debugPools = YES;
+static int  ChannelExpireAge = 180;
 
 + (void)initialize {
   NSUserDefaults *ud = [NSUserDefaults standardUserDefaults];
   
   debugOn = [ud boolForKey:@"OCSChannelManagerDebugEnabled"];
+  ChannelExpireAge = [[ud objectForKey:@"OCSChannelExpireAge"] intValue];
+  if (ChannelExpireAge < 1)
+    ChannelExpireAge = 180;
 }
 
 + (NSString *)adaptorNameForURLScheme:(NSString *)_scheme {
@@ -69,13 +79,20 @@ static BOOL debugOn = YES;
 
 - (id)init {
   if ((self = [super init])) {
-    self->urlToAdaptor = [[NSMutableDictionary alloc] initWithCapacity:4];
+    self->urlToAdaptor      = [[NSMutableDictionary alloc] initWithCapacity:4];
+    self->availableChannels = [[NSMutableArray alloc] initWithCapacity:16];
+    self->busyChannels      = [[NSMutableArray alloc] initWithCapacity:16];
   }
   return self;
 }
 
 - (void)dealloc {
-  [self->urlToAdaptor release];
+  if (self->gcTimer) [self->gcTimer invalidate];
+  [self->gcTimer release];
+
+  [self->busyChannels      release];
+  [self->availableChannels release];
+  [self->urlToAdaptor      release];
   [super dealloc];
 }
 
@@ -157,6 +174,34 @@ static BOOL debugOn = YES;
 
 /* channels */
 
+- (OCSChannelHandle *)findBusyChannelHandleForChannel:(EOAdaptorChannel *)_ch {
+  NSEnumerator *e;
+  OCSChannelHandle *handle;
+  
+  e = [self->busyChannels objectEnumerator];
+  while ((handle = [e nextObject])) {
+    if ([handle channel] == _ch)
+      return handle;
+  }
+  return nil;
+}
+- (OCSChannelHandle *)findAvailChannelHandleForURL:(NSURL *)_url {
+  NSEnumerator *e;
+  OCSChannelHandle *handle;
+  
+  e = [self->availableChannels objectEnumerator];
+  while ((handle = [e nextObject])) {
+    if ([handle canHandleURL:_url])
+      return handle;
+    
+    if (debugPools) {
+      [self logWithFormat:@"DBPOOL: cannot use handle (%@ vs %@)",
+             [_url absoluteString], [handle->url absoluteString]];
+    }
+  }
+  return nil;
+}
+
 - (EOAdaptorChannel *)_createChannelForURL:(NSURL *)_url {
   EOAdaptor        *adaptor;
   EOAdaptorContext *adContext;
@@ -179,23 +224,89 @@ static BOOL debugOn = YES;
 - (EOAdaptorChannel *)acquireOpenChannelForURL:(NSURL *)_url {
   // TODO: naive implementation, add pooling!
   EOAdaptorChannel *channel;
+  OCSChannelHandle *handle;
+  NSCalendarDate   *now;
+
+  now = [NSCalendarDate date];
+  
+  /* look for cached handles */
+  
+  if ((handle = [self findAvailChannelHandleForURL:_url]) != nil) {
+    // TODO: check age?
+    [self->busyChannels      addObject:handle];
+    [self->availableChannels removeObject:handle];
+    ASSIGN(handle->lastAcquireTime, now);
+    
+    if (debugPools)
+      [self logWithFormat:@"DBPOOL: reused cached DB channel!"];
+    return [[handle channel] retain];
+  }
+
+  if (debugPools) {
+    [self logWithFormat:@"DBPOOL: create new DB channel for URL: %@",
+           [_url absoluteString]];
+  }
+  
+  /* create channel */
   
   if ((channel = [self _createChannelForURL:_url]) == nil)
-    return channel;
+    return nil;
   
   if ([channel isOpen])
-    return [channel retain];
-  
-  if (![channel openChannel]) {
+    ;
+  else if (![channel openChannel]) {
     [self logWithFormat:@"could not open channel %@ for URL: %@",
            channel, _url];
     return nil;
   }
   
+  /* create handle for channel */
+  
+  handle = [[OCSChannelHandle alloc] init];
+  handle->url             = [_url retain];
+  handle->channel         = [channel retain];
+  handle->creationTime    = [now retain];
+  handle->lastAcquireTime = [now retain];
+  
+  [self->busyChannels addObject:handle];
+  [handle release];
+  
   return [channel retain];
 }
 - (void)releaseChannel:(EOAdaptorChannel *)_channel {
-  // TODO: naive implementation, add pooling!
+  OCSChannelHandle *handle;
+  
+  if ((handle = [self findBusyChannelHandleForChannel:_channel]) != nil) {
+    NSCalendarDate *now;
+
+    now = [NSCalendarDate date];
+    
+    handle = [handle retain];
+    ASSIGN(handle->lastReleaseTime, now);
+    
+    [self->busyChannels removeObject:handle];
+    
+    if ([[handle channel] isOpen] && [handle age] < ChannelExpireAge) {
+      // TODO: consider age
+      [self->availableChannels addObject:handle];
+      if (debugPools) {
+       [self logWithFormat:
+               @"DBPOOL: keeping channel (age %ds, #%d): %@", 
+               (int)[handle age], [self->availableChannels count],
+               [handle->url absoluteString]];
+      }
+      [_channel release];
+      [handle release];
+      return;
+    }
+    
+    [self logWithFormat:
+           @"DBPOOL: freeing old channel (age %ds)", (int)[handle age]];
+    
+    /* not reusing channel */
+    [handle release]; handle = nil;
+  }
+  
   if ([_channel isOpen])
     [_channel closeChannel];
   
@@ -271,6 +382,46 @@ static BOOL debugOn = YES;
   return self->channel;
 }
 
+- (BOOL)canHandleURL:(NSURL *)_url {
+  if (_url == nil) {
+    [self logWithFormat:@"MISMATCH: no url .."];
+    return NO;
+  }
+  if (_url == self->url)
+    return YES;
+  
+  if (![[self->url host] isEqual:[_url host]]) {
+    [self logWithFormat:@"MISMATCH: different host .."];
+    return NO;
+  }
+  if (![[self->url ocsDatabaseName] isEqualToString:[_url ocsDatabaseName]]) {
+    [self logWithFormat:@"MISMATCH: different db .."];
+    return NO;
+  }
+  if (![[self->url user] isEqual:[_url user]]) {
+    [self logWithFormat:@"MISMATCH: different user .."];
+    return NO;
+  }
+  if ([[self->url port] intValue] != [[_url port] intValue]) {
+    [self logWithFormat:@"MISMATCH: different port (%@ vs %@) ..",
+         [self->url port], [_url port]];
+    return NO;
+  }
+  
+  return YES;
+}
+
+- (NSTimeInterval)age {
+  return [[NSCalendarDate calendarDate] 
+                         timeIntervalSinceDate:self->creationTime];
+}
+
+/* NSCopying */
+
+- (id)copyWithZone:(NSZone *)_zone {
+  return [self retain];
+}
+
 /* description */
 
 - (NSString *)description {
index 8ce1d8025b9c7e1e8958197379452985c21b9663..a29b19b73c592cac4c9ac2e452e68853e965e8ca 100644 (file)
@@ -1,5 +1,7 @@
 2004-06-30  Helge Hess  <helge.hess@opengroupware.org>
 
+       * UIxCalWeekOverview.wox, UIxCalMonthOverview.wox: some minor tweaks
+
        * UIxAppointmentView.wox: made the attendee emails clickable
 
        * UIxCalView.m: removed -fetchGIDs, moved -fetchCoreInfos to client
index 4abc89bcf6e52f90555fb1b3ec548ec1d8255f86..dd690808445be6eb134d777224504b8dcead6364 100644 (file)
     >
       <var:month-info>
         <var:if condition="hasHolidayInfo">
-            <var:string value="holidayInfo" const:class="monthoverview_holidayinfo" />
+          <var:string value="holidayInfo" 
+                      const:class="monthoverview_holidayinfo" />
         </var:if>
         <var:foreach list="allDayApts" item="appointment">
-            <a var:href="appointmentViewURL"><var:string value="shortTextForApt" /></a>
+          <a var:href="appointmentViewURL"
+            ><var:string value="shortTextForApt" /></a>
         </var:foreach>
       </var:month-info>
-    <var:month-label const:orientation="top"
-                     dayOfWeek="dayOfWeek"
-                     const:class="monthoverview_title"
-    >
+      <var:month-label const:orientation="top"
+                       dayOfWeek="dayOfWeek"
+                       const:class="monthoverview_title"
+      >
         <var:string value="localizedNameOfDayOfWeek" />
-    </var:month-label>
-    <var:month-label const:orientation="left"
-                     weekOfYear="weekOfYear"
-                     class="weekStyle"
-    >
+      </var:month-label>
+      <var:month-label const:orientation="left"
+                       weekOfYear="weekOfYear"
+                       class="weekStyle"
+      >
         <a href="weekoverview"
            var:queryDictionary="currentWeekQueryParameters"
         ><var:string value="weekOfYear" /></a>
-    </var:month-label>
+      </var:month-label>
     
-        <var:month-title class="contentStyle">
-            <span class="monthoverview_day">
-                <a href="dayoverview"
-                   var:queryDictionary="currentDayQueryParameters"
-                ><var:string value="currentDay.dayOfMonth" /></a>
-            </span>
-            <br />
-            <span class="monthoverview_day_new">
-                <a href="new"
-                   var:queryDictionary="currentDayQueryParameters"
-                >[new]</a>
-            </span>
-        </var:month-title>
+      <var:month-title class="contentStyle">
+        <span class="monthoverview_day">
+          <a href="dayoverview"
+             var:queryDictionary="currentDayQueryParameters"
+            ><var:string value="currentDay.dayOfMonth" /></a>
+        </span>
+        <br />
+        <span class="monthoverview_day_new">
+          <a href="new" var:queryDictionary="currentDayQueryParameters"
+            >[new]</a>
+        </span>
+      </var:month-title>
 
-        <var:month>
-            <a var:href="appointmentViewURL"
-               class="monthoverview_content_link"
-               var:title="shortTextForApt"
-               var:queryDictionary="currentDayQueryParameters"
-            ><var:string value="shortTitleForApt" /></a>
+      <var:month>
+        <a var:href="appointmentViewURL"
+           class="monthoverview_content_link"
+           var:title="shortTextForApt"
+           var:queryDictionary="currentDayQueryParameters"
+          ><var:string value="shortTitleForApt" /></a>
         </var:month>
     </var:month-overview>
   </var:component>
index b07f74e83f35e30153dd4681c52cf456c458470a..53d61a905d21b859c64e74424ad81df3595f9bc9 100644 (file)
   <table border="0" width="100%" cellpadding="0" cellspacing="0">
   <tr>
   <td colspan="2">
-  <var:component className="UIxCalSelectTab" const:selection="week" currentDate="selectedDate">
-
+    <var:component className="UIxCalSelectTab" const:selection="week" 
+                   currentDate="selectedDate">
         <table border="0" cellpadding="4" width="100%" cellspacing="2">
           <tr>
             <td width="1%" align="left" valign="middle" bgcolor="#e8e8e0">
               <table border='0' cellpadding='0' cellspacing='0'>
                <tr>
-                  <td><img rsrc:src="icon_apt_overview_inactive.gif" title="Overview" alt="Overview" border="0" valign="top" /></td>
-                  <td><a href="weekchartview"><img rsrc:src="icon_apt_chart.gif" title="Chart" alt="Chart" border="0" valign="top" /></a></td>
-                  <td><a href="weeklistview"><img rsrc:src="icon_apt_list.gif" title="List" alt="List" border="0" valign="top" /></a></td>
+                  <td><img rsrc:src="icon_apt_overview_inactive.gif" 
+                           title="Overview" alt="Overview" border="0" 
+                           valign="top" /></td>
+                  <td><a href="weekchartview"><img 
+                         rsrc:src="icon_apt_chart.gif" title="Chart" 
+                         alt="Chart" border="0" valign="top" /></a></td>
+                  <td><a href="weeklistview"><img 
+                         rsrc:src="icon_apt_list.gif" title="List" 
+                         alt="List" border="0" valign="top" /></a></td>
                   <td>
-                    <a href="weekcolumnview"><img rsrc:src="icon_apt_column_view.gif" title="Columns" alt="Columns" border="0" valign="top" /></a>
+                    <a href="weekcolumnview"><img 
+                       rsrc:src="icon_apt_column_view.gif" title="Columns" 
+                       alt="Columns" border="0" valign="top" /></a>
                   </td>
                </tr>
               </table>
             </td>
           
             <td align="right" bgcolor="#e8e8e0">
-                <table border='0' cellpadding='0' cellspacing='1'>
-                    <tr>
-                        <td class="button_auto_env" nowrap="true" valign='middle' align='center'>
-                            <a class="button_auto" href="weekprintview" var:queryDictionary="queryParameters" target="SOGoPrintView">printview</a>
-                        </td>
-                        <td class="button_auto_env" nowrap="true" valign='middle' align='center'>
-                            <a class="button_auto" href="proposal" var:queryDictionary="queryParameters">proposal</a>
-                        </td>
-                    </tr>
-                </table>
+              <table border='0' cellpadding='0' cellspacing='1'>
+                <tr>
+                  <td class="button_auto_env" nowrap="true" valign='middle' 
+                      align='center'>
+                    <a class="button_auto" href="weekprintview" 
+                       var:queryDictionary="queryParameters" 
+                       target="SOGoPrintView">printview</a>
+                  </td>
+                  <td class="button_auto_env" nowrap="true" valign='middle' 
+                      align='center'>
+                    <a class="button_auto" href="proposal" 
+                       var:queryDictionary="queryParameters">proposal</a>
+                  </td>
+                </tr>
+              </table>
             </td>
           </tr>
         </table>
                        const:titleStyle="weekoverview_title"
                        contentStyle="contentStyle"
     >
-        <var:week-title>
-            <table cellpadding="0"
-                   width="100%"
-                   border="0"
-                   cellspacing="0"
-                   var:class="titleStyle"
-            >
-                <tr>
-                    <td align="left" valign="top">
-                        <a href="dayoverview"
-                           var:queryDictionary="currentDayQueryParameters"
-                           class="weekoverview_title_daylink"
-                        ><var:string value="currentDay.dayOfMonth" /></a>
-                    </td>
-                    <td align="center" valign="top" width="97%">
-                    <var:string value="currentDayName" /><br />
-                    [<a href="new"
-                        var:queryDictionary="currentDayQueryParameters"
-                        class="weekoverview_title_newlink"
-                     >new</a>]
-                    </td>
-                </tr>
-            </table>
-        </var:week-title>
-        <var:if condition="hasDayInfo">
-            <var:week-info>
-                <var:if condition="hasHolidayInfo">
-                    <var:string value="holidayInfo" 
-                               const:class="weekoverview_holidayinfo" />
-                </var:if>
-                <var:foreach list="allDayApts" item="appointment">
-                    <a var:href="appointmentViewURL"
-                       var:queryDictionary="currentDayQueryParameters"
-                    ><var:string value="shortTextForApt" /></a>
-                </var:foreach>
-            </var:week-info>
-        </var:if>
+      <var:week-title>
+        <table cellpadding="0" width="100%" border="0" cellspacing="0"
+               var:class="titleStyle">
+          <tr>
+            <td align="left" valign="top">
+              <a href="dayoverview"
+                 var:queryDictionary="currentDayQueryParameters"
+                 class="weekoverview_title_daylink"
+                 ><var:string value="currentDay.dayOfMonth" /></a>
+            </td>
+            <td align="center" valign="top" width="97%">
+              <var:string value="currentDayName" /><br />
+                [<a href="new"
+                    var:queryDictionary="currentDayQueryParameters"
+                    class="weekoverview_title_newlink"
+                 >new</a>]
+            </td>
+          </tr>
+        </table>
+      </var:week-title>
+      <var:if condition="hasDayInfo">
+        <var:week-info>
+          <var:if condition="hasHolidayInfo">
+            <var:string value="holidayInfo" 
+                       const:class="weekoverview_holidayinfo" />
+          </var:if>
+          <var:foreach list="allDayApts" item="appointment">
+            <a var:href="appointmentViewURL"
+               var:queryDictionary="currentDayQueryParameters"
+              ><var:string value="shortTextForApt" /></a>
+          </var:foreach>
+        </var:week-info>
+      </var:if>
       <var:week>
-          <a var:href="appointmentViewURL"><var:string value="appointment.title"/></a>
+        <a var:href="appointmentViewURL" 
+          ><small><var:string value="shortTextForApt" /></small></a>
       </var:week>
-  </var:week-overview>
+    </var:week-overview>
   </var:component>
   </td>
   </tr>