// ListChidren returns children of a givent path func (p *osPath) ListChildren() (children []osPath, err error) { pathType, err := p.GetType() if err != nil { return children, err } switch pathType { case "root": // List container resp, err := p.client.Call(&gopenstack.CallOptions{ Method: "GET", Ressource: "?format=json", }) if err = resp.HandleErr(err, []int{200, 204}); err != nil { return children, err } if err = json.Unmarshal(resp.Body, &children); err != nil { return children, err } // add ptype for k, _ := range children { children[k].Ptype = "container" } case "container", "vfolder": resp, err := p.client.Call(&gopenstack.CallOptions{ Method: "GET", Ressource: p.GetContainer() + "?format=json&prefix=" + p.GetPrefix(), //Ressource: p.GetContainer() + "?format=json&path=dev", }) if err = resp.HandleErr(err, []int{200, 203}); err != nil { return children, err } var tc []osPath err = json.Unmarshal(resp.Body, &tc) // Remove prefix prefix := p.GetPrefix() for k, c := range tc { if len(prefix) != 0 && strings.Count(c.Name, "/") > 0 { tc[k].Name = c.Name[strings.LastIndex(prefix, "/"):] posToCut := strings.Index(tc[k].Name, "/") if posToCut != -1 { tc[k].Name = tc[k].Name[posToCut+1:] } } } // Remove suffix for k, c := range tc { if i := strings.Index(c.Name, "/"); i != -1 { tc[k].Name = c.Name[:i] } } L1: for _, c := range tc { // vfolder && already in for k, v := range children { if c.Name == v.Name { //children[k].Count++ children[k].Bytes += c.Bytes children[k].ContentType = "vfolder" children[k].Etag = "" continue L1 } } if c.Bytes == 0 && c.ContentType == "application/octet-stream" { c.ContentType = "vfolder" c.Etag = "" } if c.Name != "" { children = append(children, c) } } case "object": //fmt.Println("object") resp, err := p.client.Call(&gopenstack.CallOptions{ Method: "HEAD", Ressource: p.Name, }) if err = resp.HandleErr(err, []int{200, 203}); err != nil { return children, err } cp := osPath{} cp.Name = p.Name[strings.Index(p.Name, "/"):] cp.LastModified.Time, err = time.Parse(time.RFC1123, resp.Headers["Last-Modified"][0]) if err != nil { cp.LastModified.Time = *new(time.Time) } cp.Etag = resp.Headers["Etag"][0] cp.Bytes, _ = strconv.ParseUint(resp.Headers["Content-Length"][0], 10, 64) cp.ContentType = resp.Headers["Content-Type"][0] children = append(children, cp) default: err = gopenstack.ErrUnsuportedPathType(pathType) return } return }
// DeletePath delete path & his children (helper) func (s *Swift) DeletePath(path string) error { var err error hasTrailingSlash := false objectToremovePaths := []string{} if strings.HasSuffix(path, "/") { path = path[:len(path)-1] hasTrailingSlash = true } // Container to remove (last job) containerToRemove := "" // get path type (container, object, vpath) dPath := NewOsPath(s.client, path) pathType, err := dPath.GetType() if err != nil { return err } switch pathType { case "object": objectToremovePaths = append(objectToremovePaths, path) case "container", "vfolder": objectsToRemove, err := dPath.GetChildrenObjects() if err != nil { return err } if pathType == "container" { for _, o := range objectsToRemove { objectToremovePaths = append(objectToremovePaths, path+"/"+o.Name) } if !hasTrailingSlash { containerToRemove = path } } else { if len(objectsToRemove) == 0 { return gopenstack.ErrPathNotFound(path) } container := dPath.GetContainer() for _, o := range objectsToRemove { objectToremovePaths = append(objectToremovePaths, container+"/"+o.Name) } } default: err = gopenstack.ErrUnsuportedPathType(pathType) return err } // Remove objects chanDone := make(chan bool) chanAJobIsDone := make(chan bool) chanThreadCount := make(chan int) threadsCount := 0 remainingJobs := len(objectToremovePaths) // Count concurrent threads go func() { for { threadsCount += <-chanThreadCount } }() // Update remainingJobs and send "all jobs are done" signal go func() { for { <-chanAJobIsDone remainingJobs-- if remainingJobs < 1 { chanDone <- true break } } }() // Delete if len(objectToremovePaths) > 0 { for _, p := range objectToremovePaths { for { if threadsCount < 10 { threadsCount++ break } time.Sleep(1 * time.Second) } go func(path string) { err = s.DeleteObject(path) if err != nil { chanDone <- true } threadsCount-- chanAJobIsDone <- true }(p) } // Waiting for all jobs <-chanDone } // remove container if needed if len(containerToRemove) != 0 { err = s.DeleteObject(containerToRemove) } return err }