1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
4 * Ceph - scalable distributed file system
6 * Copyright (C) 2004-2006 Sage Weil <sage@newdream.net>
8 * This is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License version 2.1, as published by the Free Software
11 * Foundation. See file COPYING.
15 #ifndef CEPH_MDS_SNAPREALM_H
16 #define CEPH_MDS_SNAPREALM_H
18 #include <boost/utility/string_view.hpp>
22 #include "include/xlist.h"
23 #include "include/elist.h"
24 #include "common/snap_types.h"
26 class MDSInternalContextBase
;
31 mutable snapid_t cached_seq
; // max seq over self and all past+present parents.
32 mutable snapid_t cached_last_created
; // max last_created over all past+present parents
33 mutable snapid_t cached_last_destroyed
;
34 mutable set
<snapid_t
> cached_snaps
;
35 mutable SnapContext cached_snap_context
;
36 mutable bufferlist cached_snap_trace
;
38 void check_cache() const;
48 bool open
; // set to true once all past_parents are opened
50 set
<SnapRealm
*> open_children
; // active children that are currently open
51 set
<SnapRealm
*> open_past_children
; // past children who has pinned me
52 map
<inodeno_t
, pair
<SnapRealm
*, set
<snapid_t
> > > open_past_parents
; // these are explicitly pinned.
53 unsigned num_open_past_parents
;
57 elist
<CInode
*> inodes_with_caps
; // for efficient realm splits
58 map
<client_t
, xlist
<Capability
*>* > client_caps
; // to identify clients who need snap notifications
60 SnapRealm(MDCache
*c
, CInode
*in
) :
62 mdcache(c
), inode(in
),
63 open(false), parent(0),
64 num_open_past_parents(0),
68 bool exists(boost::string_view name
) const {
69 for (map
<snapid_t
,SnapInfo
>::const_iterator p
= srnode
.snaps
.begin();
70 p
!= srnode
.snaps
.end();
72 if (p
->second
.name
== name
)
78 bool is_open() const { return open
; }
79 void _close_parents() { open
= false; }
80 bool _open_parents(MDSInternalContextBase
*retryorfinish
, snapid_t first
=1, snapid_t last
=CEPH_NOSNAP
);
81 bool open_parents(MDSInternalContextBase
*retryorfinish
);
82 void _remove_missing_parent(snapid_t snapid
, inodeno_t parent
, int err
);
83 bool have_past_parents_open(snapid_t first
=1, snapid_t last
=CEPH_NOSNAP
);
84 void add_open_past_parent(SnapRealm
*parent
, snapid_t last
);
85 void remove_open_past_parent(inodeno_t ino
, snapid_t last
);
88 void prune_past_parents();
89 bool has_past_parents() const { return !srnode
.past_parents
.empty(); }
91 void build_snap_set(set
<snapid_t
>& s
,
92 snapid_t
& max_seq
, snapid_t
& max_last_created
, snapid_t
& max_last_destroyed
,
93 snapid_t first
, snapid_t last
) const;
94 void get_snap_info(map
<snapid_t
,SnapInfo
*>& infomap
, snapid_t first
=0, snapid_t last
=CEPH_NOSNAP
);
96 const bufferlist
& get_snap_trace();
97 void build_snap_trace(bufferlist
& snapbl
) const;
99 boost::string_view
get_snapname(snapid_t snapid
, inodeno_t atino
);
100 snapid_t
resolve_snapname(boost::string_view name
, inodeno_t atino
, snapid_t first
=0, snapid_t last
=CEPH_NOSNAP
);
102 const set
<snapid_t
>& get_snaps() const;
103 const SnapContext
& get_snap_context() const;
104 void invalidate_cached_snaps() {
107 snapid_t
get_last_created() {
109 return cached_last_created
;
111 snapid_t
get_last_destroyed() {
113 return cached_last_destroyed
;
115 snapid_t
get_newest_snap() {
117 if (cached_snaps
.empty())
120 return *cached_snaps
.rbegin();
122 snapid_t
get_newest_seq() {
127 snapid_t
get_snap_following(snapid_t follows
) {
129 const set
<snapid_t
>& s
= get_snaps();
130 set
<snapid_t
>::const_iterator p
= s
.upper_bound(follows
);
136 bool has_snaps_in_range(snapid_t first
, snapid_t last
) {
138 const set
<snapid_t
>& s
= get_snaps();
139 set
<snapid_t
>::const_iterator p
= s
.lower_bound(first
);
140 return (p
!= s
.end() && *p
<= last
);
143 void adjust_parent();
145 void split_at(SnapRealm
*child
);
146 void join(SnapRealm
*child
);
148 void add_cap(client_t client
, Capability
*cap
) {
149 auto client_caps_entry
= client_caps
.find(client
);
150 if (client_caps_entry
== client_caps
.end())
151 client_caps_entry
= client_caps
.emplace(client
,
152 new xlist
<Capability
*>).first
;
153 client_caps_entry
->second
->push_back(&cap
->item_snaprealm_caps
);
155 void remove_cap(client_t client
, Capability
*cap
) {
156 cap
->item_snaprealm_caps
.remove_myself();
157 if (client_caps
[client
]->empty()) {
158 delete client_caps
[client
];
159 client_caps
.erase(client
);
165 ostream
& operator<<(ostream
& out
, const SnapRealm
&realm
);