generated from gopherdojo/template
-
Notifications
You must be signed in to change notification settings - Fork 179
Kadai3 2 mizushima #68
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Closed
MizushimaToshihiko
wants to merge
51
commits into
gopherdojo:master
from
MizushimaToshihiko:kadai3-2-Mizushima
Closed
Changes from 47 commits
Commits
Show all changes
51 commits
Select commit
Hold shift + click to select a range
2ae7405
課題2を提出
MizushimaToshihiko 68c1603
mainのテストを追加
MizushimaToshihiko 1da407c
コマンドラインオプションの部分を訂正
MizushimaToshihiko 766b979
使い方の2を訂正
MizushimaToshihiko a56f694
go fmt適用
MizushimaToshihiko 1393b38
README.md それぞれのカバレッジが分かりやすくなるように修正
MizushimaToshihiko 054a7e2
kadai3-1 first commit
MizushimaToshihiko 0738582
とりあえずタイピングと正解判定できるように
MizushimaToshihiko 92b63c2
時間制限とgo.mod追加
MizushimaToshihiko bcd289c
単語をCSVから読み込むように変更
MizushimaToshihiko f52c186
モジュール分割
MizushimaToshihiko 0c04595
gigitignore,Makefile,typingのテストを追加,テスト追加に伴いtyping/typing.goとmain.go変更
MizushimaToshihiko f772cf5
README修正
MizushimaToshihiko 5117bb9
go fmt適用
MizushimaToshihiko a3f3694
READMEにディレクトリ構成を追加
MizushimaToshihiko bbe053d
課題2のコミットが残っていたので削除
MizushimaToshihiko 92dd1bc
kadai3-2 first commit
MizushimaToshihiko 9d475ed
オプション周りの修正及びダウンロードはできるように
MizushimaToshihiko c3b5dea
options/options.goのimport修正、TODOリスト追加
MizushimaToshihiko 274bae4
rangeリクエスト追加
MizushimaToshihiko 3dfddf9
requestの処理を変更、rootフォルダのgo.mod変更
MizushimaToshihiko a44ebff
ダウンロードの処理を追加、途中
MizushimaToshihiko d89f81d
並行ダウンロード処理他追加
MizushimaToshihiko 21f4b85
gitignore変更
MizushimaToshihiko 0bb34f4
kadai3-1が残っていたので削除
MizushimaToshihiko 1d024fc
エラー及びキャンセル後の処理の後片づけを修正
MizushimaToshihiko 0b0eb05
gitignore修正
MizushimaToshihiko b9d9b41
エラーやキャンセルで途中終了した時の処理を修正
MizushimaToshihiko 0ce8d21
go fmt適用、オプションの処理をmain関数に移行
MizushimaToshihiko 886a1a9
エラー処理忘れ修正、errors.Wrapをfmt.Errorfに変更
MizushimaToshihiko bcbfcb6
テスト追加
MizushimaToshihiko 91a0b2b
downloadのテスト追加
MizushimaToshihiko 7d03be4
download.goのテスト修正途中
MizushimaToshihiko a3c94f9
go fmt適用
MizushimaToshihiko 5a04cf2
ダウンロードのテスト追加、request.goのテスト追加(途中)
MizushimaToshihiko 14102f5
testの記述を変更
MizushimaToshihiko 1286949
getheader_test.goにt.Helper()追加、request_test.goのTest_Request関数の作成(途中)、…
MizushimaToshihiko 2d3a754
Test_Request関数のコメント追加
MizushimaToshihiko a31b2bf
README追加、不要なpackage等削除、testdateにフォルダ名変更、それに伴い各テスト関数の修正、Makefileのtest変更他
MizushimaToshihiko 92ba19d
README.md修正
MizushimaToshihiko 2922f3e
README.md修正
MizushimaToshihiko b36d85e
README.md修正
MizushimaToshihiko 648256b
README.md修正
MizushimaToshihiko 9a40d02
README.md修正
MizushimaToshihiko b2cfb3a
READEME.md修正、及びdownload.goのコメントのスペルミスを修正
MizushimaToshihiko 880f698
mainのテスト作成中
MizushimaToshihiko 1d54062
main_test.--------止
MizushimaToshihiko 83cb3ef
modified .gitignore
MizushimaToshihiko 3852a4a
modified main function in main.go
MizushimaToshihiko 8c15153
modified main function in main.go
MizushimaToshihiko 548c9aa
modified main.go and download/download.go
MizushimaToshihiko File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
bin |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
bin/* |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
BINARY_NAME := bin/paraDW | ||
GOCMD=go | ||
GOBUILD=$(GOCMD) build | ||
GOCLEAN=$(GOCMD) clean | ||
GOTEST=$(GOCMD) test | ||
GOGET=$(GOCMD) get | ||
GOFMT=$(GOCMD) fmt | ||
|
||
all: build test | ||
|
||
build: | ||
$(GOBUILD) -o $(BINARY_NAME) -v | ||
|
||
test: build | ||
cd download; $(GOTEST) -v -cover | ||
cd getheader; $(GOTEST) -v -cover | ||
cd listen; $(GOTEST) -v -cover | ||
cd request; $(GOTEST) -v -cover | ||
|
||
clean: | ||
$(GOCLEAN) | ||
|
||
format: | ||
$(GOFMT) ./... | ||
|
||
.PHONY: test clean format |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,83 @@ | ||
## 課題3-2 分割ダウンローダを作ろう | ||
- 分割ダウンロードを行う | ||
- Rangeアクセスを用いる | ||
- いくつかのゴルーチンでダウンロードしてマージする | ||
- エラー処理を工夫する | ||
- golang.org/x/sync/errgourpパッケージなどを使ってみる | ||
- キャンセルが発生した場合の実装を行う | ||
|
||
|
||
|
||
### コマンドラインオプション | ||
|
||
| ショートオプション | ロングオプション | 説明 | デフォルト | | ||
| --------- | --------- | --------- | --------- | | ||
| -h | --help | 使い方を表示して終了 | - | | ||
| -p \<num> | --procs \<num> | プロセス数を指定 | お使いのPCのコア数 | | ||
| -o \<path> | --output \<path> | ダウンロードしたファイルをどこのディレクトリに保存するか指定する | カレントディレクトリ | | ||
| -t \<num> | --timeout \<num> | サーバーへのリクエストを止める時間を秒数で指定 | 120 | | ||
|
||
|
||
### インストール方法 | ||
```bash | ||
go get github.com/MizushimaToshihiko/gopherdojo-studyroom/kadai3-2/Mizushima | ||
``` | ||
|
||
### 使い方 | ||
1. 実行ファイル作成 | ||
```bash | ||
$ make build | ||
``` | ||
2. URLを指定してダウンロード実行 | ||
```bash | ||
$ ./bin/paraDW [option] URL( URL URL ...) | ||
``` | ||
|
||
※ URLは複数指定できます | ||
※ ダウンロード先がRangeアクセスに対応していれば、go routineを使った並行ダウンロードを行い、そうでなければ1プロセスのダウンロードを行います | ||
|
||
### テストの方法 | ||
- バイナリビルド & テスト | ||
```bash | ||
$ make | ||
``` | ||
- テスト後の処理(掃除) | ||
```bash | ||
$ make clean | ||
``` | ||
|
||
### ディレクトリ構成 | ||
```bash | ||
. | ||
├── bin | ||
│ └── paraDW # "make build" command required. | ||
├── download | ||
│ ├── download.go | ||
│ ├── download_test.go | ||
│ ├── go.mod | ||
│ └── go.sum | ||
├── getheader | ||
│ ├── geHeader_test.go | ||
│ ├── getHeader.go | ||
│ └── go.mod | ||
├── .gitignore | ||
├── go.mod | ||
├── go.sum | ||
├── listen | ||
│ ├── listen.go | ||
│ └── listen_test.go | ||
├── main.go | ||
├── Makefile | ||
├── README.md | ||
├── request | ||
│ ├── go.mod | ||
│ ├── request.go | ||
│ └── request_test.go | ||
└── testdata | ||
├── 003 | ||
└── z4d4kWk.jpg | ||
``` | ||
|
||
### 参考にしたもの | ||
[pget](https://qiita.com/codehex/items/d0a500ac387d39a34401) (goroutineを使ったダウンロード処理、コマンドラインオプションの処理等々) | ||
https://github.com/gopherdojo/dojo3/pull/50 (ctrl+cを押したときのキャンセル処理など) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,157 @@ | ||
// download package implements parallel download and non-parallel | ||
// download. | ||
package download | ||
|
||
import ( | ||
"context" | ||
"fmt" | ||
"io" | ||
"io/ioutil" | ||
"net/url" | ||
"os" | ||
"strconv" | ||
|
||
"github.com/MizushimaToshihiko/gopherdojo-studyroom/kadai3-2/Mizushima/request" | ||
"golang.org/x/sync/errgroup" | ||
) | ||
|
||
//PDownloader is user-defined struct | ||
type PDownloader struct { | ||
url *url.URL // URL for the download | ||
output *os.File // Where to save the downloaded file | ||
fileSize uint // size of the downloaded file | ||
part uint // Number of divided bytes | ||
procs uint // Number of parallel download process | ||
} | ||
|
||
// newPDownloader is constructor for PDownloader. | ||
func newPDownloader(url *url.URL, output *os.File, fileSize uint, part uint, procs uint) *PDownloader { | ||
return &PDownloader{ | ||
url: url, | ||
output: output, | ||
fileSize: fileSize, | ||
part: part, | ||
procs: procs, | ||
} | ||
} | ||
|
||
// Downloader gets elements of PDownloader, the download is parallel or not, temprary | ||
// directory name and context.Context, and drives DownloadFile method if isPara is false | ||
// or PDownload if isPara is true. | ||
// | ||
func Downloader(url *url.URL, | ||
output *os.File, fileSize uint, part uint, procs uint, isPara bool, | ||
tmpDirName string, ctx context.Context) error { | ||
pd := newPDownloader(url, output, fileSize, part, procs) | ||
if !isPara { | ||
fmt.Printf("%s do not accept range access: downloading by single process\n", url) | ||
err := pd.DownloadFile(ctx) | ||
if err != nil { | ||
return err | ||
} | ||
} else { | ||
grp, ctx := errgroup.WithContext(ctx) | ||
if err := pd.PDownload(grp, tmpDirName, procs, ctx); err != nil { | ||
return err | ||
} | ||
|
||
if err := grp.Wait(); err != nil { | ||
return err | ||
} | ||
} | ||
return nil | ||
} | ||
|
||
// DownloadFile drives a non-parallel download | ||
func (pd *PDownloader) DownloadFile(ctx context.Context) (err error) { | ||
|
||
resp, err := request.Request(ctx, "GET", pd.url.String(), "", "") | ||
if err != nil { | ||
return | ||
} | ||
defer func() { | ||
err = resp.Body.Close() | ||
}() | ||
|
||
_, err = io.Copy(pd.output, resp.Body) | ||
if err != nil { | ||
return | ||
} | ||
|
||
return nil | ||
} | ||
|
||
// PDownload drives parallel download. downloaded file is in temporary | ||
// directory named tmpDirName. | ||
func (pd *PDownloader) PDownload(grp *errgroup.Group, | ||
tmpDirName string, procs uint, ctx context.Context) error { | ||
var start, end, idx uint | ||
|
||
for idx = uint(0); idx < procs; idx++ { | ||
if idx == 0 { | ||
start = 0 | ||
} else { | ||
start = idx*pd.part + 1 | ||
} | ||
|
||
// if idx is the end | ||
if idx == pd.procs-1 { | ||
end = pd.fileSize | ||
} else { | ||
end = (idx + 1) * pd.part | ||
} | ||
|
||
// idxを代入し直す | ||
// https://qiita.com/harhogefoo/items/7ccb4e353a4a01cfa773 | ||
idx := idx | ||
// fmt.Printf("start: %d, end: %d, pd.part: %d\n", start, end, pd.part) | ||
bytes := fmt.Sprintf("bytes=%d-%d", start, end) | ||
|
||
grp.Go(func() error { | ||
fmt.Printf("grp.Go: tmpDirName: %s, bytes %s, idx: %d\n", tmpDirName, bytes, idx) | ||
return pd.ReqToMakeCopy(tmpDirName, bytes, idx, ctx) | ||
}) | ||
} | ||
return nil | ||
} | ||
|
||
// ReqToMakeCopy sends a "GET" request with "Range" field with "bytes" range. | ||
// And gets response and make a copy to a temprary file in temprary directory from response body. | ||
// | ||
func (pd *PDownloader) ReqToMakeCopy(tmpDirName, bytes string, idx uint, ctx context.Context) (err error) { | ||
// fmt.Printf("ReqToMakeCopy: tmpDirName: %s, bytes %s, idx: %d\n", tmpDirName, bytes, idx) | ||
resp, err := request.Request(ctx, "GET", pd.url.String(), "Range", bytes) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
tmpOut, err := os.Create(tmpDirName + "/" + strconv.Itoa(int(idx))) | ||
if err != nil { | ||
return err | ||
} | ||
// fmt.Printf("tmpOut.Name(): %s\n", tmpOut.Name()) | ||
defer func() { | ||
err = tmpOut.Close() | ||
}() | ||
|
||
// b := make([]byte, 1000) | ||
// resp.Body.Read(b) | ||
// fmt.Printf("resp.body: %s\n", string(b)) | ||
|
||
body, err := ioutil.ReadAll(resp.Body) | ||
if err != nil { | ||
// fmt.Printf("err: %s\n", err) | ||
if err != io.EOF && err != io.ErrUnexpectedEOF { | ||
return err | ||
} | ||
} | ||
|
||
// fmt.Printf("response body: length: %d\n", len(body)) | ||
|
||
length, err := tmpOut.Write(body) | ||
if err != nil { | ||
return err | ||
} | ||
fmt.Printf("%d/%d was downloaded len=%d\n", idx, pd.procs, length) | ||
return nil | ||
} |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
細かい事ですが、コメントでPDownloaderはユーザ定義型としか言っていないので、他と見比べるとPDownloader自体の説明が入るのが適切なのではと思います。