Files
NE_YuR/openflow/include/click/ino.hh

134 lines
3.7 KiB
C++

// -*- c-basic-offset: 4; related-file-name: "../../lib/ino.cc" -*-
#ifndef CLICK_INO_HH
#define CLICK_INO_HH
#include <click/router.hh>
CLICK_DECLS
#define INO_DEBUG 0
// /click: .e > .h > element names > global handlers [dt_global]
// /click/.e: element numbers [dt_u]
// /click/.e/NUM: handlers [dt_hu]
// /click/.h: global handlers [dt_hh]
// /click/ELEMENTNAME: .h > element names > element handlers [dt_hn]
// /click/ELEMENTNAME/.h: element handlers [dt_hh]
class ClickIno { public:
void initialize();
void cleanup();
uint32_t generation() const { return _generation; }
// NB: inode number 0 is reserved for the system.
enum { dt_u = 1U, dt_hh = 2U, dt_hu = 3U, dt_hn = 4U, dt_global = 5U };
enum { ino_globaldir = (unsigned) (dt_global << 28),
ino_enumdir = (unsigned) (dt_u << 28) };
static bool is_handler(unsigned ino) { return (int32_t) ino < 0; }
static unsigned dirtype(unsigned ino) { return ino >> 28; }
static bool has_element(unsigned ino) { return ino & 0xFFFFU; }
static bool has_handlers(unsigned ino) { return ino > (dt_u << 28); }
static bool has_names(unsigned ino) { return ino >= (dt_hn << 28); }
static int ino_element(unsigned ino) { return (int) (ino & 0xFFFFU) - 1; }
static int ino_handler(unsigned ino) {
return (has_element(ino) ? 0 : Router::FIRST_GLOBAL_HANDLER)
+ ((ino >> 16) & 0x7FFFU);
}
static unsigned make_handler(int e, int hi) {
return 0x80000000U | ((hi & 0x7FFFU) << 16) | ((e + 1) & 0xFFFFU);
}
static unsigned make_dir(unsigned dtype, int e) {
return (dtype << 28) | ((e + 1) & 0xFFFFU);
}
// These operations should be called with a configuration lock held.
inline int prepare(Router *router, uint32_t generation);
int nlink(ino_t ino);
ino_t lookup(ino_t dir, const String &component);
// readdir handles '..' (f_pos 0) and '.' (f_pos 1).
// It returns the number of things stored.
typedef bool (*filldir_t)(const char *name, int name_len, ino_t ino, int dirtype, loff_t f_pos, void *user_data);
int readdir(ino_t dir, loff_t &f_pos, filldir_t fd, void *user_data);
#if INO_DEBUG
String info() const;
#endif
struct Entry {
// Name of this entry.
String name;
// Corresponding eindex plus 1. Might be larger than the number of
// elements in the router, because of fake directories added for
// compound "elements".
uint16_t elementno_plus1;
// '_x[i].xindex' equals the index in _x of the entry for element
// number 'i - 1'.
uint16_t xindex;
// Number of child entries. 'name' is guaranteed to be a prefix of
// every child entry.
uint16_t skip;
// See enum below. X_FAKE is true on fake directories added for
// compound elements.
uint16_t flags;
};
private:
enum { X_FAKE = 1 };
Entry* _x;
int _nentries;
int _cap;
Router* _router;
uint32_t _generation;
inline int xindex(int elementno) const;
inline int next_xindex(int elementno) const;
inline int elementno(int xindex) const;
int name_search(const String &n, int first_xi, int last_xi, int name_offset) const;
int element_name_search(const String &n, int elementno) const;
int grow(int min_size);
int true_prepare(Router*, uint32_t);
};
inline int
ClickIno::prepare(Router* router, uint32_t generation)
{
if (generation != _generation)
return true_prepare(router, generation);
else
return 0;
}
inline int
ClickIno::xindex(int elementno) const
{
assert(elementno >= -1 && elementno < _nentries - 1);
return _x[elementno + 1].xindex;
}
inline int
ClickIno::next_xindex(int elementno) const
{
int xi = xindex(elementno);
return xi + _x[xi].skip + 1;
}
inline int
ClickIno::elementno(int xindex) const
{
return _x[xindex].elementno_plus1 - 1;
}
CLICK_ENDDECLS
#endif