Example #1
0
// 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
}
Example #2
0
// 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
}