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