Skip to content
This repository has been archived by the owner on Dec 8, 2024. It is now read-only.

Commit

Permalink
Added TFD Project
Browse files Browse the repository at this point in the history
  • Loading branch information
Radnar9 committed Aug 7, 2023
1 parent 9047d01 commit 110e9bd
Show file tree
Hide file tree
Showing 34 changed files with 2,076 additions and 0 deletions.
121 changes: 121 additions & 0 deletions TFD-Project/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
lerna-debug.log*

# Diagnostic reports (https://nodejs.org/api/report.html)
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json

# Runtime data
pids
*.pid
*.seed
*.pid.lock

# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov

# Coverage directory used by tools like istanbul
coverage
*.lcov

# nyc test coverage
.nyc_output

# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
.grunt

# Bower dependency directory (https://bower.io/)
bower_components

# node-waf configuration
.lock-wscript

# Compiled binary addons (https://nodejs.org/api/addons.html)
build/Release

# Dependency directories
node_modules/
jspm_packages/

# TypeScript v1 declaration files
typings/

# TypeScript cache
*.tsbuildinfo

# Optional npm cache directory
.npm

# Optional eslint cache
.eslintcache

# Microbundle cache
.rpt2_cache/
.rts2_cache_cjs/
.rts2_cache_es/
.rts2_cache_umd/

# Optional REPL history
.node_repl_history

# Output of 'npm pack'
*.tgz

# Yarn Integrity file
.yarn-integrity

# dotenv environment variables file
.env
.env.test

# parcel-bundler cache (https://parceljs.org/)
.cache

# Next.js build output
.next

# Nuxt.js build / generate output
.nuxt
dist

# Gatsby files
.cache/
# Comment in the public line in if your project uses Gatsby and *not* Next.js
# https://nextjs.org/blog/next-9-1#public-directory-support
# public

# vuepress build output
.vuepress/dist

# Serverless directories
.serverless/

# FuseBox cache
.fusebox/

# DynamoDB Local files
.dynamodb/

# TernJS port file
.tern-port

# Gradle

.gradle
/build/
!gradle/wrapper/gradle-wrapper.jar

### IntelliJ IDEA ###
/target/
*/target/**
.idea
*.iws
*.iml
*.ipr
**/out
**/bin
**/build
25 changes: 25 additions & 0 deletions TFD-Project/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# Project Configurations

The main directory of the project is divided into 3 other directories, each with its own responsibilities:

- `Client`: This directory corresponds to the client-side library that allows clients to connect and access the service, namely, invoke operations.
- `Replica`: This directory contains the Raft algorithm implementation.
- `ReplicaContract`: This directory represents the contract where all the necessary objects and operations for communication are defined.

To run the project, start by installing the `ReplicaContract`. Next, start up the `Replicas`, and finally, execute the `Client` to invoke operations.

### Replica
To run each replica, first **obtain its JAR** through Maven, and then execute the following command to start it up. Since the config file has only 5 IPs, if you don't change it, there can be a maximum of 5 replicas (0 <= `id` <= 4). The config file allows the client and the replicas to know the IP addresses of the other replicas. The log file corresponds to the mechanism of log replication. In case the replica goes down, it can easily recover its state and update its log.

```bash
java -jar Replica-1.0-jar-with-dependencies.jar <id(>= 0)> <configFile(absolute path)> <logFile(absolute path)>
```

### Client
To run the client, start by obtaining its JAR the same way as before, and then execute the following command after inserting the absolute path for the desired config file.

```bash
java -jar Client.jar <configFile(absolute path)>
```

The text has been revised for clarity, consistency, and correctness.
76 changes: 76 additions & 0 deletions TFD-Project/code/Client/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<groupId>org.example</groupId>
<artifactId>Client</artifactId>
<version>1.0-SNAPSHOT</version>

<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<java.version>11</java.version>
<maven.compiler.source>${java.version}</maven.compiler.source>
<maven.compiler.target>${java.version}</maven.compiler.target>
</properties>

<dependencies>
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-netty-shaded</artifactId>
<version>1.45.1</version>
</dependency>
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-protobuf</artifactId>
<version>1.45.1</version>
</dependency>
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-stub</artifactId>
<version>1.45.1</version>
</dependency>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.10</version>
</dependency>
<dependency>
<groupId>fcul.tfd</groupId>
<artifactId>ReplicaContract</artifactId>
<version>1.0</version>
</dependency>
</dependencies>

<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>3.1.1</version>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
<archive>
<manifest>
<mainClass>Client</mainClass>
</manifest>
</archive>
</configuration>
<executions>
<execution>
<id>assemble-all</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>


</project>
136 changes: 136 additions & 0 deletions TFD-Project/code/Client/src/main/java/org/example/Client.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
package org.example;

import com.google.protobuf.ByteString;
import com.google.protobuf.Timestamp;
import io.grpc.ManagedChannel;
import io.grpc.ManagedChannelBuilder;
import replica.Request;
import replica.Result;
import replica.ServerGrpc;

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.time.Instant;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;

public class Client {
private static final int MINIMUM = 1;
private static final int MAXIMUM = 6;
private static final int INT_SIZE = 4;
public static final int CLIENT_ID = -1;
public static final int WAITING_TIME = 5000;
private static final String INCREASE_LABEL = "increaseBy";

private static int current_leader = 2;

private static final List<Pair<ReplicaAddress, ServerGrpc.ServerBlockingStub>> replicas = new ArrayList<>();

public static void main(String[] args) {

if (args.length < 1) {
System.out.println("Usage: java -jar Client.jar <configFile(absolute path)>");
System.exit(-1);
}

try {
initClient(args[0]);
sendCommands();
} catch (Exception e) {
throw new RuntimeException(e);
}
}

private static void sendCommands() {
Request request = createRequestMessage();
boolean reset = false;
while (true) {
try {
System.out.println("Sending command to replica " + current_leader);
Result response = replicas.get(current_leader).getSecond().request(request);

System.out.println("Response arrived: " + response.getResultMessage());

if (response.getId() == -1) {
return;
}
if (response.getId() != current_leader) {
current_leader = response.getId();
System.out.println("Switched leader to: " + current_leader);
} else {
Thread.sleep(WAITING_TIME);
request = createRequestMessage();
}
} catch (Exception e){
if(current_leader > 0 && !reset) {
current_leader = 0;
reset = true;
} else {
current_leader++;
if (current_leader == replicas.size()) {
System.out.println("No available replicas to be found, exiting..");
System.exit(-1);
}
}
System.out.println("No reply from replica or crash occurred, attempting communication with other known replica (" + current_leader + ")");
}

}
}

private static Request createRequestMessage() {
System.out.println("Create request message called");
Random rand = new Random();
int value = rand.nextInt(MAXIMUM - MINIMUM) + MINIMUM;
System.out.println("Random value generated: "+ value);
byte[] data = ByteBuffer.allocate(INT_SIZE).putInt(value).array();
return Request.newBuilder()
.setId(CLIENT_ID)
.setLabel(INCREASE_LABEL)
.setData(ByteString.copyFrom(data))
.setTimestamp(getInstantTimestamp())
.build();
}

private static Timestamp getInstantTimestamp() {
var timestamp = java.sql.Timestamp.from(Instant.now());
return Timestamp.newBuilder().setSeconds(timestamp.getTime()).setNanos(timestamp.getNanos()).build();
}

private static void initClient(String configFilePath) throws IOException {
readConfigFile(configFilePath);
}

/**
* Reads each line from the file provided and stores for each line the ReplicaAddress and the stub channel in a pair
* of the list replicas
*
* @param configFilePath absolute path to the configuration text file with the replicas' addresses
* @throws IOException in case an I/O error occurs
*/
private static void readConfigFile(String configFilePath) throws IOException {
try (BufferedReader br = new BufferedReader(new FileReader(configFilePath))) {
String address;
ReplicaAddress replicaAddress;
while ((address = br.readLine()) != null) {
replicaAddress = new ReplicaAddress(address);
replicas.add(new Pair<>(replicaAddress, initStub(replicaAddress)) // To not initiate a client stub to itself
);
}
}
}

/**
* Initializes the client communication channel
*
* @param replicaAddress address of the replica to establish the connection
* @return the stub created
*/
private static ServerGrpc.ServerBlockingStub initStub(ReplicaAddress replicaAddress) {
ManagedChannel channel = ManagedChannelBuilder.forAddress(replicaAddress.getIp(), replicaAddress.getPort()).usePlaintext().build();
return ServerGrpc.newBlockingStub(channel);
}
}
23 changes: 23 additions & 0 deletions TFD-Project/code/Client/src/main/java/org/example/Pair.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package org.example;
public class Pair<K, V> {
private final K first;
private final V second;

public Pair(K first, V second) {
this.first = first;
this.second = second;
}

public K getFirst() {
return first;
}

public V getSecond() {
return second;
}

@Override
public String toString() {
return "(" + first + ", " + second + ")";
}
}
Loading

0 comments on commit 110e9bd

Please sign in to comment.