github.com/cayleygraph/cayley@v0.7.7/graph/gaedatastore/config.go (about)

     1  // Copyright 2014 The Cayley Authors. All rights reserved.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package gaedatastore
    16  
    17  import (
    18  	"encoding/json"
    19  	"fmt"
    20  	"os"
    21  	"strconv"
    22  	"time"
    23  )
    24  
    25  // Config defines the behavior of cayley database instances.
    26  type Config struct {
    27  	DatabaseType       string
    28  	DatabasePath       string
    29  	DatabaseOptions    map[string]interface{}
    30  	ReplicationType    string
    31  	ReplicationOptions map[string]interface{}
    32  	ListenHost         string
    33  	ListenPort         string
    34  	ReadOnly           bool
    35  	Timeout            time.Duration
    36  	LoadSize           int
    37  }
    38  
    39  type config struct {
    40  	DatabaseType       string                 `json:"database"`
    41  	DatabasePath       string                 `json:"db_path"`
    42  	DatabaseOptions    map[string]interface{} `json:"db_options"`
    43  	ReplicationType    string                 `json:"replication"`
    44  	ReplicationOptions map[string]interface{} `json:"replication_options"`
    45  	ListenHost         string                 `json:"listen_host"`
    46  	ListenPort         string                 `json:"listen_port"`
    47  	ReadOnly           bool                   `json:"read_only"`
    48  	Timeout            duration               `json:"timeout"`
    49  	LoadSize           int                    `json:"load_size"`
    50  }
    51  
    52  func (c *Config) UnmarshalJSON(data []byte) error {
    53  	var t config
    54  	err := json.Unmarshal(data, &t)
    55  	if err != nil {
    56  		return err
    57  	}
    58  	*c = Config{
    59  		DatabaseType:       t.DatabaseType,
    60  		DatabasePath:       t.DatabasePath,
    61  		DatabaseOptions:    t.DatabaseOptions,
    62  		ReplicationType:    t.ReplicationType,
    63  		ReplicationOptions: t.ReplicationOptions,
    64  		ListenHost:         t.ListenHost,
    65  		ListenPort:         t.ListenPort,
    66  		ReadOnly:           t.ReadOnly,
    67  		Timeout:            time.Duration(t.Timeout),
    68  		LoadSize:           t.LoadSize,
    69  	}
    70  	return nil
    71  }
    72  
    73  func (c *Config) MarshalJSON() ([]byte, error) {
    74  	return json.Marshal(config{
    75  		DatabaseType:       c.DatabaseType,
    76  		DatabasePath:       c.DatabasePath,
    77  		DatabaseOptions:    c.DatabaseOptions,
    78  		ReplicationType:    c.ReplicationType,
    79  		ReplicationOptions: c.ReplicationOptions,
    80  		ListenHost:         c.ListenHost,
    81  		ListenPort:         c.ListenPort,
    82  		ReadOnly:           c.ReadOnly,
    83  		Timeout:            duration(c.Timeout),
    84  		LoadSize:           c.LoadSize,
    85  	})
    86  }
    87  
    88  // duration is a time.Duration that satisfies the
    89  // json.UnMarshaler and json.Marshaler interfaces.
    90  type duration time.Duration
    91  
    92  // UnmarshalJSON unmarshals a duration according to the following scheme:
    93  //  * If the element is absent the duration is zero.
    94  //  * If the element is parsable as a time.Duration, the parsed value is kept.
    95  //  * If the element is parsable as a number, that number of seconds is kept.
    96  func (d *duration) UnmarshalJSON(data []byte) error {
    97  	if len(data) == 0 {
    98  		*d = 0
    99  		return nil
   100  	}
   101  	text := string(data)
   102  	t, err := time.ParseDuration(text)
   103  	if err == nil {
   104  		*d = duration(t)
   105  		return nil
   106  	}
   107  	i, err := strconv.ParseInt(text, 10, 64)
   108  	if err == nil {
   109  		*d = duration(time.Duration(i) * time.Second)
   110  		return nil
   111  	}
   112  	// This hack is to get around strconv.ParseFloat
   113  	// not handling e-notation for integers.
   114  	f, err := strconv.ParseFloat(text, 64)
   115  	*d = duration(time.Duration(f) * time.Second)
   116  	return err
   117  }
   118  
   119  func (d *duration) MarshalJSON() ([]byte, error) {
   120  	return []byte(fmt.Sprintf("%q", *d)), nil
   121  }
   122  
   123  // Load reads a JSON-encoded config contained in the given file. A zero value
   124  // config is returned if the filename is empty.
   125  func LoadConf(file string) (*Config, error) {
   126  	config := &Config{}
   127  	if file == "" {
   128  		return config, nil
   129  	}
   130  	f, err := os.Open(file)
   131  	if err != nil {
   132  		return nil, fmt.Errorf("could not open config file %q: %v", file, err)
   133  	}
   134  	defer f.Close()
   135  
   136  	dec := json.NewDecoder(f)
   137  	err = dec.Decode(config)
   138  	if err != nil {
   139  		return nil, fmt.Errorf("could not parse config file %q: %v", file, err)
   140  	}
   141  	return config, nil
   142  }