load_saseul.go

package main

import (
	"bufio"
	"fmt"
	"os"
	"path/filepath"
	"strings"
	"time"

	"github.com/joho/godotenv"
)

// SASEUL_VERSION์€ SASEUL์˜ ํ˜„์žฌ ๋ฒ„์ „์„ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค.
const SASEUL_VERSION = "2.1.9.6"

// DEBUG_LOG๋Š” ๋””๋ฒ„๊ทธ ๋กœ๊ทธ ํŒŒ์ผ์˜ ๊ฒฝ๋กœ๋ฅผ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค.
const DEBUG_LOG = "debug.log"

var (
	ROOT       = filepath.Dir(filepath.Dir(os.Args[0])) // ํ”„๋กœ์ ํŠธ์˜ ๋ฃจํŠธ ๋””๋ ‰ํ„ฐ๋ฆฌ ๊ฒฝ๋กœ์ž…๋‹ˆ๋‹ค.
	SOURCE     = filepath.Dir(os.Args[0])                // ํ˜„์žฌ ์†Œ์Šค ํŒŒ์ผ์˜ ๋””๋ ‰ํ„ฐ๋ฆฌ ๊ฒฝ๋กœ์ž…๋‹ˆ๋‹ค.
	SCRIPT_BIN = filepath.Join(SOURCE, "saseul-script")  // ์Šคํฌ๋ฆฝํŠธ ์‹คํ–‰ ํŒŒ์ผ์˜ ๊ฒฝ๋กœ์ž…๋‹ˆ๋‹ค.
	SERVICE_BIN = filepath.Join(SOURCE, "saseulsvc")     // ์„œ๋น„์Šค ์‹คํ–‰ ํŒŒ์ผ์˜ ๊ฒฝ๋กœ์ž…๋‹ˆ๋‹ค.
	SASEUL_INI map[string]string                        // SASEUL ์„ค์ • ํŒŒ์ผ์—์„œ ๋กœ๋“œ๋œ ์„ค์ •๋“ค์„ ์ €์žฅํ•ฉ๋‹ˆ๋‹ค.
)

func init() {
	// SASEUL ์„ค์ • ํŒŒ์ผ์ธ saseul.ini ํŒŒ์ผ์„ ๋กœ๋“œํ•ฉ๋‹ˆ๋‹ค.
	godotenv.Load(filepath.Join(ROOT, "saseul.ini"))

	// SASEUL_INI ๋งต์— ์„ค์ • ๊ฐ’์„ ์ €์žฅํ•ฉ๋‹ˆ๋‹ค.
	SASEUL_INI = map[string]string{
		"log":             getEnv("log", DEBUG_LOG),                     // ๋กœ๊ทธ ํŒŒ์ผ ๊ฒฝ๋กœ
		"version":         getEnv("version", SASEUL_VERSION),           // ๋ฒ„์ „ ์ •๋ณด
		"data":            getEnv("data", filepath.Join(ROOT, "data")), // ๋ฐ์ดํ„ฐ ๋””๋ ‰ํ„ฐ๋ฆฌ ๊ฒฝ๋กœ
		"peers":           getEnv("peers", ""),                         // ํ”ผ์–ด ์„ค์ •
		"network_name":    getEnv("network_name", ""),                  // ๋„คํŠธ์›Œํฌ ์ด๋ฆ„ ์„ค์ •
		"system_nonce":    getEnv("system_nonce", ""),                  // ์‹œ์Šคํ…œ ๋…ผ์Šค ์„ค์ •
		"genesis_address": getEnv("genesis_address", ""),               // genesis ์ฃผ์†Œ ์„ค์ •
		"manager_addresses": getEnv("manager_addresses", ""),           // ๋งค๋‹ˆ์ € ์ฃผ์†Œ ์„ค์ •
		"ledger":          getEnv("ledger", ""),                        // ๋ถ„์‚ฐ์žฅ๋ถ€ ์„ค์ •
		"database":        getEnv("database", ""),                      // ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์„ค์ •
		"collect":         getEnv("collect", ""),                       // ๋ฐ์ดํ„ฐ ์ˆ˜์ง‘ ์„ค์ •
		"consensus":       getEnv("consensus", ""),                     // ํ•ฉ์˜ ์„ค์ •
		"mining":          getEnv("mining", ""),                        // ์ฑ„๊ตด ์„ค์ •
		"mysql_host":      getEnv("mysql_host", ""),                    // MySQL ํ˜ธ์ŠคํŠธ ์„ค์ •
		"mysql_port":      getEnv("mysql_port", ""),                    // MySQL ํฌํŠธ ์„ค์ •
		"mysql_user":      getEnv("mysql_user", ""),                    // MySQL ์‚ฌ์šฉ์ž ์„ค์ •
		"mysql_database":  getEnv("mysql_database", ""),                // MySQL ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค ์„ค์ •
		"mysql_password":  getEnv("mysql_password", ""),                // MySQL ๋น„๋ฐ€๋ฒˆํ˜ธ ์„ค์ •
		"err_file":        getEnv("err_file", DEBUG_LOG),               // ์˜ค๋ฅ˜ ๋กœ๊ทธ ํŒŒ์ผ ๊ฒฝ๋กœ
	}
}

func main() {
	// saseul.ini ํŒŒ์ผ์ด ์กด์žฌํ•˜๋Š”์ง€ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค.
	if !fileExists(filepath.Join(ROOT, "saseul.ini")) {
		fmt.Println("\nsaseul.ini file does not exist.")
		os.Exit(1)
	}

	// ๋กœ๊ทธ ํŒŒ์ผ์„ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค.
	setLogFile()

	// ์˜ˆ์ œ: ์ „์—ญ ๋ณ€์ˆ˜ ์„ค์ •
	// Config.Version = SASEUL_INI["version"]
	// Config.Data = SASEUL_INI["data"]

	// ์˜ค๋ฅ˜ ์ฒ˜๋ฆฌ ํ•ธ๋“ค๋Ÿฌ๋ฅผ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค.
	setErrorHandler()
	setFatalErrorHandler()

	// ๋ฉ”์ธ ๋กœ์ง์˜ ๋‚˜๋จธ์ง€ ๋ถ€๋ถ„์„ ์—ฌ๊ธฐ์— ์ž‘์„ฑํ•ฉ๋‹ˆ๋‹ค.
}

// getEnv ํ•จ์ˆ˜๋Š” ํ™˜๊ฒฝ ๋ณ€์ˆ˜์—์„œ ๊ฐ’์„ ๊ฐ€์ ธ์˜ค๊ฑฐ๋‚˜ ๊ธฐ๋ณธ ๊ฐ’์„ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.
func getEnv(key, defaultValue string) string {
	if value, exists := os.LookupEnv(key); exists {
		return value
	}
	return defaultValue
}

// fileExists ํ•จ์ˆ˜๋Š” ํŒŒ์ผ์ด ์กด์žฌํ•˜๋Š”์ง€ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค.
func fileExists(filename string) bool {
	info, err := os.Stat(filename)
	return err == nil && !info.IsDir()
}

// setLogFile ํ•จ์ˆ˜๋Š” ๋กœ๊ทธ ํŒŒ์ผ์„ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค.
func setLogFile() {
	logFile := SASEUL_INI["log"]
	// ๋กœ๊ทธ ํŒŒ์ผ์ด ์กด์žฌํ•˜์ง€ ์•Š์œผ๋ฉด ๊ธฐ๋ณธ ๋””๋ฒ„๊ทธ ๋กœ๊ทธ ํŒŒ์ผ์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.
	if !fileExists(filepath.Dir(logFile)) {
		logFile = DEBUG_LOG
	}
	LoggerSetLogFile(logFile)
}

// setErrorHandler ํ•จ์ˆ˜๋Š” ์ผ๋ฐ˜์ ์ธ ์˜ค๋ฅ˜ ์ฒ˜๋ฆฌ ํ•ธ๋“ค๋Ÿฌ๋ฅผ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค.
func setErrorHandler() {
	defer func() {
		if err := recover(); err != nil {
			handleError(err)
		}
	}()
}

// setFatalErrorHandler ํ•จ์ˆ˜๋Š” ์น˜๋ช…์ ์ธ ์˜ค๋ฅ˜ ์ฒ˜๋ฆฌ ํ•ธ๋“ค๋Ÿฌ๋ฅผ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค.
func setFatalErrorHandler() {
	defer func() {
		if r := recover(); r != nil {
			handleFatalError(r)
		}
	}()
}

// handleError ํ•จ์ˆ˜๋Š” ๋ฐœ์ƒํ•œ ์ผ๋ฐ˜์ ์ธ ์˜ค๋ฅ˜๋ฅผ ์ฒ˜๋ฆฌํ•˜๊ณ  ๋กœ๊ทธ์— ๊ธฐ๋กํ•ฉ๋‹ˆ๋‹ค.
func handleError(err interface{}) {
	msg := fmt.Sprintf("\n[%s] [ERROR] %v\n\n", time.Now().Format("2006-01-02 15:04:05"), err)
	writeToFile(SASEUL_INI["err_file"], msg)
}

// handleFatalError ํ•จ์ˆ˜๋Š” ๋ฐœ์ƒํ•œ ์น˜๋ช…์ ์ธ ์˜ค๋ฅ˜๋ฅผ ์ฒ˜๋ฆฌํ•˜๊ณ  ๋กœ๊ทธ์— ๊ธฐ๋กํ•ฉ๋‹ˆ๋‹ค.
func handleFatalError(err interface{}) {
	msg := fmt.Sprintf("[%s] [Fatal Error] %v\n\n", time.Now().Format("2006-01-02 15:04:05"), err)
	writeToFile(SASEUL_INI["err_file"], msg)
}

// writeToFile ํ•จ์ˆ˜๋Š” ์ง€์ •๋œ ํŒŒ์ผ์— ๋ฐ์ดํ„ฐ๋ฅผ ์”๋‹ˆ๋‹ค.
func writeToFile(filename, data string) {
	f, err := os.OpenFile(filename, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
	if err != nil {
		fmt.Println("Error opening file:", err)
		return
	}
	defer f.Close()

	writer := bufio.NewWriter(f)
	_, err = writer.WriteString(data)
	if err != nil {
		fmt.Println("Error writing to file:", err)
	}
	writer.Flush()
}

// LoggerSetLogFile ํ•จ์ˆ˜๋Š” ๋กœ๊ฑฐ์˜ ๋กœ๊ทธ ํŒŒ์ผ์„ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค.
func LoggerSetLogFile(logFile string) {
	// ๋กœ๊ฑฐ์˜ ๋กœ๊ทธ ํŒŒ์ผ ์„ค์ • ๋กœ์ง์„ ์—ฌ๊ธฐ์— ๊ตฌํ˜„ํ•ฉ๋‹ˆ๋‹ค.
}

Last updated