@@ -1241,6 +1241,96 @@ static inline bool is_report_browser(void *timer)
12411241 return timer == NULL ;
12421242}
12431243
1244+ /*
1245+ * Only runtime switching of perf data file will make "input_name" point
1246+ * to a malloced buffer. So add "is_input_name_malloced" flag to decide
1247+ * whether we need to call free() for current "input_name" during the switch.
1248+ */
1249+ static bool is_input_name_malloced = false;
1250+
1251+ static int switch_data_file (void )
1252+ {
1253+ char * pwd , * options [32 ], * abs_path [32 ], * tmp ;
1254+ DIR * pwd_dir ;
1255+ int nr_options = 0 , choice = -1 , ret = -1 ;
1256+ struct dirent * dent ;
1257+
1258+ pwd = getenv ("PWD" );
1259+ if (!pwd )
1260+ return ret ;
1261+
1262+ pwd_dir = opendir (pwd );
1263+ if (!pwd_dir )
1264+ return ret ;
1265+
1266+ memset (options , 0 , sizeof (options ));
1267+ memset (options , 0 , sizeof (abs_path ));
1268+
1269+ while ((dent = readdir (pwd_dir ))) {
1270+ char path [PATH_MAX ];
1271+ u64 magic ;
1272+ char * name = dent -> d_name ;
1273+ FILE * file ;
1274+
1275+ if (!(dent -> d_type == DT_REG ))
1276+ continue ;
1277+
1278+ snprintf (path , sizeof (path ), "%s/%s" , pwd , name );
1279+
1280+ file = fopen (path , "r" );
1281+ if (!file )
1282+ continue ;
1283+
1284+ if (fread (& magic , 1 , 8 , file ) < 8 )
1285+ goto close_file_and_continue ;
1286+
1287+ if (is_perf_magic (magic )) {
1288+ options [nr_options ] = strdup (name );
1289+ if (!options [nr_options ])
1290+ goto close_file_and_continue ;
1291+
1292+ abs_path [nr_options ] = strdup (path );
1293+ if (!abs_path [nr_options ]) {
1294+ free (options [nr_options ]);
1295+ ui__warning ("Can't search all data files due to memory shortage.\n" );
1296+ fclose (file );
1297+ break ;
1298+ }
1299+
1300+ nr_options ++ ;
1301+ }
1302+
1303+ close_file_and_continue :
1304+ fclose (file );
1305+ if (nr_options >= 32 ) {
1306+ ui__warning ("Too many perf data files in PWD!\n"
1307+ "Only the first 32 files will be listed.\n" );
1308+ break ;
1309+ }
1310+ }
1311+ closedir (pwd_dir );
1312+
1313+ if (nr_options ) {
1314+ choice = ui__popup_menu (nr_options , options );
1315+ if (choice < nr_options && choice >= 0 ) {
1316+ tmp = strdup (abs_path [choice ]);
1317+ if (tmp ) {
1318+ if (is_input_name_malloced )
1319+ free ((void * )input_name );
1320+ input_name = tmp ;
1321+ is_input_name_malloced = true;
1322+ ret = 0 ;
1323+ } else
1324+ ui__warning ("Data switch failed due to memory shortage!\n" );
1325+ }
1326+ }
1327+
1328+ free_popup_options (options , nr_options );
1329+ free_popup_options (abs_path , nr_options );
1330+ return ret ;
1331+ }
1332+
1333+
12441334static int perf_evsel__hists_browse (struct perf_evsel * evsel , int nr_events ,
12451335 const char * helpline , const char * ev_name ,
12461336 bool left_exits ,
@@ -1275,7 +1365,8 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
12751365 int choice = 0 ,
12761366 annotate = -2 , zoom_dso = -2 , zoom_thread = -2 ,
12771367 annotate_f = -2 , annotate_t = -2 , browse_map = -2 ;
1278- int scripts_comm = -2 , scripts_symbol = -2 , scripts_all = -2 ;
1368+ int scripts_comm = -2 , scripts_symbol = -2 ,
1369+ scripts_all = -2 , switch_data = -2 ;
12791370
12801371 nr_options = 0 ;
12811372
@@ -1332,6 +1423,10 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
13321423 if (is_report_browser (hbt ))
13331424 goto do_scripts ;
13341425 continue ;
1426+ case 's' :
1427+ if (is_report_browser (hbt ))
1428+ goto do_data_switch ;
1429+ continue ;
13351430 case K_F1 :
13361431 case 'h' :
13371432 case '?' :
@@ -1351,6 +1446,7 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
13511446 "d Zoom into current DSO\n"
13521447 "t Zoom into current Thread\n"
13531448 "r Run available scripts('perf report' only)\n"
1449+ "s Switch to another data file in PWD ('perf report' only)\n"
13541450 "P Print histograms to perf.hist.N\n"
13551451 "V Verbose (DSO names in callchains, etc)\n"
13561452 "/ Filter symbol by name" );
@@ -1458,6 +1554,9 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
14581554 if (asprintf (& options [nr_options ], "Run scripts for all samples" ) > 0 )
14591555 scripts_all = nr_options ++ ;
14601556
1557+ if (is_report_browser (hbt ) && asprintf (& options [nr_options ],
1558+ "Switch to another data file in PWD" ) > 0 )
1559+ switch_data = nr_options ++ ;
14611560add_exit_option :
14621561 options [nr_options ++ ] = (char * )"Exit" ;
14631562retry_popup_menu :
@@ -1568,6 +1667,16 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
15681667
15691668 script_browse (script_opt );
15701669 }
1670+ /* Switch to another data file */
1671+ else if (choice == switch_data ) {
1672+ do_data_switch :
1673+ if (!switch_data_file ()) {
1674+ key = K_SWITCH_INPUT_DATA ;
1675+ break ;
1676+ } else
1677+ ui__warning ("Won't switch the data files due to\n"
1678+ "no valid data file get selected!\n" );
1679+ }
15711680 }
15721681out_free_stack :
15731682 pstack__delete (fstack );
@@ -1694,6 +1803,7 @@ static int perf_evsel_menu__run(struct perf_evsel_menu *menu,
16941803 "Do you really want to exit?" ))
16951804 continue ;
16961805 /* Fall thru */
1806+ case K_SWITCH_INPUT_DATA :
16971807 case 'q' :
16981808 case CTRL ('c' ):
16991809 goto out ;
0 commit comments