// internal lock code shared by unlock and lock. (different endpoints) func locking(endpoint string, services *Services, routerTable *shards.RouterTable, partition int) error { // Lock All partitions for _, e := range routerTable.Entries { response, err := client.HttpApiCallSync( fmt.Sprintf("%s:%d", e.Address, e.HttpPort), cheshire.NewRequest(endpoint, "GET"), 5*time.Second) if err != nil { services.Logger.Printf("ERROR While contacting %s -- %s", e.Address, err) //TODO: retry? continue } if response.StatusCode() != 200 { //TODO: retry? services.Logger.Printf("ERROR While locking partition %s -- %s", e.Address, response.StatusMessage()) } } return nil }
// Delete the requested partition from the entry. // this does not lock, and does not update the router table func DeletePartition(services *Services, entry *shards.RouterEntry, partition int) error { services.Logger.Printf("DELETING Partition %d From %s", partition, entry.Address) request := cheshire.NewRequest(shards.PARTITION_DELETE, "DELETE") request.Params().Put("partition", partition) services.Logger.Printf("NOW Deleting the partition from the origin server %s", entry.Address) response, err := client.HttpApiCallSync( fmt.Sprintf("%s:%d", entry.Address, entry.HttpPort), request, 300*time.Second) if err != nil { return err } if response.StatusCode() != 200 { return fmt.Errorf("ERROR While deleting partition: %s", response.StatusMessage()) } return nil }
// 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 }