source: main/trunk/greenstone3/src/java/org/greenstone/gsdl3/build/CollectionConstructor.java@ 31669

Last change on this file since 31669 was 31669, checked in by ak19, 7 years ago

Have made the EventListeners list in CollectionConstructor use the threadsafe if less efficient CopyOnWriteArrayList, so that the send event messages called by GS2PerlConstructor are threadsafe. This reduces the need to make certain methods in GS2PerlConstructor declared as synchronized, which would have locked the GS2PerlConstructor object instance rather than its inherited listeners member variable.

  • Property svn:keywords set to Author Date Id Revision
File size: 4.3 KB
Line 
1package org.greenstone.gsdl3.build;
2
3import java.io.File;
4
5import org.greenstone.gsdl3.util.*;
6//import java.util.Thread
7import java.util.concurrent.CopyOnWriteArrayList;
8import org.w3c.dom.Element;
9
10/** base class for collection construction */
11public abstract class CollectionConstructor extends Thread
12{
13
14 /** the site in which building is to take place */
15 protected String site_home = null;
16 /** the name of the site */
17 protected String site_name = null;
18 /** the name of the collection */
19 protected String collection_name = null;
20 /** the stage of construction */
21 protected int process_type = -1;
22 /** other arguments/parameters for the construction process - in a paramList */
23 protected Element process_params = null;
24 /** the list of listeners for the process. We need it to be threadsafe.
25 * see http://stackoverflow.com/questions/8259479/should-i-synchronize-listener-notifications-or-not
26 * https://docs.oracle.com/javase/6/docs/api/java/util/concurrent/CopyOnWriteArrayList.html
27 * "A thread-safe variant of ArrayList in which all mutative operations (add, set, and so on) are
28 * implemented by making a fresh copy of the underlying array.
29 * This is ordinarily too costly, but may be more efficient than alternatives when traversal operations
30 * vastly outnumber mutations, and is useful when you cannot or don't want to synchronize traversals,
31 * yet need to preclude interference among concurrent threads."
32 */
33 protected final CopyOnWriteArrayList<ConstructionListener> listeners;
34 /** A flag used to determine if this process has been asked to cancel. */
35 protected boolean cancel = false; // Not really used (in any way that works)
36 /** Stores the name of the manifest file (if one is needed) */
37 protected String manifest_file = null;
38 /** The URL params constructed as a query string, representing the CGI QUERY_STRING to the process */
39 protected String query_string = null;
40
41 public CollectionConstructor(String name)
42 {
43 super(name);
44 this.listeners = new CopyOnWriteArrayList<ConstructionListener>();
45 }
46
47 /**
48 * carry out any set up stuff - returns false if couldn't set up properly
49 */
50 public boolean configure()
51 {
52 return true;
53 }
54
55 // this method never gets called. And, the way subclass GS2PerlConstructor.runPerlCommand() was originally
56 // coded, setting cancel to true never had any effect anyway in stopping any perl command that was run.
57 public void stopAction()
58 {
59 this.cancel = true;
60 }
61
62 public void setActionType(int type)
63 {
64 this.process_type = type;
65 }
66
67 public void setSiteHome(String site_home)
68 {
69 this.site_home = site_home;
70
71 File siteHomeFile = new File(site_home);
72 this.site_name = siteHomeFile.getName();
73 }
74
75 public void setCollectionName(String coll_name)
76 {
77 this.collection_name = coll_name;
78 }
79
80 public void setQueryString(String querystring)
81 {
82 this.query_string = querystring;
83 }
84
85 public void setProcessParams(Element params)
86 {
87 this.process_params = params;
88 }
89
90 public void setManifestFile(String manifestFile)
91 {
92 this.manifest_file = manifestFile;
93 }
94
95 public boolean addListener(ConstructionListener listener)
96 {
97 this.listeners.add(listener);
98 return true;
99 }
100
101 public boolean removeListener(ConstructionListener listener)
102 {
103 this.listeners.remove(listener);
104 return true;
105 }
106
107 protected void sendProcessBegun(ConstructionEvent evt)
108 {
109 // See http://stackoverflow.com/questions/8259479/should-i-synchronize-listener-notifications-or-not
110 for (ConstructionListener l: this.listeners) {
111 l.processBegun(evt);
112 }
113 }
114
115 protected void sendProcessComplete(ConstructionEvent evt)
116 {
117 for (ConstructionListener l: this.listeners) {
118 l.processComplete(evt);
119 }
120 }
121
122 // Method doesn't need to be synchronized any more, since it uses the ThreadSafe CopyOnWriteArrayList
123 // for listeners list.
124 // See http://stackoverflow.com/questions/8259479/should-i-synchronize-listener-notifications-or-not
125 // See http://stackoverflow.com/questions/574240/is-there-an-advantage-to-use-a-synchronized-method-instead-of-a-synchronized-blo
126 protected void sendProcessStatus(ConstructionEvent evt)
127 {
128 for (ConstructionListener l: this.listeners) {
129 l.processStatus(evt);
130 }
131 }
132
133 protected void sendMessage(ConstructionEvent evt)
134 {
135 for (ConstructionListener l: this.listeners) {
136 l.message(evt);
137 }
138 }
139
140 abstract public void run();
141}
Note: See TracBrowser for help on using the repository browser.