2 EIBD eib bus access and management daemon
3 Copyright (C) 2005-2010 Martin Koegler <mkoegler@auto.tuwien.ac.at>
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20 #include "groupcache.h"
24 GroupCache::GroupCache (Layer3
* l3
, Trace
* t
)
26 TRACEPRINTF (t
, 4, this, "GroupCacheInit");
30 pth_mutex_init (&mutex
);
31 pth_cond_init (&cond
);
34 GroupCache::~GroupCache ()
36 TRACEPRINTF (t
, 4, this, "GroupCacheDestroy");
38 layer3
->deregisterGroupCallBack (this, 0);
43 GroupCache::find (eibaddr_t dst
)
45 int l
= 0, r
= cache () - 1;
49 if (cache
[p
]->dst
== dst
)
51 if (dst
> cache
[p
]->dst
)
60 GroupCache::remove (eibaddr_t addr
)
62 TRACEPRINTF (t
, 4, this, "GroupCacheRemove %d/%d/%d", (addr
>> 11) & 0x1f,
63 (addr
>> 8) & 0x07, (addr
) & 0xff);
65 int l
= 0, r
= cache () - 1;
69 if (cache
[p
]->dst
== addr
)
72 cache
.deletepart (p
, 1);
75 if (addr
> cache
[p
]->dst
)
84 GroupCache::add (GroupCacheEntry
* entry
)
87 cache
.resize (cache () + 1);
89 while (p
> 0 && cache
[p
- 1]->dst
> entry
->dst
)
91 cache
[p
] = cache
[p
- 1];
99 GroupCache::Get_L_Data (L_Data_PDU
* l
)
104 TPDU
*t
= TPDU::fromPacket (l
->data
);
105 if (t
->getType () == T_DATA_XXX_REQ
)
107 T_DATA_XXX_REQ_PDU
*t1
= (T_DATA_XXX_REQ_PDU
*) t
;
108 if (t1
->data () >= 2 && !(t1
->data
[0] & 0x3) &&
109 ((t1
->data
[1] & 0xC0) == 0x40 || (t1
->data
[1] & 0xC0) == 0x80))
117 c
->recvtime
= time (0);
118 pth_cond_notify (&cond
, 1);
122 c
= new GroupCacheEntry
;
126 c
->recvtime
= time (0);
128 pth_cond_notify (&cond
, 1);
140 TRACEPRINTF (t
, 4, this, "GroupCacheEnable");
142 if (!layer3
->registerGroupCallBack (this, 0))
152 TRACEPRINTF (t
, 4, this, "GroupCacheClear");
153 for (i
= 0; i
< cache (); i
++)
162 TRACEPRINTF (t
, 4, this, "GroupCacheStop");
164 layer3
->deregisterGroupCallBack (this, 0);
169 GroupCache::Read (eibaddr_t addr
, unsigned Timeout
, uint16_t age
)
171 TRACEPRINTF (t
, 4, this, "GroupCacheRead %d/%d/%d %d %d",
172 (addr
>> 11) & 0x1f, (addr
>> 8) & 0x07, (addr
) & 0xff,
181 TRACEPRINTF (t
, 4, this, "GroupCache not enabled");
186 if (c
&& age
&& c
->recvtime
+ age
< time (0))
191 TRACEPRINTF (t
, 4, this, "GroupCache found: %d.%d.%d",
192 (c
->src
>> 12) & 0xf, (c
->src
>> 8) & 0xf,
202 TRACEPRINTF (t
, 4, this, "GroupCache no entry");
206 A_GroupValue_Read_PDU apdu
;
207 T_DATA_XXX_REQ_PDU tpdu
;
209 pth_event_t timeout
= pth_event (PTH_EVENT_RTIME
, pth_time (Timeout
, 0));;
211 tpdu
.data
= apdu
.ToPacket ();
213 l
->data
= tpdu
.ToPacket ();
216 l
->AddrType
= GroupAddress
;
217 layer3
->send_L_Data (l
);
223 if (c
&& age
&& c
->recvtime
+ age
< time (0))
228 TRACEPRINTF (t
, 4, this, "GroupCache found: %d.%d.%d",
229 (c
->src
>> 12) & 0xf, (c
->src
>> 8) & 0xf,
231 pth_event_free (timeout
, PTH_FREE_THIS
);
235 if (pth_event_status (timeout
) == PTH_STATUS_OCCURRED
&& c
)
240 TRACEPRINTF (t
, 4, this, "GroupCache reread timeout");
241 pth_event_free (timeout
, PTH_FREE_THIS
);
245 if (pth_event_status (timeout
) == PTH_STATUS_OCCURRED
)
247 c
= new GroupCacheEntry
;
250 c
->recvtime
= time (0);
252 TRACEPRINTF (t
, 4, this, "GroupCache timeout");
253 pth_event_free (timeout
, PTH_FREE_THIS
);
257 pth_mutex_acquire (&mutex
, 0, 0);
258 pth_cond_await (&cond
, &mutex
, timeout
);
259 pth_mutex_release (&mutex
);