Ejemplo n.º 1
0
 public static function __startup()
 {
     $user_key = pts_module::read_variable('PUSHOVER_NET_USER');
     if ($user_key == null) {
         echo PHP_EOL . 'Your Pushover.net user key must be passed via the PUSHOVER_NET_USER environment variable.' . PHP_EOL;
         return pts_module::MODULE_UNLOAD;
     }
     if (function_exists('curl_setopt_array') == false || function_exists('curl_init') == false) {
         echo PHP_EOL . 'PHP5 CURL support must be installed to use this module.' . PHP_EOL;
         return pts_module::MODULE_UNLOAD;
     }
     self::$pushover_net_user_key = $user_key;
     return true;
 }
Ejemplo n.º 2
0
 public static function run($r)
 {
     $module = strtolower($r[0]);
     $pre_message = null;
     if (!class_exists($module)) {
         pts_module_manager::load_module($module);
     }
     $module_name = pts_module_manager::module_call($module, 'module_name');
     $module_description = pts_module_manager::module_call($module, 'module_description');
     $module_setup = pts_module_manager::module_call($module, 'module_setup');
     pts_client::$display->generic_heading($module_name . ' Module Configuration');
     echo $module_description . PHP_EOL;
     if (count($module_setup) == 0) {
         echo PHP_EOL . 'There are no options available for configuring with the ' . $module . ' module.' . PHP_EOL;
     } else {
         if (($module_presets = pts_client::read_env('PTS_MODULE_SETUP')) != false) {
             $module_presets = pts_client::parse_value_string_double_identifier($module_presets);
         }
         $set_options = array();
         foreach ($module_setup as $module_option) {
             if ($module_option instanceof pts_module_option) {
                 $option_identifier = $module_option->get_identifier();
                 if (isset($module_presets[$module][$option_identifier]) && $module_option->is_supported_value($module_presets[$module][$option_identifier])) {
                     echo PHP_EOL . $module_option->get_formatted_question();
                     echo $module_presets[$module][$option_identifier] . PHP_EOL;
                     $input = $module_presets[$module][$option_identifier];
                 } else {
                     do {
                         echo PHP_EOL . $module_option->get_formatted_question();
                         $input = pts_user_io::read_user_input();
                     } while (!$module_option->is_supported_value($input));
                 }
                 if (empty($input)) {
                     $input = $module_option->get_default_value();
                 }
                 $set_options[$option_identifier] = $input;
             }
         }
         $set_options = pts_module_manager::module_call($module, 'module_setup_validate', $set_options);
         if (!empty($set_options)) {
             pts_module::module_config_save($module, $set_options);
         }
     }
     echo PHP_EOL;
 }
 private static function process_summary_results(&$sensor, &$test_run_manager)
 {
     $sensor_results = self::parse_monitor_log('logs/' . phodevi::sensor_object_identifier($sensor));
     pts_module::remove_file('logs/' . phodevi::sensor_object_identifier($sensor));
     if (count($sensor_results) > 2 && self::$monitor_test_count > 1) {
         $test_profile = new pts_test_profile();
         $test_result = new pts_test_result($test_profile);
         $test_result->test_profile->set_test_title(phodevi::sensor_object_name($sensor) . ' Monitor');
         $test_result->test_profile->set_identifier(null);
         $test_result->test_profile->set_version(null);
         $test_result->test_profile->set_result_proportion(null);
         $test_result->test_profile->set_display_format('LINE_GRAPH');
         $test_result->test_profile->set_result_scale(phodevi::read_sensor_object_unit($sensor));
         $test_result->set_used_arguments_description('Phoronix Test Suite System Monitoring');
         $test_result->set_used_arguments(phodevi::sensor_object_identifier($sensor));
         $test_result->test_result_buffer = new pts_test_result_buffer();
         $test_result->test_result_buffer->add_test_result(self::$result_identifier, implode(',', $sensor_results), implode(',', $sensor_results), implode(',', $sensor_results), implode(',', $sensor_results));
         $test_run_manager->result_file->add_result($test_result);
     }
 }
Ejemplo n.º 4
0
 public static function execute_command($command, $pass_args = null)
 {
     if (!class_exists($command, false) && is_file(PTS_COMMAND_PATH . $command . '.php')) {
         include PTS_COMMAND_PATH . $command . '.php';
     }
     if (is_file(PTS_COMMAND_PATH . $command . '.php') && method_exists($command, 'argument_checks')) {
         $argument_checks = call_user_func(array($command, 'argument_checks'));
         foreach ($argument_checks as &$argument_check) {
             $function_check = $argument_check->get_function_check();
             $method_check = false;
             if (is_array($function_check) && count($function_check) == 2) {
                 $method_check = $function_check[0];
                 $function_check = $function_check[1];
             }
             if (substr($function_check, 0, 1) == '!') {
                 $function_check = substr($function_check, 1);
                 $return_fails_on = true;
             } else {
                 $return_fails_on = false;
             }
             if ($method_check != false) {
                 if (!method_exists($method_check, $function_check)) {
                     echo PHP_EOL . 'Method check fails.' . PHP_EOL;
                     continue;
                 }
                 $function_check = array($method_check, $function_check);
             } else {
                 if (!function_exists($function_check)) {
                     continue;
                 }
             }
             if ($argument_check->get_argument_index() == 'VARIABLE_LENGTH') {
                 $return_value = null;
                 foreach ($pass_args as $arg) {
                     $return_value = call_user_func_array($function_check, array($arg));
                     if ($return_value == true) {
                         break;
                     }
                 }
             } else {
                 $return_value = call_user_func_array($function_check, array(isset($pass_args[$argument_check->get_argument_index()]) ? $pass_args[$argument_check->get_argument_index()] : null));
             }
             if ($return_value == $return_fails_on) {
                 $command_alias = defined($command . '::doc_use_alias') ? constant($command . '::doc_use_alias') : $command;
                 if (isset($pass_args[$argument_check->get_argument_index()]) && !empty($pass_args[$argument_check->get_argument_index()]) || $argument_check->get_argument_index() == 'VARIABLE_LENGTH' && !empty($pass_args)) {
                     trigger_error('Invalid Argument: ' . implode(' ', $pass_args), E_USER_ERROR);
                 } else {
                     trigger_error('Phoronix Test Suite Argument Missing.', E_USER_ERROR);
                 }
                 echo PHP_EOL . 'CORRECT SYNTAX:' . PHP_EOL . 'phoronix-test-suite ' . str_replace('_', '-', $command_alias) . ' ' . implode(' ', $argument_checks) . PHP_EOL . PHP_EOL;
                 if (method_exists($command, 'invalid_command')) {
                     call_user_func_array(array($command, 'invalid_command'), $pass_args);
                     echo PHP_EOL;
                 }
                 return false;
             } else {
                 if ($argument_check->get_function_return_key() != null && !isset($pass_args[$argument_check->get_function_return_key()])) {
                     $pass_args[$argument_check->get_function_return_key()] = $return_value;
                 }
             }
         }
     }
     pts_module_manager::module_process('__pre_option_process', $command);
     if (is_file(PTS_COMMAND_PATH . $command . '.php')) {
         self::$current_command = $command;
         if (method_exists($command, 'run')) {
             call_user_func(array($command, 'run'), $pass_args);
         } else {
             echo PHP_EOL . 'There is an error in the requested command: ' . $command . PHP_EOL . PHP_EOL;
         }
     } else {
         if (($t = pts_module::valid_run_command($command)) != false) {
             list($module, $module_command) = $t;
             pts_module_manager::set_current_module($module);
             pts_module_manager::run_command($module, $module_command, $pass_args);
             pts_module_manager::set_current_module(null);
         }
     }
     echo PHP_EOL;
     pts_module_manager::module_process('__post_option_process', $command);
 }
 public static function __post_run_process(&$object)
 {
     $executable = pts_module::read_option('post_test_process');
     self::process_user_config_external_hook_process('post_test_process', $executable, 'Running the post-test process external hook', $object);
 }
 public static function get_screenshots()
 {
     if (!empty(self::$screenshots)) {
         return self::$screenshots;
     } else {
         // Another thread is going on and thread empty so try to query the file-system for differences
         $screenshots = pts_file_io::glob(pts_module::save_dir() . 'screenshot-*.png');
         return array_diff($screenshots, self::$existing_screenshots);
     }
 }
Ejemplo n.º 7
0
 public static function set_option($identifier, $value)
 {
     pts_module::module_config_save(self::module_name(), array($identifier => $value));
 }
// Default to C locale
setlocale(LC_ALL, 'C');
// Needed for shutdown functions
// declare(ticks = 1);
$sent_command = strtolower(str_replace('-', '_', isset($argv[1]) ? $argv[1] : null));
$quick_start_options = array('dump_possible_options');
pts_define('QUICK_START', in_array($sent_command, $quick_start_options));
if (QUICK_START == false) {
    pts_client::program_requirement_checks(true);
}
pts_client::init();
// Initalize the Phoronix Test Suite (pts-core) client
$pass_args = array();
if (is_file(PTS_PATH . 'pts-core/commands/' . $sent_command . '.php') == false) {
    $replaced = false;
    if (pts_module::valid_run_command($sent_command)) {
        $replaced = true;
    } else {
        if (isset($argv[1]) && strpos($argv[1], '.openbenchmarking') !== false && is_readable($argv[1])) {
            $sent_command = 'openbenchmarking_launcher';
            $argv[2] = $argv[1];
            $argc = 3;
            $replaced = true;
        } else {
            $aliases = pts_storage_object::read_from_file(PTS_TEMP_STORAGE, 'command_alias_list');
            if ($aliases == null) {
                $aliases = pts_documentation::client_commands_aliases();
            }
            if (isset($aliases[$sent_command])) {
                $sent_command = $aliases[$sent_command];
                $replaced = true;
Ejemplo n.º 9
0
 private static function set_user_context($context_script, $trigger, $schedule_id, $process)
 {
     if (!empty($context_script)) {
         $context_file = pts_client::create_temporary_file();
         file_put_contents($context_file, $context_script);
         chmod($context_file, 0755);
         pts_file_io::mkdir(pts_module::save_dir());
         $storage_path = pts_module::save_dir() . 'memory.pt2so';
         $storage_object = pts_storage_object::recover_from_file($storage_path);
         $notes_log_file = pts_module::save_dir() . sha1($trigger . $schedule_id . $process);
         // We check to see if the context was already set but the system rebooted or something in that script
         if ($storage_object == false) {
             $storage_object = new pts_storage_object(true, true);
         } else {
             if ($storage_object->read_object('last_set_context_trigger') == $trigger && $storage_object->read_object('last_set_context_schedule') == $schedule_id && $storage_object->read_object('last_set_context_process') == $process) {
                 // If the script already ran once for this trigger, don't run it again
                 self::check_user_context_log($trigger, $schedule_id, $process, $notes_log_file, null);
                 return false;
             }
         }
         $storage_object->add_object('last_set_context_trigger', $trigger);
         $storage_object->add_object('last_set_context_schedule', $schedule_id);
         $storage_object->add_object('last_set_context_process', $process);
         $storage_object->save_to_file($storage_path);
         phoromatic::update_system_status('Setting context for: ' . $schedule_id . ' - ' . $trigger . ' - ' . $process);
         // Run the set context script
         $env_vars['PHOROMATIC_TRIGGER'] = $trigger;
         $env_vars['PHOROMATIC_SCHEDULE_ID'] = $schedule_id;
         $env_vars['PHOROMATIC_SCHEDULE_PROCESS'] = $process;
         $env_vars['PHOROMATIC_LOG_FILE'] = $notes_log_file;
         $log_output = pts_client::shell_exec('./' . $context_script . ' ' . $trigger . ' 2>&1', $env_vars);
         self::check_user_context_log($trigger, $schedule_id, $process, $notes_log_file, $log_output);
         // Just simply return true for now, perhaps check exit code status and do something
         return true;
     }
     return false;
 }
Ejemplo n.º 10
0
 protected static function process_user_config_external_hook_process($process)
 {
     // Check to not run the same process
     $last_call_file = pts_module::save_dir() . self::$context . '.last-call';
     if (is_file($last_call_file)) {
         $check = pts_file_io::file_get_contents($last_call_file);
         if ($process == $check) {
             unlink($last_call_file);
             return false;
         }
     }
     $process != 'post_run' && file_put_contents($last_call_file, $process);
     if (self::$ini['set_context'][$process]) {
         $command = self::find_file(self::$ini['set_context'][$process]) ? self::find_file(self::$ini['set_context'][$process]) : self::$ini['set_context'][$process];
         $descriptor_spec = array(0 => array('pipe', 'r'), 1 => array('pipe', 'w'), 2 => array('pipe', 'w'));
         $env_vars = null;
         pts_client::$display->test_run_instance_error('Running ' . $process . ' set-context script.');
         if (is_executable($command)) {
             // Pass the context as the first argument to the string
             $command .= ' ' . self::$context;
         } else {
             // Else find $MATISK_CONTEXT in the command string
             $command = str_replace('$MATISK_CONTEXT', self::$context, $command);
         }
         $proc = proc_open($command, $descriptor_spec, $pipes, null, $env_vars);
         echo $std_output = stream_get_contents($pipes[1]);
         $return_value = proc_close($proc);
         if (pts_strings::string_bool(self::$ini['set_context']['log_context_outputs'])) {
             file_put_contents(pts_module::save_dir() . $ini['workload']['save_name'] . '/' . self::$context . '-' . $process . '.txt', $std_output);
         }
         switch ($return_value) {
             case 8:
                 exit(0);
             case 9:
                 self::$skip_test_set = true;
                 break;
         }
     }
 }
 public static function __startup()
 {
     $halt_screensaver = pts_module::read_variable('HALT_SCREENSAVER');
     if (!empty($halt_screensaver) && !pts_strings::string_bool($halt_screensaver) || phodevi::read_property('system', 'display-server') == null) {
         return pts_module::MODULE_UNLOAD;
     }
     if (phodevi::is_macosx()) {
         // Right now there doesn't appear to be a better way to disable OS X screensaver automatically...
         return pts_module::MODULE_UNLOAD;
     }
     // GNOME Screensaver?
     if (($gt = pts_client::executable_in_path('gconftool')) != false || ($gt = pts_client::executable_in_path('gconftool-2')) != false) {
         self::$gnome_gconftool = $gt;
     }
     if (self::$gnome_gconftool != false) {
         $is_gnome_screensaver_enabled = trim(shell_exec(self::$gnome_gconftool . ' -g /apps/gnome-screensaver/idle_activation_enabled 2>&1'));
         if ($is_gnome_screensaver_enabled == 'true') {
             // Stop the GNOME Screensaver
             shell_exec(self::$gnome_gconftool . ' --type bool --set /apps/gnome-screensaver/idle_activation_enabled false 2>&1');
             self::$gnome2_screensaver_halted = true;
         }
         $sleep_display_ac = trim(shell_exec(self::$gnome_gconftool . ' -g /apps/gnome-power-manager/timeout/sleep_display_ac 2>&1'));
         if ($sleep_display_ac != 0) {
             // Don't sleep the display when on AC power
             shell_exec(self::$gnome_gconftool . ' --type int --set /apps/gnome-power-manager/timeout/sleep_display_ac 0 2>&1');
             self::$sleep_display_ac = $sleep_display_ac;
         }
     }
     if (pts_client::executable_in_path('qdbus')) {
         // KDE Screensaver?
         $is_kde_screensaver_enabled = trim(shell_exec('qdbus org.freedesktop.ScreenSaver /ScreenSaver org.freedesktop.ScreenSaver.GetActive 2>&1'));
         if ($is_kde_screensaver_enabled == 'true') {
             // Stop the KDE Screensaver
             shell_exec('qdbus org.freedesktop.ScreenSaver  /ScreenSaver SimulateUserActivity 2>&1');
             self::$kde_screensaver_halted = true;
         }
     }
     if (self::$gnome2_screensaver_halted == false && pts_client::executable_in_path('gsettings')) {
         // GNOME 3.x Screensaver?
         $is_gnome3_screensaver_enabled = trim(shell_exec('gsettings get org.gnome.desktop.session idle-delay 2>&1'));
         if (stripos($is_gnome3_screensaver_enabled, 'no such key') === false && pts_strings::last_in_string($is_gnome3_screensaver_enabled) > 0) {
             // Stop the GNOME 3.x Screensaver
             shell_exec('gsettings set org.gnome.desktop.session idle-delay 0 2>&1');
             self::$gnome3_screensaver_halted = pts_strings::last_in_string($is_gnome3_screensaver_enabled);
         }
         // GNOME 3.x Lock-Screen
         $is_gnome3_lockscreen_enabled = trim(shell_exec('gsettings get org.gnome.desktop.lockdown disable-lock-screen 2>&1'));
         if (stripos($is_gnome3_lockscreen_enabled, 'no such key') === false && pts_strings::last_in_string($is_gnome3_lockscreen_enabled) == 'false') {
             // Stop the GNOME 3.x Lock Screen
             shell_exec('gsettings set org.gnome.desktop.lockdown disable-lock-screen true 2>&1');
             self::$gnome3_lockscreen_disabled = true;
         }
         // This GNOME3 GSettings method is deprecated on distributions like GNOME 3.8 with Fedora 19
         $is_gnome3_screensaver_enabled_old = trim(shell_exec('gsettings get org.gnome.desktop.screensaver idle-activation-enabled 2>&1'));
         if ($is_gnome3_screensaver_enabled_old == 'true') {
             // Stop the GNOME 3.x Screensaver
             shell_exec('gsettings set org.gnome.desktop.screensaver idle-activation-enabled false 2>&1');
             self::$gnome3_screensaver_halted_old = true;
         }
         // GNOME 3.x Sleep Dispaly?
         $is_gnome3_sleep = trim(shell_exec('gsettings get org.gnome.settings-daemon.plugins.power sleep-display-ac 2>&1'));
         if ($is_gnome3_sleep > 0) {
             // Stop the GNOME 3.x Display Sleep
             shell_exec('gsettings set org.gnome.settings-daemon.plugins.power sleep-display-ac 0 2>&1');
             self::$sleep_display_ac = $is_gnome3_sleep;
         }
     }
     if (pts_client::executable_in_path('xfconf-query')) {
         $is_xfce_screensaver_enabled = stripos(shell_exec('xfconf-query -c xfce4-session -p /startup/screensaver/enabled 2>&1'), 'false') !== false;
         if ($is_xfce_screensaver_enabled) {
             shell_exec('xfconf-query -c xfce4-session -n -t bool -p /startup/screensaver/enabled -s false 2>&1');
             self::$xfce_screensaver_halted = true;
         }
     }
     if (getenv('DISPLAY') != false && (self::$xset = pts_client::executable_in_path('xset'))) {
         shell_exec('xset s off 2>&1');
     } else {
         if (getenv('DISPLAY') == false && pts_client::executable_in_path('setterm')) {
             shell_exec('setterm -powersave off -blank 0 2>&1');
         }
     }
     if (self::$gnome2_screensaver_halted || self::$gnome3_screensaver_halted || self::$gnome3_screensaver_halted_old || self::$kde_screensaver_halted || self::$xfce_screensaver_halted) {
         self::$screensaver_halted = true;
     }
     if (($xdg = pts_client::executable_in_path('xdg-screensaver')) == false) {
         self::$xdg_screensaver_available = $xdg;
     }
     if ($xscreensaver = pts_client::executable_in_path('xscreensaver-command')) {
         shell_exec($xscreensaver . ' -exit 2>&1');
     }
 }
Ejemplo n.º 12
0
 protected static function phoromatic_setup_module()
 {
     if (!pts_module::is_module_setup()) {
         echo PHP_EOL . 'You first must run:' . PHP_EOL . PHP_EOL . 'phoronix-test-suite module-setup phoromatic' . PHP_EOL . PHP_EOL;
         return false;
     }
     self::$phoromatic_host = pts_module::read_option('remote_host');
     self::$phoromatic_account = pts_module::read_option('remote_account');
     self::$phoromatic_verifier = pts_module::read_option('remote_verifier');
     self::$phoromatic_system = pts_module::read_option('remote_system');
     if (extension_loaded('openssl') == false) {
         // OpenSSL is not supported therefore no HTTPS support
         self::$phoromatic_host = str_replace('https://', 'http://', self::$phoromatic_host);
     }
     $phoromatic = 'phoromatic';
     pts_module_manager::attach_module($phoromatic);
     return true;
 }
 public static function clean_module_list()
 {
     array_unique(self::$modules);
     foreach (self::$modules as $i => $module) {
         if (pts_module::is_module($module) == false) {
             unset(self::$modules[$i]);
         }
     }
 }
Ejemplo n.º 14
0
 private static function parse_monitor_log($log_file, $start_offset = 0)
 {
     $log_f = pts_module::read_file($log_file);
     $line_breaks = explode(PHP_EOL, $log_f);
     $results = array();
     for ($i = 0; $i < $start_offset && isset($line_breaks[$i]); $i++) {
         unset($line_breaks[$i]);
     }
     foreach ($line_breaks as $line) {
         $line = trim($line);
         if (!empty($line) && $line >= 0) {
             array_push($results, $line);
         }
     }
     if (count($results) > 0 && max($results) == 0) {
         $results = array();
     }
     return $results;
 }
 public static function __pre_run_process()
 {
     if (!(phodevi::is_nvidia_graphics() || phodevi::is_ati_graphics() && phodevi::is_linux())) {
         echo "\nNo supported driver found for graphics_override module!\n";
         return pts_module::MODULE_UNLOAD;
         // Not using a supported driver, quit the module
     }
     $force_aa = pts_module::read_variable("FORCE_AA");
     $force_af = pts_module::read_variable("FORCE_AF");
     if ($force_aa !== FALSE && in_array($force_aa, self::$supported_aa_levels)) {
         // First backup any existing override, then set the new value
         if (phodevi::is_nvidia_graphics()) {
             self::$preset_aa = phodevi_parser::read_nvidia_extension("FSAA");
             self::$preset_aa_control = phodevi_parser::read_nvidia_extension("FSAAAppControlled");
             switch ($force_aa) {
                 case 2:
                     $nvidia_aa = 2;
                     break;
                 case 4:
                     $nvidia_aa = 5;
                     break;
                 case 8:
                     $nvidia_aa = 7;
                     break;
                 case 16:
                     $nvidia_aa = 8;
                     break;
             }
             if (isset($nvidia_aa)) {
                 self::set_nvidia_extension("FSAA", $nvidia_aa);
                 self::set_nvidia_extension("FSAAAppControlled", 0);
             }
         } else {
             if (phodevi::is_ati_graphics()) {
                 self::$preset_aa = phodevi_linux_parser::read_amd_pcsdb("OpenGL,AntiAliasSamples");
                 self::$preset_aa_control = phodevi_linux_parser::read_amd_pcsdb("OpenGL,AAF");
                 switch ($force_aa) {
                     case 2:
                         $ati_aa = "0x00000002";
                         break;
                     case 4:
                         $ati_aa = "0x00000004";
                         break;
                     case 8:
                         $ati_aa = "0x00000008";
                         break;
                     case 16:
                         echo "\nThe ATI fglrx driver currently does not support 16x AA! Defaulting to 8x AA!\n";
                         $ati_aa = "0x00000008";
                         break;
                 }
                 if (isset($ati_aa)) {
                     self::set_amd_pcsdb("OpenGL,AntiAliasSamples", $ati_aa);
                     self::set_amd_pcsdb("OpenGL,AAF", "0x00000000");
                 }
             }
         }
     }
     if ($force_af !== FALSE && in_array($force_af, self::$supported_af_levels)) {
         // First backup any existing override, then set the new value
         if (phodevi::is_nvidia_graphics()) {
             self::$preset_af = phodevi_parser::read_nvidia_extension("LogAniso");
             self::$preset_af_control = phodevi_parser::read_nvidia_extension("LogAnisoAppControlled");
             switch ($force_af) {
                 case 2:
                     $nvidia_af = 1;
                     break;
                 case 4:
                     $nvidia_af = 2;
                     break;
                 case 8:
                     $nvidia_af = 3;
                     break;
                 case 16:
                     $nvidia_af = 4;
                     break;
             }
             if (isset($nvidia_af)) {
                 self::set_nvidia_extension("LogAniso", $nvidia_af);
                 self::set_nvidia_extension("LogAnisoAppControlled", 0);
             }
         } else {
             if (phodevi::is_ati_graphics()) {
                 self::$preset_af = phodevi_linux_parser::read_amd_pcsdb("OpenGL,AnisoDegree");
                 switch ($force_af) {
                     case 2:
                         $ati_af = "0x00000002";
                         break;
                     case 4:
                         $ati_af = "0x00000004";
                         break;
                     case 8:
                         $ati_af = "0x00000008";
                         break;
                     case 16:
                         $ati_af = "0x00000010";
                         break;
                 }
                 if (isset($ati_af)) {
                     self::set_amd_pcsdb("OpenGL,AnisoDegree", $ati_af);
                 }
             }
         }
     }
 }