Skip to content

Commit

Permalink
Merge pull request #1624 from abhinavdangeti/issue1623
Browse files Browse the repository at this point in the history
In RDONLY mode, use O_CREATE for bolt.Open(..) only when file doesn't exist
  • Loading branch information
abhinavdangeti authored Sep 16, 2021
2 parents a74298a + bf06d34 commit 5e873fe
Show file tree
Hide file tree
Showing 2 changed files with 100 additions and 0 deletions.
9 changes: 9 additions & 0 deletions index/scorch/scorch.go
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,15 @@ func (s *Scorch) openBolt() error {
var rootBoltOpt = *bolt.DefaultOptions
if s.readOnly {
rootBoltOpt.ReadOnly = true
rootBoltOpt.OpenFile = func(path string, flag int, mode os.FileMode) (*os.File, error) {
// Bolt appends an O_CREATE flag regardless.
// See - https://github.com/etcd-io/bbolt/blob/v1.3.5/db.go#L210
// Use os.O_RDONLY only if path exists (#1623)
if _, err := os.Stat(path); os.IsNotExist(err) {
return os.OpenFile(path, flag, mode)
}
return os.OpenFile(path, os.O_RDONLY, mode)
}
} else {
if s.path != "" {
err := os.MkdirAll(s.path, 0700)
Expand Down
91 changes: 91 additions & 0 deletions index/scorch/scorch_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,11 @@ package scorch
import (
"context"
"fmt"
"io/ioutil"
"log"
"math/rand"
"os"
"path/filepath"
"reflect"
"regexp"
"strconv"
Expand Down Expand Up @@ -2573,3 +2575,92 @@ func TestOpenBoltTimeout(t *testing.T) {
t.Error("expected timeout error opening index again")
}
}

func TestReadOnlyIndex(t *testing.T) {
// https://github.com/blevesearch/bleve/issues/1623
cfg := CreateConfig("TestReadOnlyIndex")
err := InitTest(cfg)
if err != nil {
t.Fatal(err)
}
defer func() {
err := DestroyTest(cfg)
if err != nil {
t.Log(err)
}
}()

analysisQueue := index.NewAnalysisQueue(1)
writeIdx, err := NewScorch(Name, cfg, analysisQueue)
if err != nil {
t.Fatal(err)
}
err = writeIdx.Open()
if err != nil {
t.Fatalf("error opening index: %v", err)
}
writeIdxClosed := false
defer func() {
if !writeIdxClosed {
err := writeIdx.Close()
if err != nil {
t.Fatal(err)
}
}
}()

// Add a single document to the index.
doc := document.NewDocument("1")
doc.AddField(document.NewTextField("name", []uint64{}, []byte("test")))
err = writeIdx.Update(doc)
if err != nil {
t.Errorf("Error updating index: %v", err)
}
writeIdx.Close()
writeIdxClosed = true

// After the index is written, change permissions on every file
// in the index to read-only.
var permissionsFunc func(folder string)
permissionsFunc = func(folder string) {
entries, _ := ioutil.ReadDir(folder)
for _, entry := range entries {
fullName := filepath.Join(folder, entry.Name())
if entry.IsDir() {
permissionsFunc(fullName)
} else {
os.Chmod(fullName, 0555)
}
}
}
permissionsFunc(cfg["path"].(string))

// Now reopen the index in read-only mode and attempt to read from it.
cfg["read_only"] = true
readIdx, err := NewScorch(Name, cfg, analysisQueue)
defer func() {
err := readIdx.Close()
if err != nil {
t.Fatal(err)
}
}()

if err != nil {
t.Fatal(err)
}
err = readIdx.Open()
if err != nil {
t.Errorf("error opening index: %v", err)
}
reader, err := readIdx.Reader()
if err != nil {
t.Fatal(err)
}
docCount, err := reader.DocCount()
if err != nil {
t.Fatal(err)
}
if docCount != 1 {
t.Errorf("Expected document count to be %d got %d", 1, docCount)
}
}

0 comments on commit 5e873fe

Please sign in to comment.