1 |
package appl.parallel.spmd; |
2 |
|
3 |
import java.rmi.RemoteException; |
4 |
|
5 |
import org.apache.log4j.LogManager; |
6 |
import org.apache.log4j.Logger; |
7 |
|
8 |
import appl.parallel.client.DataServer; |
9 |
import appl.parallel.spmd.split.DataPartition; |
10 |
import de.schmitzm.geotools.data.WritableGrid; |
11 |
import edu.bonn.xulu.plugin.data.grid.MultiGrid; |
12 |
|
13 |
/** |
14 |
* A multi data object stores multiple elements of the same type. |
15 |
* While the related {@link MultiDataInfo} stores only Information about |
16 |
* multi-data and is used by Xulu / V for transfer of metadata, this class |
17 |
* is a actual user object. The user can retrieve a multidata object e.g. via the |
18 |
* {@link SPMDServerController} and work with it (e.g. add elements) |
19 |
* |
20 |
* @see SPMDServerInterface#getMultiData(String) |
21 |
* @see MultiDataInfo |
22 |
* |
23 |
* @author Dominik Appl |
24 |
**/ |
25 |
|
26 |
public class MultiDataObject { |
27 |
|
28 |
private final Logger LOG = LogManager.getLogger(this.getClass().getName()); |
29 |
|
30 |
private final MultiDataInfo multiDataInfo; |
31 |
|
32 |
private final DataServer dataServer; |
33 |
|
34 |
private MultiGrid managedGrid = null; |
35 |
|
36 |
/** |
37 |
* Construct a new Multidata object |
38 |
* |
39 |
* @param info a {@link MultiDataInfo} object with the identification of the objects |
40 |
* @param dataServer a dataServer which is responsible for the actual loading of the data |
41 |
*/ |
42 |
public MultiDataObject(MultiDataInfo info, DataServer dataServer) { |
43 |
this.multiDataInfo = info; |
44 |
this.dataServer = dataServer; |
45 |
} |
46 |
|
47 |
/** |
48 |
* @param idx the position of the element |
49 |
* @return the element at the indicated position |
50 |
*/ |
51 |
public Object getElement(int idx) { |
52 |
try { |
53 |
checkIndex(idx); |
54 |
return dataServer.getData(multiDataInfo.getMultiID(idx)); |
55 |
} catch (RemoteException e) { |
56 |
LOG.error("RemoteExeception while retrieving data with ID " |
57 |
+ multiDataInfo.getMultiID(idx) |
58 |
+ " from PartitionDataServer"); |
59 |
} |
60 |
return null; |
61 |
} |
62 |
|
63 |
/** |
64 |
* checks whether the indicated index is valid |
65 |
* @throws ArrayIndexOutOfBoundsException if idx is below zero or higher than number of elements |
66 |
*/ |
67 |
private void checkIndex(int idx) { |
68 |
if ((idx > multiDataInfo.getCount() - 1) || idx <0 ) |
69 |
throw new ArrayIndexOutOfBoundsException("The Element with index " |
70 |
+ idx + " was requested, but the MultiDataObject has only " |
71 |
+ multiDataInfo.getCount() + " elements."); |
72 |
|
73 |
} |
74 |
|
75 |
/** |
76 |
* @return the number of elements in the multidataobject |
77 |
*/ |
78 |
public int getCount() { |
79 |
return multiDataInfo.getCount(); |
80 |
} |
81 |
|
82 |
/** |
83 |
* Adds an element to MultiDataObjects. Method should be thread safe. |
84 |
* |
85 |
* @return the index of the new element |
86 |
*/ |
87 |
public synchronized int addElement() { |
88 |
//the new ID of the MultiDataObject is generated by making |
89 |
//the first id negative and than subtracting the index from |
90 |
//the ID |
91 |
int idx = multiDataInfo.getCount() - 1; |
92 |
try { |
93 |
if (idx == -1) |
94 |
throw new UnsupportedOperationException( |
95 |
"The MultiDataInfo must have at least one element!"); |
96 |
//simply get the first element and create a empty one. |
97 |
int firstElementID = multiDataInfo.getMultiID(0); |
98 |
DataPartition firstElement = dataServer.getData(firstElementID); |
99 |
//generate a new id by making the first ID negative and subtracting the index value |
100 |
int newID = multiDataInfo.getNewIDForIndex(idx + 1); |
101 |
//there is a rare chance of colliding with existing ids: |
102 |
while (dataServer.getData(newID) != null) { |
103 |
newID--; |
104 |
} |
105 |
//create new element |
106 |
DataPartition newElement = firstElement.getEmpty(newID); |
107 |
multiDataInfo.addElement(newID); |
108 |
//add the element to the dataServer and to the managed MultiGrid (if any) |
109 |
dataServer.addData(newElement); |
110 |
if (managedGrid != null) |
111 |
managedGrid.addGrid((WritableGrid) newElement); |
112 |
return idx + 1; |
113 |
} catch (RemoteException e) { |
114 |
LOG |
115 |
.error("RemoteExeception while trying to add a new element with idx " |
116 |
+ idx + " to MultiData"); |
117 |
} |
118 |
return 0; |
119 |
} |
120 |
|
121 |
/** |
122 |
* Adds an element with the specified ID. |
123 |
* |
124 |
* @param id the id of the element to add |
125 |
* @return the index of the new element or 0 if an error occurred |
126 |
*/ |
127 |
public int addElement(int id) { |
128 |
//actual maxIndex |
129 |
int idx = multiDataInfo.getCount() - 1; |
130 |
try { |
131 |
if (idx == -1) |
132 |
throw new UnsupportedOperationException( |
133 |
"The MultiDataInfo must have at least one element!"); |
134 |
//simply get the first element and create a empty one. |
135 |
int firstElementID = multiDataInfo.getMultiID(0); |
136 |
DataPartition firstElement = dataServer.getData(firstElementID); |
137 |
|
138 |
//create new element |
139 |
DataPartition newElement = firstElement.getEmpty(id); |
140 |
multiDataInfo.addElement(id); |
141 |
//add the element to the dataServer and to the managed MultiGrid (if any) |
142 |
dataServer.addData(newElement); |
143 |
if (managedGrid != null) |
144 |
managedGrid.addGrid((WritableGrid) newElement); |
145 |
return idx + 1; |
146 |
} catch (RemoteException e) { |
147 |
LOG |
148 |
.error("RemoteExeception while trying to add a new element with idx " |
149 |
+ idx + " to MultiData"); |
150 |
} |
151 |
return 0; |
152 |
} |
153 |
|
154 |
/** |
155 |
* Manages a multigrid, which means that when a new element is added |
156 |
* to the multiObject, then the same element is also added to |
157 |
* the managed multiGrid. |
158 |
* |
159 |
* @param toManageMultiGrid the grid to be managed. Only one grid will be |
160 |
* managed at a time. |
161 |
* |
162 |
*/ |
163 |
public void setManagedGrid(MultiGrid toManageMultiGrid) { |
164 |
this.managedGrid = toManageMultiGrid; |
165 |
} |
166 |
|
167 |
/** |
168 |
* @return the encapsulted {@link MultiDataInfo} |
169 |
*/ |
170 |
public MultiDataInfo getMultiInfo() { |
171 |
return this.multiDataInfo; |
172 |
} |
173 |
|
174 |
public String getName() { |
175 |
return multiDataInfo.getName(); |
176 |
} |
177 |
|
178 |
/** |
179 |
* removes the element with the specified index from the dataServer |
180 |
* |
181 |
* @param idx the element |
182 |
*/ |
183 |
public void deleteElement(int idx) { |
184 |
checkIndex(idx); |
185 |
try { |
186 |
dataServer.removeData(multiDataInfo.getMultiID(idx)); |
187 |
} catch (RemoteException e) { |
188 |
LOG.error("Could not reach DataServer" , e); |
189 |
e.printStackTrace(); |
190 |
} |
191 |
} |
192 |
} |