init
This commit is contained in:
commit
26132511cb
27
LICENSE
Normal file
27
LICENSE
Normal file
@ -0,0 +1,27 @@
|
||||
Copyright (c) 2018, Stephen McQuay (smcquay)
|
||||
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
* Neither the name of pid nor the names of its contributors
|
||||
may be used to endorse or promote products derived from this software
|
||||
without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
6
README.md
Normal file
6
README.md
Normal file
@ -0,0 +1,6 @@
|
||||
# bigfiles
|
||||
|
||||
Answer to an interview question:
|
||||
|
||||
Find the largest N files hosted at `hmm.clstr.co/size/` named `000` through
|
||||
`999`, inclusive, then make it go as fast as you can.
|
105
main.go
Normal file
105
main.go
Normal file
@ -0,0 +1,105 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"net/http"
|
||||
"runtime"
|
||||
"sort"
|
||||
"sync"
|
||||
)
|
||||
|
||||
const max = 1000
|
||||
|
||||
type pair struct {
|
||||
u string
|
||||
s int64
|
||||
}
|
||||
|
||||
type pairs []pair
|
||||
|
||||
func (p pairs) Len() int { return len(p) }
|
||||
func (p pairs) Swap(a, b int) { p[a], p[b] = p[b], p[a] }
|
||||
func (p pairs) Less(a, b int) bool { return p[a].s < p[b].s }
|
||||
|
||||
var workers = flag.Int("workers", runtime.NumCPU()*4, "number of downloaders")
|
||||
|
||||
func main() {
|
||||
flag.Parse()
|
||||
for r := range srt(attack(urls(max), *workers)) {
|
||||
fmt.Printf("%v\t%v\n", r.s, r.u)
|
||||
}
|
||||
}
|
||||
|
||||
func urls(max int) chan string {
|
||||
r := make(chan string)
|
||||
|
||||
go func() {
|
||||
for i := 0; i < max; i++ {
|
||||
r <- fmt.Sprintf("https://hmm.clstr.co/size/%03d", i)
|
||||
}
|
||||
close(r)
|
||||
}()
|
||||
|
||||
return r
|
||||
}
|
||||
|
||||
func attack(urls chan string, workers int) chan pair {
|
||||
r := make(chan pair)
|
||||
go func() {
|
||||
c := http.Client{}
|
||||
s := make(chan bool, workers)
|
||||
wg := sync.WaitGroup{}
|
||||
for u := range urls {
|
||||
wg.Add(1)
|
||||
s <- true
|
||||
go func(url string) {
|
||||
resp, err := c.Get(url)
|
||||
if err != nil {
|
||||
log.Printf("probalo: %v", err)
|
||||
return
|
||||
}
|
||||
r <- pair{url, resp.ContentLength}
|
||||
|
||||
if n, err := io.Copy(ioutil.Discard, resp.Body); err != nil {
|
||||
log.Printf("after %v bytes: %v", n, err)
|
||||
}
|
||||
if err := resp.Body.Close(); err != nil {
|
||||
log.Printf("close body: %v", err)
|
||||
}
|
||||
<-s
|
||||
wg.Done()
|
||||
}(u)
|
||||
}
|
||||
wg.Wait()
|
||||
close(r)
|
||||
}()
|
||||
return r
|
||||
}
|
||||
|
||||
func srt(in chan pair) chan pair {
|
||||
r := make(chan pair)
|
||||
go func() {
|
||||
ps := pairs{}
|
||||
for r := range in {
|
||||
ps = append(ps, r)
|
||||
}
|
||||
|
||||
sort.Sort(ps)
|
||||
|
||||
for _, p := range ps {
|
||||
r <- p
|
||||
}
|
||||
close(r)
|
||||
}()
|
||||
return r
|
||||
}
|
||||
|
||||
func print() {
|
||||
for i := 0; i < 1000; i++ {
|
||||
fmt.Sprintf("hmm.clstr.co/size/%03d", i)
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user