avoid same directory with different dir ids

fix https://github.com/chrislusf/seaweedfs/issues/277
This commit is contained in:
chrislusf 2016-04-04 16:32:16 -07:00
parent 7dcbbaa653
commit 6876bfa685

View file

@ -61,9 +61,7 @@ type DirectoryManagerInMap struct {
isLoading bool isLoading bool
} }
func (dm *DirectoryManagerInMap) NewDirectoryEntryInMap(parent *DirectoryEntryInMap, name string) (d *DirectoryEntryInMap, err error) { func (dm *DirectoryManagerInMap) newDirectoryEntryInMap(parent *DirectoryEntryInMap, name string) (d *DirectoryEntryInMap, err error) {
writeLock.Lock()
defer writeLock.Unlock()
d = &DirectoryEntryInMap{Name: name, Parent: parent, subDirectories: make(map[string]*DirectoryEntryInMap)} d = &DirectoryEntryInMap{Name: name, Parent: parent, subDirectories: make(map[string]*DirectoryEntryInMap)}
var parts []string var parts []string
for p := d; p != nil && p.Name != ""; p = p.Parent { for p := d; p != nil && p.Name != ""; p = p.Parent {
@ -90,7 +88,7 @@ func (dm *DirectoryManagerInMap) log(words ...string) {
func NewDirectoryManagerInMap(dirLogFile string) (dm *DirectoryManagerInMap, err error) { func NewDirectoryManagerInMap(dirLogFile string) (dm *DirectoryManagerInMap, err error) {
dm = &DirectoryManagerInMap{} dm = &DirectoryManagerInMap{}
//dm.Root do not use NewDirectoryEntryInMap, since dm.max will be changed //dm.Root do not use newDirectoryEntryInMap, since dm.max will be changed
dm.Root = &DirectoryEntryInMap{subDirectories: make(map[string]*DirectoryEntryInMap)} dm.Root = &DirectoryEntryInMap{subDirectories: make(map[string]*DirectoryEntryInMap)}
if dm.logFile, err = os.OpenFile(dirLogFile, os.O_RDWR|os.O_CREATE, 0644); err != nil { if dm.logFile, err = os.OpenFile(dirLogFile, os.O_RDWR|os.O_CREATE, 0644); err != nil {
return nil, fmt.Errorf("cannot write directory log file %s: %v", dirLogFile, err) return nil, fmt.Errorf("cannot write directory log file %s: %v", dirLogFile, err)
@ -192,19 +190,29 @@ func (dm *DirectoryManagerInMap) loadDirectory(dirPath string, dirId filer.Direc
for i := 1; i < len(parts); i++ { for i := 1; i < len(parts); i++ {
sub, ok := dir.getChild(parts[i]) sub, ok := dir.getChild(parts[i])
if !ok { if !ok {
writeLock.Lock()
if sub2, createdByOtherThread := dir.getChild(parts[i]); createdByOtherThread {
sub = sub2
} else {
if i != len(parts)-1 { if i != len(parts)-1 {
writeLock.Unlock()
return fmt.Errorf("%s should be created after parent %s", dirPath, parts[i]) return fmt.Errorf("%s should be created after parent %s", dirPath, parts[i])
} }
var err error var err error
sub, err = dm.NewDirectoryEntryInMap(dir, parts[i]) sub, err = dm.newDirectoryEntryInMap(dir, parts[i])
if err != nil { if err != nil {
writeLock.Unlock()
return err return err
} }
if sub.Id != dirId { if sub.Id != dirId {
writeLock.Unlock()
// the dir.log should be the same order as in-memory directory id
return fmt.Errorf("%s should be have id %v instead of %v", dirPath, sub.Id, dirId) return fmt.Errorf("%s should be have id %v instead of %v", dirPath, sub.Id, dirId)
} }
dir.addChild(parts[i], sub) dir.addChild(parts[i], sub)
} }
writeLock.Unlock()
}
dir = sub dir = sub
} }
return nil return nil
@ -220,14 +228,21 @@ func (dm *DirectoryManagerInMap) makeDirectory(dirPath string) (dir *DirectoryEn
for i := 1; i < len(parts); i++ { for i := 1; i < len(parts); i++ {
sub, ok := dir.getChild(parts[i]) sub, ok := dir.getChild(parts[i])
if !ok { if !ok {
writeLock.Lock()
if sub2, createdByOtherThread := dir.getChild(parts[i]); createdByOtherThread {
sub = sub2
} else {
var err error var err error
sub, err = dm.NewDirectoryEntryInMap(dir, parts[i]) sub, err = dm.newDirectoryEntryInMap(dir, parts[i])
if err != nil { if err != nil {
writeLock.Unlock()
return nil, false return nil, false
} }
dir.addChild(parts[i], sub) dir.addChild(parts[i], sub)
created = true created = true
} }
writeLock.Unlock()
}
dir = sub dir = sub
} }
return dir, created return dir, created