[Tickets #12801] Re: Unable to parse recurring events during iCalendar import

noreply at bugs.horde.org noreply at bugs.horde.org
Sun Nov 3 14:55:18 UTC 2013


DO NOT REPLY TO THIS MESSAGE. THIS EMAIL ADDRESS IS NOT MONITORED.

Ticket URL: http://bugs.horde.org/ticket/12801
------------------------------------------------------------------------------
  Ticket             | 12801
  Updated By         | wrcdrijfhout at imperamus.eu
  Summary            | Unable to parse recurring events during iCalendar
                     | import
  Queue              | Kronolith
  Version            | 4.1.3
  Type               | Bug
  State              | Resolved
  Priority           | 2. Medium
  Milestone          |
  Patch              |
  Owners             | Jan Schneider
------------------------------------------------------------------------------


wrcdrijfhout at imperamus.eu (2013-11-03 14:55) wrote:

>> * The ICAL-URL is completely empty, supposedly because PHP's request
>> handling died prematurely.
>>
>> I will contact Jan via e-mail about a larger ICS-file with which the
>> problem can be reproduced.
>
> Works perfectly fine for me with a current Horde checkout even with  
> the other ICS file.
While I do not run the latest Horde checkout, I backported the fix you  
committed. The problem persists; I traced it to an OutOfMemory-problem:

In kronolith/lib/Api.php, line 896 onward, I wrote:
`$i=-1;
             foreach ($events as $dayevents) {
print(++$i.'<br/>');
print((memory_get_usage()/1024/1024).'MB / '. ini_get('memory_limit')  
. '<br/>');
                 foreach ($dayevents as $event) {
                     $iCal->addComponent($event->toiCalendar($iCal));
                 }
             }
die();
`

 From this I deduced I exceeded the memory limit. I find it dubious  
that experting a mere 100 calendar entries would require 184MB to  
yield a 2.9MB file; can we optimize this?

In Icalendar.php, we can (at least) do this:
`
     public function addComponent(&$components)
     {
         if (is_array($components)) {
             foreach ($components as &$component) {
                 $this->addComponent($component);
             }
         } else if ($components instanceof Horde_Icalendar) {
             $components->_container = &$this;
             $this->_components[] = &$components;
         }
     }

`
Notice the ampersands; i.e., by-reference/address-of operator. The  
line "$this->_components[] = &$component;" is still the most expensive  
one. Anyhow, by replacing addComponent as such, we cut down memory  
usage from 184MB to 53MB (and gain more performance as well)!

I recommend exploring further applications of passing values  
by-reference (by using the &-operator) instead of by-value throughout  
Horde (especially oft-used functions, like domain-entity functions).




-----------


Also, the previous fix for kronolith/lib/Event.php you added checks  
for the Timezone-object being at index 0 or 1, but array_pop always  
retrieves the object at the last index (rather than the non-Timezone  
index). I suggest the following generalization:
`
                     foreach ($vEventException_r as $key => &$vEE){
                         if ($vEE instanceof Horde_Icalendar_Vtimezone){
                             unset($vEventException_r[$key]);
                         }
                     }
                     // This should never happen, but protect against  
it anyway.
                     if (count($vEventException_r) > 1) {
                         throw new Kronolith_Exception(_("Unable to  
parse event."));
                     }
                     $vEventException = array_pop($vEventException_r);
`





More information about the bugs mailing list