Skip to content

Commit 65c4763

Browse files
author
vitaliy.emelyanov
committed
Stage 1
Signed-off-by: vitaliy.emelyanov <vitaliy.emelyanov@yadro.com>
1 parent e22da0c commit 65c4763

File tree

10 files changed

+5279
-0
lines changed

10 files changed

+5279
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
package ru.vk.itmo.test.emelyanovvitaliy;
2+
3+
import one.nio.http.*;
4+
import one.nio.server.AcceptorConfig;
5+
import ru.vk.itmo.ServiceConfig;
6+
import ru.vk.itmo.dao.BaseEntry;
7+
import ru.vk.itmo.dao.Config;
8+
import ru.vk.itmo.dao.Entry;
9+
import ru.vk.itmo.test.reference.dao.ReferenceDao;
10+
11+
import java.io.IOException;
12+
import java.io.UncheckedIOException;
13+
import java.lang.foreign.MemorySegment;
14+
import java.lang.foreign.ValueLayout;
15+
import java.nio.charset.StandardCharsets;
16+
17+
import static one.nio.http.Request.*;
18+
19+
public class DhtServer extends HttpServer {
20+
public static final byte[] EMPTY_BODY = new byte[0];
21+
private final ReferenceDao dao;
22+
public DhtServer(ServiceConfig config) throws IOException {
23+
super(createConfig(config));
24+
dao = new ReferenceDao(new Config(config.workingDir(), 1 << 24));
25+
}
26+
27+
@Override
28+
public synchronized void stop() {
29+
super.stop();
30+
try {
31+
dao.close();
32+
} catch (IOException e) {
33+
throw new UncheckedIOException(e);
34+
}
35+
}
36+
37+
@RequestMethod(METHOD_GET)
38+
@Path("/v0/entity")
39+
public Response entity(@Param(value = "id") String id) {
40+
if (isKeyIncorrect(id)) {
41+
return new Response(Response.BAD_REQUEST, EMPTY_BODY);
42+
}
43+
Entry<MemorySegment> entry = dao.get(keyFor(id));
44+
if (entry == null) {
45+
return new Response(Response.NOT_FOUND, EMPTY_BODY);
46+
}
47+
return new Response(Response.OK, valueFor(entry));
48+
}
49+
50+
@RequestMethod(METHOD_PUT)
51+
@Path("/v0/entity")
52+
public Response putEntity(@Param(value = "id") String id, Request request) {
53+
if (isKeyIncorrect(id)) {
54+
return new Response(Response.BAD_REQUEST, EMPTY_BODY);
55+
}
56+
dao.upsert(new BaseEntry<>(keyFor(id), MemorySegment.ofArray(request.getBody())));
57+
return new Response(Response.CREATED, EMPTY_BODY);
58+
}
59+
60+
@RequestMethod(METHOD_DELETE)
61+
@Path("/v0/entity")
62+
public Response deleteEntity(@Param("id") String id) {
63+
if (isKeyIncorrect(id)) {
64+
return new Response(Response.BAD_REQUEST, EMPTY_BODY);
65+
}
66+
dao.upsert(new BaseEntry<>(keyFor(id), null));
67+
return new Response(Response.ACCEPTED, EMPTY_BODY);
68+
}
69+
70+
@Override
71+
public void handleDefault(Request request, HttpSession session) throws IOException {
72+
int requestMethod = request.getMethod();
73+
if (requestMethod != METHOD_GET && requestMethod != METHOD_PUT && requestMethod != METHOD_DELETE) {
74+
session.sendResponse(new Response(Response.METHOD_NOT_ALLOWED, EMPTY_BODY));
75+
} else {
76+
session.sendResponse(new Response(Response.BAD_REQUEST, EMPTY_BODY));
77+
}
78+
}
79+
80+
private static boolean isKeyIncorrect(String key) {
81+
return key == null || key.isEmpty();
82+
}
83+
84+
private static HttpServerConfig createConfig(ServiceConfig serviceConfig) {
85+
HttpServerConfig config = new HttpServerConfig();
86+
AcceptorConfig acceptorConfig = new AcceptorConfig();
87+
acceptorConfig.port = serviceConfig.selfPort();
88+
config.acceptors = new AcceptorConfig[] {acceptorConfig};
89+
config.closeSessions = true;
90+
return config;
91+
}
92+
93+
private static MemorySegment keyFor(String id) {
94+
return MemorySegment.ofArray(id.getBytes(StandardCharsets.UTF_8));
95+
}
96+
97+
private static byte[] valueFor(Entry<MemorySegment> entry) {
98+
return entry.value().toArray(ValueLayout.JAVA_BYTE);
99+
}
100+
101+
102+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
package ru.vk.itmo.test.emelyanovvitaliy;
2+
3+
import ru.vk.itmo.Service;
4+
import ru.vk.itmo.ServiceConfig;
5+
import ru.vk.itmo.test.ServiceFactory;
6+
7+
import java.io.IOException;
8+
import java.io.UncheckedIOException;
9+
import java.util.concurrent.CompletableFuture;
10+
11+
public class DhtService implements Service {
12+
private final ServiceConfig serviceConfig;
13+
private DhtServer server;
14+
public DhtService(ServiceConfig serviceConfig) {
15+
this.serviceConfig = serviceConfig;
16+
}
17+
@Override
18+
public CompletableFuture<Void> start() throws IOException {
19+
server = new DhtServer(serviceConfig);
20+
server.start();
21+
return CompletableFuture.completedFuture(null);
22+
}
23+
24+
@Override
25+
public CompletableFuture<Void> stop() throws IOException {
26+
server.stop();
27+
server = null;
28+
return CompletableFuture.completedFuture(null);
29+
}
30+
31+
@ServiceFactory(stage = 1)
32+
public static class Factory implements ServiceFactory.Factory {
33+
34+
@Override
35+
public Service create(ServiceConfig config) {
36+
return new DhtService(config);
37+
}
38+
}
39+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
package ru.vk.itmo.test.emelyanovvitaliy;
2+
3+
import ru.vk.itmo.ServiceConfig;
4+
5+
import java.io.IOException;
6+
import java.nio.file.Files;
7+
import java.nio.file.Paths;
8+
import java.util.ArrayList;
9+
import java.util.List;
10+
11+
public class TestServerRunner {
12+
public static void main(String[] args) throws IOException {
13+
DhtServer server = new DhtServer(
14+
new ServiceConfig(
15+
8080,
16+
"http://localhost",
17+
List.of("http://localhost"),
18+
Files.createTempDirectory(".")
19+
)
20+
);
21+
server.start();
22+
}
23+
}

0 commit comments

Comments
 (0)