private FileData ReadFileData(int fileRegisterIndex, Helper.Semantics semantics) { // gets latest version LatestVersion latestVersion = ReadVersion(fileRegisterIndex, semantics); // requests file data to dataServer with latest version List <string> dataServersIds = latestVersion.DataServerIds; // loops until we get something from a read from any dataServer while (true) { foreach (string id in dataServersIds) { string location = fileRegister.FileMetadataAt(fileRegisterIndex).Locations[id]; string localFilename = fileRegister.FileMetadataAt(fileRegisterIndex).LocalFilenames[id]; IDataServerToClient dataServer = (IDataServerToClient)Activator.GetObject( typeof(IDataServerToClient), location); try { FileData fileData = dataServer.Read(localFilename); // update file registers fileRegister.SetFileDataAt(fileRegisterIndex, fileData); return(fileData); } catch (ProcessFailedException) { } catch (ProcessFreezedException) { } } } }
public void Write(int fileRegisterIndex, byte[] contents) { Console.WriteLine("WRITE FILE = " + fileRegisterIndex); try { // forces to get always the most recent file FileVersion latest = ReadVersion(fileRegisterIndex, Helper.Semantics.MONOTONIC).Version; latest.Increment(Client.id); FileData fileData = new FileData(latest, contents); string filename = fileRegister.FilenameAt(fileRegisterIndex); FileMetadata fileMetadata = fileRegister.FileMetadataAt(fileRegisterIndex); // data server id / bool write ConcurrentDictionary <string, bool> writes = new ConcurrentDictionary <string, bool>(); int requests = 0; bool quorumReached = false; //QUORUM while (true) { // voting WriteQuorum quorum = new WriteQuorum(fileMetadata.WriteQuorum); foreach (var entry in writes) { bool vote = entry.Value; quorum.AddVote(vote); if (quorum.CheckQuorum()) { quorumReached = true; break; } } // found the quorum file if (quorumReached) { break; } // if there are still pending requests // dont create new ones if (requests > 0) { continue; } // if all the votes arrived at the quorum // stops when all requests are counted (requests = 0) if (quorum.Count == (requests + quorum.Count)) { // get possible new fileMetadata locations // possible optimization // check if there are no dataa servers fileMetadata = OpenFileMetadata(filename); // broadcast to all dataServers that have that file foreach (var entry in fileMetadata.Locations) { string id = entry.Key; string location = entry.Value; string localFilename = fileMetadata.LocalFilenames[id]; // increment right away so it doesn't request untill its decremented Interlocked.Increment(ref requests); Thread request = new Thread(() => { IDataServerToClient dataServer = (IDataServerToClient)Activator.GetObject( typeof(IDataServerToClient), location); bool vote = false; try { dataServer.Write(localFilename, fileData); vote = true; } catch (ProcessFailedException) { } catch (ProcessFreezedException) { } finally { writes[id] = vote; Interlocked.Decrement(ref requests); } }); request.Start(); } } } // update file registers fileRegister.SetFileDataAt(fileRegisterIndex, fileData); } catch (FileDoesNotExistException e) { Console.WriteLine(e.Message); return; } }
private LatestVersion ReadVersion(int fileRegisterIndex, Helper.Semantics semantics) { Console.WriteLine("READ VERSION " + fileRegisterIndex); string filename = fileRegister.FilenameAt(fileRegisterIndex); FileVersion original = fileRegister.FileDataAt(fileRegisterIndex).Version; FileMetadata fileMetadata = fileRegister.FileMetadataAt(fileRegisterIndex); // data server id / file data ConcurrentDictionary <string, FileVersion> reads = new ConcurrentDictionary <string, FileVersion>(); int requests = 0; LatestVersion quorumVersion = null; //QUORUM while (true) { // voting ReadQuorum quorum = new ReadQuorum(fileMetadata.ReadQuorum, semantics); foreach (var entry in reads) { FileVersion vote = entry.Value; string dataServerId = entry.Key; quorum.AddVote(vote, dataServerId); if (quorum.CheckQuorum(vote, original)) { quorumVersion = new LatestVersion(vote, quorum.DataServersIds(vote)); break; } } // found the quorum file if (quorumVersion != null) { break; } // if there are still pending requests // dont create new ones if (requests > 0) { continue; } // if all the votes arrived at the quorum // stops when all requests are counted (requests = 0) if (quorum.Count == (requests + quorum.Count)) { // get possible new fileMetadata locations // possible optimization // check if there are no data servers fileMetadata = OpenFileMetadata(filename); // broadcast to all dataServers that have that file foreach (var entry in fileMetadata.Locations) { string id = entry.Key; string location = entry.Value; string localFilename = fileMetadata.LocalFilenames[id]; // increment right away so it doesn't request untill its decremented Interlocked.Increment(ref requests); Thread request = new Thread(() => { IDataServerToClient dataServer = (IDataServerToClient)Activator.GetObject( typeof(IDataServerToClient), location); FileVersion fileVersion = null; try { fileVersion = dataServer.Version(localFilename); } catch (ProcessFailedException) { } catch (ProcessFreezedException) { } finally { reads[id] = fileVersion; Interlocked.Decrement(ref requests); } }); request.Start(); } } } return(quorumVersion); }