diff --git a/weed/command/filer_copy.go b/weed/command/filer_copy.go index a61118bbf..8d6b84ff2 100644 --- a/weed/command/filer_copy.go +++ b/weed/command/filer_copy.go @@ -174,7 +174,7 @@ func uploadFileAsOne(filerUrl string, urlFolder string, f *os.File, fi os.FileIn fmt.Printf("uploaded %s to %s\n", f.Name(), targetUrl) if err = filer_operation.RegisterFile(filerUrl, filepath.Join(urlFolder, f.Name()), assignResult.Fid, fi.Size(), - os.Getuid(), os.Getgid(), copy.secret); err != nil { + mimeType, os.Getuid(), os.Getgid(), copy.secret); err != nil { fmt.Printf("Failed to register file %s on %s: %v\n", f.Name(), filerUrl, err) return false } @@ -185,6 +185,8 @@ func uploadFileAsOne(filerUrl string, urlFolder string, f *os.File, fi os.FileIn func uploadFileInChunks(filerUrl string, urlFolder string, f *os.File, fi os.FileInfo, chunkCount int, chunkSize int64) bool { + mimeType := detectMimeType(f) + var chunks []*filer_pb.FileChunk for i := int64(0); i < int64(chunkCount); i++ { @@ -235,6 +237,7 @@ func uploadFileInChunks(filerUrl string, urlFolder string, f *os.File, fi os.Fil Uid: uint32(os.Getuid()), FileSize: uint64(fi.Size()), FileMode: uint32(fi.Mode()), + Mime: mimeType, }, Chunks: chunks, }, diff --git a/weed/filer2/abstract_sql/abstract_sql_store.go b/weed/filer2/abstract_sql/abstract_sql_store.go index aa3b82c5b..82ef571b6 100644 --- a/weed/filer2/abstract_sql/abstract_sql_store.go +++ b/weed/filer2/abstract_sql/abstract_sql_store.go @@ -77,26 +77,21 @@ func (store *AbstractSqlStore) FindEntry(fullpath filer2.FullPath) (*filer2.Entr return entry, nil } -func (store *AbstractSqlStore) DeleteEntry(fullpath filer2.FullPath) (*filer2.Entry, error) { - - entry, err := store.FindEntry(fullpath) - if err != nil { - return nil, nil - } +func (store *AbstractSqlStore) DeleteEntry(fullpath filer2.FullPath) (error) { dir, name := fullpath.DirAndName() res, err := store.DB.Exec(store.SqlDelete, hashToLong(dir), name, dir) if err != nil { - return nil, fmt.Errorf("delete %s: %s", fullpath, err) + return fmt.Errorf("delete %s: %s", fullpath, err) } _, err = res.RowsAffected() if err != nil { - return nil, fmt.Errorf("delete %s but no rows affected: %s", fullpath, err) + return fmt.Errorf("delete %s but no rows affected: %s", fullpath, err) } - return entry, nil + return nil } func (store *AbstractSqlStore) ListDirectoryEntries(fullpath filer2.FullPath, startFileName string, inclusive bool, limit int) (entries []*filer2.Entry, err error) { diff --git a/weed/filer2/cassandra/cassandra_store.go b/weed/filer2/cassandra/cassandra_store.go index a1e63b87d..ebbaedc1d 100644 --- a/weed/filer2/cassandra/cassandra_store.go +++ b/weed/filer2/cassandra/cassandra_store.go @@ -88,22 +88,17 @@ func (store *CassandraStore) FindEntry(fullpath filer2.FullPath) (entry *filer2. return entry, nil } -func (store *CassandraStore) DeleteEntry(fullpath filer2.FullPath) (entry *filer2.Entry, err error) { - - entry, err = store.FindEntry(fullpath) - if err != nil { - return nil, nil - } +func (store *CassandraStore) DeleteEntry(fullpath filer2.FullPath) error { dir, name := fullpath.DirAndName() if err := store.session.Query( "DELETE FROM filemeta WHERE directory=? AND name=?", dir, name).Exec(); err != nil { - return entry, fmt.Errorf("delete %s : %v", entry.FullPath, err) + return fmt.Errorf("delete %s : %v", fullpath, err) } - return entry, nil + return nil } func (store *CassandraStore) ListDirectoryEntries(fullpath filer2.FullPath, startFileName string, inclusive bool, diff --git a/weed/filer2/entry.go b/weed/filer2/entry.go index cf7ad08aa..a2f8b91ef 100644 --- a/weed/filer2/entry.go +++ b/weed/filer2/entry.go @@ -13,6 +13,7 @@ type Attr struct { Mode os.FileMode // file mode Uid uint32 // owner uid Gid uint32 // group gid + Mime string } func (attr Attr) IsDirectory() bool { diff --git a/weed/filer2/entry_codec.go b/weed/filer2/entry_codec.go index 8019b2193..7585203e9 100644 --- a/weed/filer2/entry_codec.go +++ b/weed/filer2/entry_codec.go @@ -17,6 +17,7 @@ func (entry *Entry) EncodeAttributesAndChunks() ([]byte, error) { FileMode: uint32(entry.Attr.Mode), Uid: entry.Uid, Gid: entry.Gid, + Mime: entry.Mime, }, Chunks: entry.Chunks, } @@ -36,6 +37,7 @@ func (entry *Entry) DecodeAttributesAndChunks(blob []byte) error { entry.Attr.Mode = os.FileMode(message.Attributes.FileMode) entry.Attr.Uid = message.Attributes.Uid entry.Attr.Gid = message.Attributes.Gid + entry.Attr.Mime = message.Attributes.Mime entry.Chunks = message.Chunks diff --git a/weed/filer2/filer.go b/weed/filer2/filer.go index f182adb13..0b4113c38 100644 --- a/weed/filer2/filer.go +++ b/weed/filer2/filer.go @@ -9,6 +9,7 @@ import ( "path/filepath" "strings" "time" + "github.com/chrislusf/seaweedfs/weed/operation" ) type Filer struct { @@ -101,6 +102,10 @@ func (f *Filer) CreateEntry(entry *Entry) error { } */ + if oldEntry, err := f.FindEntry(entry.FullPath); err == nil { + f.deleteChunks(oldEntry) + } + if err := f.store.InsertEntry(entry); err != nil { return fmt.Errorf("insert entry %s: %v", entry.FullPath, err) } @@ -116,26 +121,30 @@ func (f *Filer) FindEntry(p FullPath) (entry *Entry, err error) { return f.store.FindEntry(p) } -func (f *Filer) DeleteEntry(p FullPath) (fileEntry *Entry, err error) { +func (f *Filer) DeleteEntryMetaAndData(p FullPath) (err error) { entry, err := f.FindEntry(p) if err != nil { - return nil, err + return err } + if entry.IsDirectory() { entries, err := f.ListDirectoryEntries(p, "", false, 1) if err != nil { - return nil, fmt.Errorf("list folder %s: %v", p, err) + return fmt.Errorf("list folder %s: %v", p, err) } if len(entries) > 0 { - return nil, fmt.Errorf("folder %s is not empty", p) + return fmt.Errorf("folder %s is not empty", p) } } + + f.deleteChunks(entry) + return f.store.DeleteEntry(p) } func (f *Filer) ListDirectoryEntries(p FullPath, startFileName string, inclusive bool, limit int) ([]*Entry, error) { if strings.HasSuffix(string(p), "/") && len(p) > 1 { - p = p[0 : len(p)-1] + p = p[0: len(p)-1] } return f.store.ListDirectoryEntries(p, startFileName, inclusive, limit) } @@ -164,3 +173,17 @@ func (f *Filer) cacheSetDirectory(dirpath string, dirEntry *Entry, level int) { f.directoryCache.Set(dirpath, dirEntry, time.Duration(minutes)*time.Minute) } + +func (f *Filer) deleteChunks(entry *Entry) { + if f.master == "" { + return + } + if entry == nil { + return + } + for _, chunk := range entry.Chunks { + if err := operation.DeleteFile(f.master, chunk.FileId, ""); err != nil { + glog.V(0).Infof("deleting file %s: %v", chunk.FileId, err) + } + } +} diff --git a/weed/filer2/filerstore.go b/weed/filer2/filerstore.go index a5cd3352e..80822559b 100644 --- a/weed/filer2/filerstore.go +++ b/weed/filer2/filerstore.go @@ -11,7 +11,7 @@ type FilerStore interface { InsertEntry(*Entry) error UpdateEntry(*Entry) (err error) FindEntry(FullPath) (entry *Entry, err error) - DeleteEntry(FullPath) (fileEntry *Entry, err error) + DeleteEntry(FullPath) (err error) ListDirectoryEntries(dirPath FullPath, startFileName string, inclusive bool, limit int) ([]*Entry, error) } diff --git a/weed/filer2/leveldb/leveldb_store.go b/weed/filer2/leveldb/leveldb_store.go index a3125e923..58787714d 100644 --- a/weed/filer2/leveldb/leveldb_store.go +++ b/weed/filer2/leveldb/leveldb_store.go @@ -93,20 +93,15 @@ func (store *LevelDBStore) FindEntry(fullpath filer2.FullPath) (entry *filer2.En return entry, nil } -func (store *LevelDBStore) DeleteEntry(fullpath filer2.FullPath) (entry *filer2.Entry, err error) { +func (store *LevelDBStore) DeleteEntry(fullpath filer2.FullPath) (err error) { key := genKey(fullpath.DirAndName()) - entry, err = store.FindEntry(fullpath) - if err != nil { - return nil, nil - } - err = store.db.Delete(key, nil) if err != nil { - return entry, fmt.Errorf("delete %s : %v", entry.FullPath, err) + return fmt.Errorf("delete %s : %v", fullpath, err) } - return entry, nil + return nil } func (store *LevelDBStore) ListDirectoryEntries(fullpath filer2.FullPath, startFileName string, inclusive bool, diff --git a/weed/filer2/memdb/memdb_store.go b/weed/filer2/memdb/memdb_store.go index 098ed5dce..a8ef5cb39 100644 --- a/weed/filer2/memdb/memdb_store.go +++ b/weed/filer2/memdb/memdb_store.go @@ -56,13 +56,9 @@ func (store *MemDbStore) FindEntry(fullpath filer2.FullPath) (entry *filer2.Entr return entry, nil } -func (store *MemDbStore) DeleteEntry(fullpath filer2.FullPath) (entry *filer2.Entry, err error) { - item := store.tree.Delete(entryItem{&filer2.Entry{FullPath: fullpath}}) - if item == nil { - return nil, nil - } - entry = item.(entryItem).Entry - return entry, nil +func (store *MemDbStore) DeleteEntry(fullpath filer2.FullPath) (err error) { + store.tree.Delete(entryItem{&filer2.Entry{FullPath: fullpath}}) + return nil } func (store *MemDbStore) ListDirectoryEntries(fullpath filer2.FullPath, startFileName string, inclusive bool, limit int) (entries []*filer2.Entry, err error) { diff --git a/weed/filer2/memdb/memdb_store_test.go b/weed/filer2/memdb/memdb_store_test.go index bd1cdfdc0..5265ed248 100644 --- a/weed/filer2/memdb/memdb_store_test.go +++ b/weed/filer2/memdb/memdb_store_test.go @@ -134,7 +134,7 @@ func TestCreateFileAndList(t *testing.T) { } // delete file and count - filer.DeleteEntry(file3Path) + filer.DeleteEntryMetaAndData(file3Path) entries, _ = filer.ListDirectoryEntries(filer2.FullPath("/home/chris/this/is"), "", false, 100) if len(entries) != 1 { t.Errorf("list entries count: %v", len(entries)) diff --git a/weed/filer2/redis/redis_store.go b/weed/filer2/redis/redis_store.go index 5d1f51812..79a25096a 100644 --- a/weed/filer2/redis/redis_store.go +++ b/weed/filer2/redis/redis_store.go @@ -94,28 +94,23 @@ func (store *RedisStore) FindEntry(fullpath filer2.FullPath) (entry *filer2.Entr return entry, nil } -func (store *RedisStore) DeleteEntry(fullpath filer2.FullPath) (entry *filer2.Entry, err error) { - - entry, err = store.FindEntry(fullpath) - if err != nil { - return nil, nil - } +func (store *RedisStore) DeleteEntry(fullpath filer2.FullPath) (err error) { _, err = store.Client.Del(string(fullpath)).Result() if err != nil { - return entry, fmt.Errorf("delete %s : %v", entry.FullPath, err) + return fmt.Errorf("delete %s : %v", fullpath, err) } dir, name := fullpath.DirAndName() if name != "" { _, err = store.Client.SRem(genDirectoryListKey(dir), name).Result() if err != nil { - return nil, fmt.Errorf("delete %s in parent dir: %v", entry.FullPath, err) + return fmt.Errorf("delete %s in parent dir: %v", fullpath, err) } } - return entry, nil + return nil } func (store *RedisStore) ListDirectoryEntries(fullpath filer2.FullPath, startFileName string, inclusive bool, diff --git a/weed/filesys/filehandle.go b/weed/filesys/filehandle.go index 9fa971236..32e4622d0 100644 --- a/weed/filesys/filehandle.go +++ b/weed/filesys/filehandle.go @@ -11,6 +11,7 @@ import ( "github.com/chrislusf/seaweedfs/weed/util" "strings" "sync" + "net/http" ) type FileHandle struct { @@ -18,10 +19,6 @@ type FileHandle struct { dirtyPages *ContinuousDirtyPages dirtyMetadata bool - cachePath string - - handle uint64 - f *File RequestId fuse.RequestID // unique ID for request NodeId fuse.NodeID // file or directory the request is about @@ -135,6 +132,11 @@ func (fh *FileHandle) Write(ctx context.Context, req *fuse.WriteRequest, resp *f resp.Size = len(req.Data) + if req.Offset == 0 { + fh.f.attributes.Mime = http.DetectContentType(req.Data) + fh.dirtyMetadata = true + } + if chunk != nil { fh.f.Chunks = append(fh.f.Chunks, chunk) glog.V(1).Infof("uploaded %s/%s to %s [%d,%d)", fh.f.dir.Path, fh.f.Name, chunk.FileId, chunk.Offset, chunk.Offset+int64(chunk.Size)) diff --git a/weed/operation/filer/register.go b/weed/operation/filer/register.go index 108d93321..655fee1ff 100644 --- a/weed/operation/filer/register.go +++ b/weed/operation/filer/register.go @@ -17,7 +17,7 @@ type SubmitResult struct { Error string `json:"error,omitempty"` } -func RegisterFile(filer string, path string, fileId string, fileSize int64, uid, gid int, secret security.Secret) error { +func RegisterFile(filer string, path string, fileId string, fileSize int64, mime string, uid, gid int, secret security.Secret) error { // TODO: jwt need to be used _ = security.GenJwt(secret, fileId) @@ -27,6 +27,7 @@ func RegisterFile(filer string, path string, fileId string, fileSize int64, uid, values.Add("fileSize", strconv.FormatInt(fileSize, 10)) values.Add("uid", strconv.Itoa(uid)) values.Add("gid", strconv.Itoa(gid)) + values.Add("mime", mime) _, err := util.Post("http://"+filer+"/admin/register", values) if err != nil { return fmt.Errorf("Failed to register path %s on filer %s to file id %s : %v", path, filer, fileId, err) diff --git a/weed/pb/filer.proto b/weed/pb/filer.proto index 98c39d4b2..0f29ad02c 100644 --- a/weed/pb/filer.proto +++ b/weed/pb/filer.proto @@ -72,6 +72,7 @@ message FuseAttributes { uint32 uid = 4; uint32 gid = 5; int64 crtime = 6; + string mime = 7; } message GetEntryAttributesRequest { diff --git a/weed/pb/filer_pb/filer.pb.go b/weed/pb/filer_pb/filer.pb.go index 0473e77c0..74e43f519 100644 --- a/weed/pb/filer_pb/filer.pb.go +++ b/weed/pb/filer_pb/filer.pb.go @@ -214,6 +214,7 @@ type FuseAttributes struct { Uid uint32 `protobuf:"varint,4,opt,name=uid" json:"uid,omitempty"` Gid uint32 `protobuf:"varint,5,opt,name=gid" json:"gid,omitempty"` Crtime int64 `protobuf:"varint,6,opt,name=crtime" json:"crtime,omitempty"` + Mime string `protobuf:"bytes,7,opt,name=mime" json:"mime,omitempty"` } func (m *FuseAttributes) Reset() { *m = FuseAttributes{} } @@ -263,6 +264,13 @@ func (m *FuseAttributes) GetCrtime() int64 { return 0 } +func (m *FuseAttributes) GetMime() string { + if m != nil { + return m.Mime + } + return "" +} + type GetEntryAttributesRequest struct { Name string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"` ParentDir string `protobuf:"bytes,2,opt,name=parent_dir,json=parentDir" json:"parent_dir,omitempty"` @@ -931,62 +939,62 @@ var _SeaweedFiler_serviceDesc = grpc.ServiceDesc{ func init() { proto.RegisterFile("filer.proto", fileDescriptor0) } var fileDescriptor0 = []byte{ - // 899 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xb4, 0x56, 0xdd, 0x6e, 0xdc, 0x44, - 0x14, 0x8e, 0xd7, 0xf1, 0x26, 0x3e, 0xbb, 0xe1, 0x67, 0x36, 0x2d, 0x66, 0x9b, 0x54, 0x61, 0xa0, - 0xa8, 0x15, 0x52, 0x14, 0x05, 0x2e, 0x2a, 0x10, 0x12, 0x55, 0x53, 0xaa, 0x4a, 0xa9, 0x2a, 0xb9, - 0x04, 0x89, 0xab, 0x95, 0x63, 0x9f, 0x5d, 0x46, 0xf1, 0xda, 0xc6, 0x33, 0x0e, 0x0a, 0xb7, 0xbc, - 0x06, 0xb7, 0xbc, 0x01, 0x6f, 0xc0, 0x8b, 0xa1, 0xf9, 0xb1, 0x3d, 0x8e, 0xbd, 0xfd, 0xb9, 0xe0, - 0x6e, 0xe6, 0xfc, 0x7c, 0xe7, 0x3b, 0x33, 0x67, 0x3e, 0x1b, 0x26, 0x4b, 0x96, 0x62, 0x79, 0x5c, - 0x94, 0xb9, 0xc8, 0xc9, 0xae, 0xda, 0x2c, 0x8a, 0x4b, 0xfa, 0x0a, 0xee, 0x9d, 0xe7, 0xf9, 0x55, - 0x55, 0x9c, 0xb1, 0x12, 0x63, 0x91, 0x97, 0x37, 0xcf, 0x32, 0x51, 0xde, 0x84, 0xf8, 0x5b, 0x85, - 0x5c, 0x90, 0x03, 0xf0, 0x93, 0xda, 0x11, 0x38, 0x47, 0xce, 0x43, 0x3f, 0x6c, 0x0d, 0x84, 0xc0, - 0x76, 0x16, 0xad, 0x31, 0x18, 0x29, 0x87, 0x5a, 0xd3, 0x67, 0x70, 0x30, 0x0c, 0xc8, 0x8b, 0x3c, - 0xe3, 0x48, 0x1e, 0x80, 0x87, 0xd2, 0xa0, 0xd0, 0x26, 0xa7, 0x1f, 0x1e, 0xd7, 0x54, 0x8e, 0x75, - 0x9c, 0xf6, 0xd2, 0x53, 0x20, 0xe7, 0x8c, 0x0b, 0x69, 0x63, 0xc8, 0xdf, 0x89, 0x0e, 0xfd, 0x01, - 0x66, 0x9d, 0x1c, 0x53, 0xf1, 0x11, 0xec, 0xa0, 0x36, 0x05, 0xce, 0x91, 0x3b, 0x54, 0xb3, 0xf6, - 0xd3, 0xbf, 0x1d, 0xf0, 0x94, 0xa9, 0x69, 0xcd, 0x69, 0x5b, 0x23, 0x9f, 0xc1, 0x94, 0xf1, 0x45, - 0x4b, 0x40, 0xb6, 0xbd, 0x1b, 0x4e, 0x18, 0x6f, 0x5a, 0x25, 0x5f, 0xc1, 0x38, 0xfe, 0xb5, 0xca, - 0xae, 0x78, 0xe0, 0xaa, 0x52, 0xb3, 0xb6, 0xd4, 0x8f, 0x2c, 0xc5, 0xa7, 0xd2, 0x17, 0x9a, 0x10, - 0xf2, 0x18, 0x20, 0x12, 0xa2, 0x64, 0x97, 0x95, 0x40, 0x1e, 0x6c, 0xab, 0xf3, 0x08, 0xac, 0x84, - 0x8a, 0xe3, 0x93, 0xc6, 0x1f, 0x5a, 0xb1, 0x74, 0x09, 0x7e, 0x03, 0x47, 0x3e, 0x81, 0x1d, 0x99, - 0xb3, 0x60, 0x89, 0x61, 0x3b, 0x96, 0xdb, 0x17, 0x09, 0xb9, 0x0b, 0xe3, 0x7c, 0xb9, 0xe4, 0x28, - 0x14, 0x53, 0x37, 0x34, 0x3b, 0xd9, 0x1b, 0x67, 0x7f, 0x60, 0xe0, 0x1e, 0x39, 0x0f, 0xb7, 0x43, - 0xb5, 0x26, 0xfb, 0xe0, 0xad, 0x05, 0x5b, 0xa3, 0xa2, 0xe1, 0x86, 0x7a, 0x43, 0xff, 0x72, 0xe0, - 0x83, 0x2e, 0x0d, 0x72, 0x0f, 0x7c, 0x55, 0x4d, 0x21, 0x38, 0x0a, 0x41, 0x4d, 0xd3, 0xeb, 0x0e, - 0xca, 0xc8, 0x42, 0x69, 0x52, 0xd6, 0x79, 0xa2, 0x8b, 0xee, 0xe9, 0x94, 0x97, 0x79, 0x82, 0xe4, - 0x23, 0x70, 0x2b, 0x96, 0xa8, 0xb2, 0x7b, 0xa1, 0x5c, 0x4a, 0xcb, 0x8a, 0x25, 0x81, 0xa7, 0x2d, - 0x2b, 0xa6, 0x1a, 0x89, 0x4b, 0x85, 0x3b, 0xd6, 0x8d, 0xe8, 0x1d, 0x5d, 0xc1, 0xa7, 0xcf, 0x51, - 0xdd, 0xf7, 0x8d, 0x75, 0x50, 0x66, 0x56, 0x86, 0x6e, 0xf0, 0x10, 0xa0, 0x88, 0x4a, 0xcc, 0x84, - 0xbc, 0x45, 0x33, 0xb6, 0xbe, 0xb6, 0x9c, 0xb1, 0xd2, 0x3e, 0x49, 0xd7, 0x3e, 0x49, 0xfa, 0xa7, - 0x03, 0xf3, 0xa1, 0x4a, 0x66, 0xc2, 0xba, 0x17, 0xe9, 0xbc, 0xfb, 0x45, 0x5a, 0xf3, 0x32, 0x7a, - 0xeb, 0xbc, 0xd0, 0x13, 0xb8, 0xf3, 0x1c, 0x85, 0xb2, 0xe7, 0x99, 0xc0, 0x4c, 0xd4, 0xad, 0x6e, - 0x9a, 0x00, 0x7a, 0x0a, 0x77, 0x6f, 0x67, 0x18, 0xca, 0x01, 0xec, 0xc4, 0xda, 0xa4, 0x52, 0xa6, - 0x61, 0xbd, 0xa5, 0xbf, 0x00, 0x79, 0x5a, 0x62, 0x24, 0xf0, 0x3d, 0x84, 0xa0, 0x79, 0xd4, 0xa3, - 0x37, 0x3e, 0xea, 0x3b, 0x30, 0xeb, 0x40, 0x6b, 0x2e, 0xb2, 0xe2, 0x45, 0x91, 0xfc, 0x5f, 0x15, - 0x3b, 0xd0, 0xa6, 0x22, 0x03, 0x72, 0x86, 0x29, 0xbe, 0x57, 0xc5, 0x01, 0xb1, 0xeb, 0x29, 0x82, - 0xdb, 0x53, 0x04, 0xc9, 0xa0, 0x53, 0xca, 0x30, 0x58, 0xc3, 0xec, 0x09, 0xe7, 0x6c, 0x95, 0xfd, - 0x9c, 0xa7, 0xd5, 0x1a, 0x6b, 0x0a, 0xfb, 0xe0, 0xc5, 0x79, 0x65, 0x2e, 0xc5, 0x0b, 0xf5, 0x86, - 0xdc, 0x07, 0x88, 0xf3, 0x34, 0xc5, 0x58, 0xb0, 0x3c, 0x33, 0x04, 0x2c, 0x0b, 0x39, 0x82, 0x49, - 0x89, 0x45, 0xca, 0xe2, 0x48, 0x05, 0xe8, 0xd9, 0xb5, 0x4d, 0xf4, 0x1a, 0xf6, 0xbb, 0xe5, 0xcc, - 0x18, 0x6c, 0xd4, 0x0e, 0xf9, 0x2c, 0xcb, 0xd4, 0xd4, 0x92, 0x4b, 0xf5, 0x76, 0xaa, 0xcb, 0x94, - 0xc5, 0x0b, 0xe9, 0x70, 0xcd, 0xdb, 0x51, 0x96, 0x8b, 0x32, 0x6d, 0x99, 0x6f, 0x5b, 0xcc, 0xe9, - 0x37, 0x30, 0xd3, 0x5f, 0x83, 0x6e, 0x9b, 0x87, 0x00, 0xd7, 0xca, 0xb0, 0x60, 0x89, 0x56, 0x65, - 0x3f, 0xf4, 0xb5, 0xe5, 0x45, 0xc2, 0xe9, 0xf7, 0xe0, 0x9f, 0xe7, 0x9a, 0x39, 0x27, 0x27, 0xe0, - 0xa7, 0xf5, 0xc6, 0x08, 0x38, 0x69, 0x6f, 0xbb, 0x8e, 0x0b, 0xdb, 0x20, 0xfa, 0x1d, 0xec, 0xd6, - 0xe6, 0xba, 0x0f, 0x67, 0x53, 0x1f, 0xa3, 0x5b, 0x7d, 0xd0, 0x7f, 0x1d, 0xd8, 0xef, 0x52, 0x36, - 0x47, 0x75, 0x01, 0x7b, 0x4d, 0x89, 0xc5, 0x3a, 0x2a, 0x0c, 0x97, 0x13, 0x9b, 0x4b, 0x3f, 0xad, - 0x21, 0xc8, 0x5f, 0x46, 0x85, 0x1e, 0x81, 0x69, 0x6a, 0x99, 0xe6, 0x3f, 0xc1, 0xc7, 0xbd, 0x10, - 0xc9, 0xfa, 0x0a, 0xeb, 0x19, 0x94, 0x4b, 0xf2, 0x08, 0xbc, 0xeb, 0x28, 0xad, 0xd0, 0xcc, 0xfb, - 0xac, 0x7f, 0x02, 0x3c, 0xd4, 0x11, 0xdf, 0x8e, 0x1e, 0x3b, 0xa7, 0xff, 0x78, 0x30, 0x7d, 0x8d, - 0xd1, 0xef, 0x88, 0x89, 0x7c, 0xfd, 0x25, 0x59, 0xd5, 0x5d, 0x75, 0x3f, 0xcb, 0xe4, 0xc1, 0x6d, - 0xfa, 0x83, 0xff, 0x01, 0xf3, 0x2f, 0xdf, 0x16, 0x66, 0xc6, 0x7a, 0x8b, 0x9c, 0xc3, 0xc4, 0xfa, - 0x08, 0x93, 0x03, 0x2b, 0xb1, 0xf7, 0x3d, 0x9f, 0x1f, 0x6e, 0xf0, 0x36, 0x68, 0x11, 0x90, 0xbe, - 0xee, 0x92, 0xcf, 0xdb, 0xb4, 0x8d, 0xfa, 0x3f, 0xff, 0xe2, 0xcd, 0x41, 0x36, 0x61, 0x4b, 0x94, - 0x6c, 0xc2, 0x7d, 0x19, 0xb4, 0x09, 0x0f, 0x29, 0x99, 0x42, 0xb3, 0x04, 0xc7, 0x46, 0xeb, 0x4b, - 0x9c, 0x8d, 0x36, 0xa4, 0x52, 0x0a, 0xcd, 0x12, 0x0f, 0x1b, 0xad, 0x2f, 0x5f, 0x36, 0xda, 0x90, - 0xe2, 0x6c, 0x91, 0x57, 0x30, 0xb5, 0x45, 0x80, 0x58, 0x09, 0x03, 0x5a, 0x34, 0xbf, 0xbf, 0xc9, - 0x6d, 0x03, 0xda, 0x33, 0x6f, 0x03, 0x0e, 0xbc, 0x7a, 0x1b, 0x70, 0xe8, 0xa9, 0xd0, 0xad, 0xcb, - 0xb1, 0xfa, 0x3d, 0xfd, 0xfa, 0xbf, 0x00, 0x00, 0x00, 0xff, 0xff, 0x83, 0x92, 0xde, 0x64, 0xad, - 0x0a, 0x00, 0x00, + // 906 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xb4, 0x56, 0x5b, 0x6f, 0xdc, 0x44, + 0x14, 0x8e, 0xd7, 0xd9, 0x4d, 0x7c, 0x76, 0xc3, 0x65, 0x36, 0x2d, 0x66, 0x9b, 0x54, 0x61, 0xa0, + 0xa8, 0x15, 0x52, 0x14, 0x05, 0x1e, 0x2a, 0x10, 0x12, 0x55, 0x53, 0xaa, 0x4a, 0xa9, 0x2a, 0xb9, + 0x04, 0x89, 0xa7, 0x95, 0x63, 0x9f, 0x5d, 0x46, 0xf1, 0x0d, 0xcf, 0x38, 0x28, 0xbc, 0xf2, 0x5b, + 0x78, 0xe7, 0x81, 0x7f, 0xc0, 0x1f, 0x43, 0x73, 0xb1, 0x3d, 0x8e, 0xbd, 0xbd, 0x3c, 0xf0, 0x36, + 0x73, 0x2e, 0xdf, 0xf9, 0xce, 0xcc, 0x99, 0xcf, 0x86, 0xe9, 0x8a, 0x25, 0x58, 0x1e, 0x17, 0x65, + 0x2e, 0x72, 0xb2, 0xab, 0x36, 0xcb, 0xe2, 0x92, 0xbe, 0x82, 0x7b, 0xe7, 0x79, 0x7e, 0x55, 0x15, + 0x67, 0xac, 0xc4, 0x48, 0xe4, 0xe5, 0xcd, 0xb3, 0x4c, 0x94, 0x37, 0x01, 0xfe, 0x56, 0x21, 0x17, + 0xe4, 0x00, 0xbc, 0xb8, 0x76, 0xf8, 0xce, 0x91, 0xf3, 0xd0, 0x0b, 0x5a, 0x03, 0x21, 0xb0, 0x9d, + 0x85, 0x29, 0xfa, 0x23, 0xe5, 0x50, 0x6b, 0xfa, 0x0c, 0x0e, 0x86, 0x01, 0x79, 0x91, 0x67, 0x1c, + 0xc9, 0x03, 0x18, 0xa3, 0x34, 0x28, 0xb4, 0xe9, 0xe9, 0x87, 0xc7, 0x35, 0x95, 0x63, 0x1d, 0xa7, + 0xbd, 0xf4, 0x14, 0xc8, 0x39, 0xe3, 0x42, 0xda, 0x18, 0xf2, 0x77, 0xa2, 0x43, 0x7f, 0x80, 0x79, + 0x27, 0xc7, 0x54, 0x7c, 0x04, 0x3b, 0xa8, 0x4d, 0xbe, 0x73, 0xe4, 0x0e, 0xd5, 0xac, 0xfd, 0xf4, + 0x2f, 0x07, 0xc6, 0xca, 0xd4, 0xb4, 0xe6, 0xb4, 0xad, 0x91, 0xcf, 0x60, 0xc6, 0xf8, 0xb2, 0x25, + 0x20, 0xdb, 0xde, 0x0d, 0xa6, 0x8c, 0x37, 0xad, 0x92, 0xaf, 0x60, 0x12, 0xfd, 0x5a, 0x65, 0x57, + 0xdc, 0x77, 0x55, 0xa9, 0x79, 0x5b, 0xea, 0x47, 0x96, 0xe0, 0x53, 0xe9, 0x0b, 0x4c, 0x08, 0x79, + 0x0c, 0x10, 0x0a, 0x51, 0xb2, 0xcb, 0x4a, 0x20, 0xf7, 0xb7, 0xd5, 0x79, 0xf8, 0x56, 0x42, 0xc5, + 0xf1, 0x49, 0xe3, 0x0f, 0xac, 0x58, 0xba, 0x02, 0xaf, 0x81, 0x23, 0x9f, 0xc0, 0x8e, 0xcc, 0x59, + 0xb2, 0xd8, 0xb0, 0x9d, 0xc8, 0xed, 0x8b, 0x98, 0xdc, 0x85, 0x49, 0xbe, 0x5a, 0x71, 0x14, 0x8a, + 0xa9, 0x1b, 0x98, 0x9d, 0xec, 0x8d, 0xb3, 0x3f, 0xd0, 0x77, 0x8f, 0x9c, 0x87, 0xdb, 0x81, 0x5a, + 0x93, 0x7d, 0x18, 0xa7, 0x82, 0xa5, 0xa8, 0x68, 0xb8, 0x81, 0xde, 0xd0, 0xbf, 0x1d, 0xf8, 0xa0, + 0x4b, 0x83, 0xdc, 0x03, 0x4f, 0x55, 0x53, 0x08, 0x8e, 0x42, 0x50, 0xd3, 0xf4, 0xba, 0x83, 0x32, + 0xb2, 0x50, 0x9a, 0x94, 0x34, 0x8f, 0x75, 0xd1, 0x3d, 0x9d, 0xf2, 0x32, 0x8f, 0x91, 0x7c, 0x04, + 0x6e, 0xc5, 0x62, 0x55, 0x76, 0x2f, 0x90, 0x4b, 0x69, 0x59, 0xb3, 0xd8, 0x1f, 0x6b, 0xcb, 0x9a, + 0xa9, 0x46, 0xa2, 0x52, 0xe1, 0x4e, 0x74, 0x23, 0x7a, 0x27, 0x1b, 0x49, 0xa5, 0x75, 0x47, 0x5f, + 0x92, 0x5c, 0xd3, 0x35, 0x7c, 0xfa, 0x1c, 0xd5, 0x0c, 0xdc, 0x58, 0x87, 0x67, 0xe6, 0x67, 0xe8, + 0x56, 0x0f, 0x01, 0x8a, 0xb0, 0xc4, 0x4c, 0xc8, 0x9b, 0x35, 0xa3, 0xec, 0x69, 0xcb, 0x19, 0x2b, + 0xed, 0xd3, 0x75, 0xed, 0xd3, 0xa5, 0x7f, 0x3a, 0xb0, 0x18, 0xaa, 0x64, 0xa6, 0xae, 0x7b, 0xb9, + 0xce, 0xbb, 0x5f, 0xae, 0x35, 0x43, 0xa3, 0xb7, 0xce, 0x10, 0x3d, 0x81, 0x3b, 0xcf, 0x51, 0x28, + 0x7b, 0x9e, 0x09, 0xcc, 0x44, 0xdd, 0xea, 0xa6, 0xa9, 0xa0, 0xa7, 0x70, 0xf7, 0x76, 0x86, 0xa1, + 0xec, 0xc3, 0x4e, 0xa4, 0x4d, 0x2a, 0x65, 0x16, 0xd4, 0x5b, 0xfa, 0x0b, 0x90, 0xa7, 0x25, 0x86, + 0x02, 0xdf, 0x43, 0x1c, 0x9a, 0x87, 0x3e, 0x7a, 0xe3, 0x43, 0xbf, 0x03, 0xf3, 0x0e, 0xb4, 0xe6, + 0x22, 0x2b, 0x5e, 0x14, 0xf1, 0xff, 0x55, 0xb1, 0x03, 0x6d, 0x2a, 0x32, 0x20, 0x67, 0x98, 0xe0, + 0x7b, 0x55, 0x1c, 0x10, 0xc0, 0x9e, 0x4a, 0xb8, 0x3d, 0x95, 0x90, 0x0c, 0x3a, 0xa5, 0x0c, 0x83, + 0x14, 0xe6, 0x4f, 0x38, 0x67, 0xeb, 0xec, 0xe7, 0x3c, 0xa9, 0x52, 0xac, 0x29, 0xec, 0xc3, 0x38, + 0xca, 0x2b, 0x73, 0x29, 0xe3, 0x40, 0x6f, 0xc8, 0x7d, 0x80, 0x28, 0x4f, 0x12, 0x8c, 0x04, 0xcb, + 0x33, 0x43, 0xc0, 0xb2, 0x90, 0x23, 0x98, 0x96, 0x58, 0x24, 0x2c, 0x0a, 0x55, 0x80, 0x9e, 0x5d, + 0xdb, 0x44, 0xaf, 0x61, 0xbf, 0x5b, 0xce, 0x8c, 0xc1, 0x46, 0x3d, 0x91, 0x4f, 0xb5, 0x4c, 0x4c, + 0x2d, 0xb9, 0x54, 0x6f, 0xa7, 0xba, 0x4c, 0x58, 0xb4, 0x94, 0x0e, 0xd7, 0xbc, 0x1d, 0x65, 0xb9, + 0x28, 0x93, 0x96, 0xf9, 0xb6, 0xc5, 0x9c, 0x7e, 0x03, 0x73, 0xfd, 0x85, 0xe8, 0xb6, 0x79, 0x08, + 0x70, 0xad, 0x0c, 0x4b, 0x16, 0x6b, 0xa5, 0xf6, 0x02, 0x4f, 0x5b, 0x5e, 0xc4, 0x9c, 0x7e, 0x0f, + 0xde, 0x79, 0xae, 0x99, 0x73, 0x72, 0x02, 0x5e, 0x52, 0x6f, 0x8c, 0xa8, 0x93, 0xf6, 0xb6, 0xeb, + 0xb8, 0xa0, 0x0d, 0xa2, 0xdf, 0xc1, 0x6e, 0x6d, 0xae, 0xfb, 0x70, 0x36, 0xf5, 0x31, 0xba, 0xd5, + 0x07, 0xfd, 0xd7, 0x81, 0xfd, 0x2e, 0x65, 0x73, 0x54, 0x17, 0xb0, 0xd7, 0x94, 0x58, 0xa6, 0x61, + 0x61, 0xb8, 0x9c, 0xd8, 0x5c, 0xfa, 0x69, 0x0d, 0x41, 0xfe, 0x32, 0x2c, 0xf4, 0x08, 0xcc, 0x12, + 0xcb, 0xb4, 0xf8, 0x09, 0x3e, 0xee, 0x85, 0x48, 0xd6, 0x57, 0x58, 0xcf, 0xa0, 0x5c, 0x92, 0x47, + 0x30, 0xbe, 0x0e, 0x93, 0x0a, 0xcd, 0xbc, 0xcf, 0xfb, 0x27, 0xc0, 0x03, 0x1d, 0xf1, 0xed, 0xe8, + 0xb1, 0x73, 0xfa, 0xcf, 0x18, 0x66, 0xaf, 0x31, 0xfc, 0x1d, 0x31, 0x96, 0xaf, 0xbf, 0x24, 0xeb, + 0xba, 0xab, 0xee, 0xa7, 0x9a, 0x3c, 0xb8, 0x4d, 0x7f, 0xf0, 0xdf, 0x60, 0xf1, 0xe5, 0xdb, 0xc2, + 0xcc, 0x58, 0x6f, 0x91, 0x73, 0x98, 0x5a, 0x1f, 0x66, 0x72, 0x60, 0x25, 0xf6, 0xbe, 0xf1, 0x8b, + 0xc3, 0x0d, 0xde, 0x06, 0x2d, 0x04, 0xd2, 0xd7, 0x5d, 0xf2, 0x79, 0x9b, 0xb6, 0x51, 0xff, 0x17, + 0x5f, 0xbc, 0x39, 0xc8, 0x26, 0x6c, 0x89, 0x92, 0x4d, 0xb8, 0x2f, 0x83, 0x36, 0xe1, 0x21, 0x25, + 0x53, 0x68, 0x96, 0xe0, 0xd8, 0x68, 0x7d, 0x89, 0xb3, 0xd1, 0x86, 0x54, 0x4a, 0xa1, 0x59, 0xe2, + 0x61, 0xa3, 0xf5, 0xe5, 0xcb, 0x46, 0x1b, 0x52, 0x9c, 0x2d, 0xf2, 0x0a, 0x66, 0xb6, 0x08, 0x10, + 0x2b, 0x61, 0x40, 0x8b, 0x16, 0xf7, 0x37, 0xb9, 0x6d, 0x40, 0x7b, 0xe6, 0x6d, 0xc0, 0x81, 0x57, + 0x6f, 0x03, 0x0e, 0x3d, 0x15, 0xba, 0x75, 0x39, 0x51, 0xbf, 0xac, 0x5f, 0xff, 0x17, 0x00, 0x00, + 0xff, 0xff, 0xf1, 0x42, 0x51, 0xbb, 0xc1, 0x0a, 0x00, 0x00, } diff --git a/weed/server/filer_grpc_server.go b/weed/server/filer_grpc_server.go index 44f5320cb..da0014af3 100644 --- a/weed/server/filer_grpc_server.go +++ b/weed/server/filer_grpc_server.go @@ -50,6 +50,7 @@ func (fs *FilerServer) ListEntries(ctx context.Context, req *filer_pb.ListEntrie Gid: entry.Gid, Uid: entry.Uid, FileMode: uint32(entry.Mode), + Mime: entry.Mime, }, }) } @@ -75,6 +76,7 @@ func (fs *FilerServer) GetEntryAttributes(ctx context.Context, req *filer_pb.Get attributes.Gid = entry.Gid attributes.Mtime = entry.Mtime.Unix() attributes.Crtime = entry.Crtime.Unix() + attributes.Mime = entry.Mime glog.V(3).Infof("GetEntryAttributes %v size %d chunks %d: %+v", fullpath, attributes.FileSize, len(entry.Chunks), attributes) @@ -120,6 +122,7 @@ func (fs *FilerServer) CreateEntry(ctx context.Context, req *filer_pb.CreateEntr Mode: os.FileMode(req.Entry.Attributes.FileMode), Uid: req.Entry.Attributes.Uid, Gid: req.Entry.Attributes.Gid, + Mime: req.Entry.Attributes.Mime, }, Chunks: req.Entry.Chunks, }) @@ -162,6 +165,7 @@ func (fs *FilerServer) UpdateEntry(ctx context.Context, req *filer_pb.UpdateEntr } newEntry.Attr.Uid = req.Entry.Attributes.Uid newEntry.Attr.Gid = req.Entry.Attributes.Gid + newEntry.Attr.Mime = req.Entry.Attributes.Mime } @@ -180,14 +184,7 @@ func (fs *FilerServer) UpdateEntry(ctx context.Context, req *filer_pb.UpdateEntr } func (fs *FilerServer) DeleteEntry(ctx context.Context, req *filer_pb.DeleteEntryRequest) (resp *filer_pb.DeleteEntryResponse, err error) { - entry, err := fs.filer.DeleteEntry(filer2.FullPath(filepath.Join(req.Directory, req.Name))) - if err == nil { - for _, chunk := range entry.Chunks { - if err = operation.DeleteFile(fs.getMasterNode(), chunk.FileId, fs.jwt(chunk.FileId)); err != nil { - glog.V(0).Infof("deleting file %s: %v", chunk.FileId, err) - } - } - } + err = fs.filer.DeleteEntryMetaAndData(filer2.FullPath(filepath.Join(req.Directory, req.Name))) return &filer_pb.DeleteEntryResponse{}, err } diff --git a/weed/server/filer_server_handlers_admin.go b/weed/server/filer_server_handlers_admin.go index 0620e2f43..93a2ab883 100644 --- a/weed/server/filer_server_handlers_admin.go +++ b/weed/server/filer_server_handlers_admin.go @@ -32,6 +32,7 @@ func (fs *FilerServer) registerHandler(w http.ResponseWriter, r *http.Request) { writeJsonError(w, r, http.StatusInternalServerError, fmt.Errorf("parsing gid: %v", err)) return } + mime := r.FormValue("mime") entry := &filer2.Entry{ FullPath: filer2.FullPath(path), Attr: filer2.Attr{ @@ -40,6 +41,7 @@ func (fs *FilerServer) registerHandler(w http.ResponseWriter, r *http.Request) { Mtime: time.Now(), Uid: uint32(uid), Gid: uint32(gid), + Mime: mime, }, Chunks: []*filer_pb.FileChunk{{ FileId: fileId, diff --git a/weed/server/filer_server_handlers_read.go b/weed/server/filer_server_handlers_read.go index 08430716c..7a208b560 100644 --- a/weed/server/filer_server_handlers_read.go +++ b/weed/server/filer_server_handlers_read.go @@ -111,9 +111,11 @@ func (fs *FilerServer) handleSingleChunk(w http.ResponseWriter, r *http.Request, func (fs *FilerServer) handleMultipleChunks(w http.ResponseWriter, r *http.Request, entry *filer2.Entry) { - mimeType := "" - if ext := path.Ext(entry.Name()); ext != "" { - mimeType = mime.TypeByExtension(ext) + mimeType := entry.Mime + if mimeType == "" { + if ext := path.Ext(entry.Name()); ext != "" { + mimeType = mime.TypeByExtension(ext) + } } if mimeType != "" { w.Header().Set("Content-Type", mimeType) diff --git a/weed/server/filer_server_handlers_write.go b/weed/server/filer_server_handlers_write.go index c4152ba4f..5d72b9808 100644 --- a/weed/server/filer_server_handlers_write.go +++ b/weed/server/filer_server_handlers_write.go @@ -195,19 +195,12 @@ func (fs *FilerServer) PostHandler(w http.ResponseWriter, r *http.Request) { // curl -X DELETE http://localhost:8888/path/to func (fs *FilerServer) DeleteHandler(w http.ResponseWriter, r *http.Request) { - entry, err := fs.filer.DeleteEntry(filer2.FullPath(r.URL.Path)) + err := fs.filer.DeleteEntryMetaAndData(filer2.FullPath(r.URL.Path)) if err != nil { glog.V(4).Infoln("deleting", r.URL.Path, ":", err.Error()) writeJsonError(w, r, http.StatusInternalServerError, err) return } - if entry != nil && !entry.IsDirectory() { - for _, chunk := range entry.Chunks { - oldFid := chunk.FileId - operation.DeleteFile(fs.getMasterNode(), oldFid, fs.jwt(oldFid)) - } - } - writeJsonQuiet(w, r, http.StatusAccepted, map[string]string{"error": ""}) } diff --git a/weed/server/filer_ui/templates.go b/weed/server/filer_ui/templates.go index d5c42672e..e5ef4b8b6 100644 --- a/weed/server/filer_ui/templates.go +++ b/weed/server/filer_ui/templates.go @@ -47,9 +47,15 @@ var StatusTpl = template.Must(template.New("status").Parse(` {{if $entry.IsDirectory}} + {{else}} + {{ $entry.Mime }} + {{end}} + + + {{if $entry.IsDirectory}} {{else}} {{ $entry.Size }} bytes -       +     {{end}}