-
Notifications
You must be signed in to change notification settings - Fork 5
/
AbstractServer.java
153 lines (127 loc) · 4.84 KB
/
AbstractServer.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
package org.genericsystem.kernel;
import java.io.Serializable;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.atomic.AtomicLong;
import org.genericsystem.api.core.ApiStatics;
import org.genericsystem.api.core.Snapshot;
import org.genericsystem.api.core.exceptions.ConcurrencyControlException;
import org.genericsystem.api.core.exceptions.OptimisticLockConstraintViolationException;
import org.genericsystem.common.AbstractCache;
import org.genericsystem.common.Container;
import org.genericsystem.common.Generic;
import org.genericsystem.common.Protocol;
import org.genericsystem.common.Root;
import org.genericsystem.common.Statics;
import org.genericsystem.common.Vertex;
/**
* @author Nicolas Feybesse
*
*/
public abstract class AbstractServer extends Root implements Generic, Protocol {
protected Archiver archiver;
private final GarbageCollector garbageCollector = new GarbageCollector(this);
private TsGenerator generator = new TsGenerator();
@Override
public AbstractServer getRoot() {
return this;
}
@Override
public abstract AbstractCache newCache();
@Override
public void close() {
super.close();
archiver.close();
garbageCollector.stopsScheduler();
}
GarbageCollector getGarbageCollector() {
return garbageCollector;
}
@Override
protected Class<Generic> getTClass() {
return Generic.class;
}
@Override
protected Generic build(Vertex vertex) {
return super.build(vertex);
}
@Override
protected Generic build(Long ts, Class<?> clazz, Generic meta, List<Generic> supers, Serializable value, List<Generic> components, long birhTs) {
return build(ts, clazz, meta, supers, value, components, isInitialized() ? new long[] { birhTs, 0L, Long.MAX_VALUE } : ApiStatics.SYSTEM_TS);
}
protected Generic build(Long ts, Class<?> clazz, Generic meta, List<Generic> supers, Serializable value, List<Generic> components, long[] otherTs) {
return init(newT(adaptClass(clazz, meta)), buildHandler(clazz, meta, supers, value, components, ts == null ? pickNewTs() : ts, otherTs));
}
protected RootServerHandler buildHandler(Class<?> clazz, Generic meta, List<Generic> supers, Serializable value, List<Generic> components, long ts, long[] otherTs) {
return new RootServerHandler(clazz, meta, supers, value, components, ts, otherTs);
}
class RootServerHandler extends DefaultHandler {
private final LifeManager lifeManager;
private final AbstractTsDependencies dependencies;
private RootServerHandler(Class<?> clazz, Generic meta, List<Generic> supers, Serializable value, List<Generic> components, long ts, long[] otherTs) {
super(clazz, meta, supers, value, components, ts);
this.lifeManager = new LifeManager(otherTs);
this.dependencies = new AbstractTsDependencies() {
@Override
public LifeManager getLifeManager() {
return lifeManager;
}
};
}
LifeManager getLifeManager() {
return lifeManager;
}
AbstractTsDependencies getDependencies() {
return dependencies;
}
@Override
protected AbstractServer getRoot() {
return AbstractServer.this;
}
@Override
public long getBirthTs() {
return lifeManager.getBirthTs();
}
}
@Override
public long pickNewTs() {
return generator.pickNewTs();
}
@Override
public Vertex getVertex(long id) {
return this.getGenericById(id).getVertex();
}
@Override
public Vertex[] getDependencies(long ts, long id) {
Generic ancestor = this.getGenericById(id);
return ancestor != null ? ((RootServerHandler) ancestor.getProxyHandler()).getDependencies().stream(ts).map(generic -> generic.getVertex()).toArray(Vertex[]::new) : Statics.EMPTY;
}
@Override
public void apply(long ts, long[] removeIds, Vertex[] addVertices) throws ConcurrencyControlException, OptimisticLockConstraintViolationException {
assert Arrays.stream(addVertices).allMatch(addVertex -> getRoot().getGenericById(addVertex.getTs()) == null);
assert Arrays.stream(addVertices).allMatch(addVertex -> addVertex.getBirthTs() == Long.MAX_VALUE);
Snapshot<Generic> removes = new Container(Arrays.stream(removeIds).mapToObj(removeId -> getRoot().getGenericById(removeId)));
Snapshot<Generic> adds = new Container(Arrays.stream(addVertices).map(addVertex -> getRoot().build(addVertex)));
try {
new Transaction(this, ts).apply(removes, adds);
} catch (ConcurrencyControlException | OptimisticLockConstraintViolationException e) {
adds.forEach(add -> getRoot().release(add.getTs()));
throw e;
}
}
private static class TsGenerator {
private final long startTime = System.currentTimeMillis() * Statics.MILLI_TO_NANOSECONDS - System.nanoTime();
private final AtomicLong lastTime = new AtomicLong(0L);
public long pickNewTs() {
long nanoTs;
long current;
for (;;) {
nanoTs = startTime + System.nanoTime();
current = lastTime.get();
if (nanoTs - current > 0)
if (lastTime.compareAndSet(current, nanoTs))
return nanoTs;
}
}
}
}