summaryrefslogtreecommitdiff
path: root/ndb/src/rep/SignalQueue.cpp
blob: 9b356a14b7dc59342e20399d48c969f731d2928b (plain)
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
/* Copyright (C) 2003 MySQL AB

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 2 of the License, or
   (at your option) any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */

#include <string.h>

#include "SignalQueue.hpp"

SignalQueue::SignalQueue() {
  m_mutex = NdbMutex_Create();
  m_cond = NdbCondition_Create();
  m_signalQueueHead = NULL;
  m_queueSize = 0;
}

SignalQueue::~SignalQueue() {
  {
    Guard g(m_mutex);
    while(m_signalQueueHead != NULL)
      delete pop();
  }
  NdbMutex_Destroy(m_mutex);
  m_mutex = NULL;
  NdbCondition_Destroy(m_cond);
  m_cond = NULL;
}

NdbApiSignal *
SignalQueue::pop() {
  NdbApiSignal *ret;

  if(m_signalQueueHead == NULL)
    return NULL;

  ret = m_signalQueueHead->signal;

  QueueEntry *old = m_signalQueueHead;
  m_signalQueueHead = m_signalQueueHead->next;

  delete old;
  m_queueSize--;
  return ret;
}

void
SignalQueue::receive(void *me, NdbApiSignal *signal) {
  SignalQueue *q = (SignalQueue *)me;
  q->receive(signal);
}

void
SignalQueue::receive(NdbApiSignal *signal) {
  QueueEntry *n = new QueueEntry();
  n->signal = signal;
  n->next = NULL;

  Guard guard(m_mutex);

  if(m_signalQueueHead == NULL) {
    m_signalQueueHead = n;
    m_queueSize++;
    NdbCondition_Broadcast(m_cond);
    return;
  }

  QueueEntry *cur = m_signalQueueHead;

  while(cur->next != NULL)
    cur = cur->next;

  cur->next = n;
  m_queueSize++;
  NdbCondition_Broadcast(m_cond);
}

NdbApiSignal *
SignalQueue::waitFor(int gsn, NodeId nodeid, Uint32 timeout) {
  Guard g(m_mutex);

  if(m_signalQueueHead == NULL)
    NdbCondition_WaitTimeout(m_cond, m_mutex, timeout);
  
  if(m_signalQueueHead == NULL)
    return NULL;
  
  if(gsn != 0 && m_signalQueueHead->signal->readSignalNumber() != gsn)
    return NULL;
  
  if(nodeid != 0 && 
     refToNode(m_signalQueueHead->signal->theSendersBlockRef) != nodeid)
    return NULL;
  
  return pop();
}