func downloader(req Request, res Response) { var pathDetail, _ = req.F()["HandledRR"].([]string) if pathDetail == nil { pathDetail = req.F()["RR"].([]string) pathDetail = append(pathDetail, filesystem.ROOT_INODE_NAME) } var fs = filesystem.GetFs(outapi.NewSwiftio(outapi.DefaultConnector, pathDetail[1])) if fs == nil { res.Status("Internal Error: the FS pool is full.", 500) } defer fs.Release() var hasSent bool = false if base, filename := pathman.SplitPath(pathDetail[2]); filename == "" { var err = fs.Get("", pathDetail[3], func(fileInode string, oriName string, oriHeader map[string]string) io.Writer { for k, v := range oriHeader { res.Set(ORIGINAL_HEADER+k, v) } res.Set(FILE_NODE, fileInode) res.Set(HEADER_CONTENT_DISPOSE, "inline; filename=\""+oriName+"\"") res.SendCode(200) hasSent = true return res.R() }) if err != nil && !hasSent { if err == exception.EX_FILE_NOT_EXIST { res.Status("File Not Found.", 404) } else { res.Status("Internal Error: "+err.Error(), 500) } } } else { var nodeName, err = fs.Locate(base, pathDetail[3]) if err != nil { res.Status("Nonexist container or path. "+err.Error(), 404) return } err = fs.Get(filename, nodeName, func(fileInode string, oriName string, oriHeader map[string]string) io.Writer { for k, v := range oriHeader { res.Set(ORIGINAL_HEADER+k, v) } res.Set(PARENT_NODE, nodeName) res.Set(HEADER_CONTENT_DISPOSE, "inline; filename=\""+oriName+"\"") res.Set(FILE_NODE, fileInode) res.SendCode(200) hasSent = true return res.R() }) if err != nil && !hasSent { if err == exception.EX_FILE_NOT_EXIST { res.Status("File Not Found.", 404) } else { res.Status("Internal Error: "+err.Error(), 500) } } } }
// ==========================API DOCS======================================= // API Name: Stream data to specified file // Action: Write the data from http to the file streamingly // API URL: /io/{contianer}/{followingpath} // REQUEST: PUT // Parameters: // - contianer(in URL): the container name // Returns: // - HTTP 200: No error, the file is written by force // When success, the returned header Parent-Node(if accessed) will // contain its parent inode and File-Node will indicate the file itself. // - HTTP 404: Either the container or the filepath does not exist. // - HTTP 500: Error. The body is supposed to return error info. // ==========================API DOCS END=================================== func uploader(req Request, res Response) { var pathDetail, _ = req.F()["HandledRR"].([]string) if pathDetail == nil { pathDetail = req.F()["RR"].([]string) pathDetail = append(pathDetail, filesystem.ROOT_INODE_NAME) } var fs = filesystem.GetFs(outapi.NewSwiftio(outapi.DefaultConnector, pathDetail[1])) if fs == nil { res.Status("Internal Error: the FS pool is full.", 500) } defer fs.Release() var putErr error if base, filename := pathman.SplitPath(pathDetail[2]); filename == "" { // TODO: glean user meta putErr, _ = fs.Put("", pathDetail[3], nil, req.R().Body) res.Set(FILE_NODE, pathDetail[3]) } else { var nodeName, err = fs.Locate(base, pathDetail[3]) if err != nil { res.Status("Nonexist container or path. "+err.Error(), 404) return } // TODO: glean user meta var targetNode string putErr, targetNode = fs.Put(filename, nodeName, nil, req.R().Body) if targetNode != "" { res.Set(FILE_NODE, targetNode) } res.Set(PARENT_NODE, nodeName) } if !egg.Nil(putErr) { if egg.In(putErr, exception.EX_FILE_NOT_EXIST) { res.Status("Nonexist container or path. Or you cannot refer to a non-existing inode in ovveride mode.", 404) return } res.Status("Internal Error: "+putErr.Error(), 500) return } res.SendCode(200) }
func mvDirectory(req Request, res Response) { //===============measurement======================== var startTime int64 = 0 if req.Get("Enable-Measure") == "True" { startTime = time.Now().UnixNano() } //================================================== var pathDetail, _ = req.F()["HandledRR"].([]string) if pathDetail == nil { pathDetail = req.F()["RR"].([]string) pathDetail = append(pathDetail, filesystem.ROOT_INODE_NAME) } var base, filename = pathman.SplitPath(pathDetail[2]) if filename == "" { res.Status("The directory/file to move should be specified.", 404) return } var destinationALL = req.Get(HEADER_DESTINATION) if destinationALL == "" { res.Status("Destination path should be specified in the Header "+HEADER_DESTINATION, 403) return } var destinationSC, destinationPath = pathman.ShortcutResolver(destinationALL) if destinationSC == "" { destinationSC = filesystem.ROOT_INODE_NAME } else { if len(destinationPath) > 0 { destinationPath = destinationPath[1:] } } var desBase, desFilename = pathman.SplitPath(destinationPath) if desFilename == "" { res.Status("The destination directory/file should be specified.", 404) return } var fs = filesystem.GetFs(outapi.NewSwiftio(outapi.DefaultConnector, pathDetail[1])) if fs == nil { res.Status("Internal Error: the FS pool is full.", 500) } defer fs.Release() var srcNodeNames, desNodeNames string var err error if req.Get(HEADER_DISTABLE_PARALLEL) == "TRUE" { srcNodeNames, err = fs.Locate(base, pathDetail[3]) if err != nil { res.Status("Nonexist container or path. "+err.Error(), 404) return } desNodeNames, err = fs.Locate(desBase, destinationSC) } else { var wg sync.WaitGroup var lock sync.Mutex wg.Add(2) go (func() { defer wg.Done() var err2 error srcNodeNames, err2 = fs.Locate(base, pathDetail[3]) if err2 != nil { lock.Lock() if err == nil { err = err2 } lock.Unlock() } })() go (func() { defer wg.Done() var err2 error desNodeNames, err = fs.Locate(desBase, destinationSC) if err2 != nil { lock.Lock() if err == nil { err = err2 } lock.Unlock() } })() wg.Wait() } if err != nil { res.Status("Nonexist container or path. "+err.Error(), 404) return } var byForce = req.Get(HEADER_MOVE_BY_FORCE) == "TRUE" if req.Get(HEADER_DISTABLE_PARALLEL) == "TRUE" { err = fs.MvX(filename, srcNodeNames, desFilename, desNodeNames, byForce) } else { err = fs.MvXParalleled(filename, srcNodeNames, desFilename, desNodeNames, byForce) } if !egg.Nil(err) { if egg.In(err, exception.EX_FILE_NOT_EXIST) { res.Status("Not Found", 404) return } if egg.In(err, exception.EX_FOLDER_ALREADY_EXIST) { res.Status("The destination has already existed.", 202) return } res.Status("Internal error: "+err.Error(), 500) return } //============================================= if startTime > 0 { res.Set("Time-Consumed", strconv.FormatInt(time.Now().UnixNano()-startTime, 10)) } //============================================= res.SendCode(201) }