Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion src/main/java/module-info.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
/*
* module-info class.
* Copyright (C) 2022 Takayuki Sato. All Rights Reserved.
* Copyright (C) 2022-2023 Takayuki Sato. All Rights Reserved.
*/

/**
* Defines the APIs of the sabi framework.
*/
module sabi {
exports sabi;
Expand Down
98 changes: 90 additions & 8 deletions src/main/java/sabi/DaxBase.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/*
* DaxBase class.
* Copyright (C) 2022 Takayuki Sato. All Rights Reserved.
* Copyright (C) 2022-2023 Takayuki Sato. All Rights Reserved.
*/
package sabi;

Expand All @@ -14,6 +14,17 @@
*/
public abstract class DaxBase {

/**
* An error reason which indicates that some dax sources failed to start up.
*
* @param errors A map of which keys are the registered names of {@link
* DaxSrc}(s) which failed to start up, and of which values are {@link Err}
* having their error reasons.
*
* @param errors A map of {@link DaxSrc} names and {@link Err}(s).
*/
public record FailToStartUpGlobalDaxSrcs(Map<String, Err> errors) {}

/**
* An error reason which indicates that a specified {@link DaxSrc} instance
* is not found.
Expand Down Expand Up @@ -80,10 +91,44 @@ public static synchronized void addGlobalDaxSrc(final String name, final DaxSrc
}

/**
* Makes unable to register any further global {@link DaxSrc}.
* Forbids adding global dax sources and makes available the registered
* global dax sources by calling {@link DaxSrc#setUp} method.
* If even one {@link DaxSrc} fail to execute its {@link DaxSrc#setUp}
* method, this function executes Free methods of all global {@link
* DaxSrc}(s) and throws an {@link Err} object.
*
* @throws Err If even one {@link DaxSrc} failed to execute {@link
* DaxSrc#setUp} method.
*/
public static synchronized void fixGlobalDaxSrcs() {
public static synchronized void startUpGlobalDaxSrcs() throws Err {
isGlobalDaxSrcsFixed = true;

var errors = new HashMap<String, Err>();

for (var entry : globalDaxSrcMap.entrySet()) {
var name = entry.getKey();
var ds = entry.getValue();
try {
ds.setUp();
} catch (Err err) {
errors.put(name, err);
}
}

if (!errors.isEmpty()) {
shutdownGlobalDaxSrcs();
throw new Err(new FailToStartUpGlobalDaxSrcs(errors));
}
}

/**
* Terminates all global dax sources and frees resources of all global dax
* sources.
*/
public static synchronized void shutdownGlobalDaxSrcs() {
for (var ds : globalDaxSrcMap.values()) {
ds.end();
}
}

/**
Expand All @@ -92,18 +137,53 @@ public static synchronized void fixGlobalDaxSrcs() {
public DaxBase() {}

/**
* Registers a local {@link DaxSrc} with a specified name.
* Registers a local {@link DaxSrc} with a specified name and sets up it.
*
* @param name The name for the argument {@link DaxSrc} and also for a
* {@link DaxConn} created by the argument {@link DaxSrc}.
* This name is used to get a {@link DaxConn} with {@link #getDaxConn}
* method.
* @param ds A {@link DaxSrc} object to be registered locally to enable to
* be used in only specific transactions.
* @throws Err If the specified {@link DaxSrc} failed to execute {@link
* DaxSrc#setUp} method.
*/
public void addLocalDaxSrc(final String name, final DaxSrc ds) {
if (!isLocalDaxSrcsFixed) {
localDaxSrcMap.put(name, ds);
public synchronized void setUpLocalDaxSrc(final String name, final DaxSrc ds) throws Err {
if (!this.isLocalDaxSrcsFixed) {
try {
ds.setUp();
} catch (Err err) {
throw err;
}
this.localDaxSrcMap.put(name, ds);
}
}

/**
* Removes a local {@link DaxSrc} of the specified name from this {@link
* DaxBase} and frees the resource of it.
*
* @param name A {@link DaxSrc} name.
*/
public synchronized void freeLocalDaxSrc(final String name) {
if (!this.isLocalDaxSrcsFixed) {
var ds = this.localDaxSrcMap.remove(name);
if (ds != null) {
ds.end();
}
}
}

/**
* Removes all local {@link DaxSrc}(s) from this {@link DaxBase} and frees
* the resources of them.
*/
public synchronized void freeAllLocalDaxSrcs() {
if (!this.isLocalDaxSrcsFixed) {
for (var ds : this.localDaxSrcMap.values()) {
ds.end();
}
this.localDaxSrcMap.clear();
}
}

Expand Down Expand Up @@ -191,13 +271,15 @@ void rollback() {
}
}

void close() {
void end() {
for (var conn : this.daxConnMap.values()) {
try {
conn.close();
} catch (Throwable t) {}
}

this.daxConnMap.clear();

this.isLocalDaxSrcsFixed = false;
}
}
17 changes: 16 additions & 1 deletion src/main/java/sabi/DaxSrc.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/*
* DaxSrc claass.
* Copyright (C) 2022 Takayuki Sato. All Rights Reserved.
* Copyright (C) 2022-2023 Takayuki Sato. All Rights Reserved.
*/
package sabi;

Expand All @@ -20,4 +20,19 @@ public interface DaxSrc {
* @throws Err If this instance failed to create a {@link DaxConn} object.
*/
DaxConn createDaxConn() throws Err;

/**
* Makes available this data source.
*
* For example, connecting to the data store, setting up connection pooling,
* and so on.
*
* @throws Err If this instance failed to set up.
*/
void setUp() throws Err;

/**
* Frees the resources of this data source.
*/
void end();
}
4 changes: 2 additions & 2 deletions src/main/java/sabi/ErrHandler.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ public interface ErrHandler {
* Handles an {@link Err} object which will be created rigth after.
*
* @param err An {@link Err} object.
* @param errOcc An {@link ErrOccasion} object which holds when and where
* @param occ An {@link ErrOccasion} object which holds when and where
* an Err occured.
*/
void handle(Err err, ErrOccasion errOcc);
void handle(Err err, ErrOccasion occ);
}
9 changes: 9 additions & 0 deletions src/main/java/sabi/ErrOccasion.java
Original file line number Diff line number Diff line change
Expand Up @@ -64,4 +64,13 @@ public String getFile() {
public int getLine() {
return line;
}

/**
* Returns a string representing the content of this object.
*
* @return A string representation of this object.
*/
public String toString() {
return "(" + file + ":" + line + ") " + time;
}
}
8 changes: 4 additions & 4 deletions src/main/java/sabi/Logic.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,24 +5,24 @@
package sabi;

/**
* Logic is a functional interface which executes a logical process.
* Logic is a functional interface which runs a logical process.
*
* In this class, only logical codes should be written and data access codes
* for external data sources should not.
* Data access codes should be written in methods associated with a dax
* interface which is an argument of {@link #execute} method.
* interface which is an argument of {@link #run} method.
*/
@FunctionalInterface
public interface Logic<D> {

/**
* Executes the logical process represented by this class.
* Runs the logical process represented by this class.
*
* This method is the entry point of the whole logical process represented by
* this class.
*
* @param dax A data access interface.
* @throws Err If an error occured in an implementation for an argument dax.
*/
void execute(final D dax) throws Err;
void run(final D dax) throws Err;
}
97 changes: 97 additions & 0 deletions src/main/java/sabi/Para.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
/*
* Para class.
* Copyright (C) 2023 Takayuki Sato. All Rights Reserved.
*/
package sabi;

import java.util.Map;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.concurrent.Callable;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.ExecutionException;

/**
* Para is a class to runs {@link Runner}(s) in parallel.
*/
public class Para {

/** The array of {@link Runner}(s). */
private final Runner[] runners;

/**
* An error reason which indicates some runner which is runned in parallel
* failed.
*
* @param errors A map contains {@link Err} objects with parallelized
* runner's indexes.
*/
public record FailToRunInParallel(Map<Integer, Err> errors) {};

/**
* An error reason which indicates that an exception occurs in parallelized
* runner.
*/
public record RunInParallelExceptionOccurs() {};

/**
* The constructor which takes an array of {@link Runner}(s) as arguments.
*
* @param runners {@link Runner}'s variadic arguments.
*/
public Para(Runner ...runners) {
this.runners = runners;
}

/**
* Runs the {@link Runner}(s) holding in this object in parallel.
*
* @throws Err If it is failed to run some of the runners.
*/
public void run() throws Err {
Para.run(runners);
}

/**
* Runs the specified {@link Runner}(s) in parallel.
*
* @param runners {@link Runner}'s variadic arguments.
* @throws Err If it is failed to run some of the runners.
*/
public static void run(final Runner... runners) throws Err {
final var executors = Executors.newFixedThreadPool(runners.length);
final var futures = new ArrayList<Future>(runners.length);
final var errors = new HashMap<Integer, Err>();
try {
for (var runner : runners) {
futures.add(executors.submit(() -> {
runner.run();
return null;
}));
}

final var it = futures.iterator();
for (int i = 0; it.hasNext(); i++) {
try {
it.next().get();
} catch (ExecutionException exc) {
var cause = exc.getCause();
if (cause instanceof Err) {
errors.put(i, Err.class.cast(cause));
} else {
errors.put(i, new Err(new RunInParallelExceptionOccurs(), cause));
}
} catch (Exception e) {
errors.put(i, new Err(new RunInParallelExceptionOccurs(), e));
}
}
} finally {
executors.shutdown();
}

if (!errors.isEmpty()) {
throw new Err(new FailToRunInParallel(errors));
}
}
}
Loading