Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DWS | Task 1 | Ершов Вадим #19

Merged
merged 13 commits into from
Mar 2, 2024
8 changes: 8 additions & 0 deletions src/main/java/ru/vk/itmo/test/vadimershov/DaoException.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package ru.vk.itmo.test.vadimershov;

public class DaoException extends RuntimeException {

public DaoException(Throwable cause) {
super(cause);
}
}
139 changes: 139 additions & 0 deletions src/main/java/ru/vk/itmo/test/vadimershov/DaoHttpServer.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
package ru.vk.itmo.test.vadimershov;

import one.nio.http.HttpServer;
import one.nio.http.HttpServerConfig;
import one.nio.http.HttpSession;
import one.nio.http.Param;
import one.nio.http.Path;
import one.nio.http.Request;
import one.nio.http.RequestMethod;
import one.nio.http.Response;
import one.nio.server.AcceptorConfig;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import ru.vk.itmo.ServiceConfig;
import ru.vk.itmo.dao.Dao;
import ru.vk.itmo.dao.Entry;
import ru.vk.itmo.test.reference.dao.ReferenceDao;

import java.io.IOException;
import java.lang.foreign.MemorySegment;
import java.util.Set;
import java.util.function.Supplier;

import static ru.vk.itmo.test.vadimershov.utils.MemorySegmentUtil.toByteArray;
import static ru.vk.itmo.test.vadimershov.utils.MemorySegmentUtil.toDeletedEntity;
import static ru.vk.itmo.test.vadimershov.utils.MemorySegmentUtil.toEntity;
import static ru.vk.itmo.test.vadimershov.utils.MemorySegmentUtil.toMemorySegment;

public class DaoHttpServer extends HttpServer {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Не хватает тут обработок неожиданных ошибок, если вдруг упадет ошибка при обработке, то что мы показывали на предыдущем занятии


private static final Set<Integer> SUPPORTED_METHODS = Set.of(
Request.METHOD_GET,
Request.METHOD_PUT,
Request.METHOD_DELETE
);

private final Logger logger = LoggerFactory.getLogger(DaoHttpServer.class);

private final Dao<MemorySegment, Entry<MemorySegment>> dao;

public DaoHttpServer(ServiceConfig config, ReferenceDao dao) throws IOException {
super(getHttpServerConfig(config));
this.dao = dao;
}

private static HttpServerConfig getHttpServerConfig(ServiceConfig config) {
HttpServerConfig httpServerConfig = new HttpServerConfig();
AcceptorConfig acceptorConfig = new AcceptorConfig();
acceptorConfig.port = config.selfPort();
acceptorConfig.reusePort = true;
httpServerConfig.acceptors = new AcceptorConfig[]{acceptorConfig};
httpServerConfig.closeSessions = true;
return httpServerConfig;
}

@Override
public void handleDefault(Request request, HttpSession session) throws IOException {
Response response = isSupportedMethod(request.getMethod())
? new Response(Response.BAD_REQUEST, Response.EMPTY)
: new Response(Response.METHOD_NOT_ALLOWED, Response.EMPTY);
session.sendResponse(response);
}

private boolean isSupportedMethod(int httpMethod) {
return SUPPORTED_METHODS.contains(httpMethod);
}

@Override
public void handleRequest(Request request, HttpSession session) throws IOException {
try {
super.handleRequest(request, session);
} catch (DaoException e) {
logger.error(e.getMessage());
session.sendResponse(new Response(Response.INTERNAL_ERROR, Response.EMPTY));
} catch (Exception e) {
logger.error(e.getMessage());
session.sendResponse(new Response(Response.BAD_REQUEST, Response.EMPTY));
}
}

@Path("/v0/entity")
@RequestMethod(Request.METHOD_GET)
public Response getMapping(
@Param(value = "id", required = true) String id
) {
return handleDaoException(() -> {
if (id.isBlank()) {
return new Response(Response.BAD_REQUEST, Response.EMPTY);
}

Entry<MemorySegment> entry = dao.get(toMemorySegment(id));
if (entry == null) {
return new Response(Response.NOT_FOUND, Response.EMPTY);
}

byte[] value = toByteArray(entry.value());
return Response.ok(value);
});
}

@Path("/v0/entity")
@RequestMethod(Request.METHOD_PUT)
public Response upsertMapping(
@Param(value = "id", required = true) String id,
Request request
) {
return handleDaoException(() -> {
if (id.isBlank() || request.getBody() == null) {
return new Response(Response.BAD_REQUEST, Response.EMPTY);
}

dao.upsert(toEntity(id, request.getBody()));
return new Response(Response.CREATED, Response.EMPTY);
});
}

@Path("/v0/entity")
@RequestMethod(Request.METHOD_DELETE)
public Response deleteMapping(
@Param(value = "id", required = true) String id
) {
return handleDaoException(() -> {
if (id.isBlank()) {
return new Response(Response.BAD_REQUEST, Response.EMPTY);
}
dao.upsert(toDeletedEntity(id));
return new Response(Response.ACCEPTED, Response.EMPTY);
});
}

private Response handleDaoException(Supplier<Response> supplier) {
try {
return supplier.get();
} catch (Exception e) {
throw new DaoException(e);
}
}

}
29 changes: 29 additions & 0 deletions src/main/java/ru/vk/itmo/test/vadimershov/Main.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package ru.vk.itmo.test.vadimershov;

import ru.vk.itmo.ServiceConfig;
import ru.vk.itmo.dao.Config;
import ru.vk.itmo.test.reference.dao.ReferenceDao;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.List;

public final class Main {

private Main() {
}

public static void main(String[] args) throws IOException {
Path daoDataPath = Path.of("/Users/ruarsv5/Developer/ITMO/sem-2/highload/src/test/dao_data");
Files.createDirectories(daoDataPath);

ReferenceDao referenceDao = new ReferenceDao(new Config(daoDataPath, 1 << 15));

String url = "localhost";
ServiceConfig serviceConfig = new ServiceConfig(8080, url, List.of(url), daoDataPath);

DaoHttpServer server = new DaoHttpServer(serviceConfig, referenceDao);
server.start();
}
}
63 changes: 63 additions & 0 deletions src/main/java/ru/vk/itmo/test/vadimershov/ServiceImpl.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
package ru.vk.itmo.test.vadimershov;

import one.nio.http.HttpServer;
import ru.vk.itmo.Service;
import ru.vk.itmo.ServiceConfig;
import ru.vk.itmo.dao.Config;
import ru.vk.itmo.test.ServiceFactory;
import ru.vk.itmo.test.reference.dao.ReferenceDao;

import java.io.IOException;
import java.io.UncheckedIOException;
import java.util.concurrent.CompletableFuture;

public class ServiceImpl implements Service {

private final Config daoConfig;
private final ServiceConfig config;
private ReferenceDao dao;
private HttpServer server;

private boolean isRun;

public ServiceImpl(ServiceConfig config) throws IOException {
int flushThresholdBytes = 1 << 11;
this.config = config;
this.daoConfig = new Config(config.workingDir(), flushThresholdBytes);
}

@Override
public synchronized CompletableFuture<Void> start() throws IOException {
if (isRun) {
return CompletableFuture.completedFuture(null);
}
dao = new ReferenceDao(daoConfig);
server = new DaoHttpServer(config, dao);
server.start();
isRun = true;
return CompletableFuture.completedFuture(null);
}

@Override
public synchronized CompletableFuture<Void> stop() throws IOException {
if (!isRun) {
return CompletableFuture.completedFuture(null);
}
server.stop();
dao.close();
isRun = false;
return CompletableFuture.completedFuture(null);
}

@ServiceFactory(stage = 1)
public static class Factory implements ServiceFactory.Factory {
@Override
public Service create(ServiceConfig config) {
try {
return new ServiceImpl(config);
} catch (IOException e) {
throw new UncheckedIOException(e);
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package ru.vk.itmo.test.vadimershov.utils;

import ru.vk.itmo.dao.BaseEntry;
import ru.vk.itmo.dao.Entry;

import javax.annotation.Nonnull;
import java.lang.foreign.MemorySegment;
import java.lang.foreign.ValueLayout;
import java.nio.charset.StandardCharsets;

public final class MemorySegmentUtil {

private MemorySegmentUtil() {
}

public static MemorySegment toMemorySegment(@Nonnull String data) {
return MemorySegment.ofArray(data.getBytes(StandardCharsets.UTF_8));
}

public static Entry<MemorySegment> toDeletedEntity(@Nonnull String key) {
return new BaseEntry<>(toMemorySegment(key), null);
}

public static Entry<MemorySegment> toEntity(@Nonnull String key, @Nonnull byte[] value) {
return new BaseEntry<>(toMemorySegment(key), MemorySegment.ofArray(value));
}

public static byte[] toByteArray(@Nonnull MemorySegment data) {
return data.toArray(ValueLayout.JAVA_BYTE);
}

}
Loading
Loading