Skip to content
This repository has been archived by the owner on Jul 6, 2023. It is now read-only.

Commit

Permalink
WIP: Journal - Heketi should keep track of transactions
Browse files Browse the repository at this point in the history
Journal support is a simple concept where heketi keeps track
of transaction and has capability to revert back to a consistent
state or continue from the point where transaction was stopped.

In case of Volume create transaction,

Brick entries are added to the devices and under volume entries
after creating bricks(or lv's on devices). Before all the bricks
created for the volume, heketi process is forcefully terminated.
DB parsing is failed as there are no complete volume entries.

Someone has to cleanup or resume the transaction. Thats journal
responsibility now.

Pair-Programmed-With: Raghavendra Talur rtalur@redhat.com

Signed-off-by: Mohamed Ashiq Liyazudeen mliyazud@redhat.com
Signed-off-by: Raghavendra Talur rtalur@redhat.com
  • Loading branch information
Mohamed Ashiq Liyazudeen committed Jan 31, 2017
1 parent 131e741 commit b78947e
Show file tree
Hide file tree
Showing 3 changed files with 121 additions and 0 deletions.
8 changes: 8 additions & 0 deletions apps/glusterfs/app.go
Expand Up @@ -38,6 +38,7 @@ const (

var (
logger = utils.NewLogger("[heketi]", utils.LEVEL_INFO)
journal = utils.NewJournal("/tmp/journal")
dbfilename = "heketi.db"
)

Expand Down Expand Up @@ -168,6 +169,13 @@ func NewApp(configIo io.Reader) *App {
}
logger.Info("Loaded %v allocator", app.conf.Allocator)

// Journal File is checked
check, err := journal.JournalCheck()
if check == false {
logger.Critical("Journal not clean", err)
return nil
}

// Show application has loaded
logger.Info("GlusterFS Application Loaded")

Expand Down
8 changes: 8 additions & 0 deletions apps/glusterfs/app_volume.go
Expand Up @@ -34,6 +34,12 @@ func (a *App) VolumeCreate(w http.ResponseWriter, r *http.Request) {
http.Error(w, "request unable to be parsed", 422)
return
}
content := fmt.Sprintf("START volume create size %v Cluster %v Durability %v", msg.Size, msg.Clusters, msg.Durability)
err = journal.WriteJ(content)
if err != nil {
http.Error(w, "Journal volume create writer failed", 422)
return
}

// Check group id
switch {
Expand Down Expand Up @@ -162,6 +168,8 @@ func (a *App) VolumeCreate(w http.ResponseWriter, r *http.Request) {
return "/volumes/" + vol.Info.Id, nil
})

content = fmt.Sprintf("END volume create size %v Cluster %v Durability %v", msg.Size, msg.Clusters, msg.Durability)
journal.WriteJ(content)
}

func (a *App) VolumeList(w http.ResponseWriter, r *http.Request) {
Expand Down
105 changes: 105 additions & 0 deletions pkg/utils/journal.go
@@ -0,0 +1,105 @@
//
// Copyright (c) 2015 The heketi Authors
//
// This file is licensed to you under your choice of the GNU Lesser
// General Public License, version 3 or any later version (LGPLv3 or
// later), or the GNU General Public License, version 2 (GPLv2), in all
// cases as published by the Free Software Foundation.
//

package utils

import (
"bufio"
"os"
"strings"

"github.com/lpabon/godbc"
)

type Journal struct {
Path string
Clean bool
}

// Create a new journal
func NewJournal(path string) *Journal {

godbc.Check(path != "", path)

j := &Journal{}

// open output file
f, err := os.OpenFile(path, os.O_CREATE|os.O_RDWR|os.O_APPEND, 0666)
if err != nil {
panic(err)
}
j.Path = path

// close fo on exit and check for its returned error
defer func() {
if err := f.Close(); err != nil {
panic(err)
}
}()

return j
}

func readLines(path string) ([]string, error) {
file, err := os.Open(path)
if err != nil {
return nil, err
}
defer file.Close()

var lines []string
scanner := bufio.NewScanner(file)
for scanner.Scan() {
lines = append(lines, scanner.Text())
}
return lines, scanner.Err()
}

func (j *Journal) JournalCheck() (bool, error) {
check := j.Clean
path := j.Path
scount := 0
ecount := 0

journal, err := readLines(path)
if err != nil {
check = false
}

for _, lines := range journal {
if strings.Contains(lines, "START") {
scount++
}
if strings.Contains(lines, "END") {
ecount++
}
}

if scount == ecount {
check = true
} else {
check = false
}
j.Clean = check
return check, nil
}

func (j *Journal) WriteJ(text string) error {
path := j.Path
f, err := os.OpenFile(path, os.O_APPEND|os.O_RDWR, 0666)
if err != nil {
panic(err)
}
defer f.Close()

_, err = f.WriteString(text)
if err != nil {
}
return err
}

0 comments on commit b78947e

Please sign in to comment.