Search/init.go
partisan f769f70ce7 wip
2024-07-05 03:08:35 +02:00

201 lines
4.1 KiB
Go

package main
import (
"bufio"
"crypto/rand"
"encoding/base64"
"encoding/json"
"fmt"
"log"
"os"
"strconv"
"strings"
"sync"
"github.com/fsnotify/fsnotify"
)
// Configuration structure
type Config struct {
Port int
AuthCode string
Peers []string
OpenSearch OpenSearchConfig
}
type OpenSearchConfig struct {
Domain string
}
// Default configuration values
var defaultConfig = Config{
Port: 5000,
OpenSearch: OpenSearchConfig{
Domain: "localhost",
},
}
const configFilePath = "config.json"
var config Config
var configLock sync.RWMutex
func main() {
err := initConfig()
if err != nil {
fmt.Println("Error during initialization:", err)
return
}
loadNodeConfig()
go startFileWatcher()
go checkMasterHeartbeat()
if config.AuthCode == "" {
config.AuthCode = generateStrongRandomString(64)
fmt.Printf("Generated connection code: %s\n", config.AuthCode)
saveConfig(config)
}
if len(config.Peers) > 0 {
go startNodeClient(config.Peers)
startElection()
}
runServer()
}
func initConfig() error {
if _, err := os.Stat(configFilePath); os.IsNotExist(err) {
return createConfig()
}
fmt.Println("Configuration file already exists.")
config = loadConfig()
return nil
}
func createConfig() error {
reader := bufio.NewReader(os.Stdin)
fmt.Println("Configuration file not found.")
fmt.Print("Do you want to use default values? (yes/no): ")
useDefaults, _ := reader.ReadString('\n')
config := defaultConfig
if useDefaults != "yes\n" {
fmt.Print("Enter port (default 5000): ")
portStr, _ := reader.ReadString('\n')
if portStr != "\n" {
port, err := strconv.Atoi(portStr[:len(portStr)-1])
if err != nil {
return err
}
config.Port = port
}
fmt.Print("Enter your domain address (e.g., domain.com): ")
domain, _ := reader.ReadString('\n')
if domain != "\n" {
config.OpenSearch.Domain = domain[:len(domain)-1]
}
fmt.Print("Do you want to connect to other nodes? (yes/no): ")
connectNodes, _ := reader.ReadString('\n')
if strings.TrimSpace(connectNodes) == "yes" {
fmt.Println("Enter peer addresses (comma separated, e.g., http://localhost:5000,http://localhost:5001): ")
peersStr, _ := reader.ReadString('\n')
if peersStr != "\n" {
config.Peers = strings.Split(strings.TrimSpace(peersStr), ",")
}
}
}
if config.AuthCode == "" {
config.AuthCode = generateStrongRandomString(64)
fmt.Printf("Generated connection code: %s\n", config.AuthCode)
}
saveConfig(config)
return nil
}
func saveConfig(config Config) {
file, err := os.Create(configFilePath)
if err != nil {
fmt.Println("Error creating config file:", err)
return
}
defer file.Close()
configData, err := json.MarshalIndent(config, "", " ")
if err != nil {
fmt.Println("Error marshalling config data:", err)
return
}
_, err = file.Write(configData)
if err != nil {
fmt.Println("Error writing to config file:", err)
}
}
func loadConfig() Config {
configFile, err := os.Open(configFilePath)
if err != nil {
log.Fatalf("Error opening config file: %v", err)
}
defer configFile.Close()
var config Config
if err := json.NewDecoder(configFile).Decode(&config); err != nil {
log.Fatalf("Error decoding config file: %v", err)
}
return config
}
func generateStrongRandomString(length int) string {
bytes := make([]byte, length)
_, err := rand.Read(bytes)
if err != nil {
log.Fatalf("Error generating random string: %v", err)
}
return base64.URLEncoding.EncodeToString(bytes)[:length]
}
func startFileWatcher() {
watcher, err := fsnotify.NewWatcher()
if err != nil {
log.Fatal(err)
}
go func() {
defer watcher.Close()
for {
select {
case event, ok := <-watcher.Events:
if !ok {
return
}
if event.Op&fsnotify.Write == fsnotify.Write {
log.Println("Modified file:", event.Name)
configLock.Lock()
config = loadConfig()
configLock.Unlock()
// Perform your logic here to handle the changes in the config file
}
case err, ok := <-watcher.Errors:
if !ok {
return
}
log.Println("Error:", err)
}
}
}()
err = watcher.Add(configFilePath)
if err != nil {
log.Fatal(err)
}
}