浏览代码

Breaks profileProtoReader into multiple functions

Wade Simba Khadder 8 年前
父节点
当前提交
a27767de2f
共有 1 个文件被更改,包括 20 次插入32 次删除
  1. 20
    32
      internal/driver/fetch.go

+ 20
- 32
internal/driver/fetch.go 查看文件

@@ -358,8 +358,15 @@ func fetch(source string, duration, timeout time.Duration, ui plugin.UI) (p *pro
358 358
 		}
359 359
 		f, err = fetchURL(sourceURL, timeout)
360 360
 		src = sourceURL
361
+	} else if isPerf, isPerfErr := isPerfFile(source); isPerf {
362
+		// Since the if statement is a new scope, if isPerfErr is named
363
+		// err, it shadows the err in the return, and does not compile.
364
+		if isPerfErr != nil {
365
+			return nil, "", isPerfErr
366
+		}
367
+		f, err = convertPerfData(source, ui)
361 368
 	} else {
362
-		f, err = profileProtoReader(source, ui)
369
+		f, err = os.Open(source)
363 370
 	}
364 371
 	if err == nil {
365 372
 		defer f.Close()
@@ -381,62 +388,43 @@ func fetchURL(source string, timeout time.Duration) (io.ReadCloser, error) {
381 388
 	return resp.Body, nil
382 389
 }
383 390
 
384
-// profileProtoReader takes a path, and using heuristics, will try to convert
385
-// the file to profile.proto format. It returns a ReadCloser to the
386
-// profile.proto data; however, if the file contents were unknown or conversion
387
-// failed, it may still not be a valid profile.proto.
388
-func profileProtoReader(path string, ui plugin.UI) (io.ReadCloser, error) {
391
+// isPerfFile checks if a file is in perf.data format.
392
+func isPerfFile(path string) (bool, error) {
389 393
 	sourceFile, openErr := os.Open(path)
390 394
 	if openErr != nil {
391
-		return nil, openErr
395
+		return false, openErr
392 396
 	}
397
+	defer sourceFile.Close()
393 398
 
394 399
 	// If the file is the output of a perf record command, it should begin
395 400
 	// with the string PERFILE2.
396 401
 	perfHeader := []byte("PERFILE2")
397 402
 	actualHeader := make([]byte, len(perfHeader))
398
-	if _, readErr := sourceFile.Read(actualHeader); readErr == io.EOF {
399
-		_, seekErr := sourceFile.Seek(0, 0)
400
-		if seekErr != nil {
401
-			return nil, seekErr
402
-		}
403
-	} else if readErr != nil {
404
-		return nil, readErr
405
-	}
406
-	if bytes.Equal(actualHeader, perfHeader) {
407
-		sourceFile.Close()
408
-		profileFilePath, convertErr := convertPerfData(path, ui)
409
-		if convertErr != nil {
410
-			return nil, convertErr
411
-		}
412
-		profileFile, openErr := os.Open(profileFilePath)
413
-		if openErr != nil {
414
-			return nil, openErr
415
-		}
416
-		return profileFile, nil
403
+	if _, readErr := sourceFile.Read(actualHeader); readErr != nil {
404
+		return false, readErr
417 405
 	}
418
-	return sourceFile, nil
406
+	return bytes.Equal(actualHeader, perfHeader), nil
419 407
 }
420 408
 
421 409
 // convertPerfData converts the file at path which should be in perf.data format
422
-// using the perf_to_profile tool and returns the path to a file containing the
410
+// using the perf_to_profile tool and returns the file containing the
423 411
 // profile.proto formatted data.
424
-func convertPerfData(perfPath string, ui plugin.UI) (string, error) {
412
+func convertPerfData(perfPath string, ui plugin.UI) (*os.File, error) {
425 413
 	ui.Print(fmt.Sprintf(
426 414
 		"Converting %s to a profile.proto... (May take a few minutes)",
427 415
 		perfPath))
428 416
 	profilePath, err := newTempFilePath("/tmp", "pprof_", ".pb.gz")
429 417
 	if err != nil {
430
-		return "", err
418
+		return nil, err
431 419
 	}
432 420
 	cmd := exec.Command("perf_to_profile", perfPath, profilePath)
433 421
 	// If perf_to_profile failed before generating the file, this defer
434 422
 	// is just a no-op.
435 423
 	deferDeleteTempFile(profilePath)
436 424
 	if err := cmd.Run(); err != nil {
437
-		return "", err
425
+		return nil, err
438 426
 	}
439
-	return profilePath, nil
427
+	return os.Open(profilePath)
440 428
 }
441 429
 
442 430
 // adjustURL validates if a profile source is a URL and returns an