コード例 #1
0
ファイル: topology.go プロジェクト: sourabhg/goshire-shards
// Moves data from one server to another
// Does the following:
// 1. Lock all necessary clients
// 2. Move Data
// 3. Update router table on servers
// 4. Delete partion from origin
// 5. Unlock
func MovePartition(services *Services, routerTable *shards.RouterTable, partition int, from, to *shards.RouterEntry) error {

	err := LockPartition(services, routerTable, partition)
	if err != nil {
		return err
	}
	//Unlock partition no matter what
	defer UnlockPartition(services, routerTable, partition)

	//copy the data
	_, err = CopyData(services, routerTable, partition, from, to)
	if err != nil {
		return err
	}

	//update the router table.
	parts := make([]int, 0)
	for _, p := range from.Partitions {
		if p != partition {
			parts = append(parts, p)
		}
	}
	from.Partitions = parts
	to.Partitions = append(to.Partitions, partition)
	routerTable, err = routerTable.AddEntries(from, to)
	routerTable, ok := RouterTableUpdate(services, routerTable, len(routerTable.Entries))
	if !ok {
		services.Logger.Printf("Uh oh, Didnt update any router tables")
	}

	//Delete the data on the from server.
	err = DeletePartition(services, from, partition)
	if err != nil {
		return err
	}

	return nil
}
コード例 #2
0
ファイル: topology.go プロジェクト: sourabhg/goshire-shards
// Moves a single partition from the largest entry to the smallest.  only
// if the smallest entry is smaller then the rest.
// if all entries are the same size, then a random entry is chosen
func RebalanceSingle(services *Services, routerTable *shards.RouterTable) error {

	var smallest *shards.RouterEntry = nil
	var largest *shards.RouterEntry = nil

	min := int(routerTable.TotalPartitions / len(routerTable.Entries))
	services.Logger.Printf("Looking for entries with more then %d partitions", min)

	//shuffle the entries array
	entries := make([]*shards.RouterEntry, len(routerTable.Entries))
	perm := rand.Perm(len(routerTable.Entries))
	for i, v := range perm {
		entries[v] = routerTable.Entries[i]
	}

	for _, entry := range entries {
		if len(entry.Partitions) < min {
			if smallest == nil {
				smallest = entry
			} else if len(entry.Partitions) < len(smallest.Partitions) {
				smallest = entry
			}

			if largest == nil {
				largest = entry
			} else if len(entry.Partitions) > len(largest.Partitions) {
				largest = entry
			}
		}
	}
	if smallest == nil || largest == nil {
		services.Logger.Printf("Cluster appears to be balanced")
		return nil
	}

	services.Logger.Printf("Moving from %s to %s", largest.Id(), smallest.Id())

	return nil
}
コード例 #3
0
ファイル: topology.go プロジェクト: sourabhg/goshire-shards
// Checkin to an entry.  will update their router table if it is out of date.  will update our router table if out of date.
func EntryCheckin(routerTable *shards.RouterTable, entry *shards.RouterEntry) (*shards.RouterTable, bool, error) {
	// make sure our routertable is up to date.
	response, err := client.HttpApiCallSync(
		fmt.Sprintf("%s:%d", entry.Address, entry.HttpPort),
		cheshire.NewRequest(shards.CHECKIN, "GET"),
		5*time.Second)
	if err != nil {
		return routerTable, false, fmt.Errorf("ERROR While contacting %s -- %s", entry.Address, err)
	}

	entry.LastSeenAt = time.Now()

	rev := response.MustInt64("rt_revision", 0)
	if rev == routerTable.Revision {
		return routerTable, false, nil
	}

	if rev < routerTable.Revision {
		//updating server.
		//set the new routertable.
		req := cheshire.NewRequest(shards.ROUTERTABLE_SET, "POST")
		req.Params().Put("router_table", req.ToDynMap())

		response, err = client.HttpApiCallSync(
			fmt.Sprintf("%s:%d", entry.Address, entry.HttpPort),
			req,
			5*time.Second)
		if err != nil {
			return routerTable, false, fmt.Errorf("ERROR While contacting for router table update %s -- %s", entry.Address, err)
		}
		if response.StatusCode() != 200 {
			return routerTable, false, fmt.Errorf("Error trying to Set router table %s -- %s", entry.Address, response.StatusMessage())
		}
	} else {
		//updating local

		log.Printf("Found updated router table at: %s", entry.Address)
		//get the new routertable.
		response, err = client.HttpApiCallSync(
			fmt.Sprintf("%s:%d", entry.Address, entry.HttpPort),
			cheshire.NewRequest(shards.ROUTERTABLE_GET, "GET"),
			5*time.Second)
		if err != nil {
			return routerTable, false, fmt.Errorf("ERROR While contacting %s -- %s", entry.Address, err)
		}
		mp, ok := response.GetDynMap("router_table")
		if !ok {
			return routerTable, false, fmt.Errorf("ERROR from %s -- BAD ROUTER TABLE RESPONSE %s", entry.Address, response)
		}

		rt, err := shards.ToRouterTable(mp)
		if err != nil {
			return routerTable, false, fmt.Errorf("ERROR While parsing router table %s -- %s", entry.Address, err)
		}

		log.Printf("SUCCESSFULLY update router table to revision %d", rt.Revision)
		routerTable = rt
		return routerTable, true, nil

	}
	return routerTable, false, nil
}