multiprocs + etag update + calendar uuid fixes
authorPhilipp Schüle <p.schuele@metaways.de>
Thu, 14 Aug 2014 15:45:56 +0000 (17:45 +0200)
committerPhilipp Schüle <p.schuele@metaways.de>
Thu, 4 Sep 2014 09:26:41 +0000 (11:26 +0200)
+ improved logging
+ removed code duplication
+ make etag update work

Change-Id: Id282821b8c0abbc14cdcce3092a5301ec1a899a1
Reviewed-on: http://gerrit.tine20.com/customers/991
Reviewed-by: Philipp Schüle <p.schuele@metaways.de>
Tested-by: Philipp Schüle <p.schuele@metaways.de>
tine20/Calendar/Backend/Sql.php
tine20/Calendar/Frontend/Cli.php
tine20/Calendar/Import/CalDav/Client.php

index 163b800..ae52865 100644 (file)
@@ -835,6 +835,8 @@ class Calendar_Backend_Sql extends Tinebase_Backend_Sql_Abstract
     public function setETags(array $etags)
     {
         foreach ($etags as $id => $etag) {
+            //$etag = replaceSpecialChars($etag);
+            
             $where  = array(
                 $this->_db->quoteInto($this->_db->quoteIdentifier($this->_identifier) . ' = ?', $id),
             );
@@ -843,24 +845,34 @@ class Calendar_Backend_Sql extends Tinebase_Backend_Sql_Abstract
     }
     
     /**
-     * checks if there is and event with this id and etag
+     * checks if there is an event with this id and etag, or an event with the same id 
      * 
      * @param string $id
      * @param string $etag
+     * @return boolean
+     * @throws Tinebase_Exception_NotFound
      */
     public function checkETag($id, $etag)
     {
+        //$etag = replaceSpecialChars($etag);
+        
         $select = $this->_db->select();
         $select->from(array($this->_tableName => $this->_tablePrefix . $this->_tableName), $this->_identifier);
         $select->where($this->_db->quoteIdentifier($this->_identifier) . ' = ?', $id);
-        $select->where($this->_db->quoteIdentifier('etag') . ' = ?', $etag);
         
         $stmt = $select->query();
+        $queryResult = $stmt->fetch();
+        $stmt->closeCursor();
         
-        $stmt->execute();
-        if ($stmt->rowCount() > 0) {
-            return true;
+        if ($queryResult === false) {
+            throw new Tinebase_Exception_NotFound('no event with id ' . $id .' found');
         }
-        return false;
+        
+        $select->where($this->_db->quoteIdentifier('etag') . ' = ?', $etag);
+        $stmt = $select->query();
+        $queryResult = $stmt->fetch();
+        $stmt->closeCursor();
+        
+        return ($queryResult !== false);
     }
 }
index 0b50841..24f6a1d 100644 (file)
@@ -162,15 +162,17 @@ class Calendar_Frontend_Cli extends Tinebase_Frontend_Cli_Abstract
     {
         $args = $this->_parseArgs($_opts, array('url', 'caldavuserfile'));
         
-        $writer = new Zend_Log_Writer_Stream('php://output');
-        $writer->addFilter(new Zend_Log_Filter_Priority(4));
-        Tinebase_Core::getLogger()->addWriter($writer);
+        $this->_addOutputLogWriter(4);
         
         $users = $this->_readCalDavUserFile($args['caldavuserfile']);
         
-        $client = new Calendar_Import_CalDav_Client(array('baseUri' => $args['url']), 'MacOSX');
+        $this->_importAllCalendars($users, $args['url']);
+    }
+    
+    protected function _importAllCalendars($users, $uri)
+    {
+        $client = new Calendar_Import_CalDav_Client(array('baseUri' => $uri), 'MacOSX');
         $client->setVerifyPeer(false);
-        
         $client->importAllCalendarsForUsers($users);
     }
     
@@ -202,140 +204,142 @@ class Calendar_Frontend_Cli extends Tinebase_Frontend_Cli_Abstract
      */
     public function importCalDavMultiProc(Zend_Console_Getopt $_opts)
     {
+        $this->_runImportUpdateMultiproc($_opts, 'import');
+    }
+    
+    protected function _runImportUpdateMultiproc(Zend_Console_Getopt $_opts, $mode)
+    {
         $args = $this->_parseArgs($_opts, array('url', 'caldavuserfile', 'numProc'));
         
         $numProc = intval($args['numProc']);
-        if ($numProc < 1) {
-            throw new Exception('numProc: ' . $numProc . ' needs to be at least 1');
-        }
-        if ($numProc > 32) {
-            throw new Exception('numProc: ' . $numProc . ' needs to be lower than 33');
-        }
+        $this->_validateNumProc($numProc);
         
-        $opts = Tinebase_Core::get('opts');
-        if (empty($opts->passwordfile)) {
-            throw new Exception('Passwordfile requried for this method');
+        if (empty($_opts->passwordfile)) {
+            throw new Exception('Passwordfile required for this method');
         }
         
-        $writer = new Zend_Log_Writer_Stream('php://output');
-        $writer->addFilter(new Zend_Log_Filter_Priority(4));
-        Tinebase_Core::getLogger()->addWriter($writer);
+        $this->_addOutputLogWriter(4);
         
         $users = $this->_readCalDavUserFile($args['caldavuserfile']);
         
-        //first import the calendars, serial sadly
-        $client = new Calendar_Import_CalDav_Client(array('baseUri' => $args['url']), 'MacOSX');
-        $client->setVerifyPeer(false);
+        if ($mode === 'import') {
+            // first import the calendars, serial sadly
+            $this->_importAllCalendars($users, $args['url']);
+        }
         
-        $client->importAllCalendarsForUsers($users);
+        $cliParams = '--username ' . $_opts->username . ' --passwordfile ' . $_opts->passwordfile
+        . ' --method Calendar.' . $mode . 'CalDavDataForUser'
+                . ' url=' .  $args['url'] . ' caldavuserfile=' . $args['caldavuserfile'];
         
-        //then do multiprocess part, no system resources may be used as of here, like file handles, db resources... see pcntl_fork man page!
-        for ($run = 1; $run < 3; ++$run)
+        $numberOfRuns = ($mode === 'import') ? 2 : 1;
+        for ($run = 1; $run <= $numberOfRuns; ++$run)
         {
-            $processes = array();
-            $line = 0;
-            foreach ($users as $user => $pwd)
-            {
-                ++$line;
-                if (count($processes) >= $numProc) {
-                    $pid = pcntl_wait($status);
-                    if (!isset($processes[$pid])) {
-                        exit('pcntl_wait return value was not found in process list: ' . $pid . ' status: ' . $status . PHP_EOL);
-                    }
-                    unset($processes[$pid]);
-                }
-                
-                $pid = pcntl_fork();
-                if ($pid == -1) {
-                     exit('could not fork' . PHP_EOL);
-                } else if ($pid) {
-                     // we are the parent
-                     $processes[$pid] = true;
-                } else {
-                    // we are the child
-                    exec('./tine20.php --username ' . $opts->username . ' --passwordfile ' . $opts->passwordfile . ' --method Calendar.importCalDavDataForUser url="https://ical.familienservice.de:8443" caldavuserfile=caldavuserfile.csv run=' . $run . ' line=' . $line);
-                    exit();
-                }
-            }
-            //wait for childs to finish
-            while (count($processes) > 0) {
-                $pid = pcntl_wait($status);
-                if (!isset($processes[$pid])) {
-                    exit('pcntl_wait return value was not found in process list: ' . $pid . ' status: ' . $status . PHP_EOL);
-                }
-                unset($processes[$pid]);
-            }
+            $this->_runMultiProcessImportUpdate($numProc, $cliParams, $users, $run);
         }
     }
     
-    /**
-     * update calendar events from a CalDav source using multiple parallel processes
-     * 
-     * param Zend_Console_Getopt $_opts
-     */
-    public function updateCalDavMultiProc(Zend_Console_Getopt $_opts)
+    protected function _validateNumProc($numProc)
     {
-        $args = $this->_parseArgs($_opts, array('url', 'caldavuserfile', 'numProc'));
-        
-        $numProc = intval($args['numProc']);
         if ($numProc < 1) {
             throw new Exception('numProc: ' . $numProc . ' needs to be at least 1');
         }
         if ($numProc > 32) {
             throw new Exception('numProc: ' . $numProc . ' needs to be lower than 33');
         }
-        
-        $opts = Tinebase_Core::get('opts');
-        if (empty($opts->passwordfile)) {
-            throw new Exception('Passwordfile requried for this method');
-        }
-        
-        $writer = new Zend_Log_Writer_Stream('php://output');
-        $writer->addFilter(new Zend_Log_Filter_Priority(4));
-        Tinebase_Core::getLogger()->addWriter($writer);
-        
-        $users = $this->_readCalDavUserFile($args['caldavuserfile']);
-        
-        //do multiprocess part, no system resources may be used as of here, like file handles, db resources... see pcntl_fork man page!
-        for ($run = 1; $run < 3; ++$run)
+    }
+    
+    /**
+     * run multi process command
+     * 
+     * do multiprocess part, no system resources may be used as of here, 
+     * like file handles, db resources... see pcntl_fork man page!
+     * 
+     * @todo add pids to processes array to allow better control 
+     * @todo generalize and move to Tinebase_Frontend_Cli_Abstract
+     * 
+     * @param integer $numProc
+     * @param string $cliParams
+     * @param array $users
+     * @param integer $run
+     */
+    protected function _runMultiProcessImportUpdate($numProc, $cliParams, $users, $run = 1)
+    {
+        // $processes = array();
+        $processes = 0;
+        $line = 0;
+        foreach ($users as $user => $pwd)
         {
-            $processes = array();
-            $line = 0;
-            foreach ($users as $user => $pwd)
-            {
-                ++$line;
-                if (count($processes) >= $numProc) {
-                    $pid = pcntl_wait($status);
-                    if (!isset($processes[$pid])) {
-                        exit('pcntl_wait return value was not found in process list: ' . $pid . ' status: ' . $status . PHP_EOL);
-                    }
-                    unset($processes[$pid]);
-                }
-                
-                $pid = pcntl_fork();
-                if ($pid == -1) {
-                     exit('could not fork' . PHP_EOL);
-                } else if ($pid) {
-                     // we are the parent
-                     $processes[$pid] = true;
-                } else {
-                    // we are the child
-                    exec('./tine20.php --username ' . $opts->username . ' --passwordfile ' . $opts->passwordfile . ' --method Calendar.updateCalDavDataForUser url="https://ical.familienservice.de:8443" caldavuserfile=caldavuserfile.csv run=' . $run . ' line=' . $line);
-                    exit();
-                }
-            }
-            //wait for childs to finish
-            while (count($processes) > 0) {
+            ++$line;
+            //if (count($processes) >= $numProc) {
+            if ($processes >= $numProc) {
                 $pid = pcntl_wait($status);
-                if (!isset($processes[$pid])) {
+    
+                if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) Tinebase_Core::getLogger()->debug(__METHOD__ . ' ' . __LINE__
+                        . ' pid: ' . $pid);
+    
+                // debug
+                //                     echo '1' . (int) pcntl_wexitstatus($status);
+                //                     echo '2' . (int) pcntl_wifexited($status);
+                //                     echo '3' . (int) pcntl_wifsignaled($status);
+                //                     echo '4' . (int) pcntl_wifstopped($status);
+                //                     echo '5' . (int) pcntl_wstopsig($status);
+                //                     echo '6' . (int) pcntl_wtermsig($status);
+    
+                if (pcntl_wifexited($status) === false ) {
                     exit('pcntl_wait return value was not found in process list: ' . $pid . ' status: ' . $status . PHP_EOL);
                 }
-                unset($processes[$pid]);
+                
+                if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) Tinebase_Core::getLogger()->debug(__METHOD__ . ' ' . __LINE__
+                    . ' Child exited');
+                
+                // unset($processes[$pid]);
+                --$processes;
+            }
+    
+            $pid = pcntl_fork();
+            if ($pid == -1) {
+                exit('could not fork' . PHP_EOL);
+            } else if ($pid) {
+                // we are the parent
+                // $processes[$pid] = true;
+                ++$processes;
+            } else {
+                // we are the child
+                $command = './tine20.php ' . $cliParams . ' run=' . $run . ' line=' . $line;
+                
+                if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) Tinebase_Core::getLogger()->debug(__METHOD__ . ' ' . __LINE__
+                     . ' Spawning new child with command: ' . $command);
+                
+                exec($command);
+                exit();
+            }
+        }
+        // wait for childs to finish
+        // while (count($processes) > 0) {
+        while ($processes > 0) {
+            $pid = pcntl_wait($status);
+            if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) Tinebase_Core::getLogger()->debug(__METHOD__ . ' ' . __LINE__
+                    . ' pid: ' . $pid);
+    
+            if (pcntl_wifexited($status) === false) {
+                exit('pcntl_wait return value was not found in process list: ' . $pid . ' status: ' . $status . PHP_EOL);
             }
+            // unset($processes[$pid]);
+            --$processes;
         }
     }
     
     /**
+     * update calendar events from a CalDav source using multiple parallel processes
+     * 
+     * param Zend_Console_Getopt $_opts
+     */
+    public function updateCalDavMultiProc(Zend_Console_Getopt $_opts)
+    {
+        $this->_runImportUpdateMultiproc($_opts, 'update');
+    }
+    
+    /**
      * import calendar events from a CalDav source for one user
      * 
      * param Zend_Console_Getopt $_opts
@@ -348,10 +352,10 @@ class Calendar_Frontend_Cli extends Tinebase_Frontend_Cli_Abstract
         $writer->addFilter(new Zend_Log_Filter_Priority(4));
         Tinebase_Core::getLogger()->addWriter($writer);
         
-        if (Tinebase_Core::isLogLevel(Zend_Log::INFO))
-            Tinebase_Core::getLogger()->info(__METHOD__ . '::' . __LINE__ . ' in importCalDavDataForUser');
-        
         $user = $this->_readCalDavUserFile($args['caldavuserfile'], $args['line']);
+
+        if (Tinebase_Core::isLogLevel(Zend_Log::INFO))
+            Tinebase_Core::getLogger()->info(__METHOD__ . '::' . __LINE__ . ' user: ' . $user['username']);
         
         $client = new Calendar_Import_CalDav_Client(array(
                 'baseUri' => $args['url'],
@@ -360,17 +364,17 @@ class Calendar_Frontend_Cli extends Tinebase_Frontend_Cli_Abstract
                 ), 'MacOSX');
         $client->setVerifyPeer(false);
         
-        $client->importAllCalendarData($args['run']==1?true:false);
+        $client->importAllCalendarData($args['run']==1 ? true : false);
     }
     
     /**
      * update calendar/events from a CalDav source using etags for one user
      * 
-     * param Zend_Console_Getopt $_opts
+     * @param Zend_Console_Getopt $_opts
      */
     public function updateCalDavDataForUser(Zend_Console_Getopt $_opts)
     {
-        $args = $this->_parseArgs($_opts, array('url', 'caldavuserfile', 'line', 'run'));
+        $args = $this->_parseArgs($_opts, array('url', 'caldavuserfile', 'line'));
         
         $writer = new Zend_Log_Writer_Stream('php://output');
         $writer->addFilter(new Zend_Log_Filter_Priority(4));
@@ -378,6 +382,9 @@ class Calendar_Frontend_Cli extends Tinebase_Frontend_Cli_Abstract
         
         $user = $this->_readCalDavUserFile($args['caldavuserfile'], $args['line']);
         
+        if (Tinebase_Core::isLogLevel(Zend_Log::INFO))
+            Tinebase_Core::getLogger()->info(__METHOD__ . '::' . __LINE__ . ' user: ' . $user['username']);
+        
         $client = new Calendar_Import_CalDav_Client(array(
                 'baseUri' => $args['url'],
                 'userName' => $user['username'],
@@ -385,7 +392,7 @@ class Calendar_Frontend_Cli extends Tinebase_Frontend_Cli_Abstract
                 ), 'MacOSX');
         $client->setVerifyPeer(false);
         
-        $client->updateAllCalendarData($args['run']==1?true:false);
+        $client->updateAllCalendarData();
     }
     
     /**
index f4a96ba..3333c80 100644 (file)
@@ -21,6 +21,7 @@ class Calendar_Import_CalDav_Client extends Tinebase_Import_CalDav_Client
 {
     protected $calendars = array();
     protected $calendarICSs = array();
+    protected $existingRecordIds = array();
     protected $maxBulkRequest = 20;
     protected $mapToDefaultContainer = 'calendar';
     protected $decorator = null;
@@ -124,7 +125,13 @@ class Calendar_Import_CalDav_Client extends Tinebase_Import_CalDav_Client
     
     protected function findContainerForCalendar($calendarUri, $displayname, $defaultCalendarsName, $type, $application_id, $modelName)
     {
-        $uuid = basename($calendarUri);
+        if (! preg_match('@__uids__/([^/]+)@', $calendarUri, $matches)) {
+            throw new Exception('no uuid found in calendar uri');
+        }
+        $uuid = $matches[1];
+        
+        if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) Tinebase_Core::getLogger()->debug(__METHOD__ . ' ' . __LINE__
+                . ' $displayname = ' . $displayname . ' $defaultCalendarsName = ' . $defaultCalendarsName . ' $uuid = ' . $uuid);
         
         $filter = new Tinebase_Model_ContainerFilter(array(
             array(
@@ -139,7 +146,9 @@ class Calendar_Import_CalDav_Client extends Tinebase_Import_CalDav_Client
             ),
         ));
         $existingCalendar = Tinebase_Container::getInstance()->search($filter, null, false, false, 'sync')->getFirstRecord();
-        if($existingCalendar) {
+        if ($existingCalendar) {
+            if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) Tinebase_Core::getLogger()->debug(__METHOD__ . ' ' . __LINE__
+                . ' Found existing calendar ' . $existingCalendar->name . ' (id: ' . $existingCalendar->getId() . ')');
             return $existingCalendar;
         }
         
@@ -148,6 +157,8 @@ class Calendar_Import_CalDav_Client extends Tinebase_Import_CalDav_Client
         if ($defaultCalendarsName == $displayname) {
             $existingCalendar = Tinebase_Container::getInstance()->getDefaultContainer('Calendar_Model_Event');
             if (! $existingCalendar->uuid) {
+                if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) Tinebase_Core::getLogger()->debug(__METHOD__ . ' ' . __LINE__
+                    . ' Found existing calendar with the same name');
                 $existingCalendar->uuid = $uuid;
                 return $existingCalendar;
             }
@@ -158,6 +169,10 @@ class Calendar_Import_CalDav_Client extends Tinebase_Import_CalDav_Client
         try {
             while (true) {
                 $existingCalendar = Tinebase_Container::getInstance()->getContainerByName('Calendar', $displayname . $counter, $type, Tinebase_Core::getUser());
+                
+                if (Tinebase_Core::isLogLevel(Zend_Log::INFO)) Tinebase_Core::getLogger()->info(__METHOD__ . ' ' . __LINE__
+                    . ' Got calendar: ' . $existingCalendar->name . ' (id: ' . $existingCalendar->getId() . ')');
+                
                 if (! $existingCalendar->uuid) {
                     $existingCalendar->uuid = $uuid;
                     return $existingCalendar;
@@ -187,6 +202,7 @@ class Calendar_Import_CalDav_Client extends Tinebase_Import_CalDav_Client
             . ' Importing all calendars for user ' . $this->userName);
         
         Calendar_Controller_Event::getInstance()->sendNotifications(false);
+        Calendar_Controller_Event::getInstance()->useNotes(false);
         Sabre\VObject\Component\VCalendar::$propertyMap['ATTACH'] = '\\Calendar_Import_CalDav_SabreAttachProperty';
         
         $this->decorator->initCalendarImport();
@@ -196,16 +212,7 @@ class Calendar_Import_CalDav_Client extends Tinebase_Import_CalDav_Client
         $type = Tinebase_Model_Container::TYPE_PERSONAL; //Tinebase_Model_Container::TYPE_SHARED;
         $defaultContainer = Tinebase_Container::getInstance()->getDefaultContainer('Calendar_Model_Event');
         
-        //decide which calendar to use as default calendar
-        //if there is a remote default calendar, use that. If not, use the first we find
-        $defaultCalendarsName = '';
-        foreach ($this->calendarICSs as $calUri => $calICSs) {
-            if ($this->mapToDefaultContainer == $this->calendars[$calUri]['displayname']) {
-                $container = Tinebase_Container::getInstance()->getDefaultContainer('Calendar_Model_Event');
-            } elseif ($defaultsCalendarsName === '') {
-                $defaultCalendarsName = $this->calendars[$calUri]['displayname'];
-            }
-        }
+        $defaultCalendarsName = $this->_getDefaultCalendarsName();
         
         foreach ($this->calendars as $calUri => $cal) {
             $container = $this->findContainerForCalendar($calUri, $cal['displayname'], $defaultCalendarsName,
@@ -218,10 +225,40 @@ class Calendar_Import_CalDav_Client extends Tinebase_Import_CalDav_Client
         }
     }
     
+    /**
+     * decide which calendar to use as default calendar
+     * if there is a remote default calendar, use that. If not, use the first we find
+     * 
+     * @return string
+     */
+    protected function _getDefaultCalendarsName() 
+    {
+        $defaultCalendarsName = '';
+        foreach ($this->calendarICSs as $calUri => $calICSs) {
+            if ($this->mapToDefaultContainer == $this->calendars[$calUri]['displayname']) {
+                return $this->calendars[$calUri]['displayname'];
+            } elseif ($defaultCalendarsName === '') {
+                $defaultCalendarsName = $this->calendars[$calUri]['displayname'];
+            }
+        }
+        return $defaultCalendarsName;
+    }
+    
+    /**
+     * 
+     * @param string $onlyCurrentUserOrganizer
+     * @return boolean
+     * 
+     * @todo check if $onlyCurrentUserOrganizer is needed
+     * @todo check deletes
+     */
     public function updateAllCalendarData($onlyCurrentUserOrganizer = false)
     {
-        if (count($this->calendarICSs) < 1 && ! $this->findAllCalendarICSs())
+        if (count($this->calendarICSs) < 1 && ! $this->findAllCalendarICSs()) {
+            if (Tinebase_Core::isLogLevel(Zend_Log::INFO))
+                Tinebase_Core::getLogger()->info(__METHOD__ . '::' . __LINE__ . ' no calendars found for: ' . $this->userName);
             return false;
+        }
         
         $newICSs = array();
         $calendarEventBackend = Calendar_Controller_Event::getInstance()->getBackend();
@@ -243,45 +280,71 @@ class Calendar_Import_CalDav_Client extends Tinebase_Import_CalDav_Client
                     if (isset($value['{DAV:}getetag'])) {
                         $name = explode('/', $key);
                         $name = end($name);
-                        $id = ($pos = strpos($name, '.')) === false ? $name : substr($name, 0, $pos);
+                        $id = $this->_getEventIdFromName($name);
                         $etags[$key] = array( 'id' => $id, 'etag' => $value['{DAV:}getetag']);
                     }
                 }
             } while($start < $max);
             
             //check etags
+            if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) Tinebase_Core::getLogger()->debug(__METHOD__ . '::' . __LINE__ . ' '
+                . ' Got ' . count($etags) . ' etags');
+            if (Tinebase_Core::isLogLevel(Zend_Log::TRACE)) Tinebase_Core::getLogger()->trace(__METHOD__ . '::' . __LINE__ . ' '
+                . ' etags: ' . print_r($etags, true));
+            
+            // @todo find out deleted events
             foreach ($etags as $ics => $data) {
-                if (! $calendarEventBackend->checkETag($data['id'], $data['etag'])) {
-                    if (!isset($newICSs[$calUri])) {
-                        $newICSs[$calUri] = array();
+                try {
+                    $etagCheck = $calendarEventBackend->checkETag($data['id'], $data['etag']);
+                    if ($etagCheck) {
+                        continue; // same
+                    } else {
+                        $eventExists = true; // different
                     }
-                    $newICSs[$calUri][] = $ics;
+                } catch (Tinebase_Exception_NotFound $tenf) {
+                    $eventExists = false;
+                }
+                
+                if (!isset($newICSs[$calUri])) {
+                    $newICSs[$calUri] = array();
+                    $this->existingRecordIds[$calUri] = array();
+                }
+                $newICSs[$calUri][] = $ics;
+                if ($eventExists) {
+                    $this->existingRecordIds[$calUri][] = $data['id'];
                 }
             }
         }
         
         if (($count = count($newICSs)) > 0) {
-            if (Tinebase_Core::isLogLevel(Zend_Log::INFO))
-                Tinebase_Core::getLogger()->info(__METHOD__ . '::' . __LINE__ . ' ' . $count . ' calendar(s) changed for: ' . $this->userName);
+            if (Tinebase_Core::isLogLevel(Zend_Log::INFO)) Tinebase_Core::getLogger()->info(__METHOD__ . '::' . __LINE__ . ' ' 
+                    . $count . ' calendar(s) changed for: ' . $this->userName);
+            if (Tinebase_Core::isLogLevel(Zend_Log::DEBUG)) Tinebase_Core::getLogger()->info(__METHOD__ . '::' . __LINE__ . ' ' 
+                    . ' events changed: ' . print_r($newICSs, true));
             $this->calendarICSs = $newICSs;
-            $this->importAllCalendarData($onlyCurrentUserOrganizer);
+            $this->importAllCalendarData($onlyCurrentUserOrganizer, /* $update = */ true);
         } else {
             if (Tinebase_Core::isLogLevel(Zend_Log::WARN))
                 Tinebase_Core::getLogger()->warn(__METHOD__ . '::' . __LINE__ . ' no changes found for: ' . $this->userName);
-            
         }
     }
     
-    public function importAllCalendarData($onlyCurrentUserOrganizer = false)
+    protected function _getEventIdFromName($name)
+    {
+        return ($pos = strpos($name, '.')) === false ? $name : substr($name, 0, $pos);
+    }
+    
+    public function importAllCalendarData($onlyCurrentUserOrganizer = false, $update = false)
     {
         if (count($this->calendarICSs) < 1 && ! $this->findAllCalendarICSs()) {
             return false;
         }
         
         if (Tinebase_Core::isLogLevel(Zend_Log::INFO)) Tinebase_Core::getLogger()->info(__METHOD__ . ' ' . __LINE__
-            . ' Importing all calendar data for user ' . $this->userName);
+            . ' Importing all calendar data for user ' . $this->userName . ' with ics uris: ' . print_r(array_keys($this->calendarICSs), true));
         
         Calendar_Controller_Event::getInstance()->sendNotifications(false);
+        Calendar_Controller_Event::getInstance()->useNotes(false);
         Sabre\VObject\Component\VCalendar::$propertyMap['ATTACH'] = '\\Calendar_Import_CalDav_SabreAttachProperty';
         
         $this->decorator->initCalendarImport();
@@ -292,18 +355,12 @@ class Calendar_Import_CalDav_Client extends Tinebase_Import_CalDav_Client
         $defaultContainer = Tinebase_Container::getInstance()->getDefaultContainer('Calendar_Model_Event');
         $calendarEventBackend = Calendar_Controller_Event::getInstance()->getBackend();
         
-        //decide which calendar to use as default calendar
-        //if there is a remote default calendar, use that. If not, use the first we find
-        $defaultCalendarsName = '';
-        foreach ($this->calendarICSs as $calUri => $calICSs) {
-            if ($this->mapToDefaultContainer == $this->calendars[$calUri]['displayname']) {
-                $container = Tinebase_Container::getInstance()->getDefaultContainer('Calendar_Model_Event');
-            } elseif ($defaultsCalendarsName === '') {
-                $defaultCalendarsName = $this->calendars[$calUri]['displayname'];
-            }
-        }
+        $defaultCalendarsName = $this->_getDefaultCalendarsName();
         
         foreach ($this->calendarICSs as $calUri => $calICSs) {
+            if (Tinebase_Core::isLogLevel(Zend_Log::INFO)) Tinebase_Core::getLogger()->info(__METHOD__ . ' ' . __LINE__
+                . ' Processing calendar ' . print_r($this->calendars[$calUri], true));
+            
             $container = $this->findContainerForCalendar($calUri, $this->calendars[$calUri]['displayname'], $defaultCalendarsName,
                     $type, $application_id, $modelName);
             
@@ -331,13 +388,20 @@ class Calendar_Import_CalDav_Client extends Tinebase_Import_CalDav_Client
                         $data = $value['{urn:ietf:params:xml:ns:caldav}calendar-data'];
                         $name = explode('/', $key);
                         $name = end($name);
+                        $id = $this->_getEventIdFromName($name);
                         try {
-                            $event = Calendar_Frontend_WebDAV_Event::create(
-                                $container,
-                                $name,
-                                $data,
-                                $onlyCurrentUserOrganizer
-                            );
+                            if ($update && in_array($id, $this->existingRecordIds[$calUri])) {
+                                $event = new Calendar_Frontend_WebDAV_Event($container, $id);
+                                $event->put($data);
+                            } else {
+                                $event = Calendar_Frontend_WebDAV_Event::create(
+                                    $container,
+                                    $name,
+                                    $data,
+                                    $onlyCurrentUserOrganizer
+                                );
+                            }
+                            
                             if ($event) {
                                 $etags[$event->getRecord()->getId()] = $value['{DAV:}getetag'];
                             }
@@ -442,16 +506,16 @@ class Calendar_Import_CalDav_Client extends Tinebase_Import_CalDav_Client
     
     public function updateAllCalendarDataForUsers(array $users)
     {
-        // first only update/import events where the current user is also the organizer
         $result = true;
-        foreach ($users as $username => $pwd) {
-            $this->clearCurrentUserCalendarData();
-            $this->userName = $username;
-            $this->password = $pwd;
-            if (!$this->updateAllCalendarData(true)) {
-                $result = false;
-            }
-        }
+        // first only update/import events where the current user is also the organizer
+//         foreach ($users as $username => $pwd) {
+//             $this->clearCurrentUserCalendarData();
+//             $this->userName = $username;
+//             $this->password = $pwd;
+//             if (!$this->updateAllCalendarData(true)) {
+//                 $result = false;
+//             }
+//         }
         // then update all events again
         foreach ($users as $username => $pwd) {
             $this->clearCurrentUserCalendarData();
@@ -467,24 +531,6 @@ class Calendar_Import_CalDav_Client extends Tinebase_Import_CalDav_Client
     public function importAllCalendarDataForUsers(array $users)
     {
         $result = true;
-        foreach ($users as $username => $pwd) {
-            $this->clearCurrentUserCalendarData();
-            $this->userName = $username;
-            $this->password = $pwd;
-            if (!$this->updateAllCalendarData()) {
-                $result = false;
-            }
-        }
-        return $result;
-    }
-    
-    public function importAllCalendarDataForUsers(array $users)
-    {
-        if (!$this->findCurrentUserPrincipalForUsers($users)) {
-            return false;
-        }
-        
-        $result = true;
         // first only import events where the current user is also the organizer
         foreach ($users as $username => $pwd) {
             $this->clearCurrentUserCalendarData();