Compare commits

...
660 Commits
Author SHA1 Message Date
Chris Lu a833021132 fix refactoring left over 2021-02-07 23:03:03 -08:00
Chris Lu 5e4b5109dd 2.24 2021-02-07 22:29:43 -08:00
Chris Lu 15c60cbb26 close the grpc connection after 10 hours
related to https://github.com/chrislusf/seaweedfs/issues/1782
2021-02-07 03:50:01 -08:00
Chris LuandGitHub 928efc642c Merge pull request #1785 from bingoohuang/master 2021-02-06 20:30:16 -08:00
bingoohuang 7256902fb0 fix typo offset.ToAcutalOffset to offset.ToActualOffset 2021-02-07 12:11:51 +08:00
Chris LuandGitHub 7fca4324f9 Merge pull request #1784 from bingoohuang/master 2021-02-06 18:48:10 -08:00
bingoohuang 94ea3bd3a5 renaming NeedleMapType to NeedleMapKind 2021-02-07 09:00:03 +08:00
Chris Lu 5138d3954f Java 1.6.0 fix filerProxy mode 2021-02-06 00:09:12 -08:00
Chris Lu 35ba277a97 Java: fix filerProxy mode 2021-02-05 22:43:56 -08:00
Chris Lu 9c1efdf11b HCFS: 1.5.9 2021-02-05 11:47:56 -08:00
Chris Lu 8f3a51f2b8 Java: 1.5.8 additional fixes 2021-02-05 10:42:20 -08:00
Chris Lu 6a2a9b67e8 Java: 1.5.8 2021-02-04 22:22:15 -08:00
Chris Lu 694df89331 java: add configurable volume access mode 2021-02-04 22:21:55 -08:00
Chris Lu 8c3177d835 java: resolve parent directory if started with seaweedfs:// 2021-02-04 21:41:19 -08:00
Chris Lu 42e5ef4b01 Java: adjust examples 2021-02-04 21:02:54 -08:00
Chris Lu 9fa7977714 Java: SeaweedOutputStream refactoring 2021-02-04 20:30:49 -08:00
Chris Lu ce416d765f Java: SeaweedOutputStream add replication option 2021-02-04 20:22:40 -08:00
Chris Lu 82c167aaca Java: supportFlush set to true 2021-02-04 20:18:33 -08:00
Chris Lu 7f90d14f10 Java: add SeaweedOutputStream example 2021-02-04 20:16:08 -08:00
Chris Lu 502554887f Java: add SeaweedInputStream example 2021-02-04 18:44:57 -08:00
Chris Lu c3af72d950 fier store: fix elastic search regression
fix https://github.com/chrislusf/seaweedfs/issues/1774
2021-02-04 01:30:14 -08:00
Chris Lu ee4b208b8a increase to 3 volumes for local cluster 2021-02-03 13:55:19 -08:00
Chris Lu 430aca474c relocating local docker compose files 2021-02-03 13:09:34 -08:00
Chris LuandGitHub 91f26b3b9b Merge pull request #1778 from kmlebedev/retryQueue
Retry queue
2021-02-03 09:34:20 -08:00
Konstantin Lebedev 2fb4c60540 fix log warn 2021-02-03 21:34:32 +05:00
Konstantin Lebedev 24ec17219b RabbitMQ delay retry with Dead Letter Exchange
https://github.com/chrislusf/seaweedfs/issues/1773

https://github.com/google/go-cloud/issues/2952
2021-02-03 21:32:30 +05:00
Chris Lu a331bbb3ae filer: should return 204 on DELETE to nonexistent file
related to

https://github.com/chrislusf/seaweedfs/issues/1776
https://github.com/chrislusf/seaweedfs/issues/1160
2021-02-03 00:40:31 -08:00
Chris Lu 5353e38469 S3: should return 204 on DELETE to nonexistent file
fix https://github.com/chrislusf/seaweedfs/issues/1776
2021-02-03 00:35:44 -08:00
Chris Lu 2396ac234c filer: fix elastic search pagination
possible fix for https://github.com/chrislusf/seaweedfs/issues/1774
2021-02-02 11:34:12 -08:00
Chris Lu 609daaf387 s3: DeleteMultipleObjectsHandler clean up leftover empty folders
fix https://github.com/chrislusf/seaweedfs/issues/1772
2021-02-01 10:49:17 -08:00
Chris Lu 9c56b46886 webdav: adds to docker file 2021-01-31 22:57:30 -08:00
Chris Lu d67ccb66c0 webdav: can start together with "weed server" or "weed filer" 2021-01-31 22:16:52 -08:00
Chris Lu 76430790b9 webdav: cache to version specific folder 2021-01-31 22:02:03 -08:00
Chris Lu 318a3d2efc 2.23 2021-01-31 20:18:06 -08:00
Chris Lu 4be51c0701 filer: leveldb and hbase may miss files when listing large directories more than 1024
fix https://github.com/chrislusf/seaweedfs/issues/1768
2021-01-31 20:11:44 -08:00
Chris Lu 1102ae32c4 fix concurrent map reads 2021-01-31 18:26:26 -08:00
Chris Lu 314dc1c957 filer: etcd store fix listing
fix https://github.com/chrislusf/seaweedfs/issues/1767
2021-01-30 13:38:44 -08:00
Chris Lu 87d1bfa862 Hadoop Compatible FS: 1.5.7 2021-01-30 06:18:41 -08:00
Chris Lu 6f4aab51f9 refactoring SeaweedInputStream 2021-01-30 06:16:02 -08:00
Chris Lu 043c2d7960 refactoring SeaweedOutputStream 2021-01-30 05:39:09 -08:00
Chris Lu 678b9a60be test different volumeServerAcccss 2021-01-30 05:38:31 -08:00
Chris Lu d475c89fcc go fmt 2021-01-28 15:23:46 -08:00
Chris Lu 19295600f9 mount: change option name to volumeServerAccess, with publicUrl and filerProxy modes 2021-01-28 15:23:16 -08:00
Chris Lu 990fa69bfe add back AdjustedUrl() related code 2021-01-28 14:36:29 -08:00
Chris Lu 9292796ec2 fmt 2021-01-28 14:29:14 -08:00
Chris Lu c2bf1a88ac delete from the deepest directory first when checking empty folders 2021-01-28 14:28:40 -08:00
Chris Lu e9d8201925 s3: batch purge empty folders 2021-01-28 13:20:06 -08:00
Chris Lu cf252fc0cd mount: report error when Flush()
The error in Release() is not working.

See https://github.com/jaderhs/libfuse/blob/master/FAQ

related to https://github.com/chrislusf/seaweedfs/issues/1765
2021-01-28 04:46:37 -08:00
Chris Lu 9a06c35da4 replicate: incremental sink only contains new and updated files
address https://github.com/chrislusf/seaweedfs/commit/da08402ba253fe5391f0152905f51f82c51fd527
2021-01-28 02:39:22 -08:00
Chris Lu da08402ba2 replicate: use creation time for local incremental file sink
related to https://github.com/chrislusf/seaweedfs/pull/1762
2021-01-28 02:17:41 -08:00
Chris LuandGitHub 822f1ade9d Merge pull request #1762 from kmlebedev/backupsink
replication to create time date directory
2021-01-28 02:03:33 -08:00
Konstantin Lebedev be1062b7fc rename in scaffold 2021-01-28 14:59:20 +05:00
Konstantin Lebedev 02fdc0a333 rename backup to local_incremental and use mtime 2021-01-28 14:56:13 +05:00
Chris LuandGitHub 5f72c388bc Merge pull request #1764 from danlsgiga/handle-umask
Use provided umask on mount
2021-01-28 01:09:20 -08:00
Daniel Santos d38613c49a match upstream 2021-01-27 20:56:41 -07:00
Chris Lu 22e167bc8a mount: skip daemon timeout on FreeBSD 2021-01-27 15:34:43 -08:00
Chris Lu 7a96276f34 adjust dev local docker compose yaml 2021-01-27 10:29:09 -08:00
Chris Lu b81956bcb5 mount: invalidate kernel cache when mounted to a filer path
fix https://github.com/chrislusf/seaweedfs/issues/1752#issuecomment-768178422
2021-01-27 10:28:37 -08:00
Konstantin Lebedev 6b54ff9912 replication to create time date directory 2021-01-27 15:01:33 +05:00
Chris Lu f20ec82a28 update help message
see https://github.com/chrislusf/seaweedfs/issues/1758#issuecomment-768123224
2021-01-27 00:48:31 -08:00
Chris Lu 1045ab8b07 avoid error message 2021-01-27 00:21:59 -08:00
Chris Lu 0488c84bea adjust help message 2021-01-27 00:17:52 -08:00
Chris LuandGitHub 2266b5c528 Merge pull request #1761 from kmlebedev/todaysDateFormat
replication to todays date directory
2021-01-27 00:15:16 -08:00
Konstantin Lebedev 3634811408 replication to todays date directory 2021-01-27 12:45:58 +05:00
Chris LuandGitHub 5e07afb0f0 Merge pull request #1759 from kmlebedev/sink.local
replication to local disk storage
2021-01-26 22:31:54 -08:00
Chris Lu b3f66199db shell: volume.fix.replication adds collectionPattern with wildcard characters
fix https://github.com/chrislusf/seaweedfs/issues/1758
2021-01-26 22:30:39 -08:00
Chris LuandGitHub 2945a64fd6 Update issue templates 2021-01-26 22:03:22 -08:00
Daniel Santos 0c64d60fdb Fix log message with correct mode 2021-01-26 21:45:52 -07:00
Daniel Santos 0aaaa9b470 Fix var assignment 2021-01-26 21:06:08 -07:00
Daniel Santos 5a761bb7a4 Enforce umask correctly 2021-01-26 20:42:10 -07:00
Chris Lu ad2a20c8a5 notification add ack and nack 2021-01-26 11:08:44 -08:00
Konstantin Lebedev 612b7975a1 replication to local disk storage 2021-01-26 22:50:25 +05:00
Chris Lu 3a1d3d3413 mount: properly invalidate kernel node cache entry
fix https://github.com/chrislusf/seaweedfs/issues/1752
2021-01-26 02:50:53 -08:00
Chris LuandGitHub c41961d5cc Update README.md 2021-01-25 10:44:16 -08:00
Chris LuandGitHub ff35520a1a Update README.md 2021-01-25 10:34:51 -08:00
Chris Lu cc1f3907ff filer.sync: default filerProxy to true 2021-01-25 10:14:42 -08:00
Chris Lu 62ebb917e0 mount: avoid the need to specify different cache directory for different mount
fix https://github.com/seaweedfs/seaweedfs-csi-driver/issues/11
2021-01-25 09:10:20 -08:00
Chris Lu 17f7c1c43f Merge branch 'mount_from_outside_cluster' 2021-01-24 19:03:02 -08:00
Chris Lu 00707ec00f mount: outsideContainerClusterMode proxy through filer
Running mount outside of the cluster would not need to expose all the volume servers to outside of the cluster. The chunk read and write will go through the filer.
2021-01-24 19:01:58 -08:00
Chris Lu 9bcb28a3ea avoid possible nil reader
fix https://github.com/chrislusf/seaweedfs/issues/1754
2021-01-24 17:19:35 -08:00
Chris Lu 2c5eac5705 2.22 2021-01-24 14:06:09 -08:00
Chris Lu 6ca10725b8 Revert "mount: when outside cluster network, use filer as proxy to access volume servers"
This reverts commit 096e088d7b.
2021-01-24 03:15:19 -08:00
Chris Lu 096e088d7b mount: when outside cluster network, use filer as proxy to access volume servers 2021-01-24 01:41:38 -08:00
Chris Lu ccbdb38c89 s3: fix for listing objects if more than 1000 in the folder
many existing tools have max key set to 1000
2021-01-24 00:27:52 -08:00
Chris Lu 80b8692688 filer.sync: replicate outside of either cluster, only need to see filers 2021-01-24 00:01:44 -08:00
Chris Lu 6897f1bfbc makefile: add env for 2 clusters 2021-01-24 00:00:42 -08:00
Chris Lu f8dbb03bdd filer: append operation returns final file size 2021-01-23 04:19:49 -08:00
Chris Lu 759482e2ac filer: proxy all http methods to volume servers 2021-01-23 03:52:38 -08:00
Chris Lu 937cfacc01 filer: add "proxyToFileId" to reverse proxy to a volume server 2021-01-23 03:43:48 -08:00
Chris Lu 3ecd989500 add local mount for testing 2021-01-22 22:47:23 -08:00
Chris Lu 20ef3bb8d4 mount: use direct_io to avoid OS page cache
fix https://github.com/chrislusf/seaweedfs/issues/1752
2021-01-22 22:39:46 -08:00
Chris Lu 711c3f3939 filer: fix http status 206 setting
fix https://github.com/chrislusf/seaweedfs/issues/1753
2021-01-22 00:26:30 -08:00
Chris Lu 024c186a48 filer.meta.tail: output json format for easier parsing 2021-01-21 22:39:25 -08:00
Chris Lu 84f05787f8 mount: limit background requests and congestion threshold 2021-01-20 23:30:14 -08:00
Chris Lu f98817cfe6 filer: support appending to a file 2021-01-20 13:40:32 -08:00
Chris Lu 1b8e3da295 refactoring 2021-01-20 12:59:54 -08:00
Chris LuandGitHub c78f3dddcb update to wangyoucao577/go-release-action@v1.14 2021-01-20 03:03:49 -08:00
Chris Lu 1a3f859c58 filer store: postgres configuration adjust text 2021-01-19 18:12:07 -08:00
Chris Lu b434f7e4e0 filer store: postgres adjust default config, add optioanl schema 2021-01-19 18:10:36 -08:00
Chris Lu d5add83e85 filer store: add postgres2 2021-01-19 18:07:29 -08:00
Chris Lu 52a8f1470e filer store: add mysql2 2021-01-19 17:21:50 -08:00
Chris Lu 93b3adba98 fix bucket creation 2021-01-19 15:55:51 -08:00
Chris Lu fa0c8d5283 fix error 2021-01-19 14:05:48 -08:00
Chris Lu 4c5b752b04 restructuring sql stores 2021-01-19 13:53:16 -08:00
Chris Lu 96354208c5 scaffold: add YugabyteDB 2021-01-19 12:35:14 -08:00
Chris Lu ca8f793978 refactor: prepare for bucket specific tables 2021-01-19 12:34:58 -08:00
Chris Lu 90ce1eec19 add more input params 2021-01-19 11:32:55 -08:00
Chris Lu f13c082583 add memsql to comments 2021-01-19 11:31:55 -08:00
Chris Lu e439b65e38 fix test 2021-01-18 01:48:00 -08:00
Chris Lu c7197470fd 2.21 2021-01-18 01:25:04 -08:00
Chris Lu 5a3386e39b Revert "Revert "mount: fake support for socket/block/character/fifo devices""
This reverts commit 3d5cb7eb86.
2021-01-18 01:15:07 -08:00
Chris Lu 67faa56920 Revert "Revert "mount: add more entry type""
This reverts commit 4085b79d38.
2021-01-18 01:14:58 -08:00
Chris Lu 7119e7b491 mount: ensure reading from dirty pages 2021-01-18 01:14:42 -08:00
Chris Lu de876c795d minor fix 2021-01-18 01:14:27 -08:00
Chris Lu 4085b79d38 Revert "mount: add more entry type"
This reverts commit d7d907be27.
2021-01-18 00:19:19 -08:00
Chris Lu 3d5cb7eb86 Revert "mount: fake support for socket/block/character/fifo devices"
This reverts commit 61ef2d8658.
2021-01-18 00:18:57 -08:00
Chris Lu 61ef2d8658 mount: fake support for socket/block/character/fifo devices
to pass pjdfstest. A distributed file system can not really support these things anyway.
2021-01-17 23:51:10 -08:00
Chris Lu d7d907be27 mount: add more entry type 2021-01-17 23:46:39 -08:00
Chris Lu 389426bbb7 s3: listing may repeat on the edge 2021-01-17 22:59:31 -08:00
Chris LuandGitHub 0fddf68417 Merge pull request #1748 from kmlebedev/prometheus
docker-compose
2021-01-17 13:23:58 -08:00
Konstantin Lebedev 0f1c08d8ec docker-compose
- prometheus
 - nginx
2021-01-17 18:33:14 +05:00
Chris Lu 09f49d1c04 refactoring 2021-01-16 19:52:15 -08:00
Chris Lu a4063a5437 add stream list directory entries 2021-01-15 23:56:24 -08:00
Chris Lu 01dc8a43ba fix rocksdb 2021-01-15 18:31:29 -08:00
Chris Lu 16ad74f477 go fmt 2021-01-14 23:11:27 -08:00
Chris Lu f002e668de change limit to int64 in case of overflow 2021-01-14 23:10:37 -08:00
Chris Lu 19e52fd414 pass along hasMore 2021-01-14 22:49:29 -08:00
Chris Lu c0bcf6f6e1 implement sql changes 2021-01-14 22:44:22 -08:00
Chris Lu 5d4568b91f implement elastic changes 2021-01-14 22:42:25 -08:00
Chris Lu 893cbc8482 implement c* changes 2021-01-14 22:38:34 -08:00
Chris Lu 5ef43b9b09 implement etcd changes 2021-01-14 22:35:56 -08:00
Chris Lu 54527f0326 implement hbase changes 2021-01-14 22:34:35 -08:00
Chris Lu b5ceffe188 implement leveldb changes 2021-01-14 22:33:05 -08:00
Chris Lu c64bfb0e2e implement mongodb changes 2021-01-14 22:28:51 -08:00
Chris Lu 34a846009d implement rocksdb changes 2021-01-14 22:24:26 -08:00
Chris Lu d2ece29fff implement redis changes 2021-01-14 22:21:31 -08:00
Chris Lu 9a50dbcda0 chagned api 2021-01-14 22:18:38 -08:00
Chris Lu e1c7bc66f9 change interface 2021-01-14 22:17:49 -08:00
Chris Lu 4aaa97c789 skip not found error in case of race condition 2021-01-14 19:56:14 -08:00
Chris Lu d0826c2f62 mount: avoid showing "topics" folder
fix https://github.com/chrislusf/seaweedfs/issues/1325
2021-01-14 19:03:15 -08:00
Chris Lu 698f58f7c4 filer, s3: add http status 206 as late as possible
fix https://github.com/chrislusf/seaweedfs/issues/1746
2021-01-14 02:59:40 -08:00
Chris Lu fd1d8a2a09 fix compilation 2021-01-14 00:06:15 -08:00
Chris LuandGitHub ae812c07d6 Merge pull request #1743 from LazyDBA247-Anyvision/master
MYSQL - Better Connection Pool Control
2021-01-14 00:04:44 -08:00
LazyDBA247-Anyvision 5581d08702 K8S mysql connection pool
set max lifetime to 10 minutes, keeping connection "fresh"
and eliminating mysql/memsql closing old connection (causing filer errors)
2021-01-14 09:48:12 +02:00
Chris Lu f20743bb38 remove WIP status 2021-01-13 22:21:34 -08:00
LazyDBA247-Anyvision 8eed763b97 better mysql connection pool management
adding SetConnMaxLifetime configuration (https://golang.org/pkg/database/sql/#DB.SetConnMaxLifetime)
to enable refresh of connections.
2021-01-14 08:14:21 +02:00
Chris Lu f17aa1d06c skip directory loop if dropping the bucket 2021-01-13 13:49:04 -08:00
Chris Lu ca73013453 leveldb3: ensure repeatable adding removing buckets 2021-01-13 13:48:48 -08:00
Chris Lu e2c7e3fe6d better locks 2021-01-13 13:20:33 -08:00
Chris Lu 819a85f59a avoid viper concurrent access 2021-01-13 13:14:52 -08:00
Chris LuandGitHub 3c5b0ed8e3 Update README.md 2021-01-13 13:04:47 -08:00
Chris LuandGitHub 9d1d6f7adf Update README.md 2021-01-13 13:03:21 -08:00
Chris LuandGitHub 9e41941ba8 Merge pull request #1742 from LazyDBA247-Anyvision/master
K8S Chart
2021-01-13 12:37:17 -08:00
Yoni NakacheandGitHub d1959de038 Merge branch 'master' into master 2021-01-13 22:32:23 +02:00
LazyDBA247-Anyvision 95982e0856 correct master service
should have also:
publishNotReadyAddresses: true
2021-01-13 22:27:27 +02:00
LazyDBA247-Anyvision d595b35ca7 filer peers & client service
in order to start several filers with peers setting, they need to be discoverable by dns name, we need a service with
- tolerate-unready-endpoints: "true"
- publishNotReadyAddresses: true

so the filer will start and "See" each other...

added "client" service which expose only ready and line filer
changed s3 config to use the new service
2021-01-13 22:26:50 +02:00
LazyDBA247-Anyvision c1ed647daf increase timeout
reduce unwanted k8s pod restarts on slow response
2021-01-13 22:23:44 +02:00
LazyDBA247-Anyvision e57e6d6677 s3 logs
set logs to hostpath same as other pods
2021-01-13 22:18:24 +02:00
LazyDBA247-Anyvision 9ca1787e7e s3 allowEmptyFolder
enable setting allowEmptyFolder for s3 server
2021-01-13 22:17:34 +02:00
LazyDBA247-Anyvision 5e62f77681 dir.idx volume config
enable setting dir.idx for volume server
2021-01-13 22:16:39 +02:00
LazyDBA247-Anyvision cfc2033bf8 shell.toml
enable running shell from each pod with default
filer & master config
2021-01-13 22:15:47 +02:00
LazyDBA247-Anyvision 8491fbf1c7 fix cronjob reschedule
avoid errors of "more than 100 jobs skipped/failed"
and stopping of job by k8s
2021-01-13 22:13:07 +02:00
LazyDBA247-Anyvision 8b55331247 appVersion
start publishing and using appVersion as the image tag,
so its clear that the appVersion of the chart and containers are the same.
2021-01-13 22:11:50 +02:00
Chris Lu 3fb2ed9093 filer.meta.tail: optionally submit metadata changes to ElasticSearch 2021-01-13 03:31:37 -08:00
Chris Lu c5df2577f5 rename 2021-01-13 00:31:19 -08:00
Chris Lu 90c5077610 rename "weed watch" to "weed filer.meta.tail" 2021-01-12 18:48:01 -08:00
Chris Lu 5cd9c9e642 remove println 2021-01-12 18:47:38 -08:00
Chris Lu def6d8e565 fix test 2021-01-12 12:32:54 -08:00
Chris Lu 1c7faf1100 Revert "close opened file"
This reverts commit 2880160113.
2021-01-12 11:07:14 -08:00
Chris Lu 2880160113 close opened file 2021-01-12 11:03:08 -08:00
Chris Lu 0ef43a23a7 go fmt 2021-01-12 02:30:12 -08:00
Chris Lu 629c9962e7 filer: add leveldb3
support dedicated leveldb instance for each bucket
2021-01-12 02:29:44 -08:00
Chris Lu 361043e6c1 filer store: leveldb2 fix nil entry error if not found 2021-01-12 02:28:57 -08:00
Chris Lu cfb9342a15 avoid concurrent map updates to viper 2021-01-12 02:28:13 -08:00
Chris Lu 38d516251e Revert "mount: avoid fatal error"
This reverts commit a4f0bac9b7.
2021-01-11 13:50:15 -08:00
Chris Lu a4f0bac9b7 mount: avoid fatal error 2021-01-11 13:26:59 -08:00
Chris Lu 8a7302ce37 s3: KeyCount is zero
fix https://github.com/chrislusf/seaweedfs/issues/1741
2021-01-11 03:50:45 -08:00
Chris Lu 2c7148cd55 redis cluster: do not enable route by latency by default 2021-01-11 02:43:53 -08:00
Chris Lu acc0d5cd2c Revert "Revert "filer store: redis module upgrade""
This reverts commit dd0171e35c.
2021-01-11 02:30:19 -08:00
Chris Lu dd0171e35c Revert "filer store: redis module upgrade"
This reverts commit 40161c9cec.
2021-01-11 02:09:18 -08:00
Chris Lu 394513f598 filer: ensure seamless meta data updates 2021-01-11 02:08:55 -08:00
Chris Lu 6e12a3a490 refactoring 2021-01-11 02:08:26 -08:00
Chris Lu 62ee484d12 refactoring 2021-01-11 00:03:13 -08:00
Chris Lu 1efb51ba84 filer: change to saveToFilerLimit from cacheToFilerLimit
short circuit saving small files to volume server
2021-01-10 23:14:46 -08:00
Chris Lu f0d3b3bf93 2.20 2021-01-09 22:55:22 -08:00
Chris Lu d3d3f2fb9b mount: default to 128 concurrent writers 2021-01-09 22:53:37 -08:00
Chris Lu e9ccc0a6c5 adjust 2021-01-09 22:53:09 -08:00
Chris Lu 90b117acf1 update ccache version 2021-01-08 02:17:43 -08:00
Chris Lu e2e0e30a51 filer: redis default to false for useReadOnly and routeByLatency 2021-01-08 01:12:44 -08:00
Chris Lu 40161c9cec filer store: redis module upgrade 2021-01-08 01:08:44 -08:00
Chris Lu 30efaa66c6 server: add option to disable master 2021-01-07 02:35:47 -08:00
Chris LuandGitHub 07f4703bfc Merge pull request #1738 from qieqieplus/rocksdb
fix rocksdb crash when list directory
2021-01-07 02:26:41 -08:00
qieqieplus 0f18592315 alter style 2021-01-07 18:21:48 +08:00
qieqieplus c7e7431fd3 fix seek lastkey may reach EOF 2021-01-07 17:07:56 +08:00
Chris Lu e327385644 go fmt 2021-01-06 04:22:00 -08:00
Chris Lu 2b76854641 add "weed filer.cat" to read files directly from volume servers 2021-01-06 04:22:00 -08:00
Chris LuandGitHub 95ecf0c72f Merge pull request #1735 from qieqieplus/rocksdb
ignore decode error for non-entry data
2021-01-06 02:22:18 -08:00
qieqieplus 0764fccde7 ignore decode error for non-entry data 2021-01-06 17:42:43 +08:00
Chris LuandGitHub f579838917 Merge pull request #1734 from runbestfast/fix_s3_use_of_closed_network_connection
fix s3 upload "use of closed network connection"
2021-01-05 23:17:53 -08:00
yuwang d253e0ea6e fix s3 upload "use of closed network connection" 2021-01-06 15:11:54 +08:00
Chris LuandGitHub ab57767d4b Merge pull request #1730 from qieqieplus/rocksdb
impl: TTL per entry for rocksdb; fix package name
2021-01-05 13:24:45 -08:00
Chris LuandGitHub 9e670c2e23 Update README.md 2021-01-05 13:20:58 -08:00
Chris LuandGitHub a08e9d59ec Update README.md 2021-01-05 12:41:11 -08:00
qieqieplusandGitHub b2e50f602f fix time comparison 2021-01-05 19:36:40 +08:00
qieqieplus bbae13e415 impl: TTL per entry for rocksdb; fix package name 2021-01-05 17:58:40 +08:00
Chris LuandGitHub eaac1a1393 Merge pull request #1728 from fuyouyshengwu/master
Seaweed custom header are not visible to Vue or javascript
2021-01-04 22:14:31 -08:00
henry b42c5b71c1 Seaweed custom header are not visible to Vue or javascript 2021-01-05 13:01:29 +08:00
henry 1309dfe612 Seaweed custom header are not visible to Vue or javascript 2021-01-05 12:58:46 +08:00
henry e4ee25e6f0 remove sort 2021-01-05 12:29:46 +08:00
henry 247d5eed93 remove sort 2021-01-05 12:27:26 +08:00
henry e92ce1d517 remove sort 2021-01-05 12:26:51 +08:00
henry 942a30f04c remove sort 2021-01-05 12:24:32 +08:00
henry a3c432dadc Merge branch 'master' of https://github.com/fuyouyshengwu/seaweedfs 2021-01-05 11:17:29 +08:00
henry e5a3ad372f gitignore 2021-01-05 11:17:04 +08:00
Chris LuandGitHub 9fa2d20357 Merge pull request #1727 from qieqieplus/rocksdb
fix #1726
2021-01-04 10:41:57 -08:00
qieqieplus ebb223c190 fix for rocksdb kv 2021-01-04 21:21:46 +08:00
chenqieqie 40b3207f18 fix #1726 2021-01-04 18:48:55 +08:00
henry 97a94eddab Merge branch 'master' of https://github.com/fuyouyshengwu/seaweedfs 2021-01-04 14:50:01 +08:00
Chris Lu 2ce86f308e 2.19 2021-01-03 17:24:02 -08:00
Chris Lu c3f674ac1d address raft nil snapshot during flush
fix https://github.com/chrislusf/seaweedfs/issues/1718
2021-01-03 13:38:27 -08:00
Chris Lu 9c9ba3c209 nil related
related to https://github.com/chrislusf/seaweedfs/issues/1676
2021-01-03 12:25:58 -08:00
Chris Lu 4b5adc60b4 upload result changes to the right output variable 2021-01-03 01:44:22 -08:00
Chris Lu 039ad101b1 manifest file also need to detect compression
fix https://github.com/chrislusf/seaweedfs/issues/1724#issuecomment-753585046
2021-01-03 01:42:21 -08:00
Chris Lu 5f538c5f9d Merge branch 'add_rocksdb' 2021-01-03 00:48:56 -08:00
Chris Lu bdd166c031 adjust readme 2021-01-03 00:47:58 -08:00
Chris Lu a04d8927a8 add scaffold 2021-01-03 00:44:52 -08:00
Chris Lu 4250a3a675 upload: add read default collection from master
fix https://github.com/chrislusf/seaweedfs/issues/1724#issuecomment-753576071
2021-01-02 23:43:01 -08:00
Chris Lu f4d87f8b9d works
performance seems about the same as leveldb for insert entries
2021-01-02 23:32:58 -08:00
Chris Lu 2c3c2c27d7 separate prefix from namePattern
fix https://github.com/chrislusf/seaweedfs/issues/1722
2021-01-01 20:23:23 -08:00
Chris Lu 3fdf73e514 add mem_limit for mount 2021-01-01 20:20:35 -08:00
Chris Lu 712563fbdd dev cluster adds fuse mount 2020-12-31 19:54:33 -08:00
Chris LuandGitHub 2a5fc7aa4d Update release.yml 2020-12-31 02:13:19 -08:00
Chris LuandGitHub 8529d56b59 Merge pull request #1720 from PeterCxy/patch-put-respect-mime
filer: respect Content-Type on PUT
2020-12-30 20:33:15 -08:00
Peter Cai cd2a9865ed filer: respect Content-Type on PUT
This is needed for the S3 gateway to conform to the S3 protocol -- the
server should always respect the Content-Type set by client.
2020-12-31 11:32:45 +08:00
Chris Lu 3433accb1b weed upload: add TTL 2020-12-30 15:46:07 -08:00
henry 14ddd15508 1 Distinguish between folders and common files, folders are listed first
2 Add some custom headers that need to be exposed
2020-12-31 00:03:22 +08:00
Chris LuandGitHub d1a05d261a Update README.md 2020-12-29 21:35:40 -08:00
Chris LuandGitHub 0d8c1f976b Update README.md 2020-12-29 21:30:17 -08:00
Chris LuandGitHub 1fc37a68c4 Update README.md 2020-12-29 21:23:59 -08:00
Chris LuandGitHub adda3207c4 Update README.md 2020-12-29 21:15:09 -08:00
Chris Lu c1cd6dd8d6 rename 2020-12-29 12:13:39 -08:00
Chris Lu 66ebc7c98f adjust actions 2020-12-29 12:12:07 -08:00
Chris Lu adef4ddc87 mount: load security keys
fix https://github.com/chrislusf/seaweedfs/issues/1714
2020-12-29 11:51:38 -08:00
Chris Lu 89977123b6 shell: add shell.toml support
fix https://github.com/chrislusf/seaweedfs/issues/1664
2020-12-28 15:07:18 -08:00
Chris LuandGitHub 54fe0e5059 Merge pull request #1713 from nivekuil/master
Add fuse to all dockerfiles
2020-12-28 14:46:11 -08:00
nivekuil efd4253ab6 Add fuse to all dockerfiles 2020-12-28 13:54:02 -08:00
Chris Lu d2ead72918 2.18 2020-12-28 12:37:10 -08:00
Chris Lu 2e6cf541e7 filer: avoid deletion error when item is not found 2020-12-28 00:18:37 -08:00
Chris Lu 6d2c979999 s3: fix regression
fix https://github.com/chrislusf/seaweedfs/issues/1707
2020-12-27 21:09:45 -08:00
Chris Lu 90df52d001 s3: add command option "allowEmptyFolder" to filer and server 2020-12-27 21:09:06 -08:00
Chris Lu da7e5aaa65 filer: optimize for less number of directory lookup
bottom up directory lookup
2020-12-27 20:46:17 -08:00
Chris LuandGitHub 2ffc87b86e Merge pull request #1708 from fuyouyshengwu/master
Solve the Chinese name disorder of download file
2020-12-27 19:37:11 -08:00
henry 7458ff9523 Solve the Chinese name disorder of download file 2020-12-28 11:28:33 +08:00
Chris LuandGitHub 7a70caac3c Update README.md 2020-12-27 11:03:41 -08:00
Chris Lu 561a2ff0bc s3: add option for "alllowEmptyFolder" 2020-12-27 10:50:27 -08:00
Chris Lu aa020ee7e7 s3: restore V2 auth type
The added headers were included in calculating the signatures, failing the comparison
2020-12-26 22:01:16 -08:00
Chris Lu da87f6b265 remove unused code 2020-12-26 15:21:12 -08:00
Chris Lu 0a7c5f85a9 filer: add namePattern to search in current folder 2020-12-26 15:05:31 -08:00
Chris Lu 515b7632d7 2.17 2020-12-25 23:58:22 -08:00
Chris Lu 0a067944cc filer: add retries during volume moving
fix https://github.com/chrislusf/seaweedfs/issues/1704
2020-12-25 02:32:55 -08:00
Chris LuandGitHub 1b1d182469 Update release.yml 2020-12-25 02:07:30 -08:00
Chris Lu 090f85be4b s3: support config action Admin:bucket 2020-12-25 00:38:56 -08:00
Chris Lu 75613b2cc7 Merge branch 'add_hbase' 2020-12-24 12:13:05 -08:00
Chris Lu 0e016bc7bd hbase add ttl 2020-12-24 12:10:35 -08:00
Chris Lu 8e48a235e2 s3: avoid looping if the directory is empty
fix https://github.com/chrislusf/seaweedfs/issues/1701
2020-12-24 11:34:52 -08:00
Chris Lu 1620de08ae added more logs 2020-12-24 01:52:06 -08:00
Chris Lu a09cd28986 add debug messages 2020-12-24 01:42:15 -08:00
Chris Lu 75c6edba9e filer: hbase add enabled flag 2020-12-24 00:19:16 -08:00
Chris Lu 9bf6c10505 fix prefix 2020-12-24 00:18:59 -08:00
Chris Lu 2fea8cfa0f fix compilation 2020-12-23 23:54:15 -08:00
Chris Lu 53bc1ea25b fix compilation 2020-12-23 23:53:46 -08:00
Chris Lu b5e2be635a adjust for directory listing 2020-12-23 23:49:22 -08:00
Chris Lu c4a202ec41 fix wrong column family 2020-12-23 23:23:05 -08:00
Chris Lu 32955b04b8 Update go.mod 2020-12-23 22:08:41 -08:00
Chris Lu c3d1b3b5aa hook up 2020-12-23 21:49:01 -08:00
Chris Lu 94e3757c08 fix 2020-12-23 21:45:16 -08:00
Chris Lu 64c48c9724 seems compiling 2020-12-23 21:44:53 -08:00
Chris Lu 3be3635799 just log error when checking empty dir failed 2020-12-23 14:36:48 -08:00
Chris Lu 0ca9d89589 s3: break loop if error
fix #1701
2020-12-23 14:34:59 -08:00
Chris LuandGitHub dc19bc2ace Merge pull request #1700 from bmillemathias/master
[shell] Clarify bucket replication setting order
2020-12-23 06:12:49 -08:00
Baptiste Mille-Mathias 385a4dec30 [shell] Clarify bucket replication setting order 2020-12-23 09:35:24 +01:00
Chris Lu da134a2eb7 minor 2020-12-22 17:43:13 -08:00
Chris Lu beb3b8ddb0 shell: change bucket.list to s3.bucket.list, same for create and delete 2020-12-22 17:40:55 -08:00
Chris Lu 4cf3176cbb filer first, master second 2020-12-22 17:34:44 -08:00
Chris Lu a1009e8044 filer: add -defaultStoreDir so that filer.toml can be skipped
fix https://github.com/chrislusf/seaweedfs/issues/1659
2020-12-22 17:33:40 -08:00
Chris Lu a0990b929d minor 2020-12-22 17:33:40 -08:00
Chris LuandGitHub 9cd26c6ca5 Merge pull request #1699 from bmillemathias/master
[shell] Add more information to bucket.create
2020-12-22 10:02:51 -08:00
Baptiste Mille-Mathias 0ed5345954 [shell] Add more information to bucket.create
State the replication setting that will be honor if not defined.
2020-12-22 17:18:59 +01:00
Chris Lu 97e3432dfe avoid wrong error
fix https://github.com/chrislusf/seaweedfs/issues/1691
2020-12-22 02:46:24 -08:00
Chris Lu 4f31c1bb94 go fmt 2020-12-22 02:34:08 -08:00
Chris Lu 6c4f32d173 remove unused code 2020-12-22 02:33:31 -08:00
Chris Lu 90d785a15f filer: redis, redis cluster, cassandra support super large directory 2020-12-22 02:26:05 -08:00
Chris Lu fe46411cd4 handle directory listing edge cases 2020-12-21 23:37:43 -08:00
Chris Lu c74bede730 handle listing directories 2020-12-21 23:19:05 -08:00
Chris Lu adf8cb4000 filer: path-specific stores trim out common prefixes 2020-12-21 22:57:13 -08:00
Chris Lu 0823bde8d8 refactor: split into two files 2020-12-21 22:05:15 -08:00
Chris Lu 8ab70ccf76 refactor 2020-12-21 21:46:32 -08:00
Chris Lu 65cc6dc636 refactor to dedicated function 2020-12-21 21:18:34 -08:00
Chris Lu 488c2680e8 change default filer store root 2020-12-21 21:15:22 -08:00
Chris Lu f5a19a87be filer: report error if the path specific store is not found
related https://github.com/chrislusf/seaweedfs/issues/1691
2020-12-21 12:43:52 -08:00
Chris LuandGitHub f30de7f827 Merge pull request #1693 from kmlebedev/local-dev-k8s
k8s build
2020-12-21 09:10:01 -08:00
Konstantin Lebedev 6b4e9eef57 k8s build 2020-12-21 20:58:41 +05:00
Chris LuandGitHub 75629954d1 Merge pull request #1690 from nivekuil/master
Add fuse to docker image
2020-12-21 05:02:01 -08:00
nivekuil af8dffd66f Add fuse to docker image 2020-12-20 21:48:35 -08:00
Chris LuandGitHub 60b4dedfb7 Update release.yml 2020-12-20 16:15:50 -08:00
Chris Lu 6912bf94ae 2.16 2020-12-20 15:30:12 -08:00
Chris Lu 41c0f3ad24 filer: support path-specific filer store 2020-12-19 01:27:09 -08:00
Chris Lu 0d5683fb0e todo: load path-specific store from filer.toml 2020-12-18 03:05:42 -08:00
Chris Lu 3269fd7eaf filer: use store by path 2020-12-18 02:57:49 -08:00
Chris Lu e605f1e001 refactor, add getActualStore() by path 2020-12-18 02:55:00 -08:00
Chris Lu 23903aa95b refactoring 2020-12-18 02:35:45 -08:00
Chris Lu 4e6b316913 assert FilerStoreWrapper is VirtualFilerStore 2020-12-18 02:17:06 -08:00
Chris LuandGitHub 85411b8cc3 Update release.yml 2020-12-17 23:24:47 -08:00
Chris LuandGitHub 252e554e18 Update release.yml 2020-12-17 23:23:47 -08:00
Chris LuandGitHub dbf46b3aa1 Update release.yml 2020-12-17 22:28:43 -08:00
Chris LuandGitHub 8c00c46f9b Update release.yml 2020-12-17 22:28:02 -08:00
Chris LuandGitHub 47f5ec0cde Update release.yml 2020-12-17 22:19:26 -08:00
Chris LuandGitHub 9fc07feb00 Update release.yml 2020-12-17 22:17:41 -08:00
Chris LuandGitHub 7af9415696 Update release.yml 2020-12-17 22:16:14 -08:00
Chris LuandGitHub 1b4237795a Update release.yml 2020-12-17 22:11:14 -08:00
Chris LuandGitHub 160d46dbcc Update release.yml 2020-12-17 22:08:04 -08:00
Chris LuandGitHub 8e3b798ea0 Update release.yml 2020-12-17 21:57:41 -08:00
Chris Lu 738c4fd203 fix logging when error
address https://github.com/chrislusf/seaweedfs/pull/1685#issuecomment-747845601
2020-12-17 19:37:46 -08:00
Chris Lu e2076201d7 volume: avoid reprocessing the same volume
fix https://github.com/chrislusf/seaweedfs/issues/1682
2020-12-17 13:03:39 -08:00
Chris Lu 986cbdf7d9 Revert "Merge pull request #1683 from qieqieplus/master"
This reverts commit 8cb67952db, reversing
changes made to 200e56215a.
2020-12-17 12:46:42 -08:00
Chris LuandGitHub 99990a3c91 Merge pull request #1686 from LazyDBA247-Anyvision/master
fix Argument Name, and use the correct one.
2020-12-17 11:06:39 -08:00
LazyDBA247-Anyvision a37f069296 fix Argument Name, and use the correct one. 2020-12-17 19:41:33 +02:00
Chris Lu b789767cd1 filer: return http status 499 for client closed connection
fix https://github.com/chrislusf/seaweedfs/issues/1684
2020-12-16 08:18:00 -08:00
Chris LuandGitHub 8cb67952db Merge pull request #1683 from qieqieplus/master
fix race condition when loading volumes concurrently
2020-12-16 07:24:27 -08:00
chenqieqie 45f902a9b7 smaller critical section 2020-12-16 20:23:51 +08:00
chenqieqie 4e58a4f24e fix race condition when loading volumes concurrently 2020-12-16 18:49:10 +08:00
Chris Lu 200e56215a Update README.md 2020-12-15 20:30:36 -08:00
Chris Lu b0a4da7111 Update README.md 2020-12-15 20:28:36 -08:00
Chris Lu 0154cca306 Update README.md 2020-12-15 20:26:01 -08:00
Chris Lu deb77e3b4a add 曙光云 2020-12-15 20:22:56 -08:00
Chris LuandGitHub fc05963fa3 Merge pull request #1681 from LazyDBA247-Anyvision/master
Dockerfile: support build branches other than master
2020-12-15 09:32:33 -08:00
LazyDBA247-Anyvision 2ac31da89e support build branches other than master 2020-12-15 14:07:13 +02:00
Chris Lu 3c7f9633eb show error a little bit more obviously
fix https://github.com/chrislusf/seaweedfs/issues/1678
2020-12-14 09:39:33 -08:00
Chris Lu 3d47c38262 collection.delete requires _default_ as the default empty collection name
fix https://github.com/chrislusf/seaweedfs/issues/1677
2020-12-14 01:05:20 -08:00
Chris LuandGitHub b7e3ca9172 Merge pull request #1650 from kmlebedev/masterServerEnableUI
security master use access.ui
2020-12-14 00:31:51 -08:00
Chris Lu 021358749b better detect IP address
following advice from https://github.com/chrislusf/seaweedfs/issues/1671
2020-12-14 00:30:20 -08:00
Konstantin Lebedev c4459249ef ui interface is always on 2020-12-14 13:24:41 +05:00
Chris Lu 38fc89d041 filer store: sql update if any insert error happens
fix https://github.com/chrislusf/seaweedfs/issues/1673
2020-12-13 20:49:44 -08:00
Chris Lu 23280257df sql put kv: avoid unnecessary update 2020-12-13 19:45:47 -08:00
Chris Lu 813453f3e1 2.15 2020-12-13 03:45:35 -08:00
Chris Lu 16cd6fb278 fix variable name 2020-12-12 21:19:40 -08:00
Chris Lu 5c465293e9 correctly determine whether a folder is empty
avoid edge cases that deleting the folder if previous 32 directories are all empty

early terminate if one file is found
2020-12-12 16:19:29 -08:00
Chris Lu 14910d035c the pagination size was too big for recursive deletion 2020-12-12 13:26:10 -08:00
Chris Lu f930c713fc more efficient recursion 2020-12-12 13:25:19 -08:00
Chris Lu 316d1b4e69 refactor APIs 2020-12-12 12:42:53 -08:00
Chris Lu 03637d6f57 s3: move "delete-directory-if-empty" to read time
move "delete-directory-if-empty" to read time instead of entry deletion time

the listing speed for a s3 bucket folder will slow down if it has many sub folders

related to https://github.com/chrislusf/seaweedfs/commit/0d345ac97d941bef0991c0cb08632ccf08c0ee83

fix https://github.com/chrislusf/seaweedfs/issues/1647

fix https://github.com/chrislusf/seaweedfs/issues/1670
2020-12-12 03:38:34 -08:00
Chris Lu 37075a414d adjust logs 2020-12-12 03:33:57 -08:00
Chris Lu ae655033ac adjust logging 2020-12-11 16:57:53 -08:00
Chris Lu d986c7196d use append time instead of filer's own modification time
fix https://github.com/chrislusf/seaweedfs/issues/1669
2020-12-11 16:55:18 -08:00
Chris Lu 3fedfec1e7 check cross device rename error 2020-12-10 23:50:32 -08:00
Chris Lu c2f18a10cb minor 2020-12-10 22:23:22 -08:00
Chris Lu 4b0c2a846b add logs 2020-12-10 19:55:28 -08:00
Chris Lu 83078ac6ce filer: change to /etc/seaweedfs folder on filer
fix https://github.com/chrislusf/seaweedfs/issues/1666
2020-12-10 11:11:02 -08:00
Chris Lu 26731694f8 s3: use static configuration by default
So that users can still use the previous configuration files.

If leave it empty, s3 will try to use the version from filer
2020-12-10 00:59:04 -08:00
Chris Lu 765b3ef1be save /etc/iam/identity.json inside filer store 2020-12-10 00:15:22 -08:00
Chris Lu 97c942b5ee paginate through large directories 2020-12-09 23:23:38 -08:00
Chris Lu 02a160c3fd s3: recursively iterate all sub folders
fix https://github.com/chrislusf/seaweedfs/issues/1656
2020-12-09 16:47:34 -08:00
Chris Lu a9c619c270 added error handling for saving 2020-12-09 01:34:24 -08:00
Chris Lu 4211601eab set file handle reader to nil 2020-12-08 22:48:18 -08:00
Chris Lu b52ae9cef8 add s3 debug 2020-12-08 22:27:04 -08:00
Chris Lu 8e78187a97 add back last read chunk cache to reader and properly close the reader 2020-12-08 22:26:46 -08:00
Chris Lu 900d22c6ec mount: avoid memory leaking read buffer
fix https://github.com/chrislusf/seaweedfs/issues/1654

the reader goes together with the file handle, which may stay for a long time.
2020-12-08 02:38:53 -08:00
Chris Lu 06bb7bf6c0 adding /usr/local/etc/seaweedfs for bsd style config search path
related to https://reviews.freebsd.org/D27391
2020-12-07 16:46:48 -08:00
Chris Lu fce8803087 break import cycle 2020-12-07 00:29:17 -08:00
Chris Lu 606051cc79 filer: cache "/etc" filder small files to filer store 2020-12-07 00:11:35 -08:00
Chris Lu ac22f1dd26 filer subscribe: handle rename subscription 2020-12-07 00:10:49 -08:00
Chris Lu eed87791b7 s3: subscribe to s3.configure changes 2020-12-07 00:10:29 -08:00
Chris Lu 01e2da5782 refactoring 2020-12-06 23:16:20 -08:00
Chris Lu 77286f8bea fix test 2020-12-06 21:56:13 -08:00
Chris Lu 57578a6cd1 change parameter help message 2020-12-06 21:54:55 -08:00
Chris Lu 78f3ab439c refactoring 2020-12-06 21:54:34 -08:00
Chris Lu 9acda432fe fix import cycle 2020-12-06 20:12:52 -08:00
Chris Lu ae5eb85a06 refactoring 2020-12-06 20:05:06 -08:00
Chris Lu 5931a2f53f filer conf: support json conf only 2020-12-06 19:47:06 -08:00
Chris Lu 4c72482536 shell: fix fs.configure 2020-12-06 19:43:31 -08:00
Chris Lu 46b91228af 2.14 2020-12-06 18:56:58 -08:00
Chris Lu 263eb29e9f filer: add option to cache small files to filer store 2020-12-04 22:39:43 -08:00
Chris Lu d171d9f988 volume: ensure the volume dat and idx files are always closed
fix https://github.com/chrislusf/seaweedfs/issues/1646
2020-12-04 21:50:26 -08:00
Konstantin Lebedev eadbba5c95 security master use access.ui 2020-12-04 12:57:59 +05:00
Chris Lu cc839f935d better unit detection 2020-12-03 19:23:59 -08:00
Chris Lu b219ccfe68 Update volume_ttl_test.go 2020-12-03 12:55:44 -08:00
Chris Lu a83b8e7b01 ttl fix: 3y was converted into 96m 2020-12-03 10:53:29 -08:00
Chris LuandGitHub 5fb60b7135 Merge pull request #1596 from kmlebedev/store_s3cred
S3 credentials store in filer
2020-12-03 00:40:20 -08:00
Chris Lu 4d2855476c Hadoop: add BufferedByteBufferReadableInputStream
fix https://github.com/chrislusf/seaweedfs/issues/1645
2020-12-03 00:08:05 -08:00
Chris Lu 3857f9c840 Hadoop: switch to ByteBuffer
fix https://github.com/chrislusf/seaweedfs/issues/1645
2020-12-02 23:45:39 -08:00
Konstantin Lebedev 14699dfcef use content field of entry 2020-12-02 17:19:05 +05:00
Konstantin Lebedev a3d4b50a49 use entry content filed 2020-12-02 16:12:13 +05:00
Chris Lu 003b6245e7 fix nil 2020-12-02 00:09:19 -08:00
Chris Lu f3bb645018 file open error 2020-12-01 23:37:49 -08:00
Chris Lu dc0bc48257 return file open error 2020-12-01 23:36:49 -08:00
Chris Lu 45dba088cd fix tests 2020-12-01 19:37:21 -08:00
Chris Lu a9efaa6385 HDFS: implement ByteBufferReadable
fix https://github.com/chrislusf/seaweedfs/issues/1645
2020-12-01 17:20:31 -08:00
Chris Lu 04062c56c7 webdav: improve webdav upload speed 2020-12-01 15:32:27 -08:00
Konstantin Lebedev 03620776ec Merge branch 'upstream_master' into store_s3cred 2020-12-01 16:03:34 +05:00
Chris LuandGitHub 005a6123e9 Merge pull request #1643 from hilimd/master
fix tls grpc ca path
2020-11-30 17:16:46 -08:00
Chris Lu f4abd01adf filer: cache small file to filer store 2020-11-30 04:34:04 -08:00
Chris Lu a9c6be5fc3 set creation time 2020-11-30 03:11:52 -08:00
Chris Lu 141ce67c09 close http request body 2020-11-30 02:45:00 -08:00
Chris Lu 0e99531dbf 2.13 2020-11-29 17:00:03 -08:00
Chris Lu 965413c21b shell: add volume.vacuum command 2020-11-28 23:18:02 -08:00
Chris Lu 96c48bc8a8 fix test 2020-11-28 03:03:43 -08:00
Chris Lu c57a7839ec adjust comments 2020-11-28 03:01:03 -08:00
Chris Lu 8438fb0cc3 fix ec shard spreading error 2020-11-28 02:21:16 -08:00
Chris Lu 536202e4e0 minor 2020-11-28 02:16:06 -08:00
Chris Lu 99c4e50d3d minor 2020-11-28 00:14:11 -08:00
Chris Lu 2c913dde04 volume: detect and drop volumes with disk IO error
from Jethro in slack:
is it possible to make the assign request a bit smarter? Currently I’m in the state that a disk failed but all assign request are being send to this volume. It would be cool if the master sees this and stopped using this volume.
e=HTTP(http://x:8089/913,045a782b63176edf) not 200 but 500 Internal Server Error
Body={"size":740167,"error":"failed to write to local disk: write /mnt/v9/913.dat: input/output error","eTag":"ee4381e202212ff3aee647704c036689"}
e=HTTP(http://x:8089/913,045a782c90240077) not 200 but 500 Internal Server Error
Body={"size":792779,"error":"failed to write to local disk: write /mnt/v9/913.dat: input/output error","eTag":"c43463ccc11eb6eb2fc306f407a6a953"}
e=HTTP(http://x:8089/913,045a782e6b7901ea) not 200 but 500 Internal Server Error
Body={"size":3962392,"error":"failed to write to local disk: write /mnt/v9/913.dat: input/output error","eTag":"04c91198e9b276c81f11dbf189af5d28"}
2020-11-28 00:09:29 -08:00
Chris Lu 9ac4935f22 read from volume index file directly instead of open a separate file
fix https://github.com/chrislusf/seaweedfs/issues/1640

read from volume index file directly instead of open a separate file,
to ensure reading latest index entries.
2020-11-27 16:18:48 -08:00
Chris Lu 85554bea38 filer: readonly handle static resources
fix https://github.com/chrislusf/seaweedfs/issues/1641
2020-11-27 13:42:14 -08:00
Chris Lu 6d30b21b10 volume: add "-dir.idx" option for separate index storage
fix https://github.com/chrislusf/seaweedfs/issues/1265
2020-11-27 03:17:10 -08:00
Chris Lu 3c229eb677 refactor 2020-11-26 17:21:55 -08:00
Chris Lu c0fb4a3766 add comments 2020-11-26 15:22:42 -08:00
Chris Lu 6783ae5f8f rename 2020-11-26 15:19:43 -08:00
Chris Lu 983fd90010 marked as WIP 2020-11-26 15:08:52 -08:00
Chris Lu 97f706f35b just refactoring 2020-11-26 15:08:05 -08:00
Chris Lu b11449f955 pass in dir.idx parameter to DiskLocation 2020-11-26 14:59:03 -08:00
Chris Lu 0d345ac97d s3: remove empty parent folder on delete
fix https://github.com/chrislusf/seaweedfs/issues/1637
2020-11-26 12:21:58 -08:00
Chris Lu cc2bd97ad9 refactor 2020-11-26 11:25:56 -08:00
Chris Lu 0da7ecfd29 go fmt 2020-11-26 11:22:30 -08:00
Chris Lu effa00ed08 refactor 2020-11-26 11:21:58 -08:00
Chris Lu 513bcd6e0d filer: avoid duplicated FindEntry for deletion 2020-11-26 11:14:56 -08:00
Chris Lu 1ae108efca add debug message 2020-11-26 10:41:10 -08:00
Chris Lu a102157020 do not retry if failed with a non transport related error 2020-11-26 01:29:30 -08:00
Konstantin Lebedev 4e55baf5b1 s3 config changes 2020-11-26 03:50:53 +05:00
Konstantin Lebedev 52c8f2fc9a s3iam test 2020-11-26 02:26:45 +05:00
Konstantin Lebedev a26f1b2040 new pkg s3iam 2020-11-26 01:30:11 +05:00
Konstantin Lebedev 6206737df2 s3 configure 2020-11-25 21:02:31 +05:00
Chris LuandGitHub b3adb221b2 Merge pull request #1633 from tgbyte/fix/grafana-qps-factor
grafana: remove incorrect QPS factor
2020-11-23 08:05:25 -08:00
Thilo-Alexander Ginkel ec51d77dcf grafana: remove incorrect QPS factor 2020-11-23 12:00:36 +01:00
Chris Lu eab53ea80d filer leveldb store: a bit more efficient directory listing with prefix 2020-11-22 21:10:41 -08:00
Chris Lu d3be2ceedd 2.12 2020-11-22 17:17:33 -08:00
Chris Lu c7ebadc25d avoid possible concurrent access inside ensureCorrectWritables() 2020-11-22 17:15:59 -08:00
hilimdandGitHub 9aa990f80f Merge pull request #39 from chrislusf/master
sync
2020-11-22 20:29:17 +08:00
limd e8296104fc fix tls grpc ca path 2020-11-22 20:27:15 +08:00
Chris Lu 92f906b6fc remove zstd
fix https://github.com/chrislusf/seaweedfs/issues/1629
2020-11-21 13:06:45 -08:00
Chris LuandGitHub 025bd8d447 Update README.md 2020-11-21 12:55:44 -08:00
Chris LuandGitHub 5f3546a688 Merge pull request #1630 from demshin/master
fix typo
2020-11-20 09:26:35 -08:00
Aleksandr Demshin 176950ea78 fix typo 2020-11-20 19:50:46 +05:00
Chris Lu 7385103057 fix volume placement validating
fix https://github.com/chrislusf/seaweedfs/issues/1626
2020-11-20 01:12:25 -08:00
Konstantin Lebedev 27e73de797 Merge branch 'upstream_master' into store_s3cred
# Conflicts:
#	weed/s3api/filer_util.go
2020-11-19 18:16:44 +05:00
Chris Lu da04bb3d1b 1.5.6 2020-11-18 01:46:38 -08:00
Chris Lu 290b5e2cd0 directly delete file chunks
keeping current async deletions for now
2020-11-17 17:20:21 -08:00
Chris Lu 781585b195 remove unnecessary checking 2020-11-17 17:00:06 -08:00
Chris Lu 8cb8cd4cc5 add locks 2020-11-17 16:59:48 -08:00
Chris Lu ec052f75d0 add example scripts 2020-11-17 13:14:03 -08:00
Chris Lu 7c9e592c2d s3: avoid nil resp when having error
fix https://github.com/chrislusf/seaweedfs/issues/1622
2020-11-17 11:23:17 -08:00
Chris LuandGitHub a7258f024e Merge pull request #1621 from hilimd/master
HCFS: add replication parameter and fix close sequence
2020-11-17 03:13:44 -08:00
limd 4737df597d HCFS:
1. add replication parameter
2. fix close sequence
2020-11-17 19:05:57 +08:00
hilimdandGitHub aec071187e Merge pull request #38 from chrislusf/master
sync
2020-11-17 19:01:04 +08:00
Chris Lu dc304342b2 fs.configure: configurable volume growth 2020-11-17 01:00:02 -08:00
Chris Lu b04375a3d1 use alternative assign request 2020-11-17 00:36:21 -08:00
Chris Lu 9add554feb fail fast if user configures collection for a bucket 2020-11-16 19:57:08 -08:00
Chris Lu c13db8de80 remove deprecated options 2020-11-16 17:00:28 -08:00
Chris Lu 6204dc6e85 add comment 2020-11-16 16:57:31 -08:00
Chris Lu ef3e068c51 deprecating "filer.options.buckets_fsync" in filer.toml 2020-11-16 16:56:49 -08:00
Chris Lu 5f19e81dab filer confi: support hierachical configuration 2020-11-16 16:50:12 -08:00
Chris Lu ed1ce3f299 adjust help message 2020-11-16 09:54:26 -08:00
hilimdandGitHub 218561c206 Merge pull request #37 from chrislusf/master
sync
2020-11-16 16:30:19 +08:00
Chris Lu c0d279c54e filere.conf: prefer to use json format 2020-11-15 21:48:17 -08:00
Chris Lu 83527a8f55 adds more help message 2020-11-15 21:31:14 -08:00
Chris Lu fe01059675 volume id cache: reduce cache time 2020-11-15 21:27:21 -08:00
Chris Lu 61d96fde01 protect against edge cases when locations expires 2020-11-15 21:26:04 -08:00
Chris Lu af658ea970 fix typo 2020-11-15 21:16:28 -08:00
Chris Lu 98827d68d9 2.11 2020-11-15 20:25:56 -08:00
Chris Lu ee2fa14dbe filer conf: delete location specific configuration 2020-11-15 20:15:47 -08:00
Chris Lu 2bd6fd3bbe remove unused function 2020-11-15 20:15:07 -08:00
Chris Lu 71056dae07 fs.configure: read and local add filer configuration 2020-11-15 18:09:35 -08:00
Chris Lu 0ea5c087ce go fmt 2020-11-15 16:59:28 -08:00
Chris Lu 95c0de285d refactoring 2020-11-15 16:58:48 -08:00
Chris Lu 500bcab953 refactoring 2020-11-15 14:41:56 -08:00
Chris Lu 590f02179d filer: load filer conf when starting 2020-11-15 14:06:03 -08:00
Chris Lu 0a406f652e load filer conf and match by prefix 2020-11-15 00:26:05 -08:00
Chris Lu 68043cfcac add reference implementation to detect create/update/delete/rename events 2020-11-14 21:21:58 -08:00
Chris Lu 0fc9ffc603 able to read filer.conf if updated 2020-11-14 21:21:20 -08:00
Chris Lu 7cfa616843 raft: grpc wait for ready
related to https://github.com/chrislusf/seaweedfs/issues/1618

https://github.com/grpc/grpc/blob/master/doc/wait-for-ready.md

https://github.com/chrislusf/raft/commit/7c64624a0692a6058b2482f4f2857a77274187f0
2020-11-14 20:52:26 -08:00
Chris Lu 57c770a7b4 go get github.com/chrislusf/raft@v1.0.2 2020-11-14 20:39:12 -08:00
Chris Lu 442e092995 filer watch "/etc" folder for configuration changes 2020-11-14 14:26:08 -08:00
Chris LuandGitHub b2a72630da Update release.yml 2020-11-13 19:47:52 -08:00
Chris Lu 824e96ffcc updates 2020-11-13 12:47:46 -08:00
Chris Lu 3e362451d2 add example of watch files 2020-11-13 12:10:55 -08:00
Chris Lu 0d5355c614 rename 2020-11-13 11:43:25 -08:00
Chris Lu 7d24980840 HCFS: 1.5.4 2020-11-13 11:37:53 -08:00
Chris LuandGitHub 56d8e5b540 Update release.yml 2020-11-13 11:33:01 -08:00
Chris LuandGitHub b3f22a53b0 Merge pull request #1616 from taozix/master
adjust check bucket.
2020-11-13 01:58:06 -08:00
ruitao.liu a9990a1dc6 adjust check bucket if exist or has access. 2020-11-13 17:13:20 +08:00
hilimdandGitHub e0d5207ed9 Merge pull request #36 from chrislusf/master
sync
2020-11-13 15:34:38 +08:00
Chris Lu a2962604ad add volume id cache 2020-11-12 23:25:11 -08:00
Chris Lu 559dfacdac adding test example 2020-11-12 23:24:39 -08:00
Chris Lu e6333da65a enable admin to access all buckets 2020-11-12 13:57:54 -08:00
Chris Lu 7094492428 fix ErrNotFound 2020-11-12 13:30:46 -08:00
Chris Lu c6a0704019 rename function 2020-11-12 13:30:08 -08:00
Chris LuandGitHub ed3b0f81c6 Merge pull request #1613 from taozix/master
check permission for bucket delete/head.
2020-11-12 13:25:28 -08:00
ruitao.liu c4f0fd6e1b skip if entry.Extended map is nil. 2020-11-12 17:59:31 +08:00
ruitao.liu ab966410d2 return NoSuchBucket instead of InternalError delete non-existed bucket. 2020-11-12 16:44:16 +08:00
Chris Lu a4dfa00030 adjust filer conf 2020-11-12 00:39:59 -08:00
Chris Lu 2251a8e472 minor 2020-11-12 00:38:58 -08:00
Chris Lu 5a16f17e47 remove unused message type 2020-11-12 00:38:23 -08:00
ruitao.liu e06676f007 check permission for bucket delete/head. 2020-11-12 16:15:59 +08:00
Chris Lu c32b6f4d9d prepare for path based configuration 2020-11-11 23:46:45 -08:00
Chris LuandGitHub 0fbc27b640 Merge pull request #1612 from taozix/master
add owner attr for bucket.
2020-11-11 22:19:47 -08:00
ruitao.liu d7cc0498e0 check if bucket already exists. 2020-11-12 14:11:03 +08:00
Chris LuandGitHub 827930e249 Merge pull request #1610 from kmlebedev/prefer_read_in_this_dc
prefer to read from volumes in this data center
2020-11-11 22:09:41 -08:00
Konstantin Lebedev 0880aff224 update dc flag desc 2020-11-12 10:07:52 +05:00
Chris LuandGitHub 4300ca8142 Update README.md 2020-11-11 21:00:07 -08:00
ruitao.liu dbba8cb57e fix if nil map in entry. 2020-11-12 11:50:19 +08:00
Konstantin Lebedev aa30604cec fix tests 2020-11-12 08:49:38 +05:00
Konstantin Lebedev 1eec5c8d5d gen pb 2020-11-12 04:10:06 +05:00
Konstantin Lebedev fc7baef5bb fiil serverUrls sorted by data center 2020-11-12 02:13:33 +05:00
Chris Lu 745ee8d8f3 avoid unnecessary error message
fix https://github.com/chrislusf/seaweedfs/issues/1611
2020-11-11 13:00:05 -08:00
Chris Lu a29abd8600 add a {X-,}Idempotency-Key header for http POST
fix https://github.com/chrislusf/seaweedfs/issues/1592

according to https://github.com/golang/go/issues/19943
2020-11-11 12:56:53 -08:00
Chris Lu 8708e7a64d print out data size 2020-11-11 12:51:44 -08:00
Chris Lu c6bd244ebd add TODO 2020-11-11 12:51:27 -08:00
Konstantin Lebedev b73ef6aa95 Merge remote-tracking branch 'upstream/master' into prefer_read_in_this_dc 2020-11-11 23:29:57 +05:00
Konstantin Lebedev dc26012a3b initial 2020-11-11 15:03:47 +05:00
Chris Lu 81024761cd add local registry docker cluster 2020-11-11 02:02:30 -08:00
Chris Lu 86cdb2a3e5 adjust logs 2020-11-11 02:01:24 -08:00
Chris Lu 73f934d5de s3: do not close reader too early
fix https://github.com/chrislusf/seaweedfs/issues/1609
2020-11-11 01:49:39 -08:00
ruitao.liu 5b636b3242 Add bucket owner attr. 2020-11-11 16:20:59 +08:00
Chris Lu 15956d8a8e 2.10 2020-11-10 23:17:13 -08:00
hilimdandGitHub a38efe2e7b Merge pull request #35 from chrislusf/master
sync
2020-11-11 10:16:39 +08:00
Chris Lu de3bdd0651 delete old volume replica
related to https://github.com/chrislusf/seaweedfs/issues/1607

old is:
* older compaction revision
* older modified time
* smaller volume size
2020-11-10 12:26:05 -08:00
Chris Lu 1dd3a6ac36 avoid verbose logs 2020-11-09 15:56:11 -08:00
Chris LuandGitHub eee3f00559 Update README.md 2020-11-09 13:38:42 -08:00
Chris LuandGitHub cc62a2c9ac Update README.md 2020-11-09 13:38:18 -08:00
Chris Lu 6856b0d57e filer: add API to add/modify/delete tagging 2020-11-09 01:00:07 -08:00
Chris Lu 4f676aa7d3 2.09 2020-11-08 22:06:06 -08:00
Chris LuandGitHub be2bf1f102 Merge pull request #1603 from LazyDBA247-Anyvision/master
Chart Fix
2020-11-07 17:21:42 -08:00
LazyDBA247-Anyvision e7e3d8df7c fix reading the correct Values.yaml for s3 metricsPort 2020-11-08 02:07:47 +02:00
LazyDBA247-Anyvision de277418bf remove extra curly brace
helm read/need only 2
2020-11-08 02:07:16 +02:00
Chris LuandGitHub 2b6fdebd5e Merge pull request #1602 from LazyDBA247-Anyvision/master
naming typo fix
2020-11-07 08:12:19 -08:00
LazyDBA247-Anyvision 5779265992 naming typo fix 2020-11-07 18:00:59 +02:00
Chris LuandGitHub 63de3ea518 Merge pull request #1601 from LazyDBA247-Anyvision/master
grafana dashboard - use Helm Files.Get
2020-11-07 07:54:06 -08:00
LazyDBA247-Anyvision e92780b91e grafana dashboard - use Helm Files.Get
easier to use "original" json without escaping and tabs
updated json to latest from:
https://raw.githubusercontent.com/chrislusf/seaweedfs/master/other/metrics/grafana_seaweedfs.json
2020-11-07 17:40:59 +02:00
hilimdandGitHub 546f1bcb90 Merge pull request #34 from chrislusf/master
sync
2020-11-05 12:02:47 +08:00
Chris LuandGitHub 75887ba2a2 Update release.yml 2020-11-04 17:46:14 -08:00
Chris LuandGitHub 549422085b Update README.md 2020-11-04 12:30:46 -08:00
Chris LuandGitHub 5fb8530358 Merge pull request #1598 from kmlebedev/hotfix/ErrNoSuchKey
avoid blank response for 404
2020-11-04 10:18:17 -08:00
Chris LuandGitHub baced7b94f Update release.yml 2020-11-04 10:12:30 -08:00
Konstantin Lebedev 6cd6ff6962 avoid blank response for 404 2020-11-04 22:54:47 +05:00
Chris Lu 2121eba4cf add instructions to get help 2020-11-04 09:52:40 -08:00
Chris LuandGitHub eb0b8cd9d8 Update release.yml 2020-11-04 09:35:21 -08:00
Chris Lu 0dafcf1f5a volume: detect max volume count changes based on disk usage
fix https://github.com/chrislusf/seaweedfs/issues/1594
2020-11-03 14:43:17 -08:00
Chris Lu 06ee199ef3 ensure entryViewCache is in sync with the chunks 2020-11-03 12:22:19 -08:00
Chris Lu b132cb893f in case some chunks modified earliar are added later 2020-11-03 12:22:19 -08:00
Chris Lu 0ae4d7bfdf lock "addChunks()" 2020-11-03 12:22:19 -08:00
Chris LuandGitHub 8054ef2310 Update README.md 2020-11-03 10:08:07 -08:00
Konstantin Lebedev e1190b3224 load S3 config from filer
https://github.com/chrislusf/seaweedfs/issues/1500
2020-11-03 21:45:56 +05:00
Chris Lu c709059b69 HCFS: add close() to SeaweedFileSystem.java 2020-11-03 00:46:00 -08:00
Chris Lu d29b787220 store together with "Seaweed-" prefix 2020-11-03 00:21:10 -08:00
Chris Lu 5448781dfc filer: Headers with "Seaweed-" prefix are stored as extended properties 2020-11-03 00:15:51 -08:00
Chris Lu 0ecff9521d avoid []byte reuse 2020-11-02 23:27:54 -08:00
Chris Lu 031aa70da6 Revert "revert bytebufferpool, seems problematic"
This reverts commit e0fcab47c0.
2020-11-02 19:11:25 -08:00
Chris Lu c923170d7c Revert "go mod tidy"
This reverts commit 85e43b678f.
2020-11-02 19:11:11 -08:00
Chris Lu 85e43b678f go mod tidy 2020-11-02 14:23:33 -08:00
Chris Lu 7d5db73d98 go fmt 2020-11-02 14:21:07 -08:00
Chris Lu a9662d44ac avoid closing chunkSaveErrChan too early 2020-11-02 14:20:38 -08:00
Chris Lu e0fcab47c0 revert bytebufferpool, seems problematic 2020-11-02 13:49:38 -08:00
Chris Lu e1423a83dd mount: clear possible leftover entry data in memory 2020-11-01 23:28:56 -08:00
Chris Lu 448475e100 README: add quick start 2020-11-01 13:26:56 -08:00
Chris Lu 9b10d1ac33 2.08 2020-11-01 12:45:20 -08:00
Chris Lu 8750cac090 move to util.RetryWaitTime 2020-11-01 02:36:43 -08:00
Chris Lu ef908e166b break import cycle 2020-11-01 02:28:11 -08:00
Chris Lu 4609644658 mount: remove files that may still are open
related to https://github.com/chrislusf/seaweedfs/issues/1581
2020-11-01 01:33:26 -08:00
Chris Lu df8d976bb0 refactoring 2020-11-01 01:58:48 -07:00
Chris Lu 7192a378cc add retry to master clients also 2020-11-01 01:40:16 -07:00
Chris Lu 004aa9ca5d only retry transport related errors 2020-11-01 01:21:44 -07:00
Chris Lu f7b21973ac mount: add retry for all operations with filer
fix https://github.com/chrislusf/seaweedfs/issues/1589
2020-11-01 01:11:08 -07:00
Chris Lu de86945aeb go fmt 2020-10-31 16:45:38 -07:00
Chris Lu 306062b4e7 filer: add CORS support 2020-10-31 16:44:03 -07:00
Chris Lu 05acc33294 volume: add CORS support 2020-10-31 16:31:39 -07:00
Chris Lu 9708df47d1 ensure offset in the index file is positive 2020-10-31 15:50:01 -07:00
Chris Lu 10f9f1cc26 handle mknod requests 2020-10-30 23:51:32 -07:00
Chris Lu 8826601be1 mount: optional limit for the number of concurrent writers 2020-10-30 21:22:20 -07:00
Chris Lu be95f68ca7 scaffold for sftpd 2020-10-30 20:57:08 -07:00
Chris LuandGitHub b9ccaabdcc Merge pull request #1586 from kmlebedev/pre_stop_remove_volumes
delete volumes from master on stop volume server
2020-10-30 15:48:46 -07:00
Chris Lu 20b967e38c Update README.md 2020-10-30 15:45:32 -07:00
Konstantin Lebedev d2a4ffdd60 glog 2020-10-31 03:21:54 +05:00
Konstantin Lebedev 46303c36bf When the volume server is stopped, the master server immediately sees the deletion of volumes 2020-10-31 02:48:25 +05:00
Chris Lu eb32af25d4 make space for the QR code 2020-10-30 10:55:31 -07:00
Chris Lu 7ecbb4b3c9 clean up 2020-10-30 10:46:31 -07:00
Chris LuandGitHub 9081ff8e65 Merge pull request #1584 from alloneinfo/master
修改 weed filer.copy 上传目录时文件名变子目录的问题
2020-10-30 10:40:04 -07:00
KennyandGitHub 8a7f5eba99 Merge pull request #1 from alloneinfo/mymod
Update filer_copy.go
2020-10-30 18:17:15 +08:00
KennyandGitHub 9cc6575ab5 Update filer_copy.go
修改 weed filer.copy 上传目录时文件名变子目录的问题
2020-10-30 18:16:49 +08:00
Chris Lu c057dd1f64 add back upload retries 2020-10-30 02:16:34 -07:00
Chris Lu 19098f2c2d make a copy of the filer.entry for most read operations 2020-10-30 01:23:26 -07:00
Chris Lu 6135cbaa02 clear file.entry 2020-10-30 01:23:26 -07:00
Chris LuandGitHub 0cdf172694 Update go.yml 2020-10-29 23:46:54 -07:00
Chris LuandGitHub 09a7cb8353 Create go.yml 2020-10-29 23:41:54 -07:00
Chris LuandGitHub 0ab72a0904 Update release.yml 2020-10-29 23:41:36 -07:00
Chris LuandGitHub 737d6ed650 Update and rename go.yml to release.yml 2020-10-29 23:41:10 -07:00
Chris Lu 02dc51b1ed properly clear out the file.entry 2020-10-29 23:31:06 -07:00
Chris LuandGitHub abff1f67a6 Update go.yml 2020-10-29 23:26:40 -07:00
Chris LuandGitHub 202964a09b Update go.yml 2020-10-29 23:15:28 -07:00
Chris LuandGitHub e379fc3658 Update go.yml 2020-10-29 23:09:28 -07:00
Chris LuandGitHub 11697ca9fd Update go.yml 2020-10-29 23:01:41 -07:00
Chris LuandGitHub 08cbc714f0 Delete build_binary.yml 2020-10-29 22:49:39 -07:00
Chris LuandGitHub 23a0551c26 Update go.yml 2020-10-29 22:49:29 -07:00
Chris Lu 6560ac6466 volume loading: trim out unreachable idx file content
fix https://github.com/chrislusf/seaweedfs/issues/1583
2020-10-29 22:25:23 -07:00
Chris LuandGitHub cf0cd12943 Update build_binary.yml 2020-10-29 21:16:27 -07:00
Chris LuandGitHub 4c231054fb Update build_binary.yml 2020-10-29 21:01:25 -07:00
Chris LuandGitHub ba64390555 Create build_binary.yml 2020-10-29 20:54:05 -07:00
Chris Lu 0b68b68ec4 reload entry only when it is a hard link
fix https://github.com/chrislusf/seaweedfs/issues/1581
2020-10-29 16:32:45 -07:00
Chris Lu 47047516d6 Revert "increase default volume file size limit to 1024"
This reverts commit 0983060a

I am confused why this was changed to 1024 by myself. 1GB should be too large for most cases.
2020-10-29 15:46:29 -07:00
Chris LuandGitHub 6f8b426f4f Merge pull request #1578 from taozix/master
S3 bucket list, response with uploaded storageclass.
2020-10-29 08:32:27 -07:00
ruitao.liu 22a9ea0512 adjust s3 header file. 2020-10-29 16:05:40 +08:00
Chris Lu c6d9974fe7 server: Add option to enable/disable volume server
fix https://github.com/chrislusf/seaweedfs/issues/1572
2020-10-29 00:24:18 -07:00
ruitao.liu b917be7955 S3 bucket list, response with uploaded storageclass. 2020-10-29 14:57:19 +08:00
Chris LuandGitHub 8a55b7053f Merge pull request #1577 from kmlebedev/grpc_waitforeeady
add WaitForReady to grpc DialOption. this will affect all grpc calls. Not quite sure about the possible effects. let's see.
2020-10-28 20:39:56 -07:00
Konstantin Lebedev 918546bbdb add WaitForReady to grpc DialOption 2020-10-29 08:29:04 +05:00
Chris LuandGitHub 6364d59f92 Merge pull request #1575 from kmlebedev/shell_mark_writable
add readonly
2020-10-28 12:13:08 -07:00
Konstantin Lebedev fab01f9d8d add readonly 2020-10-28 23:17:03 +05:00
Chris LuandGitHub 2a10904d03 Merge pull request #1574 from kmlebedev/shell_mark_writable
add shell command volume mark writable
2020-10-28 11:07:09 -07:00
Konstantin Lebedev 884db215a1 add shell command volume mark writable 2020-10-28 22:47:09 +05:00
Chris LuandGitHub c321378976 Merge pull request #1571 from kmlebedev/stats_readonly_detail
collection Volume ReadOnly Count with detailed status
2020-10-28 08:58:10 -07:00
Konstantin Lebedev 1ad1b8c4f6 collection Volume ReadOnly Count with detailed status 2020-10-28 17:38:26 +05:00
Chris LuandGitHub 326fcdd86b Merge pull request #1569 from taozix/master
save s3 metadata to filer.
2020-10-28 03:27:24 -07:00
ruitao.liu 2dcc178d0a save s3 metadata to filer. 2020-10-28 18:16:05 +08:00
Chris Lu 5db46bb0dd typo 2020-10-28 01:45:55 -07:00
Chris LuandGitHub 9ff0490dab Update README.md 2020-10-28 01:29:06 -07:00
Chris Lu 744c5594da volume: automatically trim out unreachable entries 2020-10-28 01:14:39 -07:00
Chris Lu 3e925faddd trim out name extension 2020-10-28 01:14:05 -07:00
Chris LuandGitHub 73d924f1ee Merge pull request #1568 from binbinshi/master
sometime volumeServer restart occur out of memory error
2020-10-27 23:45:32 -07:00
shibinbin a67eb1afa1 fix: restart volumeserver sometime occurred out of memory error 2020-10-28 12:03:06 +08:00
shibinbin 7cc07655d4 Merge remote-tracking branch 'upstream/master' 2020-10-28 11:36:42 +08:00
Chris Lu 53c3aad875 volume: add a note file to avoid incomplete volume files
fix https://github.com/chrislusf/seaweedfs/issues/1567
2020-10-27 15:56:49 -07:00
Chris Lu 6da87720eb shorter tag prefix 2020-10-27 15:33:26 -07:00
Chris Lu 24bf142596 copy large file first 2020-10-27 15:31:15 -07:00
Chris LuandGitHub 432c6f8db3 Merge pull request #1566 from taozix/master
return x-amz-tag-count header when GET object.
2020-10-27 13:16:58 -07:00
Chris Lu 06c15ab35c volume: add special handling for .dat larger than 32GB 2020-10-27 13:11:56 -07:00
ruitao.liu 72f6b77dea fix tag prefix. 2020-10-27 18:01:37 +08:00
ruitao.liu 8766ca1b95 rename s3 tag prefix. 2020-10-27 17:33:24 +08:00
ruitao.liu 19026ae55d return x-amz-tag-count header when GET object. 2020-10-27 16:49:31 +08:00
hilimdandGitHub 843865f2ca Merge pull request #33 from chrislusf/master
sync
2020-10-26 22:01:50 +08:00
Chris Lu 44921220b0 2.07 2020-10-25 22:03:46 -07:00
Chris Lu 283d584141 update to correct block size 2020-10-25 22:03:37 -07:00
Chris Lu c693c98c15 write a lot of files 2020-10-25 19:28:11 -07:00
Chris Lu e71463a9eb mount: invalide file cache when metadata is changed 2020-10-25 19:24:15 -07:00
Chris Lu e219c57849 passing full path when assign volume locations 2020-10-25 15:46:29 -07:00
Chris Lu f375b93aef renaming 2020-10-25 15:32:43 -07:00
Chris Lu 596d476e3d HCFS: 1.5.2 2020-10-25 14:44:18 -07:00
Chris Lu 63b0fb54f7 minor 2020-10-25 14:15:53 -07:00
hilimdandGitHub cf7a1c722f Merge pull request #32 from chrislusf/master
sync
2020-10-22 15:50:49 +08:00
hilimdandGitHub ab1105c524 Merge pull request #31 from chrislusf/master
sync
2020-10-21 20:04:11 +08:00
hilimdandGitHub 2c40f56e5a Merge pull request #30 from chrislusf/master
sync
2020-10-19 15:16:44 +08:00
hilimdandGitHub 6e63e5eaf0 Merge pull request #29 from chrislusf/master
sync
2020-10-19 09:42:43 +08:00
hilimdandGitHub 62af2d961d Merge pull request #28 from chrislusf/master
sync
2020-10-18 09:44:04 +08:00
hilimdandGitHub 5c2e409ffe Merge pull request #27 from chrislusf/master
sync
2020-10-15 15:15:01 +08:00
hilimdandGitHub a911375798 Merge pull request #26 from chrislusf/master
sync
2020-10-14 16:39:45 +08:00
hilimdandGitHub 2ff727a32d Merge pull request #25 from chrislusf/master
sync
2020-10-12 11:01:13 +08:00
hilimdandGitHub b9a446839a Merge pull request #24 from chrislusf/master
sync
2020-10-10 16:20:26 +08:00
hilimdandGitHub 411e49f964 Merge pull request #23 from chrislusf/master
sync
2020-10-10 13:07:57 +08:00
limd ac162fc857 hdfs: Hadoop on SeaweedFS: create empty file 2020-10-10 13:07:27 +08:00
limd 95bfec4931 hadoop: filesystem cannot create file
issues: https://github.com/chrislusf/seaweedfs/issues/1494
2020-09-26 01:38:48 +08:00
shibinbin 29a4c3944e Merge remote-tracking branch 'upstream/master' 2020-06-11 11:14:31 +08:00
shibinbin 40334bc28d Merge remote-tracking branch 'upstream/master' 2020-06-04 17:24:18 +08:00
binbinshiandGitHub d892cad15d Merge pull request #1 from chrislusf/master
update from chrisluf
2020-02-05 16:56:23 +08:00
311 changed files with 13530 additions and 5594 deletions
+1
View File
@@ -9,6 +9,7 @@ assignees: ''
Sponsors SeaweedFS via Patreon https://www.patreon.com/seaweedfs
Report issues here. Ask questions here https://stackoverflow.com/questions/tagged/seaweedfs
Please ask questions in https://github.com/chrislusf/seaweedfs/discussions
example of a good issue report:
https://github.com/chrislusf/seaweedfs/issues/1005
+22
View File
@@ -0,0 +1,22 @@
name: Cleanup
on:
push:
branches: [ master ]
jobs:
build:
name: Build
runs-on: ubuntu-latest
steps:
- name: Delete old release assets
uses: mknejp/delete-release-assets@v1
with:
token: ${{ github.token }}
tag: dev
fail-if-no-assets: false
assets: |
weed-*
+62
View File
@@ -0,0 +1,62 @@
name: Release
on:
push:
branches: [ master ]
jobs:
build:
name: Build
runs-on: ubuntu-latest
strategy:
matrix:
goos: [linux, windows, darwin, freebsd ]
goarch: [amd64, arm]
exclude:
- goarch: arm
goos: darwin
- goarch: arm
goos: windows
steps:
- name: Check out code into the Go module directory
uses: actions/checkout@v2
- name: Wait for the deletion
uses: jakejarvis/wait-action@master
with:
time: '30s'
- name: Set BUILD_TIME env
run: echo BUILD_TIME=$(date -u +%Y-%m-%d-%H-%M) >> ${GITHUB_ENV}
- name: Go Release Binaries
uses: wangyoucao577/go-release-action@v1.14
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
goos: ${{ matrix.goos }}
goarch: ${{ matrix.goarch }}
release_tag: dev
overwrite: true
build_flags: -tags 5BytesOffset # optional, default is
ldflags: -extldflags -static -X github.com/chrislusf/seaweedfs/weed/util.COMMIT=${{github.sha}}
# Where to run `go build .`
project_path: weed
binary_name: weed-large-disk
asset_name: "weed-large-disk-${{ env.BUILD_TIME }}-${{ matrix.goos }}-${{ matrix.goarch }}"
- name: Go Release Binaries
uses: wangyoucao577/go-release-action@v1.14
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
goos: ${{ matrix.goos }}
goarch: ${{ matrix.goarch }}
release_tag: dev
overwrite: true
ldflags: -extldflags -static -X github.com/chrislusf/seaweedfs/weed/util.COMMIT=${{github.sha}}
# Where to run `go build .`
project_path: weed
binary_name: weed-
asset_name: "weed-${{ env.BUILD_TIME }}-${{ matrix.goos }}-${{ matrix.goarch }}"
+42 -41
View File
@@ -1,14 +1,17 @@
# SeaweedFS
[![Slack](https://img.shields.io/badge/slack-purple)](https://join.slack.com/t/seaweedfs/shared_invite/enQtMzI4MTMwMjU2MzA3LTEyYzZmZWYzOGQ3MDJlZWMzYmI0OTE4OTJiZjJjODBmMzUxNmYwODg0YjY3MTNlMjBmZDQ1NzQ5NDJhZWI2ZmY)
[![Twitter](https://img.shields.io/twitter/follow/seaweedfs.svg?style=social&label=Follow)](https://twitter.com/intent/follow?screen_name=seaweedfs)
[![Build Status](https://travis-ci.org/chrislusf/seaweedfs.svg?branch=master)](https://travis-ci.org/chrislusf/seaweedfs)
[![GoDoc](https://godoc.org/github.com/chrislusf/seaweedfs/weed?status.svg)](https://godoc.org/github.com/chrislusf/seaweedfs/weed)
[![Wiki](https://img.shields.io/badge/docs-wiki-blue.svg)](https://github.com/chrislusf/seaweedfs/wiki)
[![Docker Pulls](https://img.shields.io/docker/pulls/chrislusf/seaweedfs.svg?maxAge=4800)](https://hub.docker.com/r/chrislusf/seaweedfs/)
![SeaweedFS Logo](https://raw.githubusercontent.com/chrislusf/seaweedfs/master/note/seaweedfs.png)
<h2 align="center">Supporting SeaweedFS</h2>
<h2 align="center"><a href="https://www.patreon.com/seaweedfs">Sponsor SeaweedFS via Patreon</a></h2>
SeaweedFS is an independent Apache-licensed open source project with its ongoing development made
possible entirely thanks to the support of these awesome [backers](https://github.com/chrislusf/seaweedfs/blob/master/backers.md).
@@ -17,8 +20,6 @@ If you'd like to grow SeaweedFS even stronger, please consider joining our
Your support will be really appreciated by me and other supporters!
<h3 align="center"><a href="https://www.patreon.com/seaweedfs">Sponsor SeaweedFS via Patreon</a></h3>
<!--
<h4 align="center">Platinum</h4>
@@ -27,24 +28,12 @@ Your support will be really appreciated by me and other supporters!
Add your name or icon here
</a>
</p>
<h4 align="center">Gold</h4>
<table>
<tbody>
<tr>
<td align="center" valign="middle">
<a href="" target="_blank">
Add your name or icon here
</a>
</td>
</tr>
<tr></tr>
</tbody>
</table>
-->
### Gold Sponsors
![shuguang](https://raw.githubusercontent.com/chrislusf/seaweedfs/master/note/shuguang.png)
---
@@ -58,11 +47,12 @@ Your support will be really appreciated by me and other supporters!
Table of Contents
=================
* [Quick Start](#quick-start)
* [Introduction](#introduction)
* [Features](#features)
* [Additional Features](#additional-features)
* [Filer Features](#filer-features)
* [Example Usage](#example-usage)
* [Example: Using Seaweed Object Store](#example-Using-Seaweed-Object-Store)
* [Architecture](#architecture)
* [Compared to Other File Systems](#compared-to-other-file-systems)
* [Compared to HDFS](#compared-to-hdfs)
@@ -75,6 +65,13 @@ Table of Contents
* [Benchmark](#Benchmark)
* [License](#license)
## Quick Start ##
* Download the latest binary from https://github.com/chrislusf/seaweedfs/releases and unzip a single binary file `weed` or `weed.exe`
* Run `weed server -dir=/some/data/dir -s3` to start one master, one volume server, one filer, and one S3 gateway.
Also, to increase capacity, just add more volume servers by running `weed volume -dir="/some/data/dir2" -mserver="<master_host>:9333" -port=8081` locally, or on a different machine, or on thoudsands of machines. That is it!
## Introduction ##
SeaweedFS is a simple and highly scalable distributed file system. There are two objectives:
@@ -82,15 +79,17 @@ SeaweedFS is a simple and highly scalable distributed file system. There are two
1. to store billions of files!
2. to serve the files fast!
SeaweedFS started as an Object Store to handle small files efficiently. Instead of managing all file metadata in a central master, the central master only manages file volumes, and it lets these volume servers manage files and their metadata. This relieves concurrency pressure from the central master and spreads file metadata into volume servers, allowing faster file access (O(1), usually just one disk read operation).
SeaweedFS started as an Object Store to handle small files efficiently. Instead of managing all file metadata in a central master, the central master only manages volumes on volume servers, and these volume servers manage files and their metadata. This relieves concurrency pressure from the central master and spreads file metadata into volume servers, allowing faster file access (O(1), usually just one disk read operation).
SeaweedFS can transparently integrate with the cloud. With hot data on local cluster, and warm data on the cloud with O(1) access time, SeaweedFS can achieve both fast local access time and elastic cloud storage capacity, without any client side changes.
SeaweedFS can transparently integrate with the cloud. With hot data on local cluster, and warm data on the cloud with O(1) access time, SeaweedFS can achieve both fast local access time and elastic cloud storage capacity. What's more, the cloud storage access API cost is minimized. Faster and Cheaper than direct cloud storage!
There is only 40 bytes of disk storage overhead for each file's metadata. It is so simple with O(1) disk reads that you are welcome to challenge the performance with your actual use cases.
SeaweedFS started by implementing [Facebook's Haystack design paper](http://www.usenix.org/event/osdi10/tech/full_papers/Beaver.pdf). Also, SeaweedFS implements erasure coding with ideas from [f4: Facebook’s Warm BLOB Storage System](https://www.usenix.org/system/files/conference/osdi14/osdi14-paper-muralidhar.pdf)
On top of the object store, optional [Filer] can support directories and POSIX attributes. Filer is a separate linearly-scalable stateless server with customizable metadata stores, e.g., MySql, Postgres, Mongodb, Redis, Cassandra, Elastic Search, LevelDB, MemSql, TiDB, Etcd, CockroachDB, etc.
On top of the object store, optional [Filer] can support directories and POSIX attributes. Filer is a separate linearly-scalable stateless server with customizable metadata stores, e.g., MySql, Postgres, Redis, Cassandra, HBase, Mongodb, Elastic Search, LevelDB, RocksDB, MemSql, TiDB, Etcd, CockroachDB, etc.
For any distributed key value stores, the large values can be offloaded to SeaweedFS. With the fast access speed and linearly scalable capacity, SeaweedFS can work as a distributed [Key-Large-Value store][KeyLargeValueStore].
[Back to TOC](#table-of-contents)
@@ -101,7 +100,7 @@ On top of the object store, optional [Filer] can support directories and POSIX a
* Automatic compaction to reclaim disk space after deletion or update.
* [Automatic entry TTL expiration][VolumeServerTTL].
* Any server with some disk spaces can add to the total storage space.
* Adding/Removing servers does **not** cause any data re-balancing.
* Adding/Removing servers does **not** cause any data re-balancing unless triggered by admin commands.
* Optional picture resizing.
* Support ETag, Accept-Range, Last-Modified, etc.
* Support in-memory/leveldb/readonly mode tuning for memory/performance balance.
@@ -113,16 +112,20 @@ On top of the object store, optional [Filer] can support directories and POSIX a
## Filer Features ##
* [Filer server][Filer] provides "normal" directories and files via http.
* [Super Large Files][SuperLargeFiles] stores large or super large files in tens of TB.
* [File TTL][FilerTTL] automatically expires file metadata and actual file data.
* [Mount filer][Mount] reads and writes files directly as a local directory via FUSE.
* [Filer Store Replication][FilerStoreReplication] enables HA for filer meta data stores.
* [Active-Active Replication][ActiveActiveAsyncReplication] enables asynchronous one-way or two-way cross cluster continuous replication.
* [Amazon S3 compatible API][AmazonS3API] accesses files with S3 tooling.
* [Hadoop Compatible File System][Hadoop] accesses files from Hadoop/Spark/Flink/etc or even runs HBase.
* [Async Replication To Cloud][BackupToCloud] has extremely fast local access and backups to Amazon S3, Google Cloud Storage, Azure, BackBlaze.
* [WebDAV] accesses as a mapped drive on Mac and Windows, or from mobile devices.
* [AES256-GCM Encrypted Storage][FilerDataEncryption] safely stores the encrypted data.
* [File TTL][FilerTTL] automatically purges file metadata and actual file data.
* [Super Large Files][SuperLargeFiles] stores large or super large files in tens of TB.
## Kubernetes ##
* [Kubernetes CSI Driver][SeaweedFsCsiDriver] A Container Storage Interface (CSI) Driver. [![Docker Pulls](https://img.shields.io/docker/pulls/chrislusf/seaweedfs-csi-driver.svg?maxAge=4800)](https://hub.docker.com/r/chrislusf/seaweedfs-csi-driver/)
* [SeaweedFS Operator](https://github.com/seaweedfs/seaweedfs-operator)
[Filer]: https://github.com/chrislusf/seaweedfs/wiki/Directories-and-Files
[SuperLargeFiles]: https://github.com/chrislusf/seaweedfs/wiki/Data-Structure-for-Large-Files
@@ -138,10 +141,12 @@ On top of the object store, optional [Filer] can support directories and POSIX a
[VolumeServerTTL]: https://github.com/chrislusf/seaweedfs/wiki/Store-file-with-a-Time-To-Live
[SeaweedFsCsiDriver]: https://github.com/seaweedfs/seaweedfs-csi-driver
[ActiveActiveAsyncReplication]: https://github.com/chrislusf/seaweedfs/wiki/Filer-Active-Active-cross-cluster-continuous-synchronization
[FilerStoreReplication]: https://github.com/chrislusf/seaweedfs/wiki/Filer-Store-Replication
[KeyLargeValueStore]: https://github.com/chrislusf/seaweedfs/wiki/Filer-as-a-Key-Large-Value-Store
[Back to TOC](#table-of-contents)
## Example Usage ##
## Example: Using Seaweed Object Store ##
By default, the master node runs on port 9333, and the volume nodes run on port 8080.
Let's start one master node, and two volume nodes on port 8080 and 8081. Ideally, they should be started from different machines. We'll use localhost as an example.
@@ -339,7 +344,7 @@ Usually hot data are fresh and warm data are old. SeaweedFS puts the newly creat
With the O(1) access time, the network latency cost is kept at minimum.
If the hot~warm data is split as 20~80, with 20 servers, you can achieve storage capacity of 100 servers. That's a cost saving of 80%! Or you can repurpose the 80 servers to store new data also, and get 5X storage throughput.
If the hot/warm data is split as 20/80, with 20 servers, you can achieve storage capacity of 100 servers. That's a cost saving of 80%! Or you can repurpose the 80 servers to store new data also, and get 5X storage throughput.
[Back to TOC](#table-of-contents)
@@ -369,7 +374,7 @@ The architectures are mostly the same. SeaweedFS aims to store and read files fa
* SeaweedFS optimizes for small files, ensuring O(1) disk seek operation, and can also handle large files.
* SeaweedFS statically assigns a volume id for a file. Locating file content becomes just a lookup of the volume id, which can be easily cached.
* SeaweedFS Filer metadata store can be any well-known and proven data stores, e.g., Cassandra, Mongodb, Redis, Elastic Search, MySql, Postgres, MemSql, TiDB, CockroachDB, Etcd etc, and is easy to customized.
* SeaweedFS Filer metadata store can be any well-known and proven data stores, e.g., Redis, Cassandra, HBase, Mongodb, Elastic Search, MySql, Postgres, MemSql, TiDB, CockroachDB, Etcd etc, and is easy to customized.
* SeaweedFS Volume server also communicates directly with clients via HTTP, supporting range queries, direct uploads, etc.
| System | File Metadata | File Content Read| POSIX | REST API | Optimized for large number of small files |
@@ -407,11 +412,11 @@ SeaweedFS has a centralized master group to look up free volumes, while Ceph use
Same as SeaweedFS, Ceph is also based on the object store RADOS. Ceph is rather complicated with mixed reviews.
Ceph uses CRUSH hashing to automatically manage the data placement. SeaweedFS places data by assigned volumes.
Ceph uses CRUSH hashing to automatically manage the data placement, which is efficient to locate the data. But the data has to be placed according to the CRUSH algorithm. Any wrong configuration would cause data loss. SeaweedFS places data by assigning them to any writable volumes. If writes to one volume failed, just pick another volume to write. Adding more volumes are also as simple as it can be.
SeaweedFS is optimized for small files. Small files are stored as one continuous block of content, with at most 8 unused bytes between files. Small file access is O(1) disk read.
SeaweedFS Filer uses off-the-shelf stores, such as MySql, Postgres, Mongodb, Redis, Elastic Search, Cassandra, MemSql, TiDB, CockroachCB, Etcd, to manage file directories. These stores are proven, scalable, and easier to manage.
SeaweedFS Filer uses off-the-shelf stores, such as MySql, Postgres, Mongodb, Redis, Elastic Search, Cassandra, HBase, MemSql, TiDB, CockroachCB, Etcd, to manage file directories. These stores are proven, scalable, and easier to manage.
| SeaweedFS | comparable to Ceph | advantage |
| ------------- | ------------- | ---------------- |
@@ -425,9 +430,10 @@ SeaweedFS Filer uses off-the-shelf stores, such as MySql, Postgres, Mongodb, Red
MinIO follows AWS S3 closely and is ideal for testing for S3 API. It has good UI, policies, versionings, etc. SeaweedFS is trying to catch up here. It is also possible to put MinIO as a gateway in front of SeaweedFS later.
MinIO metadata are in simple files. Each file write will incur meta file writes.
MinIO metadata are in simple files. Each file write will incur extra writes to corresponding meta file.
MinIO does not have optimization for large number of small files.
MinIO does not have optimization for lots of small files. The files are simply stored as is to local disks.
Plus the extra meta file and shards for erasure coding, it only amplifies the LOSF problem.
MinIO has multiple disk IO to read one file. SeaweedFS has O(1) disk reads, even for erasure coded files.
@@ -439,17 +445,12 @@ MinIO has specific requirements on storage layout. It is not flexible to adjust
## Dev Plan ##
More tools and documentation, on how to maintain and scale the system. For example, how to move volumes, automatically balancing data, how to grow volumes, how to check system status, etc.
Other key features include: Erasure Encoding, JWT security.
* More tools and documentation, on how to manage and scale the system.
* Read and write stream data.
* Support structured data.
This is a super exciting project! And we need helpers and [support](https://www.patreon.com/seaweedfs)!
BTW, We suggest run the code style check script `util/gostd` before you push your branch to remote, it will make SeaweedFS easy to review, maintain and develop:
```
$ ./util/gostd
```
[Back to TOC](#table-of-contents)
## Installation Guide ##
+3
View File
@@ -12,6 +12,7 @@ RUN \
SUPERCRONIC=supercronic-linux-$ARCH && \
# Install SeaweedFS and Supercronic ( for cron job mode )
apk add --no-cache --virtual build-dependencies --update wget curl ca-certificates && \
apk add fuse && \
wget -P /tmp https://github.com/$(curl -s -L https://github.com/chrislusf/seaweedfs/releases/latest | egrep -o "chrislusf/seaweedfs/releases/download/.*/linux_$ARCH.tar.gz") && \
tar -C /usr/bin/ -xzvf /tmp/linux_$ARCH.tar.gz && \
curl -fsSLO "$SUPERCRONIC_URL" && \
@@ -36,6 +37,8 @@ EXPOSE 19333
EXPOSE 9333
# s3 server http port
EXPOSE 8333
# webdav server http port
EXPOSE 7333
RUN mkdir -p /data/filerldb2
+6 -1
View File
@@ -1,7 +1,9 @@
FROM frolvlad/alpine-glibc as builder
RUN apk add git go g++
RUN apk add git go g++ fuse
RUN mkdir -p /go/src/github.com/chrislusf/
RUN git clone https://github.com/chrislusf/seaweedfs /go/src/github.com/chrislusf/seaweedfs
ARG BRANCH=${BRANCH:-master}
RUN cd /go/src/github.com/chrislusf/seaweedfs && git checkout $BRANCH
RUN cd /go/src/github.com/chrislusf/seaweedfs/weed \
&& export LDFLAGS="-X github.com/chrislusf/seaweedfs/weed/util.COMMIT=$(git rev-parse --short HEAD)" \
&& go install -ldflags "${LDFLAGS}"
@@ -12,6 +14,7 @@ COPY --from=builder /root/go/bin/weed /usr/bin/
RUN mkdir -p /etc/seaweedfs
COPY --from=builder /go/src/github.com/chrislusf/seaweedfs/docker/filer.toml /etc/seaweedfs/filer.toml
COPY --from=builder /go/src/github.com/chrislusf/seaweedfs/docker/entrypoint.sh /entrypoint.sh
RUN apk add fuse # for weed mount
# volume server gprc port
EXPOSE 18080
@@ -27,6 +30,8 @@ EXPOSE 19333
EXPOSE 9333
# s3 server http port
EXPOSE 8333
# webdav server http port
EXPOSE 7333
RUN mkdir -p /data/filerldb2
+6 -1
View File
@@ -1,7 +1,9 @@
FROM frolvlad/alpine-glibc as builder
RUN apk add git go g++
RUN apk add git go g++ fuse
RUN mkdir -p /go/src/github.com/chrislusf/
RUN git clone https://github.com/chrislusf/seaweedfs /go/src/github.com/chrislusf/seaweedfs
ARG BRANCH=${BRANCH:-master}
RUN cd /go/src/github.com/chrislusf/seaweedfs && git checkout $BRANCH
RUN cd /go/src/github.com/chrislusf/seaweedfs/weed \
&& export LDFLAGS="-X github.com/chrislusf/seaweedfs/weed/util.COMMIT=$(git rev-parse --short HEAD)" \
&& go install -tags 5BytesOffset -ldflags "${LDFLAGS}"
@@ -12,6 +14,7 @@ COPY --from=builder /root/go/bin/weed /usr/bin/
RUN mkdir -p /etc/seaweedfs
COPY --from=builder /go/src/github.com/chrislusf/seaweedfs/docker/filer.toml /etc/seaweedfs/filer.toml
COPY --from=builder /go/src/github.com/chrislusf/seaweedfs/docker/entrypoint.sh /entrypoint.sh
RUN apk add fuse # for weed mount
# volume server gprc port
EXPOSE 18080
@@ -27,6 +30,8 @@ EXPOSE 19333
EXPOSE 9333
# s3 server http port
EXPOSE 8333
# webdav server http port
EXPOSE 7333
RUN mkdir -p /data/filerldb2
+3
View File
@@ -4,6 +4,7 @@ COPY ./weed /usr/bin/
RUN mkdir -p /etc/seaweedfs
COPY ./filer.toml /etc/seaweedfs/filer.toml
COPY ./entrypoint.sh /entrypoint.sh
RUN apk add fuse # for weed mount
# volume server grpc port
EXPOSE 18080
@@ -19,6 +20,8 @@ EXPOSE 19333
EXPOSE 9333
# s3 server http port
EXPOSE 8333
# webdav server http port
EXPOSE 7333
RUN mkdir -p /data/filerldb2
+20 -2
View File
@@ -10,10 +10,28 @@ build:
rm ./weed
dev: build
docker-compose -f local-dev-compose.yml -p seaweedfs up
docker-compose -f compose/local-dev-compose.yml -p seaweedfs up
dev_mount: build
docker-compose -f compose/local-mount-compose.yml -p seaweedfs up
k8s: build
docker-compose -f compose/local-k8s-compose.yml -p seaweedfs up
dev_registry: build
docker-compose -f compose/local-registry-compose.yml -p seaweedfs up
dev_replicate: build
docker-compose -f compose/local-replicate-compose.yml -p seaweedfs up
cluster: build
docker-compose -f local-cluster-compose.yml -p seaweedfs up
docker-compose -f compose/local-cluster-compose.yml -p seaweedfs up
2clusters: build
docker-compose -f compose/local-clusters-compose.yml -p seaweedfs up
filer_etcd: build
docker stack deploy -c compose/swarm-etcd.yml fs
clean:
rm ./weed
@@ -19,12 +19,32 @@ services:
- 9335:9335
- 19335:19335
command: "master -ip=master2 -port=9335 -peers=master0:9333,master1:9334,master2:9335 -mdir=/data/m3"
volume:
volume1:
image: chrislusf/seaweedfs:local
ports:
- 8080:8080
- 18080:18080
command: 'volume -mserver="master0:9333,master1:9334,master2:9335" -port=8080 -ip=volume -publicUrl=localhost:8080'
command: 'volume -mserver="master0:9333,master1:9334,master2:9335" -port=8080 -ip=volume1 -publicUrl=localhost:8080'
depends_on:
- master0
- master1
- master2
volume2:
image: chrislusf/seaweedfs:local
ports:
- 8082:8082
- 18082:18082
command: 'volume -mserver="master0:9333,master1:9334,master2:9335" -port=8082 -ip=volume2 -publicUrl=localhost:8082'
depends_on:
- master0
- master1
- master2
volume3:
image: chrislusf/seaweedfs:local
ports:
- 8083:8083
- 18083:18083
command: 'volume -mserver="master0:9333,master1:9334,master2:9335" -port=8083 -ip=volume3 -publicUrl=localhost:8083'
depends_on:
- master0
- master1
@@ -39,7 +59,8 @@ services:
- master0
- master1
- master2
- volume
- volume1
- volume2
s3:
image: chrislusf/seaweedfs:local
ports:
@@ -49,5 +70,6 @@ services:
- master0
- master1
- master2
- volume
- volume1
- volume2
- filer
+23
View File
@@ -0,0 +1,23 @@
version: '2'
services:
server1:
image: chrislusf/seaweedfs:local
ports:
- 9333:9333
- 19333:19333
- 8084:8080
- 18084:18080
- 8888:8888
- 18888:18888
command: "server -ip=server1 -filer -volume.max=0 -master.volumeSizeLimitMB=1024 -volume.preStopSeconds=1"
server2:
image: chrislusf/seaweedfs:local
ports:
- 9334:9333
- 19334:19333
- 8085:8080
- 18085:18080
- 8889:8888
- 18889:18888
command: "server -ip=server2 -filer -volume.max=0 -master.volumeSizeLimitMB=1024 -volume.preStopSeconds=1"
@@ -12,7 +12,7 @@ services:
ports:
- 8080:8080
- 18080:18080
command: "volume -mserver=master:9333 -port=8080 -ip=volume"
command: "volume -mserver=master:9333 -port=8080 -ip=volume -preStopSeconds=1"
depends_on:
- master
filer:
@@ -33,3 +33,14 @@ services:
- master
- volume
- filer
mount:
image: chrislusf/seaweedfs:local
privileged: true
cap_add:
- SYS_ADMIN
mem_limit: 4096m
command: '-v=4 mount -filer="filer:8888" -dirAutoCreate -dir=/mnt/seaweedfs -cacheCapacityMB=100 -concurrentWriters=128'
depends_on:
- master
- volume
- filer
+94
View File
@@ -0,0 +1,94 @@
version: '2'
services:
master:
image: chrislusf/seaweedfs:local
ports:
- 9333:9333
- 19333:19333
command: "master -ip=master"
volume:
image: chrislusf/seaweedfs:local
ports:
- 8080:8080
- 18080:18080
command: "volume -mserver=master:9333 -port=8080 -ip=volume"
depends_on:
- master
mysql:
image: percona/percona-server:5.7
ports:
- 3306:3306
volumes:
- ./seaweedfs.sql:/docker-entrypoint-initdb.d/seaweedfs.sql
environment:
- MYSQL_ROOT_PASSWORD=secret
- MYSQL_DATABASE=seaweedfs
- MYSQL_PASSWORD=secret
- MYSQL_USER=seaweedfs
filer:
image: chrislusf/seaweedfs:local
ports:
- 8888:8888
- 18888:18888
environment:
- WEED_MYSQL_HOSTNAME=mysql
- WEED_MYSQL_PORT=3306
- WEED_MYSQL_DATABASE=seaweedfs
- WEED_MYSQL_USERNAME=seaweedfs
- WEED_MYSQL_PASSWORD=secret
- WEED_MYSQL_ENABLED=true
- WEED_MYSQL_CONNECTION_MAX_IDLE=5
- WEED_MYSQL_CONNECTION_MAX_OPEN=75
# "refresh" connection every 10 minutes, eliminating mysql closing "old" connections
- WEED_MYSQL_CONNECTION_MAX_LIFETIME_SECONDS=600
# enable usage of memsql as filer backend
- WEED_MYSQL_INTERPOLATEPARAMS=true
- WEED_LEVELDB2_ENABLED=false
command: '-v 9 filer -master="master:9333"'
depends_on:
- master
- volume
- mysql
ingress:
image: jwilder/nginx-proxy:alpine
ports:
- "80:80"
volumes:
- /var/run/docker.sock:/tmp/docker.sock:ro
- ./nginx/proxy.conf:/etc/nginx/proxy.conf
s3:
image: chrislusf/seaweedfs:local
ports:
- 8333:8333
command: '-v 9 s3 -filer="filer:8888"'
depends_on:
- master
- volume
- filer
environment:
- VIRTUAL_HOST=ingress
- VIRTUAL_PORT=8333
registry:
image: registry:2
environment:
REGISTRY_HTTP_ADDR: "0.0.0.0:5001" # seaweedfs s3
REGISTRY_LOG_LEVEL: "debug"
REGISTRY_STORAGE: "s3"
REGISTRY_STORAGE_S3_REGION: "us-east-1"
REGISTRY_STORAGE_S3_REGIONENDPOINT: "http://ingress"
REGISTRY_STORAGE_S3_BUCKET: "registry"
REGISTRY_STORAGE_S3_ACCESSKEY: "some_access_key1"
REGISTRY_STORAGE_S3_SECRETKEY: "some_secret_key1"
REGISTRY_STORAGE_S3_V4AUTH: "true"
REGISTRY_STORAGE_S3_SECURE: "false"
REGISTRY_STORAGE_S3_SKIPVERIFY: "true"
REGISTRY_STORAGE_S3_ROOTDIRECTORY: "/"
REGISTRY_STORAGE_DELETE_ENABLED: "true"
REGISTRY_STORAGE_REDIRECT_DISABLE: "true"
REGISTRY_VALIDATION_DISABLED: "true"
ports:
- 5001:5001
depends_on:
- s3
- ingress
+46
View File
@@ -0,0 +1,46 @@
version: '2'
services:
master:
image: chrislusf/seaweedfs:local
ports:
- 9333:9333
- 19333:19333
command: "master -ip=master"
volume:
image: chrislusf/seaweedfs:local
ports:
- 7455:8080
- 9325:9325
command: 'volume -mserver="master:9333" -port=8080 -metricsPort=9325 -preStopSeconds=1 -publicUrl=localhost:7455'
depends_on:
- master
filer:
image: chrislusf/seaweedfs:local
ports:
- 8888:8888
- 18888:18888
- 9326:9326
command: 'filer -master="master:9333" -metricsPort=9326'
tty: true
stdin_open: true
depends_on:
- master
- volume
mount_1:
image: chrislusf/seaweedfs:local
privileged: true
entrypoint: '/bin/sh -c "mkdir -p t1 && mkdir -p cache/t1 && weed -v=4 mount -filer=filer:8888 -cacheDir=./cache/t1 -dir=./t1 -filer.path=/c1" -volumeServerAccess=filerProxy'
depends_on:
- master
- volume
- filer
mount_2:
image: chrislusf/seaweedfs:local
privileged: true
entrypoint: '/bin/sh -c "mkdir -p t2 && mkdir -p cache/t2 && weed -v=4 mount -filer=filer:8888 -cacheDir=./cache/t2 -dir=./t2 -filer.path=/c1" -volumeServerAcess=publicUrl'
depends_on:
- master
- volume
- filer
- mount_1
+91
View File
@@ -0,0 +1,91 @@
version: '2'
services:
master:
image: chrislusf/seaweedfs:local
ports:
- 9333:9333
- 19333:19333
command: "master -ip=master -volumeSizeLimitMB=1024"
volume:
image: chrislusf/seaweedfs:local
ports:
- 8080:8080
- 18080:18080
command: "volume -mserver=master:9333 -port=8080 -ip=volume -max=0 -preStopSeconds=1"
depends_on:
- master
filer:
image: chrislusf/seaweedfs:local
ports:
- 8888:8888
- 18888:18888
command: 'filer -master="master:9333"'
depends_on:
- master
- volume
s3:
image: chrislusf/seaweedfs:local
ports:
- 8333:8333
command: '-v 9 s3 -filer="filer:8888"'
depends_on:
- master
- volume
- filer
minio:
image: minio/minio
ports:
- 9000:9000
command: 'minio server /data'
environment:
MINIO_ACCESS_KEY: "some_access_key1"
MINIO_SECRET_KEY: "some_secret_key1"
depends_on:
- master
registry1:
image: registry:2
environment:
REGISTRY_HTTP_ADDR: "0.0.0.0:5001" # seaweedfs s3
REGISTRY_LOG_LEVEL: "debug"
REGISTRY_STORAGE: "s3"
REGISTRY_STORAGE_S3_REGION: "us-east-1"
REGISTRY_STORAGE_S3_REGIONENDPOINT: "http://s3:8333"
REGISTRY_STORAGE_S3_BUCKET: "registry"
REGISTRY_STORAGE_S3_ACCESSKEY: "some_access_key1"
REGISTRY_STORAGE_S3_SECRETKEY: "some_secret_key1"
REGISTRY_STORAGE_S3_V4AUTH: "true"
REGISTRY_STORAGE_S3_SECURE: "false"
REGISTRY_STORAGE_S3_SKIPVERIFY: "true"
REGISTRY_STORAGE_S3_ROOTDIRECTORY: "/"
REGISTRY_STORAGE_DELETE_ENABLED: "true"
REGISTRY_STORAGE_REDIRECT_DISABLE: "true"
REGISTRY_VALIDATION_DISABLED: "true"
ports:
- 5001:5001
depends_on:
- s3
- minio
registry2:
image: registry:2
environment:
REGISTRY_HTTP_ADDR: "0.0.0.0:5002" # minio
REGISTRY_LOG_LEVEL: "debug"
REGISTRY_STORAGE: "s3"
REGISTRY_STORAGE_S3_REGION: "us-east-1"
REGISTRY_STORAGE_S3_REGIONENDPOINT: "http://minio:9000"
REGISTRY_STORAGE_S3_BUCKET: "registry"
REGISTRY_STORAGE_S3_ACCESSKEY: "some_access_key1"
REGISTRY_STORAGE_S3_SECRETKEY: "some_secret_key1"
REGISTRY_STORAGE_S3_V4AUTH: "true"
REGISTRY_STORAGE_S3_SECURE: "false"
REGISTRY_STORAGE_S3_SKIPVERIFY: "true"
REGISTRY_STORAGE_S3_ROOTDIRECTORY: "/"
REGISTRY_STORAGE_DELETE_ENABLED: "true"
REGISTRY_STORAGE_REDIRECT_DISABLE: "true"
REGISTRY_VALIDATION_DISABLED: "true"
ports:
- 5002:5002
depends_on:
- s3
- minio
@@ -0,0 +1,61 @@
version: '2'
services:
master:
image: chrislusf/seaweedfs:local
ports:
- 9333:9333
- 19333:19333
command: "master -ip=master"
volume:
image: chrislusf/seaweedfs:local
ports:
- 8080:8080
- 18080:18080
command: "volume -mserver=master:9333 -port=8080 -ip=volume -preStopSeconds=1"
depends_on:
- master
filer:
image: chrislusf/seaweedfs:local
ports:
- 8888:8888
- 18888:18888
command: '-v=9 filer -master="master:9333"'
restart: on-failure
volumes:
- ./notification.toml:/etc/seaweedfs/notification.toml
depends_on:
- master
- volume
- rabbitmq
- replicate
environment:
RABBIT_SERVER_URL: "amqp://guest:guest@rabbitmq:5672/"
replicate:
image: chrislusf/seaweedfs:local
command: '-v=9 filer.replicate'
restart: on-failure
volumes:
- ./notification.toml:/etc/seaweedfs/notification.toml
- ./replication.toml:/etc/seaweedfs/replication.toml
depends_on:
- rabbitmq
environment:
RABBIT_SERVER_URL: "amqp://guest:guest@rabbitmq:5672/"
s3:
image: chrislusf/seaweedfs:local
ports:
- 8333:8333
command: 's3 -filer="filer:8888"'
depends_on:
- master
- volume
- filer
rabbitmq:
image: rabbitmq:3.8.10-management-alpine
ports:
- 5672:5672
- 15671:15671
- 15672:15672
environment:
RABBITMQ_SERVER_ADDITIONAL_ERL_ARGS: "-rabbit log_levels [{connection,error},{queue,debug}]"
+84
View File
@@ -0,0 +1,84 @@
# 2021-01-30 16:25:30
version: '3.8'
services:
etcd:
image: gasparekatapy/etcd
networks:
- net
deploy:
mode: replicated
replicas: 3
master:
image: chrislusf/seaweedfs:local
environment:
WEED_MASTER_FILER_DEFAULT: "filer:8888"
WEED_MASTER_SEQUENCER_TYPE: "raft"
ports:
- "9333:9333"
- "19333:19333"
networks:
- net
command:
- 'master'
- '-resumeState=true'
- '-ip=master'
- '-port=9333'
deploy:
mode: replicated
replicas: 1
filer:
image: chrislusf/seaweedfs:local
environment:
WEED_LEVELDB2_ENABLED: "false"
WEED_ETCD_ENABLED: "true"
WEED_ETCD_SERVERS: "etcd:2379"
ports:
- target: 8888
published: 8888
protocol: tcp
mode: host
- target: 18888
published: 18888
protocol: tcp
mode: host
networks:
- net
command:
- 'filer'
- '-ip=filer'
- '-port=8888'
- '-port.readonly=28888'
- '-master=master:9333'
- '-disableDirListing=true'
deploy:
mode: replicated
replicas: 1
volume:
image: chrislusf/seaweedfs:local
ports:
- target: 8080
published: 8080
protocol: tcp
mode: host
- target: 18080
published: 18080
protocol: tcp
mode: host
networks:
- net
command:
- 'volume'
- '-mserver=master:9333'
- '-port=8080'
deploy:
mode: global
###########################################################################
networks:
net:
+30
View File
@@ -0,0 +1,30 @@
# HTTP 1.1 support
proxy_http_version 1.1;
#proxy_buffering off;
proxy_set_header Host $http_host;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $proxy_connection;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $proxy_x_forwarded_proto;
proxy_set_header X-Forwarded-Ssl $proxy_x_forwarded_ssl;
proxy_set_header X-Forwarded-Port $proxy_x_forwarded_port;
# Mitigate httpoxy attack (see README for details)
proxy_set_header Proxy "";
# aws default max_concurrent_requests 10
# aws default multipart_threshold 8MB
proxy_buffering on; # GET buffering or “X-Accel-Buffering” enables or disables buffering of a response;
proxy_buffers 64 1m; # buffers used for reading a response from the proxied server, for a single connection
proxy_buffer_size 8k; # maximum size of the data that nginx can receive from the server at a time is set
proxy_busy_buffers_size 2m;
proxy_request_buffering on; # PUT buffering
client_body_buffer_size 64m; # buffer size for reading client request body
client_max_body_size 64m;
proxy_next_upstream error timeout non_idempotent http_500; # PUT request should be passed to the next server:
proxy_connect_timeout 200ms;
proxy_read_timeout 3s; #timeout is set only between two successive read operations
proxy_send_timeout 3s; #timeout is set only between two successive write operations
+17
View File
@@ -0,0 +1,17 @@
[notification.log]
# this is only for debugging perpose and does not work with "weed filer.replicate"
enabled = false
[notification.gocdk_pub_sub]
# The Go Cloud Development Kit (https://gocloud.dev).
# PubSub API (https://godoc.org/gocloud.dev/pubsub).
# Supports AWS SNS/SQS, Azure Service Bus, Google PubSub, NATS and RabbitMQ.
enabled = true
# This URL will Dial the RabbitMQ server at the URL in the environment
# variable RABBIT_SERVER_URL and open the exchange "myexchange".
# The exchange must have already been created by some other means, like
# the RabbitMQ management plugin. Сreate myexchange of type fanout and myqueue then
# create binding myexchange => myqueue
topic_url = "rabbit://swexchange"
sub_url = "rabbit://swqueue"
+13
View File
@@ -0,0 +1,13 @@
global:
scrape_interval: 30s
scrape_timeout: 10s
scrape_configs:
- job_name: services
metrics_path: /metrics
static_configs:
- targets:
- 'prometheus:9090'
- 'volume:9325'
- 'filer:9326'
- 's3:9327'
+11
View File
@@ -0,0 +1,11 @@
[source.filer]
enabled = true
grpcAddress = "filer:18888"
# all files under this directory tree are replicated.
# this is not a directory on your hard drive, but on your filer.
# i.e., all files with this "prefix" are sent to notification message queue.
directory = "/buckets"
[sink.local_incremental]
enabled = true
directory = "/data"
+24 -3
View File
@@ -12,7 +12,8 @@ services:
ports:
- 8080:8080
- 18080:18080
command: 'volume -mserver="master:9333" -port=8080'
- 9325:9325
command: 'volume -mserver="master:9333" -port=8080 -metricsPort=9325'
depends_on:
- master
filer:
@@ -20,7 +21,8 @@ services:
ports:
- 8888:8888
- 18888:18888
command: 'filer -master="master:9333"'
- 9326:9326
command: 'filer -master="master:9333" -metricsPort=9326'
tty: true
stdin_open: true
depends_on:
@@ -40,8 +42,27 @@ services:
image: chrislusf/seaweedfs # use a remote image
ports:
- 8333:8333
command: 's3 -filer="filer:8888"'
- 9327:9327
command: 's3 -filer="filer:8888" -metricsPort=9327'
depends_on:
- master
- volume
- filer
webdav:
image: chrislusf/seaweedfs # use a remote image
ports:
- 7333:7333
command: 'webdav -filer="filer:8888"'
depends_on:
- master
- volume
- filer
prometheus:
image: prom/prometheus:v2.21.0
ports:
- 9000:9090
volumes:
- ./prometheus:/etc/prometheus
command: --web.enable-lifecycle --config.file=/etc/prometheus/prometheus.yml
depends_on:
- s3
+9
View File
@@ -33,3 +33,12 @@ services:
- master
- volume
- filer
webdav:
image: chrislusf/seaweedfs:dev # use a remote dev image
ports:
- 7333:7333
command: 'webdav -filer="filer:8888"'
depends_on:
- master
- volume
- filer
+12
View File
@@ -0,0 +1,12 @@
CREATE DATABASE IF NOT EXISTS seaweedfs;
CREATE USER IF NOT EXISTS 'seaweedfs'@'%' IDENTIFIED BY 'secret';
GRANT ALL PRIVILEGES ON seaweedfs_fast.* TO 'seaweedfs'@'%';
FLUSH PRIVILEGES;
USE seaweedfs;
CREATE TABLE IF NOT EXISTS filemeta (
dirhash BIGINT COMMENT 'first 64 bits of MD5 hash value of directory field',
name VARCHAR(1000) COMMENT 'directory or file name',
directory TEXT COMMENT 'full path to parent directory',
meta LONGBLOB,
PRIMARY KEY (dirhash, name)
) DEFAULT CHARSET=utf8;
+29 -24
View File
@@ -3,15 +3,18 @@ module github.com/chrislusf/seaweedfs
go 1.12
require (
cloud.google.com/go v0.44.3
cloud.google.com/go v0.58.0
cloud.google.com/go/pubsub v1.3.1
cloud.google.com/go/storage v1.9.0
github.com/Azure/azure-amqp-common-go/v2 v2.1.0 // indirect
github.com/Azure/azure-pipeline-go v0.2.2 // indirect
github.com/Azure/azure-storage-blob-go v0.8.0
github.com/Azure/azure-storage-blob-go v0.9.0
github.com/OneOfOne/xxhash v1.2.2
github.com/Shopify/sarama v1.23.1
github.com/aws/aws-sdk-go v1.33.5
github.com/aws/aws-sdk-go v1.34.30
github.com/buraksezer/consistent v0.0.0-20191006190839-693edf70fd72
github.com/cespare/xxhash v1.1.0
github.com/chrislusf/raft v1.0.2-0.20201002174524-b13c3bfdb011
github.com/chrislusf/raft v1.0.4
github.com/coreos/go-semver v0.3.0 // indirect
github.com/dgrijalva/jwt-go v3.2.0+incompatible
github.com/disintegration/imaging v1.6.2
@@ -22,12 +25,14 @@ require (
github.com/facebookgo/stack v0.0.0-20160209184415-751773369052 // indirect
github.com/facebookgo/stats v0.0.0-20151006221625-1b76add642e4
github.com/facebookgo/subset v0.0.0-20200203212716-c811ad88dec4 // indirect
github.com/fclairamb/ftpserverlib v0.8.0
github.com/frankban/quicktest v1.7.2 // indirect
github.com/go-redis/redis v6.15.7+incompatible
github.com/go-errors/errors v1.1.1 // indirect
github.com/go-redis/redis/v8 v8.4.4
github.com/go-sql-driver/mysql v1.5.0
github.com/gocql/gocql v0.0.0-20190829130954-e163eff7a8c6
github.com/gogo/protobuf v1.2.2-0.20190730201129-28a6bbf47e48 // indirect
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e
github.com/golang/protobuf v1.4.2
github.com/google/btree v1.0.0
github.com/google/uuid v1.1.1
@@ -37,54 +42,54 @@ require (
github.com/jcmturner/gofork v1.0.0 // indirect
github.com/json-iterator/go v1.1.10
github.com/karlseguin/ccache v2.0.3+incompatible
github.com/karlseguin/expect v1.0.1 // indirect
github.com/klauspost/compress v1.10.9
github.com/karlseguin/ccache/v2 v2.0.7
github.com/klauspost/compress v1.10.9 // indirect
github.com/klauspost/cpuid v1.2.1 // indirect
github.com/klauspost/crc32 v1.2.0
github.com/klauspost/reedsolomon v1.9.2
github.com/kurin/blazer v0.5.3
github.com/lib/pq v1.2.0
github.com/lunixbochs/vtclean v1.0.0 // indirect
github.com/magiconair/properties v1.8.1 // indirect
github.com/mattn/go-ieproxy v0.0.0-20190805055040-f9202b1cfdeb // indirect
github.com/mattn/go-colorable v0.1.2 // indirect
github.com/mattn/go-runewidth v0.0.4 // indirect
github.com/nats-io/nats-server/v2 v2.0.4 // indirect
github.com/olivere/elastic/v7 v7.0.19
github.com/onsi/ginkgo v1.10.1 // indirect
github.com/onsi/gomega v1.7.0 // indirect
github.com/peterh/liner v1.1.0
github.com/pierrec/lz4 v2.2.7+incompatible // indirect
github.com/prometheus/client_golang v1.1.0
github.com/prometheus/procfs v0.0.4 // indirect
github.com/prometheus/client_golang v1.3.0
github.com/rakyll/statik v0.1.7
github.com/rcrowley/go-metrics v0.0.0-20190826022208-cac0b30c2563 // indirect
github.com/seaweedfs/fuse v1.0.7
github.com/seaweedfs/fuse v1.1.1
github.com/seaweedfs/goexif v1.0.2
github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e
github.com/spaolacci/murmur3 v1.1.0 // indirect
github.com/spf13/afero v1.2.2 // indirect
github.com/spf13/jwalterweatherman v1.1.0 // indirect
github.com/spf13/viper v1.4.0
github.com/streadway/amqp v0.0.0-20190827072141-edfb9018d271 // indirect
github.com/streadway/amqp v0.0.0-20200108173154-1c71cc93ed71
github.com/stretchr/testify v1.6.1
github.com/syndtr/goleveldb v1.0.0
github.com/tecbot/gorocksdb v0.0.0-20191217155057-f0fad39f321c
github.com/tidwall/gjson v1.3.2
github.com/tidwall/match v1.0.1
github.com/tsuna/gohbase v0.0.0-20201125011725-348991136365
github.com/valyala/bytebufferpool v1.0.0
github.com/viant/assertly v0.5.4 // indirect
github.com/viant/ptrie v0.3.0
github.com/viant/toolbox v0.33.2 // indirect
github.com/willf/bitset v1.1.10 // indirect
github.com/willf/bloom v2.0.3+incompatible
github.com/wsxiaoys/terminal v0.0.0-20160513160801-0940f3fc43a0 // indirect
go.etcd.io/etcd v3.3.15+incompatible
go.mongodb.org/mongo-driver v1.3.2
gocloud.dev v0.16.0
gocloud.dev/pubsub/natspubsub v0.16.0
gocloud.dev/pubsub/rabbitpubsub v0.16.0
gocloud.dev v0.20.0
gocloud.dev/pubsub/natspubsub v0.20.0
gocloud.dev/pubsub/rabbitpubsub v0.20.0
golang.org/x/image v0.0.0-20200119044424-58c23975cae1 // indirect
golang.org/x/net v0.0.0-20200202094626-16171245cfb2
golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb
golang.org/x/sync v0.0.0-20200930132711-30421366ff76 // indirect
golang.org/x/sys v0.0.0-20201022201747-fb209a7c41cd
golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5
google.golang.org/api v0.9.0
google.golang.org/appengine v1.6.2 // indirect
golang.org/x/tools v0.0.0-20200608174601-1b747fd94509
google.golang.org/api v0.26.0
google.golang.org/grpc v1.29.1
google.golang.org/protobuf v1.24.0
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 // indirect
+476 -28
View File
File diff suppressed because it is too large Load Diff
+2 -1
View File
@@ -1,4 +1,5 @@
apiVersion: v1
description: SeaweedFS
name: seaweedfs
version: 2.06
appVersion: "2.24"
version: 2.24
File diff suppressed because it is too large Load Diff
+7 -7
View File
@@ -52,12 +52,12 @@ Inject extra environment vars in the format key:value, if populated
{{- $registryName := default .Values.image.registry .Values.global.localRegistry | toString -}}
{{- $repositoryName := .Values.image.repository | toString -}}
{{- $name := .Values.global.imageName | toString -}}
{{- $tag := .Values.global.imageTag | toString -}}
{{- $tag := .Chart.AppVersion | toString -}}
{{- printf "%s%s%s:%s" $registryName $repositoryName $name $tag -}}
{{- end -}}
{{- end -}}
{{/* Return the proper postgresqlSchema image */}}
{{/* Return the proper dbSchema image */}}
{{- define "filer.dbSchema.image" -}}
{{- if .Values.filer.dbSchema.imageOverride -}}
{{- $imageOverride := .Values.filer.dbSchema.imageOverride -}}
@@ -80,7 +80,7 @@ Inject extra environment vars in the format key:value, if populated
{{- $registryName := default .Values.image.registry .Values.global.localRegistry | toString -}}
{{- $repositoryName := .Values.image.repository | toString -}}
{{- $name := .Values.global.imageName | toString -}}
{{- $tag := .Values.global.imageTag | toString -}}
{{- $tag := .Chart.AppVersion | toString -}}
{{- printf "%s%s%s:%s" $registryName $repositoryName $name $tag -}}
{{- end -}}
{{- end -}}
@@ -94,7 +94,7 @@ Inject extra environment vars in the format key:value, if populated
{{- $registryName := default .Values.image.registry .Values.global.localRegistry | toString -}}
{{- $repositoryName := .Values.image.repository | toString -}}
{{- $name := .Values.global.imageName | toString -}}
{{- $tag := .Values.global.imageTag | toString -}}
{{- $tag := .Chart.AppVersion | toString -}}
{{- printf "%s%s%s:%s" $registryName $repositoryName $name $tag -}}
{{- end -}}
{{- end -}}
@@ -108,7 +108,7 @@ Inject extra environment vars in the format key:value, if populated
{{- $registryName := default .Values.image.registry .Values.global.localRegistry | toString -}}
{{- $repositoryName := .Values.image.repository | toString -}}
{{- $name := .Values.global.imageName | toString -}}
{{- $tag := .Values.global.imageTag | toString -}}
{{- $tag := .Chart.AppVersion | toString -}}
{{- printf "%s%s%s:%s" $registryName $repositoryName $name $tag -}}
{{- end -}}
{{- end -}}
@@ -122,7 +122,7 @@ Inject extra environment vars in the format key:value, if populated
{{- $registryName := default .Values.image.registry .Values.global.localRegistry | toString -}}
{{- $repositoryName := .Values.image.repository | toString -}}
{{- $name := .Values.global.imageName | toString -}}
{{- $tag := .Values.global.imageTag | toString -}}
{{- $tag := .Chart.AppVersion | toString -}}
{{- printf "%s%s%s:%s" $registryName $repositoryName $name $tag -}}
{{- end -}}
{{- end -}}
{{- end -}}
+2 -1
View File
@@ -6,6 +6,7 @@ metadata:
name: {{ include "seaweedfs.fullname" . }}-cronjob
spec:
schedule: "{{ .Values.cronjob.schedule }}"
startingDeadlineSeconds: 200
concurrencyPolicy: Forbid
failedJobsHistoryLimit: 2
successfulJobsHistoryLimit: 2
@@ -51,4 +52,4 @@ spec:
-filer {{ template "seaweedfs.name" . }}-filer.{{ .Release.Namespace }}.svc:{{ .Values.filer.port }}
{{- end }}
{{- end }}
{{- end }}
{{- end }}
@@ -0,0 +1,31 @@
apiVersion: v1
kind: Service
metadata:
name: {{ template "seaweedfs.name" . }}-filer-client
namespace: {{ .Release.Namespace }}
labels:
app: {{ template "seaweedfs.name" . }}
component: filer
{{- if .Values.filer.metricsPort }}
monitoring: "true"
{{- end }}
spec:
clusterIP: None
ports:
- name: "swfs-filer"
port: {{ .Values.filer.port }}
targetPort: {{ .Values.filer.port }}
protocol: TCP
- name: "swfs-filer-grpc"
port: {{ .Values.filer.grpcPort }}
targetPort: {{ .Values.filer.grpcPort }}
protocol: TCP
{{- if .Values.filer.metricsPort }}
- name: "metrics"
port: {{ .Values.filer.metricsPort }}
targetPort: {{ .Values.filer.metricsPort }}
protocol: TCP
{{- end }}
selector:
app: {{ template "seaweedfs.name" . }}
component: filer
+4 -7
View File
@@ -1,6 +1,8 @@
apiVersion: v1
kind: Service
metadata:
annotations:
service.alpha.kubernetes.io/tolerate-unready-endpoints: "true"
name: {{ template "seaweedfs.name" . }}-filer
namespace: {{ .Release.Namespace }}
labels:
@@ -8,6 +10,7 @@ metadata:
component: filer
spec:
clusterIP: None
publishNotReadyAddresses: true
ports:
- name: "swfs-filer"
port: {{ .Values.filer.port }}
@@ -17,12 +20,6 @@ spec:
port: {{ .Values.filer.grpcPort }}
targetPort: {{ .Values.filer.grpcPort }}
protocol: TCP
{{- if .Values.filer.metricsPort }}
- name: "swfs-filer-metrics"
port: {{ .Values.filer.metricsPort }}
targetPort: {{ .Values.filer.metricsPort }}
protocol: TCP
{{- end }}
selector:
app: {{ template "seaweedfs.name" . }}
component: filer
component: filer
+10 -4
View File
@@ -87,6 +87,12 @@ spec:
value: {{ $value | quote }}
{{- end }}
{{- end }}
{{- if .Values.global.extraEnvironmentVars }}
{{- range $key, $value := .Values.global.extraEnvironmentVars }}
- name: {{ $key }}
value: {{ $value | quote }}
{{- end }}
{{- end }}
command:
- "/bin/sh"
- "-ec"
@@ -101,7 +107,7 @@ spec:
-port={{ .Values.filer.port }} \
{{- if .Values.filer.metricsPort }}
-metricsPort {{ .Values.filer.metricsPort }} \
{{- end }}}
{{- end }}
{{- if .Values.filer.redirectOnRead }}
-redirectOnRead \
{{- end }}
@@ -128,7 +134,7 @@ spec:
{{- end }}
-ip=${POD_IP} \
{{- if gt (.Values.filer.replicas | int) 1 }}
-peers={{ range $index := until (.Values.filer.replicas | int) }}${SEAWEEDFS_FULLNAME}-filer-{{ $index }}.${SEAWEEDFS_FULLNAME}-filer:{{ $.Values.filer.port }}{{ if lt $index (sub ($.Values.filer.replicas | int) 1) }},{{ end }}{{ end }}
-peers=$(echo -n "{{ range $index := until (.Values.filer.replicas | int) }}${SEAWEEDFS_FULLNAME}-filer-{{ $index }}.${SEAWEEDFS_FULLNAME}-filer:{{ $.Values.filer.port }}{{ if lt $index (sub ($.Values.filer.replicas | int) 1) }},{{ end }}{{ end }}" | sed "s/$HOSTNAME.${SEAWEEDFS_FULLNAME}-filer:{{ $.Values.filer.port }}//" | sed 's/,$//; 's/^,//'; s/,,/,/;' ) \
{{- end }}
-master={{ range $index := until (.Values.master.replicas | int) }}${SEAWEEDFS_FULLNAME}-master-{{ $index }}.${SEAWEEDFS_FULLNAME}-master:{{ $.Values.master.port }}{{ if lt $index (sub ($.Values.master.replicas | int) 1) }},{{ end }}{{ end }}
{{- if or (.Values.global.enableSecurity) (.Values.filer.extraVolumeMounts) }}
@@ -172,7 +178,7 @@ spec:
periodSeconds: 15
successThreshold: 1
failureThreshold: 100
timeoutSeconds: 3
timeoutSeconds: 10
livenessProbe:
httpGet:
path: /
@@ -182,7 +188,7 @@ spec:
periodSeconds: 30
successThreshold: 1
failureThreshold: 5
timeoutSeconds: 3
timeoutSeconds: 10
{{- if .Values.filer.resources }}
resources:
{{ tpl .Values.filer.resources . | nindent 12 | trim }}
+2 -1
View File
@@ -10,6 +10,7 @@ metadata:
service.alpha.kubernetes.io/tolerate-unready-endpoints: "true"
spec:
clusterIP: None
publishNotReadyAddresses: true
ports:
- name: "swfs-master"
port: {{ .Values.master.port }}
@@ -21,4 +22,4 @@ spec:
protocol: TCP
selector:
app: {{ template "seaweedfs.name" . }}
component: master
component: master
@@ -76,6 +76,12 @@ spec:
value: {{ $value | quote }}
{{- end }}
{{- end }}
{{- if .Values.global.extraEnvironmentVars }}
{{- range $key, $value := .Values.global.extraEnvironmentVars }}
- name: {{ $key }}
value: {{ $value | quote }}
{{- end }}
{{- end }}
command:
- "/bin/sh"
- "-ec"
@@ -157,7 +163,7 @@ spec:
periodSeconds: 45
successThreshold: 2
failureThreshold: 100
timeoutSeconds: 5
timeoutSeconds: 10
livenessProbe:
httpGet:
path: /cluster/status
@@ -167,7 +173,7 @@ spec:
periodSeconds: 30
successThreshold: 1
failureThreshold: 4
timeoutSeconds: 5
timeoutSeconds: 10
{{- if .Values.master.resources }}
resources:
{{ tpl .Values.master.resources . | nindent 12 | trim }}
+22 -7
View File
@@ -59,11 +59,17 @@ spec:
fieldPath: metadata.namespace
- name: SEAWEEDFS_FULLNAME
value: "{{ template "seaweedfs.name" . }}"
{{- if .Values.global.extraEnvironmentVars }}
{{- range $key, $value := .Values.global.extraEnvironmentVars }}
- name: {{ $key }}
value: {{ $value | quote }}
{{- end }}
{{- end }}
command:
- "/bin/sh"
- "-ec"
- |
exec /usr/bin/weed \
exec /usr/bin/weed -logdir=/logs \
{{- if .Values.s3.loggingOverrideLevel }}
-v={{ .Values.s3.loggingOverrideLevel }} \
{{- else }}
@@ -73,7 +79,7 @@ spec:
-port={{ .Values.s3.port }} \
{{- if .Values.s3.metricsPort }}
-metricsPort {{ .Values.s3.metricsPort }} \
{{- end }}}
{{- end }}
{{- if .Values.global.enableSecurity }}
-cert.file=/usr/local/share/ca-certificates/client/tls.crt \
-key.file=/usr/local/share/ca-certificates/client/tls.key \
@@ -81,9 +87,13 @@ spec:
{{- if .Values.s3.domainName }}
-domainName={{ .Values.s3.domainName }} \
{{- end }}
-filer={{ template "seaweedfs.name" . }}-filer:{{ .Values.filer.port }}
{{- if or (.Values.global.enableSecurity) (.Values.s3.extraVolumeMounts) }}
{{- if .Values.s3.allowEmptyFolder }}
-allowEmptyFolder={{ .Values.s3.allowEmptyFolder }} \
{{- end }}
-filer={{ template "seaweedfs.name" . }}-filer-client:{{ .Values.filer.port }}
volumeMounts:
- name: logs
mountPath: "/logs/"
{{- if .Values.global.enableSecurity }}
- name: security-config
readOnly: true
@@ -106,7 +116,6 @@ spec:
mountPath: /usr/local/share/ca-certificates/client/
{{- end }}
{{ tpl .Values.s3.extraVolumeMounts . | nindent 12 | trim }}
{{- end }}
ports:
- containerPort: {{ .Values.s3.port }}
name: swfs-s3
@@ -119,7 +128,7 @@ spec:
periodSeconds: 15
successThreshold: 1
failureThreshold: 100
timeoutSeconds: 3
timeoutSeconds: 10
livenessProbe:
httpGet:
path: /
@@ -129,12 +138,18 @@ spec:
periodSeconds: 60
successThreshold: 1
failureThreshold: 20
timeoutSeconds: 3
timeoutSeconds: 10
{{- if .Values.s3.resources }}
resources:
{{ tpl .Values.s3.resources . | nindent 12 | trim }}
{{- end }}
volumes:
{{- if eq .Values.s3.logs.type "hostPath" }}
- name: logs
hostPath:
path: /storage/logs/seaweedfs/s3
type: DirectoryOrCreate
{{- end }}
{{- if .Values.global.enableSecurity }}
- name: security-config
configMap:
+2 -2
View File
@@ -14,10 +14,10 @@ spec:
protocol: TCP
{{- if .Values.s3.metricsPort }}
- name: "swfs-s3-metrics"
port: {{ .Values.filer.s3 }}
port: {{ .Values.s3.metricsPort }}
targetPort: {{ .Values.s3.metricsPort }}
protocol: TCP
{{- end }}}
{{- end }}
selector:
app: {{ template "seaweedfs.name" . }}
component: s3
@@ -15,4 +15,4 @@ spec:
selector:
app: {{ template "seaweedfs.name" . }}
component: s3
{{- end }}}
{{- end }}
@@ -0,0 +1,20 @@
{{- if .Values.global.monitoring.enabled }}
{{- $files := .Files.Glob "dashboards/*.json" }}
{{- if $files }}
apiVersion: v1
kind: ConfigMapList
items:
{{- range $path, $fileContents := $files }}
{{- $dashboardName := regexReplaceAll "(^.*/)(.*)\\.json$" $path "${2}" }}
- apiVersion: v1
kind: ConfigMap
metadata:
name: {{ printf "%s" $dashboardName | lower | replace "_" "-" }}
namespace: {{ $.Release.Namespace }}
labels:
grafana_dashboard: "1"
data:
{{ $dashboardName }}.json: {{ $.Files.Get $path | toJson }}
{{- end }}
{{- end }}
{{- end }}
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -22,7 +22,7 @@ spec:
port: {{ .Values.volume.metricsPort }}
targetPort: {{ .Values.volume.metricsPort }}
protocol: TCP
{{- end }}}
{{- end }}
selector:
app: {{ template "seaweedfs.name" . }}
component: volume
@@ -15,4 +15,4 @@ spec:
selector:
app: {{ template "seaweedfs.name" . }}
component: volume
{{- end }}}
{{- end }}
@@ -64,6 +64,12 @@ spec:
fieldPath: status.hostIP
- name: SEAWEEDFS_FULLNAME
value: "{{ template "seaweedfs.name" . }}"
{{- if .Values.global.extraEnvironmentVars }}
{{- range $key, $value := .Values.global.extraEnvironmentVars }}
- name: {{ $key }}
value: {{ $value | quote }}
{{- end }}
{{- end }}
command:
- "/bin/sh"
- "-ec"
@@ -78,8 +84,11 @@ spec:
-port={{ .Values.volume.port }} \
{{- if .Values.volume.metricsPort }}
-metricsPort {{ .Values.volume.metricsPort }} \
{{- end }}}
{{- end }}
-dir={{ .Values.volume.dir }} \
{{- if .Values.volume.dir_idx }}
-dir.idx={{ .Values.volume.dir_idx }} \
{{- end }}
-max={{ .Values.volume.maxVolumes }} \
{{- if .Values.volume.rack }}
-rack={{ .Values.volume.rack }} \
@@ -149,7 +158,7 @@ spec:
periodSeconds: 90
successThreshold: 1
failureThreshold: 100
timeoutSeconds: 5
timeoutSeconds: 30
livenessProbe:
httpGet:
path: /status
@@ -159,7 +168,7 @@ spec:
periodSeconds: 90
successThreshold: 1
failureThreshold: 4
timeoutSeconds: 5
timeoutSeconds: 30
{{- if .Values.volume.resources }}
resources:
{{ tpl .Values.volume.resources . | nindent 12 | trim }}
+18 -7
View File
@@ -4,7 +4,7 @@ global:
registry: ""
repository: ""
imageName: chrislusf/seaweedfs
imageTag: "2.06"
# imageTag: "2.24" - started using {.Chart.appVersion}
imagePullPolicy: IfNotPresent
imagePullSecrets: imagepullsecret
restartPolicy: Always
@@ -21,6 +21,10 @@ global:
# Y number of replica in other racks in the same data center
# Z number of replica in other servers in the same rack
replicationPlacment: "001"
extraEnvironmentVars:
WEED_CLUSTER_DEFAULT: "sw"
WEED_CLUSTER_SW_MASTER: "seaweedfs-master:9333"
WEED_CLUSTER_SW_FILER: "seaweedfs-filer-client:8888"
image:
registry: ""
@@ -140,6 +144,8 @@ volume:
# Directories to store data files. dir[,dir]... (default "/tmp")
dir: "/data"
# Directories to store index files. dir[,dir]... (default "/tmp")
dir_idx: null
# Maximum numbers of volumes, count[,count]...
# If set to zero on non-windows OS, the limit will be auto configured. (default "7")
@@ -292,8 +298,10 @@ filer:
WEED_MYSQL_HOSTNAME: "mysql-db-host"
WEED_MYSQL_PORT: "3306"
WEED_MYSQL_DATABASE: "sw_database"
WEED_MYSQL_CONNECTION_MAX_IDLE: "10"
WEED_MYSQL_CONNECTION_MAX_OPEN: "150"
WEED_MYSQL_CONNECTION_MAX_IDLE: "5"
WEED_MYSQL_CONNECTION_MAX_OPEN: "75"
# "refresh" connection every 10 minutes, eliminating mysql closing "old" connections
WEED_MYSQL_CONNECTION_MAX_LIFETIME_SECONDS: "600"
# enable usage of memsql as filer backend
WEED_MYSQL_INTERPOLATEPARAMS: "true"
WEED_LEVELDB2_ENABLED: "false"
@@ -302,10 +310,6 @@ filer:
WEED_FILER_OPTIONS_RECURSIVE_DELETE: "false"
# directories under this folder will be automatically creating a separate bucket
WEED_FILER_BUCKETS_FOLDER: "/buckets"
# directories under this folder will be store message queue data
WEED_FILER_QUEUES_FOLDER: "/queues"
# WEED_FILER_OPTIONS_BUCKETS_FSYNC a list of buckets names with all write requests fsync=true
WEED_FILER_OPTIONS_BUCKETS_FSYNC: []
s3:
enabled: true
@@ -317,6 +321,8 @@ s3:
port: 8333
metricsPort: 9327
loggingOverrideLevel: null
#allow empty folders
allowEmptyFolder: true
# Suffix of the host name, {bucket}.{domainName}
domainName: ""
@@ -347,6 +353,11 @@ s3:
# ref: https://kubernetes.io/docs/concepts/configuration/pod-priority-preemption/
priorityClassName: ""
logs:
type: "hostPath"
size: ""
storageClass: ""
cronjob:
enabled: false
schedule: "*/7 * * * *"
BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

+6 -1
View File
@@ -5,7 +5,7 @@
<groupId>com.github.chrislusf</groupId>
<artifactId>seaweedfs-client</artifactId>
<version>1.5.1</version>
<version>1.6.0</version>
<parent>
<groupId>org.sonatype.oss</groupId>
@@ -68,6 +68,11 @@
<version>4.13.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>javax.annotation</groupId>
<artifactId>javax.annotation-api</artifactId>
<version>1.3.2</version>
</dependency>
</dependencies>
<distributionManagement>
+1 -1
View File
@@ -5,7 +5,7 @@
<groupId>com.github.chrislusf</groupId>
<artifactId>seaweedfs-client</artifactId>
<version>1.5.1</version>
<version>1.6.0</version>
<parent>
<groupId>org.sonatype.oss</groupId>
+6 -1
View File
@@ -5,7 +5,7 @@
<groupId>com.github.chrislusf</groupId>
<artifactId>seaweedfs-client</artifactId>
<version>1.5.1</version>
<version>1.6.0</version>
<parent>
<groupId>org.sonatype.oss</groupId>
@@ -68,6 +68,11 @@
<version>4.13.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>javax.annotation</groupId>
<artifactId>javax.annotation-api</artifactId>
<version>1.3.2</version>
</dependency>
</dependencies>
<build>
@@ -15,7 +15,6 @@ public class ChunkCache {
}
this.cache = CacheBuilder.newBuilder()
.maximumSize(maxEntries)
.weakValues()
.expireAfterAccess(1, TimeUnit.HOURS)
.build();
}
@@ -74,7 +74,7 @@ public class FileChunkManifest {
byte[] chunkData = SeaweedRead.chunkCache.getChunk(chunkView.fileId);
if (chunkData == null) {
LOG.debug("doFetchFullChunkData:{}", chunkView);
chunkData = SeaweedRead.doFetchFullChunkData(chunkView, locations);
chunkData = SeaweedRead.doFetchFullChunkData(filerGrpcClient, chunkView, locations);
}
if (chunk.getIsChunkManifest()){
LOG.debug("chunk {} size {}", chunkView.fileId, chunkData.length);
@@ -86,7 +86,7 @@ public class FileChunkManifest {
}
public static List<FilerProto.FileChunk> maybeManifestize(
final FilerGrpcClient filerGrpcClient, List<FilerProto.FileChunk> inputChunks) throws IOException {
final FilerGrpcClient filerGrpcClient, List<FilerProto.FileChunk> inputChunks, String parentDirectory) throws IOException {
// the return variable
List<FilerProto.FileChunk> chunks = new ArrayList<>();
@@ -101,7 +101,7 @@ public class FileChunkManifest {
int remaining = dataChunks.size();
for (int i = 0; i + mergeFactor < dataChunks.size(); i += mergeFactor) {
FilerProto.FileChunk chunk = mergeIntoManifest(filerGrpcClient, dataChunks.subList(i, i + mergeFactor));
FilerProto.FileChunk chunk = mergeIntoManifest(filerGrpcClient, dataChunks.subList(i, i + mergeFactor), parentDirectory);
chunks.add(chunk);
remaining -= mergeFactor;
}
@@ -113,7 +113,7 @@ public class FileChunkManifest {
return chunks;
}
private static FilerProto.FileChunk mergeIntoManifest(final FilerGrpcClient filerGrpcClient, List<FilerProto.FileChunk> dataChunks) throws IOException {
private static FilerProto.FileChunk mergeIntoManifest(final FilerGrpcClient filerGrpcClient, List<FilerProto.FileChunk> dataChunks, String parentDirectory) throws IOException {
// create and serialize the manifest
dataChunks = FilerClient.beforeEntrySerialization(dataChunks);
FilerProto.FileChunkManifest.Builder m = FilerProto.FileChunkManifest.newBuilder().addAllChunks(dataChunks);
@@ -130,7 +130,7 @@ public class FileChunkManifest {
filerGrpcClient.getReplication(),
filerGrpcClient,
minOffset,
data, 0, data.length);
data, 0, data.length, parentDirectory);
manifestChunk.setIsChunkManifest(true);
manifestChunk.setSize(maxOffset - minOffset);
return manifestChunk.build();
@@ -275,9 +275,9 @@ public class FilerClient {
try {
FilerProto.CreateEntryResponse createEntryResponse =
filerGrpcClient.getBlockingStub().createEntry(FilerProto.CreateEntryRequest.newBuilder()
.setDirectory(parent)
.setEntry(entry)
.build());
.setDirectory(parent)
.setEntry(entry)
.build());
if (Strings.isNullOrEmpty(createEntryResponse.getError())) {
return true;
}
@@ -333,4 +333,13 @@ public class FilerClient {
return true;
}
public Iterator<FilerProto.SubscribeMetadataResponse> watch(String prefix, String clientName, long sinceNs) {
return filerGrpcClient.getBlockingStub().subscribeMetadata(FilerProto.SubscribeMetadataRequest.newBuilder()
.setPathPrefix(prefix)
.setClientName(clientName)
.setSinceNs(sinceNs)
.build()
);
}
}
@@ -9,8 +9,8 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.net.ssl.SSLException;
import java.util.Map;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;
public class FilerGrpcClient {
@@ -26,6 +26,9 @@ public class FilerGrpcClient {
}
}
public final int VOLUME_SERVER_ACCESS_DIRECT = 0;
public final int VOLUME_SERVER_ACCESS_PUBLIC_URL = 1;
public final int VOLUME_SERVER_ACCESS_FILER_PROXY = 2;
public final Map<String, FilerProto.Locations> vidLocations = new HashMap<>();
private final ManagedChannel channel;
private final SeaweedFilerGrpc.SeaweedFilerBlockingStub blockingStub;
@@ -34,6 +37,8 @@ public class FilerGrpcClient {
private boolean cipher = false;
private String collection = "";
private String replication = "";
private int volumeServerAccess = VOLUME_SERVER_ACCESS_DIRECT;
private String filerAddress;
public FilerGrpcClient(String host, int grpcPort) {
this(host, grpcPort, sslContext);
@@ -49,6 +54,8 @@ public class FilerGrpcClient {
.negotiationType(NegotiationType.TLS)
.sslContext(sslContext));
filerAddress = String.format("%s:%d", host, grpcPort - 10000);
FilerProto.GetFilerConfigurationResponse filerConfigurationResponse =
this.getBlockingStub().getFilerConfiguration(
FilerProto.GetFilerConfigurationRequest.newBuilder().build());
@@ -58,7 +65,7 @@ public class FilerGrpcClient {
}
public FilerGrpcClient(ManagedChannelBuilder<?> channelBuilder) {
private FilerGrpcClient(ManagedChannelBuilder<?> channelBuilder) {
channel = channelBuilder.build();
blockingStub = SeaweedFilerGrpc.newBlockingStub(channel);
asyncStub = SeaweedFilerGrpc.newStub(channel);
@@ -93,4 +100,39 @@ public class FilerGrpcClient {
return futureStub;
}
public void setAccessVolumeServerDirectly() {
this.volumeServerAccess = VOLUME_SERVER_ACCESS_DIRECT;
}
public boolean isAccessVolumeServerDirectly() {
return this.volumeServerAccess == VOLUME_SERVER_ACCESS_DIRECT;
}
public void setAccessVolumeServerByPublicUrl() {
this.volumeServerAccess = VOLUME_SERVER_ACCESS_PUBLIC_URL;
}
public boolean isAccessVolumeServerByPublicUrl() {
return this.volumeServerAccess == VOLUME_SERVER_ACCESS_PUBLIC_URL;
}
public void setAccessVolumeServerByFilerProxy() {
this.volumeServerAccess = VOLUME_SERVER_ACCESS_FILER_PROXY;
}
public boolean isAccessVolumeServerByFilerProxy() {
return this.volumeServerAccess == VOLUME_SERVER_ACCESS_FILER_PROXY;
}
public String getChunkUrl(String chunkId, String url, String publicUrl) {
switch (this.volumeServerAccess) {
case VOLUME_SERVER_ACCESS_PUBLIC_URL:
return String.format("http://%s/%s", publicUrl, chunkId);
case VOLUME_SERVER_ACCESS_FILER_PROXY:
return String.format("http://%s/?proxyChunkId=%s", this.filerAddress, chunkId);
default:
return String.format("http://%s/%s", url, chunkId);
}
}
}
@@ -1,26 +1,22 @@
package seaweed.hdfs;
package seaweedfs.client;
// based on org.apache.hadoop.fs.azurebfs.services.AbfsInputStream
import org.apache.hadoop.fs.FSExceptionMessages;
import org.apache.hadoop.fs.FSInputStream;
import org.apache.hadoop.fs.FileSystem.Statistics;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import seaweedfs.client.FilerGrpcClient;
import seaweedfs.client.FilerProto;
import seaweedfs.client.SeaweedRead;
import java.io.EOFException;
import java.io.IOException;
import java.io.InputStream;
import java.nio.ByteBuffer;
import java.util.List;
public class SeaweedInputStream extends FSInputStream {
public class SeaweedInputStream extends InputStream {
private static final Logger LOG = LoggerFactory.getLogger(SeaweedInputStream.class);
private static final IOException EXCEPTION_STREAM_IS_CLOSED = new IOException("Stream is closed!");
private final FilerGrpcClient filerGrpcClient;
private final Statistics statistics;
private final String path;
private final FilerProto.Entry entry;
private final List<SeaweedRead.VisibleInterval> visibleIntervalList;
@@ -32,11 +28,26 @@ public class SeaweedInputStream extends FSInputStream {
public SeaweedInputStream(
final FilerGrpcClient filerGrpcClient,
final Statistics statistics,
final String fullpath) throws IOException {
this.filerGrpcClient = filerGrpcClient;
this.path = fullpath;
FilerClient filerClient = new FilerClient(filerGrpcClient);
this.entry = filerClient.lookupEntry(
SeaweedOutputStream.getParentDirectory(fullpath),
SeaweedOutputStream.getFileName(fullpath));
this.contentLength = SeaweedRead.fileSize(entry);
this.visibleIntervalList = SeaweedRead.nonOverlappingVisibleIntervals(filerGrpcClient, entry.getChunksList());
LOG.debug("new path:{} entry:{} visibleIntervalList:{}", path, entry, visibleIntervalList);
}
public SeaweedInputStream(
final FilerGrpcClient filerGrpcClient,
final String path,
final FilerProto.Entry entry) throws IOException {
this.filerGrpcClient = filerGrpcClient;
this.statistics = statistics;
this.path = path;
this.entry = entry;
this.contentLength = SeaweedRead.fileSize(entry);
@@ -63,14 +74,8 @@ public class SeaweedInputStream extends FSInputStream {
}
@Override
public synchronized int read(final byte[] b, final int off, final int len) throws IOException {
public int read(final byte[] b, final int off, final int len) throws IOException {
if (position < 0) {
throw new IllegalArgumentException("attempting to read from negative offset");
}
if (position >= contentLength) {
return -1; // Hadoop prefers -1 to EOFException
}
if (b == null) {
throw new IllegalArgumentException("null byte array passed in to read() method");
}
@@ -84,53 +89,62 @@ public class SeaweedInputStream extends FSInputStream {
throw new IllegalArgumentException("requested read length is more than will fit after requested offset in buffer");
}
long bytesRead = SeaweedRead.read(this.filerGrpcClient, this.visibleIntervalList, this.position, b, off, len, SeaweedRead.fileSize(entry));
ByteBuffer buf = ByteBuffer.wrap(b, off, len);
return read(buf);
}
// implement ByteBufferReadable
public synchronized int read(ByteBuffer buf) throws IOException {
if (position < 0) {
throw new IllegalArgumentException("attempting to read from negative offset");
}
if (position >= contentLength) {
return -1; // Hadoop prefers -1 to EOFException
}
long bytesRead = 0;
int len = buf.remaining();
int start = (int) this.position;
if (start+len <= entry.getContent().size()) {
entry.getContent().substring(start, start+len).copyTo(buf);
} else {
bytesRead = SeaweedRead.read(this.filerGrpcClient, this.visibleIntervalList, this.position, buf, SeaweedRead.fileSize(entry));
}
if (bytesRead > Integer.MAX_VALUE) {
throw new IOException("Unexpected Content-Length");
}
if (bytesRead > 0) {
this.position += bytesRead;
if (statistics != null) {
statistics.incrementBytesRead(bytesRead);
}
}
return (int) bytesRead;
}
/**
* Seek to given position in stream.
*
* @param n position to seek to
* @throws IOException if there is an error
* @throws EOFException if attempting to seek past end of file
*/
@Override
public synchronized void seek(long n) throws IOException {
if (closed) {
throw new IOException(FSExceptionMessages.STREAM_IS_CLOSED);
throw EXCEPTION_STREAM_IS_CLOSED;
}
if (n < 0) {
throw new EOFException(FSExceptionMessages.NEGATIVE_SEEK);
throw new EOFException("Cannot seek to a negative offset");
}
if (n > contentLength) {
throw new EOFException(FSExceptionMessages.CANNOT_SEEK_PAST_EOF);
throw new EOFException("Attempted to seek or read past the end of the file");
}
this.position = n;
}
@Override
public synchronized long skip(long n) throws IOException {
if (closed) {
throw new IOException(FSExceptionMessages.STREAM_IS_CLOSED);
throw EXCEPTION_STREAM_IS_CLOSED;
}
if (this.position == contentLength) {
if (n > 0) {
throw new EOFException(FSExceptionMessages.CANNOT_SEEK_PAST_EOF);
throw new EOFException("Attempted to seek or read past the end of the file");
}
}
long newPos = this.position + n;
@@ -158,10 +172,9 @@ public class SeaweedInputStream extends FSInputStream {
@Override
public synchronized int available() throws IOException {
if (closed) {
throw new IOException(
FSExceptionMessages.STREAM_IS_CLOSED);
throw EXCEPTION_STREAM_IS_CLOSED;
}
final long remaining = this.contentLength - this.getPos();
final long remaining = this.contentLength - this.position;
return remaining <= Integer.MAX_VALUE
? (int) remaining : Integer.MAX_VALUE;
}
@@ -176,65 +189,21 @@ public class SeaweedInputStream extends FSInputStream {
*/
public long length() throws IOException {
if (closed) {
throw new IOException(FSExceptionMessages.STREAM_IS_CLOSED);
throw EXCEPTION_STREAM_IS_CLOSED;
}
return contentLength;
}
/**
* Return the current offset from the start of the file
*
* @throws IOException throws {@link IOException} if there is an error
*/
@Override
public synchronized long getPos() throws IOException {
if (closed) {
throw new IOException(FSExceptionMessages.STREAM_IS_CLOSED);
throw EXCEPTION_STREAM_IS_CLOSED;
}
return position;
}
/**
* Seeks a different copy of the data. Returns true if
* found a new source, false otherwise.
*
* @throws IOException throws {@link IOException} if there is an error
*/
@Override
public boolean seekToNewSource(long l) throws IOException {
return false;
}
@Override
public synchronized void close() throws IOException {
closed = true;
}
/**
* Not supported by this stream. Throws {@link UnsupportedOperationException}
*
* @param readlimit ignored
*/
@Override
public synchronized void mark(int readlimit) {
throw new UnsupportedOperationException("mark()/reset() not supported on this stream");
}
/**
* Not supported by this stream. Throws {@link UnsupportedOperationException}
*/
@Override
public synchronized void reset() throws IOException {
throw new UnsupportedOperationException("mark()/reset() not supported on this stream");
}
/**
* gets whether mark and reset are supported by {@code ADLFileInputStream}. Always returns false.
*
* @return always {@code false}
*/
@Override
public boolean markSupported() {
return false;
}
}
@@ -1,16 +1,9 @@
package seaweed.hdfs;
package seaweedfs.client;
// adapted from org.apache.hadoop.fs.azurebfs.services.AbfsOutputStream
import com.google.common.base.Preconditions;
import org.apache.hadoop.fs.FSExceptionMessages;
import org.apache.hadoop.fs.Path;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import seaweedfs.client.ByteBufferPool;
import seaweedfs.client.FilerGrpcClient;
import seaweedfs.client.FilerProto;
import seaweedfs.client.SeaweedWrite;
import java.io.IOException;
import java.io.InterruptedIOException;
@@ -18,21 +11,19 @@ import java.io.OutputStream;
import java.nio.ByteBuffer;
import java.util.concurrent.*;
import static seaweed.hdfs.SeaweedFileSystemStore.getParentDirectory;
public class SeaweedOutputStream extends OutputStream {
private static final Logger LOG = LoggerFactory.getLogger(SeaweedOutputStream.class);
protected final boolean supportFlush = true;
private final FilerGrpcClient filerGrpcClient;
private final Path path;
private final String path;
private final int bufferSize;
private final int maxConcurrentRequestCount;
private final ThreadPoolExecutor threadExecutor;
private final ExecutorCompletionService<Void> completionService;
private final FilerProto.Entry.Builder entry;
private final boolean supportFlush = false; // true;
private final ConcurrentLinkedDeque<WriteOperation> writeOperations;
private final boolean shouldSaveMetadata = false;
private FilerProto.Entry.Builder entry;
private long position;
private boolean closed;
private volatile IOException lastError;
@@ -42,7 +33,15 @@ public class SeaweedOutputStream extends OutputStream {
private long outputIndex;
private String replication = "000";
public SeaweedOutputStream(FilerGrpcClient filerGrpcClient, final Path path, FilerProto.Entry.Builder entry,
public SeaweedOutputStream(FilerGrpcClient filerGrpcClient, final String fullpath) {
this(filerGrpcClient, fullpath, "000");
}
public SeaweedOutputStream(FilerGrpcClient filerGrpcClient, final String fullpath, final String replication) {
this(filerGrpcClient, fullpath, null, 0, 8 * 1024 * 1024, "000");
}
public SeaweedOutputStream(FilerGrpcClient filerGrpcClient, final String path, FilerProto.Entry.Builder entry,
final long position, final int bufferSize, final String replication) {
this.filerGrpcClient = filerGrpcClient;
this.replication = replication;
@@ -67,7 +66,45 @@ public class SeaweedOutputStream extends OutputStream {
this.completionService = new ExecutorCompletionService<>(this.threadExecutor);
this.entry = entry;
if (this.entry == null) {
long now = System.currentTimeMillis() / 1000L;
this.entry = FilerProto.Entry.newBuilder()
.setName(getFileName(path))
.setIsDirectory(false)
.setAttributes(FilerProto.FuseAttributes.newBuilder()
.setFileMode(0755)
.setReplication(replication)
.setCrtime(now)
.setMtime(now)
.clearGroupName()
);
}
}
public static String getParentDirectory(String path) {
int protoIndex = path.indexOf("://");
if (protoIndex >= 0) {
int pathStart = path.indexOf("/", protoIndex+3);
path = path.substring(pathStart);
}
if (path.equals("/")) {
return path;
}
int lastSlashIndex = path.lastIndexOf("/");
if (lastSlashIndex == 0) {
return "/";
}
return path.substring(0, lastSlashIndex);
}
public static String getFileName(String path) {
if (path.indexOf("/") < 0) {
return path;
}
int lastSlashIndex = path.lastIndexOf("/");
return path.substring(lastSlashIndex + 1);
}
private synchronized void flushWrittenBytesToServiceInternal(final long offset) throws IOException {
@@ -89,7 +126,9 @@ public class SeaweedOutputStream extends OutputStream {
throws IOException {
maybeThrowLastError();
Preconditions.checkArgument(data != null, "null data");
if (data == null) {
return;
}
if (off < 0 || length < 0 || length > data.length - off) {
throw new IndexOutOfBoundsException();
@@ -152,7 +191,7 @@ public class SeaweedOutputStream extends OutputStream {
flushInternal();
threadExecutor.shutdown();
} finally {
lastError = new IOException(FSExceptionMessages.STREAM_IS_CLOSED);
lastError = new IOException("Stream is closed!");
ByteBufferPool.release(buffer);
buffer = null;
outputIndex = 0;
@@ -162,6 +201,7 @@ public class SeaweedOutputStream extends OutputStream {
threadExecutor.shutdownNow();
}
}
}
private synchronized void writeCurrentBufferToService() throws IOException {
@@ -185,7 +225,7 @@ public class SeaweedOutputStream extends OutputStream {
}
final Future<Void> job = completionService.submit(() -> {
// System.out.println(path + " is going to save [" + (writePosition) + "," + ((writePosition) + bytesLength) + ")");
SeaweedWrite.writeData(entry, replication, filerGrpcClient, writePosition, bufferToWrite.array(), bufferToWrite.position(), bufferToWrite.limit());
SeaweedWrite.writeData(entry, replication, filerGrpcClient, writePosition, bufferToWrite.array(), bufferToWrite.position(), bufferToWrite.limit(), path);
// System.out.println(path + " saved [" + (writePosition) + "," + ((writePosition) + bytesLength) + ")");
ByteBufferPool.release(bufferToWrite);
return null;
@@ -239,13 +279,13 @@ public class SeaweedOutputStream extends OutputStream {
}
}
private synchronized void flushInternal() throws IOException {
protected synchronized void flushInternal() throws IOException {
maybeThrowLastError();
writeCurrentBufferToService();
flushWrittenBytesToService();
}
private synchronized void flushInternalAsync() throws IOException {
protected synchronized void flushInternalAsync() throws IOException {
maybeThrowLastError();
writeCurrentBufferToService();
flushWrittenBytesToServiceAsync();
@@ -278,10 +318,6 @@ public class SeaweedOutputStream extends OutputStream {
private final long length;
WriteOperation(final Future<Void> task, final long startOffset, final long length) {
Preconditions.checkNotNull(task, "task");
Preconditions.checkArgument(startOffset >= 0, "startOffset");
Preconditions.checkArgument(length >= 0, "length");
this.task = task;
this.startOffset = startOffset;
this.length = length;
@@ -12,6 +12,7 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.*;
public class SeaweedRead {
@@ -19,24 +20,36 @@ public class SeaweedRead {
private static final Logger LOG = LoggerFactory.getLogger(SeaweedRead.class);
static ChunkCache chunkCache = new ChunkCache(4);
static VolumeIdCache volumeIdCache = new VolumeIdCache(4 * 1024);
// returns bytesRead
public static long read(FilerGrpcClient filerGrpcClient, List<VisibleInterval> visibleIntervals,
final long position, final byte[] buffer, final int bufferOffset,
final int bufferLength, final long fileSize) throws IOException {
final long position, final ByteBuffer buf, final long fileSize) throws IOException {
List<ChunkView> chunkViews = viewFromVisibles(visibleIntervals, position, bufferLength);
List<ChunkView> chunkViews = viewFromVisibles(visibleIntervals, position, buf.remaining());
Map<String, FilerProto.Locations> knownLocations = new HashMap<>();
FilerProto.LookupVolumeRequest.Builder lookupRequest = FilerProto.LookupVolumeRequest.newBuilder();
for (ChunkView chunkView : chunkViews) {
String vid = parseVolumeId(chunkView.fileId);
lookupRequest.addVolumeIds(vid);
FilerProto.Locations locations = volumeIdCache.getLocations(vid);
if (locations == null) {
lookupRequest.addVolumeIds(vid);
} else {
knownLocations.put(vid, locations);
}
}
FilerProto.LookupVolumeResponse lookupResponse = filerGrpcClient
.getBlockingStub().lookupVolume(lookupRequest.build());
Map<String, FilerProto.Locations> vid2Locations = lookupResponse.getLocationsMapMap();
if (lookupRequest.getVolumeIdsCount() > 0) {
FilerProto.LookupVolumeResponse lookupResponse = filerGrpcClient
.getBlockingStub().lookupVolume(lookupRequest.build());
Map<String, FilerProto.Locations> vid2Locations = lookupResponse.getLocationsMapMap();
for (Map.Entry<String, FilerProto.Locations> entry : vid2Locations.entrySet()) {
volumeIdCache.setLocations(entry.getKey(), entry.getValue());
knownLocations.put(entry.getKey(), entry.getValue());
}
}
//TODO parallel this
long readCount = 0;
@@ -46,18 +59,19 @@ public class SeaweedRead {
if (startOffset < chunkView.logicOffset) {
long gap = chunkView.logicOffset - startOffset;
LOG.debug("zero [{},{})", startOffset, startOffset + gap);
buf.position(buf.position()+ (int)gap);
readCount += gap;
startOffset += gap;
}
FilerProto.Locations locations = vid2Locations.get(parseVolumeId(chunkView.fileId));
FilerProto.Locations locations = knownLocations.get(parseVolumeId(chunkView.fileId));
if (locations == null || locations.getLocationsCount() == 0) {
LOG.error("failed to locate {}", chunkView.fileId);
// log here!
return 0;
}
int len = readChunkView(startOffset, buffer, bufferOffset + readCount, chunkView, locations);
int len = readChunkView(filerGrpcClient, startOffset, buf, chunkView, locations);
LOG.debug("read [{},{}) {} size {}", startOffset, startOffset + len, chunkView.fileId, chunkView.size);
@@ -66,11 +80,12 @@ public class SeaweedRead {
}
long limit = Math.min(bufferOffset + bufferLength, fileSize);
long limit = Math.min(buf.limit(), fileSize);
if (startOffset < limit) {
long gap = limit - startOffset;
LOG.debug("zero2 [{},{})", startOffset, startOffset + gap);
buf.position(buf.position()+ (int)gap);
readCount += gap;
startOffset += gap;
}
@@ -78,30 +93,30 @@ public class SeaweedRead {
return readCount;
}
private static int readChunkView(long startOffset, byte[] buffer, long bufOffset, ChunkView chunkView, FilerProto.Locations locations) throws IOException {
private static int readChunkView(FilerGrpcClient filerGrpcClient, long startOffset, ByteBuffer buf, ChunkView chunkView, FilerProto.Locations locations) throws IOException {
byte[] chunkData = chunkCache.getChunk(chunkView.fileId);
if (chunkData == null) {
chunkData = doFetchFullChunkData(chunkView, locations);
chunkData = doFetchFullChunkData(filerGrpcClient, chunkView, locations);
chunkCache.setChunk(chunkView.fileId, chunkData);
}
int len = (int) chunkView.size;
LOG.debug("readChunkView fid:{} chunkData.length:{} chunkView.offset:{} chunkView[{};{}) buf[{},{})/{} startOffset:{}",
chunkView.fileId, chunkData.length, chunkView.offset, chunkView.logicOffset, chunkView.logicOffset + chunkView.size, bufOffset, bufOffset + len, buffer.length, startOffset);
System.arraycopy(chunkData, (int) (startOffset - chunkView.logicOffset + chunkView.offset), buffer, (int) bufOffset, len);
LOG.debug("readChunkView fid:{} chunkData.length:{} chunkView.offset:{} chunkView[{};{}) startOffset:{}",
chunkView.fileId, chunkData.length, chunkView.offset, chunkView.logicOffset, chunkView.logicOffset + chunkView.size, startOffset);
buf.put(chunkData, (int) (startOffset - chunkView.logicOffset + chunkView.offset), len);
return len;
}
public static byte[] doFetchFullChunkData(ChunkView chunkView, FilerProto.Locations locations) throws IOException {
public static byte[] doFetchFullChunkData(FilerGrpcClient filerGrpcClient, ChunkView chunkView, FilerProto.Locations locations) throws IOException {
byte[] data = null;
IOException lastException = null;
for (long waitTime = 1000L; waitTime < 10 * 1000; waitTime += waitTime / 2) {
for (FilerProto.Location location : locations.getLocationsList()) {
String url = String.format("http://%s/%s", location.getUrl(), chunkView.fileId);
String url = filerGrpcClient.getChunkUrl(chunkView.fileId, location.getUrl(), location.getPublicUrl());
try {
data = doFetchOneFullChunkData(chunkView, url);
lastException = null;
@@ -130,7 +145,7 @@ public class SeaweedRead {
}
public static byte[] doFetchOneFullChunkData(ChunkView chunkView, String url) throws IOException {
private static byte[] doFetchOneFullChunkData(ChunkView chunkView, String url) throws IOException {
HttpGet request = new HttpGet(url);
@@ -26,9 +26,10 @@ public class SeaweedWrite {
final FilerGrpcClient filerGrpcClient,
final long offset,
final byte[] bytes,
final long bytesOffset, final long bytesLength) throws IOException {
final long bytesOffset, final long bytesLength,
final String path) throws IOException {
FilerProto.FileChunk.Builder chunkBuilder = writeChunk(
replication, filerGrpcClient, offset, bytes, bytesOffset, bytesLength);
replication, filerGrpcClient, offset, bytes, bytesOffset, bytesLength, path);
synchronized (entry) {
entry.addChunks(chunkBuilder);
}
@@ -39,18 +40,20 @@ public class SeaweedWrite {
final long offset,
final byte[] bytes,
final long bytesOffset,
final long bytesLength) throws IOException {
final long bytesLength,
final String path) throws IOException {
FilerProto.AssignVolumeResponse response = filerGrpcClient.getBlockingStub().assignVolume(
FilerProto.AssignVolumeRequest.newBuilder()
.setCollection(filerGrpcClient.getCollection())
.setReplication(replication == null ? filerGrpcClient.getReplication() : replication)
.setDataCenter("")
.setTtlSec(0)
.setPath(path)
.build());
String fileId = response.getFileId();
String url = response.getUrl();
String auth = response.getAuth();
String targetUrl = String.format("http://%s/%s", url, fileId);
String targetUrl = filerGrpcClient.getChunkUrl(fileId, response.getUrl(), response.getPublicUrl());
ByteString cipherKeyString = com.google.protobuf.ByteString.EMPTY;
byte[] cipherKey = null;
@@ -77,7 +80,7 @@ public class SeaweedWrite {
final FilerProto.Entry.Builder entry) throws IOException {
synchronized (entry) {
List<FilerProto.FileChunk> chunks = FileChunkManifest.maybeManifestize(filerGrpcClient, entry.getChunksList());
List<FilerProto.FileChunk> chunks = FileChunkManifest.maybeManifestize(filerGrpcClient, entry.getChunksList(), parentDirectory);
entry.clearChunks();
entry.addAllChunks(chunks);
filerGrpcClient.getBlockingStub().createEntry(
@@ -0,0 +1,36 @@
package seaweedfs.client;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import java.util.concurrent.TimeUnit;
public class VolumeIdCache {
private Cache<String, FilerProto.Locations> cache = null;
public VolumeIdCache(int maxEntries) {
if (maxEntries == 0) {
return;
}
this.cache = CacheBuilder.newBuilder()
.maximumSize(maxEntries)
.expireAfterAccess(5, TimeUnit.MINUTES)
.build();
}
public FilerProto.Locations getLocations(String volumeId) {
if (this.cache == null) {
return null;
}
return this.cache.getIfPresent(volumeId);
}
public void setLocations(String volumeId, FilerProto.Locations locations) {
if (this.cache == null) {
return;
}
this.cache.put(volumeId, locations);
}
}
+22 -1
View File
@@ -100,6 +100,7 @@ message Entry {
map<string, bytes> extended = 5;
bytes hard_link_id = 7;
int32 hard_link_counter = 8; // only exists in hard link meta data
bytes content = 9; // if not empty, the file content
}
message FullEntry {
@@ -217,7 +218,7 @@ message AssignVolumeRequest {
string replication = 3;
int32 ttl_sec = 4;
string data_center = 5;
string parent_path = 6;
string path = 6;
string rack = 7;
}
@@ -348,3 +349,23 @@ message KvPutRequest {
message KvPutResponse {
string error = 1;
}
// path-based configurations
message FilerConf {
int32 version = 1;
message PathConf {
string location_prefix = 1;
string collection = 2;
string replication = 3;
string ttl = 4;
enum DiskType {
NONE = 0;
HDD = 1;
SSD = 2;
}
DiskType disk_type = 5;
bool fsync = 6;
uint32 volume_growth_count = 7;
}
repeated PathConf locations = 2;
}
+32
View File
@@ -0,0 +1,32 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.example</groupId>
<artifactId>unzip</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>com.github.chrislusf</groupId>
<artifactId>seaweedfs-client</artifactId>
<version>1.6.0</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>com.github.chrislusf</groupId>
<artifactId>seaweedfs-hadoop2-client</artifactId>
<version>1.6.0</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-common</artifactId>
<version>2.9.2</version>
<scope>compile</scope>
</dependency>
</dependencies>
</project>
@@ -0,0 +1,48 @@
package com.seaweedfs.examples;
import seaweedfs.client.FilerGrpcClient;
import seaweedfs.client.SeaweedInputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
public class ExampleReadFile {
public static void main(String[] args) throws IOException {
FilerGrpcClient filerGrpcClient = new FilerGrpcClient("localhost", 18888);
long startTime = System.currentTimeMillis();
parseZip("/Users/chris/tmp/test.zip");
long startTime2 = System.currentTimeMillis();
long localProcessTime = startTime2 - startTime;
SeaweedInputStream seaweedInputStream = new SeaweedInputStream(
filerGrpcClient, "/test.zip");
parseZip(seaweedInputStream);
long swProcessTime = System.currentTimeMillis() - startTime2;
System.out.println("Local time: " + localProcessTime);
System.out.println("SeaweedFS time: " + swProcessTime);
}
public static void parseZip(String filename) throws IOException {
FileInputStream fileInputStream = new FileInputStream(filename);
parseZip(fileInputStream);
}
public static void parseZip(InputStream is) throws IOException {
ZipInputStream zin = new ZipInputStream(is);
ZipEntry ze;
while ((ze = zin.getNextEntry()) != null) {
System.out.println(ze.getName());
}
}
}
@@ -0,0 +1,46 @@
package com.seaweedfs.examples;
import seaweedfs.client.FilerClient;
import seaweedfs.client.FilerProto;
import java.io.IOException;
import java.util.Date;
import java.util.Iterator;
public class ExampleWatchFileChanges {
public static void main(String[] args) throws IOException {
FilerClient filerClient = new FilerClient("localhost", 18888);
long sinceNs = (System.currentTimeMillis() - 3600 * 1000) * 1000000L;
Iterator<FilerProto.SubscribeMetadataResponse> watch = filerClient.watch(
"/buckets",
"exampleClientName",
sinceNs
);
System.out.println("Connected to filer, subscribing from " + new Date());
while (watch.hasNext()) {
FilerProto.SubscribeMetadataResponse event = watch.next();
FilerProto.EventNotification notification = event.getEventNotification();
if (!event.getDirectory().equals(notification.getNewParentPath())) {
// move an entry to a new directory, possibly with a new name
if (notification.hasOldEntry() && notification.hasNewEntry()) {
System.out.println("moved " + event.getDirectory() + "/" + notification.getOldEntry().getName() + " to " + notification.getNewParentPath() + "/" + notification.getNewEntry().getName());
} else {
System.out.println("this should not happen.");
}
} else if (notification.hasNewEntry() && !notification.hasOldEntry()) {
System.out.println("created entry " + event.getDirectory() + "/" + notification.getNewEntry().getName());
} else if (!notification.hasNewEntry() && notification.hasOldEntry()) {
System.out.println("deleted entry " + event.getDirectory() + "/" + notification.getOldEntry().getName());
} else if (notification.hasNewEntry() && notification.hasOldEntry()) {
System.out.println("updated entry " + event.getDirectory() + "/" + notification.getNewEntry().getName());
}
}
}
}
@@ -0,0 +1,48 @@
package com.seaweedfs.examples;
import seaweedfs.client.FilerGrpcClient;
import seaweedfs.client.SeaweedInputStream;
import seaweedfs.client.SeaweedOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
public class ExampleWriteFile {
public static void main(String[] args) throws IOException {
FilerGrpcClient filerGrpcClient = new FilerGrpcClient("localhost", 18888);
SeaweedInputStream seaweedInputStream = new SeaweedInputStream(
filerGrpcClient, "/test.zip");
unZipFiles(filerGrpcClient, seaweedInputStream);
}
public static void unZipFiles(FilerGrpcClient filerGrpcClient, InputStream is) throws IOException {
ZipInputStream zin = new ZipInputStream(is);
ZipEntry ze;
while ((ze = zin.getNextEntry()) != null) {
String filename = ze.getName();
if (filename.indexOf("/") >= 0) {
filename = filename.substring(filename.lastIndexOf("/") + 1);
}
if (filename.length()==0) {
continue;
}
SeaweedOutputStream seaweedOutputStream = new SeaweedOutputStream(filerGrpcClient, "/test/"+filename);
byte[] bytesIn = new byte[16 * 1024];
int read = 0;
while ((read = zin.read(bytesIn))!=-1) {
seaweedOutputStream.write(bytesIn,0,read);
}
seaweedOutputStream.close();
System.out.println(ze.getName());
}
}
}
@@ -0,0 +1,25 @@
package com.seaweedfs.examples;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.IOUtils;
import java.io.*;
public class HdfsCopyFile {
public static void main(String[] args) throws IOException {
Configuration configuration = new Configuration();
configuration.set("fs.defaultFS", "seaweedfs://localhost:8888");
configuration.set("fs.seaweedfs.impl", "seaweed.hdfs.SeaweedFileSystem");
FileSystem fs = FileSystem.get(configuration);
String source = "/Users/chris/tmp/test.zip";
String destination = "/buckets/spark/test01.zip";
InputStream in = new BufferedInputStream(new FileInputStream(source));
OutputStream out = fs.create(new Path(destination));
IOUtils.copyBytes(in, out, 4096, true);
}
}
+1 -1
View File
@@ -301,7 +301,7 @@
</snapshotRepository>
</distributionManagement>
<properties>
<seaweedfs.client.version>1.5.1</seaweedfs.client.version>
<seaweedfs.client.version>1.6.0</seaweedfs.client.version>
<hadoop.version>2.9.2</hadoop.version>
</properties>
</project>
+1 -1
View File
@@ -5,7 +5,7 @@
<modelVersion>4.0.0</modelVersion>
<properties>
<seaweedfs.client.version>1.5.1</seaweedfs.client.version>
<seaweedfs.client.version>1.6.0</seaweedfs.client.version>
<hadoop.version>2.9.2</hadoop.version>
</properties>
@@ -0,0 +1,25 @@
package seaweed.hdfs;
import org.apache.hadoop.fs.*;
import java.io.IOException;
import java.nio.ByteBuffer;
public class BufferedByteBufferReadableInputStream extends BufferedFSInputStream implements ByteBufferReadable {
public BufferedByteBufferReadableInputStream(FSInputStream in, int size) {
super(in, size);
if (!(in instanceof Seekable) || !(in instanceof PositionedReadable)) {
throw new IllegalArgumentException("In is not an instance of Seekable or PositionedReadable");
}
}
@Override
public int read(ByteBuffer buf) throws IOException {
if (this.in instanceof ByteBufferReadable) {
return ((ByteBufferReadable)this.in).read(buf);
} else {
throw new UnsupportedOperationException("Byte-buffer read unsupported by input stream");
}
}
}
@@ -25,6 +25,8 @@ public class SeaweedFileSystem extends FileSystem {
public static final String FS_SEAWEED_FILER_PORT = "fs.seaweed.filer.port";
public static final int FS_SEAWEED_DEFAULT_PORT = 8888;
public static final String FS_SEAWEED_BUFFER_SIZE = "fs.seaweed.buffer.size";
public static final String FS_SEAWEED_REPLICATION = "fs.seaweed.replication";
public static final String FS_SEAWEED_VOLUME_SERVER_ACCESS = "fs.seaweed.volume.server.access";
public static final int FS_SEAWEED_DEFAULT_BUFFER_SIZE = 4 * 1024 * 1024;
private static final Logger LOG = LoggerFactory.getLogger(SeaweedFileSystem.class);
@@ -65,6 +67,12 @@ public class SeaweedFileSystem extends FileSystem {
}
@Override
public void close() throws IOException {
super.close();
this.seaweedFileSystemStore.close();
}
@Override
public FSDataInputStream open(Path path, int bufferSize) throws IOException {
@@ -75,7 +83,7 @@ public class SeaweedFileSystem extends FileSystem {
try {
int seaweedBufferSize = this.getConf().getInt(FS_SEAWEED_BUFFER_SIZE, FS_SEAWEED_DEFAULT_BUFFER_SIZE);
FSInputStream inputStream = seaweedFileSystemStore.openFileForRead(path, statistics);
return new FSDataInputStream(new BufferedFSInputStream(inputStream, 4 * seaweedBufferSize));
return new FSDataInputStream(new BufferedByteBufferReadableInputStream(inputStream, 4 * seaweedBufferSize));
} catch (Exception ex) {
LOG.warn("open path: {} bufferSize:{}", path, bufferSize, ex);
return null;
@@ -91,7 +99,7 @@ public class SeaweedFileSystem extends FileSystem {
path = qualify(path);
try {
String replicaPlacement = String.format("%03d", replication - 1);
String replicaPlacement = this.getConf().get(FS_SEAWEED_REPLICATION, String.format("%03d", replication - 1));
int seaweedBufferSize = this.getConf().getInt(FS_SEAWEED_BUFFER_SIZE, FS_SEAWEED_DEFAULT_BUFFER_SIZE);
OutputStream outputStream = seaweedFileSystemStore.createFile(path, overwrite, permission, seaweedBufferSize, replicaPlacement);
return new FSDataOutputStream(outputStream, statistics);
@@ -18,8 +18,7 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import static seaweed.hdfs.SeaweedFileSystem.FS_SEAWEED_BUFFER_SIZE;
import static seaweed.hdfs.SeaweedFileSystem.FS_SEAWEED_DEFAULT_BUFFER_SIZE;
import static seaweed.hdfs.SeaweedFileSystem.*;
public class SeaweedFileSystemStore {
@@ -34,6 +33,21 @@ public class SeaweedFileSystemStore {
filerGrpcClient = new FilerGrpcClient(host, grpcPort);
filerClient = new FilerClient(filerGrpcClient);
this.conf = conf;
String volumeServerAccessMode = this.conf.get(FS_SEAWEED_VOLUME_SERVER_ACCESS, "direct");
if (volumeServerAccessMode.equals("publicUrl")) {
filerGrpcClient.setAccessVolumeServerByPublicUrl();
} else if (volumeServerAccessMode.equals("filerProxy")) {
filerGrpcClient.setAccessVolumeServerByFilerProxy();
}
}
public void close() {
try {
this.filerGrpcClient.shutdown();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public static String getParentDirectory(Path path) {
@@ -185,6 +199,7 @@ public class SeaweedFileSystemStore {
if (existingEntry != null) {
entry = FilerProto.Entry.newBuilder();
entry.mergeFrom(existingEntry);
entry.clearContent();
entry.getAttributesBuilder().setMtime(now);
LOG.debug("createFile merged entry path:{} entry:{} from:{}", path, entry, existingEntry);
writePosition = SeaweedRead.fileSize(existingEntry);
@@ -207,7 +222,7 @@ public class SeaweedFileSystemStore {
SeaweedWrite.writeMeta(filerGrpcClient, getParentDirectory(path), entry);
}
return new SeaweedOutputStream(filerGrpcClient, path, entry, writePosition, bufferSize, replication);
return new SeaweedHadoopOutputStream(filerGrpcClient, path.toString(), entry, writePosition, bufferSize, replication);
}
@@ -221,7 +236,7 @@ public class SeaweedFileSystemStore {
throw new FileNotFoundException("read non-exist file " + path);
}
return new SeaweedInputStream(filerGrpcClient,
return new SeaweedHadoopInputStream(filerGrpcClient,
statistics,
path.toUri().getPath(),
entry);
@@ -0,0 +1,150 @@
package seaweed.hdfs;
// based on org.apache.hadoop.fs.azurebfs.services.AbfsInputStream
import org.apache.hadoop.fs.ByteBufferReadable;
import org.apache.hadoop.fs.FSInputStream;
import org.apache.hadoop.fs.FileSystem.Statistics;
import seaweedfs.client.FilerGrpcClient;
import seaweedfs.client.FilerProto;
import seaweedfs.client.SeaweedInputStream;
import java.io.EOFException;
import java.io.IOException;
import java.nio.ByteBuffer;
public class SeaweedHadoopInputStream extends FSInputStream implements ByteBufferReadable {
private final SeaweedInputStream seaweedInputStream;
private final Statistics statistics;
public SeaweedHadoopInputStream(
final FilerGrpcClient filerGrpcClient,
final Statistics statistics,
final String path,
final FilerProto.Entry entry) throws IOException {
this.seaweedInputStream = new SeaweedInputStream(filerGrpcClient, path, entry);
this.statistics = statistics;
}
@Override
public int read() throws IOException {
return seaweedInputStream.read();
}
@Override
public int read(final byte[] b, final int off, final int len) throws IOException {
return seaweedInputStream.read(b, off, len);
}
// implement ByteBufferReadable
@Override
public synchronized int read(ByteBuffer buf) throws IOException {
int bytesRead = seaweedInputStream.read(buf);
if (bytesRead > 0) {
if (statistics != null) {
statistics.incrementBytesRead(bytesRead);
}
}
return bytesRead;
}
/**
* Seek to given position in stream.
*
* @param n position to seek to
* @throws IOException if there is an error
* @throws EOFException if attempting to seek past end of file
*/
@Override
public synchronized void seek(long n) throws IOException {
seaweedInputStream.seek(n);
}
@Override
public synchronized long skip(long n) throws IOException {
return seaweedInputStream.skip(n);
}
/**
* Return the size of the remaining available bytes
* if the size is less than or equal to {@link Integer#MAX_VALUE},
* otherwise, return {@link Integer#MAX_VALUE}.
* <p>
* This is to match the behavior of DFSInputStream.available(),
* which some clients may rely on (HBase write-ahead log reading in
* particular).
*/
@Override
public synchronized int available() throws IOException {
return seaweedInputStream.available();
}
/**
* Returns the length of the file that this stream refers to. Note that the length returned is the length
* as of the time the Stream was opened. Specifically, if there have been subsequent appends to the file,
* they wont be reflected in the returned length.
*
* @return length of the file.
* @throws IOException if the stream is closed
*/
public long length() throws IOException {
return seaweedInputStream.length();
}
/**
* Return the current offset from the start of the file
*
* @throws IOException throws {@link IOException} if there is an error
*/
@Override
public synchronized long getPos() throws IOException {
return seaweedInputStream.getPos();
}
/**
* Seeks a different copy of the data. Returns true if
* found a new source, false otherwise.
*
* @throws IOException throws {@link IOException} if there is an error
*/
@Override
public boolean seekToNewSource(long l) throws IOException {
return false;
}
@Override
public synchronized void close() throws IOException {
seaweedInputStream.close();
}
/**
* Not supported by this stream. Throws {@link UnsupportedOperationException}
*
* @param readlimit ignored
*/
@Override
public synchronized void mark(int readlimit) {
throw new UnsupportedOperationException("mark()/reset() not supported on this stream");
}
/**
* Not supported by this stream. Throws {@link UnsupportedOperationException}
*/
@Override
public synchronized void reset() throws IOException {
throw new UnsupportedOperationException("mark()/reset() not supported on this stream");
}
/**
* gets whether mark and reset are supported by {@code ADLFileInputStream}. Always returns false.
*
* @return always {@code false}
*/
@Override
public boolean markSupported() {
return false;
}
}
@@ -0,0 +1,16 @@
package seaweed.hdfs;
// adapted from org.apache.hadoop.fs.azurebfs.services.AbfsOutputStream
import seaweedfs.client.FilerGrpcClient;
import seaweedfs.client.FilerProto;
import seaweedfs.client.SeaweedOutputStream;
public class SeaweedHadoopOutputStream extends SeaweedOutputStream {
public SeaweedHadoopOutputStream(FilerGrpcClient filerGrpcClient, final String path, FilerProto.Entry.Builder entry,
final long position, final int bufferSize, final String replication) {
super(filerGrpcClient, path.toString(), entry, position, bufferSize, replication);
}
}
@@ -1,240 +0,0 @@
package seaweed.hdfs;
// based on org.apache.hadoop.fs.azurebfs.services.AbfsInputStream
import org.apache.hadoop.fs.FSExceptionMessages;
import org.apache.hadoop.fs.FSInputStream;
import org.apache.hadoop.fs.FileSystem.Statistics;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import seaweedfs.client.FilerGrpcClient;
import seaweedfs.client.FilerProto;
import seaweedfs.client.SeaweedRead;
import java.io.EOFException;
import java.io.IOException;
import java.util.List;
public class SeaweedInputStream extends FSInputStream {
private static final Logger LOG = LoggerFactory.getLogger(SeaweedInputStream.class);
private final FilerGrpcClient filerGrpcClient;
private final Statistics statistics;
private final String path;
private final FilerProto.Entry entry;
private final List<SeaweedRead.VisibleInterval> visibleIntervalList;
private final long contentLength;
private long position = 0; // cursor of the file
private boolean closed = false;
public SeaweedInputStream(
final FilerGrpcClient filerGrpcClient,
final Statistics statistics,
final String path,
final FilerProto.Entry entry) throws IOException {
this.filerGrpcClient = filerGrpcClient;
this.statistics = statistics;
this.path = path;
this.entry = entry;
this.contentLength = SeaweedRead.fileSize(entry);
this.visibleIntervalList = SeaweedRead.nonOverlappingVisibleIntervals(filerGrpcClient, entry.getChunksList());
LOG.debug("new path:{} entry:{} visibleIntervalList:{}", path, entry, visibleIntervalList);
}
public String getPath() {
return path;
}
@Override
public int read() throws IOException {
byte[] b = new byte[1];
int numberOfBytesRead = read(b, 0, 1);
if (numberOfBytesRead < 0) {
return -1;
} else {
return (b[0] & 0xFF);
}
}
@Override
public synchronized int read(final byte[] b, final int off, final int len) throws IOException {
if (position < 0) {
throw new IllegalArgumentException("attempting to read from negative offset");
}
if (position >= contentLength) {
return -1; // Hadoop prefers -1 to EOFException
}
if (b == null) {
throw new IllegalArgumentException("null byte array passed in to read() method");
}
if (off >= b.length) {
throw new IllegalArgumentException("offset greater than length of array");
}
if (len < 0) {
throw new IllegalArgumentException("requested read length is less than zero");
}
if (len > (b.length - off)) {
throw new IllegalArgumentException("requested read length is more than will fit after requested offset in buffer");
}
long bytesRead = SeaweedRead.read(this.filerGrpcClient, this.visibleIntervalList, this.position, b, off, len, SeaweedRead.fileSize(entry));
if (bytesRead > Integer.MAX_VALUE) {
throw new IOException("Unexpected Content-Length");
}
if (bytesRead > 0) {
this.position += bytesRead;
if (statistics != null) {
statistics.incrementBytesRead(bytesRead);
}
}
return (int) bytesRead;
}
/**
* Seek to given position in stream.
*
* @param n position to seek to
* @throws IOException if there is an error
* @throws EOFException if attempting to seek past end of file
*/
@Override
public synchronized void seek(long n) throws IOException {
if (closed) {
throw new IOException(FSExceptionMessages.STREAM_IS_CLOSED);
}
if (n < 0) {
throw new EOFException(FSExceptionMessages.NEGATIVE_SEEK);
}
if (n > contentLength) {
throw new EOFException(FSExceptionMessages.CANNOT_SEEK_PAST_EOF);
}
this.position = n;
}
@Override
public synchronized long skip(long n) throws IOException {
if (closed) {
throw new IOException(FSExceptionMessages.STREAM_IS_CLOSED);
}
if (this.position == contentLength) {
if (n > 0) {
throw new EOFException(FSExceptionMessages.CANNOT_SEEK_PAST_EOF);
}
}
long newPos = this.position + n;
if (newPos < 0) {
newPos = 0;
n = newPos - this.position;
}
if (newPos > contentLength) {
newPos = contentLength;
n = newPos - this.position;
}
seek(newPos);
return n;
}
/**
* Return the size of the remaining available bytes
* if the size is less than or equal to {@link Integer#MAX_VALUE},
* otherwise, return {@link Integer#MAX_VALUE}.
* <p>
* This is to match the behavior of DFSInputStream.available(),
* which some clients may rely on (HBase write-ahead log reading in
* particular).
*/
@Override
public synchronized int available() throws IOException {
if (closed) {
throw new IOException(
FSExceptionMessages.STREAM_IS_CLOSED);
}
final long remaining = this.contentLength - this.getPos();
return remaining <= Integer.MAX_VALUE
? (int) remaining : Integer.MAX_VALUE;
}
/**
* Returns the length of the file that this stream refers to. Note that the length returned is the length
* as of the time the Stream was opened. Specifically, if there have been subsequent appends to the file,
* they wont be reflected in the returned length.
*
* @return length of the file.
* @throws IOException if the stream is closed
*/
public long length() throws IOException {
if (closed) {
throw new IOException(FSExceptionMessages.STREAM_IS_CLOSED);
}
return contentLength;
}
/**
* Return the current offset from the start of the file
*
* @throws IOException throws {@link IOException} if there is an error
*/
@Override
public synchronized long getPos() throws IOException {
if (closed) {
throw new IOException(FSExceptionMessages.STREAM_IS_CLOSED);
}
return position;
}
/**
* Seeks a different copy of the data. Returns true if
* found a new source, false otherwise.
*
* @throws IOException throws {@link IOException} if there is an error
*/
@Override
public boolean seekToNewSource(long l) throws IOException {
return false;
}
@Override
public synchronized void close() throws IOException {
closed = true;
}
/**
* Not supported by this stream. Throws {@link UnsupportedOperationException}
*
* @param readlimit ignored
*/
@Override
public synchronized void mark(int readlimit) {
throw new UnsupportedOperationException("mark()/reset() not supported on this stream");
}
/**
* Not supported by this stream. Throws {@link UnsupportedOperationException}
*/
@Override
public synchronized void reset() throws IOException {
throw new UnsupportedOperationException("mark()/reset() not supported on this stream");
}
/**
* gets whether mark and reset are supported by {@code ADLFileInputStream}. Always returns false.
*
* @return always {@code false}
*/
@Override
public boolean markSupported() {
return false;
}
}
+1 -1
View File
@@ -309,7 +309,7 @@
</snapshotRepository>
</distributionManagement>
<properties>
<seaweedfs.client.version>1.5.1</seaweedfs.client.version>
<seaweedfs.client.version>1.6.0</seaweedfs.client.version>
<hadoop.version>3.1.1</hadoop.version>
</properties>
</project>
+1 -1
View File
@@ -5,7 +5,7 @@
<modelVersion>4.0.0</modelVersion>
<properties>
<seaweedfs.client.version>1.5.1</seaweedfs.client.version>
<seaweedfs.client.version>1.6.0</seaweedfs.client.version>
<hadoop.version>3.1.1</hadoop.version>
</properties>
@@ -0,0 +1,25 @@
package seaweed.hdfs;
import org.apache.hadoop.fs.*;
import java.io.IOException;
import java.nio.ByteBuffer;
public class BufferedByteBufferReadableInputStream extends BufferedFSInputStream implements ByteBufferReadable {
public BufferedByteBufferReadableInputStream(FSInputStream in, int size) {
super(in, size);
if (!(in instanceof Seekable) || !(in instanceof PositionedReadable)) {
throw new IllegalArgumentException("In is not an instance of Seekable or PositionedReadable");
}
}
@Override
public int read(ByteBuffer buf) throws IOException {
if (this.in instanceof ByteBufferReadable) {
return ((ByteBufferReadable)this.in).read(buf);
} else {
throw new UnsupportedOperationException("Byte-buffer read unsupported by input stream");
}
}
}
@@ -25,6 +25,8 @@ public class SeaweedFileSystem extends FileSystem {
public static final String FS_SEAWEED_FILER_PORT = "fs.seaweed.filer.port";
public static final int FS_SEAWEED_DEFAULT_PORT = 8888;
public static final String FS_SEAWEED_BUFFER_SIZE = "fs.seaweed.buffer.size";
public static final String FS_SEAWEED_REPLICATION = "fs.seaweed.replication";
public static final String FS_SEAWEED_VOLUME_SERVER_ACCESS = "fs.seaweed.volume.server.access";
public static final int FS_SEAWEED_DEFAULT_BUFFER_SIZE = 4 * 1024 * 1024;
private static final Logger LOG = LoggerFactory.getLogger(SeaweedFileSystem.class);
@@ -65,6 +67,12 @@ public class SeaweedFileSystem extends FileSystem {
}
@Override
public void close() throws IOException {
super.close();
this.seaweedFileSystemStore.close();
}
@Override
public FSDataInputStream open(Path path, int bufferSize) throws IOException {
@@ -75,7 +83,7 @@ public class SeaweedFileSystem extends FileSystem {
try {
int seaweedBufferSize = this.getConf().getInt(FS_SEAWEED_BUFFER_SIZE, FS_SEAWEED_DEFAULT_BUFFER_SIZE);
FSInputStream inputStream = seaweedFileSystemStore.openFileForRead(path, statistics);
return new FSDataInputStream(new BufferedFSInputStream(inputStream, 4 * seaweedBufferSize));
return new FSDataInputStream(new BufferedByteBufferReadableInputStream(inputStream, 4 * seaweedBufferSize));
} catch (Exception ex) {
LOG.warn("open path: {} bufferSize:{}", path, bufferSize, ex);
return null;
@@ -91,7 +99,7 @@ public class SeaweedFileSystem extends FileSystem {
path = qualify(path);
try {
String replicaPlacement = String.format("%03d", replication - 1);
String replicaPlacement = this.getConf().get(FS_SEAWEED_REPLICATION, String.format("%03d", replication - 1));
int seaweedBufferSize = this.getConf().getInt(FS_SEAWEED_BUFFER_SIZE, FS_SEAWEED_DEFAULT_BUFFER_SIZE);
OutputStream outputStream = seaweedFileSystemStore.createFile(path, overwrite, permission, seaweedBufferSize, replicaPlacement);
return new FSDataOutputStream(outputStream, statistics);
@@ -18,8 +18,7 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import static seaweed.hdfs.SeaweedFileSystem.FS_SEAWEED_BUFFER_SIZE;
import static seaweed.hdfs.SeaweedFileSystem.FS_SEAWEED_DEFAULT_BUFFER_SIZE;
import static seaweed.hdfs.SeaweedFileSystem.*;
public class SeaweedFileSystemStore {
@@ -34,6 +33,21 @@ public class SeaweedFileSystemStore {
filerGrpcClient = new FilerGrpcClient(host, grpcPort);
filerClient = new FilerClient(filerGrpcClient);
this.conf = conf;
String volumeServerAccessMode = this.conf.get(FS_SEAWEED_VOLUME_SERVER_ACCESS, "direct");
if (volumeServerAccessMode.equals("publicUrl")) {
filerGrpcClient.setAccessVolumeServerByPublicUrl();
} else if (volumeServerAccessMode.equals("filerProxy")) {
filerGrpcClient.setAccessVolumeServerByFilerProxy();
}
}
public void close() {
try {
this.filerGrpcClient.shutdown();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public static String getParentDirectory(Path path) {
@@ -185,6 +199,7 @@ public class SeaweedFileSystemStore {
if (existingEntry != null) {
entry = FilerProto.Entry.newBuilder();
entry.mergeFrom(existingEntry);
entry.clearContent();
entry.getAttributesBuilder().setMtime(now);
LOG.debug("createFile merged entry path:{} entry:{} from:{}", path, entry, existingEntry);
writePosition = SeaweedRead.fileSize(existingEntry);
@@ -207,7 +222,7 @@ public class SeaweedFileSystemStore {
SeaweedWrite.writeMeta(filerGrpcClient, getParentDirectory(path), entry);
}
return new SeaweedOutputStream(filerGrpcClient, path, entry, writePosition, bufferSize, replication);
return new SeaweedHadoopOutputStream(filerGrpcClient, path.toString(), entry, writePosition, bufferSize, replication);
}
@@ -221,7 +236,7 @@ public class SeaweedFileSystemStore {
throw new FileNotFoundException("read non-exist file " + path);
}
return new SeaweedInputStream(filerGrpcClient,
return new SeaweedHadoopInputStream(filerGrpcClient,
statistics,
path.toUri().getPath(),
entry);
@@ -0,0 +1,150 @@
package seaweed.hdfs;
// based on org.apache.hadoop.fs.azurebfs.services.AbfsInputStream
import org.apache.hadoop.fs.ByteBufferReadable;
import org.apache.hadoop.fs.FSInputStream;
import org.apache.hadoop.fs.FileSystem.Statistics;
import seaweedfs.client.FilerGrpcClient;
import seaweedfs.client.FilerProto;
import seaweedfs.client.SeaweedInputStream;
import java.io.EOFException;
import java.io.IOException;
import java.nio.ByteBuffer;
public class SeaweedHadoopInputStream extends FSInputStream implements ByteBufferReadable {
private final SeaweedInputStream seaweedInputStream;
private final Statistics statistics;
public SeaweedHadoopInputStream(
final FilerGrpcClient filerGrpcClient,
final Statistics statistics,
final String path,
final FilerProto.Entry entry) throws IOException {
this.seaweedInputStream = new SeaweedInputStream(filerGrpcClient, path, entry);
this.statistics = statistics;
}
@Override
public int read() throws IOException {
return seaweedInputStream.read();
}
@Override
public int read(final byte[] b, final int off, final int len) throws IOException {
return seaweedInputStream.read(b, off, len);
}
// implement ByteBufferReadable
@Override
public synchronized int read(ByteBuffer buf) throws IOException {
int bytesRead = seaweedInputStream.read(buf);
if (bytesRead > 0) {
if (statistics != null) {
statistics.incrementBytesRead(bytesRead);
}
}
return bytesRead;
}
/**
* Seek to given position in stream.
*
* @param n position to seek to
* @throws IOException if there is an error
* @throws EOFException if attempting to seek past end of file
*/
@Override
public synchronized void seek(long n) throws IOException {
seaweedInputStream.seek(n);
}
@Override
public synchronized long skip(long n) throws IOException {
return seaweedInputStream.skip(n);
}
/**
* Return the size of the remaining available bytes
* if the size is less than or equal to {@link Integer#MAX_VALUE},
* otherwise, return {@link Integer#MAX_VALUE}.
* <p>
* This is to match the behavior of DFSInputStream.available(),
* which some clients may rely on (HBase write-ahead log reading in
* particular).
*/
@Override
public synchronized int available() throws IOException {
return seaweedInputStream.available();
}
/**
* Returns the length of the file that this stream refers to. Note that the length returned is the length
* as of the time the Stream was opened. Specifically, if there have been subsequent appends to the file,
* they wont be reflected in the returned length.
*
* @return length of the file.
* @throws IOException if the stream is closed
*/
public long length() throws IOException {
return seaweedInputStream.length();
}
/**
* Return the current offset from the start of the file
*
* @throws IOException throws {@link IOException} if there is an error
*/
@Override
public synchronized long getPos() throws IOException {
return seaweedInputStream.getPos();
}
/**
* Seeks a different copy of the data. Returns true if
* found a new source, false otherwise.
*
* @throws IOException throws {@link IOException} if there is an error
*/
@Override
public boolean seekToNewSource(long l) throws IOException {
return false;
}
@Override
public synchronized void close() throws IOException {
seaweedInputStream.close();
}
/**
* Not supported by this stream. Throws {@link UnsupportedOperationException}
*
* @param readlimit ignored
*/
@Override
public synchronized void mark(int readlimit) {
throw new UnsupportedOperationException("mark()/reset() not supported on this stream");
}
/**
* Not supported by this stream. Throws {@link UnsupportedOperationException}
*/
@Override
public synchronized void reset() throws IOException {
throw new UnsupportedOperationException("mark()/reset() not supported on this stream");
}
/**
* gets whether mark and reset are supported by {@code ADLFileInputStream}. Always returns false.
*
* @return always {@code false}
*/
@Override
public boolean markSupported() {
return false;
}
}
@@ -0,0 +1,64 @@
package seaweed.hdfs;
// adapted from org.apache.hadoop.fs.azurebfs.services.AbfsOutputStream
import org.apache.hadoop.fs.StreamCapabilities;
import org.apache.hadoop.fs.Syncable;
import seaweedfs.client.FilerGrpcClient;
import seaweedfs.client.FilerProto;
import seaweedfs.client.SeaweedOutputStream;
import java.io.IOException;
import java.util.Locale;
public class SeaweedHadoopOutputStream extends SeaweedOutputStream implements Syncable, StreamCapabilities {
public SeaweedHadoopOutputStream(FilerGrpcClient filerGrpcClient, final String path, FilerProto.Entry.Builder entry,
final long position, final int bufferSize, final String replication) {
super(filerGrpcClient, path, entry, position, bufferSize, replication);
}
/**
* Similar to posix fsync, flush out the data in client's user buffer
* all the way to the disk device (but the disk may have it in its cache).
*
* @throws IOException if error occurs
*/
@Override
public void hsync() throws IOException {
if (supportFlush) {
flushInternal();
}
}
/**
* Flush out the data in client's user buffer. After the return of
* this call, new readers will see the data.
*
* @throws IOException if any error occurs
*/
@Override
public void hflush() throws IOException {
if (supportFlush) {
flushInternal();
}
}
/**
* Query the stream for a specific capability.
*
* @param capability string to query the stream support for.
* @return true for hsync and hflush.
*/
@Override
public boolean hasCapability(String capability) {
switch (capability.toLowerCase(Locale.ENGLISH)) {
case StreamCapabilities.HSYNC:
case StreamCapabilities.HFLUSH:
return supportFlush;
default:
return false;
}
}
}
@@ -1,338 +0,0 @@
package seaweed.hdfs;
// adapted from org.apache.hadoop.fs.azurebfs.services.AbfsOutputStream
import com.google.common.base.Preconditions;
import org.apache.hadoop.fs.FSExceptionMessages;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.fs.StreamCapabilities;
import org.apache.hadoop.fs.Syncable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import seaweedfs.client.ByteBufferPool;
import seaweedfs.client.FilerGrpcClient;
import seaweedfs.client.FilerProto;
import seaweedfs.client.SeaweedWrite;
import java.io.IOException;
import java.io.InterruptedIOException;
import java.io.OutputStream;
import java.nio.ByteBuffer;
import java.util.Arrays;
import java.util.Locale;
import java.util.concurrent.*;
import static seaweed.hdfs.SeaweedFileSystemStore.getParentDirectory;
public class SeaweedOutputStream extends OutputStream implements Syncable, StreamCapabilities {
private static final Logger LOG = LoggerFactory.getLogger(SeaweedOutputStream.class);
private final FilerGrpcClient filerGrpcClient;
private final Path path;
private final int bufferSize;
private final int maxConcurrentRequestCount;
private final ThreadPoolExecutor threadExecutor;
private final ExecutorCompletionService<Void> completionService;
private final FilerProto.Entry.Builder entry;
private final boolean supportFlush = false; // true;
private final ConcurrentLinkedDeque<WriteOperation> writeOperations;
private long position;
private boolean closed;
private volatile IOException lastError;
private long lastFlushOffset;
private long lastTotalAppendOffset = 0;
private ByteBuffer buffer;
private long outputIndex;
private String replication = "000";
public SeaweedOutputStream(FilerGrpcClient filerGrpcClient, final Path path, FilerProto.Entry.Builder entry,
final long position, final int bufferSize, final String replication) {
this.filerGrpcClient = filerGrpcClient;
this.replication = replication;
this.path = path;
this.position = position;
this.closed = false;
this.lastError = null;
this.lastFlushOffset = 0;
this.bufferSize = bufferSize;
this.buffer = ByteBufferPool.request(bufferSize);
this.outputIndex = 0;
this.writeOperations = new ConcurrentLinkedDeque<>();
this.maxConcurrentRequestCount = Runtime.getRuntime().availableProcessors();
this.threadExecutor
= new ThreadPoolExecutor(maxConcurrentRequestCount,
maxConcurrentRequestCount,
120L,
TimeUnit.SECONDS,
new LinkedBlockingQueue<Runnable>());
this.completionService = new ExecutorCompletionService<>(this.threadExecutor);
this.entry = entry;
}
private synchronized void flushWrittenBytesToServiceInternal(final long offset) throws IOException {
try {
SeaweedWrite.writeMeta(filerGrpcClient, getParentDirectory(path), entry);
} catch (Exception ex) {
throw new IOException(ex);
}
this.lastFlushOffset = offset;
}
@Override
public void write(final int byteVal) throws IOException {
write(new byte[]{(byte) (byteVal & 0xFF)});
}
@Override
public synchronized void write(final byte[] data, final int off, final int length)
throws IOException {
maybeThrowLastError();
Preconditions.checkArgument(data != null, "null data");
if (off < 0 || length < 0 || length > data.length - off) {
throw new IndexOutOfBoundsException();
}
// System.out.println(path + " write [" + (outputIndex + off) + "," + ((outputIndex + off) + length) + ")");
int currentOffset = off;
int writableBytes = bufferSize - buffer.position();
int numberOfBytesToWrite = length;
while (numberOfBytesToWrite > 0) {
if (numberOfBytesToWrite < writableBytes) {
buffer.put(data, currentOffset, numberOfBytesToWrite);
outputIndex += numberOfBytesToWrite;
break;
}
// System.out.println(path + " [" + (outputIndex + currentOffset) + "," + ((outputIndex + currentOffset) + writableBytes) + ") " + buffer.capacity());
buffer.put(data, currentOffset, writableBytes);
outputIndex += writableBytes;
currentOffset += writableBytes;
writeCurrentBufferToService();
numberOfBytesToWrite = numberOfBytesToWrite - writableBytes;
writableBytes = bufferSize - buffer.position();
}
}
/**
* Flushes this output stream and forces any buffered output bytes to be
* written out. If any data remains in the payload it is committed to the
* service. Data is queued for writing and forced out to the service
* before the call returns.
*/
@Override
public void flush() throws IOException {
if (supportFlush) {
flushInternalAsync();
}
}
/**
* Similar to posix fsync, flush out the data in client's user buffer
* all the way to the disk device (but the disk may have it in its cache).
*
* @throws IOException if error occurs
*/
@Override
public void hsync() throws IOException {
if (supportFlush) {
flushInternal();
}
}
/**
* Flush out the data in client's user buffer. After the return of
* this call, new readers will see the data.
*
* @throws IOException if any error occurs
*/
@Override
public void hflush() throws IOException {
if (supportFlush) {
flushInternal();
}
}
/**
* Query the stream for a specific capability.
*
* @param capability string to query the stream support for.
* @return true for hsync and hflush.
*/
@Override
public boolean hasCapability(String capability) {
switch (capability.toLowerCase(Locale.ENGLISH)) {
case StreamCapabilities.HSYNC:
case StreamCapabilities.HFLUSH:
return supportFlush;
default:
return false;
}
}
/**
* Force all data in the output stream to be written to Azure storage.
* Wait to return until this is complete. Close the access to the stream and
* shutdown the upload thread pool.
* If the blob was created, its lease will be released.
* Any error encountered caught in threads and stored will be rethrown here
* after cleanup.
*/
@Override
public synchronized void close() throws IOException {
if (closed) {
return;
}
LOG.debug("close path: {}", path);
try {
flushInternal();
threadExecutor.shutdown();
} finally {
lastError = new IOException(FSExceptionMessages.STREAM_IS_CLOSED);
ByteBufferPool.release(buffer);
buffer = null;
outputIndex = 0;
closed = true;
writeOperations.clear();
if (!threadExecutor.isShutdown()) {
threadExecutor.shutdownNow();
}
}
}
private synchronized void writeCurrentBufferToService() throws IOException {
if (buffer.position() == 0) {
return;
}
position += submitWriteBufferToService(buffer, position);
buffer = ByteBufferPool.request(bufferSize);
}
private synchronized int submitWriteBufferToService(final ByteBuffer bufferToWrite, final long writePosition) throws IOException {
bufferToWrite.flip();
int bytesLength = bufferToWrite.limit() - bufferToWrite.position();
if (threadExecutor.getQueue().size() >= maxConcurrentRequestCount) {
waitForTaskToComplete();
}
final Future<Void> job = completionService.submit(() -> {
// System.out.println(path + " is going to save [" + (writePosition) + "," + ((writePosition) + bytesLength) + ")");
SeaweedWrite.writeData(entry, replication, filerGrpcClient, writePosition, bufferToWrite.array(), bufferToWrite.position(), bufferToWrite.limit());
// System.out.println(path + " saved [" + (writePosition) + "," + ((writePosition) + bytesLength) + ")");
ByteBufferPool.release(bufferToWrite);
return null;
});
writeOperations.add(new WriteOperation(job, writePosition, bytesLength));
// Try to shrink the queue
shrinkWriteOperationQueue();
return bytesLength;
}
private void waitForTaskToComplete() throws IOException {
boolean completed;
for (completed = false; completionService.poll() != null; completed = true) {
// keep polling until there is no data
}
if (!completed) {
try {
completionService.take();
} catch (InterruptedException e) {
lastError = (IOException) new InterruptedIOException(e.toString()).initCause(e);
throw lastError;
}
}
}
private void maybeThrowLastError() throws IOException {
if (lastError != null) {
throw lastError;
}
}
/**
* Try to remove the completed write operations from the beginning of write
* operation FIFO queue.
*/
private synchronized void shrinkWriteOperationQueue() throws IOException {
try {
while (writeOperations.peek() != null && writeOperations.peek().task.isDone()) {
writeOperations.peek().task.get();
lastTotalAppendOffset += writeOperations.peek().length;
writeOperations.remove();
}
} catch (Exception e) {
lastError = new IOException(e);
throw lastError;
}
}
private synchronized void flushInternal() throws IOException {
maybeThrowLastError();
writeCurrentBufferToService();
flushWrittenBytesToService();
}
private synchronized void flushInternalAsync() throws IOException {
maybeThrowLastError();
writeCurrentBufferToService();
flushWrittenBytesToServiceAsync();
}
private synchronized void flushWrittenBytesToService() throws IOException {
for (WriteOperation writeOperation : writeOperations) {
try {
writeOperation.task.get();
} catch (Exception ex) {
lastError = new IOException(ex);
throw lastError;
}
}
LOG.debug("flushWrittenBytesToService: {} position:{}", path, position);
flushWrittenBytesToServiceInternal(position);
}
private synchronized void flushWrittenBytesToServiceAsync() throws IOException {
shrinkWriteOperationQueue();
if (this.lastTotalAppendOffset > this.lastFlushOffset) {
this.flushWrittenBytesToServiceInternal(this.lastTotalAppendOffset);
}
}
private static class WriteOperation {
private final Future<Void> task;
private final long startOffset;
private final long length;
WriteOperation(final Future<Void> task, final long startOffset, final long length) {
Preconditions.checkNotNull(task, "task");
Preconditions.checkArgument(startOffset >= 0, "startOffset");
Preconditions.checkArgument(length >= 0, "length");
this.task = task;
this.startOffset = startOffset;
this.length = length;
}
}
}
+3 -3
View File
@@ -386,7 +386,7 @@
"steppedLine": false,
"targets": [
{
"expr": "rate(SeaweedFS_filer_request_total[1m]) * 5",
"expr": "rate(SeaweedFS_filer_request_total[1m])",
"format": "time_series",
"intervalFactor": 2,
"legendFormat": "{{type}}",
@@ -761,7 +761,7 @@
"steppedLine": false,
"targets": [
{
"expr": "rate(SeaweedFS_s3_request_total[1m]) * 5",
"expr": "rate(SeaweedFS_s3_request_total[1m])",
"format": "time_series",
"intervalFactor": 2,
"legendFormat": "{{type}}",
@@ -1853,4 +1853,4 @@
"timezone": "browser",
"title": "SeaweedFS",
"version": 2
}
}
+4 -4
View File
@@ -97,7 +97,7 @@
"steppedLine": false,
"targets": [
{
"expr": "sum(rate(SeaweedFS_s3_request_total{namespace=\"$namespace\",service=~\"$service-api\",type=~\"$method\"}[1m]) * 5) by (code)",
"expr": "sum(rate(SeaweedFS_s3_request_total{namespace=\"$namespace\",service=~\"$service-api\",type=~\"$method\"}[1m])) by (code)",
"format": "time_series",
"interval": "",
"intervalFactor": 2,
@@ -210,7 +210,7 @@
"steppedLine": false,
"targets": [
{
"expr": "sum(rate(SeaweedFS_s3_request_total{namespace=\"$namespace\",service=~\"$service-api\"}[1m]) * 5) by (type)",
"expr": "sum(rate(SeaweedFS_s3_request_total{namespace=\"$namespace\",service=~\"$service-api\"}[1m])) by (type)",
"format": "time_series",
"interval": "",
"intervalFactor": 2,
@@ -1014,7 +1014,7 @@
"steppedLine": false,
"targets": [
{
"expr": "rate(SeaweedFS_filer_request_total{namespace=\"$namespace\",service=~\"$service-api\"}[1m]) * 5",
"expr": "rate(SeaweedFS_filer_request_total{namespace=\"$namespace\",service=~\"$service-api\"}[1m])",
"format": "time_series",
"interval": "",
"intervalFactor": 2,
@@ -2359,4 +2359,4 @@
"timezone": "browser",
"title": "SeaweedFS",
"version": 2
}
}
@@ -168,7 +168,7 @@ func getVolumeFiles(v uint32, addr string) (map[types.NeedleId]needleState, int6
size: size,
}
}
if actual := offset.ToAcutalOffset(); actual > maxOffset {
if actual := offset.ToActualOffset(); actual > maxOffset {
maxOffset = actual
}
return nil
+3
View File
@@ -0,0 +1,3 @@
#!/bin/bash
hsbench -a accesstoken -s secret -z 4K -d 10 -t 10 -b 10 -u http://localhost:8333 -m "cxipgdx" -bp "hsbench-"
@@ -0,0 +1,54 @@
package main
import (
"flag"
"fmt"
"math/rand"
"os"
"time"
)
var (
minSize = flag.Int("minSize", 1024, "min file size")
maxSize = flag.Int("maxSize", 3*1024*1024, "max file size")
fileCount = flag.Int("n", 1, "number of files to write")
blockSize = flag.Int("blockSizeKB", 4, "write block size")
toDir = flag.String("dir", ".", "destination directory")
)
func check(e error) {
if e != nil {
panic(e)
}
}
func main() {
flag.Parse()
block := make([]byte, *blockSize*1024)
for i := 0; i < *fileCount; i++ {
f, err := os.Create(fmt.Sprintf("%s/file%05d", *toDir, i))
check(err)
fileSize := *minSize + rand.Intn(*maxSize-*minSize)
startTime := time.Now()
fmt.Printf("write %s %d bytes: ", f.Name(), fileSize)
for x := 0; x < fileSize; {
rand.Read(block)
_, err = f.Write(block)
check(err)
x += len(block)
}
err = f.Close()
check(err)
fmt.Printf("%.02f MB/sec\n", float64(fileSize)*float64(time.Second)/float64(time.Now().Sub(startTime)*1024*1024))
}
}
+5 -1
View File
@@ -20,7 +20,7 @@ debug_mount:
debug_server:
go build -gcflags="all=-N -l"
dlv --listen=:2345 --headless=true --api-version=2 --accept-multiclient exec weed -- server -dir=/Volumes/mobile_disk/99 -filer -volume.port=8343 -s3 -volume.max=0
dlv --listen=:2345 --headless=true --api-version=2 --accept-multiclient exec weed -- server -dir=/Volumes/mobile_disk/99 -filer -volume.port=8343 -s3 -volume.max=0 -master.volumeSizeLimitMB=1024 -volume.preStopSeconds=1
debug_volume:
go build -gcflags="all=-N -l"
@@ -29,3 +29,7 @@ debug_volume:
debug_webdav:
go build -gcflags="all=-N -l"
dlv --listen=:2345 --headless=true --api-version=2 --accept-multiclient exec weed -- -v=4 webdav
debug_s3:
go build -gcflags="all=-N -l"
dlv --listen=:2345 --headless=true --api-version=2 --accept-multiclient exec weed -- -v=4 s3
+2 -2
View File
@@ -112,7 +112,7 @@ func runBackup(cmd *Command, args []string) bool {
return true
}
}
v, err := storage.NewVolume(util.ResolvePath(*s.dir), *s.collection, vid, storage.NeedleMapInMemory, replication, ttl, 0, 0)
v, err := storage.NewVolume(util.ResolvePath(*s.dir), util.ResolvePath(*s.dir), *s.collection, vid, storage.NeedleMapInMemory, replication, ttl, 0, 0)
if err != nil {
fmt.Printf("Error creating or reading from volume %d: %v\n", vid, err)
return true
@@ -137,7 +137,7 @@ func runBackup(cmd *Command, args []string) bool {
// remove the old data
v.Destroy()
// recreate an empty volume
v, err = storage.NewVolume(util.ResolvePath(*s.dir), *s.collection, vid, storage.NeedleMapInMemory, replication, ttl, 0, 0)
v, err = storage.NewVolume(util.ResolvePath(*s.dir), util.ResolvePath(*s.dir), *s.collection, vid, storage.NeedleMapInMemory, replication, ttl, 0, 0)
if err != nil {
fmt.Printf("Error creating or reading from volume %d: %v\n", vid, err)
return true
+1 -1
View File
@@ -125,7 +125,7 @@ func runBenchmark(cmd *Command, args []string) bool {
defer pprof.StopCPUProfile()
}
b.masterClient = wdclient.NewMasterClient(b.grpcDialOption, "client", "", 0, strings.Split(*b.masters, ","))
b.masterClient = wdclient.NewMasterClient(b.grpcDialOption, "client", "", 0, "", strings.Split(*b.masters, ","))
go b.masterClient.KeepConnectedToMaster()
b.masterClient.WaitUntilConnected()
+2 -1
View File
@@ -15,6 +15,8 @@ var Commands = []*Command{
cmdDownload,
cmdExport,
cmdFiler,
cmdFilerCat,
cmdFilerMetaTail,
cmdFilerReplicate,
cmdFilerSynchronize,
cmdFix,
@@ -25,7 +27,6 @@ var Commands = []*Command{
cmdScaffold,
cmdServer,
cmdShell,
cmdWatch,
cmdUpload,
cmdVersion,
cmdVolume,
+1 -2
View File
@@ -41,8 +41,7 @@ func runCompact(cmd *Command, args []string) bool {
preallocate := *compactVolumePreallocate * (1 << 20)
vid := needle.VolumeId(*compactVolumeId)
v, err := storage.NewVolume(util.ResolvePath(*compactVolumePath), *compactVolumeCollection, vid,
storage.NeedleMapInMemory, nil, nil, preallocate, 0)
v, err := storage.NewVolume(util.ResolvePath(*compactVolumePath), util.ResolvePath(*compactVolumePath), *compactVolumeCollection, vid, storage.NeedleMapInMemory, nil, nil, preallocate, 0)
if err != nil {
glog.Fatalf("Load Volume [ERROR] %s\n", err)
}
+1 -1
View File
@@ -113,7 +113,7 @@ func (scanner *VolumeFileScanner4Export) VisitNeedle(n *needle.Needle, offset in
nv, ok := needleMap.Get(n.Id)
glog.V(3).Infof("key %d offset %d size %d disk_size %d compressed %v ok %v nv %+v",
n.Id, offset, n.Size, n.DiskSize(scanner.version), n.IsCompressed(), ok, nv)
if *showDeleted && n.Size > 0 || ok && nv.Size.IsValid() && nv.Offset.ToAcutalOffset() == offset {
if *showDeleted && n.Size > 0 || ok && nv.Size.IsValid() && nv.Offset.ToActualOffset() == offset {
if newerThanUnix >= 0 && n.HasLastModifiedDate() && n.LastModified < uint64(newerThanUnix) {
glog.V(3).Infof("Skipping this file, as it's old enough: LastModified %d vs %d",
n.LastModified, newerThanUnix)
+33 -11
View File
@@ -3,6 +3,7 @@ package command
import (
"fmt"
"net/http"
"os"
"strconv"
"strings"
"time"
@@ -19,9 +20,11 @@ import (
)
var (
f FilerOptions
filerStartS3 *bool
filerS3Options S3Options
f FilerOptions
filerStartS3 *bool
filerS3Options S3Options
filerStartWebDav *bool
filerWebDavOptions WebDavOption
)
type FilerOptions struct {
@@ -42,8 +45,7 @@ type FilerOptions struct {
cipher *bool
peers *string
metricsHttpPort *int
// default leveldb directory, used in "weed server" mode
saveToFilerLimit *int
defaultLevelDbDirectory *string
}
@@ -59,12 +61,14 @@ func init() {
f.disableDirListing = cmdFiler.Flag.Bool("disableDirListing", false, "turn off directory listing")
f.maxMB = cmdFiler.Flag.Int("maxMB", 32, "split files larger than the limit")
f.dirListingLimit = cmdFiler.Flag.Int("dirListLimit", 100000, "limit sub dir listing size")
f.dataCenter = cmdFiler.Flag.String("dataCenter", "", "prefer to write to volumes in this data center")
f.dataCenter = cmdFiler.Flag.String("dataCenter", "", "prefer to read and write to volumes in this data center")
f.rack = cmdFiler.Flag.String("rack", "", "prefer to write to volumes in this rack")
f.disableHttp = cmdFiler.Flag.Bool("disableHttp", false, "disable http request, only gRpc operations are allowed")
f.cipher = cmdFiler.Flag.Bool("encryptVolumeData", false, "encrypt data on volume servers")
f.peers = cmdFiler.Flag.String("peers", "", "all filers sharing the same filer store in comma separated ip:port list")
f.metricsHttpPort = cmdFiler.Flag.Int("metricsPort", 0, "Prometheus metrics listen port")
f.saveToFilerLimit = cmdFiler.Flag.Int("saveToFilerLimit", 0, "files smaller than this limit will be saved in filer store")
f.defaultLevelDbDirectory = cmdFiler.Flag.String("defaultStoreDir", ".", "if filer.toml is empty, use an embedded filer store in the directory")
// start s3 on filer
filerStartS3 = cmdFiler.Flag.Bool("s3", false, "whether to start S3 gateway")
@@ -73,6 +77,16 @@ func init() {
filerS3Options.tlsPrivateKey = cmdFiler.Flag.String("s3.key.file", "", "path to the TLS private key file")
filerS3Options.tlsCertificate = cmdFiler.Flag.String("s3.cert.file", "", "path to the TLS certificate file")
filerS3Options.config = cmdFiler.Flag.String("s3.config", "", "path to the config file")
filerS3Options.allowEmptyFolder = cmdFiler.Flag.Bool("s3.allowEmptyFolder", false, "allow empty folders")
// start webdav on filer
filerStartWebDav = cmdFiler.Flag.Bool("webdav", false, "whether to start webdav gateway")
filerWebDavOptions.port = cmdFiler.Flag.Int("webdav.port", 7333, "webdav server http listen port")
filerWebDavOptions.collection = cmdFiler.Flag.String("webdav.collection", "", "collection to create the files")
filerWebDavOptions.tlsPrivateKey = cmdFiler.Flag.String("webdav.key.file", "", "path to the TLS private key file")
filerWebDavOptions.tlsCertificate = cmdFiler.Flag.String("webdav.cert.file", "", "path to the TLS certificate file")
filerWebDavOptions.cacheDir = cmdFiler.Flag.String("webdav.cacheDir", os.TempDir(), "local cache directory for file chunks")
filerWebDavOptions.cacheSizeMB = cmdFiler.Flag.Int64("webdav.cacheCapacityMB", 1000, "local cache capacity in MB")
}
var cmdFiler = &Command{
@@ -89,7 +103,8 @@ var cmdFiler = &Command{
//return a json format subdirectory and files listing
GET /path/to/
The configuration file "filer.toml" is read from ".", "$HOME/.seaweedfs/", or "/etc/seaweedfs/", in that order.
The configuration file "filer.toml" is read from ".", "$HOME/.seaweedfs/", "/usr/local/etc/seaweedfs/", or "/etc/seaweedfs/", in that order.
If the "filer.toml" is not found, an embedded filer store will be craeted under "-defaultStoreDir".
The example filer.toml configuration file can be generated by "weed scaffold -config=filer"
@@ -111,6 +126,15 @@ func runFiler(cmd *Command, args []string) bool {
}()
}
if *filerStartWebDav {
filerAddress := fmt.Sprintf("%s:%d", *f.ip, *f.port)
filerWebDavOptions.filer = &filerAddress
go func() {
time.Sleep(2 * time.Second)
filerWebDavOptions.startWebDav()
}()
}
f.startFiler()
return true
@@ -125,10 +149,7 @@ func (fo *FilerOptions) startFiler() {
publicVolumeMux = http.NewServeMux()
}
defaultLevelDbDirectory := "./filerldb2"
if fo.defaultLevelDbDirectory != nil {
defaultLevelDbDirectory = util.ResolvePath(*fo.defaultLevelDbDirectory + "/filerldb2")
}
defaultLevelDbDirectory := util.ResolvePath(*fo.defaultLevelDbDirectory + "/filerldb2")
var peers []string
if *fo.peers != "" {
@@ -149,6 +170,7 @@ func (fo *FilerOptions) startFiler() {
Host: *fo.ip,
Port: uint32(*fo.port),
Cipher: *fo.cipher,
SaveToFilerLimit: *fo.saveToFilerLimit,
Filers: peers,
})
if nfs_err != nil {
+118
View File
@@ -0,0 +1,118 @@
package command
import (
"context"
"fmt"
"github.com/chrislusf/seaweedfs/weed/filer"
"github.com/chrislusf/seaweedfs/weed/pb"
"github.com/chrislusf/seaweedfs/weed/pb/filer_pb"
"github.com/chrislusf/seaweedfs/weed/wdclient"
"google.golang.org/grpc"
"math"
"net/url"
"os"
"strings"
"github.com/chrislusf/seaweedfs/weed/security"
"github.com/chrislusf/seaweedfs/weed/util"
)
var (
filerCat FilerCatOptions
)
type FilerCatOptions struct {
grpcDialOption grpc.DialOption
filerAddress string
filerClient filer_pb.SeaweedFilerClient
output *string
}
func (fco *FilerCatOptions) GetLookupFileIdFunction() wdclient.LookupFileIdFunctionType {
return func(fileId string) (targetUrls []string, err error) {
vid := filer.VolumeId(fileId)
resp, err := fco.filerClient.LookupVolume(context.Background(), &filer_pb.LookupVolumeRequest{
VolumeIds: []string{vid},
})
if err != nil {
return nil, err
}
locations := resp.LocationsMap[vid]
for _, loc := range locations.Locations {
targetUrls = append(targetUrls, fmt.Sprintf("http://%s/%s", loc.Url, fileId))
}
return
}
}
func init() {
cmdFilerCat.Run = runFilerCat // break init cycle
filerCat.output = cmdFilerCat.Flag.String("o", "", "write to file instead of stdout")
}
var cmdFilerCat = &Command{
UsageLine: "filer.cat [-o <file>] http://localhost:8888/path/to/file",
Short: "copy one file to local",
Long: `read one file to stdout or write to a file
`,
}
func runFilerCat(cmd *Command, args []string) bool {
util.LoadConfiguration("security", false)
if len(args) == 0 {
return false
}
filerSource := args[len(args)-1]
filerUrl, err := url.Parse(filerSource)
if err != nil {
fmt.Printf("The last argument should be a URL on filer: %v\n", err)
return false
}
urlPath := filerUrl.Path
if strings.HasSuffix(urlPath, "/") {
fmt.Printf("The last argument should be a file: %v\n", err)
return false
}
filerCat.filerAddress = filerUrl.Host
filerCat.grpcDialOption = security.LoadClientTLS(util.GetViper(), "grpc.client")
dir, name := util.FullPath(urlPath).DirAndName()
writer := os.Stdout
if *filerCat.output != "" {
fmt.Printf("saving %s to %s\n", filerSource, *filerCat.output)
f, err := os.OpenFile(*filerCat.output, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0755)
if err != nil {
fmt.Printf("open file %s: %v\n", *filerCat.output, err)
return false
}
defer f.Close()
writer = f
}
pb.WithFilerClient(filerCat.filerAddress, filerCat.grpcDialOption, func(client filer_pb.SeaweedFilerClient) error {
request := &filer_pb.LookupDirectoryEntryRequest{
Name: name,
Directory: dir,
}
respLookupEntry, err := filer_pb.LookupEntry(client, request)
if err != nil {
return err
}
filerCat.filerClient = client
return filer.StreamContent(&filerCat, writer, respLookupEntry.Entry.Chunks, 0, math.MaxInt64)
})
return true
}
+7 -7
View File
@@ -92,7 +92,7 @@ func runCopy(cmd *Command, args []string) bool {
}
urlPath := filerUrl.Path
if !strings.HasSuffix(urlPath, "/") {
fmt.Printf("The last argument should be a folder and end with \"/\": %v\n", err)
fmt.Printf("The last argument should be a folder and end with \"/\"\n")
return false
}
@@ -116,13 +116,13 @@ func runCopy(cmd *Command, args []string) bool {
fmt.Printf("read from filer %s: %v\n", filerGrpcAddress, err)
return false
}
if strings.HasPrefix(urlPath, dirBuckets) {
if strings.HasPrefix(urlPath, dirBuckets+"/") {
restPath := urlPath[len(dirBuckets)+1:]
if strings.Index(restPath, "/") > 0 {
expectedBucket := restPath[:strings.Index(restPath, "/")]
if *copy.collection == "" {
*copy.collection = expectedBucket
} else {
} else if *copy.collection != expectedBucket {
fmt.Printf("destination %s uses collection \"%s\": unexpected collection \"%v\"\n", urlPath, expectedBucket, *copy.collection)
return true
}
@@ -157,7 +157,7 @@ func runCopy(cmd *Command, args []string) bool {
defer close(fileCopyTaskChan)
for _, fileOrDir := range fileOrDirs {
if err := genFileCopyTask(fileOrDir, urlPath, fileCopyTaskChan); err != nil {
fmt.Fprintf(os.Stderr, "gen file list error: %v\n", err)
fmt.Fprintf(os.Stderr, "genFileCopyTask : %v\n", err)
break
}
}
@@ -200,7 +200,7 @@ func genFileCopyTask(fileOrDir string, destPath string, fileCopyTaskChan chan Fi
fi, err := os.Stat(fileOrDir)
if err != nil {
fmt.Fprintf(os.Stderr, "Failed to get stat for file %s: %v\n", fileOrDir, err)
fmt.Fprintf(os.Stderr, "Error: read file %s: %v\n", fileOrDir, err)
return nil
}
@@ -311,7 +311,7 @@ func (worker *FileCopyWorker) uploadFileAsOne(task FileCopyTask, f *os.File) err
Replication: *worker.options.replication,
Collection: *worker.options.collection,
TtlSec: worker.options.ttlSec,
ParentPath: task.destinationUrlPath,
Path: task.destinationUrlPath,
}
assignResult, assignError = client.AssignVolume(context.Background(), request)
@@ -405,7 +405,7 @@ func (worker *FileCopyWorker) uploadFileInChunks(task FileCopyTask, f *os.File,
Replication: *worker.options.replication,
Collection: *worker.options.collection,
TtlSec: worker.options.ttlSec,
ParentPath: task.destinationUrlPath,
Path: task.destinationUrlPath + fileName,
}
assignResult, assignError = client.AssignVolume(context.Background(), request)
+211
View File
@@ -0,0 +1,211 @@
package command
import (
"context"
"fmt"
"github.com/golang/protobuf/jsonpb"
jsoniter "github.com/json-iterator/go"
"github.com/olivere/elastic/v7"
"io"
"os"
"path/filepath"
"strings"
"time"
"github.com/chrislusf/seaweedfs/weed/pb"
"github.com/chrislusf/seaweedfs/weed/pb/filer_pb"
"github.com/chrislusf/seaweedfs/weed/security"
"github.com/chrislusf/seaweedfs/weed/util"
)
func init() {
cmdFilerMetaTail.Run = runFilerMetaTail // break init cycle
}
var cmdFilerMetaTail = &Command{
UsageLine: "filer.meta.tail [-filer=localhost:8888] [-target=/]",
Short: "see recent changes on a filer",
Long: `See recent changes on a filer.
weed filer.meta.tail -timeAgo=30h | grep truncate
weed filer.meta.tail -timeAgo=30h | jq .
weed filer.meta.tail -timeAgo=30h | jq .eventNotification.newEntry.name
`,
}
var (
tailFiler = cmdFilerMetaTail.Flag.String("filer", "localhost:8888", "filer hostname:port")
tailTarget = cmdFilerMetaTail.Flag.String("pathPrefix", "/", "path to a folder or file, or common prefix for the folders or files on filer")
tailStart = cmdFilerMetaTail.Flag.Duration("timeAgo", 0, "start time before now. \"300ms\", \"1.5h\" or \"2h45m\". Valid time units are \"ns\", \"us\" (or \"µs\"), \"ms\", \"s\", \"m\", \"h\"")
tailPattern = cmdFilerMetaTail.Flag.String("pattern", "", "full path or just filename pattern, ex: \"/home/?opher\", \"*.pdf\", see https://golang.org/pkg/path/filepath/#Match ")
esServers = cmdFilerMetaTail.Flag.String("es", "", "comma-separated elastic servers http://<host:port>")
esIndex = cmdFilerMetaTail.Flag.String("es.index", "seaweedfs", "ES index name")
)
func runFilerMetaTail(cmd *Command, args []string) bool {
grpcDialOption := security.LoadClientTLS(util.GetViper(), "grpc.client")
var filterFunc func(dir, fname string) bool
if *tailPattern != "" {
if strings.Contains(*tailPattern, "/") {
println("watch path pattern", *tailPattern)
filterFunc = func(dir, fname string) bool {
matched, err := filepath.Match(*tailPattern, dir+"/"+fname)
if err != nil {
fmt.Printf("error: %v", err)
}
return matched
}
} else {
println("watch file pattern", *tailPattern)
filterFunc = func(dir, fname string) bool {
matched, err := filepath.Match(*tailPattern, fname)
if err != nil {
fmt.Printf("error: %v", err)
}
return matched
}
}
}
shouldPrint := func(resp *filer_pb.SubscribeMetadataResponse) bool {
if filterFunc == nil {
return true
}
if resp.EventNotification.OldEntry == nil && resp.EventNotification.NewEntry == nil {
return false
}
if resp.EventNotification.OldEntry != nil && filterFunc(resp.Directory, resp.EventNotification.OldEntry.Name) {
return true
}
if resp.EventNotification.NewEntry != nil && filterFunc(resp.EventNotification.NewParentPath, resp.EventNotification.NewEntry.Name) {
return true
}
return false
}
jsonpbMarshaler := jsonpb.Marshaler{
EmitDefaults: false,
}
eachEntryFunc := func(resp *filer_pb.SubscribeMetadataResponse) error {
jsonpbMarshaler.Marshal(os.Stdout, resp)
fmt.Fprintln(os.Stdout)
return nil
}
if *esServers != "" {
var err error
eachEntryFunc, err = sendToElasticSearchFunc(*esServers, *esIndex)
if err != nil {
fmt.Printf("create elastic search client to %s: %+v\n", *esServers, err)
return false
}
}
tailErr := pb.WithFilerClient(*tailFiler, grpcDialOption, func(client filer_pb.SeaweedFilerClient) error {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
stream, err := client.SubscribeMetadata(ctx, &filer_pb.SubscribeMetadataRequest{
ClientName: "tail",
PathPrefix: *tailTarget,
SinceNs: time.Now().Add(-*tailStart).UnixNano(),
})
if err != nil {
return fmt.Errorf("listen: %v", err)
}
for {
resp, listenErr := stream.Recv()
if listenErr == io.EOF {
return nil
}
if listenErr != nil {
return listenErr
}
if !shouldPrint(resp) {
continue
}
if err = eachEntryFunc(resp); err != nil {
return err
}
}
})
if tailErr != nil {
fmt.Printf("tail %s: %v\n", *tailFiler, tailErr)
}
return true
}
type EsDocument struct {
Dir string `json:"dir,omitempty"`
Name string `json:"name,omitempty"`
IsDirectory bool `json:"isDir,omitempty"`
Size uint64 `json:"size,omitempty"`
Uid uint32 `json:"uid,omitempty"`
Gid uint32 `json:"gid,omitempty"`
UserName string `json:"userName,omitempty"`
Collection string `json:"collection,omitempty"`
Crtime int64 `json:"crtime,omitempty"`
Mtime int64 `json:"mtime,omitempty"`
Mime string `json:"mime,omitempty"`
}
func toEsEntry(event *filer_pb.EventNotification) (*EsDocument, string) {
entry := event.NewEntry
dir, name := event.NewParentPath, entry.Name
id := util.Md5String([]byte(util.NewFullPath(dir, name)))
esEntry := &EsDocument{
Dir: dir,
Name: name,
IsDirectory: entry.IsDirectory,
Size: entry.Attributes.FileSize,
Uid: entry.Attributes.Uid,
Gid: entry.Attributes.Gid,
UserName: entry.Attributes.UserName,
Collection: entry.Attributes.Collection,
Crtime: entry.Attributes.Crtime,
Mtime: entry.Attributes.Mtime,
Mime: entry.Attributes.Mime,
}
return esEntry, id
}
func sendToElasticSearchFunc(servers string, esIndex string) (func(resp *filer_pb.SubscribeMetadataResponse) error, error) {
options := []elastic.ClientOptionFunc{}
options = append(options, elastic.SetURL(strings.Split(servers, ",")...))
options = append(options, elastic.SetSniff(false))
options = append(options, elastic.SetHealthcheck(false))
client, err := elastic.NewClient(options...)
if err != nil {
return nil, err
}
return func(resp *filer_pb.SubscribeMetadataResponse) error {
event := resp.EventNotification
if event.OldEntry != nil &&
(event.NewEntry == nil || resp.Directory != event.NewParentPath || event.OldEntry.Name != event.NewEntry.Name) {
// delete or not update the same file
dir, name := resp.Directory, event.OldEntry.Name
id := util.Md5String([]byte(util.NewFullPath(dir, name)))
println("delete", id)
_, err := client.Delete().Index(esIndex).Id(id).Do(context.Background())
return err
}
if event.NewEntry != nil {
// add a new file or update the same file
esEntry, id := toEsEntry(event)
value, err := jsoniter.Marshal(esEntry)
if err != nil {
return err
}
println(string(value))
_, err = client.Index().Index(esIndex).Id(id).BodyJson(string(value)).Do(context.Background())
return err
}
return nil
}, nil
}
+15 -3
View File
@@ -11,10 +11,10 @@ import (
_ "github.com/chrislusf/seaweedfs/weed/replication/sink/b2sink"
_ "github.com/chrislusf/seaweedfs/weed/replication/sink/filersink"
_ "github.com/chrislusf/seaweedfs/weed/replication/sink/gcssink"
_ "github.com/chrislusf/seaweedfs/weed/replication/sink/localsink"
_ "github.com/chrislusf/seaweedfs/weed/replication/sink/s3sink"
"github.com/chrislusf/seaweedfs/weed/replication/sub"
"github.com/chrislusf/seaweedfs/weed/util"
"github.com/spf13/viper"
)
func init() {
@@ -98,13 +98,19 @@ func runFilerReplicate(cmd *Command, args []string) bool {
replicator := replication.NewReplicator(config, "source.filer.", dataSink)
for {
key, m, err := notificationInput.ReceiveMessage()
key, m, onSuccessFn, onFailureFn, err := notificationInput.ReceiveMessage()
if err != nil {
glog.Errorf("receive %s: %+v", key, err)
if onFailureFn != nil {
onFailureFn()
}
continue
}
if key == "" {
// long poll received no messages
if onSuccessFn != nil {
onSuccessFn()
}
continue
}
if m.OldEntry != nil && m.NewEntry == nil {
@@ -116,14 +122,20 @@ func runFilerReplicate(cmd *Command, args []string) bool {
}
if err = replicator.Replicate(context.Background(), key, m); err != nil {
glog.Errorf("replicate %s: %+v", key, err)
if onFailureFn != nil {
onFailureFn()
}
} else {
glog.V(1).Infof("replicated %s", key)
if onSuccessFn != nil {
onSuccessFn()
}
}
}
}
func validateOneEnabledInput(config *viper.Viper) {
func validateOneEnabledInput(config *util.ViperProxy) {
enabledInput := ""
for _, input := range sub.NotificationInputs {
if config.GetBool("notification." + input.GetName() + ".enabled") {
+17 -11
View File
@@ -33,6 +33,8 @@ type SyncOptions struct {
bTtlSec *int
aDebug *bool
bDebug *bool
aProxyByFiler *bool
bProxyByFiler *bool
}
var (
@@ -43,7 +45,7 @@ var (
func init() {
cmdFilerSynchronize.Run = runFilerSynchronize // break init cycle
syncOptions.isActivePassive = cmdFilerSynchronize.Flag.Bool("isActivePassive", false, "one directional follow if true")
syncOptions.isActivePassive = cmdFilerSynchronize.Flag.Bool("isActivePassive", false, "one directional follow from A to B if true")
syncOptions.filerA = cmdFilerSynchronize.Flag.String("a", "", "filer A in one SeaweedFS cluster")
syncOptions.filerB = cmdFilerSynchronize.Flag.String("b", "", "filer B in the other SeaweedFS cluster")
syncOptions.aPath = cmdFilerSynchronize.Flag.String("a.path", "/", "directory to sync on filer A")
@@ -54,6 +56,8 @@ func init() {
syncOptions.bCollection = cmdFilerSynchronize.Flag.String("b.collection", "", "collection on filer B")
syncOptions.aTtlSec = cmdFilerSynchronize.Flag.Int("a.ttlSec", 0, "ttl in seconds on filer A")
syncOptions.bTtlSec = cmdFilerSynchronize.Flag.Int("b.ttlSec", 0, "ttl in seconds on filer B")
syncOptions.aProxyByFiler = cmdFilerSynchronize.Flag.Bool("a.filerProxy", false, "read and write file chunks by filer A instead of volume servers")
syncOptions.bProxyByFiler = cmdFilerSynchronize.Flag.Bool("b.filerProxy", false, "read and write file chunks by filer B instead of volume servers")
syncOptions.aDebug = cmdFilerSynchronize.Flag.Bool("a.debug", false, "debug mode to print out filer A received files")
syncOptions.bDebug = cmdFilerSynchronize.Flag.Bool("b.debug", false, "debug mode to print out filer B received files")
syncCpuProfile = cmdFilerSynchronize.Flag.String("cpuprofile", "", "cpu profile output file")
@@ -62,8 +66,8 @@ func init() {
var cmdFilerSynchronize = &Command{
UsageLine: "filer.sync -a=<oneFilerHost>:<oneFilerPort> -b=<otherFilerHost>:<otherFilerPort>",
Short: "continuously synchronize between two active-active or active-passive SeaweedFS clusters",
Long: `continuously synchronize file changes between two active-active or active-passive filers
Short: "resumeable continuous synchronization between two active-active or active-passive SeaweedFS clusters",
Long: `resumeable continuous synchronization for file changes between two active-active or active-passive filers
filer.sync listens on filer notifications. If any file is updated, it will fetch the updated content,
and write to the other destination. Different from filer.replicate:
@@ -86,8 +90,9 @@ func runFilerSynchronize(cmd *Command, args []string) bool {
go func() {
for {
err := doSubscribeFilerMetaChanges(grpcDialOption, *syncOptions.filerA, *syncOptions.aPath, *syncOptions.filerB,
*syncOptions.bPath, *syncOptions.bReplication, *syncOptions.bCollection, *syncOptions.bTtlSec, *syncOptions.bDebug)
err := doSubscribeFilerMetaChanges(grpcDialOption, *syncOptions.filerA, *syncOptions.aPath, *syncOptions.aProxyByFiler,
*syncOptions.filerB, *syncOptions.bPath, *syncOptions.bReplication, *syncOptions.bCollection, *syncOptions.bTtlSec, *syncOptions.bProxyByFiler,
*syncOptions.bDebug)
if err != nil {
glog.Errorf("sync from %s to %s: %v", *syncOptions.filerA, *syncOptions.filerB, err)
time.Sleep(1747 * time.Millisecond)
@@ -98,8 +103,9 @@ func runFilerSynchronize(cmd *Command, args []string) bool {
if !*syncOptions.isActivePassive {
go func() {
for {
err := doSubscribeFilerMetaChanges(grpcDialOption, *syncOptions.filerB, *syncOptions.bPath, *syncOptions.filerA,
*syncOptions.aPath, *syncOptions.aReplication, *syncOptions.aCollection, *syncOptions.aTtlSec, *syncOptions.aDebug)
err := doSubscribeFilerMetaChanges(grpcDialOption, *syncOptions.filerB, *syncOptions.bPath, *syncOptions.bProxyByFiler,
*syncOptions.filerA, *syncOptions.aPath, *syncOptions.aReplication, *syncOptions.aCollection, *syncOptions.aTtlSec, *syncOptions.aProxyByFiler,
*syncOptions.aDebug)
if err != nil {
glog.Errorf("sync from %s to %s: %v", *syncOptions.filerB, *syncOptions.filerA, err)
time.Sleep(2147 * time.Millisecond)
@@ -113,8 +119,8 @@ func runFilerSynchronize(cmd *Command, args []string) bool {
return true
}
func doSubscribeFilerMetaChanges(grpcDialOption grpc.DialOption, sourceFiler, sourcePath, targetFiler, targetPath string,
replicationStr, collection string, ttlSec int, debug bool) error {
func doSubscribeFilerMetaChanges(grpcDialOption grpc.DialOption, sourceFiler, sourcePath string, sourceReadChunkFromFiler bool, targetFiler, targetPath string,
replicationStr, collection string, ttlSec int, sinkWriteChunkByFiler, debug bool) error {
// read source filer signature
sourceFilerSignature, sourceErr := replication.ReadFilerSignature(grpcDialOption, sourceFiler)
@@ -138,9 +144,9 @@ func doSubscribeFilerMetaChanges(grpcDialOption grpc.DialOption, sourceFiler, so
// create filer sink
filerSource := &source.FilerSource{}
filerSource.DoInitialize(pb.ServerToGrpcAddress(sourceFiler), sourcePath)
filerSource.DoInitialize(sourceFiler, pb.ServerToGrpcAddress(sourceFiler), sourcePath, sourceReadChunkFromFiler)
filerSink := &filersink.FilerSink{}
filerSink.DoInitialize(pb.ServerToGrpcAddress(targetFiler), targetPath, replicationStr, collection, ttlSec, grpcDialOption)
filerSink.DoInitialize(targetFiler, pb.ServerToGrpcAddress(targetFiler), targetPath, replicationStr, collection, ttlSec, grpcDialOption, sinkWriteChunkByFiler)
filerSink.SetSourceFiler(filerSource)
processEventFn := func(resp *filer_pb.SubscribeMetadataResponse) error {
+1 -1
View File
@@ -69,7 +69,7 @@ var cmdMaster = &Command{
Short: "start a master server",
Long: `start a master server to provide volume=>location mapping service and sequence number of file ids
The configuration file "security.toml" is read from ".", "$HOME/.seaweedfs/", or "/etc/seaweedfs/", in that order.
The configuration file "security.toml" is read from ".", "$HOME/.seaweedfs/", "/usr/local/etc/seaweedfs/", or "/etc/seaweedfs/", in that order.
The example security.toml configuration file can be generated by "weed scaffold -config=security"
+20 -18
View File
@@ -6,23 +6,24 @@ import (
)
type MountOptions struct {
filer *string
filerMountRootPath *string
dir *string
dirAutoCreate *bool
collection *string
replication *string
ttlSec *int
chunkSizeLimitMB *int
cacheDir *string
cacheSizeMB *int64
dataCenter *string
allowOthers *bool
umaskString *string
nonempty *bool
outsideContainerClusterMode *bool
uidMap *string
gidMap *string
filer *string
filerMountRootPath *string
dir *string
dirAutoCreate *bool
collection *string
replication *string
ttlSec *int
chunkSizeLimitMB *int
concurrentWriters *int
cacheDir *string
cacheSizeMB *int64
dataCenter *string
allowOthers *bool
umaskString *string
nonempty *bool
volumeServerAccess *string
uidMap *string
gidMap *string
}
var (
@@ -42,13 +43,14 @@ func init() {
mountOptions.replication = cmdMount.Flag.String("replication", "", "replication(e.g. 000, 001) to create to files. If empty, let filer decide.")
mountOptions.ttlSec = cmdMount.Flag.Int("ttl", 0, "file ttl in seconds")
mountOptions.chunkSizeLimitMB = cmdMount.Flag.Int("chunkSizeLimitMB", 2, "local write buffer size, also chunk large files")
mountOptions.concurrentWriters = cmdMount.Flag.Int("concurrentWriters", 128, "limit concurrent goroutine writers if not 0")
mountOptions.cacheDir = cmdMount.Flag.String("cacheDir", os.TempDir(), "local cache directory for file chunks and meta data")
mountOptions.cacheSizeMB = cmdMount.Flag.Int64("cacheCapacityMB", 1000, "local file chunk cache capacity in MB (0 will disable cache)")
mountOptions.dataCenter = cmdMount.Flag.String("dataCenter", "", "prefer to write to the data center")
mountOptions.allowOthers = cmdMount.Flag.Bool("allowOthers", true, "allows other users to access the file system")
mountOptions.umaskString = cmdMount.Flag.String("umask", "022", "octal umask, e.g., 022, 0111")
mountOptions.nonempty = cmdMount.Flag.Bool("nonempty", false, "allows the mounting over a non-empty directory")
mountOptions.outsideContainerClusterMode = cmdMount.Flag.Bool("outsideContainerClusterMode", false, "allows other users to access volume servers with publicUrl")
mountOptions.volumeServerAccess = cmdMount.Flag.String("volumeServerAccess", "direct", "access volume servers by [direct|publicUrl|filerProxy]")
mountOptions.uidMap = cmdMount.Flag.String("map.uid", "", "map local uid to uid on filer, comma-separated <local_uid>:<filer_uid>")
mountOptions.gidMap = cmdMount.Flag.String("map.gid", "", "map local gid to gid on filer, comma-separated <local_gid>:<filer_gid>")
+34 -28
View File
@@ -5,8 +5,6 @@ package command
import (
"context"
"fmt"
"github.com/chrislusf/seaweedfs/weed/filer"
"github.com/chrislusf/seaweedfs/weed/filesys/meta_cache"
"os"
"os/user"
"path"
@@ -15,6 +13,8 @@ import (
"strings"
"time"
"github.com/chrislusf/seaweedfs/weed/filesys/meta_cache"
"github.com/seaweedfs/fuse"
"github.com/seaweedfs/fuse/fs"
@@ -33,7 +33,7 @@ func runMount(cmd *Command, args []string) bool {
if *mountReadRetryTime < time.Second {
*mountReadRetryTime = time.Second
}
filer.ReadWaitTime = *mountReadRetryTime
util.RetryWaitTime = *mountReadRetryTime
umask, umaskErr := strconv.ParseUint(*mountOptions.umaskString, 8, 64)
if umaskErr != nil {
@@ -58,6 +58,7 @@ func RunMount(option *MountOptions, umask os.FileMode) bool {
return true
}
util.LoadConfiguration("security", false)
// try to connect to filer, filerBucketsPath may be useful later
grpcDialOption := security.LoadClientTLS(util.GetViper(), "grpc.client")
var cipher bool
@@ -78,8 +79,6 @@ func RunMount(option *MountOptions, umask os.FileMode) bool {
dir := util.ResolvePath(*option.dir)
chunkSizeLimitMB := *mountOptions.chunkSizeLimitMB
util.LoadConfiguration("security", false)
fmt.Printf("This is SeaweedFS version %s %s %s\n", util.Version(), runtime.GOOS, runtime.GOARCH)
if dir == "" {
fmt.Printf("Please specify the mount directory via \"-dir\"")
@@ -101,9 +100,9 @@ func RunMount(option *MountOptions, umask os.FileMode) bool {
uid, gid := uint32(0), uint32(0)
mountMode := os.ModeDir | 0777
if err == nil {
mountMode = os.ModeDir | fileInfo.Mode()
mountMode = os.ModeDir | os.FileMode(0777)&^umask
uid, gid = util.GetFileUidGid(fileInfo)
fmt.Printf("mount point owner uid=%d gid=%d mode=%s\n", uid, gid, fileInfo.Mode())
fmt.Printf("mount point owner uid=%d gid=%d mode=%s\n", uid, gid, mountMode)
} else {
fmt.Printf("can not stat %s\n", dir)
return false
@@ -151,6 +150,8 @@ func RunMount(option *MountOptions, umask os.FileMode) bool {
fuse.MaxReadahead(1024 * 128),
fuse.AsyncRead(),
fuse.WritebackCache(),
fuse.MaxBackground(128),
fuse.CongestionThreshold(128),
}
options = append(options, osSpecificMountOptions()...)
@@ -168,26 +169,29 @@ func RunMount(option *MountOptions, umask os.FileMode) bool {
}
seaweedFileSystem := filesys.NewSeaweedFileSystem(&filesys.Option{
FilerGrpcAddress: filerGrpcAddress,
GrpcDialOption: grpcDialOption,
FilerMountRootPath: mountRoot,
Collection: *option.collection,
Replication: *option.replication,
TtlSec: int32(*option.ttlSec),
ChunkSizeLimit: int64(chunkSizeLimitMB) * 1024 * 1024,
CacheDir: *option.cacheDir,
CacheSizeMB: *option.cacheSizeMB,
DataCenter: *option.dataCenter,
EntryCacheTtl: 3 * time.Second,
MountUid: uid,
MountGid: gid,
MountMode: mountMode,
MountCtime: fileInfo.ModTime(),
MountMtime: time.Now(),
Umask: umask,
OutsideContainerClusterMode: *mountOptions.outsideContainerClusterMode,
Cipher: cipher,
UidGidMapper: uidGidMapper,
MountDirectory: dir,
FilerAddress: filer,
FilerGrpcAddress: filerGrpcAddress,
GrpcDialOption: grpcDialOption,
FilerMountRootPath: mountRoot,
Collection: *option.collection,
Replication: *option.replication,
TtlSec: int32(*option.ttlSec),
ChunkSizeLimit: int64(chunkSizeLimitMB) * 1024 * 1024,
ConcurrentWriters: *option.concurrentWriters,
CacheDir: *option.cacheDir,
CacheSizeMB: *option.cacheSizeMB,
DataCenter: *option.dataCenter,
EntryCacheTtl: 3 * time.Second,
MountUid: uid,
MountGid: gid,
MountMode: mountMode,
MountCtime: fileInfo.ModTime(),
MountMtime: time.Now(),
Umask: umask,
VolumeServerAccess: *mountOptions.volumeServerAccess,
Cipher: cipher,
UidGidMapper: uidGidMapper,
})
// mount
@@ -204,7 +208,9 @@ func RunMount(option *MountOptions, umask os.FileMode) bool {
})
glog.V(0).Infof("mounted %s%s to %s", filer, mountRoot, dir)
err = fs.Serve(c, seaweedFileSystem)
server := fs.New(c, nil)
seaweedFileSystem.Server = server
err = server.Serve(seaweedFileSystem)
// check if the mount process has an error to report
<-c.Ready
+10 -7
View File
@@ -23,13 +23,14 @@ var (
)
type S3Options struct {
filer *string
port *int
config *string
domainName *string
tlsPrivateKey *string
tlsCertificate *string
metricsHttpPort *int
filer *string
port *int
config *string
domainName *string
tlsPrivateKey *string
tlsCertificate *string
metricsHttpPort *int
allowEmptyFolder *bool
}
func init() {
@@ -41,6 +42,7 @@ func init() {
s3StandaloneOptions.tlsPrivateKey = cmdS3.Flag.String("key.file", "", "path to the TLS private key file")
s3StandaloneOptions.tlsCertificate = cmdS3.Flag.String("cert.file", "", "path to the TLS certificate file")
s3StandaloneOptions.metricsHttpPort = cmdS3.Flag.Int("metricsPort", 0, "Prometheus metrics listen port")
s3StandaloneOptions.allowEmptyFolder = cmdS3.Flag.Bool("allowEmptyFolder", false, "allow empty folders")
}
var cmdS3 = &Command{
@@ -181,6 +183,7 @@ func (s3opt *S3Options) startS3Server() bool {
DomainName: *s3opt.domainName,
BucketsPath: filerBucketsPath,
GrpcDialOption: grpcDialOption,
AllowEmptyFolder: *s3opt.allowEmptyFolder,
})
if s3ApiServer_err != nil {
glog.Fatalf("S3 API Server startup error: %v", s3ApiServer_err)

Some files were not shown because too many files have changed in this diff Show More