Esempio n. 1
0
// downloadSector retrieves a Ring from the quorum it is stored on.
// It reconstructs the original Sector from the Ring.
func downloadSector(hash crypto.Hash) (sec *common.Sector, err error) {
	// look up Sector in SectorDB
	rh := SectorDB[hash]
	if rh == nil {
		err = fmt.Errorf("Sector not found in database")
		return
	}

	// send requests to each member of the quorum
	var segs []common.Segment
	for i := range rh.Hosts {
		var seg common.Segment
		sendErr := router.SendMessage(&common.Message{
			Dest: rh.Hosts[i],
			Proc: "Server.DownloadSegment",
			Args: rh.SegHashes[i],
			Resp: &seg,
		})
		if sendErr == nil {
			segs = append(segs, seg)
		} else {
			fmt.Println(sendErr)
		}
	}

	// rebuild file
	sec, err = erasure.RebuildSector(segs, rh.Params)
	return
}
Esempio n. 2
0
func (dh *downloadHandler) HandleMessage(payload []byte) {
	// first byte is the segment index
	dh.indices = append(dh.indices, uint8(payload[0]))
	dh.segments = append(dh.segments, string(payload[1:]))
	// if enough segments have been collected, reconstruct the data
	if len(dh.segments) == dh.k {
		dh.data, _ = erasure.RebuildSector(dh.k, dh.b, dh.segments, dh.indices)
		dh.done <- true
	}
}
Esempio n. 3
0
// TestRPCUploadSector tests the NewRPCServer and uploadFile functions.
// NewRPCServer must properly initialize a RPC server.
// uploadSector must succesfully distribute a Sector among a quorum.
// The uploaded Sector must be successfully reconstructed.
func TestRPCuploadSector(t *testing.T) {
	SectorDB = make(map[crypto.Hash]*common.RingHeader)

	// create RPCServer
	var err error
	router, err = network.NewRPCServer(9985)
	if err != nil {
		t.Fatal("Failed to initialize RPCServer:", err)
	}
	defer router.Close()

	// create quorum
	var q [common.QuorumSize]common.Address
	var shs [common.QuorumSize]Server
	for i := 0; i < common.QuorumSize; i++ {
		q[i] = common.Address{0, "localhost", 9000 + i}
		qrpc, err := network.NewRPCServer(9000 + i)
		defer qrpc.Close()
		if err != nil {
			t.Fatal("Failed to initialize RPCServer:", err)
		}
		q[i].ID = qrpc.RegisterHandler(&shs[i])
	}

	// create sector
	secData, err := crypto.RandomByteSlice(70000)
	if err != nil {
		t.Fatal("Could not generate test data:", err)
	}

	sec, err := common.NewSector(secData)
	if err != nil {
		t.Fatal("Failed to create sector:", err)
	}

	// add sector to database
	k := common.QuorumSize / 2
	SectorDB[sec.Hash] = &common.RingHeader{
		Hosts:  q,
		Params: sec.CalculateParams(k),
	}

	// upload sector to quorum
	err = uploadSector(sec)
	if err != nil {
		t.Fatal("Failed to upload file:", err)
	}

	// rebuild file from first k segments
	var newRing []common.Segment
	for i := 0; i < k; i++ {
		newRing = append(newRing, shs[i].seg)
	}

	sec, err = erasure.RebuildSector(newRing, SectorDB[sec.Hash].Params)
	if err != nil {
		t.Fatal("Failed to rebuild file:", err)
	}

	// check hash
	rebuiltHash, err := crypto.CalculateHash(sec.Data)
	if err != nil {
		t.Fatal("Failed to calculate hash:", err)
	}

	if sec.Hash != rebuiltHash {
		t.Fatal("Failed to recover file: hashes do not match")
	}
}
Esempio n. 4
0
// TestTCPUploadFile tests the NewTCPServer and UploadFile functions.
// NewTCPServer must properly initialize a TCP server.
// UploadFile must succesfully distribute a file among a quorum.
// The uploaded file must be successfully reconstructed.
func TestTCPUploadFile(t *testing.T) {
	// create TCPServer
	tcp, err := network.NewTCPServer(9988)
	if err != nil {
		t.Fatal("Failed to initialize TCPServer:", err)
	}
	defer tcp.Close()

	// create quorum
	var q [common.QuorumSize]common.Address
	var uhs [common.QuorumSize]uploadHandler
	for i := 0; i < common.QuorumSize; i++ {
		q[i] = common.Address{0, "localhost", 9000 + i}
		qtcp, err := network.NewTCPServer(9000 + i)
		defer qtcp.Close()
		if err != nil {
			t.Fatal("Failed to initialize TCPServer:", err)
		}
		uhs[i].done = make(chan bool, 1)
		q[i].Id = qtcp.AddMessageHandler(&uhs[i]).Id
	}

	// create file
	file, err := os.Create("InputFile")
	if err != nil {
		t.Fatal("Failed to create file \"InputFile\"")
	}
	defer file.Close()
	defer os.Remove("InputFile")

	fileData, err := crypto.RandomByteSlice(70000)
	if err != nil {
		t.Fatal("Could not generate test data:", err)
	}

	err = ioutil.WriteFile("InputFile", fileData, 0644)
	if err != nil {
		t.Fatal("Failed to write to file InputFile:", err)
	}

	// calculate hash
	origHash, err := crypto.CalculateHash(fileData)
	if err != nil {
		t.Fatal("Failed to calculate hash:", err)
	}

	// upload file to quorum
	k := 50
	b, err := UploadFile(tcp, file, k, q)
	if err != nil {
		t.Fatal("Failed to upload file:", err)
	}

	// wait for all participants to complete
	for i := range uhs {
		<-uhs[i].done
	}

	// rebuild file from first k segments
	segments := make([]string, k)
	indices := make([]uint8, k)
	for i := 0; i < k; i++ {
		segments[i] = string(uhs[i].data)
		indices[i] = uint8(uhs[i].index)
	}

	rebuiltData, err := erasure.RebuildSector(k, b, segments, indices)
	if err != nil {
		t.Fatal("Failed to rebuild file:", err)
	}
	// remove padding
	rebuiltData = rebuiltData[:len(fileData)]

	// check hash
	rebuiltHash, err := crypto.CalculateHash(rebuiltData)
	if err != nil {
		t.Fatal("Failed to calculate hash:", err)
	}

	if origHash != rebuiltHash {
		t.Fatal("Failed to recover file: hashes do not match")
	}
}