/**
  * Run this BTX through the matchers
  * 
  * @param CRM_Banking_BAO_BankTransaction $btx
  * @param bool $override_processed   Set this to TRUE if you want to re-match processed transactions. 
  *                                    This will destroy all records of the execution!
  */
 public function match($btx_id, $override_processed = FALSE)
 {
     // TODO: timeout is 30s - do we need a setting here?
     $lock_timeout = 30.0;
     $lock = CRM_Utils_BankingSafeLock::acquireLock('org.project60.banking.tx' . '-' . $btx_id, $lock_timeout);
     if (empty($lock)) {
         error_log("org.project60.banking - couldn't acquire lock. Timeout is {$lock_timeout}.");
         return false;
     }
     // load btx
     $btx = new CRM_Banking_BAO_BankTransaction();
     $btx->get('id', $btx_id);
     if (!$override_processed) {
         // don't match already executed transactions...
         $processed_status_id = banking_helper_optionvalueid_by_groupname_and_name('civicrm_banking.bank_tx_status', 'Processed');
         $ignored_status_id = banking_helper_optionvalueid_by_groupname_and_name('civicrm_banking.bank_tx_status', 'Ignored');
         if ($btx->status_id == $processed_status_id || $btx->status_id == $ignored_status_id) {
             // will not match already executed transactions
             $lock->release();
             return true;
         }
     }
     // reset the BTX suggestion list
     $btx->resetSuggestions();
     // reset the cache / context object
     $context = new CRM_Banking_Matcher_Context($btx);
     // run through the list of matchers
     if (empty($this->plugins)) {
         CRM_Core_Session::setStatus(ts("No matcher plugins configured!"), ts('No processors'), 'alert');
     } else {
         foreach ($this->plugins as $weight => $plugins) {
             foreach ($plugins as $plugin) {
                 try {
                     // run matchers to generate suggestions
                     $continue = $this->matchPlugin($plugin, $context);
                     if (!$continue) {
                         $lock->release();
                         return true;
                     }
                     // check if we can execute the suggestion right aways
                     $abort = $this->checkAutoExecute($plugin, $btx);
                     if ($abort) {
                         $lock->release();
                         return false;
                     }
                 } catch (Exception $e) {
                     $matcher_id = $plugin->getPluginID();
                     error_log("org.project60.banking - Exception during the execution of matcher [{$matcher_id}], error was: " . $e->getMessage());
                     $lock->release();
                     return false;
                 }
             }
         }
     }
     $btx->saveSuggestions();
     // set the status
     $newStatus = banking_helper_optionvalueid_by_groupname_and_name('civicrm_banking.bank_tx_status', 'Suggestions');
     $btx->status_id = $newStatus;
     $btx->setStatus($newStatus);
     $lock->release();
     return false;
 }
 /**
  * Will release a lock with the given name, 
  *  if it has been acquired before
  */
 public function release()
 {
     if ($this->counter > 1) {
         // this is a lock that we acquired multiple times:
         //  simply decrease counter
         $this->counter -= 1;
         //error_log('released ' . getmypid() . "[{$this->counter}]");
     } elseif ($this->counter == 1) {
         // simply release the lock
         $this->counter = 0;
         $this->lock->release();
         self::$_acquired_lock = NULL;
         //error_log('released ' . getmypid());
     } else {
         // lock has already been released!
         error_log("org.project60.banking: This process cannot realease lock '{$name}', it has already been released before.");
         throw new Exception("This process cannot realease lock '{$name}', it has already been released before.");
     }
 }