func (this *DataMgr) downloadLoop() { this.Log.Printf("Entering download loop") this.lock.Lock() // Lock is held *except* when doing remote calls & sleeping // While I'm not closing for !this.isClosing { this.SyncMgr.Log.Printf("Looking things to download\n") // Get a object to download var key string row := this.Db.SingleQuery("SELECT key FROM Blob WHERE needs_download = 1") if !this.Db.MaybeScan(row, &key) { this.Log.Printf("Nothing to download, sleeping\n") this.download.Wait() continue } friends := this.allAdverts(key) if len(friends) == 0 { this.Log.Printf("Strangely got a download where len(friends) = 0") this.Db.Exec("UPDATE Blob SET needs_download = 0 WHERE key = ?", key) continue } friend := friends[rand.Intn(len(friends))] obj := this.getObj(key) obj.startDownload() this.writeObj(obj) this.lock.Unlock() this.Log.Printf("Doing a download of %s from %d!\n", key, friend) var send_buf bytes.Buffer transfer.Encode(&send_buf, key) tmppath := path.Join(this.incoming, crypto.RandomString()) file, _ := os.Create(tmppath) hasher := crypto.NewHasher() both := io.MultiWriter(file, hasher) tryTime := time.Now() err := this.Send(link.ServiceData, friend, &send_buf, both) if err != nil && time.Now().Sub(tryTime) < 5*time.Second { // TODO: Make this not suck time.Sleep(5 * time.Second) } if err != nil { this.Log.Printf("Download failed: %s", err) } else { this.Log.Printf("Download worked!") } this.lock.Lock() obj = this.getObj(key) obj.finishDownload(tmppath, err == nil) this.writeObj(obj) } this.lock.Unlock() this.goRoutines.Done() }
// Reads from io.Reader and generates a new object, put it to the meta-data layer func (this *DataMgr) PutData(topic string, key string, writer *crypto.SecretIdentity, stream io.Reader) error { this.Log.Printf("Putting data: %s, %s", topic, key) // Write the object to disk tmppath := path.Join(this.incoming, crypto.RandomString()) file, err := os.Create(tmppath) if err != nil { return err } hasher := crypto.NewHasher() both := io.MultiWriter(file, hasher) _, err = io.Copy(both, stream) if err != nil { _ = os.Remove(tmppath) // Ignore errors return err } digest := hasher.Finalize() okey := digest.String() // Add info to DB this.lock.Lock() obj := this.getObj(okey) obj.newFile(tmppath) obj.Holds++ this.writeObj(obj) this.lock.Unlock() // Put to meta-data layer data, _ := transfer.EncodeBytes(digest) err = this.MetaMgr.Put(topic, writer, key, data) // Remove hold this.lock.Lock() obj = this.getObj(okey) obj.Holds-- this.writeObj(obj) this.lock.Unlock() return err }