XRootD
XrdSsiEvent.cc
Go to the documentation of this file.
1 /******************************************************************************/
2 /* */
3 /* X r d S s i E v e n t . c c */
4 /* */
5 /* (c) 2015 by the Board of Trustees of the Leland Stanford, Jr., University */
6 /* Produced by Andrew Hanushevsky for Stanford University under contract */
7 /* DE-AC02-76-SFO0515 with the Department of Energy */
8 /* */
9 /* This file is part of the XRootD software suite. */
10 /* */
11 /* XRootD is free software: you can redistribute it and/or modify it under */
12 /* the terms of the GNU Lesser General Public License as published by the */
13 /* Free Software Foundation, either version 3 of the License, or (at your */
14 /* option) any later version. */
15 /* */
16 /* XRootD is distributed in the hope that it will be useful, but WITHOUT */
17 /* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or */
18 /* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public */
19 /* License for more details. */
20 /* */
21 /* You should have received a copy of the GNU Lesser General Public License */
22 /* along with XRootD in a file called COPYING.LESSER (LGPL license) and file */
23 /* COPYING (GPL license). If not, see <http://www.gnu.org/licenses/>. */
24 /* */
25 /* The copyright holder's institutional names and contributor's names may not */
26 /* be used to endorse or promote products derived from this software without */
27 /* specific prior written permission of the institution or contributor. */
28 /******************************************************************************/
29 
30 #include "XrdSsi/XrdSsiEvent.hh"
31 #include "XrdSsi/XrdSsiTrace.hh"
32 #include "Xrd/XrdScheduler.hh"
33 
34 using namespace XrdSsi;
35 
36 /******************************************************************************/
37 /* S t a t i c s & G l o b a l s */
38 /******************************************************************************/
39 
40 namespace
41 {
42 XrdSsiMutex frMutex;
43 }
44 
45 XrdSsiEvent::EventData *XrdSsiEvent::freeEvent = 0;
46 
47 namespace XrdSsi
48 {
49 extern XrdScheduler *schedP;
50 }
51 
52 /******************************************************************************/
53 /* A d d E v e n t */
54 /******************************************************************************/
55 
57 {
58  EPNAME("AddEvent");
59  XrdSsiMutexMon monMutex(evMutex);
60 
61 // Indicate there is pending event here
62 //
63  DEBUG("New event: isClear=" <<isClear <<" running=" <<running);
64  isClear = false;
65 
66 // If the base object has no status then we need to set it and schedule
67 // ourselves for processing if not already running.
68 //
69  if (!thisEvent.status)
70  {thisEvent.status = st;
71  thisEvent.response = resp;
72  if (!running)
73  {running = true;
74  XrdSsi::schedP->Schedule(this);
75  }
76  return;
77  }
78 
79 // Allocate a new event object and chain it from the base event. This also
80 // implies that we doesn't need to be scheduled as it already was scheduled.
81 //
82  frMutex.Lock();
83  EventData *edP = freeEvent;
84  if (!edP) edP = new EventData(st, resp);
85  else {freeEvent = edP->next;
86  edP->status = st;
87  edP->response = resp;
88  edP->next = 0;
89  }
90  frMutex.UnLock();
91 
92 // Establish the last event
93 //
94  if (lastEvent) lastEvent->next = edP;
95  else thisEvent .next = edP;
96  lastEvent = edP;
97 }
98 
99 /******************************************************************************/
100 /* C l r E v e n t */
101 /******************************************************************************/
102 
103 void XrdSsiEvent::ClrEvent(XrdSsiEvent::EventData *fdP)
104 {
105  EPNAME("ClrEvent");
106  EventData *xdP, *edP = fdP;
107 
108 // This method may be safely called on a undeleted EventData object even if
109 // this event object has been deleted; as can happen in XeqEvent().
110 // Clear any chained events. This loop ends with edP pointing to the last event.
111 //
112  while(edP->next)
113  {edP = edP->next;
114  delete edP->status;
115  delete edP->response;
116  }
117 
118 // Place all chained elements, if any, in the free list
119 //
120  if (fdP->next)
121  {frMutex.Lock();
122  xdP = fdP->next; edP->next = freeEvent; freeEvent = xdP;
123  frMutex.UnLock();
124  fdP->next = 0;
125  }
126 
127 // Clear the base event
128 //
129  if (fdP->status) {delete fdP->status; fdP->status = 0;}
130  if (fdP->response) {delete fdP->response; fdP->response = 0;}
131 
132 // If we are clearing our events then indicate we are not running. Note that
133 // this method is only called when cleaning up so we can't be running. We don't
134 // trace clears on event copies as they always occur.
135 //
136  if (fdP == &thisEvent)
137  {DEBUG("Self running=" <<running);
138  lastEvent = 0;
139  running = false;
140  isClear = true;
141  }
142 }
143 
144 /******************************************************************************/
145 /* D o I t */
146 /******************************************************************************/
147 
149 {
150  EPNAME("RunEvent");
151  EventData *edP, myEvent;
152  int rc;
153 
154 // Process all of the events in our list. This is a tricky proposition because
155 // the event executor may delete us upon return. Hence we do not directly use
156 // any data members of this class, only copies. The return rc tells what to do.
157 // rc > 0: terminate event processing and conclude in a normal fashion.
158 // rc = 0: reflect next event.
159 // rc < 0: immediately return as this object has become invalid.
160 //
161  evMutex.Lock();
162 do{thisEvent.Move2(myEvent);
163  lastEvent = 0;
164  isClear = true;
165  evMutex.UnLock();
166  edP = &myEvent;
167 
168  do {if ((rc = XeqEvent(edP->status, &edP->response)) != 0) break;
169  edP = edP->next;
170  } while(edP);
171 
172  ClrEvent(&myEvent);
173 
174  if (rc)
175  {DEBUG("XeqEvent requested " <<(rc < 0 ? "halt" : "flush"));
176  if (rc < 0) return;
177  evMutex.Lock();
178  break;
179  }
180 
181  evMutex.Lock();
182  } while(thisEvent.status);
183 
184 // Indicate we are no longer running
185 //
186  running = false;
187  evMutex.UnLock();
188 
189 // The last thing we need to do is to tell the event handler that we are done
190 // as it may decide to delete this object if no more events will occur.
191 //
192  XeqEvFin();
193 }
#define DEBUG(x)
Definition: XrdBwmTrace.hh:54
#define EPNAME(x)
Definition: XrdBwmTrace.hh:56
void Schedule(XrdJob *jp)
virtual void DoIt()
Definition: XrdSsiEvent.cc:148
void ClrEvent()
Definition: XrdSsiEvent.hh:42
void AddEvent(XrdCl::XRootDStatus *st, XrdCl::AnyObject *resp)
Definition: XrdSsiEvent.cc:56
XrdScheduler * schedP
Definition: XrdSsiClient.cc:74