Re: Encode/Decode new framework

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hey,

I spent a bit of time looking at this today but quickly ran up against a 
problem.  Maybe this is obvious, but I hadn't noticed yesterday. Sam's 
original branch defines encode/decode functions like so:

template<typename type, typename traits=enc_dec_traits<type> >
inline typename std::enable_if<traits::supported && !traits::feature>::type
encode(const type &v, bufferlist &bl, uint64_t features=0) {
  size_t size = traits::estimate(v);
  bufferlist::unsafe_appender app(&bl, size);
  traits::encode(v, app);
}

This type of approach simply doesn't work if our overall goal is to do 
*one* estimate for a complex encode (container of items, or big structure 
that includes smaller ones), and then encode into a preallocated buffer.  
At least it won't work if our encode functions are written in the usual 
way like

  void encode(bufferlist& bl) const {
    ::encode(member1, bl);
    ::encode(member2, bl);
  }

because those encodes will re-invoke the above glue wrappers that do the 
estimation.

In order for this to work, I think a key requirement is that we have 
"new-style" and "old-style" encode functions.  If any old-style code calls 
an old-style encode() on a new-style object, we'll invoke a wrapper like 
the above that does an estimation.  But new-style code has to invoke a 
new-style encode for any nested structures.  (It simply doesn't make sense 
for a new-style encode to encode an old-style object because it can't 
calculate its size.)

That means we need to define a new-style that is distinct.  I suggest 
we just go with Allen's enc_dec scheme.  It's clearly distinct, and 
it promises to be faster for both encode (char *'s passed around) 
and decode.

And then we explicitly disallow new-style enc_dec from encoding old-style 
objects.

Once we do that, I think the glue to make this work will be really simple: 
invoke estimate, preallocate a buffer, and then invoke the new encode.

I think the only trick is containers, where we'll need to define two 
different versions: one for old-style encoders (the existing code with 
enable_if and !supported guarding them) and one for new encoders.

Given that, I think it makes the most sense to start with Allen and 
Varada's original branch.  I'm going to give it a go...

sage





On Wed, 7 Sep 2016, Sage Weil wrote:

> Hi Varada!
> 
> On Wed, 7 Sep 2016, Varada Kari wrote:
> > Hi Sage,
> > 
> > Here is the branch with some changes, not able to compile(yet!). Need to
> > write some more templates for STL(multimap etc...) and intrusive containers.
> > 
> > https://github.com/varadakari/ceph/commits/wip-enc-dec-proto
> > 
> > Right now i am facing some problem with encoding of MonMap with mon_addr
> > which is a map with string and entity_address_t. Have a written template
> > class for string which doesn't need any features. But this map needs a
> > features for address and not for string.
> > Trying to fix the problem. Please have a look. Correct me if i am going
> > in a wrong direction in the implementation(overall approach).
> 
> I think teh way to address this is make sure that non-featured items have 
> the uint64_t features = 0 argument defined for encode (as they do now). 
> Then make the container declaration something like
> 
> template<typename T, typename S>
> struct enc_dec_traits<
>   std::map<T, S>,
>   typename std::enable_if<
>     enc_dec_traits<T>::supported && enc_dec_traits<S>::feature &&
>     (enc_dec_traits<T>::feature || enc_dec_traits<S>::feature)>::type> {
>   const static bool supported = true;
>   const static bool feature = true;
>   ...
> 
> and then make the encode methods pass through a feature argument.  I.e., 
> if either the key or the value requires featurse to encode, we require 
> features to encode.
> 
> Is that what you're asking?
> 
> Alternatively, we can probably avoid specializing the template on 
> featured/unfeatured at all, and in the enc_dec_traits just declare both a 
> featured and unfeatured encode method.  The unfeatured one will error out 
> at compile time if you call it on T or S types that require features.
> 
> I haven't looked to closely at this branch, but it looks like the basic 
> approach is:
> 
>  - my appenders
>  - sam's branch that defines encode with templated App
>  - each object has encode, decode, and estimate
>  - STL containers are defined based on above
> 
> but none of the enc_dec functions that let you write all three in one go.  
> Are you thinking that that would be a separate, orthoganal thing, that 
> lets you write a single enc_dec template function, and then use a macro to 
> declare the encode/decode/estimate functions that call it, so that it all 
> glues together?
> 
> I'm still confused about what we are doing with the encode/decode/estimate 
> members of the enc_dec_traits<> structures.  If we need a traits instance 
> in order to encode/decode, that means we can't do the bare
> 
>   ::encode(foo, bl);
> 
> that we've been doing so far.  Unless there's some other template magic 
> that instantiates the traits on demand?  Something like
> 
> template<class T, class App>
> void encode(const T& a, App &app) {
>   enc_dec_traits<T> t;
>   t.encode(a, app);
> }
> 
> ?
> 
> Should we get on a bluejeans and walk through the possible paths here and 
> pick an approach?  Because I'm pretty confused now by all the variations 
> I've seen.
> 
> sage
> --
> To unsubscribe from this list: send the line "unsubscribe ceph-devel" in
> the body of a message to majordomo@xxxxxxxxxxxxxxx
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 
> 
--
To unsubscribe from this list: send the line "unsubscribe ceph-devel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html



[Index of Archives]     [CEPH Users]     [Ceph Large]     [Information on CEPH]     [Linux BTRFS]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]
  Powered by Linux