Madan Jampani
Committed by Gerrit Code Review

Remove deprecated code.

Change-Id: Ifd68e4ddfaade2a8dd7de43a83bf222b48b9291b
Showing 26 changed files with 3 additions and 2792 deletions
/*
* Copyright 2014 Open Networking Laboratory
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.cli;
import org.apache.karaf.shell.commands.Argument;
import org.apache.karaf.shell.commands.Command;
import org.onlab.packet.IpAddress;
import org.onosproject.cluster.ControllerNode;
import org.onosproject.cluster.DefaultControllerNode;
import org.onosproject.cluster.NodeId;
import org.onosproject.store.service.DatabaseAdminService;
/**
* Adds a new controller cluster node.
*/
@Command(scope = "onos", name = "tablet-add",
description = "Adds a new member to tablet")
public class TabletAddCommand extends AbstractShellCommand {
@Argument(index = 0, name = "nodeId", description = "Node ID",
required = true, multiValued = false)
String nodeId = null;
@Argument(index = 1, name = "ip", description = "Node IP address",
required = true, multiValued = false)
String ip = null;
@Argument(index = 2, name = "tcpPort", description = "Node TCP listen port",
required = false, multiValued = false)
int tcpPort = 9876;
// TODO add tablet name argument when we support multiple tablets
@Override
protected void execute() {
DatabaseAdminService service = get(DatabaseAdminService.class);
ControllerNode node = new DefaultControllerNode(new NodeId(nodeId),
IpAddress.valueOf(ip),
tcpPort);
service.addMember(node);
}
}
/*
* Copyright 2014 Open Networking Laboratory
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.cli;
import org.apache.karaf.shell.commands.Command;
import org.onosproject.cluster.ControllerNode;
import org.onosproject.store.service.DatabaseAdminService;
import java.util.Optional;
/**
* Lists mastership roles of nodes for each device.
*/
@Command(scope = "onos", name = "tablet-leader",
description = "Prints the current leader of a tablet.")
public class TabletLeaderCommand extends AbstractShellCommand {
@Override
protected void execute() {
final DatabaseAdminService dbAdminService = get(DatabaseAdminService.class);
Optional<ControllerNode> leader = dbAdminService.leader();
if (leader.isPresent()) {
print("Leader: %s", leader.get());
} else {
print("No Leader");
}
}
}
/*
* Copyright 2014 Open Networking Laboratory
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.cli;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ArrayNode;
import org.apache.karaf.shell.commands.Command;
import org.onosproject.cluster.ClusterService;
import org.onosproject.cluster.ControllerNode;
import org.onosproject.store.service.DatabaseAdminService;
import java.util.Collections;
import java.util.List;
import static com.google.common.collect.Lists.newArrayList;
/**
* Lists all controller cluster nodes.
*/
@Command(scope = "onos", name = "tablet-member",
description = "Lists all member nodes")
public class TabletMemberCommand extends AbstractShellCommand {
// TODO add tablet name argument when we support multiple tablets
@Override
protected void execute() {
DatabaseAdminService service = get(DatabaseAdminService.class);
ClusterService clusterService = get(ClusterService.class);
List<ControllerNode> nodes = newArrayList(service.listMembers());
Collections.sort(nodes, Comparators.NODE_COMPARATOR);
if (outputJson()) {
print("%s", json(service, nodes));
} else {
ControllerNode self = clusterService.getLocalNode();
for (ControllerNode node : nodes) {
print("id=%s, address=%s:%s %s",
node.id(), node.ip(), node.tcpPort(),
node.equals(self) ? "*" : "");
}
}
}
// Produces JSON structure.
private JsonNode json(DatabaseAdminService service, List<ControllerNode> nodes) {
ObjectMapper mapper = new ObjectMapper();
ArrayNode result = mapper.createArrayNode();
for (ControllerNode node : nodes) {
result.add(mapper.createObjectNode()
.put("id", node.id().toString())
.put("ip", node.ip().toString())
.put("tcpPort", node.tcpPort()));
}
return result;
}
}
/*
* Copyright 2014 Open Networking Laboratory
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.cli;
import org.apache.karaf.shell.commands.Argument;
import org.apache.karaf.shell.commands.Command;
import org.onosproject.cluster.ClusterService;
import org.onosproject.cluster.ControllerNode;
import org.onosproject.cluster.NodeId;
import org.onosproject.store.service.DatabaseAdminService;
/**
* Removes a controller cluster node.
*/
@Command(scope = "onos", name = "tablet-remove",
description = "Removes a member from tablet")
public class TabletRemoveCommand extends AbstractShellCommand {
@Argument(index = 0, name = "nodeId", description = "Node ID",
required = true, multiValued = false)
String nodeId = null;
// TODO add tablet name argument when we support multiple tablets
@Override
protected void execute() {
DatabaseAdminService service = get(DatabaseAdminService.class);
ClusterService clusterService = get(ClusterService.class);
ControllerNode node = clusterService.getNode(new NodeId(nodeId));
if (node != null) {
service.removeMember(node);
}
}
}
......@@ -53,33 +53,6 @@
</command>
<command>
<action class="org.onosproject.cli.TabletMemberCommand"/>
</command>
<command>
<action class="org.onosproject.cli.TabletLeaderCommand"/>
</command>
<!--
<command>
<action class="org.onosproject.cli.TabletAddCommand"/>
<completers>
<ref component-id="nodeIdCompleter"/>
<null/>
<null/>
</completers>
</command>
<command>
<action class="org.onosproject.cli.TabletRemoveCommand"/>
<completers>
<ref component-id="nodeIdCompleter"/>
<null/>
<null/>
</completers>
</command>
-->
<command>
<action class="org.onosproject.cli.NodesListCommand"/>
</command>
<!--
......
/*
* Copyright 2014 Open Networking Laboratory
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.store.service;
import java.util.List;
import com.google.common.base.MoreObjects;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
/**
* Collection of read requests to be submitted as one batch.
*/
public final class BatchReadRequest {
private final List<ReadRequest> readRequests;
/**
* Creates a new BatchReadRequest object from the specified list of read requests.
* @param readRequests read requests.
* @return BatchReadRequest object.
*/
public static BatchReadRequest create(List<ReadRequest> readRequests) {
return new BatchReadRequest(readRequests);
}
private BatchReadRequest(List<ReadRequest> readRequests) {
this.readRequests = ImmutableList.copyOf(readRequests);
}
/**
* Returns the number of requests in this batch.
* @return size of request batch.
*/
public int batchSize() {
return readRequests.size();
}
/**
* Returns the requests in this batch as a list.
* @return list of read requests
*/
public List<ReadRequest> getAsList() {
return readRequests;
}
@Override
public String toString() {
return MoreObjects.toStringHelper(getClass())
.add("readRequests", readRequests)
.toString();
}
/**
* Builder for BatchReadRequest.
*/
public static class Builder {
private final List<ReadRequest> readRequests = Lists.newLinkedList();
/**
* Append a get request.
* @param tableName table name
* @param key key to fetch.
* @return this Builder
*/
public Builder get(String tableName, String key) {
readRequests.add(new ReadRequest(tableName, key));
return this;
}
/**
* Builds a BatchReadRequest.
* @return BatchReadRequest
*/
public BatchReadRequest build() {
return new BatchReadRequest(readRequests);
}
}
}
/*
* Copyright 2014 Open Networking Laboratory
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.store.service;
import java.util.List;
import com.google.common.base.MoreObjects;
import com.google.common.collect.ImmutableList;
/**
* Result of a batch read operation.
*/
public class BatchReadResult {
private final List<ReadResult> readResults;
public BatchReadResult(List<ReadResult> readResults) {
this.readResults = ImmutableList.copyOf(readResults);
}
/**
* Returns the results as a list.
* @return list of results
*/
public List<ReadResult> getAsList() {
return readResults;
}
/**
* Returns the batch size.
* @return batch size
*/
public int batchSize() {
return readResults.size();
}
@Override
public String toString() {
return MoreObjects.toStringHelper(getClass())
.add("readResults", readResults)
.toString();
}
}
/*
* Copyright 2014 Open Networking Laboratory
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.store.service;
import java.util.List;
import com.google.common.base.MoreObjects;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
/**
* Collection of write requests to be submitted as one batch.
*/
public final class BatchWriteRequest {
private final List<WriteRequest> writeRequests;
/**
* Creates a new BatchWriteRequest object from the specified list of write requests.
* @param writeRequests write requests.
* @return BatchWriteRequest object.
*/
public static BatchWriteRequest create(List<WriteRequest> writeRequests) {
return new BatchWriteRequest(writeRequests);
}
private BatchWriteRequest(List<WriteRequest> writeRequests) {
this.writeRequests = ImmutableList.copyOf(writeRequests);
}
/**
* Returns the requests in this batch as a list.
* @return list of write requests
*/
public List<WriteRequest> getAsList() {
return writeRequests;
}
/**
* Returns the number of requests in this batch.
* @return size of request batch.
*/
public int batchSize() {
return writeRequests.size();
}
@Override
public String toString() {
return MoreObjects.toStringHelper(getClass())
.add("writeRequests", writeRequests)
.toString();
}
public static Builder newBuilder() {
return new Builder();
}
/**
* Builder for BatchWriteRequest.
*/
public static class Builder {
private final List<WriteRequest> writeRequests = Lists.newLinkedList();
public Builder put(String tableName, String key, byte[] value) {
writeRequests.add(WriteRequest.put(tableName, key, value));
return this;
}
public Builder putIfAbsent(String tableName, String key, byte[] value) {
writeRequests.add(WriteRequest.putIfAbsent(tableName, key, value));
return this;
}
public Builder putIfValueMatches(String tableName, String key, byte[] oldValue, byte[] newValue) {
writeRequests.add(WriteRequest.putIfValueMatches(tableName, key, oldValue, newValue));
return this;
}
public Builder putIfVersionMatches(String tableName, String key, byte[] value, long version) {
writeRequests.add(WriteRequest.putIfVersionMatches(tableName, key, value, version));
return this;
}
public Builder remove(String tableName, String key) {
writeRequests.add(WriteRequest.remove(tableName, key));
return this;
}
public Builder removeIfVersionMatches(String tableName, String key, long version) {
writeRequests.add(WriteRequest.removeIfVersionMatches(tableName, key, version));
return this;
}
public Builder removeIfValueMatches(String tableName, String key, byte[] value) {
writeRequests.add(WriteRequest.removeIfValueMatches(tableName, key, value));
return this;
}
public BatchWriteRequest build() {
return new BatchWriteRequest(writeRequests);
}
}
}
/*
* Copyright 2014 Open Networking Laboratory
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.store.service;
import java.util.List;
import com.google.common.base.MoreObjects;
import com.google.common.collect.ImmutableList;
/**
* Result of a batch write operation.
*/
public class BatchWriteResult {
private final List<WriteResult> writeResults;
public BatchWriteResult(List<WriteResult> writeResults) {
this.writeResults = ImmutableList.copyOf(writeResults);
}
/**
* Returns true if this batch write operation was successful.
* @return true if successful, false otherwise.
*/
public boolean isSuccessful() {
for (WriteResult result : writeResults) {
if (result.status() != WriteStatus.OK) {
return false;
}
}
return true;
}
/**
* Returns the results as a List.
* @return list of batch results.
*/
public List<WriteResult> getAsList() {
return this.writeResults;
}
/**
* Returns the size of this batch.
* @return batch size.
*/
public int batchSize() {
return writeResults.size();
}
@Override
public String toString() {
return MoreObjects.toStringHelper(getClass())
.add("writeResults", writeResults)
.toString();
}
}
/*
* Copyright 2014 Open Networking Laboratory
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.store.service;
import java.util.Collection;
import java.util.Optional;
import java.util.Set;
import org.onosproject.cluster.ControllerNode;
/**
* Service interface for running administrative tasks on a Database.
*/
public interface DatabaseAdminService {
/**
* Creates a new table.
* Table creation is idempotent. Attempting to create a table
* that already exists will be a noop.
* @param name table name.
* @return true if the table was created by this call, false otherwise.
*/
public boolean createTable(String name);
/**
* Creates a new table where last update time will be used to track and expire old entries.
* Table creation is idempotent. Attempting to create a table
* that already exists will be a noop.
* @param name table name.
* @param ttlMillis total duration in millis since last update time when entries will be expired.
* @return true if the table was created by this call, false otherwise.
*/
public boolean createTable(String name, int ttlMillis);
/**
* Lists all the tables in the database.
* @return set of table names.
*/
public Set<String> listTables();
/**
* Deletes a table from the database.
* @param name name of the table to delete.
*/
public void dropTable(String name);
/**
* Deletes all tables from the database.
*/
public void dropAllTables();
/**
* Add member to default Tablet.
*
* @param node to add
*/
public void addMember(ControllerNode node);
/**
* Remove member from default Tablet.
*
* @param node node to remove
*/
public void removeMember(ControllerNode node);
/**
* List members forming default Tablet.
*
* @return Copied collection of members forming default Tablet.
*/
public Collection<ControllerNode> listMembers();
/**
* Returns the current Leader of the default Tablet.
*
* @return leader node
*/
public Optional<ControllerNode> leader();
}
/*
* Copyright 2014 Open Networking Laboratory
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.store.service;
/**
* Base exception type for database failures.
*/
@SuppressWarnings("serial")
public class DatabaseException extends RuntimeException {
public DatabaseException(String message, Throwable t) {
super(message, t);
}
public DatabaseException(String message) {
super(message);
}
public DatabaseException(Throwable t) {
super(t);
}
public DatabaseException() {
};
public static class Timeout extends DatabaseException {
public Timeout(String message, Throwable t) {
super(message, t);
}
public Timeout(String message) {
super(message);
}
public Timeout(Throwable t) {
super(t);
}
}
}
/*
* Copyright 2014 Open Networking Laboratory
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.store.service;
import java.util.Map;
/**
* Service interface for a strongly consistent and durable
* key value data store.
*/
public interface DatabaseService {
/**
* Reads the specified key.
* @param tableName name of the table associated with this operation.
* @param key key to read.
* @return value (and version) associated with this key. This calls returns null if the key does not exist.
*/
VersionedValue get(String tableName, String key);
/**
* Reads the whole table.
*
* @param tableName name of the table associated with this operation.
* @return the whole table
*/
Map<String, VersionedValue> getAll(String tableName);
/**
* Associate the key with a value.
* @param tableName table name in which this key/value resides.
* @param key key with which the specified value is to be associated
* @param value value to be associated with the specified key
* @return the previous value associated with the specified key, or null if there was no mapping for the key.
*/
VersionedValue put(String tableName, String key, byte[] value);
/**
* If the specified key is not already associated with a value, associate it with the given value.
* @param tableName table name in which this key/value resides.
* @param key key with which the specified value is to be associated
* @param value value to be associated with the specified key
* @return true if put was successful, false if there is already a value associated with this key
*/
boolean putIfAbsent(String tableName, String key, byte[] value);
/**
* Sets the key to the specified value if the version in the database (for that key)
* matches the specified version.
* @param tableName name of table associated with this operation.
* @param key key
* @param value value
* @param version version that should present in the database for the put to be successful.
* @return true if put was successful, false if there version in database is different from what is specified.
*/
boolean putIfVersionMatches(String tableName, String key, byte[] value, long version);
/**
* Replaces the entry for a key only if currently mapped to a given value.
* @param tableName name of table associated with this operation.
* @param key with which the specified value is associated
* @param oldValue value expected to be associated with the specified key
* @param newValue value to be associated with the specified key
* @return true if put was successful, false if there version in database is different from what is specified.
*/
boolean putIfValueMatches(String tableName, String key, byte[] oldValue, byte[] newValue);
/**
* Removes the key (and associated value).
* @param tableName name of table associated with this operation.
* @param key key to remove
* @return value previously associated with the key. This call returns null if the key does not exist.
*/
VersionedValue remove(String tableName, String key);
/**
* Removes the key (and associated value) if the version in the database matches specified version.
* @param tableName name of table associated with this operation.
* @param key key to remove
* @param version version that should present in the database for the remove to be successful.
* @return true if remove was successful, false if there version in database is different from what is specified.
*/
boolean removeIfVersionMatches(String tableName, String key, long version);
/**
* Removes the key (and associated value) if the value in the database matches specified value.
* @param tableName name of table associated with this operation.
* @param key key to remove
* @param value value that should present in the database for the remove to be successful.
* @return true if remove was successful, false if there value in database is different from what is specified.
*/
boolean removeIfValueMatches(String tableName, String key, byte[] value);
/**
* Performs a batch read operation and returns the results.
* @param batchRequest batch request.
* @return result of the batch operation.
*/
BatchReadResult batchRead(BatchReadRequest batchRequest);
/**
* Performs a batch write operation and returns the results.
* This method provides transactional semantics. Either all writes succeed or none do.
* Even a single write failure would cause the entire batch to be aborted.
* In the case of unsuccessful operation, the batch result can be inspected to determine
* which operation(s) caused the batch to fail.
* @param batchRequest batch request.
* @return result of the batch operation.
*/
BatchWriteResult batchWrite(BatchWriteRequest batchRequest);
}
/*
* Copyright 2014 Open Networking Laboratory
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.store.service;
/**
* Exception thrown when an operation (read or write) is requested for
* a table that does not exist.
*/
@SuppressWarnings("serial")
public class NoSuchTableException extends DatabaseException {
}
/*
* Copyright 2014 Open Networking Laboratory
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.store.service;
/**
* A container object which either has a result or an exception.
* <p>
* If a result is present, get() will return it otherwise get() will throw
* the exception that was encountered in the process of generating the result.
* </p>
* @param <R> type of result.
* @param <E> exception encountered in generating the result.
*/
public interface OptionalResult<R, E extends Throwable> {
/**
* Returns the result or throws an exception if there is no
* valid result.
* @return result
*/
public R get();
/**
* Returns true if there is a valid result.
* @return true is yes, false otherwise.
*/
public boolean hasValidResult();
}
/*
* Copyright 2014 Open Networking Laboratory
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.store.service;
import static com.google.common.base.Preconditions.checkNotNull;
import java.util.Objects;
import com.google.common.base.MoreObjects;
/**
* Database read request.
*/
public class ReadRequest {
private final String tableName;
private final String key;
/**
* Creates a read request,
* which will retrieve the specified key from the table.
*
* @param tableName name of the table
* @param key key in the table
* @return ReadRequest
*/
public static ReadRequest get(String tableName, String key) {
return new ReadRequest(tableName, key);
}
public ReadRequest(String tableName, String key) {
this.tableName = checkNotNull(tableName);
this.key = checkNotNull(key);
}
/**
* Return the name of the table.
* @return table name.
*/
public String tableName() {
return tableName;
}
/**
* Returns the key.
* @return key.
*/
public String key() {
return key;
}
@Override
public String toString() {
return MoreObjects.toStringHelper(getClass())
.add("tableName", tableName)
.add("key", key)
.toString();
}
@Override
public int hashCode() {
return Objects.hash(key, tableName);
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
ReadRequest other = (ReadRequest) obj;
return Objects.equals(this.key, other.key) &&
Objects.equals(this.tableName, other.tableName);
}
}
/*
* Copyright 2014 Open Networking Laboratory
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.store.service;
import com.google.common.base.MoreObjects;
/**
* Database read result.
*/
public class ReadResult {
private final String tableName;
private final String key;
private final VersionedValue value;
private final ReadStatus status;
public ReadResult(ReadStatus status, String tableName, String key, VersionedValue value) {
this.status = status;
this.tableName = tableName;
this.key = key;
this.value = value;
}
/**
* Returns the status of the read operation.
* @return read operation status
*/
public ReadStatus status() {
return status;
}
/**
* Returns database table name.
* @return table name
*/
public String tableName() {
return tableName;
}
/**
* Returns database table key.
* @return key
*/
public String key() {
return key;
}
/**
* Returns true if database table contained value for the key.
*
* @return true if database table contained value for the key
*/
public boolean valueExists() {
return value != null;
}
/**
* Returns value associated with the key.
* @return non-null value if the table contains one, null otherwise.
*/
public VersionedValue value() {
return value;
}
@Override
public String toString() {
return MoreObjects.toStringHelper(getClass())
.add("status", status)
.add("tableName", tableName)
.add("key", key)
.add("value", value)
.toString();
}
}
/*
* Copyright 2014 Open Networking Laboratory
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.store.service;
/**
* Status of completed read request.
*/
public enum ReadStatus {
/**
* Read completed successfully.
*/
OK,
/**
* Read failed due to an invalid table name being specified.
*/
NO_SUCH_TABLE
}
/*
* Copyright 2014 Open Networking Laboratory
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.store.service;
import java.util.Arrays;
import org.onlab.util.ByteArraySizeHashPrinter;
import com.google.common.base.MoreObjects;
/**
* Wrapper object that holds the object (as byte array) and its version.
*/
public class VersionedValue {
private final byte[] value;
private final long version;
/**
* Creates a new instance with the specified value and version.
* @param value value
* @param version version
*/
public VersionedValue(byte[] value, long version) {
this.value = value;
this.version = version;
}
/**
* Returns the value.
* @return value.
*/
public byte[] value() {
return value;
}
/**
* Returns the version.
* @return version.
*/
public long version() {
return version;
}
/**
* Creates a copy of given VersionedValue.
*
* @param original VersionedValue to create a copy
* @return same as original if original or it's value is null,
* otherwise creates a copy.
*/
public static VersionedValue copy(VersionedValue original) {
if (original == null) {
return null;
}
if (original.value == null) {
// immutable, no need to copy
return original;
} else {
return new VersionedValue(
Arrays.copyOf(original.value,
original.value.length),
original.version);
}
}
@Override
public String toString() {
return MoreObjects.toStringHelper(getClass())
.add("version", version)
.add("value", ByteArraySizeHashPrinter.orNull(value))
.toString();
}
}
/*
* Copyright 2014 Open Networking Laboratory
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.store.service;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import static org.onosproject.store.service.WriteRequest.Type.*;
import java.util.Objects;
import org.onlab.util.ByteArraySizeHashPrinter;
import com.google.common.base.MoreObjects;
/**
* Database write request.
*/
public class WriteRequest {
public static final int ANY_VERSION = -1;
private final String tableName;
private final String key;
private final Type type;
private final byte[] newValue;
private final long previousVersion;
private final byte[] oldValue;
/**
* Creates a write request, which will
* put the specified value to the table regardless of the previous value.
*
* @param tableName name of the table
* @param key key in the table
* @param newValue value to write, must not be null
* @return WriteRequest
*/
public static WriteRequest put(String tableName, String key,
byte[] newValue) {
return new WriteRequest(PUT, tableName, key,
checkNotNull(newValue), ANY_VERSION, null);
}
/**
* Creates a write request, which will
* put the specified value to the table if the previous version matches.
*
* @param tableName name of the table
* @param key key in the table
* @param newValue value to write, must not be null
* @param previousVersion previous version expected
* @return WriteRequest
*/
public static WriteRequest putIfVersionMatches(String tableName, String key,
byte[] newValue,
long previousVersion) {
checkArgument(previousVersion >= 0);
return new WriteRequest(PUT_IF_VERSION, tableName, key,
checkNotNull(newValue), previousVersion, null);
}
/**
* Creates a write request, which will
* put the specified value to the table if the previous value matches.
*
* @param tableName name of the table
* @param key key in the table
* @param oldValue previous value expected, must not be null
* @param newValue value to write, must not be null
* @return WriteRequest
*/
public static WriteRequest putIfValueMatches(String tableName, String key,
byte[] oldValue,
byte[] newValue) {
return new WriteRequest(PUT_IF_VALUE, tableName, key,
checkNotNull(newValue), ANY_VERSION,
checkNotNull(oldValue));
}
/**
* Creates a write request, which will
* put the specified value to the table if the previous value does not exist.
*
* @param tableName name of the table
* @param key key in the table
* @param newValue value to write, must not be null
* @return WriteRequest
*/
public static WriteRequest putIfAbsent(String tableName, String key,
byte[] newValue) {
return new WriteRequest(PUT_IF_ABSENT, tableName, key,
checkNotNull(newValue), ANY_VERSION, null);
}
/**
* Creates a write request, which will
* remove the specified entry from the table regardless of the previous value.
*
* @param tableName name of the table
* @param key key in the table
* @return WriteRequest
*/
public static WriteRequest remove(String tableName, String key) {
return new WriteRequest(REMOVE, tableName, key,
null, ANY_VERSION, null);
}
/**
* Creates a write request, which will
* remove the specified entry from the table if the previous version matches.
*
* @param tableName name of the table
* @param key key in the table
* @param previousVersion previous version expected
* @return WriteRequest
*/
public static WriteRequest removeIfVersionMatches(String tableName, String key,
long previousVersion) {
return new WriteRequest(REMOVE_IF_VERSION, tableName, key,
null, previousVersion, null);
}
/**
* Creates a write request, which will
* remove the specified entry from the table if the previous value matches.
*
* @param tableName name of the table
* @param key key in the table
* @param oldValue previous value expected, must not be null
* @return WriteRequest
*/
public static WriteRequest removeIfValueMatches(String tableName, String key,
byte[] oldValue) {
return new WriteRequest(REMOVE_IF_VALUE, tableName, key,
null, ANY_VERSION, checkNotNull(oldValue));
}
public enum Type {
PUT,
PUT_IF_VERSION,
PUT_IF_VALUE,
PUT_IF_ABSENT,
REMOVE,
REMOVE_IF_VERSION,
REMOVE_IF_VALUE,
}
// hidden constructor
protected WriteRequest(Type type, String tableName, String key,
byte[] newValue,
long previousVersion, byte[] oldValue) {
checkNotNull(tableName);
checkNotNull(key);
this.tableName = tableName;
this.key = key;
this.type = type;
this.newValue = newValue;
this.previousVersion = previousVersion;
this.oldValue = oldValue;
}
public String tableName() {
return tableName;
}
public String key() {
return key;
}
public WriteRequest.Type type() {
return type;
}
public byte[] newValue() {
return newValue;
}
public long previousVersion() {
return previousVersion;
}
public byte[] oldValue() {
return oldValue;
}
@Override
public String toString() {
return MoreObjects.toStringHelper(getClass())
.add("type", type)
.add("tableName", tableName)
.add("key", key)
.add("newValue", ByteArraySizeHashPrinter.orNull(newValue))
.add("previousVersion", previousVersion)
.add("oldValue", ByteArraySizeHashPrinter.orNull(oldValue))
.toString();
}
// TODO: revisit hashCode, equals condition
@Override
public int hashCode() {
return Objects.hash(type, key, tableName, previousVersion);
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
WriteRequest other = (WriteRequest) obj;
return Objects.equals(this.type, other.type) &&
Objects.equals(this.key, other.key) &&
Objects.equals(this.tableName, other.tableName) &&
Objects.equals(this.previousVersion, other.previousVersion);
}
}
/*
* Copyright 2014 Open Networking Laboratory
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.store.service;
import com.google.common.base.MoreObjects;
/**
* Database write result.
*/
public class WriteResult {
private final WriteStatus status;
private final VersionedValue previousValue;
public WriteResult(WriteStatus status, VersionedValue previousValue) {
this.status = status;
this.previousValue = previousValue;
}
public VersionedValue previousValue() {
return previousValue;
}
public WriteStatus status() {
return status;
}
@Override
public String toString() {
return MoreObjects.toStringHelper(getClass())
.add("status", status)
.add("previousValue", previousValue)
.toString();
}
}
/*
* Copyright 2014 Open Networking Laboratory
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.store.service;
/**
* Status of completed write request.
*/
public enum WriteStatus {
/**
* Write completed successfully.
*/
OK,
/**
* Write was aborted (ex: if one or more write operations in a batch fail, others are aborted).
*/
ABORTED,
/**
* Write failed due to pre-condition failure. (ex: version or value mis-match).
*/
PRECONDITION_VIOLATION,
/**
* Write failed due to an invalid table name being specified.
*/
NO_SUCH_TABLE,
}
/*
* Copyright 2014 Open Networking Laboratory
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.store.intent.impl;
import com.codahale.metrics.Timer;
import com.codahale.metrics.Timer.Context;
import com.google.common.base.Verify;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import com.google.common.collect.ImmutableSet;
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.Reference;
import org.apache.felix.scr.annotations.ReferenceCardinality;
import org.apache.felix.scr.annotations.Service;
import org.onlab.metrics.MetricsService;
import org.onlab.util.KryoNamespace;
import org.onosproject.core.MetricsHelper;
import org.onosproject.net.intent.Intent;
import org.onosproject.net.intent.IntentEvent;
import org.onosproject.net.intent.IntentId;
import org.onosproject.net.intent.IntentState;
import org.onosproject.net.intent.IntentStore;
import org.onosproject.net.intent.IntentStoreDelegate;
import org.onosproject.net.intent.Key;
import org.onosproject.store.AbstractStore;
import org.onosproject.store.serializers.KryoNamespaces;
import org.onosproject.store.serializers.KryoSerializer;
import org.onosproject.store.serializers.StoreSerializer;
import org.onosproject.store.service.DatabaseAdminService;
import org.onosproject.store.service.DatabaseService;
import org.onosproject.store.service.impl.CMap;
import org.slf4j.Logger;
import java.util.EnumSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import static org.onlab.metrics.MetricsUtil.startTimer;
import static org.onlab.metrics.MetricsUtil.stopTimer;
import static org.onosproject.net.intent.IntentState.FAILED;
import static org.onosproject.net.intent.IntentState.INSTALLED;
import static org.onosproject.net.intent.IntentState.INSTALL_REQ;
import static org.onosproject.net.intent.IntentState.WITHDRAWN;
import static org.slf4j.LoggerFactory.getLogger;
//TODO Note: this store will be removed
@Component(immediate = true, enabled = false)
@Service
public class DistributedIntentStore
extends AbstractStore<IntentEvent, IntentStoreDelegate>
implements IntentStore, MetricsHelper {
/** Valid parking state, which can transition to INSTALLED. */
private static final Set<IntentState> PRE_INSTALLED = EnumSet.of(INSTALL_REQ, INSTALLED, FAILED);
/** Valid parking state, which can transition to WITHDRAWN. */
private static final Set<IntentState> PRE_WITHDRAWN = EnumSet.of(INSTALLED, FAILED);
private static final Set<IntentState> PARKING = EnumSet.of(INSTALL_REQ, INSTALLED, WITHDRAWN, FAILED);
private final Logger log = getLogger(getClass());
// Assumption: IntentId will not have synonyms
private static final String INTENTS_TABLE = "intents";
private CMap<IntentId, Intent> intents;
private static final String STATES_TABLE = "intent-states";
private CMap<IntentId, IntentState> states;
// TODO transient state issue remains for this impl.: ONOS-103
// Map to store instance local intermediate state transition
private transient Map<IntentId, IntentState> transientStates = new ConcurrentHashMap<>();
private static final String INSTALLABLE_TABLE = "installable-intents";
private CMap<IntentId, List<Intent>> installable;
private LoadingCache<IntentId, String> keyCache;
private StoreSerializer serializer;
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected DatabaseAdminService dbAdminService;
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected DatabaseService dbService;
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected MetricsService metricsService;
// TODO make this configurable
private boolean onlyLogTransitionError = true;
private Timer getInstallableIntentsTimer;
private Timer getIntentCountTimer;
private Timer getIntentsTimer;
private Timer getIntentTimer;
private Timer getIntentStateTimer;
private Timer createResponseTimer(String methodName) {
return createTimer("IntentStore", methodName, "responseTime");
}
@Activate
public void activate() {
getInstallableIntentsTimer = createResponseTimer("getInstallableIntents");
getIntentCountTimer = createResponseTimer("getIntentCount");
getIntentsTimer = createResponseTimer("getIntents");
getIntentTimer = createResponseTimer("getIntent");
getIntentStateTimer = createResponseTimer("getIntentState");
// We need a way to add serializer for intents which has been plugged-in.
// As a short term workaround, relax Kryo config to
// registrationRequired=false
serializer = new KryoSerializer() {
@Override
protected void setupKryoPool() {
serializerPool = KryoNamespace.newBuilder()
.setRegistrationRequired(false)
.register(KryoNamespaces.API)
.nextId(KryoNamespaces.BEGIN_USER_CUSTOM_ID)
.build();
}
};
keyCache = CacheBuilder.newBuilder()
.softValues()
.build(new CacheLoader<IntentId, String>() {
@Override
public String load(IntentId key) {
return key.toString();
}
});
intents = new IntentIdMap<>(dbAdminService, dbService, INTENTS_TABLE, serializer);
states = new IntentIdMap<>(dbAdminService, dbService, STATES_TABLE, serializer);
transientStates.clear();
installable = new IntentIdMap<>(dbAdminService, dbService, INSTALLABLE_TABLE, serializer);
log.info("Started");
}
@Deactivate
public void deactivate() {
log.info("Stopped");
}
@Override
public MetricsService metricsService() {
return metricsService;
}
@Override
public long getIntentCount() {
Context timer = startTimer(getIntentCountTimer);
try {
return intents.size();
} finally {
stopTimer(timer);
}
}
@Override
public Iterable<Intent> getIntents() {
Context timer = startTimer(getIntentsTimer);
try {
return ImmutableSet.copyOf(intents.values());
} finally {
stopTimer(timer);
}
}
@Override
public Intent getIntent(Key intentKey) {
return null;
}
public Intent getIntent(IntentId intentId) {
Context timer = startTimer(getIntentTimer);
try {
return intents.get(intentId);
} finally {
stopTimer(timer);
}
}
@Override
public IntentState getIntentState(Key key) {
// TODO: either implement this or remove the class
return IntentState.FAILED;
/*
Context timer = startTimer(getIntentStateTimer);
try {
final IntentState localState = transientStates.get(id);
if (localState != null) {
return localState;
}
return states.get(id);
} finally {
stopTimer(timer);
}
*/
}
private void verify(boolean expression, String errorMessageTemplate, Object... errorMessageArgs) {
if (onlyLogTransitionError) {
if (!expression) {
log.error(errorMessageTemplate.replace("%s", "{}"), errorMessageArgs);
}
} else {
Verify.verify(expression, errorMessageTemplate, errorMessageArgs);
}
}
@Override
public List<Intent> getInstallableIntents(Key intentKey) {
// TODO: implement this or delete class
return null;
/*
Context timer = startTimer(getInstallableIntentsTimer);
try {
return installable.get(intentId);
} finally {
stopTimer(timer);
}
*/
}
protected String strIntentId(IntentId key) {
return keyCache.getUnchecked(key);
}
/**
* Distributed Map from IntentId to some value.
*
* @param <V> Map value type
*/
final class IntentIdMap<V> extends CMap<IntentId, V> {
/**
* Creates a IntentIdMap instance.
*
* @param dbAdminService DatabaseAdminService to use for this instance
* @param dbService DatabaseService to use for this instance
* @param tableName table which this Map corresponds to
* @param serializer Value serializer
*/
public IntentIdMap(DatabaseAdminService dbAdminService,
DatabaseService dbService,
String tableName,
StoreSerializer serializer) {
super(dbAdminService, dbService, tableName, serializer);
}
@Override
protected String sK(IntentId key) {
return strIntentId(key);
}
}
/*@Override
public List<Operation> batchWrite(BatchWrite batch) {
if (batch.isEmpty()) {
return Collections.emptyList();
}
List<Operation> failed = new ArrayList<>();
final Builder builder = BatchWriteRequest.newBuilder();
List<IntentEvent> events = Lists.newArrayList();
final Set<IntentId> transitionedToParking = new HashSet<>();
for (Operation op : batch.operations()) {
switch (op.type()) {
case CREATE_INTENT:
checkArgument(op.args().size() == 1,
"CREATE_INTENT takes 1 argument. %s", op);
Intent intent = op.arg(0);
builder.putIfAbsent(INTENTS_TABLE, strIntentId(intent.id()), serializer.encode(intent));
builder.putIfAbsent(STATES_TABLE, strIntentId(intent.id()), serializer.encode(INSTALL_REQ));
events.add(IntentEvent.getEvent(INSTALL_REQ, intent));
break;
case REMOVE_INTENT:
checkArgument(op.args().size() == 1,
"REMOVE_INTENT takes 1 argument. %s", op);
IntentId intentId = (IntentId) op.arg(0);
builder.remove(INTENTS_TABLE, strIntentId(intentId));
builder.remove(STATES_TABLE, strIntentId(intentId));
builder.remove(INSTALLABLE_TABLE, strIntentId(intentId));
break;
case SET_STATE:
checkArgument(op.args().size() == 2,
"SET_STATE takes 2 arguments. %s", op);
intent = op.arg(0);
IntentState newState = op.arg(1);
builder.put(STATES_TABLE, strIntentId(intent.id()), serializer.encode(newState));
if (PARKING.contains(newState)) {
transitionedToParking.add(intent.id());
events.add(IntentEvent.getEvent(newState, intent));
} else {
transitionedToParking.remove(intent.id());
}
break;
case SET_INSTALLABLE:
checkArgument(op.args().size() == 2,
"SET_INSTALLABLE takes 2 arguments. %s", op);
intentId = op.arg(0);
List<Intent> installableIntents = op.arg(1);
builder.put(INSTALLABLE_TABLE, strIntentId(intentId), serializer.encode(installableIntents));
break;
case REMOVE_INSTALLED:
checkArgument(op.args().size() == 1,
"REMOVE_INSTALLED takes 1 argument. %s", op);
intentId = op.arg(0);
builder.remove(INSTALLABLE_TABLE, strIntentId(intentId));
break;
default:
log.warn("Unknown Operation encountered: {}", op);
failed.add(op);
break;
}
}
BatchWriteResult batchWriteResult = dbService.batchWrite(builder.build());
if (batchWriteResult.isSuccessful()) {
// no-failure (except for invalid input)
transitionedToParking.forEach((intentId) -> transientStates.remove(intentId));
notifyDelegate(events);
return failed;
} else {
// everything failed
return batch.operations();
}
}*/
}
/*
* Copyright 2014-2015 Open Networking Laboratory
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.store.resource.impl;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
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.Reference;
import org.apache.felix.scr.annotations.ReferenceCardinality;
import org.apache.felix.scr.annotations.Service;
import org.onlab.util.PositionalParameterStringFormatter;
import org.onosproject.net.AnnotationKeys;
import org.onosproject.net.Link;
import org.onosproject.net.LinkKey;
import org.onosproject.net.intent.IntentId;
import org.onosproject.net.link.LinkService;
import org.onosproject.net.resource.Bandwidth;
import org.onosproject.net.resource.BandwidthResourceAllocation;
import org.onosproject.net.resource.Lambda;
import org.onosproject.net.resource.LambdaResourceAllocation;
import org.onosproject.net.resource.LinkResourceAllocations;
import org.onosproject.net.resource.LinkResourceEvent;
import org.onosproject.net.resource.LinkResourceStore;
import org.onosproject.net.resource.MplsLabel;
import org.onosproject.net.resource.MplsLabelResourceAllocation;
import org.onosproject.net.resource.ResourceAllocation;
import org.onosproject.net.resource.ResourceAllocationException;
import org.onosproject.net.resource.ResourceType;
import org.onosproject.store.serializers.KryoSerializer;
import org.onosproject.store.serializers.StoreSerializer;
import org.onosproject.store.service.BatchWriteRequest;
import org.onosproject.store.service.BatchWriteRequest.Builder;
import org.onosproject.store.service.BatchWriteResult;
import org.onosproject.store.service.DatabaseAdminService;
import org.onosproject.store.service.DatabaseException;
import org.onosproject.store.service.DatabaseService;
import org.onosproject.store.service.VersionedValue;
import org.onosproject.store.service.WriteRequest;
import org.onosproject.store.service.WriteResult;
import org.slf4j.Logger;
import com.google.common.base.Function;
import com.google.common.collect.FluentIterable;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Sets;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState;
import static com.google.common.base.Predicates.notNull;
import static org.onlab.util.HexString.toHexString;
import static org.slf4j.LoggerFactory.getLogger;
/**
* Manages link resources using database service.
*/
@Component(immediate = true, enabled = false)
@Service
public class DistributedLinkResourceStore implements LinkResourceStore {
private final Logger log = getLogger(getClass());
private static final Bandwidth DEFAULT_BANDWIDTH = Bandwidth.mbps(1_000);
// table to store current allocations
/** LinkKey -> List<LinkResourceAllocations>. */
private static final String LINK_RESOURCE_ALLOCATIONS = "LinkResourceAllocations";
/** IntentId -> LinkResourceAllocations. */
private static final String INTENT_ALLOCATIONS = "IntentAllocations";
private static final Bandwidth EMPTY_BW = Bandwidth.bps(0);
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected DatabaseAdminService databaseAdminService;
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected DatabaseService databaseService;
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected LinkService linkService;
// Link annotation key name to use as bandwidth in Mbps
private String bandwidthAnnotation = AnnotationKeys.BANDWIDTH;
// Link annotation key name to use as max lambda
private String wavesAnnotation = AnnotationKeys.OPTICAL_WAVES;
// Max MPLS labels: 2^20 – 1
private int maxMplsLabel = 0xFFFFF;
private StoreSerializer serializer;
void createTable(String tableName) {
boolean tableReady = false;
do {
try {
if (!databaseAdminService.listTables().contains(tableName)) {
databaseAdminService.createTable(tableName);
}
tableReady = true;
} catch (DatabaseException e) {
log.debug("Failed creating table, retrying", e);
try {
Thread.sleep(200);
} catch (InterruptedException e1) {
throw new DatabaseException(e1);
}
}
} while (!tableReady);
}
@Activate
public void activate() {
serializer = new KryoSerializer();
createTable(LINK_RESOURCE_ALLOCATIONS);
createTable(INTENT_ALLOCATIONS);
log.info("Started");
}
@Deactivate
public void deactivate() {
log.info("Stopped");
}
private Set<? extends ResourceAllocation> getResourceCapacity(ResourceType type, Link link) {
if (type == ResourceType.BANDWIDTH) {
return ImmutableSet.of(getBandwidthResourceCapacity(link));
}
if (type == ResourceType.LAMBDA) {
return getLambdaResourceCapacity(link);
}
if (type == ResourceType.MPLS_LABEL) {
return getMplsResourceCapacity();
}
return null;
}
private Set<LambdaResourceAllocation> getLambdaResourceCapacity(Link link) {
Set<LambdaResourceAllocation> allocations = new HashSet<>();
try {
final int waves = Integer.parseInt(link.annotations().value(wavesAnnotation));
for (int i = 1; i <= waves; i++) {
allocations.add(new LambdaResourceAllocation(Lambda.valueOf(i)));
}
} catch (NumberFormatException e) {
log.debug("No {} annotation on link %s", wavesAnnotation, link);
}
return allocations;
}
private BandwidthResourceAllocation getBandwidthResourceCapacity(Link link) {
// if Link annotation exist, use them
// if all fails, use DEFAULT_BANDWIDTH
Bandwidth bandwidth = null;
String strBw = link.annotations().value(bandwidthAnnotation);
if (strBw != null) {
try {
bandwidth = Bandwidth.mbps(Double.parseDouble(strBw));
} catch (NumberFormatException e) {
// do nothings
bandwidth = null;
}
}
if (bandwidth == null) {
// fall back, use fixed default
bandwidth = DEFAULT_BANDWIDTH;
}
return new BandwidthResourceAllocation(bandwidth);
}
private Set<MplsLabelResourceAllocation> getMplsResourceCapacity() {
Set<MplsLabelResourceAllocation> allocations = new HashSet<>();
//Ignoring reserved labels of 0 through 15
for (int i = 16; i <= maxMplsLabel; i++) {
allocations.add(new MplsLabelResourceAllocation(MplsLabel
.valueOf(i)));
}
return allocations;
}
private Map<ResourceType, Set<? extends ResourceAllocation>> getResourceCapacity(Link link) {
Map<ResourceType, Set<? extends ResourceAllocation>> caps = new HashMap<>();
for (ResourceType type : ResourceType.values()) {
Set<? extends ResourceAllocation> cap = getResourceCapacity(type, link);
if (cap != null) {
caps.put(type, cap);
}
}
return caps;
}
@Override
public Set<ResourceAllocation> getFreeResources(Link link) {
Map<ResourceType, Set<? extends ResourceAllocation>> freeResources = getFreeResourcesEx(link);
Set<ResourceAllocation> allFree = new HashSet<>();
for (Set<? extends ResourceAllocation> r:freeResources.values()) {
allFree.addAll(r);
}
return allFree;
}
private Map<ResourceType, Set<? extends ResourceAllocation>> getFreeResourcesEx(Link link) {
// returns capacity - allocated
checkNotNull(link);
Map<ResourceType, Set<? extends ResourceAllocation>> free = new HashMap<>();
final Map<ResourceType, Set<? extends ResourceAllocation>> caps = getResourceCapacity(link);
final Iterable<LinkResourceAllocations> allocations = getAllocations(link);
for (ResourceType type : ResourceType.values()) {
// there should be class/category of resources
switch (type) {
case BANDWIDTH:
{
Set<? extends ResourceAllocation> bw = caps.get(ResourceType.BANDWIDTH);
if (bw == null || bw.isEmpty()) {
bw = Sets.newHashSet(new BandwidthResourceAllocation(EMPTY_BW));
}
BandwidthResourceAllocation cap = (BandwidthResourceAllocation) bw.iterator().next();
double freeBw = cap.bandwidth().toDouble();
// enumerate current allocations, subtracting resources
for (LinkResourceAllocations alloc : allocations) {
Set<ResourceAllocation> types = alloc.getResourceAllocation(link);
for (ResourceAllocation a : types) {
if (a instanceof BandwidthResourceAllocation) {
BandwidthResourceAllocation bwA = (BandwidthResourceAllocation) a;
freeBw -= bwA.bandwidth().toDouble();
}
}
}
free.put(type, Sets.newHashSet(new BandwidthResourceAllocation(Bandwidth.bps(freeBw))));
break;
}
case LAMBDA:
{
Set<? extends ResourceAllocation> lmd = caps.get(type);
if (lmd == null || lmd.isEmpty()) {
// nothing left
break;
}
Set<LambdaResourceAllocation> freeL = new HashSet<>();
for (ResourceAllocation r : lmd) {
if (r instanceof LambdaResourceAllocation) {
freeL.add((LambdaResourceAllocation) r);
}
}
// enumerate current allocations, removing resources
for (LinkResourceAllocations alloc : allocations) {
Set<ResourceAllocation> types = alloc.getResourceAllocation(link);
for (ResourceAllocation a : types) {
if (a instanceof LambdaResourceAllocation) {
freeL.remove(a);
}
}
}
free.put(type, freeL);
break;
}
case MPLS_LABEL:
{
Set<? extends ResourceAllocation> mpls = caps.get(type);
if (mpls == null || mpls.isEmpty()) {
// nothing left
break;
}
Set<MplsLabelResourceAllocation> freeLabel = new HashSet<>();
for (ResourceAllocation r : mpls) {
if (r instanceof MplsLabelResourceAllocation) {
freeLabel.add((MplsLabelResourceAllocation) r);
}
}
// enumerate current allocations, removing resources
for (LinkResourceAllocations alloc : allocations) {
Set<ResourceAllocation> types = alloc
.getResourceAllocation(link);
for (ResourceAllocation a : types) {
if (a instanceof MplsLabelResourceAllocation) {
freeLabel.remove(a);
}
}
}
free.put(type, freeLabel);
break;
}
default:
break;
}
}
return free;
}
private LinkResourceAllocations getIntentAllocations(IntentId id) {
VersionedValue vv
= databaseService.get(INTENT_ALLOCATIONS, toIntentDbKey(checkNotNull(id)));
if (vv == null || vv.value() == null) {
return null;
}
return decodeIntentAllocations(vv.value());
}
private Builder putIntentAllocations(Builder ctx,
IntentId id,
LinkResourceAllocations alloc) {
return ctx.put(INTENT_ALLOCATIONS,
toIntentDbKey(id),
encodeIntentAllocations(alloc));
}
@Override
public void allocateResources(LinkResourceAllocations allocations) {
checkNotNull(allocations);
Builder tx = BatchWriteRequest.newBuilder();
// TODO: Should IntentId -> Allocation be updated conditionally?
putIntentAllocations(tx, allocations.intendId(), allocations);
for (Link link : allocations.links()) {
allocateLinkResource(tx, link, allocations);
}
BatchWriteRequest batch = tx.build();
// log.info("Intent: {}", databaseService.getAll(INTENT_ALLOCATIONS));
// log.info("Link: {}",
// databaseService.getAll(LINK_RESOURCE_ALLOCATIONS));
BatchWriteResult result = databaseService.batchWrite(batch);
if (!result.isSuccessful()) {
log.error("Allocation Failed.");
if (log.isDebugEnabled()) {
logFailureDetail(batch, result);
}
checkState(result.isSuccessful(), "Allocation failed");
}
}
private void logFailureDetail(BatchWriteRequest batch,
BatchWriteResult result) {
for (int i = 0; i < batch.batchSize(); ++i) {
final WriteRequest req = batch.getAsList().get(i);
final WriteResult fail = result.getAsList().get(i);
switch (fail.status()) {
case ABORTED:
log.debug("ABORTED: {}@{}", req.key(), req.tableName());
break;
case PRECONDITION_VIOLATION:
switch (req.type()) {
case PUT_IF_ABSENT:
log.debug("{}: {}@{} : {}", req.type(),
req.key(), req.tableName(), fail.previousValue());
break;
case PUT_IF_VALUE:
case REMOVE_IF_VALUE:
log.debug("{}: {}@{} : was {}, expected {}", req.type(),
req.key(), req.tableName(),
fail.previousValue(),
toHexString(req.oldValue()));
break;
case PUT_IF_VERSION:
case REMOVE_IF_VERSION:
log.debug("{}: {}@{} : was {}, expected {}", req.type(),
req.key(), req.tableName(),
fail.previousValue().version(),
req.previousVersion());
break;
default:
log.error("Should never reach here.");
break;
}
break;
default:
log.error("Should never reach here.");
break;
}
}
}
private Builder allocateLinkResource(Builder builder, Link link,
LinkResourceAllocations allocations) {
// requested resources
Set<ResourceAllocation> reqs = allocations.getResourceAllocation(link);
Map<ResourceType, Set<? extends ResourceAllocation>> available = getFreeResourcesEx(link);
for (ResourceAllocation req : reqs) {
Set<? extends ResourceAllocation> avail = available.get(req.type());
if (req instanceof BandwidthResourceAllocation) {
// check if allocation should be accepted
if (avail.isEmpty()) {
checkState(!avail.isEmpty(),
"There's no Bandwidth resource on %s?",
link);
}
BandwidthResourceAllocation bw = (BandwidthResourceAllocation) avail.iterator().next();
double bwLeft = bw.bandwidth().toDouble();
bwLeft -= ((BandwidthResourceAllocation) req).bandwidth().toDouble();
BandwidthResourceAllocation bwReq = ((BandwidthResourceAllocation) req);
if (bwLeft < 0) {
throw new ResourceAllocationException(
PositionalParameterStringFormatter.format(
"Unable to allocate bandwidth for link {} "
+ " requested amount is {} current allocation is {}",
link,
bwReq.bandwidth().toDouble(),
bw));
}
} else if (req instanceof LambdaResourceAllocation) {
final LambdaResourceAllocation lambdaAllocation = (LambdaResourceAllocation) req;
// check if allocation should be accepted
if (!avail.contains(req)) {
// requested lambda was not available
throw new ResourceAllocationException(
PositionalParameterStringFormatter.format(
"Unable to allocate lambda for link {} lambda is {}",
link,
lambdaAllocation.lambda().toInt()));
}
} else if (req instanceof MplsLabelResourceAllocation) {
final MplsLabelResourceAllocation mplsAllocation = (MplsLabelResourceAllocation) req;
// check if allocation should be accepted
if (!avail.contains(req)) {
// requested mpls label was not available
throw new ResourceAllocationException(
PositionalParameterStringFormatter
.format("Unable to allocate MPLS label for "
+ "link {} MPLS label is {}",
link,
mplsAllocation
.mplsLabel()
.toString()));
}
}
}
// all requests allocatable => add allocation
final List<LinkResourceAllocations> before = getAllocations(link);
List<LinkResourceAllocations> after = new ArrayList<>(before.size());
after.addAll(before);
after.add(allocations);
replaceLinkAllocations(builder, LinkKey.linkKey(link), before, after);
return builder;
}
private Builder replaceLinkAllocations(Builder builder, LinkKey linkKey,
List<LinkResourceAllocations> before,
List<LinkResourceAllocations> after) {
byte[] oldValue = encodeLinkAllocations(before);
byte[] newValue = encodeLinkAllocations(after);
builder.putIfValueMatches(LINK_RESOURCE_ALLOCATIONS, toLinkDbKey(linkKey), oldValue, newValue);
return builder;
}
@Override
public LinkResourceEvent releaseResources(LinkResourceAllocations allocations) {
checkNotNull(allocations);
final IntentId intendId = allocations.intendId();
final String dbIntentId = toIntentDbKey(intendId);
final Collection<Link> links = allocations.links();
boolean success;
do {
Builder tx = BatchWriteRequest.newBuilder();
// TODO: Should IntentId -> Allocation be updated conditionally?
tx.remove(INTENT_ALLOCATIONS, dbIntentId);
for (Link link : links) {
final LinkKey linkId = LinkKey.linkKey(link);
final String dbLinkId = toLinkDbKey(linkId);
VersionedValue vv = databaseService.get(LINK_RESOURCE_ALLOCATIONS, dbLinkId);
if (vv == null || vv.value() == null) {
// something is wrong, but it is already freed
log.warn("There was no resource left to release on {}", linkId);
continue;
}
List<LinkResourceAllocations> before = decodeLinkAllocations(vv.value());
List<LinkResourceAllocations> after = new ArrayList<>(before);
after.remove(allocations);
byte[] oldValue = encodeLinkAllocations(before);
byte[] newValue = encodeLinkAllocations(after);
tx.putIfValueMatches(LINK_RESOURCE_ALLOCATIONS, dbLinkId, oldValue, newValue);
}
BatchWriteResult batchWrite = databaseService.batchWrite(tx.build());
success = batchWrite.isSuccessful();
} while (!success);
// Issue events to force recompilation of intents.
final List<LinkResourceAllocations> releasedResources = ImmutableList.of(allocations);
return new LinkResourceEvent(
LinkResourceEvent.Type.ADDITIONAL_RESOURCES_AVAILABLE,
releasedResources);
}
@Override
public LinkResourceAllocations getAllocations(IntentId intentId) {
checkNotNull(intentId);
VersionedValue vv = databaseService.get(INTENT_ALLOCATIONS, toIntentDbKey(intentId));
if (vv == null) {
return null;
}
LinkResourceAllocations allocations = decodeIntentAllocations(vv.value());
return allocations;
}
private String toLinkDbKey(LinkKey linkid) {
// introduce cache if necessary
return linkid.toString();
// Note: Above is irreversible, if we need reverse conversion
// we may need something like below, due to String only limitation
// byte[] bytes = serializer.encode(linkid);
// StringBuilder builder = new StringBuilder(bytes.length * 4);
// boolean isFirst = true;
// for (byte b : bytes) {
// if (!isFirst) {
// builder.append(',');
// }
// builder.append(b);
// isFirst = false;
// }
// return builder.toString();
}
// private LinkKey toLinkKey(String linkKey) {
// String[] bytes = linkKey.split(",");
// ByteBuffer buf = ByteBuffer.allocate(bytes.length);
// for (String bs : bytes) {
// buf.put(Byte.parseByte(bs));
// }
// buf.flip();
// return serializer.decode(buf);
// }
private String toIntentDbKey(IntentId intentid) {
return intentid.toString();
}
private IntentId toIntentId(String intentid) {
checkArgument(intentid.startsWith("0x"));
return IntentId.valueOf(Long.parseLong(intentid.substring(2)));
}
private LinkResourceAllocations decodeIntentAllocations(byte[] bytes) {
return serializer.decode(bytes);
}
private byte[] encodeIntentAllocations(LinkResourceAllocations alloc) {
return serializer.encode(checkNotNull(alloc));
}
private List<LinkResourceAllocations> decodeLinkAllocations(byte[] bytes) {
return serializer.decode(bytes);
}
private byte[] encodeLinkAllocations(List<LinkResourceAllocations> alloc) {
return serializer.encode(checkNotNull(alloc));
}
@Override
public List<LinkResourceAllocations> getAllocations(Link link) {
checkNotNull(link);
final LinkKey key = LinkKey.linkKey(link);
final String dbKey = toLinkDbKey(key);
VersionedValue vv = databaseService.get(LINK_RESOURCE_ALLOCATIONS, dbKey);
if (vv == null) {
// write empty so that all other update can be replace operation
byte[] emptyList = encodeLinkAllocations(new ArrayList<>());
boolean written = databaseService.putIfAbsent(LINK_RESOURCE_ALLOCATIONS, dbKey, emptyList);
log.trace("Empty allocation write success? {}", written);
vv = databaseService.get(LINK_RESOURCE_ALLOCATIONS, dbKey);
if (vv == null) {
log.error("Failed to re-read allocation for {}", dbKey);
// note: cannot be Collections.emptyList();
return new ArrayList<>();
}
}
List<LinkResourceAllocations> allocations = decodeLinkAllocations(vv.value());
return allocations;
}
@Override
public Iterable<LinkResourceAllocations> getAllocations() {
//IntentId -> LinkResourceAllocations
Map<String, VersionedValue> all = databaseService.getAll(INTENT_ALLOCATIONS);
return FluentIterable.from(all.values())
.transform(new Function<VersionedValue, LinkResourceAllocations>() {
@Override
public LinkResourceAllocations apply(VersionedValue input) {
if (input == null || input.value() == null) {
return null;
}
return decodeIntentAllocations(input.value());
}
})
.filter(notNull());
}
}
/*
* Copyright 2014 Open Networking Laboratory
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.onosproject.store.service.impl;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Predicates.notNull;
import java.util.Map;
import org.onosproject.store.serializers.StoreSerializer;
import org.onosproject.store.service.DatabaseAdminService;
import org.onosproject.store.service.DatabaseException;
import org.onosproject.store.service.DatabaseService;
import org.onosproject.store.service.VersionedValue;
import com.google.common.base.Function;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import com.google.common.collect.FluentIterable;
/**
* Map like interface wrapper around DatabaseService.
*
* @param <K> Key type of the map.
* The type must have toString(), which can uniquely identify the entry.
* @param <V> Value type
*/
public class CMap<K, V> {
@SuppressWarnings("unused")
private final DatabaseAdminService dbAdminService;
private final DatabaseService dbService;
private final String tableName;
private final StoreSerializer serializer;
private final LoadingCache<K, String> keyCache;
/**
* Creates a CMap instance.
* It will create the table if necessary.
*
* @param dbAdminService DatabaseAdminService to use for this instance
* @param dbService DatabaseService to use for this instance
* @param tableName table which this Map corresponds to
* @param serializer Value serializer
*/
public CMap(DatabaseAdminService dbAdminService,
DatabaseService dbService,
String tableName,
StoreSerializer serializer) {
this.dbAdminService = checkNotNull(dbAdminService);
this.dbService = checkNotNull(dbService);
this.tableName = checkNotNull(tableName);
this.serializer = checkNotNull(serializer);
boolean tableReady = false;
do {
try {
if (!dbAdminService.listTables().contains(tableName)) {
dbAdminService.createTable(tableName);
}
tableReady = true;
} catch (DatabaseException e) {
try {
Thread.sleep(200);
} catch (InterruptedException e1) {
throw new DatabaseException(e1);
}
}
} while (!tableReady);
keyCache = CacheBuilder.newBuilder()
.softValues()
.build(new CacheLoader<K, String>() {
@Override
public String load(K key) {
return key.toString();
}
});
}
protected String sK(K key) {
return keyCache.getUnchecked(key);
}
protected byte[] sV(V val) {
return serializer.encode(val);
}
protected V dV(byte[] valBytes) {
return serializer.decode(valBytes);
}
/**
* Puts an entry to the map, if not already present.
*
* @param key the key of the value to put if absent
* @param value the value to be put if previous value does not exist
* @return true if put was successful.
*/
public boolean putIfAbsent(K key, V value) {
return dbService.putIfAbsent(tableName, sK(key), sV(value));
}
/**
* Removes an entry associated to specified key.
*
* @param key key of the value to remove
* @return previous value in the map for the key
*/
public V remove(K key) {
VersionedValue removed = dbService.remove(tableName, sK(key));
if (removed == null) {
return null;
}
return dV(removed.value());
}
/**
* Returns the size of the map.
*
* @return size of the map
*/
public long size() {
// TODO this is very inefficient
return dbService.getAll(tableName).size();
}
/**
* Returns all the values contained in the map.
*
* @return values containd in this map
*/
public Iterable<V> values() {
Map<String, VersionedValue> all = dbService.getAll(tableName);
return FluentIterable.from(all.values())
.transform(new Function<VersionedValue, V>() {
@Override
public V apply(VersionedValue input) {
if (input == null) {
return null;
}
return dV(input.value());
}
})
.filter(notNull());
}
/**
* Gets the value in the map.
*
* @param key to get from the map
* @return value associated with the key, null if not such entry
*/
public V get(K key) {
VersionedValue vv = dbService.get(tableName, sK(key));
if (vv == null) {
return null;
}
return dV(vv.value());
}
/**
* Replaces the value in the map if the value matches the expected.
*
* @param key of the entry to replace
* @param oldVal value expected to be in the map
* @param newVal value to be replaced with
* @return true if successfully replaced
*/
public boolean replace(K key, V oldVal, V newVal) {
return dbService.putIfValueMatches(tableName, sK(key), sV(oldVal), sV(newVal));
}
/**
* Puts a value int the map.
*
* @param key key with which the specified value is to be associated
* @param value value to be associated with the specified key
* @return previous value or null if not such entry
*/
public V put(K key, V value) {
VersionedValue vv = dbService.put(tableName, sK(key), sV(value));
if (vv == null) {
return null;
}
return dV(vv.value());
}
}
/*
* Copyright 2015 Open Networking Laboratory
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* Utility services and backing mechanisms for implementations of distributed stores.
*/
package org.onosproject.store.service.impl;
\ No newline at end of file
......@@ -18,6 +18,7 @@ package org.onosproject.store.serializers;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import org.onlab.packet.ChassisId;
import org.onlab.packet.Ip4Address;
import org.onlab.packet.Ip4Prefix;
......@@ -119,15 +120,7 @@ import org.onosproject.net.resource.MplsLabel;
import org.onosproject.net.resource.MplsLabelResourceAllocation;
import org.onosproject.net.resource.MplsLabelResourceRequest;
import org.onosproject.store.Timestamp;
import org.onosproject.store.service.BatchReadRequest;
import org.onosproject.store.service.BatchWriteRequest;
import org.onosproject.store.service.ReadRequest;
import org.onosproject.store.service.ReadResult;
import org.onosproject.store.service.ReadStatus;
import org.onosproject.store.service.VersionedValue;
import org.onosproject.store.service.WriteRequest;
import org.onosproject.store.service.WriteResult;
import org.onosproject.store.service.WriteStatus;
import org.onosproject.store.service.Versioned;
import java.net.URI;
import java.time.Duration;
......@@ -339,16 +332,7 @@ public final class KryoNamespaces {
.register(new MastershipTermSerializer(), MastershipTerm.class)
.register(new HostLocationSerializer(), HostLocation.class)
.register(new DefaultOutboundPacketSerializer(), DefaultOutboundPacket.class)
.register(ReadRequest.class)
.register(WriteRequest.class)
.register(WriteRequest.Type.class)
.register(WriteResult.class)
.register(ReadResult.class)
.register(BatchReadRequest.class)
.register(BatchWriteRequest.class)
.register(ReadStatus.class)
.register(WriteStatus.class)
.register(VersionedValue.class)
.register(Versioned.class)
.register(DefaultGroupId.class)
.register(
MplsIntent.class,
......