Source code: com/flexstor/flexdbserver/services/checkincheckout/CheckInService.java
1 /*
2 * CheckInService.java
3 *
4 * Copyright $Date: 2003/08/11 02:22:49 $ FLEXSTOR.net Inc.
5 *
6 * This work is licensed for use and distribution under license terms found at
7 * http://www.flexstor.org/license.html
8 *
9 */
10
11 package com.flexstor.flexdbserver.services.checkincheckout;
12
13 import java.util.Enumeration;
14 import java.util.Hashtable;
15 import java.util.Vector;
16
17 import com.flexstor.common.data.ActionData;
18 import com.flexstor.common.data.ActionResult;
19 import com.flexstor.common.data.AssetRecordData;
20 import com.flexstor.common.resources.Resources;
21 import com.flexstor.common.threadmgr.ThreadCallbackI;
22 import com.flexstor.common.threadmgr.ThreadConsumerI;
23 import com.flexstor.flexdbserver.services.Service;
24 import com.flexstor.flexdbserver.services.ServiceContext;
25 import com.flexstor.flexdbserver.transactionmanager.TransMngCheckIn;
26
27 /**
28 * <P>
29 * CheckInService <BR>
30 * <BLOCKQUOTE>
31 * Checks in new versions of assets after modifications, making such assets the current assets
32 * in the system. Older versions are kept in the system.
33 * </BLOCKQUOTE>
34 * </P>
35 *
36 * <P>
37 * Input Data Object <BR>
38 * <BLOCKQUOTE>
39 * com.flexstor.common.data.ActionData
40 * </BLOCKQUOTE>
41 * </P>
42 *
43 * <P>
44 * Output Data Object <BR>
45 * <BLOCKQUOTE>
46 * com.flexstor.common.dataActionResult
47 * </BLOCKQUOTE>
48 * </P>
49 *
50 * <P>
51 * Programmable Properties (passed inside data object) <BR>
52 * <BLOCKQUOTE>
53 * Specific Properties (apply to each individual asset) <BR>
54 * <BLOCKQUOTE>
55 * <P>
56 * MacBinaryFormat: Indicates whether the file represented by this asset is in
57 * MacBinary format or not (defaults to false). <BR>
58 * Data type: Boolean <BR>
59 * Legal values: true or false <BR>
60 * </P>
61 * <P>
62 * RegenerateThumbnails: Indicates if the CheckInService needs to call the
63 * ImportActionDataService to regenerate the thumbnail (defaults to false). <BR>
64 * Data type: Boolean <BR>
65 * Legal values: true or false <BR>
66 * </P>
67 * <P>
68 * VersionNo: The version number of the asset to check in. <BR>
69 * Data type: String <BR>
70 * Legal values: any String <BR>
71 * </P>
72 * <P>
73 * VersionNoPrevious: The version number of the asset, previous to being checked in. <BR>
74 * Data type: String <BR>
75 * Legal values: Any String <BR>
76 * </P>
77 * <P>
78 * CheckInDateTime: The date and time this asset was checked in. <BR>
79 * Data type: String <BR>
80 * Legal values: String of the form MM-DD-YYYY hh24:mi:ss <BR>
81 * </P>
82 * <P>
83 * SourceLocation: Full path, including name, of file to be checked in. <BR>
84 * Data type: String <BR>
85 * Legal values: Full path to the file, including name <BR>
86 * </P>
87 * <P>
88 * KeepLowres: If set to true, it will preserve the old low resolution asset synchronized
89 * with the old asset prior being to checked in (defaults to true). <BR>
90 * Data type: Boolean <BR>
91 * Legal values: true or false <BR>
92 * </P>
93 * </BLOCKQUOTE>
94 * </BLOCKQUOTE>
95 * </P>
96 */
97 public class CheckInService
98 implements Service, ThreadCallbackI
99 {
100 // To get the version number from MKS
101 public final static String IDENTIFIER="$Id: CheckInService.java,v 1.5 2003/08/11 02:22:49 aleric Exp $";
102
103 protected ActionData data = null;
104 protected ActionResult result = null;
105 protected Vector vRecords = new Vector();
106 protected Vector vBadRecords = new Vector();
107 protected int nManagerRunning = 0;
108 protected String sThisService = "";
109
110 private int id = -1;
111
112 /**
113 * Calls before the service is initialized (before initData is called) to
114 * pass information about the environment in which the service is running.
115 * This environment consists of information about the properties set for the
116 * service in one of these files (services.config, roletype_services.config,
117 * or *.ctl), plus methods to access other information such as an instance
118 * of the service broker to invoke other services, the transaction id for
119 * the service, file separator character and local path for the installation
120 * directory and configuration directory.
121 *
122 * @param context Holds information about the environment in which the service
123 * is running.
124 */
125 public void setServiceContext( ServiceContext context )
126 {
127 id = context.getTransactionId();
128 }
129
130 /**
131 * A data initialization method called at the beginning of the service.
132 * The input argument, ActionData must be cast into its subclass in order
133 * to extract the CheckInService specific data from it.
134 */
135 public void initData(ActionData actionData)
136 {
137 this.data = actionData;
138 //6232=Check-In Service
139 sThisService = Resources.get(6232) + " (" + id + ")";
140 }
141
142 /**
143 * The start of the CheckIn Service.
144 */
145 public ActionResult go()
146 {
147 // Create subsets of data objects per server and start a new ServiceManager
148 //for each.
149 Hashtable htSubSets = createSubSets();
150
151 if ( htSubSets != null && htSubSets.size() > 0 )
152 {
153 // Create one thread per data object SubSet and start a Service Manager
154 // synchronized to make sure we start all the threads before getting any response back
155 // from observables.
156 synchronized (this)
157 {
158 for (Enumeration e = htSubSets.keys(); e.hasMoreElements(); )
159 {
160 String sServerName = (String) e.nextElement();
161 ActionData dataSubSet = (ActionData)htSubSets.get(sServerName);
162 (new CheckInServiceManager( sServerName, dataSubSet, this )).startManager();
163 nManagerRunning++;
164 }
165 }
166 }
167 else
168 vBadRecords = data.getRecords();
169
170 // while there are services still running, just wait until be notified of an update;
171 // if all services are done, exit loop and exit Check-In Service
172 synchronized (this)
173 {
174 while ( nManagerRunning > 0 )
175 {
176 try
177 {
178 this.wait();
179 }
180 catch (InterruptedException ie)
181 {
182 vBadRecords = data.getRecords();
183 }
184 }
185 }
186
187 boolean bResult = true;
188 if ( vBadRecords.size() > 0 )
189 bResult = false;
190
191 // Remove this persisted transaction from TransList.per
192 (new TransMngCheckIn( data.getTransId() )).setTransactionCompletedState(bResult);
193
194 if ( bResult )
195 result = new ActionResult( true );
196 else
197 {
198 result = new ActionResult( false );
199 result.setBadRecords( vBadRecords );
200 // Update the list of record with the good ones only, if any
201 data.setRecords( vRecords );
202 }
203
204 result.setData( data );
205 result.setId( data.getTransId() );
206 return result;
207 }
208
209 /**
210 * create a Hashtable containing a list of objects to be sent to the service manager.
211 * key = server name; value = ServiceManagerData
212 */
213 private Hashtable createSubSets()
214 {
215 // Retrieve the vector of AssetRecordData and parse thru it; for each server name found
216 // create a ActionData for each new server and add the respective elements to it.
217
218 Hashtable htSubSets = new Hashtable();
219 ActionData dataSubSet;
220 AssetRecordData currRecord;
221 String sServerName;
222
223 vRecords = data.getRecords();
224 if ( vRecords != null)
225 {
226 for ( int i = 0; i < vRecords.size(); i++ )
227 {
228 AssetRecordData dummy = (AssetRecordData)vRecords.elementAt(i);
229 currRecord = (AssetRecordData)dummy.clone();
230 sServerName = currRecord.getServer();
231
232 if ( sServerName != null )
233 {
234 dataSubSet = (ActionData) htSubSets.get( sServerName );
235 if ( dataSubSet == null )
236 {
237 dataSubSet = (ActionData) data.clone();
238 dataSubSet.addRecord( currRecord );
239 htSubSets.put( sServerName, dataSubSet );
240 }
241 else
242 dataSubSet.addRecord( currRecord );
243 }
244 }
245 }
246 return htSubSets;
247 }
248
249 /**
250 * update the ImportData after the set of services are executed for
251 * a ImportData sub set.
252 **/
253 private synchronized void notify( ActionResult result )
254 {
255 Vector vBadRecs = null;
256 if ( result == null )
257 vBadRecs = data.getRecords();
258 else if ( !result.isSuccess() )
259 vBadRecs = result.getBadRecords();
260
261 if ( vBadRecs != null && vBadRecs.size() > 0 )
262 {
263 AssetRecordData record;
264 for (int i = 0; i < vBadRecs.size(); i++ )
265 {
266 // Set records to bad and remove the Vector of good records
267 record = (AssetRecordData)vBadRecs.elementAt(i);
268 vBadRecords.addElement( record );
269 vRecords.removeElement( record );
270 }
271 }
272
273 nManagerRunning--;
274 this.notifyAll();
275 }
276
277 /**
278 * Called when a thread task is about to begin.
279 * @param consumer the instance that this task will run against.
280 * @param obj the user defined parameter for this task.
281 */
282 public void threadTaskStart ( ThreadConsumerI consumer, Object obj ) {}
283
284 /**
285 * Called when a thread task has just finished.
286 * @param consumer the instance that this task will run against.
287 * @param obj the user defined parameter for this task.
288 */
289 public void threadTaskEnd ( ThreadConsumerI consumer, Object obj )
290 {
291 notify( ((CheckInServiceManager)consumer).getResult() );
292 }
293 }