-
Notifications
You must be signed in to change notification settings - Fork 8
/
main.go
150 lines (132 loc) · 4.38 KB
/
main.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
package main
import (
"errors"
"flag"
"fmt"
"log"
"os"
"path"
"runtime"
"strings"
"time"
)
var (
port int
version bool
maxHandleCount int
host string
uiDir string
enableInternalApis bool // internal APIs are not exposed to public
enableSSL bool
certFilePath string
keyFilePath string
logToFile bool // logs will be written to file when true
varnamdConfig *config // config instance used across the application
startedAt time.Time
downloadEnabledSchemes string // comma separated list of scheme identifier for which download will be performed
syncIntervalInSecs int
upstreamURL string
syncDispatcherRunning bool
)
// varnamd configurations
// this is populated from various command line flags
type config struct {
upstream string
schemesToDownload map[string]bool
syncIntervalInSecs time.Duration
}
func initConfig() *config {
toDownload := make(map[string]bool)
schemes := strings.Split(downloadEnabledSchemes, ",")
for _, scheme := range schemes {
s := strings.TrimSpace(scheme)
if s != "" {
if !isValidSchemeIdentifier(s) {
panic(fmt.Sprintf("%s is not a valid libvarnam supported scheme", s))
}
toDownload[s] = true
}
}
return &config{upstream: upstreamURL, schemesToDownload: toDownload,
syncIntervalInSecs: time.Duration(syncIntervalInSecs)}
}
func (c *config) setDownloadStatus(langCode string, status bool) error {
if !isValidSchemeIdentifier(langCode) {
return errors.New(fmt.Sprintf("%s is not a valid libvarnam supported scheme", langCode))
}
c.schemesToDownload[langCode] = status
if status {
// when varnamd was started without any langcodes to sync, the dispatcher won't be running
// in that case, we need to start the dispatcher since we have a new lang code to download now
startSyncDispatcher()
}
return nil
}
func getConfigDir() string {
if runtime.GOOS == "windows" {
return path.Join(os.Getenv("localappdata"), ".varnamd")
} else {
return path.Join(os.Getenv("HOME"), ".varnamd")
}
}
func getLogsDir() string {
d := getConfigDir()
logsDir := path.Join(d, "logs")
err := os.MkdirAll(logsDir, 0777)
if err != nil {
panic(err)
}
return logsDir
}
func redirectLogToFile() {
year, month, day := time.Now().Date()
logfile := path.Join(getLogsDir(), fmt.Sprintf("%d-%d-%d.log", year, month, day))
f, err := os.OpenFile(logfile, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)
if err != nil {
panic(err)
}
log.SetOutput(f)
}
func init() {
flag.IntVar(&port, "p", 8080, "Run daemon in specified port")
flag.IntVar(&maxHandleCount, "max-handle-count", 10, "Maximum number of handles can be opened for each language")
flag.StringVar(&host, "host", "", "Host for the varnam daemon server")
flag.StringVar(&uiDir, "ui", "", "UI directory path")
flag.BoolVar(&enableInternalApis, "enable-internal-apis", false, "Enable internal APIs")
flag.BoolVar(&enableSSL, "enable-ssl", false, "Enables SSL")
flag.StringVar(&certFilePath, "cert-file-path", "", "Certificate file path")
flag.StringVar(&keyFilePath, "key-file-path", "", "Key file path")
flag.StringVar(&upstreamURL, "upstream", "https://api.varnamproject.com", "Provide an upstream server")
flag.StringVar(&downloadEnabledSchemes, "enable-download", "", "Comma separated language identifier for which varnamd will download words from upstream")
flag.IntVar(&syncIntervalInSecs, "sync-interval", 30, "Download interval in seconds")
flag.BoolVar(&logToFile, "log-to-file", true, "If true, logs will be written to a file")
flag.BoolVar(&version, "version", false, "Print the version and exit")
}
func syncRequired() bool {
return len(varnamdConfig.schemesToDownload) > 0
}
// Starts the sync process only if it is not running
func startSyncDispatcher() {
if syncRequired() && !syncDispatcherRunning {
sync := newSyncDispatcher(varnamdConfig.syncIntervalInSecs * time.Second)
sync.start()
sync.runNow() // run one round of sync immediatly rather than waiting for the next interval to occur
syncDispatcherRunning = true
}
}
func main() {
runtime.GOMAXPROCS(runtime.NumCPU())
flag.Parse()
varnamdConfig = initConfig()
startedAt = time.Now()
if version {
fmt.Println(varnamdVersion)
os.Exit(0)
}
if logToFile {
redirectLogToFile()
}
log.Printf("varnamd %s", varnamdVersion)
startSyncDispatcher()
startDaemon()
}