public LockObjectReply Lock(LockObjectRequest request) { Console.WriteLine("Received LockObjectRequest with params:"); Console.Write($"Key: \r\n PartitionId: {request.Key.PartitionId} \r\n ObjectId: {request.Key.ObjectId}\r\n"); if (!KeyValuePairs.TryGetValue(new ObjectKey(request.Key), out ObjectValueManager objectValueManager)) { LocalReadWriteLock.AcquireWriterLock(-1); objectValueManager = new ObjectValueManager(); KeyValuePairs[new ObjectKey(request.Key)] = objectValueManager; objectValueManager.LockWrite(); LocalReadWriteLock.ReleaseWriterLock(); } else { objectValueManager.LockWrite(); } return(new LockObjectReply { Success = true }); }
public WriteObjectReply Write(WriteObjectRequest request) { Console.WriteLine("Received write with params:"); Console.WriteLine($"Partition_id: {request.Key.PartitionId}"); Console.WriteLine($"Object_id: {request.Key.ObjectId}"); Console.WriteLine($"Value: {request.Value}"); if (MasteredPartitions.Contains(request.Key.PartitionId)) { lock (WriteGlobalLock) { // I'm master of this object's partition // Send request to all other servers of partition ServersByPartition.TryGetValue(request.Key.PartitionId, out List <string> serverIds); if (!KeyValuePairs.TryGetValue(new ObjectKey(request.Key), out ObjectValueManager objectValueManager)) { LocalReadWriteLock.AcquireWriterLock(-1); objectValueManager = new ObjectValueManager(); KeyValuePairs[new ObjectKey(request.Key)] = objectValueManager; objectValueManager.LockWrite(); LocalReadWriteLock.ReleaseWriterLock(); } else { objectValueManager.LockWrite(); } var connectionCrashedServers = new HashSet <string>(); foreach (var server in ServerUrls.Where(x => serverIds.Contains(x.Key) && x.Key != MyId)) { var channel = GrpcChannel.ForAddress(server.Value); var client = new ServerSyncGrpcService.ServerSyncGrpcServiceClient(channel); // What to do if success returns false ? try { client.LockObject(new LockObjectRequest { Key = request.Key }); } catch (RpcException e) { // If grpc does no respond, we can assume it has crashed if (e.Status.StatusCode == StatusCode.DeadlineExceeded || e.Status.StatusCode == StatusCode.Unavailable || e.Status.StatusCode == StatusCode.Internal) { // Add to hash Set Console.WriteLine($"Server {server.Key} has crashed"); connectionCrashedServers.Add(server.Key); } else { throw e; } } } foreach (var server in ServerUrls.Where(x => serverIds.Contains(x.Key) && x.Key != MyId)) { try { var channel = GrpcChannel.ForAddress(server.Value); var client = new ServerSyncGrpcService.ServerSyncGrpcServiceClient(channel); // What to do if success returns false ? client.ReleaseObjectLock(new ReleaseObjectLockRequest { Key = request.Key, Value = request.Value }); } catch (RpcException e) { if (e.Status.StatusCode == StatusCode.DeadlineExceeded || e.Status.StatusCode == StatusCode.Unavailable || e.Status.StatusCode == StatusCode.Internal) { // Add to hash Set Console.WriteLine($"Server {server.Key} has crashed"); connectionCrashedServers.Add(server.Key); } else { throw e; } } } if (connectionCrashedServers.Any()) { // Update the crashed servers UpdateCrashedServers(request.Key.PartitionId, connectionCrashedServers); // Contact Partition slaves an update their view of the partition foreach (var server in ServerUrls.Where(x => serverIds.Contains(x.Key) && x.Key != MyId)) { var channel = GrpcChannel.ForAddress(server.Value); var client = new ServerSyncGrpcService.ServerSyncGrpcServiceClient(channel); client.RemoveCrashedServers(new RemoveCrashedServersRequest { PartitionId = request.Key.PartitionId, ServerIds = { connectionCrashedServers } }); } } objectValueManager.UnlockWrite(request.Value); return(new WriteObjectReply { Ok = true }); } } else { // Tell him I'm not the master throw new RpcException(new Status(StatusCode.PermissionDenied, $"Server {MyId} is not the master of partition {request.Key.PartitionId}")); } }