Exemplo n.º 1
0
        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
            });
        }
Exemplo n.º 2
0
        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}"));
            }
        }