Bug 7521: Convert Snapshot to store a State instance
[controller.git] / opendaylight / md-sal / sal-distributed-datastore / src / main / java / org / opendaylight / controller / cluster / datastore / actors / ShardSnapshotActor.java
1 /*
2  * Copyright (c) 2016 Cisco Systems, Inc. and others.  All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  */
8 package org.opendaylight.controller.cluster.datastore.actors;
9
10 import akka.actor.ActorRef;
11 import akka.actor.Props;
12 import com.google.common.base.Preconditions;
13 import java.io.IOException;
14 import java.io.OutputStream;
15 import java.util.Optional;
16 import org.opendaylight.controller.cluster.common.actor.AbstractUntypedActorWithMetering;
17 import org.opendaylight.controller.cluster.datastore.persisted.ShardDataTreeSnapshot;
18 import org.opendaylight.controller.cluster.datastore.persisted.ShardSnapshotState;
19 import org.opendaylight.controller.cluster.raft.base.messages.CaptureSnapshotReply;
20 import org.slf4j.Logger;
21 import org.slf4j.LoggerFactory;
22
23 /**
24  * This is an offload actor, which is given an isolated snapshot of the data tree. It performs the potentially
25  * time-consuming operation of serializing the snapshot.
26  *
27  * @author Robert Varga
28  */
29 public final class ShardSnapshotActor extends AbstractUntypedActorWithMetering {
30     private static final Logger LOG = LoggerFactory.getLogger(ShardSnapshotActor.class);
31
32     // Internal message
33     private static final class SerializeSnapshot {
34         private final ShardDataTreeSnapshot snapshot;
35         private final Optional<OutputStream> installSnapshotStream;
36         private final ActorRef replyTo;
37
38         SerializeSnapshot(final ShardDataTreeSnapshot snapshot, final Optional<OutputStream> installSnapshotStream,
39                 final ActorRef replyTo) {
40             this.snapshot = Preconditions.checkNotNull(snapshot);
41             this.installSnapshotStream = Preconditions.checkNotNull(installSnapshotStream);
42             this.replyTo = Preconditions.checkNotNull(replyTo);
43         }
44
45         ShardDataTreeSnapshot getSnapshot() {
46             return snapshot;
47         }
48
49         Optional<OutputStream> getInstallSnapshotStream() {
50             return installSnapshotStream;
51         }
52
53         ActorRef getReplyTo() {
54             return replyTo;
55         }
56     }
57
58     //actor name override used for metering. This does not change the "real" actor name
59     private static final String ACTOR_NAME_FOR_METERING = "shard-snapshot";
60
61     private ShardSnapshotActor() {
62         super(ACTOR_NAME_FOR_METERING);
63     }
64
65     @Override
66     protected void handleReceive(final Object message) throws Exception {
67         if (message instanceof SerializeSnapshot) {
68             onSerializeSnapshot((SerializeSnapshot) message);
69         } else {
70             unknownMessage(message);
71         }
72     }
73
74     private void onSerializeSnapshot(SerializeSnapshot request) {
75         Optional<OutputStream> installSnapshotStream = request.getInstallSnapshotStream();
76         if (installSnapshotStream.isPresent()) {
77             try {
78                 request.getSnapshot().serialize(installSnapshotStream.get());
79             } catch (IOException e) {
80                 // TODO - we should communicate the failure in the CaptureSnapshotReply.
81                 LOG.error("Error serializing snapshot", e);
82             }
83         }
84
85         request.getReplyTo().tell(new CaptureSnapshotReply(new ShardSnapshotState(request.getSnapshot()),
86                 installSnapshotStream), ActorRef.noSender());
87     }
88
89     /**
90      * Sends a request to a ShardSnapshotActor to process a snapshot and send a CaptureSnapshotReply.
91      *
92      * @param snapshotActor the ShardSnapshotActor
93      * @param snapshot the snapshot to process
94      * @param installSnapshotStream Optional OutputStream that is present if the snapshot is to also be installed
95      *        on a follower.
96      * @param replyTo the actor to which to send the CaptureSnapshotReply
97      */
98     public static void requestSnapshot(final ActorRef snapshotActor, final ShardDataTreeSnapshot snapshot,
99             final Optional<OutputStream> installSnapshotStream, final ActorRef replyTo) {
100         snapshotActor.tell(new SerializeSnapshot(snapshot, installSnapshotStream, replyTo), ActorRef.noSender());
101     }
102
103     public static Props props() {
104         return Props.create(ShardSnapshotActor.class);
105     }
106 }