/** * This validator method checks if srcid is a valid crash report ID or * debug info ID. */ public function checkSrcId() { if ($this->type == ProcessingError::TYPE_CRASH_REPORT_ERROR) { $crashReport = CrashReport::model()->find('id=' . $this->srcid); if ($crashReport === Null) { $this->addError('srcid', 'SrcID must be a valid crash report ID.'); return false; } } else { if ($this->type == ProcessingError::TYPE_DEBUG_INFO_ERROR) { $debugInfo = DebugInfo::model()->find('id=' . $this->srcid); if ($debugInfo === Null) { $this->addError('srcid', 'SrcID must be a valid debug info ID.'); return false; } } } return true; }
/** * Returns the data model based on the primary key given in the GET variable. * If the data model is not found, an HTTP exception will be raised. * @param integer the ID of the model to be loaded */ public function loadModel($id) { $model = CrashReport::model()->findByPk($id); if ($model === null) { throw new CHttpException(404, 'The requested page does not exist.'); } return $model; }
public function testGetCrashGroupTitle() { // Create new crash report $model = new CrashReport(); $model->md5 = '123456789012345678'; $model->project_id = 100; // invalid project id $model->status = CrashReport::STATUS_PROCESSED; $groupMD5 = ''; $title = $model->getCrashGroupTitle($groupMD5); $this->assertTrue($title == 'Unknown Project'); $this->assertTrue(strlen($groupMD5) != 0); $model->project_id = 1; // valid project id $groupMD5 = ''; $title = $model->getCrashGroupTitle($groupMD5); $this->assertTrue($title == 'Reports without Exception Info'); $this->assertTrue(strlen($groupMD5) != 0); // Find a pending crash report $model = CrashReport::model()->findByPk(1); $this->assertTrue($model != null); $groupMD5 = ''; $title = $model->getCrashGroupTitle($groupMD5); $this->assertTrue($title == 'Unsorted Reports'); $this->assertTrue(strlen($groupMD5) != 0); // Find an invalid crash report $model = CrashReport::model()->findByPk(5); $this->assertTrue($model != null); $groupMD5 = ''; $title = $model->getCrashGroupTitle($groupMD5); $this->assertTrue($title == 'Invalid Reports'); $this->assertTrue(strlen($groupMD5) != 0); // Find a processed crash report $model = CrashReport::model()->findByPk(4); $this->assertTrue($model != null); $groupMD5 = ''; $title = $model->getCrashGroupTitle($groupMD5); $this->assertTrue($title == 'CrashRptd.dll! wmain() +0x2bd9 [crtex.c: 120]'); $this->assertTrue(strlen($groupMD5) != 0); // Find another processed crash report $model = CrashReport::model()->findByPk(6); $this->assertTrue($model != null); $groupMD5 = ''; $title = $model->getCrashGroupTitle($groupMD5); $this->assertTrue($title == 'CrashRpt.dll!+0xf'); $this->assertTrue(strlen($groupMD5) != 0); }
/** * Generates a crash report geographic location distribution graph for currently * selected project and dumps it to stdout. * @param type $w Desired image width. * @param type $h Desired image height. * @throws CHttpException * @return void */ public static function generateGeoLocationDistributionGraph($w, $h, $file = null) { if (!is_numeric($w) || $w <= 0 || $w > 1024) { throw new CHttpException(403, 'Invalid parameter'); } if (!is_numeric($h) || $h <= 0 || $h > 960) { throw new CHttpException(403, 'Invalid parameter'); } // Get current project info $curProjectId = Yii::app()->user->getCurProjectId(); if ($curProjectId == false) { throw new CHttpException(403, 'Invalid parameter'); } // Prepare data $criteria = new CDbCriteria(); $criteria->select = 'geo_location, COUNT(*) as cnt'; $criteria->group = 'geo_location'; $criteria->compare('t.project_id', $curProjectId); $criteria->order = 'cnt DESC'; $curVer = '(not set)'; $versions = Yii::app()->user->getCurProjectVersions($curVer); if ($curVer != -1) { $criteria->compare('appversion_id', $curVer == 0 ? null : $curVer); } $data = array(); $models = CrashReport::model()->findAll($criteria); $totalCount = 0; foreach ($models as $model) { $totalCount += $model->cnt; if ($model->geo_location === null) { if (isset($data[''])) { $data[''] += $model->cnt; } else { $data[''] = $model->cnt; } } else { $data[$model->geo_location] = $model->cnt; } } if ($file == null) { $fout = fopen('php://output', 'w'); } else { $fout = fopen($file, 'wt'); } fprintf($fout, '<div class="digest-pane-image" style="width:' . $w . 'px;min-height:' . $h . 'px;max-height:' . $h . 'px;overflow:hidden"><table id="geo-locations">'); // Check the case when $data is empty. if (count($data) == 0) { fprintf($fout, '<tr><td><i>No data available</i></td></tr>'); } else { foreach ($data as $name => $val) { $percent = 100 * $val / $totalCount; $percentStr = sprintf('%0.1f', $percent); $nameStr = '(not set)'; if ($name != '') { $nameStr = MiscHelpers::addEllipsis(CrashReport::geoIdToCountryName($name), 30); } fprintf($fout, '<tr><td>' . $nameStr . '</td><td>' . $percentStr . '%%</td></tr>'); } } fprintf($fout, '</table></div>'); if ($file != null) { fclose($fout); } }
/** * Returns count of crash reports in this project. * @param integer $totalFileSize On output, receives the total size in bytes of files. * @param integer $percentOfDiskQuota On output, receives percent of disk quota. * @param integer $appver Optional. If specified, count of files is calculated for the given version. * @return integer count of crash report files. */ public function getCrashReportCount(&$totalFileSize, &$percentOfDiskQuota, $appver = Project::PROJ_VER_ALL) { // Find all crash reports belonging to this project and having // $appver application version. $criteria = new CDbCriteria(); $criteria->compare('project_id', $this->id, false, 'AND'); if ($appver != Project::PROJ_VER_ALL) { $criteria->compare('appversion_id', $appver, false, 'AND'); } $crashReports = CrashReport::model()->findAll($criteria); // Calculate count of crash reports $count = CrashReport::model()->count($criteria); // Calculate total file size $totalFileSize = 0; foreach ($crashReports as $crashReport) { $totalFileSize += $crashReport->filesize; } // Calc percent of disk quota if ($this->crash_report_files_disc_quota <= 0) { // unlimited $percentOfDiskQuota = -1; } else { $percentOfDiskQuota = 100 * $totalFileSize / ($this->crash_report_files_disc_quota * 1024 * 1024); } // Return file count return $count; }
/** * This method is executed before AR is saved to database. * In this method, we set some model attributes. * @return boolean True on success. */ protected function beforeSave() { if (!parent::beforeSave()) { return false; } // Check if this is a new record. if ($this->isNewRecord) { // Set project id $this->project_id = Yii::app()->user->getCurProjectId(); // Set project version $curVer = false; $versions = Yii::app()->user->getCurProjectVersions($curVer); if ($curVer != Project::PROJ_VER_ALL) { $this->appversion_id = $curVer; } else { // Project version '<all>' currently selected. // We have to determine bug version from associated // crash reports/collections. $numbers = MiscHelpers::splitNumberList($this->crashgroups); foreach ($numbers as $number) { $crashGroup = CrashGroup::model()->findByPk($number); if ($crashGroup === Null) { throw new HttpException('Invalid crash group ID'); } $curVer = $crashGroup->appversion_id; break; } if ($curVer == -1) { $numbers = MiscHelpers::splitNumberList($this->crashreports); foreach ($numbers as $number) { $crashReport = CrashReport::model()->findByPk($number); if ($crashReport === Null) { throw new HttpException('Invalid crash report ID'); } $curVer = $crashReport->appversion_id; break; } } if ($curVer == -1) { throw new CHttpException(403, 'Invalid request'); } $this->appversion_id = $curVer; } // Set date created $this->date_created = time(); // Set date last modified $this->date_last_modified = $this->date_created; // Set reported by $this->reported_by = Yii::app()->user->id; if ($this->assigned_to < 0) { unset($this->assigned_to); } } else { // Set date last modified $this->date_last_modified = time(); if ($this->status > Bug::STATUS_OPEN_MAX) { $this->date_closed = $this->date_last_modified; } else { unset($this->date_closed); } } // Success. return true; }
/** * Determines if a bug can be opened for this group. A bug can not be opened * if the crash group is empty or does not contain processed crash reports. * @return boolean true if a bug can be opened. */ public function canOpenNewBug() { // Calculate count of processed reports in this group $criteria = new CDbCriteria(); $criteria->compare('groupid', $this->id); $criteria->compare('status', CrashReport::STATUS_PROCESSED); $count = CrashReport::model()->count($criteria); if ($count == 0) { return false; } // No such reports // OK return true; }
/** * This method finalizes the given operation, updates appropriate db tables * and removes temporary files. */ public function finalizeOperation($op, $opStatus) { // Update operation db record. $op->status = $opStatus; $op->save(); if ($op->optype == Operation::OPTYPE_PROCESS_CRASH_REPORT) { // Delete temporary files and directories $crashReportFileName = $op->operand1; $xmlFileName = $op->operand2; if ($opStatus != Operation::STATUS_SUCCEEDED) { // Set crash report record status to Invalid Yii::log('Setting crash report #' . $op->srcid . ' status to invalid ', 'error'); $crashReport = CrashReport::model()->find('id=' . $op->srcid); if ($crashReport != null) { $crashReport->status = DebugInfo::STATUS_INVALID; $crashReport->save(); } } // Delete temp XML file Yii::log('Deleting file ' . $xmlFileName, 'info'); if (!@unlink($xmlFileName)) { // Couldn't delete file Yii::log('Error deleting file ' . $xmlFileName, 'error'); } } else { if ($op->optype == Operation::OPTYPE_IMPORTPDB) { // Delete temporary files and directories $pdbFileName = $op->operand1; $xmlFileName = $op->operand2; if ($opStatus != Operation::STATUS_SUCCEEDED) { // Set debug info record status to Invalid Yii::log('Setting debug info #' . $op->srcid . ' status to invalid ', 'error'); $debugInfo = DebugInfo::model()->find('id=' . $op->srcid); if ($debugInfo != null) { $debugInfo->status = DebugInfo::STATUS_INVALID; $debugInfo->save(); } } // Delete file Yii::log('Deleting file ' . $xmlFileName, 'info'); if (!@unlink($xmlFileName)) { // Couldn't delete file Yii::log('Error deleting file ' . $xmlFileName, 'error'); } // If operation has succeeded, we can remove original PDB file and // its parent directories, because the file was copied by daemon // to its persistent location. if ($op->status == Operation::STATUS_SUCCEEDED) { // Delete file Yii::log('Deleting file ' . $pdbFileName, 'info'); if (!@unlink($pdbFileName)) { // Couldn't delete file Yii::log('Error deleting file ' . $pdbFileName, 'error'); } // Delete parent directory. $parentDirName = dirname($pdbFileName); Yii::log('Deleting directory ' . $parentDirName, 'info'); if (!@rmdir($parentDirName)) { // Couldn't delete directory. Yii::log('Error deleting directory ' . $parentDirName, 'error'); } // Delete first-level parent directory. $parentDirName = dirname($parentDirName); Yii::log('Deleting directory ' . $parentDirName, 'info'); if (!@rmdir($parentDirName)) { // Couldn't delete dir Yii::log('Error deleting directory ' . $parentDirName, 'error'); } } } } }