Toggle navigation
Toggle navigation
This project
Loading...
Sign in
홍길동
/
onos
Go to a project
Toggle navigation
Toggle navigation pinning
Projects
Groups
Snippets
Help
Project
Activity
Repository
Pipelines
Graphs
Issues
0
Merge Requests
0
Wiki
Snippets
Network
Create a new issue
Builds
Commits
Issue Boards
Authored by
Jonathan Hart
2014-10-17 12:46:42 -0700
Browse Files
Options
Browse Files
Download
Email Patches
Plain Diff
Commit
f735707bb9273d2e496d657e57c3129962b44bc3
f735707b
1 parent
a309989f
Remove hz/net files again
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
0 additions
and
801 deletions
core/store/hz/net/src/main/java/org/onlab/onos/store/device/impl/DistributedDeviceStore.java
core/store/hz/net/src/test/java/org/onlab/onos/store/device/impl/DistributedDeviceStoreTest.java
core/store/hz/net/src/main/java/org/onlab/onos/store/device/impl/DistributedDeviceStore.java
deleted
100644 → 0
View file @
a309989
package
org
.
onlab
.
onos
.
store
.
device
.
impl
;
import
static
com
.
google
.
common
.
base
.
Predicates
.
notNull
;
import
com.google.common.base.Optional
;
import
com.google.common.cache.LoadingCache
;
import
com.google.common.collect.FluentIterable
;
import
com.google.common.collect.ImmutableList
;
import
com.google.common.collect.ImmutableSet
;
import
com.google.common.collect.ImmutableSet.Builder
;
import
com.hazelcast.core.IMap
;
import
com.hazelcast.core.ISet
;
import
org.apache.felix.scr.annotations.Activate
;
import
org.apache.felix.scr.annotations.Component
;
import
org.apache.felix.scr.annotations.Deactivate
;
import
org.apache.felix.scr.annotations.Service
;
import
org.onlab.onos.net.DefaultDevice
;
import
org.onlab.onos.net.DefaultPort
;
import
org.onlab.onos.net.Device
;
import
org.onlab.onos.net.DeviceId
;
import
org.onlab.onos.net.Port
;
import
org.onlab.onos.net.PortNumber
;
import
org.onlab.onos.net.device.DeviceDescription
;
import
org.onlab.onos.net.device.DeviceEvent
;
import
org.onlab.onos.net.device.DeviceStore
;
import
org.onlab.onos.net.device.DeviceStoreDelegate
;
import
org.onlab.onos.net.device.PortDescription
;
import
org.onlab.onos.net.provider.ProviderId
;
import
org.onlab.onos.store.common.AbsentInvalidatingLoadingCache
;
import
org.onlab.onos.store.common.AbstractHazelcastStore
;
import
org.onlab.onos.store.common.OptionalCacheLoader
;
import
org.slf4j.Logger
;
import
java.util.ArrayList
;
import
java.util.Collections
;
import
java.util.HashMap
;
import
java.util.HashSet
;
import
java.util.Iterator
;
import
java.util.List
;
import
java.util.Map
;
import
java.util.Objects
;
import
java.util.Set
;
import
static
com
.
google
.
common
.
base
.
Preconditions
.
checkArgument
;
import
static
com
.
google
.
common
.
cache
.
CacheBuilder
.
newBuilder
;
import
static
org
.
onlab
.
onos
.
net
.
device
.
DeviceEvent
.
Type
.*;
import
static
org
.
slf4j
.
LoggerFactory
.
getLogger
;
//TODO: Add support for multiple provider and annotations
/**
* Manages inventory of infrastructure devices using Hazelcast-backed map.
*/
@Component
(
immediate
=
true
)
@Service
public
class
DistributedDeviceStore
extends
AbstractHazelcastStore
<
DeviceEvent
,
DeviceStoreDelegate
>
implements
DeviceStore
{
private
final
Logger
log
=
getLogger
(
getClass
());
public
static
final
String
DEVICE_NOT_FOUND
=
"Device with ID %s not found"
;
// private IMap<DeviceId, DefaultDevice> cache;
private
IMap
<
byte
[],
byte
[]>
rawDevices
;
private
LoadingCache
<
DeviceId
,
Optional
<
DefaultDevice
>>
devices
;
// private ISet<DeviceId> availableDevices;
private
ISet
<
byte
[]>
availableDevices
;
// TODO DevicePorts is very inefficient consider restructuring.
// private IMap<DeviceId, Map<PortNumber, Port>> devicePorts;
private
IMap
<
byte
[],
byte
[]>
rawDevicePorts
;
private
LoadingCache
<
DeviceId
,
Optional
<
Map
<
PortNumber
,
Port
>>>
devicePorts
;
private
String
devicesListener
;
private
String
portsListener
;
@Override
@Activate
public
void
activate
()
{
super
.
activate
();
// IMap event handler needs value
final
boolean
includeValue
=
true
;
// TODO decide on Map name scheme to avoid collision
rawDevices
=
theInstance
.
getMap
(
"devices"
);
final
OptionalCacheLoader
<
DeviceId
,
DefaultDevice
>
deviceLoader
=
new
OptionalCacheLoader
<>(
serializer
,
rawDevices
);
devices
=
new
AbsentInvalidatingLoadingCache
<>(
newBuilder
().
build
(
deviceLoader
));
// refresh/populate cache based on notification from other instance
devicesListener
=
rawDevices
.
addEntryListener
(
new
RemoteDeviceEventHandler
(
devices
),
includeValue
);
// TODO cache availableDevices
availableDevices
=
theInstance
.
getSet
(
"availableDevices"
);
rawDevicePorts
=
theInstance
.
getMap
(
"devicePorts"
);
final
OptionalCacheLoader
<
DeviceId
,
Map
<
PortNumber
,
Port
>>
devicePortLoader
=
new
OptionalCacheLoader
<>(
serializer
,
rawDevicePorts
);
devicePorts
=
new
AbsentInvalidatingLoadingCache
<>(
newBuilder
().
build
(
devicePortLoader
));
// refresh/populate cache based on notification from other instance
portsListener
=
rawDevicePorts
.
addEntryListener
(
new
RemotePortEventHandler
(
devicePorts
),
includeValue
);
loadDeviceCache
();
loadDevicePortsCache
();
log
.
info
(
"Started"
);
}
@Deactivate
public
void
deactivate
()
{
rawDevicePorts
.
removeEntryListener
(
portsListener
);
rawDevices
.
removeEntryListener
(
devicesListener
);
log
.
info
(
"Stopped"
);
}
@Override
public
int
getDeviceCount
()
{
return
devices
.
asMap
().
size
();
}
@Override
public
Iterable
<
Device
>
getDevices
()
{
// TODO builder v.s. copyOf. Guava semms to be using copyOf?
Builder
<
Device
>
builder
=
ImmutableSet
.
builder
();
for
(
Optional
<
DefaultDevice
>
e
:
devices
.
asMap
().
values
())
{
if
(
e
.
isPresent
())
{
builder
.
add
(
e
.
get
());
}
}
return
builder
.
build
();
}
private
void
loadDeviceCache
()
{
for
(
byte
[]
keyBytes
:
rawDevices
.
keySet
())
{
final
DeviceId
id
=
deserialize
(
keyBytes
);
devices
.
refresh
(
id
);
}
}
private
void
loadDevicePortsCache
()
{
for
(
byte
[]
keyBytes
:
rawDevicePorts
.
keySet
())
{
final
DeviceId
id
=
deserialize
(
keyBytes
);
devicePorts
.
refresh
(
id
);
}
}
@Override
public
Device
getDevice
(
DeviceId
deviceId
)
{
// TODO revisit if ignoring exception is safe.
return
devices
.
getUnchecked
(
deviceId
).
orNull
();
}
@Override
public
DeviceEvent
createOrUpdateDevice
(
ProviderId
providerId
,
DeviceId
deviceId
,
DeviceDescription
deviceDescription
)
{
DefaultDevice
device
=
devices
.
getUnchecked
(
deviceId
).
orNull
();
if
(
device
==
null
)
{
return
createDevice
(
providerId
,
deviceId
,
deviceDescription
);
}
return
updateDevice
(
providerId
,
device
,
deviceDescription
);
}
// Creates the device and returns the appropriate event if necessary.
private
DeviceEvent
createDevice
(
ProviderId
providerId
,
DeviceId
deviceId
,
DeviceDescription
desc
)
{
DefaultDevice
device
=
new
DefaultDevice
(
providerId
,
deviceId
,
desc
.
type
(),
desc
.
manufacturer
(),
desc
.
hwVersion
(),
desc
.
swVersion
(),
desc
.
serialNumber
(),
desc
.
chassisId
());
synchronized
(
this
)
{
final
byte
[]
deviceIdBytes
=
serialize
(
deviceId
);
rawDevices
.
put
(
deviceIdBytes
,
serialize
(
device
));
devices
.
put
(
deviceId
,
Optional
.
of
(
device
));
availableDevices
.
add
(
deviceIdBytes
);
}
return
new
DeviceEvent
(
DEVICE_ADDED
,
device
,
null
);
}
// Updates the device and returns the appropriate event if necessary.
private
DeviceEvent
updateDevice
(
ProviderId
providerId
,
DefaultDevice
device
,
DeviceDescription
desc
)
{
// We allow only certain attributes to trigger update
if
(!
Objects
.
equals
(
device
.
hwVersion
(),
desc
.
hwVersion
())
||
!
Objects
.
equals
(
device
.
swVersion
(),
desc
.
swVersion
()))
{
DefaultDevice
updated
=
new
DefaultDevice
(
providerId
,
device
.
id
(),
desc
.
type
(),
desc
.
manufacturer
(),
desc
.
hwVersion
(),
desc
.
swVersion
(),
desc
.
serialNumber
(),
desc
.
chassisId
());
synchronized
(
this
)
{
final
byte
[]
deviceIdBytes
=
serialize
(
device
.
id
());
rawDevices
.
put
(
deviceIdBytes
,
serialize
(
updated
));
devices
.
put
(
device
.
id
(),
Optional
.
of
(
updated
));
availableDevices
.
add
(
serialize
(
device
.
id
()));
}
return
new
DeviceEvent
(
DeviceEvent
.
Type
.
DEVICE_UPDATED
,
updated
,
null
);
}
// Otherwise merely attempt to change availability
synchronized
(
this
)
{
boolean
added
=
availableDevices
.
add
(
serialize
(
device
.
id
()));
return
!
added
?
null
:
new
DeviceEvent
(
DEVICE_AVAILABILITY_CHANGED
,
device
,
null
);
}
}
@Override
public
DeviceEvent
markOffline
(
DeviceId
deviceId
)
{
synchronized
(
this
)
{
Device
device
=
devices
.
getUnchecked
(
deviceId
).
orNull
();
boolean
removed
=
device
!=
null
&&
availableDevices
.
remove
(
serialize
(
deviceId
));
return
!
removed
?
null
:
new
DeviceEvent
(
DEVICE_AVAILABILITY_CHANGED
,
device
,
null
);
}
}
@Override
public
List
<
DeviceEvent
>
updatePorts
(
ProviderId
providerId
,
DeviceId
deviceId
,
List
<
PortDescription
>
portDescriptions
)
{
List
<
DeviceEvent
>
events
=
new
ArrayList
<>();
synchronized
(
this
)
{
Device
device
=
devices
.
getUnchecked
(
deviceId
).
orNull
();
checkArgument
(
device
!=
null
,
DEVICE_NOT_FOUND
,
deviceId
);
Map
<
PortNumber
,
Port
>
ports
=
getPortMap
(
deviceId
);
// Add new ports
Set
<
PortNumber
>
processed
=
new
HashSet
<>();
for
(
PortDescription
portDescription
:
portDescriptions
)
{
Port
port
=
ports
.
get
(
portDescription
.
portNumber
());
events
.
add
(
port
==
null
?
createPort
(
device
,
portDescription
,
ports
)
:
updatePort
(
device
,
port
,
portDescription
,
ports
));
processed
.
add
(
portDescription
.
portNumber
());
}
updatePortMap
(
deviceId
,
ports
);
events
.
addAll
(
pruneOldPorts
(
device
,
ports
,
processed
));
}
return
FluentIterable
.
from
(
events
).
filter
(
notNull
()).
toList
();
}
// Creates a new port based on the port description adds it to the map and
// Returns corresponding event.
//@GuardedBy("this")
private
DeviceEvent
createPort
(
Device
device
,
PortDescription
portDescription
,
Map
<
PortNumber
,
Port
>
ports
)
{
DefaultPort
port
=
new
DefaultPort
(
device
,
portDescription
.
portNumber
(),
portDescription
.
isEnabled
());
ports
.
put
(
port
.
number
(),
port
);
updatePortMap
(
device
.
id
(),
ports
);
return
new
DeviceEvent
(
PORT_ADDED
,
device
,
port
);
}
// Checks if the specified port requires update and if so, it replaces the
// existing entry in the map and returns corresponding event.
//@GuardedBy("this")
private
DeviceEvent
updatePort
(
Device
device
,
Port
port
,
PortDescription
portDescription
,
Map
<
PortNumber
,
Port
>
ports
)
{
if
(
port
.
isEnabled
()
!=
portDescription
.
isEnabled
())
{
DefaultPort
updatedPort
=
new
DefaultPort
(
device
,
portDescription
.
portNumber
(),
portDescription
.
isEnabled
());
ports
.
put
(
port
.
number
(),
updatedPort
);
updatePortMap
(
device
.
id
(),
ports
);
return
new
DeviceEvent
(
PORT_UPDATED
,
device
,
updatedPort
);
}
return
null
;
}
// Prunes the specified list of ports based on which ports are in the
// processed list and returns list of corresponding events.
//@GuardedBy("this")
private
List
<
DeviceEvent
>
pruneOldPorts
(
Device
device
,
Map
<
PortNumber
,
Port
>
ports
,
Set
<
PortNumber
>
processed
)
{
List
<
DeviceEvent
>
events
=
new
ArrayList
<>();
Iterator
<
PortNumber
>
iterator
=
ports
.
keySet
().
iterator
();
while
(
iterator
.
hasNext
())
{
PortNumber
portNumber
=
iterator
.
next
();
if
(!
processed
.
contains
(
portNumber
))
{
events
.
add
(
new
DeviceEvent
(
PORT_REMOVED
,
device
,
ports
.
get
(
portNumber
)));
iterator
.
remove
();
}
}
if
(!
events
.
isEmpty
())
{
updatePortMap
(
device
.
id
(),
ports
);
}
return
events
;
}
// Gets the map of ports for the specified device; if one does not already
// exist, it creates and registers a new one.
// WARN: returned value is a copy, changes made to the Map
// needs to be written back using updatePortMap
//@GuardedBy("this")
private
Map
<
PortNumber
,
Port
>
getPortMap
(
DeviceId
deviceId
)
{
Map
<
PortNumber
,
Port
>
ports
=
devicePorts
.
getUnchecked
(
deviceId
).
orNull
();
if
(
ports
==
null
)
{
ports
=
new
HashMap
<>();
// this probably is waste of time in most cases.
updatePortMap
(
deviceId
,
ports
);
}
return
ports
;
}
//@GuardedBy("this")
private
void
updatePortMap
(
DeviceId
deviceId
,
Map
<
PortNumber
,
Port
>
ports
)
{
rawDevicePorts
.
put
(
serialize
(
deviceId
),
serialize
(
ports
));
devicePorts
.
put
(
deviceId
,
Optional
.
of
(
ports
));
}
@Override
public
DeviceEvent
updatePortStatus
(
ProviderId
providerId
,
DeviceId
deviceId
,
PortDescription
portDescription
)
{
synchronized
(
this
)
{
Device
device
=
devices
.
getUnchecked
(
deviceId
).
orNull
();
checkArgument
(
device
!=
null
,
DEVICE_NOT_FOUND
,
deviceId
);
Map
<
PortNumber
,
Port
>
ports
=
getPortMap
(
deviceId
);
Port
port
=
ports
.
get
(
portDescription
.
portNumber
());
return
updatePort
(
device
,
port
,
portDescription
,
ports
);
}
}
@Override
public
List
<
Port
>
getPorts
(
DeviceId
deviceId
)
{
Map
<
PortNumber
,
Port
>
ports
=
devicePorts
.
getUnchecked
(
deviceId
).
orNull
();
return
ports
==
null
?
Collections
.<
Port
>
emptyList
()
:
ImmutableList
.
copyOf
(
ports
.
values
());
}
@Override
public
Port
getPort
(
DeviceId
deviceId
,
PortNumber
portNumber
)
{
Map
<
PortNumber
,
Port
>
ports
=
devicePorts
.
getUnchecked
(
deviceId
).
orNull
();
return
ports
==
null
?
null
:
ports
.
get
(
portNumber
);
}
@Override
public
boolean
isAvailable
(
DeviceId
deviceId
)
{
return
availableDevices
.
contains
(
serialize
(
deviceId
));
}
@Override
public
DeviceEvent
removeDevice
(
DeviceId
deviceId
)
{
synchronized
(
this
)
{
byte
[]
deviceIdBytes
=
serialize
(
deviceId
);
// TODO conditional remove?
Device
device
=
deserialize
(
rawDevices
.
remove
(
deviceIdBytes
));
devices
.
invalidate
(
deviceId
);
return
device
==
null
?
null
:
new
DeviceEvent
(
DEVICE_REMOVED
,
device
,
null
);
}
}
private
class
RemoteDeviceEventHandler
extends
RemoteCacheEventHandler
<
DeviceId
,
DefaultDevice
>
{
public
RemoteDeviceEventHandler
(
LoadingCache
<
DeviceId
,
Optional
<
DefaultDevice
>>
cache
)
{
super
(
cache
);
}
@Override
protected
void
onAdd
(
DeviceId
deviceId
,
DefaultDevice
device
)
{
notifyDelegate
(
new
DeviceEvent
(
DEVICE_ADDED
,
device
));
}
@Override
protected
void
onRemove
(
DeviceId
deviceId
,
DefaultDevice
device
)
{
notifyDelegate
(
new
DeviceEvent
(
DEVICE_REMOVED
,
device
));
}
@Override
protected
void
onUpdate
(
DeviceId
deviceId
,
DefaultDevice
oldDevice
,
DefaultDevice
device
)
{
notifyDelegate
(
new
DeviceEvent
(
DEVICE_UPDATED
,
device
));
}
}
private
class
RemotePortEventHandler
extends
RemoteCacheEventHandler
<
DeviceId
,
Map
<
PortNumber
,
Port
>>
{
public
RemotePortEventHandler
(
LoadingCache
<
DeviceId
,
Optional
<
Map
<
PortNumber
,
Port
>>>
cache
)
{
super
(
cache
);
}
@Override
protected
void
onAdd
(
DeviceId
deviceId
,
Map
<
PortNumber
,
Port
>
ports
)
{
// notifyDelegate(new DeviceEvent(PORT_ADDED, getDevice(deviceId)));
}
@Override
protected
void
onRemove
(
DeviceId
deviceId
,
Map
<
PortNumber
,
Port
>
ports
)
{
// notifyDelegate(new DeviceEvent(PORT_REMOVED, getDevice(deviceId)));
}
@Override
protected
void
onUpdate
(
DeviceId
deviceId
,
Map
<
PortNumber
,
Port
>
oldPorts
,
Map
<
PortNumber
,
Port
>
ports
)
{
// notifyDelegate(new DeviceEvent(PORT_UPDATED, getDevice(deviceId)));
}
}
// TODO cache serialized DeviceID if we suffer from serialization cost
}
core/store/hz/net/src/test/java/org/onlab/onos/store/device/impl/DistributedDeviceStoreTest.java
deleted
100644 → 0
View file @
a309989
/**
*
*/
package
org
.
onlab
.
onos
.
store
.
device
.
impl
;
import
static
org
.
junit
.
Assert
.*;
import
static
org
.
onlab
.
onos
.
net
.
Device
.
Type
.
SWITCH
;
import
static
org
.
onlab
.
onos
.
net
.
DeviceId
.
deviceId
;
import
static
org
.
onlab
.
onos
.
net
.
device
.
DeviceEvent
.
Type
.*;
import
java.util.Arrays
;
import
java.util.HashMap
;
import
java.util.List
;
import
java.util.Map
;
import
java.util.Set
;
import
java.util.concurrent.CountDownLatch
;
import
java.util.concurrent.TimeUnit
;
import
org.junit.After
;
import
org.junit.AfterClass
;
import
org.junit.Before
;
import
org.junit.BeforeClass
;
import
org.junit.Ignore
;
import
org.junit.Test
;
import
org.onlab.onos.net.Device
;
import
org.onlab.onos.net.DeviceId
;
import
org.onlab.onos.net.Port
;
import
org.onlab.onos.net.PortNumber
;
import
org.onlab.onos.net.device.DefaultDeviceDescription
;
import
org.onlab.onos.net.device.DefaultPortDescription
;
import
org.onlab.onos.net.device.DeviceDescription
;
import
org.onlab.onos.net.device.DeviceEvent
;
import
org.onlab.onos.net.device.DeviceStoreDelegate
;
import
org.onlab.onos.net.device.PortDescription
;
import
org.onlab.onos.net.provider.ProviderId
;
import
org.onlab.onos.store.common.StoreManager
;
import
org.onlab.onos.store.common.StoreService
;
import
org.onlab.onos.store.common.TestStoreManager
;
import
com.google.common.collect.Iterables
;
import
com.google.common.collect.Sets
;
import
com.hazelcast.config.Config
;
import
com.hazelcast.core.Hazelcast
;
import
org.onlab.packet.ChassisId
;
/**
* Test of the Hazelcast based distributed DeviceStore implementation.
*/
public
class
DistributedDeviceStoreTest
{
private
static
final
ProviderId
PID
=
new
ProviderId
(
"of"
,
"foo"
);
private
static
final
DeviceId
DID1
=
deviceId
(
"of:foo"
);
private
static
final
DeviceId
DID2
=
deviceId
(
"of:bar"
);
private
static
final
String
MFR
=
"whitebox"
;
private
static
final
String
HW
=
"1.1.x"
;
private
static
final
String
SW1
=
"3.8.1"
;
private
static
final
String
SW2
=
"3.9.5"
;
private
static
final
String
SN
=
"43311-12345"
;
private
static
final
ChassisId
CID
=
new
ChassisId
();
private
static
final
PortNumber
P1
=
PortNumber
.
portNumber
(
1
);
private
static
final
PortNumber
P2
=
PortNumber
.
portNumber
(
2
);
private
static
final
PortNumber
P3
=
PortNumber
.
portNumber
(
3
);
private
DistributedDeviceStore
deviceStore
;
private
StoreManager
storeManager
;
@BeforeClass
public
static
void
setUpBeforeClass
()
throws
Exception
{
}
@AfterClass
public
static
void
tearDownAfterClass
()
throws
Exception
{
}
@Before
public
void
setUp
()
throws
Exception
{
// TODO should find a way to clean Hazelcast instance without shutdown.
Config
config
=
TestStoreManager
.
getTestConfig
();
storeManager
=
new
TestStoreManager
(
Hazelcast
.
newHazelcastInstance
(
config
));
storeManager
.
activate
();
deviceStore
=
new
TestDistributedDeviceStore
(
storeManager
);
deviceStore
.
activate
();
}
@After
public
void
tearDown
()
throws
Exception
{
deviceStore
.
deactivate
();
storeManager
.
deactivate
();
}
private
void
putDevice
(
DeviceId
deviceId
,
String
swVersion
)
{
DeviceDescription
description
=
new
DefaultDeviceDescription
(
deviceId
.
uri
(),
SWITCH
,
MFR
,
HW
,
swVersion
,
SN
,
CID
);
deviceStore
.
createOrUpdateDevice
(
PID
,
deviceId
,
description
);
}
private
static
void
assertDevice
(
DeviceId
id
,
String
swVersion
,
Device
device
)
{
assertNotNull
(
device
);
assertEquals
(
id
,
device
.
id
());
assertEquals
(
MFR
,
device
.
manufacturer
());
assertEquals
(
HW
,
device
.
hwVersion
());
assertEquals
(
swVersion
,
device
.
swVersion
());
assertEquals
(
SN
,
device
.
serialNumber
());
}
@Test
public
final
void
testGetDeviceCount
()
{
assertEquals
(
"initialy empty"
,
0
,
deviceStore
.
getDeviceCount
());
putDevice
(
DID1
,
SW1
);
putDevice
(
DID2
,
SW2
);
putDevice
(
DID1
,
SW1
);
assertEquals
(
"expect 2 uniq devices"
,
2
,
deviceStore
.
getDeviceCount
());
}
@Test
public
final
void
testGetDevices
()
{
assertEquals
(
"initialy empty"
,
0
,
Iterables
.
size
(
deviceStore
.
getDevices
()));
putDevice
(
DID1
,
SW1
);
putDevice
(
DID2
,
SW2
);
putDevice
(
DID1
,
SW1
);
assertEquals
(
"expect 2 uniq devices"
,
2
,
Iterables
.
size
(
deviceStore
.
getDevices
()));
Map
<
DeviceId
,
Device
>
devices
=
new
HashMap
<>();
for
(
Device
device
:
deviceStore
.
getDevices
())
{
devices
.
put
(
device
.
id
(),
device
);
}
assertDevice
(
DID1
,
SW1
,
devices
.
get
(
DID1
));
assertDevice
(
DID2
,
SW2
,
devices
.
get
(
DID2
));
// add case for new node?
}
@Test
public
final
void
testGetDevice
()
{
putDevice
(
DID1
,
SW1
);
assertDevice
(
DID1
,
SW1
,
deviceStore
.
getDevice
(
DID1
));
assertNull
(
"DID2 shouldn't be there"
,
deviceStore
.
getDevice
(
DID2
));
}
@Test
public
final
void
testCreateOrUpdateDevice
()
{
DeviceDescription
description
=
new
DefaultDeviceDescription
(
DID1
.
uri
(),
SWITCH
,
MFR
,
HW
,
SW1
,
SN
,
CID
);
DeviceEvent
event
=
deviceStore
.
createOrUpdateDevice
(
PID
,
DID1
,
description
);
assertEquals
(
DEVICE_ADDED
,
event
.
type
());
assertDevice
(
DID1
,
SW1
,
event
.
subject
());
DeviceDescription
description2
=
new
DefaultDeviceDescription
(
DID1
.
uri
(),
SWITCH
,
MFR
,
HW
,
SW2
,
SN
,
CID
);
DeviceEvent
event2
=
deviceStore
.
createOrUpdateDevice
(
PID
,
DID1
,
description2
);
assertEquals
(
DEVICE_UPDATED
,
event2
.
type
());
assertDevice
(
DID1
,
SW2
,
event2
.
subject
());
assertNull
(
"No change expected"
,
deviceStore
.
createOrUpdateDevice
(
PID
,
DID1
,
description2
));
}
@Test
public
final
void
testMarkOffline
()
{
putDevice
(
DID1
,
SW1
);
assertTrue
(
deviceStore
.
isAvailable
(
DID1
));
DeviceEvent
event
=
deviceStore
.
markOffline
(
DID1
);
assertEquals
(
DEVICE_AVAILABILITY_CHANGED
,
event
.
type
());
assertDevice
(
DID1
,
SW1
,
event
.
subject
());
assertFalse
(
deviceStore
.
isAvailable
(
DID1
));
DeviceEvent
event2
=
deviceStore
.
markOffline
(
DID1
);
assertNull
(
"No change, no event"
,
event2
);
}
@Test
public
final
void
testUpdatePorts
()
{
putDevice
(
DID1
,
SW1
);
List
<
PortDescription
>
pds
=
Arrays
.<
PortDescription
>
asList
(
new
DefaultPortDescription
(
P1
,
true
),
new
DefaultPortDescription
(
P2
,
true
)
);
List
<
DeviceEvent
>
events
=
deviceStore
.
updatePorts
(
PID
,
DID1
,
pds
);
Set
<
PortNumber
>
expectedPorts
=
Sets
.
newHashSet
(
P1
,
P2
);
for
(
DeviceEvent
event
:
events
)
{
assertEquals
(
PORT_ADDED
,
event
.
type
());
assertDevice
(
DID1
,
SW1
,
event
.
subject
());
assertTrue
(
"PortNumber is one of expected"
,
expectedPorts
.
remove
(
event
.
port
().
number
()));
assertTrue
(
"Port is enabled"
,
event
.
port
().
isEnabled
());
}
assertTrue
(
"Event for all expectedport appeared"
,
expectedPorts
.
isEmpty
());
List
<
PortDescription
>
pds2
=
Arrays
.<
PortDescription
>
asList
(
new
DefaultPortDescription
(
P1
,
false
),
new
DefaultPortDescription
(
P2
,
true
),
new
DefaultPortDescription
(
P3
,
true
)
);
events
=
deviceStore
.
updatePorts
(
PID
,
DID1
,
pds2
);
assertFalse
(
"event should be triggered"
,
events
.
isEmpty
());
for
(
DeviceEvent
event
:
events
)
{
PortNumber
num
=
event
.
port
().
number
();
if
(
P1
.
equals
(
num
))
{
assertEquals
(
PORT_UPDATED
,
event
.
type
());
assertDevice
(
DID1
,
SW1
,
event
.
subject
());
assertFalse
(
"Port is disabled"
,
event
.
port
().
isEnabled
());
}
else
if
(
P2
.
equals
(
num
))
{
fail
(
"P2 event not expected."
);
}
else
if
(
P3
.
equals
(
num
))
{
assertEquals
(
PORT_ADDED
,
event
.
type
());
assertDevice
(
DID1
,
SW1
,
event
.
subject
());
assertTrue
(
"Port is enabled"
,
event
.
port
().
isEnabled
());
}
else
{
fail
(
"Unknown port number encountered: "
+
num
);
}
}
List
<
PortDescription
>
pds3
=
Arrays
.<
PortDescription
>
asList
(
new
DefaultPortDescription
(
P1
,
false
),
new
DefaultPortDescription
(
P2
,
true
)
);
events
=
deviceStore
.
updatePorts
(
PID
,
DID1
,
pds3
);
assertFalse
(
"event should be triggered"
,
events
.
isEmpty
());
for
(
DeviceEvent
event
:
events
)
{
PortNumber
num
=
event
.
port
().
number
();
if
(
P1
.
equals
(
num
))
{
fail
(
"P1 event not expected."
);
}
else
if
(
P2
.
equals
(
num
))
{
fail
(
"P2 event not expected."
);
}
else
if
(
P3
.
equals
(
num
))
{
assertEquals
(
PORT_REMOVED
,
event
.
type
());
assertDevice
(
DID1
,
SW1
,
event
.
subject
());
assertTrue
(
"Port was enabled"
,
event
.
port
().
isEnabled
());
}
else
{
fail
(
"Unknown port number encountered: "
+
num
);
}
}
}
@Test
public
final
void
testUpdatePortStatus
()
{
putDevice
(
DID1
,
SW1
);
List
<
PortDescription
>
pds
=
Arrays
.<
PortDescription
>
asList
(
new
DefaultPortDescription
(
P1
,
true
)
);
deviceStore
.
updatePorts
(
PID
,
DID1
,
pds
);
DeviceEvent
event
=
deviceStore
.
updatePortStatus
(
PID
,
DID1
,
new
DefaultPortDescription
(
P1
,
false
));
assertEquals
(
PORT_UPDATED
,
event
.
type
());
assertDevice
(
DID1
,
SW1
,
event
.
subject
());
assertEquals
(
P1
,
event
.
port
().
number
());
assertFalse
(
"Port is disabled"
,
event
.
port
().
isEnabled
());
}
@Test
public
final
void
testGetPorts
()
{
putDevice
(
DID1
,
SW1
);
putDevice
(
DID2
,
SW1
);
List
<
PortDescription
>
pds
=
Arrays
.<
PortDescription
>
asList
(
new
DefaultPortDescription
(
P1
,
true
),
new
DefaultPortDescription
(
P2
,
true
)
);
deviceStore
.
updatePorts
(
PID
,
DID1
,
pds
);
Set
<
PortNumber
>
expectedPorts
=
Sets
.
newHashSet
(
P1
,
P2
);
List
<
Port
>
ports
=
deviceStore
.
getPorts
(
DID1
);
for
(
Port
port
:
ports
)
{
assertTrue
(
"Port is enabled"
,
port
.
isEnabled
());
assertTrue
(
"PortNumber is one of expected"
,
expectedPorts
.
remove
(
port
.
number
()));
}
assertTrue
(
"Event for all expectedport appeared"
,
expectedPorts
.
isEmpty
());
assertTrue
(
"DID2 has no ports"
,
deviceStore
.
getPorts
(
DID2
).
isEmpty
());
}
@Test
public
final
void
testGetPort
()
{
putDevice
(
DID1
,
SW1
);
putDevice
(
DID2
,
SW1
);
List
<
PortDescription
>
pds
=
Arrays
.<
PortDescription
>
asList
(
new
DefaultPortDescription
(
P1
,
true
),
new
DefaultPortDescription
(
P2
,
false
)
);
deviceStore
.
updatePorts
(
PID
,
DID1
,
pds
);
Port
port1
=
deviceStore
.
getPort
(
DID1
,
P1
);
assertEquals
(
P1
,
port1
.
number
());
assertTrue
(
"Port is enabled"
,
port1
.
isEnabled
());
Port
port2
=
deviceStore
.
getPort
(
DID1
,
P2
);
assertEquals
(
P2
,
port2
.
number
());
assertFalse
(
"Port is disabled"
,
port2
.
isEnabled
());
Port
port3
=
deviceStore
.
getPort
(
DID1
,
P3
);
assertNull
(
"P3 not expected"
,
port3
);
}
@Test
public
final
void
testRemoveDevice
()
{
putDevice
(
DID1
,
SW1
);
putDevice
(
DID2
,
SW1
);
assertEquals
(
2
,
deviceStore
.
getDeviceCount
());
DeviceEvent
event
=
deviceStore
.
removeDevice
(
DID1
);
assertEquals
(
DEVICE_REMOVED
,
event
.
type
());
assertDevice
(
DID1
,
SW1
,
event
.
subject
());
assertEquals
(
1
,
deviceStore
.
getDeviceCount
());
}
// TODO add test for Port events when we have them
@Ignore
(
"Ignore until Delegate spec. is clear."
)
@Test
public
final
void
testEvents
()
throws
InterruptedException
{
final
CountDownLatch
addLatch
=
new
CountDownLatch
(
1
);
DeviceStoreDelegate
checkAdd
=
new
DeviceStoreDelegate
()
{
@Override
public
void
notify
(
DeviceEvent
event
)
{
assertEquals
(
DEVICE_ADDED
,
event
.
type
());
assertDevice
(
DID1
,
SW1
,
event
.
subject
());
addLatch
.
countDown
();
}
};
final
CountDownLatch
updateLatch
=
new
CountDownLatch
(
1
);
DeviceStoreDelegate
checkUpdate
=
new
DeviceStoreDelegate
()
{
@Override
public
void
notify
(
DeviceEvent
event
)
{
assertEquals
(
DEVICE_UPDATED
,
event
.
type
());
assertDevice
(
DID1
,
SW2
,
event
.
subject
());
updateLatch
.
countDown
();
}
};
final
CountDownLatch
removeLatch
=
new
CountDownLatch
(
1
);
DeviceStoreDelegate
checkRemove
=
new
DeviceStoreDelegate
()
{
@Override
public
void
notify
(
DeviceEvent
event
)
{
assertEquals
(
DEVICE_REMOVED
,
event
.
type
());
assertDevice
(
DID1
,
SW2
,
event
.
subject
());
removeLatch
.
countDown
();
}
};
DeviceDescription
description
=
new
DefaultDeviceDescription
(
DID1
.
uri
(),
SWITCH
,
MFR
,
HW
,
SW1
,
SN
,
CID
);
deviceStore
.
setDelegate
(
checkAdd
);
deviceStore
.
createOrUpdateDevice
(
PID
,
DID1
,
description
);
assertTrue
(
"Add event fired"
,
addLatch
.
await
(
1
,
TimeUnit
.
SECONDS
));
DeviceDescription
description2
=
new
DefaultDeviceDescription
(
DID1
.
uri
(),
SWITCH
,
MFR
,
HW
,
SW2
,
SN
,
CID
);
deviceStore
.
unsetDelegate
(
checkAdd
);
deviceStore
.
setDelegate
(
checkUpdate
);
deviceStore
.
createOrUpdateDevice
(
PID
,
DID1
,
description2
);
assertTrue
(
"Update event fired"
,
updateLatch
.
await
(
1
,
TimeUnit
.
SECONDS
));
deviceStore
.
unsetDelegate
(
checkUpdate
);
deviceStore
.
setDelegate
(
checkRemove
);
deviceStore
.
removeDevice
(
DID1
);
assertTrue
(
"Remove event fired"
,
removeLatch
.
await
(
1
,
TimeUnit
.
SECONDS
));
}
private
class
TestDistributedDeviceStore
extends
DistributedDeviceStore
{
public
TestDistributedDeviceStore
(
StoreService
storeService
)
{
this
.
storeService
=
storeService
;
}
}
}
Please
register
or
login
to post a comment