Browse Source

Add search functionality to hosted resources

hosted-resources-search
proto 3 years ago
parent
commit
a3753c01bc
  1. 16
      src/main/java/org/qortal/api/resource/ArbitraryResource.java
  2. 58
      src/main/java/org/qortal/controller/arbitrary/ArbitraryDataStorageManager.java

16
src/main/java/org/qortal/api/resource/ArbitraryResource.java

@ -432,14 +432,24 @@ public class ArbitraryResource {
@HeaderParam(Security.API_KEY_HEADER) String apiKey, @HeaderParam(Security.API_KEY_HEADER) String apiKey,
@Parameter(description = "Include status") @QueryParam("includestatus") Boolean includeStatus, @Parameter(description = "Include status") @QueryParam("includestatus") Boolean includeStatus,
@Parameter(ref = "limit") @QueryParam("limit") Integer limit, @Parameter(ref = "limit") @QueryParam("limit") Integer limit,
@Parameter(ref = "offset") @QueryParam("offset") Integer offset) { @Parameter(ref = "offset") @QueryParam("offset") Integer offset,
@Parameter(ref = "query") @QueryParam("query") String query) {
Security.checkApiCallAllowed(request); Security.checkApiCallAllowed(request);
List<ArbitraryResourceInfo> resources = new ArrayList<>(); List<ArbitraryResourceInfo> resources = new ArrayList<>();
try (final Repository repository = RepositoryManager.getRepository()) { try (final Repository repository = RepositoryManager.getRepository()) {
List<ArbitraryTransactionData> transactionDataList;
if(query.equals("")){
transactionDataList = ArbitraryDataStorageManager.getInstance().listAllHostedTransactions(repository, limit, offset);
}else{
transactionDataList = ArbitraryDataStorageManager.getInstance().searchHostedTransactions(repository,query, limit, offset);
}
List<ArbitraryTransactionData> transactionDataList = ArbitraryDataStorageManager.getInstance().listAllHostedTransactions(repository, limit, offset);
for (ArbitraryTransactionData transactionData : transactionDataList) { for (ArbitraryTransactionData transactionData : transactionDataList) {
ArbitraryResourceInfo arbitraryResourceInfo = new ArbitraryResourceInfo(); ArbitraryResourceInfo arbitraryResourceInfo = new ArbitraryResourceInfo();
arbitraryResourceInfo.name = transactionData.getName(); arbitraryResourceInfo.name = transactionData.getName();
@ -461,6 +471,8 @@ public class ArbitraryResource {
} }
} }
@DELETE @DELETE
@Path("/resource/{service}/{name}/{identifier}") @Path("/resource/{service}/{name}/{identifier}")
@Operation( @Operation(

58
src/main/java/org/qortal/controller/arbitrary/ArbitraryDataStorageManager.java

@ -47,6 +47,9 @@ public class ArbitraryDataStorageManager extends Thread {
private List<ArbitraryTransactionData> hostedTransactions; private List<ArbitraryTransactionData> hostedTransactions;
private String searchQuery;
private List<ArbitraryTransactionData> searchResultsTransactions;
private static final long DIRECTORY_SIZE_CHECK_INTERVAL = 10 * 60 * 1000L; // 10 minutes private static final long DIRECTORY_SIZE_CHECK_INTERVAL = 10 * 60 * 1000L; // 10 minutes
/** Treat storage as full at 90% usage, to reduce risk of going over the limit. /** Treat storage as full at 90% usage, to reduce risk of going over the limit.
@ -301,6 +304,61 @@ public class ArbitraryDataStorageManager extends Thread {
return ArbitraryTransactionUtils.limitOffsetTransactions(arbitraryTransactionDataList, limit, offset); return ArbitraryTransactionUtils.limitOffsetTransactions(arbitraryTransactionDataList, limit, offset);
} }
/**
* searchHostedTransactions
* Allow to run a query against hosted data names and return matches if there are any
* @param repository
* @param query
* @param limit
* @param offset
* @return
*/
public List<ArbitraryTransactionData> searchHostedTransactions(Repository repository, String query, Integer limit, Integer offset) {
// Load from cache if we can (results that exists for the same query), to avoid disk reads
if (this.searchResultsTransactions != null && this.searchQuery.equals(query.toLowerCase())) {
return ArbitraryTransactionUtils.limitOffsetTransactions(this.searchResultsTransactions, limit, offset);
}
this.searchQuery=query.toLowerCase();//set the searchQuery so that it can be checked on the next call
List<ArbitraryTransactionData> searchResultsList = new ArrayList<>();
// Find all hosted paths
List<Path> allPaths = this.findAllHostedPaths();
// Loop through each path and attempt to match it to a signature, and check if it's a match with our search query
for (Path path : allPaths) {
try {
String[] contents = path.toFile().list();
if (contents == null || contents.length == 0) {
// Ignore empty directories
continue;
}
String signature58 = path.getFileName().toString();
byte[] signature = Base58.decode(signature58);
TransactionData transactionData = repository.getTransactionRepository().fromSignature(signature);
if (transactionData == null || transactionData.getType() != Transaction.TransactionType.ARBITRARY) {
continue;
}
ArbitraryTransactionData arbitraryTransactionData =(ArbitraryTransactionData) transactionData;
if(arbitraryTransactionData.getName().toLowerCase().contains(this.searchQuery) || arbitraryTransactionData.getIdentifier().toLowerCase().contains(this.searchQuery))
searchResultsList.add(arbitraryTransactionData);
} catch (DataException e) {
continue;
}
}
// Sort by newest first
searchResultsList.sort(Comparator.comparingLong(ArbitraryTransactionData::getTimestamp).reversed());
// Update cache
this.searchResultsTransactions = searchResultsList;
return ArbitraryTransactionUtils.limitOffsetTransactions(this.searchResultsTransactions, limit, offset);
}
/** /**
* Warning: this method will walk through the entire data directory * Warning: this method will walk through the entire data directory

Loading…
Cancel
Save