Documentation
¶
Overview ¶
Package grasure is an Universal Erasure Coding Architecture in Go
For usage and examples, see https://github.com/DurantVivado/Grasure
Index ¶
- type Erasure
- func (e *Erasure) Destroy(mode string, failNum int, fileName string)
- func (e *Erasure) EncodeFile(filename string) (*fileInfo, error)
- func (e *Erasure) InitSystem(assume bool) error
- func (e *Erasure) ReadConfig() error
- func (e *Erasure) ReadDiskPath() error
- func (e *Erasure) ReadFile(filename string, savepath string, degrade bool) error
- func (e *Erasure) Recover() (map[string]string, error)
- func (e *Erasure) RemoveFile(filename string) error
- func (e *Erasure) Scale(new_k, new_m int) error
- func (e *Erasure) Update(oldFile, newFile string) error
- func (e *Erasure) WriteConfig() error
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Erasure ¶
type Erasure struct { // the number of data blocks in a stripe K int `json:"dataShards"` // the number of parity blocks in a stripe M int `json:"parityShards"` // the block size. default to 4KiB BlockSize int64 `json:"blockSize"` // the disk number, only the first diskNum disks are used in diskPathFile DiskNum int `json:"diskNum"` //FileMeta lists, indicating fileName, fileSize, fileHash, fileDist... FileMeta []*fileInfo `json:"fileLists"` //how many stripes are allowed to encode/decode concurrently ConStripes int `json:"-"` // the replication factor for config file ReplicateFactor int // configuration file path ConfigFile string `json:"-"` // the path of file recording all disks path DiskFilePath string `json:"-"` // whether or not to override former files or directories, default to false Override bool `json:"-"` //whether or not to mute outputs Quiet bool `json:"-"` // contains filtered or unexported fields }
func (*Erasure) Destroy ¶
Destroy simulates disk failure or bitrot:
for `diskFail mode`, `failNum` random disks are marked as unavailable, `failName` is ignored.
for `bitRot`, `failNum` random blocks in a stripe of the file corrupts, that only works in Read Mode;
Since it's a simulation, no real data will be lost. Note that failNum = min(failNum, DiskNum).
func (*Erasure) EncodeFile ¶
EncodeFile takes filepath as input and encodes the file into data and parity blocks concurrently.
It returns `*fileInfo` and an error. Specify `blocksize` and `conStripe` for better performance.
Example ¶
An intriguing example of how to encode a file into the system
package main import ( "fmt" "log" "math/rand" "os" grasure "github.com/DurantVivado/Grasure" ) func fillRandom(p []byte) { for i := 0; i < len(p); i += 7 { val := rand.Int63() for j := 0; i+j < len(p) && j < 7; j++ { p[i+j] = byte(val) val >>= 8 } } } func prepareDir(diskNum int) error { f, err := os.Create(".hdr.disks.path") if err != nil { return err } defer f.Close() for i := 0; i < diskNum; i++ { path := fmt.Sprintf("disk%d", i) if err := os.RemoveAll(path); err != nil { return err } if err := os.Mkdir(path, 0644); err != nil { return err } _, err := f.WriteString(path + "\n") if err != nil { return err } } return nil } func main() { // Create some sample data data := make([]byte, 250000) filepath := "example.file" fillRandom(data) // write it into a file f, err := os.OpenFile(filepath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0666) if err != nil { log.Fatal(err) } _, err = f.Write(data) if err != nil { log.Fatal(err) } f.Close() // define the struct Erasure erasure := &grasure.Erasure{ DiskFilePath: ".hdr.disks.path", ConfigFile: "config.json", DiskNum: 10, K: 6, M: 3, BlockSize: 4096, ReplicateFactor: 3, ConStripes: 100, Override: true, } err = prepareDir(13) if err != nil { log.Fatal(err) } //read the disk paths err = erasure.ReadDiskPath() if err != nil { log.Fatal(err) } //first init the system err = erasure.InitSystem(true) if err != nil { log.Fatal(err) } //read the config file (auto-generated) err = erasure.ReadConfig() if err != nil { log.Fatal(err) } //encode the file into system _, err = erasure.EncodeFile(filepath) if err != nil { log.Fatal(err) } //write the config err = erasure.WriteConfig() if err != nil { log.Fatal(err) } fmt.Println("encode ok!") }
Output: Warning: you are intializing a new erasure-coded system, which means the previous data will also be reset. System init! Erasure parameters: dataShards:6, parityShards:3,blocksize:4096,diskNum:10 encode ok!
func (*Erasure) InitSystem ¶
Init initiates the erasure-coded system, this func can NOT be called concurrently. It will clear all the data on the storage, so a consulting procedure is added in advance of perilous action.
Note if `assume` renders yes then the consulting part will be skipped.
func (*Erasure) ReadConfig ¶
ReadConfig reads the config file during system warm-up.
Calling it before actions like encode and read is a good habit.
func (*Erasure) ReadDiskPath ¶
ReadDiskPath reads the disk paths from diskFilePath. There should be exactly ONE disk path at each line.
This func can NOT be called concurrently.
func (*Erasure) ReadFile ¶
ReadFile reads ONE file on the system and save it to local `savePath`.
In case of any failure within fault tolerance, the file will be decoded first. `degrade` indicates whether degraded read is enabled.
func (*Erasure) Recover ¶
RecoverReadFull mainly deals with a disk-level disaster reconstruction. User should provide enough backup devices in `.hdr.disk.path` for data transferring.
An (oldPath -> replacedPath) replace map is returned in the first placeholder.
Example ¶
A fabulous example on recovery of disks
package main import ( "fmt" "log" grasure "github.com/DurantVivado/Grasure" ) func main() { erasure := &grasure.Erasure{ DiskFilePath: ".hdr.disks.path", ConfigFile: "config.json", DiskNum: 10, K: 6, M: 3, BlockSize: 4096, ReplicateFactor: 3, ConStripes: 100, Override: true, } //read the disk paths err := erasure.ReadDiskPath() if err != nil { log.Fatal(err) } err = erasure.ReadConfig() if err != nil { log.Fatal(err) } erasure.Destroy("diskFail", 2, "") _, err = erasure.Recover() if err != nil { log.Fatal(err) } err = erasure.WriteConfig() if err != nil { log.Fatal(err) } fmt.Println("system recovered") }
Output: system recovered
func (*Erasure) RemoveFile ¶
RemoveFile deletes specific file `filename`in the system.
Both the file blobs and meta data are deleted. It's currently irreversible.
Example ¶
A curious example on removal of file, please encode the file into system first
package main import ( "fmt" "log" grasure "github.com/DurantVivado/Grasure" ) func main() { filepath := "example.file" erasure := &grasure.Erasure{ DiskFilePath: ".hdr.disks.path", ConfigFile: "config.json", DiskNum: 10, K: 6, M: 3, BlockSize: 4096, ReplicateFactor: 3, ConStripes: 100, Override: true, } //read the disk paths err := erasure.ReadDiskPath() if err != nil { log.Fatal(err) } err = erasure.ReadConfig() if err != nil { log.Fatal(err) } err = erasure.RemoveFile(filepath) if err != nil { log.Fatal(err) } err = erasure.WriteConfig() if err != nil { log.Fatal(err) } fmt.Println("file removed") }
Output: file removed
func (*Erasure) Scale ¶ added in v0.0.4
Scale expands the storage system to a new k and new m, for example, Start with a (2,1) system but with more data flouring into, the system needs to be scaled to a larger system, say (6,4).
One advantage is that a bigger k supports higher storage efficiency.
Another is that requirement of fault tolerance may level up when needed.
It unavoidably incurrs serious data migration. We are working to minimize the traffic.
func (*Erasure) Update ¶ added in v0.0.4
update a file according to a new file, the local `filename` will be used to update the file in the cloud with the same name
func (*Erasure) WriteConfig ¶
WriteConfig writes the erasure parameters and file information list into config files.
Calling it after actions like encode and read is a good habit.