diff --git a/adastor.iml b/adastor.iml
index 7d71d4f..bd4e95b 100644
--- a/adastor.iml
+++ b/adastor.iml
@@ -90,6 +90,7 @@
+
diff --git a/adastor.ipr b/adastor.ipr
index 91733a9..2a334d9 100644
--- a/adastor.ipr
+++ b/adastor.ipr
@@ -13,6 +13,15 @@
+
+
+ hsqldb.local
+ true
+ true
+ org.hsqldb.jdbc.JDBCDriver
+ jdbc:hsqldb:file:$PROJECT_DIR$/database/adastor
+
+
@@ -167,6 +176,16 @@
+
+
+
+ "
+
+
+ master_key
+ sa
+
+
@@ -883,6 +902,17 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/pom.xml b/pom.xml
index 6dfa25e..b2c81e6 100644
--- a/pom.xml
+++ b/pom.xml
@@ -42,6 +42,12 @@
hsqldb
+
+ org.modelmapper
+ modelmapper
+ 2.3.2
+
+
org.springframework.boot
spring-boot-starter-jetty
diff --git a/src/main/java/ru/bvn13/adastor/config/Config.java b/src/main/java/ru/bvn13/adastor/config/Config.java
index 33b4939..9962d31 100644
--- a/src/main/java/ru/bvn13/adastor/config/Config.java
+++ b/src/main/java/ru/bvn13/adastor/config/Config.java
@@ -4,6 +4,7 @@ import lombok.Getter;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
+import javax.annotation.PostConstruct;
import java.io.File;
/**
@@ -16,9 +17,38 @@ public class Config {
private String storagePath;
@Getter
+ // #{new Integer.parseInt('${api.orders.pingFrequency}')}
@Value("${adastor.storage.space.free}")
private Long freeSpace;
+ @Getter
+ @Value("${adastor.max-size}")
+ private Long maxSize;
+
+ @Getter
+ @Value("${adastor.min-days-storing}")
+ private Long minDaysStoring;
+
+ @Getter
+ @Value("${adastor.max-days-storing}")
+ private Long maxDaysStoring;
+
+ @PostConstruct
+ public void checkParams() {
+ if (storagePath == null || storagePath.isEmpty()) {
+ throw new IllegalArgumentException("Storage path is not specified!");
+ }
+ if (freeSpace == null || freeSpace.equals(0L)) {
+ throw new IllegalArgumentException("Free space is not specified!");
+ }
+ if (maxSize == null || maxSize.equals(0L)) {
+ throw new IllegalArgumentException("Max size is not specified!");
+ }
+ if (maxDaysStoring == null || maxDaysStoring.equals(0L)) {
+ throw new IllegalArgumentException("Max days storing is not specified!");
+ }
+ }
+
public String getStoragePath() {
String absStoragePath = storagePath.startsWith(".") ? new File("").getAbsolutePath() + storagePath.substring(1) : storagePath;
File path = new File(absStoragePath);
diff --git a/src/main/java/ru/bvn13/adastor/config/WebConfig.java b/src/main/java/ru/bvn13/adastor/config/WebConfig.java
index 3371510..18ca59d 100644
--- a/src/main/java/ru/bvn13/adastor/config/WebConfig.java
+++ b/src/main/java/ru/bvn13/adastor/config/WebConfig.java
@@ -1,5 +1,7 @@
package ru.bvn13.adastor.config;
+import org.modelmapper.ModelMapper;
+import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
@@ -8,5 +10,9 @@ import org.springframework.context.annotation.Configuration;
@Configuration
public class WebConfig {
+ @Bean
+ public ModelMapper modelMapper() {
+ return new ModelMapper();
+ }
}
diff --git a/src/main/java/ru/bvn13/adastor/entities/Stortion.java b/src/main/java/ru/bvn13/adastor/entities/Stortion.java
index 74fafdb..a864245 100644
--- a/src/main/java/ru/bvn13/adastor/entities/Stortion.java
+++ b/src/main/java/ru/bvn13/adastor/entities/Stortion.java
@@ -4,10 +4,13 @@ import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
+import org.springframework.beans.factory.annotation.Autowired;
+import ru.bvn13.adastor.config.Config;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
+import javax.persistence.Transient;
import java.time.LocalDateTime;
/**
diff --git a/src/main/java/ru/bvn13/adastor/entities/dtos/StortionDto.java b/src/main/java/ru/bvn13/adastor/entities/dtos/StortionDto.java
new file mode 100644
index 0000000..4f645a5
--- /dev/null
+++ b/src/main/java/ru/bvn13/adastor/entities/dtos/StortionDto.java
@@ -0,0 +1,31 @@
+package ru.bvn13.adastor.entities.dtos;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+
+import javax.persistence.Transient;
+import java.time.LocalDateTime;
+
+/**
+ * @author boykovn at 12.03.2019
+ */
+@Getter
+@Setter
+@AllArgsConstructor
+@NoArgsConstructor
+public class StortionDto {
+
+ private String uuid;
+
+ private LocalDateTime storeDate;
+
+ private long size;
+
+ private String path;
+
+ @Transient
+ private long retention;
+
+}
diff --git a/src/main/java/ru/bvn13/adastor/web/controllers/TestController.java b/src/main/java/ru/bvn13/adastor/web/controllers/TestController.java
new file mode 100644
index 0000000..e55a7cf
--- /dev/null
+++ b/src/main/java/ru/bvn13/adastor/web/controllers/TestController.java
@@ -0,0 +1,36 @@
+package ru.bvn13.adastor.web.controllers;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.ResponseBody;
+import ru.bvn13.adastor.entities.Stortion;
+import ru.bvn13.adastor.entities.dtos.StortionDto;
+import ru.bvn13.adastor.web.repositories.StortionRepository;
+import ru.bvn13.adastor.web.services.StortionService;
+
+import java.util.stream.Stream;
+
+/**
+ * @author boykovn at 12.03.2019
+ */
+@Controller
+public class TestController {
+
+ private StortionService stortionService;
+
+ @Autowired
+ public void setStortionRepository(StortionService stortionService) {
+ this.stortionService = stortionService;
+ }
+
+ @GetMapping("/t")
+ public @ResponseBody String test() {
+
+ Stream stortions = stortionService.findAllSortedByRetention();
+ stortions.forEach(st -> System.out.println(String.format("%s - %s - %s - %s", st.getUuid(), st.getStoreDate(), st.getSize(), st.getRetention())));
+
+ return "done";
+ }
+
+}
diff --git a/src/main/java/ru/bvn13/adastor/web/controllers/UploadController.java b/src/main/java/ru/bvn13/adastor/web/controllers/UploadController.java
index 085f65b..9788287 100644
--- a/src/main/java/ru/bvn13/adastor/web/controllers/UploadController.java
+++ b/src/main/java/ru/bvn13/adastor/web/controllers/UploadController.java
@@ -4,7 +4,7 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.ResponseBody;
-import ru.bvn13.adastor.entities.Stortion;
+import ru.bvn13.adastor.entities.dtos.StortionDto;
import ru.bvn13.adastor.web.services.StortionService;
import javax.servlet.http.HttpServletRequest;
@@ -24,7 +24,8 @@ public class UploadController {
}
@PostMapping(value="/a", produces = {"application/json"})
- public @ResponseBody Stortion uploadData(HttpServletRequest request) throws IOException {
+ public @ResponseBody
+ StortionDto uploadData(HttpServletRequest request) throws IOException {
return stortionService.createStortion(request.getInputStream());
}
diff --git a/src/main/java/ru/bvn13/adastor/web/repositories/CustomStortionRepository.java b/src/main/java/ru/bvn13/adastor/web/repositories/CustomStortionRepository.java
new file mode 100644
index 0000000..ecefe47
--- /dev/null
+++ b/src/main/java/ru/bvn13/adastor/web/repositories/CustomStortionRepository.java
@@ -0,0 +1,14 @@
+package ru.bvn13.adastor.web.repositories;
+
+import ru.bvn13.adastor.entities.Stortion;
+
+import java.util.stream.Stream;
+
+/**
+ * @author boykovn at 12.03.2019
+ */
+public interface CustomStortionRepository {
+
+ Stream findAllSortedByRetention();
+
+}
diff --git a/src/main/java/ru/bvn13/adastor/web/repositories/StortionRepository.java b/src/main/java/ru/bvn13/adastor/web/repositories/StortionRepository.java
index 534569e..c13e6cf 100644
--- a/src/main/java/ru/bvn13/adastor/web/repositories/StortionRepository.java
+++ b/src/main/java/ru/bvn13/adastor/web/repositories/StortionRepository.java
@@ -8,6 +8,6 @@ import ru.bvn13.adastor.entities.Stortion;
* @author boykovn at 11.03.2019
*/
@Repository
-public interface StortionRepository extends JpaRepository {
+public interface StortionRepository extends JpaRepository, CustomStortionRepository {
}
diff --git a/src/main/java/ru/bvn13/adastor/web/repositories/impl/StortionRepositoryImpl.java b/src/main/java/ru/bvn13/adastor/web/repositories/impl/StortionRepositoryImpl.java
new file mode 100644
index 0000000..428d6b5
--- /dev/null
+++ b/src/main/java/ru/bvn13/adastor/web/repositories/impl/StortionRepositoryImpl.java
@@ -0,0 +1,57 @@
+package ru.bvn13.adastor.web.repositories.impl;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Repository;
+import ru.bvn13.adastor.config.Config;
+import ru.bvn13.adastor.entities.Stortion;
+import ru.bvn13.adastor.web.repositories.CustomStortionRepository;
+
+import javax.persistence.EntityManager;
+import javax.persistence.PersistenceContext;
+import javax.persistence.Query;
+import java.util.stream.Stream;
+
+/**
+ * @author boykovn at 12.03.2019
+ */
+@Repository
+public class StortionRepositoryImpl implements CustomStortionRepository {
+
+ private Config config;
+
+ @Autowired
+ public void setConfig(Config config) {
+ this.config = config;
+ }
+
+
+ @PersistenceContext
+ private EntityManager entityManager;
+
+ /**
+ * RETENTION = min_age + (-max_age + min_age) * pow((file_size / max_size - 1), 3)
+ *
+ * Implemets the query - selecting all stortions ordered by retention ascending
+ *
+ * SELECT * FROM STORTION
+ * ORDER BY 'retention' ASC
+ *
+ * @return queried collection
+ */
+ @Override
+ public Stream findAllSortedByRetention() {
+
+ long min_age = config.getMinDaysStoring();
+ long max_age = config.getMaxDaysStoring();
+ long max_size = config.getMaxSize();
+
+ Query query = entityManager.createQuery("SELECT s FROM Stortion s ORDER BY "
+ +" (CAST(:min_age as double) + (- CAST(:max_age as double) + CAST(:min_age as double)) * POWER((CAST(s.size as double) / CAST(:max_size as double) - 1), 3)) ASC");
+ query.setParameter("min_age", (double)min_age);
+ query.setParameter("max_age", (double)max_age);
+ query.setParameter("max_size", max_size);
+
+ return (Stream) query.getResultStream();
+
+ }
+}
diff --git a/src/main/java/ru/bvn13/adastor/web/services/StortionService.java b/src/main/java/ru/bvn13/adastor/web/services/StortionService.java
index f5a9e9c..189b4b3 100644
--- a/src/main/java/ru/bvn13/adastor/web/services/StortionService.java
+++ b/src/main/java/ru/bvn13/adastor/web/services/StortionService.java
@@ -1,15 +1,18 @@
package ru.bvn13.adastor.web.services;
+import org.modelmapper.ModelMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import ru.bvn13.adastor.config.Config;
import ru.bvn13.adastor.entities.Stortion;
+import ru.bvn13.adastor.entities.dtos.StortionDto;
import ru.bvn13.adastor.web.repositories.StortionRepository;
import java.io.*;
import java.time.LocalDateTime;
import java.util.Optional;
import java.util.UUID;
+import java.util.stream.Stream;
/**
* @author boykovn at 11.03.2019
@@ -19,6 +22,7 @@ public class StortionService {
private StortionRepository stortionRepository;
private Config config;
+ private ModelMapper modelMapper;
@Autowired
public void setStortionRepository(StortionRepository stortionRepository) {
@@ -30,6 +34,11 @@ public class StortionService {
this.config = config;
}
+ @Autowired
+ public void setModelMapper(ModelMapper modelMapper) {
+ this.modelMapper = modelMapper;
+ }
+
public Optional findStortion(String uuid) {
return stortionRepository.findById(uuid);
}
@@ -45,7 +54,7 @@ public class StortionService {
return targetStream;
}
- public Stortion createStortion(InputStream is) throws IOException {
+ public StortionDto createStortion(InputStream is) throws IOException {
String uuid = UUID.randomUUID().toString();
String path = String.format("/%s", uuid);
String fullPath = String.format("%s/%s", config.getStoragePath(), uuid);
@@ -62,7 +71,28 @@ public class StortionService {
stortion.setSize(bytesCount);
stortionRepository.save(stortion);
- return stortion;
+ return convertToDto(stortion);
+ }
+
+ private StortionDto convertToDto(Stortion stortion) {
+ StortionDto stortionDto = modelMapper.map(stortion, StortionDto.class);
+ stortionDto.setRetention(computeRetention(stortion));
+ return stortionDto;
+ }
+
+ public Stream findAllSortedByRetention() {
+ Stream stortions = stortionRepository.findAllSortedByRetention();
+ return stortions.map(this::convertToDto);
+ }
+
+ /**
+ * RETENTION = min_age + (-max_age + min_age) * pow((file_size / max_size - 1), 3)
+ * @return retention
+ */
+ private long computeRetention(Stortion stortion) {
+ double retention = config.getMinDaysStoring()
+ + (-config.getMaxDaysStoring() + config.getMinDaysStoring()) * Math.pow((double) stortion.getSize() / config.getMaxSize() - 1, 3);
+ return Math.round(retention);
}
}
diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties
index 93c027b..295fe16 100644
--- a/src/main/resources/application.properties
+++ b/src/main/resources/application.properties
@@ -1,7 +1,13 @@
#relative or absolute
adastor.storage.path=./storage
-#in Megabytes
-adastor.storage.space.free=100Mb
+#in bytes
+adastor.storage.space.free=200000000
+#max stortion size in bytes
+adastor.max-size=100000000
+#min days storing
+adastor.min-days-storing=30
+#max days storing
+adastor.max-days-storing=356
spring.datasource.driver-class-name=org.hsqldb.jdbc.JDBCDriver
spring.datasource.url=jdbc:hsqldb:file:./database/adastor