// Saves Meta data from dirTree to meta File func saveMeta(data *ReveloData) error { var Meta *horcrux.Meta var err error data.lock.RLock() Meta, err = dirTree.GetMeta(data.Root) Meta.Config = data.Config Meta.CurrVer = data.CurrVer data.lock.RUnlock() if err != nil { log.Error("saveMeta: Cannot get Meta data") return err } js, err := json.MarshalIndent(Meta, "", " ") if err != nil { log.WithFields( log.Fields{"Meta": Meta, "Error": err}).Error("saveMeta: Cannot marshal meta") return err } metaFile, err := os.OpenFile(data.cacheDir+"/"+data.metaName, os.O_WRONLY|os.O_SYNC, 0600) if err != nil { log.WithFields(log.Fields{"Meta File": data.metaName, "Error": err}).Error("saveMeta: Cannot open meta file") return err } defer metaFile.Close() // XXX Using File EX lock to avoid multiple access for err = syscall.Flock(int(metaFile.Fd()), syscall.LOCK_EX); err == syscall.EINTR; { } if err != nil { log.WithFields(log.Fields{"Error": err}).Error("saveMeta: Cannot lock meta file") return err } defer syscall.Flock(int(metaFile.Fd()), syscall.LOCK_UN) metaFile.Truncate(0) //XXX: Do Truncate(n) after write succeeds!! n, err := metaFile.Write(js) if err != nil { log.WithFields(log.Fields{ "Meta file": data.metaName, "Wrote": n, "Size": len(js), "Error": err, }).Error("saveMeta: Cannot write to meta file") return err } log.Debug("saveMeta: Done") return nil }
// Walks the tree and gets the flat Meta data func GetMeta(root *Node) (*horcrux.Meta, error) { var Meta *horcrux.Meta var queue [MIN_KIDS * MIN_KIDS]*Node if root == nil { log.Error("GetMeta: nil root") return nil, syscall.EINVAL } q := queue[0:0] Meta = new(horcrux.Meta) Meta.Entries = make([]horcrux.Entry, 0, MIN_KIDS*MIN_KIDS) node := root idx := 0 for node != nil { /* log.WithFields(log.Fields{ "Idx": idx, "Name": node.Entry.Name, "Prefix": node.Entry.Prefix, }).Debug("Getting Entry") */ Meta.Entries = append(Meta.Entries, node.Entry) idx++ for i := 0; i < node.numKids; i++ { name := node.kidsArr[i] n := node.kidsMap[name] /* log.WithFields(log.Fields{ "Entry Name": n.Entry.Name, "Entry Prefix": n.Entry.Prefix, }).Debug("Queuing node..") */ q = enqueue(q, n) } q, node = dequeue(q) } Meta.NumFiles = idx Meta.Entries = Meta.Entries[:idx] return Meta, nil }