Savarese Software Research Corporation
group_session/protocol.h
Go to the documentation of this file.
00001 /*
00002  * Copyright 2006-2009 Savarese Software Research Corporation
00003  *
00004  * Licensed under the Apache License, Version 2.0 (the "License");
00005  * you may not use this file except in compliance with the License.
00006  * You may obtain a copy of the License at
00007  *
00008  *     https://www.savarese.com/software/ApacheLicense-2.0
00009  *
00010  * Unless required by applicable law or agreed to in writing, software
00011  * distributed under the License is distributed on an "AS IS" BASIS,
00012  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00013  * See the License for the specific language governing permissions and
00014  * limitations under the License.
00015  */
00016 
00022 #ifndef __SSRC_WSPR_GROUP_SESSION_PROTOCOL_H
00023 #define __SSRC_WSPR_GROUP_SESSION_PROTOCOL_H
00024 
00025 #include <ssrc/wispers/protocol.h>
00026 #include <ssrc/wispers/utility/Properties.h>
00027 #include <ssrc/wispers/utility/ToString.h>
00028 #include <ssrc/wispers/group_session/types.h>
00029 
00030 // Includes serialize function for std::pair.
00031 #include <boost/serialization/utility.hpp>
00032 
00033 __BEGIN_NS_SSRC_WSPR_PROTOCOL
00034 
00035 WSPR_DEFINE_PROTOCOL(GroupSession,group_session);
00036 
00037 __END_NS_SSRC_WSPR_PROTOCOL
00038 
00039 __BEGIN_NS_SSRC_WSPR_GROUP_SESSION
00040 
00041 using NS_SSRC_WSPR::ByteBuffer;
00042 using NS_SSRC_WSPR_UTILITY::Properties;
00043 using NS_SSRC_WSPR_UTILITY::properties_ptr;
00044 using NS_SSRC_WSPR_UTILITY::ToString;
00045 using NS_SSRC_WISP_PROTOCOL::wisp_message_protocol;
00046 
00047 typedef std::vector<gsid_type> gsid_container;
00048 typedef std::vector<uid_type> uid_container;
00049 typedef std::vector<GroupSession> group_session_container;
00050 typedef std::vector<Reservation> reservation_container;
00051 typedef std::vector<Member> member_container;
00052 
00053 struct GroupSessionProtocol :
00054   public protocol::ServiceProtocol<protocol::GroupSession>
00055 {
00056   typedef protocol::ServiceProtocol<protocol::GroupSession> super;
00057 
00058   WISP_IMPORT(super, caller_type);
00059 
00061   static const gsid_type GSIDMax = boost::integer_traits<gsid_type>::const_max;
00062 
00064   static const gsid_type GSIDMin = boost::integer_traits<gsid_type>::const_min;
00065 
00071   // Calculation is independent of whether gsid_type is signed or unsigned.
00072   // Protocol numbers start at 0, which is why we use
00073   // boost::integer_traits<wisp_message_protocol>::const_max without respect
00074   // to the distance to const_min.
00075   static const gsid_type GSIDSpace =
00076       (((boost::integer_traits<gsid_type>::const_max >> 2) + 1)
00077        - (boost::integer_traits<gsid_type>::const_min >> 2))  /
00078       ((boost::integer_traits<wisp_message_protocol>::const_max >> 2) + 1);
00079 
00080   static string event_group_expire() {
00081     return WSPR_EVENT_GROUP("group_session", "expire");
00082   }
00083 
00084   enum {
00085     RelayEvent,
00086     RelayEventSelfDiscard,
00087     RelayEvents,
00088     RelayEventsSelfDiscard,
00089     CreateGroupSession,
00090     EndGroupSession,
00091     ExpireGroupSession,
00092     FindGroupSessions,
00093     FindGroupSessionsResult,
00094     FindGroupSessionsForMember,
00095     ReturnGroupSessionsForMember,
00096     FindGroupSessionsByType,
00097     ReturnGroupSessionsByType,
00098     CreateReservation,
00099     CancelReservation,
00100     StartGroupSession,
00101     FindMembers,
00102     FindMembersResult,
00103     AddMembers,
00104     RemoveMembers,
00105     AddMember,
00106     AddMemberConfirm,
00107     RemoveMember,
00108     RemoveMemberConfirm
00109   };
00110 
00111   enum { DefaultPayloadCapacity = NS_SSRC_SPREAD::Message::DefaultCapacity };
00112 
00113   enum MemberType { Participant, Observer };
00114 
00115   struct MessageCreateGroupSession :
00116     public protocol::MessageGroupSession<CreateGroupSession>
00117   {
00118     string session_name;
00119     string session_group;
00120     string session_type;
00121     sec_type lifetime;
00122     uid_container participants;
00123     unsigned int max_observers;
00124     ByteBuffer payload;
00125 
00126     MessageCreateGroupSession() : payload(DefaultPayloadCapacity) { }
00127 
00128     MessageCreateGroupSession(const string & session_name,
00129                               const string & session_group,
00130                               const string & session_type,
00131                               const sec_type lifetime,
00132                               const uid_container & participants,
00133                               const unsigned int max_observers) :
00134       session_name(session_name),
00135       session_group(session_group),
00136       session_type(session_type),
00137       lifetime(lifetime),
00138       participants(participants),
00139       max_observers(max_observers),
00140       payload(DefaultPayloadCapacity)
00141     { }
00142 
00143     template<class Archive>
00144     void serialize(Archive & ar, const unsigned int) {
00145       ar & session_name & session_group & session_type & lifetime
00146          & participants & max_observers & payload;
00147     }
00148   };
00149 
00150   struct MessageCreateReservation :
00151     public protocol::MessageGroupSession<CreateReservation>
00152   {
00153     string session_name;
00154     string session_group;
00155     string session_type;
00156     sec_type gs_lifetime;
00157     uid_type creator_uid;
00158     sec_type reservation_lifetime;
00159     unsigned int max_observers;
00160     ByteBuffer payload;
00161 
00162     MessageCreateReservation() : payload(DefaultPayloadCapacity) { }
00163 
00164     MessageCreateReservation(const string & session_name,
00165                              const string & session_group,
00166                              const string & session_type,
00167                              const sec_type gs_lifetime,
00168                              const uid_type creator_uid,
00169                              const sec_type reservation_lifetime,
00170                              const unsigned int max_observers) :
00171       session_name(session_name),
00172       session_group(session_group),
00173       session_type(session_type),
00174       gs_lifetime(gs_lifetime),
00175       creator_uid(creator_uid),
00176       reservation_lifetime(reservation_lifetime),
00177       max_observers(max_observers),
00178       payload(DefaultPayloadCapacity)
00179     { }
00180 
00181     template<class Archive>
00182     void serialize(Archive & ar, const unsigned int) {
00183       ar & session_name & session_group & session_type & gs_lifetime
00184         & creator_uid & reservation_lifetime & max_observers & payload;
00185     }
00186   };
00187 
00188   WISP_PROTOCOL_MESSAGE(EndGroupSession, protocol::MessageGroupSession,
00189                         ((gsid_type, gsid)));
00190 
00191   WISP_PROTOCOL_MESSAGE(CancelReservation, protocol::MessageGroupSession,
00192                         ((gsid_type, gsid))((uid_type, requestor)));
00193 
00194   WISP_PROTOCOL_MESSAGE(StartGroupSession,
00195                         protocol::MessageGroupSession,
00196                         ((string, gs_name))
00197                         ((GroupSession, session)));
00198 
00199   WISP_STRUCT(ExpirationNotification,
00200               ((gsid_type, gsid))
00201               ((uid_container, uids)));
00202   typedef
00203   std::vector<ExpirationNotification> expiration_notification_container;
00207   WISP_PROTOCOL_MESSAGE(ExpireGroupSession, protocol::MessageGroupSession,
00208                         ((expiration_notification_container, notifications)));
00209 
00210   WISP_PROTOCOL_MESSAGE_WITH_INIT(RelayEvent, protocol::MessageGroupSession,
00211                                   ((gsid_type, gsid))
00212                                   ((string, event_queue))
00213                                   ((properties_ptr, event)),
00214                                   ((gsid_type()))
00215                                   ((string()))
00216                                   ((properties_ptr(new Properties))));
00217 
00218   WISP_PROTOCOL_MESSAGE_WITH_INIT(RelayEventSelfDiscard,
00219                                   protocol::MessageGroupSession,
00220                                   ((uid_type, source))
00221                                   ((gsid_type, gsid))
00222                                   ((string, event_queue))
00223                                   ((properties_ptr, event)),
00224                                   ((uid_type()))
00225                                   ((gsid_type()))
00226                                   ((string()))
00227                                   ((properties_ptr(new Properties))));
00228 
00229   WISP_PROTOCOL_MESSAGE_WITH_INIT(RelayEvents, protocol::MessageGroupSession,
00230                                   ((gsid_type, gsid))
00231                                   ((string, event_queue))
00232                                   ((std::vector<Properties>, events)),
00233                                   ((gsid_type()))
00234                                   ((string()))
00235                                   ((std::vector<Properties>())));
00236 
00237   WISP_PROTOCOL_MESSAGE_WITH_INIT(RelayEventsSelfDiscard,
00238                                   protocol::MessageGroupSession,
00239                                   ((uid_type, source))
00240                                   ((gsid_type, gsid))
00241                                   ((string, event_queue))
00242                                   ((std::vector<Properties>, events)),
00243                                   ((uid_type()))
00244                                   ((gsid_type()))
00245                                   ((string()))
00246                                   ((std::vector<Properties>())));
00247 
00248   WISP_PROTOCOL_MESSAGE(FindGroupSessions, protocol::MessageGroupSession,
00249                         ((uid_type, requestor))
00250                         ((db_limit_type, limit))
00251                         ((db_offset_type, offset)));
00252 
00253   WISP_PROTOCOL_MESSAGE(FindGroupSessionsResult, protocol::MessageGroupSession,
00254                         ((uid_type, requestor))
00255                         ((unsigned int, total_sessions))
00256                         ((db_limit_type, limit))
00257                         ((db_offset_type, offset))
00258                         ((string, gs_name))
00259                         ((group_session_container, sessions)));
00260 
00261   WISP_PROTOCOL_MESSAGE(FindGroupSessionsForMember,
00262                         protocol::MessageGroupSession,
00263                         ((uid_type, uid)));
00264 
00265   WISP_PROTOCOL_MESSAGE(ReturnGroupSessionsForMember,
00266                         protocol::MessageGroupSession,
00267                         ((uid_type, uid))
00268                         ((string, gs_name))
00269                         ((group_session_container, participating))
00270                         ((group_session_container, observing))
00271                         ((reservation_container, awaiting)));
00272 
00273   typedef std::vector<string> query_list;
00274   WISP_PROTOCOL_MESSAGE(FindGroupSessionsByType, protocol::MessageGroupSession,
00275                         ((query_list, keys)));
00276   WISP_PROTOCOL_MESSAGE(ReturnGroupSessionsByType,
00277                         protocol::MessageGroupSession,
00278                         ((group_session_container, sessions)));
00279 
00280   WISP_PROTOCOL_MESSAGE(FindMembers,
00281                         protocol::MessageGroupSession,
00282                         ((uid_type, requestor))
00283                         ((gsid_container, sessions)));
00284 
00285   WISP_PROTOCOL_MESSAGE(FindMembersResult,
00286                         protocol::MessageGroupSession,
00287                         ((uid_type, requestor))
00288                         ((member_container, participants))
00289                         ((member_container, observers)));
00290 
00291   WISP_PROTOCOL_MESSAGE(AddMembers,
00292                         protocol::MessageGroupSession,
00293                         ((member_container, participants))
00294                         ((member_container, observers)));
00295 
00296   WISP_PROTOCOL_MESSAGE(RemoveMembers,
00297                         protocol::MessageGroupSession,
00298                         ((member_container, participants))
00299                         ((member_container, observers)));
00300 
00301   WISP_PROTOCOL_MESSAGE(AddMember,
00302                         protocol::MessageGroupSession,
00303                         ((MemberType, member_type))
00304                         ((Member, member)));
00305 
00306   enum AddMemberResultCode {
00307     AddMemberInternalError,
00308     AddMemberNonexistentGroupSession,
00309     AddMemberDuplicateEntry,
00310     AddMemberMaxObserversReached,
00311     AddMemberSuccess
00312   };
00313 
00314   WISP_PROTOCOL_MESSAGE(AddMemberConfirm,
00315                         protocol::MessageGroupSession,
00316                         ((AddMemberResultCode, result))
00317                         ((MemberType, member_type))
00318                         ((uid_type, uid))
00319                         ((string, gs_name))
00320                         ((GroupSession, session)));
00321 
00322   WISP_PROTOCOL_MESSAGE(RemoveMember,
00323                         protocol::MessageGroupSession,
00324                         ((MemberType, member_type))
00325                         ((Member, member)));
00326 
00327   WISP_PROTOCOL_MESSAGE(RemoveMemberConfirm,
00328                         protocol::MessageGroupSession,
00329                         ((MemberType, member_type))
00330                         ((Member, member))
00331                         ((string, gs_name))
00332                         ((GroupSession, session)));
00333 
00334   WISP_ONE_WAY_CALL(caller_type, CreateGroupSession);
00335   WISP_ONE_WAY_CALL(caller_type, EndGroupSession);
00336   WISP_ONE_WAY_CALL(caller_type, ExpireGroupSession);
00337   WISP_ONE_WAY_CALL(caller_type, RelayEvent);
00338   WISP_ONE_WAY_CALL(caller_type, RelayEventSelfDiscard);
00339   WISP_ONE_WAY_CALL(caller_type, RelayEvents);
00340   WISP_ONE_WAY_CALL(caller_type, RelayEventsSelfDiscard);
00341 
00342   WISP_ONE_WAY_CALL(caller_type, CreateReservation);
00343   WISP_ONE_WAY_CALL(caller_type, CancelReservation);
00344   WISP_ONE_WAY_CALL(caller_type, StartGroupSession);
00345 
00346   WISP_TWO_WAY_CALL(caller_type, FindGroupSessionsForMember,
00347                     ReturnGroupSessionsForMember);
00348   WISP_ONE_WAY_CALL(caller_type, ReturnGroupSessionsForMember);
00349 
00350   WISP_TWO_WAY_CALL(caller_type, FindGroupSessionsByType,
00351                     ReturnGroupSessionsByType);
00352   WISP_ONE_WAY_CALL(caller_type, ReturnGroupSessionsByType);
00353 
00354   // Conceptually these are two-way calls, but we don't invoke them that way.
00355   WISP_ONE_WAY_CALL(caller_type, FindGroupSessions);
00356   WISP_ONE_WAY_CALL(caller_type, FindGroupSessionsResult);
00357   WISP_ONE_WAY_CALL(caller_type, FindMembers);
00358   WISP_ONE_WAY_CALL(caller_type, FindMembersResult);
00359 
00360 
00361   WISP_ONE_WAY_CALL(caller_type, AddMembers);
00362   WISP_ONE_WAY_CALL(caller_type, RemoveMembers);
00363   WISP_ONE_WAY_CALL(caller_type, AddMember);
00364   WISP_ONE_WAY_CALL(caller_type, AddMemberConfirm);
00365   WISP_ONE_WAY_CALL(caller_type, RemoveMember);
00366   WISP_ONE_WAY_CALL(caller_type, RemoveMemberConfirm);
00367 };
00368 
00378 template<typename session_type>
00379 inline void bind_group_session_properties(const session_type & session,
00380                                           Properties & node)
00381 {
00382   node.set(session.gsid, "gsid");
00383   node.set(session.created, "created");
00384   node.set(session.expires, "expires");
00385   node.set(session.type, "type");
00386   node.set(session.name, "name");
00387 }
00388 
00395 inline gsid_type gsid_min(const wisp_message_protocol protocol) {
00396   return
00397     (GroupSessionProtocol::GSIDMin +
00398      (static_cast<gsid_type>(protocol) * GroupSessionProtocol::GSIDSpace));
00399 }
00400 
00407 inline gsid_type gsid_max(const wisp_message_protocol protocol) {
00408   return
00409     ((GroupSessionProtocol::GSIDMin +
00410       (static_cast<gsid_type>(protocol) + 1) * GroupSessionProtocol::GSIDSpace) - 1);
00411 }
00412 
00424 inline gsid_type gsid_min(const wisp_message_protocol protocol,
00425                           const unsigned int partition_id,
00426                           const unsigned int num_partitions)
00427 {
00428   const gsid_type min_gsid = gsid_min(protocol);
00429   const gsid_type space = GroupSessionProtocol::GSIDSpace / num_partitions;
00430 
00431   return (min_gsid + space * partition_id);
00432 }
00433 
00445 inline gsid_type gsid_max(const wisp_message_protocol protocol,
00446                           const unsigned int partition_id,
00447                           const unsigned int num_partitions)
00448 {
00449   // Spill over space rounding error to last partition.
00450   if(partition_id >= (num_partitions - 1))
00451     return gsid_max(protocol);
00452 
00453   return gsid_min(protocol, partition_id + 1, num_partitions) - 1;
00454 }
00455 
00462 inline wisp_message_protocol gsid_to_protocol(const gsid_type gsid) {
00463   // Can't use basic algebra because of overflow.
00464   gsid_type result(gsid);
00465 
00466   if(gsid < 0)
00467     result-=GroupSessionProtocol::GSIDMin;
00468 
00469   result /= GroupSessionProtocol::GSIDSpace;
00470 
00471   if(gsid >= 0) {
00472     const gsid_type midpoint = 
00473       (boost::integer_traits<wisp_message_protocol>::const_min / -2);
00474     result+=midpoint;
00475   }
00476 
00477   return static_cast<wisp_message_protocol>(result);
00478 }
00479 
00488 inline
00489 unsigned int gsid_to_protocol_partition(gsid_type gsid,
00490                                         const unsigned int num_partitions)
00491 {
00492   const wisp_message_protocol protocol = gsid_to_protocol(gsid);
00493   const gsid_type space = GroupSessionProtocol::GSIDSpace / num_partitions;
00494 
00495   gsid-=gsid_min(protocol);
00496   gsid /= space;
00497 
00498   if(gsid >= num_partitions)
00499     gsid = num_partitions - 1;
00500 
00501   return static_cast<unsigned int>(gsid);
00502 }
00503 
00511 class GSToGroup {
00512   const string _gs_protocol_prefix;
00513   string _gs_group;
00514   ToString _string_cast;
00515 
00516 public:
00517 
00518   GSToGroup() :
00519     _gs_protocol_prefix("wspr.gs.protocol."),
00520     _gs_group(_gs_protocol_prefix),
00521     _string_cast()
00522   { }
00523 
00524   const string & gs_protocol_group(const wisp_message_protocol protocol) {
00525     _gs_group.erase(_gs_protocol_prefix.size());
00526     return _gs_group.append(_string_cast(protocol));
00527   }
00528 
00529   const string &
00530   gs_protocol_partition_group(const wisp_message_protocol protocol,
00531                               const unsigned int partition_id)
00532   {
00533     _gs_group.erase(_gs_protocol_prefix.size());
00534     _gs_group.append(_string_cast(protocol)).append(".");
00535     // Can't string together all of the appends because of undefined
00536     // execution order of _string_cast, which returns a reference and
00537     // can cause the protocol value to be used in each case.
00538     return _gs_group.append(_string_cast(partition_id));
00539   }
00540 
00541   const string & gsid_protocol_group(const gsid_type gsid) {
00542     return gs_protocol_group(gsid_to_protocol(gsid));
00543   }
00544 };
00545 
00555 inline string gs_protocol_group(const wisp_message_protocol protocol) {
00556   GSToGroup gsid_to_group;
00557   return gsid_to_group.gs_protocol_group(protocol);
00558 }
00559 
00571 inline
00572 string gs_protocol_partition_group(const wisp_message_protocol protocol,
00573                                    const unsigned int partition_id)
00574 {
00575   GSToGroup gsid_to_group;
00576   return gsid_to_group.gs_protocol_partition_group(protocol, partition_id);
00577 }
00578 
00587 inline string gsid_protocol_group(const gsid_type gsid) {
00588   GSToGroup gsid_to_group;
00589   return gsid_to_group.gsid_protocol_group(gsid);
00590 }
00591 
00592 __END_NS_SSRC_WSPR_GROUP_SESSION
00593 
00594 #endif

Savarese Software Research Corporation
Copyright © 2006-2011 Savarese Software Research Corporation. All rights reserved.