1 |
mojays |
2 |
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 |
|
|
} |