Example #1
0
 public function testDeletePid()
 {
     $reflectionClass = new ReflectionClass($this->_TMInstance);
     $reflectedMethod = $reflectionClass->getMethod('_killPids');
     $reflectedMethod->setAccessible(true);
     $reflectionProperty = $reflectionClass->getProperty('_numProcessesMax');
     $reflectionProperty->setAccessible(true);
     $reflectionProperty->setValue($this->_TMInstance, 20);
     //TEST remove pid 2 ( seek and destroy )
     //put a known pid into the list
     $this->_redisClient->getConnection()->sadd('ch_pid_set_p2', 2);
     //check for correctness
     $this->assertTrue($this->_redisClient->getConnection()->sismember('ch_pid_set_p2', 2));
     $reflectedMethod->invokeArgs($this->_TMInstance, array(null, 2));
     $list = $this->_redisClient->getConnection()->smembers('ch_pid_set_p2');
     $this->assertNotContains(2, $list);
     $config = parse_ini_file('tm_config.ini', true);
     //remove 3 elements from queue 1
     $x = QueuesList::get($config['context_definitions']);
     //        $old_len = $this->_redisClient->getConnection()->scard( $x->list[0]->pid_set_name );
     //        $reflectedMethod->invokeArgs( $this->_TMInstance, array( $x->list[0], 0, 3 ) );
     //        $new_len = $this->_redisClient->getConnection()->scard( $x->list[0]->pid_set_name );
     //        $this->assertEquals( 3, $old_len - $new_len );
     //        //put a known pid into the list
     //        $this->_redisClient->getConnection()->sadd( 'ch_pid_set_p3', 99999 );
     //        //check for correctness
     //        $this->assertTrue( $this->_redisClient->getConnection()->sismember( 'ch_pid_set_p3', 99999 ) );
     //        $reflectedMethod->invokeArgs( $this->_TMInstance, array( $x->list[2], 99999 ) );
     //        $list = $this->_redisClient->getConnection()->smembers( 'ch_pid_set_p2' );
     //        $this->assertNotContains( 99999, $list );
     //remove 5 pids by balancing
     $old_len = $this->_redisClient->getConnection()->scard($x->list['P1']->pid_set_name);
     $old_len += $this->_redisClient->getConnection()->scard($x->list['P2']->pid_set_name);
     $old_len += $this->_redisClient->getConnection()->scard($x->list['P3']->pid_set_name);
     $reflectedMethod->invokeArgs($this->_TMInstance, array(null, 0, 5));
     $new_len = $this->_redisClient->getConnection()->scard($x->list['P1']->pid_set_name);
     $new_len += $this->_redisClient->getConnection()->scard($x->list['P2']->pid_set_name);
     $new_len += $this->_redisClient->getConnection()->scard($x->list['P3']->pid_set_name);
     $this->assertEquals(5, $old_len - $new_len);
     //delete all pid in a list
     $reflectedMethod->invokeArgs($this->_TMInstance, array($x->list[2]));
     $new_len = $this->_redisClient->getConnection()->scard($x->list[2]->pid_set_name);
     $this->assertEquals(0, $new_len);
     //bad and stranges
     //remove a non existent pid from a list
     //there is not. expected: do nothing
     $old_len = $this->_redisClient->getConnection()->scard($x->list[1]->pid_set_name);
     $reflectedMethod->invokeArgs($this->_TMInstance, array($x->list[1], 99999));
     $new_len = $this->_redisClient->getConnection()->scard($x->list[1]->pid_set_name);
     $this->assertEquals(0, $old_len - $new_len);
     $this->assertNotEquals(0, $new_len);
     //Bad invocation, expected: pid kill routine but pid not found ( do nothing, ignore third param )
     $old_list = $this->_redisClient->getConnection()->smembers('ch_pid_set_p1');
     $old_list += $this->_redisClient->getConnection()->smembers('ch_pid_set_p2');
     $old_list += $this->_redisClient->getConnection()->smembers('ch_pid_set_p3');
     $this->assertNotContains(99999, $old_list);
     $reflectedMethod->invokeArgs($this->_TMInstance, array(null, 99999, 3));
     $new_list = $this->_redisClient->getConnection()->smembers('ch_pid_set_p1');
     $new_list += $this->_redisClient->getConnection()->smembers('ch_pid_set_p2');
     $new_list += $this->_redisClient->getConnection()->smembers('ch_pid_set_p3');
     $this->assertNotContains(99999, $new_list);
     $this->assertEquals($new_list, $old_list);
     //expected kill pid 99999 from queue2 and not found ( do nothing, ignore third param )
     $old_list = $this->_redisClient->getConnection()->smembers('ch_pid_set_p1');
     $this->assertNotContains(99999, $old_list);
     $reflectedMethod->invokeArgs($this->_TMInstance, array($x->list[0], 99999, 3));
     $new_list = $this->_redisClient->getConnection()->smembers('ch_pid_set_p1');
     $this->assertNotContains(99999, $new_list);
     //expected kill ALL pids and exit from infinite loop
     $old_list = $this->_redisClient->getConnection()->smembers('ch_pid_set_p1');
     $old_list += $this->_redisClient->getConnection()->smembers('ch_pid_set_p2');
     $old_list += $this->_redisClient->getConnection()->smembers('ch_pid_set_p3');
     $this->assertNotEmpty($old_list);
     $this->assertLessThan(3000, count($old_list));
     $reflectedMethod->invokeArgs($this->_TMInstance, array(null, 0, 3000));
     $new_list = $this->_redisClient->getConnection()->smembers('ch_pid_set_p1');
     $new_list += $this->_redisClient->getConnection()->smembers('ch_pid_set_p2');
     $new_list += $this->_redisClient->getConnection()->smembers('ch_pid_set_p3');
     $this->assertEmpty($new_list);
     //empty all queues
     $this->setUp();
     //remove second set
     $this->_redisClient->getConnection()->del('ch_pid_set_p2');
     $old_list = $this->_redisClient->getConnection()->smembers('ch_pid_set_p1');
     $old_list += $this->_redisClient->getConnection()->smembers('ch_pid_set_p3');
     $this->assertNotEmpty($old_list);
     $reflectedMethod->invokeArgs($this->_TMInstance, array());
     $new_list = $this->_redisClient->getConnection()->smembers('ch_pid_set_p1');
     $new_list += $this->_redisClient->getConnection()->smembers('ch_pid_set_p3');
     $this->assertEmpty($new_list);
 }
 public function doAction()
 {
     try {
         $this->_checkData();
     } catch (Exception $e) {
         if ($e->getCode() == -1) {
             Utils::sendErrMailReport($e->getMessage());
         }
         Log::doLog($e->getMessage());
         return $e->getCode();
     }
     //check tag mismatch
     //get original source segment, first
     $segment = getSegment($this->id_segment);
     //compare segment-translation and get results
     $check = new QA($segment['segment'], $this->translation);
     $check->performConsistencyCheck();
     if ($check->thereAreWarnings()) {
         $err_json = $check->getWarningsJSON();
         $translation = $this->translation;
     } else {
         $err_json = '';
         $translation = $check->getTrgNormalized();
     }
     /*
      * begin stats counter
      *
      * It works good with default InnoDB Isolation level
      *
      * REPEATABLE-READ offering a row level lock for this id_segment
      *
      */
     $db = Database::obtain();
     $db->begin();
     $old_translation = getCurrentTranslation($this->id_job, $this->id_segment);
     if (false === $old_translation) {
         $old_translation = array();
     }
     // $old_translation if `false` sometimes
     //if volume analysis is not enabled and no translation rows exists
     //create the row
     if (!INIT::$VOLUME_ANALYSIS_ENABLED && empty($old_translation['status'])) {
         $_Translation = array();
         $_Translation['id_segment'] = (int) $this->id_segment;
         $_Translation['id_job'] = (int) $this->id_job;
         $_Translation['status'] = Constants_TranslationStatus::STATUS_NEW;
         $_Translation['segment_hash'] = $segment['segment_hash'];
         $_Translation['translation'] = $segment['segment'];
         $_Translation['standard_word_count'] = $segment['raw_word_count'];
         $_Translation['serialized_errors_list'] = '';
         $_Translation['suggestion_position'] = 0;
         $_Translation['warning'] = false;
         $_Translation['translation_date'] = date("Y-m-d H:i:s");
         $res = addTranslation($_Translation);
         if ($res < 0) {
             $this->result['errors'][] = array("code" => -101, "message" => "database errors");
             $db->rollback();
             return $res;
         }
         /*
          * begin stats counter
          *
          */
         $old_translation = $_Translation;
     }
     $_Translation = array();
     $_Translation['id_segment'] = $this->id_segment;
     $_Translation['id_job'] = $this->id_job;
     $_Translation['status'] = $this->status;
     $_Translation['time_to_edit'] = $this->time_to_edit;
     $_Translation['translation'] = preg_replace('/[ \\t\\n\\r\\0\\x0A\\xA0]+$/u', '', $translation);
     $_Translation['serialized_errors_list'] = $err_json;
     $_Translation['suggestion_position'] = $this->chosen_suggestion_index;
     $_Translation['warning'] = $check->thereAreWarnings();
     $_Translation['translation_date'] = date("Y-m-d H:i:s");
     /**
      * Evaluate new Avg post-editing effort for the job:
      * - get old translation
      * - get suggestion
      * - evaluate $_seg_oldPEE and normalize it on the number of words for this segment
      *
      * - get new translation
      * - evaluate $_seg_newPEE and normalize it on the number of words for this segment
      *
      * - get $_jobTotalPEE
      * - evaluate $_jobTotalPEE - $_seg_oldPEE + $_seg_newPEE and save it into the job's row
      */
     $this->updateJobPEE($old_translation, $_Translation);
     $editLogModel = new EditLog_EditLogModel($this->id_job, $this->password);
     $this->result['pee_error_level'] = $editLogModel->getMaxIssueLevel();
     /**
      * when the status of the translation changes, the auto propagation flag
      * must be removed
      */
     if ($_Translation['translation'] != $old_translation['translation'] || $this->status == Constants_TranslationStatus::STATUS_TRANSLATED || $this->status == Constants_TranslationStatus::STATUS_APPROVED) {
         $_Translation['autopropagated_from'] = 'NULL';
     }
     $res = CatUtils::addSegmentTranslation($_Translation);
     if (!empty($res['errors'])) {
         $this->result['errors'] = $res['errors'];
         $msg = "\n\n Error addSegmentTranslation \n\n Database Error \n\n " . var_export(array_merge($this->result, $_POST), true);
         Log::doLog($msg);
         Utils::sendErrMailReport($msg);
         $db->rollback();
         return -1;
     }
     if (INIT::$DQF_ENABLED && !empty($this->jobData['dqf_key']) && $_Translation['status'] == Constants_TranslationStatus::STATUS_TRANSLATED) {
         $dqfSegmentStruct = DQF_DqfSegmentStruct::getStruct();
         if ($old_translation['suggestion'] == null) {
             $dqfSegmentStruct->target_segment = "";
             $dqfSegmentStruct->tm_match = 0;
         } else {
             $dqfSegmentStruct->target_segment = $old_translation['suggestion'];
             $dqfSegmentStruct->tm_match = $old_translation['suggestion_match'];
         }
         $dqfSegmentStruct->task_id = $this->id_job;
         $dqfSegmentStruct->segment_id = $this->id_segment;
         $dqfSegmentStruct->source_segment = $segment['segment'];
         $dqfSegmentStruct->new_target_segment = $_Translation['translation'];
         $dqfSegmentStruct->time = $_Translation['time_to_edit'];
         //            $dqfSegmentStruct->mtengine = $this->jobData['id_mt_engine'];
         $dqfSegmentStruct->mt_engine_version = 1;
         try {
             $dqfQueueHandler = new DqfQueueHandler();
             $dqfQueueHandler->createSegment($dqfSegmentStruct);
         } catch (Exception $exn) {
             $msg = $exn->getMessage() . "\n\n" . $exn->getTraceAsString();
             Log::doLog($msg);
             Utils::sendErrMailReport($msg);
         }
     }
     $propagateToTranslated = true;
     //for the moment, this is set explicitely
     if ($this->propagate == false) {
         $propagateToTranslated = false;
     }
     //propagate translations
     $TPropagation = array();
     //Warning: this value will NOT be used to update values,
     //but to exclude current segment from auto-propagation
     $_idSegment = $this->id_segment;
     $propagateToTranslated ? $TPropagation['status'] = $this->status : null;
     $TPropagation['id_job'] = $this->id_job;
     $TPropagation['translation'] = $translation;
     $TPropagation['autopropagated_from'] = $this->id_segment;
     $TPropagation['serialized_errors_list'] = $err_json;
     $TPropagation['warning'] = $check->thereAreWarnings();
     //        $TPropagation[ 'translation_date' ]       = date( "Y-m-d H:i:s" );
     $TPropagation['segment_hash'] = $old_translation['segment_hash'];
     $propagationTotal = array();
     if ($propagateToTranslated && in_array($this->status, array(Constants_TranslationStatus::STATUS_TRANSLATED, Constants_TranslationStatus::STATUS_APPROVED, Constants_TranslationStatus::STATUS_REJECTED))) {
         try {
             $propagationTotal = propagateTranslation($TPropagation, $this->jobData, $_idSegment, $propagateToTranslated);
         } catch (Exception $e) {
             $msg = $e->getMessage() . "\n\n" . $e->getTraceAsString();
             Log::doLog($msg);
             Utils::sendErrMailReport($msg);
             $db->rollback();
             return $e->getCode();
         }
     }
     $old_wStruct = $this->recountJobTotals($old_translation['status']);
     //redundant because the update is made only where status = old status
     if ($this->status != $old_translation['status']) {
         //cambiato status, sposta i conteggi
         $old_count = !is_null($old_translation['eq_word_count']) ? $old_translation['eq_word_count'] : $segment['raw_word_count'];
         //if there is not a row in segment_translations because volume analysis is disabled
         //search for a just created row
         $old_status = !empty($old_translation['status']) ? $old_translation['status'] : Constants_TranslationStatus::STATUS_NEW;
         $counter = new WordCount_Counter($old_wStruct);
         $counter->setOldStatus($old_status);
         $counter->setNewStatus($this->status);
         $newValues = array();
         $newValues[] = $counter->getUpdatedValues($old_count);
         foreach ($propagationTotal as $__pos => $old_value) {
             $counter->setOldStatus($old_value['status']);
             $counter->setNewStatus($this->status);
             $newValues[] = $counter->getUpdatedValues($old_value['total']);
         }
         try {
             $newTotals = $counter->updateDB($newValues);
         } catch (Exception $e) {
             $this->result['errors'][] = array("code" => -101, "message" => "database errors");
             Log::doLog("Lock: Transaction Aborted. " . $e->getMessage());
             $db->rollback();
             return $e->getCode();
         }
     } else {
         $newTotals = $old_wStruct;
     }
     //update total time to edit
     try {
         updateTotalTimeToEdit($this->id_job, $this->password, $this->time_to_edit);
     } catch (Exception $e) {
         $this->result['errors'][] = array("code" => -101, "message" => "database errors");
         Log::doLog("Lock: Transaction Aborted. " . $e->getMessage());
         //                $x1 = explode( "\n" , var_export( $old_translation, true) );
         //                Log::doLog("Lock: Translation status was " . implode( " ", $x1 ) );
         $db->rollback();
         return $e->getCode();
     }
     $job_stats = CatUtils::getFastStatsForJob($newTotals);
     $project = getProject($this->jobData['id_project']);
     $project = array_pop($project);
     $job_stats['ANALYSIS_COMPLETE'] = $project['status_analysis'] == Constants_ProjectStatus::STATUS_DONE || $project['status_analysis'] == Constants_ProjectStatus::STATUS_NOT_TO_ANALYZE ? true : false;
     $file_stats = array();
     $this->result['stats'] = $job_stats;
     $this->result['file_stats'] = $file_stats;
     $this->result['code'] = 1;
     $this->result['data'] = "OK";
     $this->result['version'] = date_create($_Translation['translation_date'])->getTimestamp();
     /* FIXME: added for code compatibility with front-end. Remove. */
     $_warn = $check->getWarnings();
     $warning = $_warn[0];
     /* */
     $this->result['warning']['cod'] = $warning->outcome;
     if ($warning->outcome > 0) {
         $this->result['warning']['id'] = $this->id_segment;
     } else {
         $this->result['warning']['id'] = 0;
     }
     //strtoupper transforms null to "" so check for the first element to be an empty string
     if (!empty($this->split_statuses[0]) && !empty($this->split_num)) {
         /* put the split inside the transaction if they are present */
         $translationStruct = TranslationsSplit_SplitStruct::getStruct();
         $translationStruct->id_segment = $this->id_segment;
         $translationStruct->id_job = $this->id_job;
         $translationStruct->target_chunk_lengths = array('len' => $this->split_chunk_lengths, 'statuses' => $this->split_statuses);
         $translationDao = new TranslationsSplit_SplitDAO(Database::obtain());
         $result = $translationDao->update($translationStruct);
     }
     $db->commit();
     //EVERY time an user changes a row in his job when the job is completed,
     // a query to do the update is executed...
     // Avoid this by setting a key on redis with an reasonable TTL
     $redisHandler = new RedisHandler();
     $job_status = $redisHandler->getConnection()->get('job_completeness:' . $this->id_job);
     if ($job_stats['TRANSLATED_PERC'] == '100' && empty($job_status)) {
         $redisHandler->getConnection()->setex('job_completeness:' . $this->id_job, 60 * 60 * 24 * 15, true);
         //15 days
         $update_completed = setJobCompleteness($this->id_job, 1);
         if ($update_completed < 0) {
             $msg = "\n\n Error setJobCompleteness \n\n " . var_export($_POST, true);
             $redisHandler->getConnection()->del('job_completeness:' . $this->id_job);
             Log::doLog($msg);
             Utils::sendErrMailReport($msg);
         }
     }
 }