//Store will store a file located at path in the DHT (under key) by //contacting the node at addr func Store(key [sha256.Size]byte, path string, addr string) error { //do a lookup of the key ipaddr, err := chord.Lookup(key, addr) file, err := os.Open(path) checkError(err) if err != nil { fmt.Printf("error here (0)\n") return err } defer file.Close() document := make([]byte, 4096) n, err := file.Read(document) checkError(err) if err != nil { fmt.Printf("error here (1)\n") return err } //create message to send to target ip msg := getstoreMsg(key, document[:n]) //send message TODO: check reply for errors _, err = chord.Send(msg, ipaddr) if err != nil { fmt.Printf("error here (2)\n") } return err }
//Notify is part of the ChordApp interface and will update the //application by moving files if its predecessor changes func (fs *FileSystem) Notify(id [sha256.Size]byte, myid [sha256.Size]byte, addr string) { fmt.Printf("Predecessor changed to %s.\n", addr) dir, err := os.Open(fs.home) defer dir.Close() checkError(err) if err != nil { return } names, err := dir.Readdirnames(0) checkError(err) if err != nil { return } for _, name := range names { var key [sha256.Size]byte decoded, err := base32.StdEncoding.DecodeString(name) if err != nil { //fmt.Printf("file was not encoded.\n") continue } copy(key[:], decoded[:sha256.Size]) if chord.InRange(id, key, myid) { //transfer file. fs.cache[name] = true file, err := os.Open(fmt.Sprintf("%s/%s", fs.home, name)) checkError(err) if err != nil { checkError(err) } defer file.Close() document := make([]byte, 4096) n, err := file.Read(document) checkError(err) if err != nil { checkError(err) } //create message to send to target ip msg := getstoreMsg(key, document[:n]) //send message TODO: check reply for errors _, err = chord.Send(msg, addr) if err != nil { checkError(err) } fmt.Printf("Relocated file %s to node %s.\n", name, addr) } } //TODO: exchange mirrored files }
//Fetch will retrieve a file with key specified by key from the DHT and //save it to path by contacting the node at addr func Fetch(key [sha256.Size]byte, path string, addr string) error { ipaddr, err := chord.Lookup(key, addr) if err != nil { name := base32.StdEncoding.EncodeToString(key[:]) err = &FSError{ipaddr, name, err} fmt.Printf("%s.\n", err.Error()) return err } //create message to send to target ip msg := getfetchMsg(key) reply, err := chord.Send(msg, ipaddr) if err != nil { name := base32.StdEncoding.EncodeToString(key[:]) err = &FSError{ipaddr, name, err} fmt.Printf("%s.\n", err.Error()) return err } reply, err = parseHeader(reply) if err != nil { name := base32.StdEncoding.EncodeToString(key[:]) err = &FSError{ipaddr, name, err} fmt.Printf("%s.\n", err.Error()) return err } if reply == nil { name := base32.StdEncoding.EncodeToString(key[:]) err = &FSError{ipaddr, name, err} fmt.Printf("%s.\n", err.Error()) return err } document, err := parseDoc(reply) if err != nil { name := base32.StdEncoding.EncodeToString(key[:]) err = &FSError{ipaddr, name, err} fmt.Printf("%s.\n", err.Error()) return err } if document == nil { name := base32.StdEncoding.EncodeToString(key[:]) err = &FSError{ipaddr, name, err} fmt.Printf("%s.\n", err.Error()) return err } file, err := os.Create(path) checkError(err) if err != nil { return err } defer file.Close() _, err = file.Write(document) checkError(err) if err != nil { return err } return err }