本文整理匯總了Golang中github.com/HouzuoGuo/tiedot/tdlog.Noticef函數的典型用法代碼示例。如果您正苦於以下問題:Golang Noticef函數的具體用法?Golang Noticef怎麽用?Golang Noticef使用的例子?那麽, 這裏精選的函數代碼示例或許可以為您提供幫助。
在下文中一共展示了Noticef函數的15個代碼示例,這些例子默認根據受歡迎程度排序。您可以為喜歡或者感覺有用的代碼點讚,您的評價將有助於係統推薦出更棒的Golang代碼示例。
示例1: linuxPerfAdvice
// Read Linux system VM parameters and print performance configuration advice when necessary.
func linuxPerfAdvice() {
readFileIntContent := func(filePath string) (contentInt int, err error) {
content, err := ioutil.ReadFile(filePath)
if err != nil {
return
}
contentInt, err = strconv.Atoi(strings.TrimSpace(string(content)))
return
}
swappiness, err := readFileIntContent("/proc/sys/vm/swappiness")
if err != nil {
tdlog.Notice("Non-fatal - unable to offer performance advice based on vm.swappiness.")
} else if swappiness > 30 {
tdlog.Noticef("System vm.swappiness is very high (%d), for optimium performance please lower it below 30.", swappiness)
}
dirtyRatio, err := readFileIntContent("/proc/sys/vm/dirty_ratio")
if err != nil {
tdlog.Notice("Non-fatal - unable to offer performance advice based on vm.dirty_ratio.")
} else if dirtyRatio < 50 {
tdlog.Noticef("System vm.dirty_ratio is very low (%d), for optimium performance please raise it above 50.", dirtyRatio)
}
dirtyBGRatio, err := readFileIntContent("/proc/sys/vm/dirty_background_ratio")
if err != nil {
tdlog.Notice("Non-fatal - unable to offer performance advice based on vm.dirty_background_ratio.")
} else if dirtyBGRatio > 20 {
tdlog.Noticef("System vm.dirty_background_ratio is very high (%d), for optimium performance please lower it below 20.", dirtyBGRatio)
}
}
示例2: Start
func Start(dir string, port int, tlsCrt, tlsKey, jwtPubKey, jwtPrivateKey string) {
var err error
HttpDB, err = db.OpenDB(dir)
if err != nil {
panic(err)
}
// These endpoints are always available and do not require JWT auth
http.HandleFunc("/", Welcome)
http.HandleFunc("/version", Version)
http.HandleFunc("/memstats", MemStats)
if jwtPrivateKey != "" {
// JWT support
ServeJWTEnabledEndpoints(jwtPubKey, jwtPrivateKey)
} else {
// No JWT
ServeEndpoints()
}
if tlsCrt != "" {
tdlog.Noticef("Will listen on all interfaces (HTTPS), port %d.", port)
if err := http.ListenAndServeTLS(fmt.Sprintf(":%d", port), tlsCrt, tlsKey, nil); err != nil {
tdlog.Panicf("Failed to start HTTPS service - %s", err)
}
} else {
tdlog.Noticef("Will listen on all interfaces (HTTP), port %d.", port)
http.ListenAndServe(fmt.Sprintf(":%d", port), nil)
}
}
示例3: RegisterWebCp
func RegisterWebCp() {
if WebCp == "" || WebCp == "none" || WebCp == "no" || WebCp == "false" {
tdlog.Noticef("Web control panel is disabled on your request")
return
}
http.HandleFunc("/"+WebCp, handleWebCp)
http.HandleFunc("/favicon.ico", func(w http.ResponseWriter, r *http.Request) {
w.Write(rice.MustFindBox("static/img").MustBytes("favicon.ico"))
})
http.Handle("/"+WebCp+"/css/", http.StripPrefix("/"+WebCp+"/css/", http.FileServer(rice.MustFindBox("static/css").HTTPBox())))
http.Handle("/"+WebCp+"/js/", http.StripPrefix("/"+WebCp+"/js/", http.FileServer(rice.MustFindBox("static/js").HTTPBox())))
tdlog.Noticef("Web control panel is accessible at /%s", WebCp)
}
示例4: Dump
// Copy this database into destination directory (for backup).
func (db *DB) Dump(dest string) error {
db.schemaLock.Lock()
defer db.schemaLock.Unlock()
for _, col := range db.cols {
if err := col.sync(); err != nil {
return err
}
}
cpFun := func(currPath string, info os.FileInfo, err error) error {
if err != nil {
return err
}
if info.IsDir() {
relPath, err := filepath.Rel(db.path, currPath)
if err != nil {
return err
}
destDir := path.Join(dest, relPath)
if err := os.MkdirAll(destDir, 0770); err != nil {
return err
}
tdlog.Noticef("Dump: created directory %s", destDir)
} else {
src, err := os.Open(currPath)
if err != nil {
return err
}
relPath, err := filepath.Rel(db.path, currPath)
if err != nil {
return err
}
destPath := path.Join(dest, relPath)
if _, fileExists := os.Open(destPath); fileExists == nil {
return fmt.Errorf("Destination file %s already exists", destPath)
}
destFile, err := os.Create(destPath)
if err != nil {
return err
}
written, err := io.Copy(destFile, src)
if err != nil {
return err
}
tdlog.Noticef("Dump: copied file %s, size is %d", destPath, written)
}
return nil
}
return filepath.Walk(db.path, cpFun)
}
示例5: ServeAuthTokenEndpoints
func ServeAuthTokenEndpoints(token string) {
authToken = token
// collection management (stop-the-world)
http.HandleFunc("/create", authWrap(Create))
http.HandleFunc("/rename", authWrap(Rename))
http.HandleFunc("/drop", authWrap(Drop))
http.HandleFunc("/all", authWrap(All))
http.HandleFunc("/scrub", authWrap(Scrub))
http.HandleFunc("/sync", authWrap(Sync))
// query
http.HandleFunc("/query", authWrap(Query))
http.HandleFunc("/count", authWrap(Count))
// document management
http.HandleFunc("/insert", authWrap(Insert))
http.HandleFunc("/get", authWrap(Get))
http.HandleFunc("/getpage", authWrap(GetPage))
http.HandleFunc("/update", authWrap(Update))
http.HandleFunc("/delete", authWrap(Delete))
http.HandleFunc("/approxdoccount", authWrap(ApproxDocCount))
// index management (stop-the-world)
http.HandleFunc("/index", authWrap(Index))
http.HandleFunc("/indexes", authWrap(Indexes))
http.HandleFunc("/unindex", authWrap(Unindex))
// misc
http.HandleFunc("/shutdown", authWrap(Shutdown))
http.HandleFunc("/dump", authWrap(Dump))
tdlog.Noticef("API endpoints now require the 'Authorization: token' header.")
}
示例6: Delete
// Delete a document.
func (col *Col) Delete(id int) error {
col.db.schemaLock.RLock()
part := col.parts[id%col.db.numParts]
// Place lock, read back original document and delete document
part.DataLock.Lock()
originalB, err := part.Read(id)
if err != nil {
part.DataLock.Unlock()
col.db.schemaLock.RUnlock()
return err
}
err = part.Delete(id)
part.DataLock.Unlock()
if err != nil {
col.db.schemaLock.RUnlock()
return err
}
// Done with the collection data, next is to remove indexed values
var original map[string]interface{}
err = json.Unmarshal(originalB, &original)
if err == nil {
part.LockUpdate(id)
col.unindexDoc(id, original)
part.UnlockUpdate(id)
} else {
tdlog.Noticef("Will not attempt to unindex document %d during delete", id)
}
col.db.schemaLock.RUnlock()
return nil
}
示例7: Start
func Start(db *db.DB, port int) {
HttpDB = db
// collection management (stop-the-world)
http.HandleFunc("/create", Create)
http.HandleFunc("/rename", Rename)
http.HandleFunc("/drop", Drop)
http.HandleFunc("/all", All)
http.HandleFunc("/scrub", Scrub)
http.HandleFunc("/sync", Sync)
// query
http.HandleFunc("/query", Query)
http.HandleFunc("/count", Count)
// document management
http.HandleFunc("/insert", Insert)
http.HandleFunc("/get", Get)
http.HandleFunc("/update", Update)
http.HandleFunc("/delete", Delete)
// index management (stop-the-world)
http.HandleFunc("/index", Index)
http.HandleFunc("/indexes", Indexes)
http.HandleFunc("/unindex", Unindex)
// misc (stop-the-world)
http.HandleFunc("/shutdown", Shutdown)
http.HandleFunc("/dump", Dump)
// misc
http.HandleFunc("/version", Version)
http.HandleFunc("/memstats", MemStats)
tdlog.Noticef("Will listen on all interfaces, port %d", port)
http.ListenAndServe(fmt.Sprintf(":%d", port), nil)
}
示例8: Delete
// Delete a document.
func (col *Col) Delete(id int) error {
part := col.parts[id%col.db.numParts]
part.Lock.Lock()
// Place lock, read back original document and delete document
if err := part.LockUpdate(id); err != nil {
part.Lock.Unlock()
return fmt.Errorf("Document %d is locked for update, please try again later", id)
}
originalB, err := part.Read(id)
if err != nil {
part.UnlockUpdate(id)
part.Lock.Unlock()
return fmt.Errorf("Cannot delete %d: %v", id, err)
}
var original map[string]interface{}
if err = json.Unmarshal(originalB, &original); err != nil {
tdlog.Noticef("Will not attempt to unindex document %d during delete", id)
}
if err = part.Delete(id); err != nil {
part.UnlockUpdate(id)
part.Lock.Unlock()
return err
}
// Done with the collection data, next is to remove indexed values
part.Lock.Unlock()
if original != nil {
col.unindexDoc(id, original)
}
part.Lock.Lock()
part.UnlockUpdate(id)
part.Lock.Unlock()
return nil
}
示例9: load
// Load all collection schema.
func (db *DB) load() error {
// Create DB directory and PART_NUM_FILE if necessary
var numPartsAssumed = false
numPartsFilePath := path.Join(db.path, PART_NUM_FILE)
if err := os.MkdirAll(db.path, 0777); err != nil {
return err
}
if partNumFile, err := os.Stat(numPartsFilePath); err != nil {
// The new database has as many partitions as number of CPUs recognized by OS
if err := ioutil.WriteFile(numPartsFilePath, []byte(strconv.Itoa(runtime.NumCPU())), 0600); err != nil {
return err
}
numPartsAssumed = true
} else if partNumFile.IsDir() {
return fmt.Errorf("Database config file %s is actually a directory, is database path correct?", PART_NUM_FILE)
}
// Get number of partitions from the text file
if numParts, err := ioutil.ReadFile(numPartsFilePath); err != nil {
return err
} else if db.numParts, err = strconv.Atoi(strings.Trim(string(numParts), "\r\n ")); err != nil {
return err
}
// Look for collection directories and open the collections
db.cols = make(map[string]*Col)
dirContent, err := ioutil.ReadDir(db.path)
if err != nil {
return err
}
for _, maybeColDir := range dirContent {
if !maybeColDir.IsDir() {
continue
}
if numPartsAssumed {
return fmt.Errorf("Please manually repair database partition number config file %s", numPartsFilePath)
}
if db.cols[maybeColDir.Name()], err = OpenCol(db, maybeColDir.Name()); err != nil {
return err
}
}
// Synchronize data files at regular interval
if db.autoSync == nil {
db.autoSync = time.NewTicker(AUTO_SYNC_INTERVAL * time.Millisecond)
go func() {
for {
select {
case <-db.autoSync.C:
if err := db.Sync(); err != nil {
tdlog.Noticef("Background Auto-Sync on %s: Failed with error: %v", db.path, err)
}
case <-db.autoSyncStop:
db.autoSync.Stop()
return
}
}
}()
}
return err
}
示例10: Scrub
// Scrub a collection - fix corrupted documents and de-fragment free space.
func (db *DB) Scrub(name string) error {
db.schemaLock.Lock()
defer db.schemaLock.Unlock()
if _, exists := db.cols[name]; !exists {
return fmt.Errorf("Collection %s does not exist", name)
} else if err := db.cols[name].sync(); err != nil {
return err
}
// Prepare a temporary collection in file system
tmpColName := fmt.Sprintf("scrub-%s-%d", name, time.Now().UnixNano())
tmpColDir := path.Join(db.path, tmpColName)
if err := os.MkdirAll(tmpColDir, 0777); err != nil {
return err
}
// Mirror indexes from original collection
for _, idxPath := range db.cols[name].indexPaths {
if err := os.MkdirAll(path.Join(tmpColDir, strings.Join(idxPath, INDEX_PATH_SEP)), 0777); err != nil {
return err
}
}
// Iterate through all documents and put them into the temporary collection
tmpCol, err := OpenCol(db, tmpColName)
if err != nil {
return err
}
db.cols[name].ForEachDoc(func(id int, doc []byte) bool {
var docObj map[string]interface{}
if err := json.Unmarshal([]byte(doc), &docObj); err != nil {
// Skip corrupted document
return true
}
if err := tmpCol.InsertRecovery(id, docObj); err != nil {
tdlog.Noticef("Scrub %s: failed to insert back document %v", name, docObj)
}
return true
})
if err := tmpCol.close(); err != nil {
return err
}
// Replace the original collection with the "temporary" one
db.cols[name].close()
if err := os.RemoveAll(path.Join(db.path, name)); err != nil {
return err
}
if err := os.Rename(path.Join(db.path, tmpColName), path.Join(db.path, name)); err != nil {
return err
}
if db.cols[name], err = OpenCol(db, name); err != nil {
return err
}
return nil
}
示例11: Update
// Update a document.
func (col *Col) Update(id int, doc map[string]interface{}) error {
if doc == nil {
return fmt.Errorf("Updating %d: input doc may not be nil", id)
}
docJS, err := json.Marshal(doc)
if err != nil {
return err
}
col.db.schemaLock.RLock()
part := col.parts[id%col.db.numParts]
part.Lock.Lock()
// Place lock, read back original document and update
if err := part.LockUpdate(id); err != nil {
part.Lock.Unlock()
col.db.schemaLock.RUnlock()
return err
}
originalB, err := part.Read(id)
if err != nil {
part.UnlockUpdate(id)
part.Lock.Unlock()
col.db.schemaLock.RUnlock()
return err
}
var original map[string]interface{}
if err = json.Unmarshal(originalB, &original); err != nil {
tdlog.Noticef("Will not attempt to unindex document %d during update", id)
}
if err = part.Update(id, []byte(docJS)); err != nil {
part.UnlockUpdate(id)
part.Lock.Unlock()
col.db.schemaLock.RUnlock()
return err
}
// Done with the collection data, next is to maintain indexed values
part.Lock.Unlock()
if original != nil {
col.unindexDoc(id, original)
}
col.indexDoc(id, doc)
// Done with the document
part.Lock.Lock()
part.UnlockUpdate(id)
part.Lock.Unlock()
col.db.schemaLock.RUnlock()
return nil
}
示例12: UpdateBytesFunc
// UpdateBytesFunc will update a document bytes.
// update func will get current document bytes and should return bytes of updated document;
// updated document should be valid JSON;
// provided buffer could be modified (reused for returned value);
// non-nil error will be propagated back and returned from UpdateBytesFunc.
func (col *Col) UpdateBytesFunc(id int, update func(origDoc []byte) (newDoc []byte, err error)) error {
col.db.schemaLock.RLock()
part := col.parts[id%col.db.numParts]
// Place lock, read back original document and update
part.DataLock.Lock()
originalB, err := part.Read(id)
if err != nil {
part.DataLock.Unlock()
col.db.schemaLock.RUnlock()
return err
}
var original map[string]interface{}
json.Unmarshal(originalB, &original) // Unmarshal originalB before passing it to update
docB, err := update(originalB)
if err != nil {
part.DataLock.Unlock()
col.db.schemaLock.RUnlock()
return err
}
var doc map[string]interface{} // check if docB are valid JSON before Update
if err = json.Unmarshal(docB, &doc); err != nil {
part.DataLock.Unlock()
col.db.schemaLock.RUnlock()
return err
}
err = part.Update(id, docB)
part.DataLock.Unlock()
if err != nil {
col.db.schemaLock.RUnlock()
return err
}
// Done with the collection data, next is to maintain indexed values
part.LockUpdate(id)
if original != nil {
col.unindexDoc(id, original)
} else {
tdlog.Noticef("Will not attempt to unindex document %d during update", id)
}
col.indexDoc(id, doc)
// Done with the index
part.UnlockUpdate(id)
col.db.schemaLock.RUnlock()
return nil
}
示例13: ServeJWTEnabledEndpoints
func ServeJWTEnabledEndpoints(jwtPubKey, jwtPrivateKey string) {
var e error
if publicKey, e = ioutil.ReadFile(jwtPubKey); e != nil {
tdlog.Panicf("JWT: Failed to read public key file - %s", e)
} else if privateKey, e = ioutil.ReadFile(jwtPrivateKey); e != nil {
tdlog.Panicf("JWT: Failed to read private key file - %s", e)
}
jwtInitSetup()
// collection management (stop-the-world)
http.HandleFunc("/create", jwtWrap(Create))
http.HandleFunc("/rename", jwtWrap(Rename))
http.HandleFunc("/drop", jwtWrap(Drop))
http.HandleFunc("/all", jwtWrap(All))
http.HandleFunc("/scrub", jwtWrap(Scrub))
http.HandleFunc("/sync", jwtWrap(Sync))
// query
http.HandleFunc("/query", jwtWrap(Query))
http.HandleFunc("/count", jwtWrap(Count))
// document management
http.HandleFunc("/insert", jwtWrap(Insert))
http.HandleFunc("/get", jwtWrap(Get))
http.HandleFunc("/getpage", jwtWrap(GetPage))
http.HandleFunc("/update", jwtWrap(Update))
http.HandleFunc("/delete", jwtWrap(Delete))
http.HandleFunc("/approxdoccount", jwtWrap(ApproxDocCount))
// index management (stop-the-world)
http.HandleFunc("/index", jwtWrap(Index))
http.HandleFunc("/indexes", jwtWrap(Indexes))
http.HandleFunc("/unindex", jwtWrap(Unindex))
// misc
http.HandleFunc("/shutdown", jwtWrap(Shutdown))
http.HandleFunc("/dump", jwtWrap(Dump))
// does not require JWT auth
http.HandleFunc("/getjwt", getJWT)
http.HandleFunc("/checkjwt", checkJWT)
tdlog.Noticef("JWT is enabled. API endpoints require JWT authorization.")
}
示例14: main
func main() {
var err error
var defaultMaxprocs int
if defaultMaxprocs, err = strconv.Atoi(os.Getenv("GOMAXPROCS")); err != nil {
defaultMaxprocs = runtime.NumCPU()
}
// Parse CLI parameters
var mode, dir string
var port, maxprocs int
var profile bool
flag.StringVar(&mode, "mode", "", "[httpd|bench|bench2|example]")
flag.StringVar(&dir, "dir", "", "(HTTP API) database directory")
flag.IntVar(&port, "port", 8080, "(HTTP API) port number")
flag.StringVar(&webcp.WebCp, "webcp", "admin", "(HTTP API) web control panel route (without leading slash)")
flag.IntVar(&maxprocs, "gomaxprocs", defaultMaxprocs, "GOMAXPROCS")
flag.IntVar(&benchSize, "benchsize", 400000, "Benchmark sample size")
flag.BoolVar(&profile, "profile", false, "Write profiler results to prof.out")
flag.BoolVar(&tdlog.VerboseLog, "verbose", false, "Turn verbose logging on/off")
flag.BoolVar(&benchCleanup, "benchcleanup", true, "Whether to clean up (delete benchmark DB) after benchmark")
flag.Parse()
// User must specify a mode to run
if mode == "" {
flag.PrintDefaults()
return
}
// Set appropriate GOMAXPROCS
runtime.GOMAXPROCS(maxprocs)
tdlog.Noticef("GOMAXPROCS is set to %d", maxprocs)
if maxprocs < runtime.NumCPU() {
tdlog.Noticef("GOMAXPROCS (%d) is less than number of CPUs (%d), this may reduce performance. You can change it via environment variable GOMAXPROCS or by passing CLI parameter -gomaxprocs", maxprocs, runtime.NumCPU())
}
// Start profiler if enabled
if profile {
resultFile, err := os.Create("perf.out")
if err != nil {
log.Panicf("Cannot create profiler result file %s", resultFile)
}
pprof.StartCPUProfile(resultFile)
defer pprof.StopCPUProfile()
}
switch mode {
case "httpd": // Run HTTP API server
if dir == "" {
tdlog.Panicf("Please specify database directory, for example -dir=/tmp/db")
}
if port == 0 {
tdlog.Panicf("Please specify port number, for example -port=8080")
}
db, err := db.OpenDB(dir)
if err != nil {
panic(err)
}
httpapi.Start(db, port)
case "example": // Run embedded usage examples
embeddedExample()
case "bench": // Benchmark scenarios
benchmark()
case "bench2":
benchmark2()
default:
flag.PrintDefaults()
return
}
}
示例15: main
func main() {
var err error
var defaultMaxprocs int
if defaultMaxprocs, err = strconv.Atoi(os.Getenv("GOMAXPROCS")); err != nil {
defaultMaxprocs = runtime.NumCPU()
}
// Parse CLI parameters
// General params
var mode string
var maxprocs int
flag.StringVar(&mode, "mode", "", "Mandatory - specify the execution mode [httpd|bench|bench2|example]")
flag.IntVar(&maxprocs, "gomaxprocs", defaultMaxprocs, "GOMAXPROCS")
// Debug params
var profile, debug bool
flag.BoolVar(&tdlog.VerboseLog, "verbose", false, "Turn verbose logging on/off")
flag.BoolVar(&profile, "profile", false, "Write profiler results to prof.out")
flag.BoolVar(&debug, "debug", false, "Dump goroutine stack traces upon receiving interrupt signal")
// HTTP mode params
var dir string
var bind string
var port int
var authToken string
var tlsCrt, tlsKey string
flag.StringVar(&dir, "dir", "", "(HTTP server) database directory")
flag.StringVar(&bind, "bind", "", "(HTTP server) bind to IP address (all network interfaces by default)")
flag.IntVar(&port, "port", 8080, "(HTTP server) port number")
flag.StringVar(&tlsCrt, "tlscrt", "", "(HTTP server) TLS certificate (empty to disable TLS).")
flag.StringVar(&tlsKey, "tlskey", "", "(HTTP server) TLS certificate key (empty to disable TLS).")
flag.StringVar(&authToken, "authtoken", "", "(HTTP server) Only authorize requests carrying this token in 'Authorization: token TOKEN' header. (empty to disable)")
// HTTP + JWT params
var jwtPubKey, jwtPrivateKey string
flag.StringVar(&jwtPubKey, "jwtpubkey", "", "(HTTP JWT server) Public key for signing tokens (empty to disable JWT)")
flag.StringVar(&jwtPrivateKey, "jwtprivatekey", "", "(HTTP JWT server) Private key for decoding tokens (empty to disable JWT)")
// Benchmark mode params
flag.IntVar(&benchSize, "benchsize", 400000, "Benchmark sample size")
flag.BoolVar(&benchCleanup, "benchcleanup", true, "Whether to clean up (delete benchmark DB) after benchmark")
flag.Parse()
// User must specify a mode to run
if mode == "" {
flag.PrintDefaults()
os.Exit(1)
}
// Set appropriate GOMAXPROCS
runtime.GOMAXPROCS(maxprocs)
tdlog.Noticef("GOMAXPROCS is set to %d", maxprocs)
// Performance advices
if maxprocs < runtime.NumCPU() {
tdlog.Noticef("GOMAXPROCS (%d) is less than number of CPUs (%d), this may reduce performance. You can change it via environment variable GOMAXPROCS or by passing CLI parameter -gomaxprocs", maxprocs, runtime.NumCPU())
}
linuxPerfAdvice()
// Start profiler if enabled
if profile {
resultFile, err := os.Create("perf.out")
if err != nil {
tdlog.Noticef("Cannot create profiler result file %s", resultFile)
os.Exit(1)
}
pprof.StartCPUProfile(resultFile)
defer pprof.StopCPUProfile()
}
// Dump goroutine stacktraces upon receiving interrupt signal
if debug {
c := make(chan os.Signal, 1)
signal.Notify(c, os.Interrupt)
go func() {
for range c {
pprof.Lookup("goroutine").WriteTo(os.Stderr, 1)
}
}()
}
switch mode {
case "httpd":
// Run HTTP API server
if dir == "" {
tdlog.Notice("Please specify database directory, for example -dir=/tmp/db")
os.Exit(1)
}
if port == 0 {
tdlog.Notice("Please specify port number, for example -port=8080")
os.Exit(1)
}
if tlsCrt != "" && tlsKey == "" || tlsKey != "" && tlsCrt == "" {
tdlog.Notice("To enable HTTPS, please specify both RSA certificate and key file.")
os.Exit(1)
}
if jwtPrivateKey != "" && jwtPubKey == "" || jwtPubKey != "" && jwtPrivateKey == "" {
tdlog.Notice("To enable JWT, please specify RSA private and public key.")
os.Exit(1)
}
httpapi.Start(dir, port, tlsCrt, tlsKey, jwtPubKey, jwtPrivateKey, bind, authToken)
//.........這裏部分代碼省略.........