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 |
|
|
import appl.parallel.client.DataServer; |
10 |
|
|
import appl.parallel.spmd.split.DataPartition; |
11 |
alfonx |
78 |
import edu.bonn.xulu.plugin.data.grid.MultiGrid; |
12 |
mojays |
2 |
|
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 |
|
|
} |