github.com/turbot/steampipe@v1.7.0-rc.0.0.20240517123944-7cef272d4458/pkg/db/db_local/service.go (about)

     1  package db_local
     2  
     3  import (
     4  	"fmt"
     5  	"log"
     6  	"os"
     7  	"strconv"
     8  	"strings"
     9  
    10  	filehelpers "github.com/turbot/go-kit/files"
    11  	"github.com/turbot/steampipe/pkg/constants"
    12  	"github.com/turbot/steampipe/pkg/filepaths"
    13  	"github.com/turbot/steampipe/pkg/utils"
    14  )
    15  
    16  // GetState checks that the database instance is running and returns its details
    17  func GetState() (*RunningDBInstanceInfo, error) {
    18  	utils.LogTime("db.GetStatus start")
    19  	defer utils.LogTime("db.GetStatus end")
    20  
    21  	info, err := loadRunningInstanceInfo()
    22  	if err != nil {
    23  		return nil, err
    24  	}
    25  
    26  	if info == nil {
    27  		log.Println("[TRACE] GetRunStatus - loadRunningInstanceInfo returned nil ")
    28  		// we do not have a info file
    29  		return nil, errorIfUnknownService()
    30  	}
    31  
    32  	pidExists, err := utils.PidExists(info.Pid)
    33  	if err != nil {
    34  		return nil, err
    35  	}
    36  	if !pidExists {
    37  		log.Printf("[TRACE] GetState - pid %v does not exist\n", info.Pid)
    38  		// nothing to do here
    39  		os.Remove(filepaths.RunningInfoFilePath())
    40  		return nil, nil
    41  	}
    42  
    43  	return info, nil
    44  }
    45  
    46  // errorIfUnknownService returns an error if it can find a `postmaster.pid` in the `INSTALL_DIR`
    47  // and the PID recorded in the found `postmaster.pid` is running - nil otherwise.
    48  //
    49  // This is because, this function is called when we cannot find the steampipe service state file.
    50  //
    51  // No steampipe state file indicates that the service is not running, so, if the service
    52  // is running without us knowing about it, then it's an irrecoverable state
    53  func errorIfUnknownService() error {
    54  	// no postmaster.pid, we are good
    55  	if !filehelpers.FileExists(filepaths.GetPostmasterPidLocation()) {
    56  		return nil
    57  	}
    58  
    59  	// read the content of the postmaster.pid file
    60  	fileContent, err := os.ReadFile(filepaths.GetPostmasterPidLocation())
    61  	if err != nil {
    62  		return err
    63  	}
    64  
    65  	// the first line contains the PID
    66  	lines := strings.FieldsFunc(string(fileContent), func(r rune) bool {
    67  		return r == '\n'
    68  	})
    69  
    70  	// make sure that there's split up content
    71  	if len(lines) == 0 {
    72  		return nil
    73  	}
    74  
    75  	// extract it
    76  	pid, err := strconv.ParseInt(lines[0], 10, 64)
    77  	if err != nil {
    78  		return err
    79  	}
    80  
    81  	// check if a process with that PID exists
    82  	exists, err := utils.PidExists(int(pid))
    83  	if err != nil {
    84  		return err
    85  	}
    86  	if exists {
    87  		// if it does, then somehow we don't know about it. Error out
    88  		return fmt.Errorf("service is running in an unknown state [PID: %d] - try killing it with %s", pid, constants.Bold("steampipe service stop --force"))
    89  	}
    90  
    91  	// the pid does not exist
    92  	// this can confuse postgres as per https://postgresapp.com/documentation/troubleshooting.html
    93  	// delete it
    94  	os.Remove(filepaths.GetPostmasterPidLocation())
    95  
    96  	// this must be a stale file left over by PG. Ignore
    97  	return nil
    98  }