1//  Copyright (c) 2014 Couchbase, Inc.
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
15package bleve
16
17import (
18	"encoding/json"
19	"io/ioutil"
20	"os"
21
22	"github.com/blevesearch/bleve/index/upsidedown"
23)
24
25const metaFilename = "index_meta.json"
26
27type indexMeta struct {
28	Storage   string                 `json:"storage"`
29	IndexType string                 `json:"index_type"`
30	Config    map[string]interface{} `json:"config,omitempty"`
31}
32
33func newIndexMeta(indexType string, storage string, config map[string]interface{}) *indexMeta {
34	return &indexMeta{
35		IndexType: indexType,
36		Storage:   storage,
37		Config:    config,
38	}
39}
40
41func openIndexMeta(path string) (*indexMeta, error) {
42	if _, err := os.Stat(path); os.IsNotExist(err) {
43		return nil, ErrorIndexPathDoesNotExist
44	}
45	indexMetaPath := indexMetaPath(path)
46	metaBytes, err := ioutil.ReadFile(indexMetaPath)
47	if err != nil {
48		return nil, ErrorIndexMetaMissing
49	}
50	var im indexMeta
51	err = json.Unmarshal(metaBytes, &im)
52	if err != nil {
53		return nil, ErrorIndexMetaCorrupt
54	}
55	if im.IndexType == "" {
56		im.IndexType = upsidedown.Name
57	}
58	return &im, nil
59}
60
61func (i *indexMeta) Save(path string) (err error) {
62	indexMetaPath := indexMetaPath(path)
63	// ensure any necessary parent directories exist
64	err = os.MkdirAll(path, 0700)
65	if err != nil {
66		if os.IsExist(err) {
67			return ErrorIndexPathExists
68		}
69		return err
70	}
71	metaBytes, err := json.Marshal(i)
72	if err != nil {
73		return err
74	}
75	indexMetaFile, err := os.OpenFile(indexMetaPath, os.O_RDWR|os.O_CREATE|os.O_EXCL, 0666)
76	if err != nil {
77		if os.IsExist(err) {
78			return ErrorIndexPathExists
79		}
80		return err
81	}
82	defer func() {
83		if ierr := indexMetaFile.Close(); err == nil && ierr != nil {
84			err = ierr
85		}
86	}()
87	_, err = indexMetaFile.Write(metaBytes)
88	if err != nil {
89		return err
90	}
91	return nil
92}
93
94func indexMetaPath(path string) string {
95	return path + string(os.PathSeparator) + metaFilename
96}
97