generated from gopherdojo/template
-
Notifications
You must be signed in to change notification settings - Fork 179
Kadai3 2/yuonoda #22
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
Closed
Kadai3 2/yuonoda #22
Changes from 73 commits
Commits
Show all changes
94 commits
Select commit
Hold shift + click to select a range
147b8c4
画像変換の最小の処理をつくった
c9131d0
ディレクトリを変更
3753ee4
flagで変換前後のフォーマットを受け取れるようにした
7347ed5
Gif画像への変換を追加
0d10587
ディレクトリ内の画像を取得する関数を追加
87005e9
画像パスのスライスを返すように変更
e1d1691
複数の画像フォーマットをデコードする関数を作成
7c297c7
ファイル出力をまとめた
459b199
複数フォーマットをエンコードする関数を作成
52a0d06
画像パスをループさせて一括変換
53836db
mainパッケージと自作パッケージを分離
4770892
ファイル名の比較を修正
dc4cf11
go.modファイルを作成
829dcc1
パッケージ名を変更
1c212a6
Merge pull request #1 from yuonoda/kadai1-yuonoda
6d3e221
typoを修正
06c6c58
Merge pull request #2 from yuonoda/kadai1-yuonoda
daf05ef
実行ファイルをつくり、モジュールの設定を追加
cad2538
ユーザー定義型imgを追加
e730f5b
go docを追加
8929c28
実行ファイルを更新
4663590
moduleを整理
f73eeaa
フォーマット判定のcase文を整理
dd3a43c
sliceが空のときの返り値を修正
ca648d2
fmtをimgFmtに修正
e0e15d6
課題2-1作成
2f3feef
課題2-1を完了
7145e14
テストファイルを作成
6942e82
Merge remote-tracking branch 'origin/kadai1-yuonoda'
yuonoda d1738bb
エンコードのテストを作成
yuonoda 8b34dad
imgConverterを修正
yuonoda 1e1ea93
エンコードのテストを作成
yuonoda afc0e5c
imgConverterのテストを作成
yuonoda 6d89a8f
デコードをリファクタ
yuonoda a90bcb8
全体のテストを追加
yuonoda e2a5d1a
到達しないreturnを削除
yuonoda dce4bcf
コメントを修正
yuonoda 43d47ae
ファイル名を修正
yuonoda ad81dd3
コメントを修正
yuonoda 5160bd3
バイナリを削除
yuonoda ec92022
テストパッケージを分離
yuonoda 46261a4
errの変数名を変更
yuonoda c43f0d4
flagの処理をライブラリ外に出す
yuonoda 5968420
テーブル駆動テスト内をサブテスト化
yuonoda db486ea
テストディレクトリ作成用の関数を修正中
yuonoda 2f90502
テストディレクトリの構造をパラメーター化
yuonoda 3bfc3fd
エラーケースの判定を真偽値にする
yuonoda f9c6b1f
変更をリセット
yuonoda f72c945
ファイルを作成
yuonoda 58a1dee
モジュールを修正
yuonoda 5c9fc6f
モジュールを修正
yuonoda a44ac58
モジュールを修正
yuonoda 4ef1efb
GETリクエスト実装
yuonoda d51871b
ダウンロードしたデータをファイルに書き込み
yuonoda 63e4494
HEADでコンテンツサイズを取得
yuonoda ba5b36e
プライベートメソッドをエクスポートする
yuonoda 52e70e6
逐次アクセスでまず実装
yuonoda 6f54f5b
Rangeの指定を修正
yuonoda ce69308
Rangeリクエストを別関数にした
yuonoda b0e4086
バイト列の一部を置換する関数を作成
yuonoda 3766296
マージする処理を追加
yuonoda 696f186
URLとシングルサイズを引数にした
yuonoda 2e5f465
範囲の上限を設定
yuonoda 9008fab
ステータスコードを判定
yuonoda b450978
リトライ機能を追加
yuonoda fa14393
エラーグループを使ってエラー処理
yuonoda d9c9f53
エラーが起きたらファイルを削除
yuonoda 8c017ad
スリープをランダムにした
yuonoda d564a48
テストを別パッケージにした
yuonoda 8be759c
型とメソッドにまとめた
yuonoda 925d11c
resourceに処理を分離
yuonoda 7acb86e
Runのテストを追加
yuonoda 9ee4f5c
readmeを削除
yuonoda d5f70d4
Resourceメソッド内のlog.Fatalを削除
yuonoda 7062317
テスト内のlog.Fatalを削除
yuonoda fd0eff9
リトライ数を定数にした
yuonoda 28d355c
ダウンロード先のデフォルトをカレントディレクトリに変更した
yuonoda 1aaaa42
中断時にキャンセルコンテクストにいれる
yuonoda d326a56
中断時にBodyの読み込みをやめる処理を追加
yuonoda a34e5bd
TODOを整理
yuonoda b5c977a
パッケージの名称を変更
yuonoda e59e2da
utilitiesを別パッケージに分離
yuonoda 362adda
TODOを整理
yuonoda 9fd8299
Downloadをメソッドにした
yuonoda 4b8e35b
terminateを別パッケージにした
yuonoda e70df58
一時ファイルの削除をdeferで一括化
yuonoda e87a1b9
Download関数のエラー時にlog.Fatalを呼び出し
yuonoda 6cadba5
新しいdownloaderパッケージ用にテストを修正
yuonoda cffce87
terminateパッケージのテストを追加
yuonoda 26bebfe
Body読み込み時のGoルーチンを削除
yuonoda 9f0a7a3
エラーハンドリング漏れを修正
yuonoda 18f9d15
リクエストのエラーをエラーチャンネルで制御
yuonoda c1d2419
deferのエラーハンドリングを追加
yuonoda e72a1dc
一時ファイルが残っってなければ、削除をスキップ
yuonoda 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 @@ | ||
.idea |
This file was deleted.
Oops, something went wrong.
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,5 @@ | ||
module github.com/yuonoda/gopherdojo-studyroom/kadai3-2/yuonoda | ||
|
||
go 1.15 | ||
|
||
require golang.org/x/sync v0.0.0-20201207232520-09787c993a3a |
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,2 @@ | ||
golang.org/x/sync v0.0.0-20201207232520-09787c993a3a h1:DcqTD9SDLc+1P/r1EmRBwnVsrOwW+kk2vWf9n+1sGhs= | ||
golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= |
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,3 @@ | ||
package splitDownload | ||
|
||
var ExportedFillByteArr = fillByteArr |
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 @@ | ||
package splitDownload | ||
|
||
import ( | ||
"bytes" | ||
"errors" | ||
"fmt" | ||
"golang.org/x/sync/errgroup" | ||
"io/ioutil" | ||
"log" | ||
"math" | ||
"math/rand" | ||
"net/http" | ||
"strconv" | ||
"time" | ||
) | ||
|
||
type partialContent struct { | ||
StartByte int | ||
EndByte int | ||
Body []byte | ||
} | ||
|
||
type resource struct { | ||
Url string | ||
Size int | ||
BatchSize int | ||
BatchCount int | ||
Content []byte | ||
PartialContentCh chan partialContent | ||
Http http.Client | ||
} | ||
|
||
func (r *resource) GetSize() error { | ||
log.Printf("resource.getSize()\n") | ||
|
||
// HEADでサイズを調べる | ||
res, err := r.Http.Head(r.Url) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
// データサイズを取得 | ||
header := res.Header | ||
cl, ok := header["Content-Length"] | ||
if !ok { | ||
return errors.New("Content-Length couldn't be found") | ||
} | ||
r.Size, err = strconv.Atoi(cl[0]) | ||
if err != nil { | ||
return err | ||
} | ||
return nil | ||
|
||
} | ||
|
||
func (r *resource) GetPartialContent(startByte int, endByte int) error { | ||
log.Printf("resource.getPartialContent(%d, %d)\n", startByte, endByte) | ||
// Rangeヘッダーを作成 | ||
rangeVal := fmt.Sprintf("bytes=%d-%d", startByte, endByte) | ||
|
||
// リクエストとクライアントの作成 | ||
reader := bytes.NewReader([]byte{}) | ||
req, err := http.NewRequest("GET", r.Url, reader) | ||
if err != nil { | ||
return err | ||
} | ||
req.Header.Set("Range", rangeVal) | ||
client := &http.Client{} | ||
|
||
res := &http.Response{} | ||
for i := 0; i < 3; i++ { | ||
// リクエストの実行 | ||
log.Printf("rangeVal[%d]:%s", i, rangeVal) | ||
res, err = client.Do(req) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
// ステータスが200系ならループを抜ける | ||
log.Printf("res.StatusCode:%d\n", res.StatusCode) | ||
if res.StatusCode >= 200 && res.StatusCode <= 299 { | ||
break | ||
} | ||
|
||
// 乱数分スリープ | ||
rand.Seed(time.Now().UnixNano()) | ||
randFloat := rand.Float64() + 1 | ||
randMs := math.Pow(randFloat, float64(i+1)) * 1000 | ||
sleepTime := time.Duration(randMs) * time.Millisecond | ||
log.Printf("sleep:%v\n", sleepTime) | ||
time.Sleep(sleepTime) | ||
} | ||
|
||
// 正常系レスポンスでないとき | ||
if res.StatusCode < 200 || res.StatusCode > 299 { | ||
return errors.New("status code is not 2xx, got " + res.Status) | ||
} | ||
|
||
// bodyの取得 | ||
body, err := ioutil.ReadAll(res.Body) | ||
defer res.Body.Close() | ||
if err != nil { | ||
return err | ||
} | ||
|
||
pc := partialContent{StartByte: startByte, EndByte: endByte, Body: body} | ||
r.PartialContentCh <- pc | ||
return nil | ||
} | ||
|
||
func (r *resource) GetContent(batchCount int) error { | ||
log.Println("resource.getContent()") | ||
|
||
// コンテンツのデータサイズを取得 | ||
err := r.GetSize() | ||
if err != nil { | ||
log.Fatal(err) | ||
yuonoda marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} | ||
log.Printf("r.size: %d\n", r.Size) | ||
|
||
// batchCount分リクエスト | ||
r.BatchCount = batchCount | ||
r.BatchSize = int(math.Ceil(float64(r.Size) / float64(r.BatchCount))) | ||
r.Content = make([]byte, r.Size) | ||
var eg errgroup.Group | ||
r.PartialContentCh = make(chan partialContent, r.BatchCount) | ||
for i := 0; i < r.BatchCount; i++ { | ||
|
||
// 担当する範囲を決定 | ||
startByte := r.BatchSize * i | ||
endByte := r.BatchSize*(i+1) - 1 | ||
if endByte > r.Size { | ||
endByte = r.Size | ||
} | ||
|
||
// レンジごとにリクエスト | ||
eg.Go(func() error { | ||
return r.GetPartialContent(startByte, endByte) | ||
}) | ||
} | ||
|
||
// 1リクエストでも失敗すれば終了 | ||
if err := eg.Wait(); err != nil { | ||
return err | ||
} | ||
|
||
// 一つのバイト列にマージ | ||
r.Content = make([]byte, r.Size) | ||
for i := 0; i < r.BatchCount; i++ { | ||
log.Println("merging...") | ||
pc := <-r.PartialContentCh | ||
log.Printf("pc.startByte: %v\n", pc.StartByte) | ||
fillByteArr(r.Content[:], pc.StartByte, pc.Body) | ||
} | ||
|
||
return nil | ||
} |
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,48 @@ | ||
package splitDownload | ||
|
||
import ( | ||
"log" | ||
"os" | ||
"path/filepath" | ||
"strings" | ||
) | ||
|
||
func Run(url string, batchCount int, dwDirPath string) string { | ||
log.Println("Run") | ||
|
||
// ファイルの作成 | ||
_, filename := filepath.Split(url) | ||
homedir, err := os.UserHomeDir() | ||
yuonoda marked this conversation as resolved.
Show resolved
Hide resolved
|
||
if err != nil { | ||
log.Fatal(err) | ||
} | ||
if dwDirPath == "" { | ||
dwDirPath = homedir + "/Downloads" | ||
} | ||
dwFilePath := dwDirPath + "/" + filename + ".download" | ||
log.Println(dwFilePath) | ||
dwFile, err := os.Create(dwFilePath) | ||
if err != nil { | ||
os.Remove(dwFilePath) | ||
yuonoda marked this conversation as resolved.
Show resolved
Hide resolved
|
||
log.Fatal(err) | ||
} | ||
|
||
// ダウンロード実行 | ||
r := &resource{Url: url} | ||
err = r.GetContent(batchCount) | ||
if err != nil { | ||
log.Fatal(err) | ||
} | ||
|
||
// データの書き込み | ||
_, err = dwFile.Write(r.Content) | ||
if err != nil { | ||
os.Remove(dwFilePath) | ||
log.Fatal(err) | ||
} | ||
finishedFilePath := strings.Trim(dwFilePath, ".download") | ||
os.Rename(dwFilePath, finishedFilePath) | ||
|
||
log.Println("download succeeded!") | ||
return finishedFilePath | ||
} |
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,98 @@ | ||
package splitDownload_test | ||
|
||
import ( | ||
"log" | ||
"os" | ||
"reflect" | ||
"testing" | ||
|
||
splitDownload "github.com/yuonoda/gopherdojo-studyroom/kadai3-2/yuonoda/lib" | ||
) | ||
|
||
func TestRun(t *testing.T) { | ||
cases := []struct { | ||
name string | ||
url string | ||
expectedSize int64 | ||
concurrency int | ||
}{ | ||
{ | ||
name: "basic", | ||
url: "https://dumps.wikimedia.org/jawiki/20210101/jawiki-20210101-pages-articles-multistream-index.txt.bz2", | ||
expectedSize: int64(25802009), | ||
concurrency: 3, | ||
}, | ||
} | ||
|
||
for _, c := range cases { | ||
t.Run(c.name, func(t *testing.T) { | ||
// ダウンロードパスを指定 | ||
homedir, err := os.UserHomeDir() | ||
if err != nil { | ||
log.Fatal(err) | ||
} | ||
dwDirPath := homedir + "/Downloads" | ||
|
||
// ダウンロード | ||
filePath := splitDownload.Run(c.url, c.concurrency, dwDirPath) | ||
file, err := os.Open(filePath) | ||
if err != nil { | ||
t.Error(err) | ||
} | ||
|
||
// サイズを取得 | ||
info, err := file.Stat() | ||
if err != nil { | ||
t.Error(err) | ||
} | ||
dwSize := info.Size() | ||
|
||
// サイズを比較 | ||
if dwSize != c.expectedSize { | ||
t.Errorf("Size doesn't match, got %d but expexted %d", dwSize, c.expectedSize) | ||
} | ||
|
||
// ファイルを削除 | ||
err = os.Remove(filePath) | ||
if err != nil { | ||
t.Error(err) | ||
} | ||
}) | ||
} | ||
|
||
} | ||
|
||
func TestFillByteArr(t *testing.T) { | ||
cases := []struct { | ||
name string | ||
arr []byte | ||
startAt int | ||
partArr []byte | ||
expectedArr []byte | ||
}{ | ||
{ | ||
name: "basic", | ||
arr: []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, | ||
startAt: 3, | ||
partArr: []byte{4, 5, 6}, | ||
expectedArr: []byte{0, 0, 0, 4, 5, 6, 0, 0, 0, 0}, | ||
}, | ||
{ | ||
name: "basic2", | ||
arr: []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, | ||
startAt: 8, | ||
partArr: []byte{9, 10}, | ||
expectedArr: []byte{0, 0, 0, 0, 0, 0, 0, 0, 9, 10}, | ||
}, | ||
} | ||
|
||
for _, c := range cases { | ||
t.Run(c.name, func(t *testing.T) { | ||
splitDownload.ExportedFillByteArr(c.arr[:], c.startAt, c.partArr) | ||
if !reflect.DeepEqual(c.expectedArr, c.arr) { | ||
t.Error("Array does not match") | ||
} | ||
}) | ||
} | ||
|
||
} |
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,9 @@ | ||
package splitDownload | ||
|
||
// 配列の一部を別配列に置き換える | ||
func fillByteArr(arr []byte, startAt int, partArr []byte) { | ||
for i := 0; i < len(partArr); i++ { | ||
globalIndex := i + startAt | ||
arr[globalIndex] = partArr[i] | ||
} | ||
} |
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,15 @@ | ||
package main | ||
|
||
import ( | ||
"flag" | ||
splitDownload "github.com/yuonoda/gopherdojo-studyroom/kadai3-2/yuonoda/lib" | ||
) | ||
|
||
var url = flag.String("url", "https://dumps.wikimedia.org/jawiki/20210101/jawiki-20210101-pages-articles-multistream-index.txt.bz2", "URL to download") | ||
var batchCount = flag.Int("c", 1, "how many times you request content") | ||
var dwDirPath = flag.String("path", "", "where to put a downloaded file") | ||
|
||
func main() { | ||
flag.Parse() | ||
splitDownload.Run(*url, *batchCount, *dwDirPath) | ||
} |
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.
Uh oh!
There was an error while loading. Please reload this page.