github.com/gogf/gf@v1.16.9/os/gproc/gproc_comm.go (about)

     1  // Copyright GoFrame Author(https://goframe.org). All Rights Reserved.
     2  //
     3  // This Source Code Form is subject to the terms of the MIT License.
     4  // If a copy of the MIT was not distributed with this file,
     5  // You can obtain one at https://github.com/gogf/gf.
     6  
     7  package gproc
     8  
     9  import (
    10  	"context"
    11  	"fmt"
    12  	"github.com/gogf/gf/container/gmap"
    13  	"github.com/gogf/gf/errors/gcode"
    14  	"github.com/gogf/gf/errors/gerror"
    15  	"github.com/gogf/gf/internal/intlog"
    16  	"github.com/gogf/gf/net/gtcp"
    17  	"github.com/gogf/gf/os/gfile"
    18  	"github.com/gogf/gf/util/gconv"
    19  )
    20  
    21  // MsgRequest is the request structure for process communication.
    22  type MsgRequest struct {
    23  	SendPid int    // Sender PID.
    24  	RecvPid int    // Receiver PID.
    25  	Group   string // Message group name.
    26  	Data    []byte // Request data.
    27  }
    28  
    29  // MsgResponse is the response structure for process communication.
    30  type MsgResponse struct {
    31  	Code    int    // 1: OK; Other: Error.
    32  	Message string // Response message.
    33  	Data    []byte // Response data.
    34  }
    35  
    36  const (
    37  	defaultFolderNameForProcComm = "gf_pid_port_mapping" // Default folder name for storing pid to port mapping files.
    38  	defaultGroupNameForProcComm  = ""                    // Default group name.
    39  	defaultTcpPortForProcComm    = 10000                 // Starting port number for receiver listening.
    40  	maxLengthForProcMsgQueue     = 10000                 // Max size for each message queue of the group.
    41  )
    42  
    43  var (
    44  	// commReceiveQueues is the group name to queue map for storing received data.
    45  	// The value of the map is type of *gqueue.Queue.
    46  	commReceiveQueues = gmap.NewStrAnyMap(true)
    47  
    48  	// commPidFolderPath specifies the folder path storing pid to port mapping files.
    49  	commPidFolderPath string
    50  )
    51  
    52  func init() {
    53  	availablePaths := []string{
    54  		"/var/tmp",
    55  		"/var/run",
    56  	}
    57  	if homePath, _ := gfile.Home(); homePath != "" {
    58  		availablePaths = append(availablePaths, gfile.Join(homePath, ".config"))
    59  	}
    60  	availablePaths = append(availablePaths, gfile.TempDir())
    61  	for _, availablePath := range availablePaths {
    62  		checkPath := gfile.Join(availablePath, defaultFolderNameForProcComm)
    63  		if !gfile.Exists(checkPath) && gfile.Mkdir(checkPath) != nil {
    64  			continue
    65  		}
    66  		if gfile.IsWritable(checkPath) {
    67  			commPidFolderPath = checkPath
    68  			break
    69  		}
    70  	}
    71  	if commPidFolderPath == "" {
    72  		intlog.Errorf(
    73  			context.TODO(),
    74  			`cannot find available folder for storing pid to port mapping files in paths: %+v, process communication feature will fail`,
    75  			availablePaths,
    76  		)
    77  	}
    78  
    79  }
    80  
    81  // getConnByPid creates and returns a TCP connection for specified pid.
    82  func getConnByPid(pid int) (*gtcp.PoolConn, error) {
    83  	port := getPortByPid(pid)
    84  	if port > 0 {
    85  		if conn, err := gtcp.NewPoolConn(fmt.Sprintf("127.0.0.1:%d", port)); err == nil {
    86  			return conn, nil
    87  		} else {
    88  			return nil, err
    89  		}
    90  	}
    91  	return nil, gerror.NewCodef(gcode.CodeOperationFailed, "could not find port for pid: %d", pid)
    92  }
    93  
    94  // getPortByPid returns the listening port for specified pid.
    95  // It returns 0 if no port found for the specified pid.
    96  func getPortByPid(pid int) int {
    97  	return gconv.Int(gfile.GetContentsWithCache(getCommFilePath(pid)))
    98  }
    99  
   100  // getCommFilePath returns the pid to port mapping file path for given pid.
   101  func getCommFilePath(pid int) string {
   102  	return gfile.Join(commPidFolderPath, gconv.String(pid))
   103  }