func (nd *Node) Rename(newName string) error { if nd.Name() == newName { return nil } nd.name = newName nd.mimeType = util.MimeType(nd.name) return nd.save() }
func (ng *NodeGraph) NewNodeWithNodeInfo(info NodeInfo) (*Node, error) { node := ng.NodeWithNodeInfo(info) node.Id = uuid.New() if info.Type != "" { node.mimeType = info.Type } else { node.mimeType = util.MimeType(info.Name) } return node, ng.AddNode(ng.NodeWithId(info.ParentId), node) }
func (ng *NodeGraph) NewNode(name, parentId string) (*Node, error) { node := new(Node) node.parentId = parentId node.Id = uuid.New() node.mTime = time.Now() node.name = name node.graph = ng node.mimeType = util.MimeType(name) return node, ng.AddNode(ng.NodeWithId(parentId), node) }
// POST v1/node/{parentId} // body -> {nodeInfo} // returns -> {nodeInfo} func (restApi OlympusApi) CreateNode(writer http.ResponseWriter, req *http.Request) { parent := restApi.graph.NodeWithId(paramFromRequest("parentId", req)) if !parent.Exists() { writeNodeNotFoundError(parent.Id, writer) return } var nodeInfo graph.NodeInfo defer req.Body.Close() decoder := decoderFromHeader(req.Body, req.Header) if err := decoder.Decode(&nodeInfo); err != nil { writer.WriteHeader(http.StatusBadRequest) writer.Write([]byte(err.Error())) return } else if node := restApi.graph.NodeWithName(parent.Id, nodeInfo.Name); node != nil && node.Exists() { http.Error(writer, fmt.Sprintf("Node exists, call /v1/touch/%s/ to update this object", node.Id), http.StatusBadRequest) } else { nodeInfo.ParentId = parent.Id nodeInfo.MTime = time.Now() if nodeInfo.Type == "" { nodeInfo.Type = util.MimeType(nodeInfo.Name) } if newNode, err := restApi.graph.NewNodeWithNodeInfo(nodeInfo); err != nil { http.Error(writer, err.Error(), http.StatusBadRequest) } else { encoder := encoderFromHeader(writer, req.Header) writer.WriteHeader(http.StatusCreated) nodeInfo = newNode.NodeInfo() encoder.Encode(nodeInfo) } } }
func (manager *Manager) UploadFile(parentId, localPath string, callback ProgressCallback) (*graph.Node, error) { errorFmt := func(err error) error { return fmt.Errorf("Error uploading file: %s", err.Error()) } if fi, err := os.Stat(localPath); err != nil { return nil, errorFmt(err) } else if fi.IsDir() { return nil, errors.New("Cannot upload a directory") } else { nodeInfo := graph.NodeInfo{ Name: filepath.Base(fi.Name()), Size: fi.Size(), Mode: 0700, MTime: time.Now(), ParentId: parentId, Type: util.MimeType(fi.Name()), } if newNode, err := manager.api.CreateNode(nodeInfo); err != nil { return nil, errorFmt(err) } else if localFile, err := os.Open(localPath); err != nil { return nil, errorFmt(err) } else { defer localFile.Close() errChan := make(chan error) uploadChan := make(chan heap, 5) defer close(uploadChan) var wg sync.WaitGroup numBlocks := int(fi.Size() / graph.BLOCK_SIZE) if fi.Size()%graph.BLOCK_SIZE > 0 { numBlocks++ } wg.Add(numBlocks) var uploadedBytes int64 for i := 0; i < 5; i++ { // TODO: min(numblocks, 5) go func() { for h := range uploadChan { payloadSize := int64(len(h.data)) rd := bytes.NewBuffer(h.data) hash := graph.Hash(h.data) if err = manager.api.WriteBlock(newNode.Id, h.offset, hash, rd); err != nil { errChan <- err } uploadedBytes += payloadSize callback(fi.Size(), uploadedBytes) wg.Done() } }() } errChecker := func() error { select { case err := <-errChan: return errorFmt(err) default: return nil } } var offset int64 for offset = 0; offset < fi.Size(); offset += graph.BLOCK_SIZE { buf := make([]byte, min(fi.Size()-offset, graph.BLOCK_SIZE)) if _, err = localFile.ReadAt(buf, offset); err != nil { return nil, errorFmt(err) } uploadChan <- heap{offset, buf} if err := errChecker(); err != nil { return nil, errorFmt(err) } } if err := errChecker(); err != nil { return nil, errorFmt(err) } wg.Wait() return manager.graph.NodeWithNodeInfo(newNode), err } } }