Skip to main content
aboutsummaryrefslogtreecommitdiffstats
blob: 4ffa4cd1c12261f75195f448dab914d345c591c8 (plain) (blame)
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
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
/*******************************************************************************
 * Copyright (c) 2013 protos software gmbh (http://www.protos.de).
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 * 
 * CONTRIBUTORS:
 * 		Henrik Rentz-Reichert (initial contribution)
 * 
 *******************************************************************************/

package org.eclipse.etrice.runtime.java.modelbase;

import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;
import java.util.ArrayList;
import java.util.LinkedList;

import org.eclipse.etrice.runtime.java.messaging.IRTObject;
import org.eclipse.etrice.runtime.java.messaging.RTServices;

/**
 * This class serves as base class for generated classes.
 * It specializes {@link OptionalActorInterfaceBase} for replicated optional actors.
 * 
 * @see OptionalActorInterfaceBase
 * 
 * @author Henrik Rentz-Reichert
 */
public class ReplicatedOptionalActorInterfaceBase extends OptionalActorInterfaceBase implements IPersistable {

	/**
	 * A separator for the index part of the name.
	 */
	private static final char INDEX_SEP = ':';
	
	/**
	 * A list of freed indices.
	 */
	private LinkedList<Integer> releasedIndices = new LinkedList<Integer>();
	
	/**
	 * All actor instances currently alive.
	 */
	private ArrayList<ActorClassBase> actors = new ArrayList<ActorClassBase>();

	/**
	 * The only constructor.
	 * 
	 * @param parent the parent event receiver
	 * @param name the name of the actor reference
	 * @param clsname the actor class name of the reference
	 */
	protected ReplicatedOptionalActorInterfaceBase(IEventReceiver parent, String name, String clsname) {
		super(parent, name, clsname);
	}
	
	/**
	 * This method instantiates and starts an optional actor (together with its contained instances).
	 * 
	 * @param actorClass the name of the actor class to be instantiated
	 * @param thread the ID of the message service (and thus the thread) for the newly created instances
	 * @return the index of the newly create instance or {@code -1} on failure
	 */
	public int createOptionalActor(String actorClass, int thread) {
		return createOptionalActor(actorClass, thread, null);
	}
	
	/**
	 * This method instantiates and starts an optional actor (together with its contained instances).
	 * 
	 * @param actorClass the name of the actor class to be instantiated
	 * @param thread the ID of the message service (and thus the thread) for the newly created instances
	 * @param input an optional {@link ObjectInput}
	 * @return the index of the newly create instance or {@code -1} on failure
	 */
	public int createOptionalActor(String actorClass, int thread, ObjectInput input) {
		setSubtreeThread(thread);
		
		IOptionalActorFactory factory = RTServices.getInstance().getSubSystem().getFactory(getClassName(), actorClass);
		if (factory==null)
			return -1;
		
		// the factory will set our path2peers map
		int index = getFreeIndex();
		String name = getChildName(index);
		logCreation(actorClass, name);
		ActorClassBase actor = factory.create(this, name);
		if (actor==null)
			return -1;
		
		actors.add(actor);
	
		startupSubTree(actor, input);
		
		return index;
	}
	
	/**
	 * Destroys an actor instance of this array.
	 * Before actual destruction the instances are shut down properly.
	 * 
	 * @param idx the index of the instance to be destroyed
	 * @return {@code true} on success, {@code false} else
	 */
	public boolean destroyOptionalActor(int idx) {
		return destroyOptionalActor(idx, null);
	}
	
	/**
	 * Destroys an actor instance of this array.
	 * Before actual destruction the instances are shut down properly.
	 * 
	 * @param idx the index of the instance to be destroyed
	 * @param output an optional {@link ObjectOutput}
	 * @return {@code true} on success, {@code false} else
	 */
	public boolean destroyOptionalActor(int idx, ObjectOutput output) {
		String childName = getChildName(idx);
		logDeletion(childName);
		IRTObject child = getChild(childName);
		if (!(child instanceof ActorClassBase))
			return false;
		
		shutdownSubTree((ActorClassBase)child, output);
		
		((ActorClassBase)child).destroy();
		releasedIndices.push(idx);
		actors.remove(child);
		
		return true;
	}
	
	/**
	 * Destroys all instances in the array.
	 * Before actual destruction the instances are shut down properly.
	 */
	public void destroyAllOptionalActors() {
		destroyAllOptionalActors(null);
	}
	
	/**
	 * Destroys all instances in the array.
	 * Before actual destruction the instances are shut down properly.
	 * 
	 * @param output an optional {@link ObjectOutput}
	 */
	public void destroyAllOptionalActors(ObjectOutput output) {
		for (ActorClassBase actor : actors) {
			shutdownSubTree(actor, output);
			actor.destroy();
			int idx = Integer.parseInt(actor.getName().substring(getName().length()));
			releasedIndices.push(idx);
		}
		actors.clear();
	}
	
	/**
	 * Composes a name with an index for a child instance.
	 * 
	 * @param idx the index to be used
	 * @return the composed name of the form &lt;name>:&lt;idx>
	 */
	public String getChildName(int idx) {
		return getName()+INDEX_SEP+idx;
	}
	
	/**
	 * @return the next free index
	 */
	private int getFreeIndex() {
		if (releasedIndices.isEmpty())
			return actors.size();
		else
			return releasedIndices.pop();
	}

	public String toString(){
		return "ReplicatedOptionalActorInterface(className="+getClassName()+", instancePath="+getInterfaceInstancePath()+")";
	}

	/* (non-Javadoc)
	 * @see org.eclipse.etrice.runtime.java.modelbase.IPersistable#saveObject(java.io.ObjectOutput)
	 */
	@Override
	public void saveObject(ObjectOutput output) throws IOException {
		output.writeInt(actors.size());
		for (ActorClassBase actor : actors) {
			output.writeUTF(actor.getClassName());
			output.writeInt(actor.getThread());
			int idx = Integer.parseInt(actor.getName().substring(actor.getName().indexOf(INDEX_SEP)+1));
			output.writeInt(idx);
			saveActor(actor, output);
		}
	}

	/* (non-Javadoc)
	 * @see org.eclipse.etrice.runtime.java.modelbase.IPersistable#loadObject(java.io.ObjectInput)
	 */
	@Override
	public void loadObject(ObjectInput input) throws IOException, ClassNotFoundException {
		int size = input.readInt();
		for (int i=0; i<size; ++i) {
			String className = input.readUTF();
			int thread = input.readInt();
			int idx = input.readInt();
			releasedIndices.add(idx);	// will be used as next index
			createOptionalActor(className, thread, input);
		}
	}

}

Back to the top