LTP GCOV extension - code coverage report
Current view: directory - net/tipc - name_table.c
Test: tipc.info
Date: 2003-08-07 Instrumented lines: 371
Code covered: 66.0 % Executed lines: 245

       1                 : /* 
       2                 :  * TIPC Linux kernel implementation
       3                 :  * Copyright (c) 2001-2003 Ericsson Research Canada
       4                 :  * Copyright (c) 2003 OSDL, Inc.
       5                 :  *
       6                 :  * This file is based on the original source code done by Jon Maloy
       7                 :  * (jon.maloy@ericsson.com) for TIPC version 0.96, available from
       8                 :  * http://tipc.sourceforge.net
       9                 :  ***************************************************************************
      10                 :  * This program is free software; you can redistribute it and/or modify
      11                 :  * it under the terms of the GNU General Public License as published by
      12                 :  * the Free Software Foundation; either version 2 of the License, or
      13                 :  * (at your option) any later version.
      14                 :  *   
      15                 :  * This program is distributed in the hope that it will be useful,
      16                 :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      17                 :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      18                 :  * GNU General Public License for more details.
      19                 :  *  
      20                 :  * You should have received a copy of the GNU General Public License
      21                 :  * along with this program; if not, write to the Free Software
      22                 :  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
      23                 :  ***************************************************************************
      24                 :  * Alphabetical list of people who have worked on this file:
      25                 :  *      - Mark Haverkamp        (markh@osdl.org)
      26                 :  *      - Mika Kukkonen         (mika@osdl.org)
      27                 :  *      - Rusty Lynch           (rusty@linux.intel.com)
      28                 :  */
      29                 : 
      30                 : #include "debug.h"
      31                 : #include "msg_buf.h"
      32                 : #include "name_table.h"
      33                 : #include "named.h"
      34                 : #include "net_event.h"
      35                 : #include "name_subscription.h"
      36                 : #include "port.h"
      37                 : #include "link.h"
      38                 : #include <net/tipc.h>
      39                 : 
      40                 : #ifdef CONFIG_TIPC_DBG_BUF
      41                 : void nametbl_print(tipc_dbg_buf_t * buf, const char *str);
      42                 : void nametbl_dump(void);
      43                 : #endif
      44                 : uint published_reserved = 0;
      45                 : 
      46                 : Publication *publ_pool = 0;
      47                 : 
      48                 : void
      49                 : publ_handleUnavailable(Publication * this, tipc_net_addr_t a)
      50               0 : {
      51                 :         dbg_msg("publ_handleUnavailable: %x\n", a);
      52               0 :         nametbl_remove(this->type, this->lower, this->node, this->key);
      53                 : }
      54                 : 
      55                 : Publication *
      56                 : publ_new(uint type,
      57                 :          uint lower,
      58                 :          uint upper, uint port, tipc_net_addr_t node, uint scope, uint key)
      59              24 : {
      60              24 :         Publication *this;
      61                 : 
      62              25 :         mem_cnew(this, publ_pool, 32500);
      63              24 :         netwsub_init(&this->subscription,
      64                 :                      this, (NS_Virtual) 0, (NS_Virtual) publ_handleUnavailable);
      65                 :         assert(this->prev == 0);
      66              24 :         this->next = this;
      67              24 :         this->prev = this;
      68              24 :         this->type = type;
      69              24 :         this->lower = lower;
      70              24 :         this->upper = upper;
      71              24 :         this->port = port;
      72              24 :         this->node = node;
      73              24 :         this->scope = scope;
      74              24 :         this->key = key;
      75              24 :         this->nextInPortChain = 0;
      76              24 :         if (node != tipc_my_addr) {
      77               5 :                 tipc_net_register(&this->subscription, node);
      78                 :         }
      79              24 :         return this;
      80                 : }
      81                 : 
      82                 : void
      83                 : publ_delete(Publication * this)
      84              18 : {
      85                 :         dbg_msg("publ_delete called, node = %x\n", this->node);
      86                 :         assert(this->prev);
      87                 :         assert(this->next);
      88              18 :         this->prev->next = this->next;
      89              18 :         this->next->prev = this->prev;
      90              18 :         this->prev = 0;
      91              18 :         this->next = publ_pool;
      92              18 :         publ_pool = this;
      93              18 :         if (this->node != tipc_my_addr) {
      94               1 :                 netwsub_unsubscribe(&this->subscription);
      95                 :         }
      96                 : }
      97                 : 
      98                 : /* ////////////////////////////////////////////////////////////// 
      99                 : //
     100                 : //  SubSequence: A contiguous sub-sequence within a name sequence.
     101                 : //  A subsequence refers to 'Publication' objects representing
     102                 : //  the ports from which  the publications are issued.
     103                 : //  A big independent area of subsequences is maintained here
     104                 : //  because of the need for efficient memory usage, while
     105                 : //  allocation/deallocation speed is less critical.
     106                 : //
     107                 : ////////////////////////////////////////////////////////////// */
     108                 : 
     109                 : typedef struct SubSequence {
     110                 :         uint lower;
     111                 :         uint upper;
     112                 :         Publication *preferred;
     113                 :         Publication *loadshared;
     114                 : } SubSequence;
     115                 : 
     116                 : #define SS_SIZE (sizeof(SubSequence))
     117                 : 
     118                 : #define subseq_busy(X) (*((int *)&((X)->preferred)) != ~0)
     119                 : #define subseq_setFree(X) {(X)->preferred = (Publication*)~0;};
     120                 : 
     121                 : #define subseq_get(X,Y) (pools[(X)]?&pools[(X)]->subsequences[(Y)]:0)
     122                 : 
     123                 : typedef struct SubSequencePool {
     124                 :         uint size;
     125                 :         uint occupied;
     126                 :         SubSequence subsequences[1];
     127                 : } SubSequencePool;
     128                 : 
     129                 : SubSequencePool *pools[20] =
     130                 :     { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
     131                 : 
     132                 : SubSequence *
     133                 : subseq_allocate(uint sz, uint * poolno, uint * i)
     134              11 : {
     135              11 :         struct SubSequencePool *pool;
     136              11 :         uint chunk_size = *poolno = 1;
     137                 : 
     138                 :         dbg_msg("Subseq: allocating %u items\n", sz);
     139              11 :         while (chunk_size < sz) {
     140              13 :                 chunk_size = chunk_size << 1;
     141              13 :                 (*poolno)++;
     142                 :         }
     143                 :         dbg_msg("Subseq: found pool no %u, is %p \n", *poolno, pools[*poolno]);
     144                 :         assert(*poolno < 20);
     145              11 :         pool = pools[*poolno];
     146                 : 
     147                 :         /* Make sure that there is free space: */
     148              11 :         if (!pool) {
     149               5 :                 uint oc =
     150                 :                     2 * sizeof (int) +
     151               5 :                     ((4000 < (chunk_size * SS_SIZE)) ? (chunk_size * SS_SIZE) : 4000);
     152                 :                 dbg_msg("Subseq: allocating new pool of sz %u/%u \n", oc,
     153                 :                         (oc / SS_SIZE));
     154               5 :                 pool = pools[*poolno] = (SubSequencePool *) mem_alloc(oc);
     155               5 :                 memset(pool, 0xff, oc);
     156               5 :                 pool->size = oc / SS_SIZE / chunk_size;
     157               5 :                 pool->occupied = 0;
     158               6 :         } else if (pool->occupied >= pool->size) {
     159               0 :                 uint oc = pool->size * SS_SIZE * chunk_size + 2 * sizeof (int);
     160                 : 
     161                 :                 assert(pool->occupied == pool->size);
     162               0 :                 pool =
     163                 :                     (struct SubSequencePool *) mem_alloc((oc * 2) -
     164                 :                                                          2 * sizeof (int));
     165               0 :                 memset(((char *) pool) + oc, 0xff, oc - 2 * sizeof (int));
     166               0 :                 memcpy(pool, pools[*poolno], oc);
     167               0 :                 pool->size *= 2;
     168               0 :                 mem_free((char *) pools[*poolno]);
     169               0 :                 pools[*poolno] = pool;
     170                 :                 dbg_msg("Subseq: extended pool no: %u->%u \n", oc / SS_SIZE,
     171                 :                         pool->size);
     172                 :         }
     173                 :         dbg_msg("Subseq: pool no %u is %p\n", *poolno, pool);
     174                 :         dbg_msg(".. has sz %u, %u busy\n", pool ? pool->size : 0,
     175                 :                 pool ? pool->occupied : 0);
     176                 : 
     177                 :         /* Find first free space: */
     178              11 :         for (*i = 0; subseq_busy(&(pool->subsequences[*i])); (*i) += chunk_size) {
     179                 :                 assert(*i < (pool->size * chunk_size));
     180                 :         }
     181              11 :         pool->occupied++;
     182              11 :         memset(&(pool->subsequences[*i]), 0, sizeof (SubSequence));
     183                 :         dbg_msg("Subseq: found space at pos %u, in pool %u\n", *i, *poolno);
     184              11 :         return &pool->subsequences[*i];
     185                 : }
     186                 : 
     187                 : void
     188                 : subseq_deallocate(uint poolno, uint index)
     189               9 : {
     190                 :         assert(pools[poolno]);
     191                 :         dbg_msg("Subseq: deallocating at pos %u, in pool %u\n", index, poolno);
     192               9 :         subseq_setFree(&pools[poolno]->subsequences[index]);
     193               9 :         pools[poolno]->occupied--;
     194                 : }
     195                 : 
     196                 : /* ////////////////////////////////////////////////////////////// 
     197                 : //
     198                 : //  NameSequence: A container of more or less contiguous sub-
     199                 : //  sequences of name individuals. All individuals represent
     200                 : //  a name of the same 'type'. 
     201                 : //
     202                 : ////////////////////////////////////////////////////////////// */
     203                 : 
     204                 : typedef struct NameSequence {
     205                 :         uint type;
     206                 :         uint subseqPool;
     207                 :         uint subseqIndex;
     208                 :         uint allocated;
     209                 :         uint firstFree;
     210                 :         struct NameSequence *prev;
     211                 :         struct NameSequence *next;
     212                 :         NameSubscription *subscriptions;
     213                 : } NameSequence;
     214                 : 
     215                 : NameSequence *nameseq_pool = 0;
     216                 : 
     217                 : NameSequence *
     218                 : nameseq_new(uint type, NameSequence * next)
     219               5 : {
     220               5 :         NameSequence *this;
     221                 : 
     222               6 :         mem_cnew(this, nameseq_pool, 16000);
     223                 :         dbg_msg("nameseq_new called()  for type %u, next =%p\n", type, next);
     224               5 :         this->allocated = 0;
     225               5 :         this->firstFree = 0;
     226               5 :         this->subseqPool = 0;
     227               5 :         this->subseqIndex = 0;
     228               5 :         this->type = type;
     229               5 :         this->prev = 0;
     230               5 :         this->next = next;
     231               5 :         this->subscriptions = 0;
     232               5 :         if (next)
     233               0 :                 next->prev = this;
     234               5 :         return this;
     235                 : }
     236                 : 
     237                 : void
     238                 : nameseq_delete(NameSequence * this)
     239               3 : {
     240                 :         dbg_msg("nameseq_delete called() %p: firstFree = %u,alloc = %u\n",
     241                 :                 this, this->firstFree, this->allocated);
     242                 :         assert(this->firstFree == 0);
     243                 :         assert(this->subscriptions == 0);
     244               3 :         subseq_deallocate(this->subseqPool, this->subseqIndex);
     245               3 :         this->next = nameseq_pool;
     246               3 :         nameseq_pool = this;
     247                 : }
     248                 : 
     249                 : #define nameseq_findSubsequence(this,subsequences,instance,res)\
     250                 : {\
     251                 :    uint mid = 0;\
     252                 :    int low = 0;\
     253                 :    int high = (this)->firstFree - 1;\
     254                 :    res = ~0;\
     255                 :    while (low <= high)\
     256                 :    {\
     257                 :       mid = (low + high) / 2;\
     258                 :       if (((instance) >= subsequences[mid].lower) &&\
     259                 :           ((instance) <= subsequences[mid].upper))\
     260                 :       {\
     261                 :          res = mid;\
     262                 :          break;\
     263                 :       }\
     264                 :       else\
     265                 :       {\
     266                 :          if ((instance) < subsequences[mid].lower)\
     267                 :          {\
     268                 :             high = mid - 1;\
     269                 :          }\
     270                 :          else\
     271                 :          {\
     272                 :             low = mid + 1;\
     273                 :          }\
     274                 :       }\
     275                 :    }\
     276                 : \
     277                 :    if (res < 0)\
     278                 :    /* No match, return inverse of position where insertion can be done */\
     279                 :    {\
     280                 :      if ((this)->firstFree)\
     281                 :      {\
     282                 :         assert(mid <= (this)->firstFree);\
     283                 :         res = ((subsequences[mid].upper<(instance))?mid+1:mid);\
     284                 :         assert(res <= (int)(this)->firstFree);\
     285                 :         if (res < (int)(this)->firstFree)\
     286                 :         { \
     287                 :            assert(subsequences[res].lower > (instance));\
     288                 :         }\
     289                 :         else assert(subsequences[res-1].upper < (instance));\
     290                 :         res=~res; \
     291                 :      }\
     292                 :      else {assert(res == ~0);};\
     293                 :    }\
     294                 : }
     295                 : 
     296                 : Publication *
     297                 : nameseq_insert(NameSequence * this,
     298                 :                uint type,
     299                 :                uint lower,
     300                 :                uint upper,
     301                 :                uint port,
     302                 :                tipc_net_addr_t node, uint scope, uint preferred, uint key)
     303              24 : {
     304              24 :         int i = ~0;
     305              24 :         Publication *publ = 0;
     306              24 :         SubSequence *sseqs = subseq_get(this->subseqPool, this->subseqIndex);
     307              24 :         uint new_subsequence = 0;
     308                 : 
     309              24 :         if (!sseqs) {
     310               5 :                 subseq_allocate(1, &this->subseqPool, &this->subseqIndex);
     311               5 :                 this->allocated = 1;
     312               5 :                 sseqs = subseq_get(this->subseqPool, this->subseqIndex);
     313                 :         } else {
     314              19 :                 int u;
     315                 : 
     316              19 :                 nameseq_findSubsequence(this, sseqs, lower, i);
     317              19 :                 nameseq_findSubsequence(this, sseqs, upper, u);
     318              19 :                 if (u != i)
     319               0 :                         return 0;
     320                 :         }
     321                 : 
     322              24 :         if (i < 0) {         /* No match found, insert new subsequence */
     323                 :                 /* Make sure there is enough space: */
     324              22 :                 if (this->firstFree >= this->allocated) {
     325               6 :                         uint oldpool = this->subseqPool;
     326               6 :                         uint oldindex = this->subseqIndex;
     327               6 :                         SubSequence *oldss = sseqs;
     328               6 :                         uint newsize = this->allocated * 2;
     329                 : 
     330                 :                         dbg_msg("nameseq_insert:expanding %u->%u\n",
     331                 :                                 this->allocated, newsize);
     332                 :                         assert(this->firstFree == this->allocated);
     333               6 :                         subseq_allocate(newsize, &this->subseqPool,
     334                 :                                         &this->subseqIndex);
     335               6 :                         sseqs = subseq_get(this->subseqPool, this->subseqIndex);
     336               6 :                         memcpy(sseqs, oldss, this->allocated * SS_SIZE);
     337               6 :                         subseq_deallocate(oldpool, oldindex);
     338               6 :                         this->allocated = newsize;
     339                 :                 }
     340                 : 
     341              22 :                 i = ~i;         /* Gives insert position */
     342                 :                 dbg_msg("nameseq_insert:inserting into pos %u <%u,%u,%u>\n",
     343                 :                         i, type, lower, upper);
     344                 : 
     345              22 :                 if (i < (int) this->firstFree) {  /* Insert new */
     346              13 :                         char *from = ((char *) &sseqs[i]);
     347              13 :                         uint sz = ((char *) &sseqs[this->firstFree]) - from;
     348                 : 
     349              13 :                         if (i && !(sseqs[i - 1].upper < lower))
     350               0 :                                 return 0;
     351              13 :                         memmove(&sseqs[i + 1], from, sz);
     352                 :                 }
     353              22 :                 this->firstFree++;
     354              22 :                 sseqs[i].preferred = 0;
     355              22 :                 sseqs[i].loadshared = 0;
     356              22 :                 sseqs[i].lower = lower;
     357              22 :                 sseqs[i].upper = upper;
     358              22 :                 new_subsequence = 1;
     359                 :         } else {                /* Subsequences must match exactly */
     360                 : 
     361               2 :                 if ((sseqs[i].lower != lower) || (sseqs[i].upper != upper)) {
     362               0 :                         Publication *p =
     363                 :                             sseqs[i].preferred ? sseqs[i].preferred : sseqs[i].
     364               0 :                             loadshared;
     365               0 :                         tipc_net_addr_t a = p ? p->node : 0;
     366                 : 
     367               0 :                         warn("TIPC: Attempted publication <%u,%u,%u> from port <%u.%u.%u:%u>\n" "overlaps with existing one <%u,%u,%u> from port <%u.%u.%u:%u>\n", type, lower, upper, tipc_zone_id(node), tipc_cluster_id(node), tipc_node_id(node), port, type, sseqs[i].lower, sseqs[i].upper, tipc_zone_id(a), tipc_cluster_id(a), tipc_node_id(a), p ? p->port : 0);
     368               0 :                         return 0;
     369                 :                 }
     370                 :         }
     371                 : 
     372                 :         /* Insert a port reference: */
     373                 : 
     374              24 :         publ = publ_new(type, lower, upper, port, node, scope, key);
     375              24 :         if ((node == tipc_my_addr) && (preferred)) {
     376               2 :                 if (sseqs[i].preferred) {
     377                 : 
     378               0 :                         err("TIPC: User Error: Preferred local publication <%u,%u,%u> from port" " %u\n clashes with existing one from port %u\n", type, lower, upper, port, sseqs[i].preferred->port);
     379               0 :                         publ_delete(publ);
     380               0 :                         return 0;
     381                 :                 }
     382               2 :                 sseqs[i].preferred = publ;
     383                 :         } else {
     384              22 :                 Publication *crs = sseqs[i].loadshared;
     385                 : 
     386              22 :                 if (!crs)
     387              22 :                         crs = publ;
     388              22 :                 publ->next = crs;
     389              22 :                 publ->prev = crs->prev;
     390              22 :                 publ->prev->next = publ;
     391              22 :                 publ->next->prev = publ;
     392              22 :                 sseqs[i].loadshared = publ;
     393                 :         }
     394                 : 
     395                 :         /* Any subscriptions waiting ? */
     396              24 :         if (new_subsequence) {
     397              22 :                 NameSubscription *s = this->subscriptions;
     398                 : 
     399              22 :                 while (s) {
     400              12 :                         NameSubscription *next = s->next;
     401                 : 
     402                 :                         /* If any overlap, report it */
     403              12 :                         uint low = (s->lower < lower) ? lower : s->lower;
     404              12 :                         uint up = (s->upper > upper) ? upper : s->upper;
     405                 : 
     406                 :                         dbg_msg("nameseq_insert; subsc = %p\n", s);
     407              12 :                         if (low <= up) {     /* Found match */
     408                 :                                 dbg_msg
     409                 :                                     ("nameseq_insert(%u,%u,%u, calling subscriber\n",
     410                 :                                      type, low, up);
     411              12 :                                 namesub_handleEvent(s, low, up, tipc_name_published, port, node);
     412                 :                         }
     413              12 :                         s = next;
     414                 :                 }
     415                 :         }
     416              24 :         return publ;
     417                 : }
     418                 : 
     419                 : uint
     420                 : nameseq_remove(NameSequence * this, uint instance, tipc_net_addr_t node,
     421                 :                uint key)
     422              18 : {
     423              18 :         int i;
     424              18 :         Publication *publ = 0;
     425              18 :         uint result = ~0u;
     426              18 :         uint port;
     427              18 :         SubSequence *sseqs = subseq_get(this->subseqPool, this->subseqIndex);
     428                 : 
     429                 :         dbg_msg("nameseq_remove: got subseqs %p, looking for instance %u\n",
     430                 :                 sseqs, instance);
     431              18 :         nameseq_findSubsequence(this, sseqs, instance, i);
     432               0 :         if ((i < 0) || (i >= (int)this->firstFree))
     433                 :         {
     434               0 :                 warn("TIPC: Failed to withdraw unknown <%u,%u>\n",this->type,instance);
     435               0 :                 return result;
     436                 :         }
     437                 : 
     438                 :         /* Find corresponding publications: */
     439                 : 
     440              18 :         if ((node == tipc_my_addr) && sseqs[i].preferred) {
     441               0 :                 if (sseqs[i].preferred->key == key) {
     442               0 :                         publ = sseqs[i].preferred;
     443               0 :                         sseqs[i].preferred = 0;
     444                 :                 }
     445                 :         }
     446                 : 
     447              18 :         if (!publ) {
     448              18 :                 publ = sseqs[i].loadshared;
     449                 :                 assert(publ);
     450              18 :                 do {
     451              18 :                         if ((key == publ->key)
     452                 :                             && (node == publ->node)) {
     453              18 :                                 if (publ == publ->next) {    /* The only one in list ? */
     454                 :                                         assert(publ == publ->prev);
     455              18 :                                         sseqs[i].loadshared = 0;
     456               0 :                                 } else if (publ == sseqs[i].loadshared) {
     457               0 :                                         sseqs[i].loadshared = publ->next;
     458                 :                                 }
     459               0 :                                 break;
     460                 :                         }
     461               0 :                         publ = publ->next;
     462               0 :                 }
     463                 :                 while (publ != sseqs[i].loadshared);
     464                 :         }
     465                 : 
     466                 :         /* There must be one: */
     467                 :         assert(publ->node == node);
     468                 :         assert(publ->key == key);
     469              18 :         result = publ->scope;
     470              18 :         port = publ->port;
     471              18 :         publ_delete(publ);
     472                 : 
     473                 :         /* Contract subsequence list if necessary: */
     474              18 :         if ((sseqs[i].preferred == 0) && (sseqs[i].loadshared == 0)) {
     475              18 :                 uint lower = sseqs[i].lower;
     476              18 :                 uint upper = sseqs[i].upper;
     477              18 :                 char *from = (char *) &sseqs[i + 1];
     478              18 :                 uint sz = (char *) &sseqs[this->firstFree--] - from;
     479                 : 
     480                 :                 dbg_msg("nameseq_remove() firstFree = %u, moving %u bytes\n",
     481                 :                         this->firstFree, sz);
     482                 :                 assert(sz <= (1u << 31));
     483              18 :                 memmove(&sseqs[i], from, sz);
     484                 : 
     485                 :                 /* Any subscriptions waiting ? */
     486                 :                 {
     487              18 :                         NameSubscription *s = this->subscriptions;
     488                 : 
     489              18 :                         while (s) {
     490                 :                                 /* If any overlap, report it */
     491               0 :                                 uint low =
     492               0 :                                     (s->lower < lower) ? lower : s->lower;
     493               0 :                                 uint up = (s->upper > upper) ? upper : s->upper;
     494                 : 
     495                 :                                 dbg_msg("nameseq_remove; subsc = %p\n", s);
     496               0 :                                 if (low <= up) {
     497                 :                                         dbg_msg
     498                 :                                             ("nameseq_remove; sending signal\n");
     499               0 :                                         namesub_handleEvent(s, low, up,
     500                 :                                                             tipc_name_withdrawn,
     501                 :                                                             port, node);
     502                 :                                 }
     503               0 :                                 s = s->next;
     504                 :                         }
     505                 :                 }
     506                 :         }
     507              18 :         return result;
     508                 : }
     509                 : 
     510                 : void
     511                 : nameseq_subscribe(NameSequence * this, NameSubscription * s)
     512              12 : {
     513              12 :         uint i;
     514              12 :         uint lower = s->lower;
     515              12 :         uint upper = s->upper;
     516              12 :         SubSequence *sseqs = subseq_get(this->subseqPool, this->subseqIndex);
     517                 : 
     518              12 :         s->next = this->subscriptions;
     519              12 :         this->subscriptions = s;
     520                 :         dbg_msg("NameSequencesubscribe; subsc = %p, for <%u,%u,%u>\n",
     521                 :                 s, this->type, lower, upper);
     522              12 :         for (i = 0; i < this->firstFree; i++) {
     523                 :                 /* If any overlap, report it */
     524               0 :                 uint foundLower =
     525               0 :                     (lower < sseqs[i].lower) ? sseqs[i].lower : lower;
     526               0 :                 uint foundUpper =
     527               0 :                     (upper > sseqs[i].upper) ? sseqs[i].upper : upper;
     528               0 :                 if (foundLower <= foundUpper) {
     529               0 :                         SubSequence* ss = &sseqs[i];
     530               0 :                         Publication* p = ss->preferred;
     531               0 :                         if (!p)
     532               0 :                                 p = ss->loadshared;
     533                 :                         assert(p);
     534                 :                         dbg_msg("NameSequencesubscribe: handleEvent(PUBLISHED)");
     535               0 :                         namesub_handleEvent(s, foundLower, foundUpper,
     536                 :                                             tipc_name_published, p->port, p->node);
     537                 :                 }
     538                 :         }
     539                 : }
     540                 : 
     541                 : /* ////////////////////////////////////////////////////////////// 
     542                 : //
     543                 : //  Name Table: Translation table containing all existing
     544                 : //  port name publications. Consists of 'NameSequence' objects
     545                 : //  sorted on 'type'. 
     546                 : //
     547                 : ////////////////////////////////////////////////////////////// */
     548                 : 
     549                 : #define LOCAL_PUBLICATIONLIMIT 10000
     550                 : #define TABLE_SIZE  (1<<14)
     551                 : #define HASH(X)  ((X)&(TABLE_SIZE-1))
     552                 : 
     553                 : typedef struct NameTable {
     554                 :         NameSequence *types[TABLE_SIZE];
     555                 :         uint key;
     556                 :         unsigned long int timerRef;
     557                 :         uint localPublicationCount;
     558                 : } NameTable;
     559                 : 
     560                 : static NameTable table;
     561                 : 
     562                 : #define  nametbl_findNameSequence(TYPE,SEQ) \
     563                 : {\
     564                 :    (SEQ) = table.types[HASH((TYPE))];\
     565                 :    while ((SEQ) && ((SEQ)->type != (TYPE))) {(SEQ) = (SEQ)->next;}\
     566                 : };
     567                 : 
     568                 : Publication *
     569                 : nametbl_insert(uint type,
     570                 :                uint lower,
     571                 :                uint upper,
     572                 :                uint port,
     573                 :                tipc_net_addr_t node, uint scope, uint preferred, uint key)
     574              24 : {
     575              24 :         Publication *publ;
     576              24 :         NameSequence *item;
     577                 : 
     578                 :         assert(lower <= upper);
     579              24 :         nametbl_findNameSequence(type, item);
     580                 :         dbg_msg("Publishing <%u,%u,%u> from %x\n", type, lower, upper, node);
     581              24 :         if (scope != ZONE_SCOPE) {
     582                 :                 dbg_msg("       with scope %u\n", scope);
     583                 :         }
     584              24 :         if (!item) {
     585               4 :                 NameSequence *head = table.types[HASH(type)];
     586                 : 
     587               4 :                 item = table.types[HASH(type)] = nameseq_new(type, head);
     588                 :                 dbg_msg("nametbl_insert: created %p\n", item);
     589                 :         }
     590                 :         assert(item->type == type);
     591              24 :         publ = nameseq_insert(item, type, lower, upper, port, node, scope,
     592                 :                               preferred, key);
     593              24 :         return publ;
     594                 : }
     595                 : 
     596                 : uint
     597                 : nametbl_remove(uint type, uint lower, tipc_net_addr_t node, uint key)
     598              18 : {
     599              18 :         uint result;
     600              18 :         NameSequence *seq;
     601                 : 
     602              18 :         nametbl_findNameSequence(type, seq);
     603               0 :         if (!seq)
     604               0 :                 return ~0u;
     605                 :         dbg_msg("Withdrawing <%u,%u> from %x\n", type, lower, node);
     606              18 :         result = nameseq_remove(seq, lower, node, key);
     607              18 :         if ((result != ~0u) && (seq->firstFree == 0) && (seq->subscriptions == 0)) {
     608               3 :                 if (seq->prev)
     609               0 :                         seq->prev->next = seq->next;
     610                 :                 else
     611               3 :                         table.types[HASH(seq->type)] = seq->next;
     612               3 :                 if (seq->next)
     613               0 :                         seq->next->prev = seq->prev;
     614               3 :                 nameseq_delete(seq);
     615                 :         }
     616              18 :         return result;
     617                 : }
     618                 : 
     619                 : uint
     620                 : nametbl_translate(uint type, uint instance, tipc_net_addr_t * destnode)
     621              80 : {
     622              80 :         NameSequence *seq;
     623              80 :         int i;
     624              80 :         Publication *publ;
     625              80 :         SubSequence *sseqs;
     626                 : 
     627              80 :         nametbl_findNameSequence(type, seq);
     628                 :         dbg_msg("NameSequence::translate: [%d, %d] \n", type, instance);
     629               0 :         if (!seq)
     630               1 :                 return 0;
     631              79 :         sseqs = subseq_get(seq->subseqPool, seq->subseqIndex);
     632              79 :         if (!sseqs)
     633              11 :                 return 0;
     634              68 :         nameseq_findSubsequence(seq, sseqs, instance, i);
     635               1 :         if (i < 0)
     636               1 :                 return 0;
     637                 :         assert(sseqs[i].upper >= instance);
     638                 :         assert(sseqs[i].lower <= instance);
     639                 :         dbg_msg("nameseq_translate: pos %u ok\n", i);
     640              67 :         publ = sseqs[i].preferred;
     641              67 :         if (!publ) {
     642              43 :                 publ = sseqs[i].loadshared;
     643              43 :                 sseqs[i].loadshared = publ->next;
     644                 :         }
     645                 :         assert(publ);
     646              67 :         *destnode = publ->node;
     647              67 :         return publ->port;
     648                 : }
     649                 : 
     650                 : Publication *
     651                 : nametbl_publish(uint type,
     652                 :                 uint lower, uint upper, uint port, uint scope, uint preferred)
     653              19 : {
     654              19 :         Publication *publ;
     655                 : 
     656              19 :         if ((type <= 1) && (++published_reserved > 2)) {
     657                 :                 warn("TIPC: Failed to publish from port %u \n"
     658               0 :                      "type %u is reserved\n", port, type);
     659               0 :                 return 0;
     660                 :         }
     661                 : 
     662              19 :         if (lower > upper) {
     663                 :                 warn("TIPC: Failed to publish <%u,%u,%u> from port %u.\n"
     664                 :                      "Illegal suite: lower > upper\n", type, lower, upper,
     665               0 :                      port);
     666               0 :                 return 0;
     667                 :         }
     668                 : 
     669              19 :         if (table.localPublicationCount >= LOCAL_PUBLICATIONLIMIT) {
     670               0 :                 warn("TIPC: Not possible to publish more port names, \nlimit of " " %u node local publications exceeded\n", LOCAL_PUBLICATIONLIMIT);
     671               0 :                 return 0;
     672                 :         }
     673              19 :         table.localPublicationCount++;
     674              19 :         publ = nametbl_insert(type, lower, upper, port, tipc_my_addr,
     675                 :                               scope, preferred, ++table.key);
     676              19 :         if (publ && (scope != NODE_SCOPE)) {
     677              19 :                 tipc_named_publish(type, lower, upper, port, table.key);
     678                 :         }
     679              19 :         return publ;
     680                 : }
     681                 : 
     682                 : uint
     683                 : nametbl_withdraw(uint type, uint lower, uint key)
     684              17 : {
     685              17 :         uint scope;
     686                 : 
     687                 :         dbg_msg("\nnametbl_withdraw:<%d,%d,%d>\n", type, lower, key);
     688              17 :         scope = nametbl_remove(type, lower, tipc_my_addr, key);
     689              17 :         if (scope == ~0u)
     690               0 :                 return 0;
     691              17 :         table.localPublicationCount--;
     692              17 :         if (scope != NODE_SCOPE) {
     693              17 :                 tipc_named_withdraw(type, lower, key);
     694                 :         }
     695              17 :         return 1;
     696                 : }
     697                 : 
     698                 : void
     699                 : nametbl_subscribe(NameSubscription * s, uint type)
     700              12 : {
     701              12 :         NameSequence *item;
     702                 : 
     703              12 :         nametbl_findNameSequence(type, item);
     704                 :         dbg_msg("nametblsubscribe:found %p for <%u,%u,%u>\n",
     705                 :                 item, type, s->lower, s->upper);
     706               0 :         if (!item) {
     707               1 :                 NameSequence *head = table.types[HASH(type)];
     708                 : 
     709               1 :                 item = table.types[HASH(type)] = nameseq_new(type, head);
     710                 :                 dbg_msg("nametblsubscribe: created %p\n", item);
     711                 :         }
     712                 :         assert(item->type == type);
     713              12 :         nameseq_subscribe(item, s);
     714                 : }
     715                 : 
     716                 : void
     717                 : nametbl_unsubscribe(NameSubscription * s, uint type)
     718              12 : {
     719              12 :         NameSubscription *prev;
     720              12 :         NameSubscription *item;
     721              12 :         NameSequence *seq;
     722                 : 
     723              12 :         nametbl_findNameSequence(type, seq);
     724                 :         dbg_msg("namtbl_unsubscribe:found %p for type %u\n", seq, type);
     725              12 :         if (!seq)
     726              12 :                 return;         /* No NameSequence (can't be valid) */
     727                 :         assert(seq->type == type);
     728              12 :         prev = 0;
     729              12 :         item = seq->subscriptions;
     730              12 :         while ((item != 0) && (item != s)) {
     731              40 :                 prev = item;
     732              40 :                 item = item->next;
     733                 :         }
     734              12 :         if (!item)
     735              12 :                 return;         /* No match found */
     736                 : 
     737              12 :         if (!prev)
     738               2 :                 seq->subscriptions = item->next;
     739                 :         else
     740              10 :                 prev->next = item->next;
     741                 : }
     742                 : 
     743                 : void
     744                 : name_table_init(void)
     745               1 : {
     746               1 :         memset(&table, 0, sizeof (table));
     747               1 :         table.key = tipc_my_addr;
     748                 : }
     749                 : 
     750                 : /* //////////////////////////////////////////////////////////////////
     751                 : //
     752                 : // tipc_sendNamedMessage is called from user when a named message is 
     753                 : // being sent. 
     754                 : //
     755                 : /////////////////////////////////////////////////////////////////// */
     756                 : 
     757                 : uint
     758                 : tipc_sendNamedMsg(TipcSendMsgArgv * argv)
     759               0 : {
     760               0 :         tipc_net_addr_t destnode;
     761               0 :         NameSequence *seq;
     762               0 :         int i;
     763               0 :         Publication *publ;
     764               0 :         uint destport;
     765               0 :         tipc_msg_hdr_t *phdr;
     766               0 :         uint type;
     767               0 :         uint inst;
     768               0 :         uint dest;
     769                 : 
     770                 :         /* Get pre-built header and update */
     771               0 :         Port *oport = port_deref(argv->origport);
     772                 : 
     773               0 :         if (!oport)
     774               0 :                 return tipc_userError(tipc_invalid_args);
     775               0 :         if (port_connected(oport))
     776               0 :                 return tipc_userError(tipc_illegal_operation);
     777               0 :         phdr = port_phdr(oport);
     778               0 :         type = argv->dest.name.type;
     779               0 :         inst = argv->dest.name.instance;
     780               0 :         dest = argv->dest.name.translationNode;
     781               0 :         if (dest < 512)
     782               0 :                 dest = tipc_make_addr(dest, 0, 0);      /* undocumented feature */
     783               0 :         set_name_type(phdr, type);
     784               0 :         set_name_inst(phdr, inst);
     785               0 :         set_hdr_size(phdr, LONG_HDR_SIZE);
     786               0 :         set_msg_type(phdr, TIPC_NAMED_MSG);
     787                 : 
     788                 :         /* Should first lookup be done somewhere else ? */
     789               0 :         if (!tipc_addr_match(dest, tipc_my_addr)) {
     790                 :                 dbg_msg("Sending <%u,%u> for translation on %x\n",
     791                 :                         type, inst, argv->dest.name.translationNode);
     792               0 :                 set_dest_port(phdr, 0);
     793               0 :                 set_dest_node(phdr, dest);
     794               0 :                 return tipc_sendMsg(argv);
     795                 :         }
     796                 :         dbg_msg("Looking up <%u,%u> ", type, inst);
     797                 : 
     798                 :         /* Do the lookup: */
     799               0 :         nametbl_findNameSequence(type, seq);
     800               0 :         if (seq) {
     801               0 :                 SubSequence *sseqs =
     802               0 :                     subseq_get(seq->subseqPool, seq->subseqIndex);
     803               0 :                 nameseq_findSubsequence(seq, sseqs, inst, i);
     804               0 :                 if (i >= 0) {        /* Found */
     805                 :                         assert(sseqs[i].upper >= inst);
     806                 :                         assert(sseqs[i].lower <= inst);
     807               0 :                         publ = sseqs[i].preferred;
     808               0 :                         if (!publ) {
     809               0 :                                 publ = sseqs[i].loadshared;
     810               0 :                                 sseqs[i].loadshared = publ->next;
     811                 :                         }
     812                 :                         assert(publ);
     813               0 :                         destport = publ->port;
     814               0 :                         destnode = publ->node;
     815                 : 
     816                 :                         /* Update header as far as known now */
     817               0 :                         set_dest_node(phdr, destnode);
     818               0 :                         set_dest_port(phdr, destport);
     819                 : 
     820               0 :                         if (destport) {
     821                 :                                 dbg_msg("found [%u,%x] \n", destport, destnode);
     822               0 :                                 if (destnode == tipc_my_addr) {
     823               0 :                                         return port_sendMsg(oport, (TipcSendMsgArgv *) argv);
     824                 :                                 } else {
     825               0 :                                         return
     826                 :                                             tipc_sendMsg((TipcSendMsgArgv *) argv);
     827                 :                                 }
     828                 :                         }
     829                 :                 }
     830                 :         }
     831                 :         dbg_msg("failed... \n");
     832               0 :         return port_rejectReq(argv, phdr, tipc_no_portname);
     833                 : }
     834                 : 
     835                 : /* //////////////////////////////////////////////////////////////////
     836                 : //
     837                 : // tipc_multicastNamedMessage is called from user when a named message is 
     838                 : // being sent. 
     839                 : //
     840                 : /////////////////////////////////////////////////////////////////// */
     841                 : 
     842                 : uint
     843                 : tipc_multicastNamedMsg(TipcSendMsgArgv * argv)
     844               0 : {
     845               0 :         return 0;
     846                 : }
     847                 : 
     848                 : uint
     849                 : tipc_nameAvailable(const TipcNameAvailabilityArgv * argv)
     850              17 : {
     851              17 :         tipc_net_addr_t addr;
     852              17 :         uint res = nametbl_translate(argv->type, argv->instance, &addr);
     853                 : 
     854                 :         dbg_msg(" tipc_nameAvailable <%u,%u> returns %s\n",
     855                 :                 argv->type, argv->instance, res ? "1" : "0");
     856              17 :         return res;
     857                 : }
     858                 : 
     859                 : uint
     860                 : nametbl_nameSeqAvailable(uint type, uint lower, uint upper)
     861               0 : {
     862               0 :         NameSequence *seq;
     863               0 :         uint i;
     864               0 :         SubSequence *sseqs;
     865                 : 
     866               0 :         nametbl_findNameSequence(type, seq);
     867               0 :         if (!seq)
     868               0 :                 return 0;
     869               0 :         sseqs = subseq_get(seq->subseqPool, seq->subseqIndex);
     870               0 :         if (!sseqs)
     871               0 :                 return 0;
     872               0 :         for (i = 0; i < seq->firstFree; i++) {
     873               0 :                 if ((sseqs[i].lower >= lower) && (sseqs[i].lower <= upper))
     874               0 :                         return 1;
     875               0 :                 if ((sseqs[i].upper >= lower) && (sseqs[i].upper <= upper))
     876               0 :                         return 1;
     877                 :         }
     878               0 :         return 0;
     879                 : }
     880                 : 
     881                 : #ifdef CONFIG_TIPC_DBG_BUF
     882                 : void
     883                 : nametbl_list(tipc_dbg_buf_t * buf, uint type, uint depth)
     884                 : {
     885                 :         NameSequence *seq = 0;
     886                 :         Publication *publ = 0;
     887                 :         uint i;
     888                 : 
     889                 :         for (i = 0; i < TABLE_SIZE; i++) {
     890                 :                 if (table.types[i] != 0) {
     891                 :                         seq = table.types[i];
     892                 :                         while (seq) {
     893                 :                                 uint j;
     894                 :                                 SubSequence *sseqs = subseq_get(seq->subseqPool,
     895                 :                                                                 seq->
     896                 :                                                                 subseqIndex);
     897                 :                                 if (!type || (type == seq->type)) {
     898                 :                                         debug_output(buf, "Index %u:\n", i);
     899                 :                                         debug_output(buf, "   Type: %u\n",
     900                 :                                                      seq->type);
     901                 :                                         if (depth <= 1) {    /* Print subsequences */
     902                 :                                                 for (j = 0; j < seq->firstFree;
     903                 :                                                      j++) {
     904                 :                                                         debug_output(buf,
     905                 :                                                                      "   Sub-sequence[%u]:[%u,%u]\n",
     906                 :                                                                      j,
     907                 :                                                                      sseqs[j].
     908                 :                                                                      lower,
     909                 :                                                                      sseqs[j].
     910                 :                                                                      upper);
     911                 :                                                         if (depth == 0) {       /* Print all */
     912                 :                                                                 if (sseqs[j].
     913                 :                                                                     preferred !=
     914                 :                                                                     0) {
     915                 :                                                                         debug_output
     916                 :                                                                             (buf,
     917                 :                                                                              "      Local port: %u key = %u\n",
     918                 :                                                                              sseqs
     919                 :                                                                              [j].
     920                 :                                                                              preferred->
     921                 :                                                                              port,
     922                 :                                                                              sseqs
     923                 :                                                                              [j].
     924                 :                                                                              preferred->
     925                 :                                                                              key);
     926                 :                                                                 }
     927                 : 
     928                 :                                                                 if (sseqs[j].
     929                 :                                                                     loadshared
     930                 :                                                                     != 0) {
     931                 :                                                                         publ =
     932                 :                                                                             sseqs
     933                 :                                                                             [j].
     934                 :                                                                             loadshared;
     935                 :                                                                         do {
     936                 :                                                                                 debug_output
     937                 :                                                                                     (buf,
     938                 :                                                                                      "      Remote port: [%u,%x],key: %u\n",
     939                 :                                                                                      publ->
     940                 :                                                                                      port,
     941                 :                                                                                      publ->
     942                 :                                                                                      node,
     943                 :                                                                                      publ->
     944                 :                                                                                      key);
     945                 :                                                                                 publ = publ->next;
     946                 :                                                                         }
     947                 :                                                                         while
     948                 :                                                                             (publ
     949                 :                                                                              !=
     950                 :                                                                              sseqs
     951                 :                                                                              [j].
     952                 :                                                                              loadshared);
     953                 :                                                                 }
     954                 :                                                         }
     955                 :                                                 }
     956                 :                                         }
     957                 :                                 }
     958                 :                                 seq = seq->next;
     959                 :                         }
     960                 :                         debug_output(buf, "\n");
     961                 :                 }
     962                 :         }
     963                 : }
     964                 : 
     965                 : void
     966                 : nametbl_print(tipc_dbg_buf_t * buf, const char *str)
     967                 : {
     968                 :         debug_output(buf, str);
     969                 :         nametbl_list(buf, 0, 0);
     970                 : }
     971                 : 
     972                 : const char *
     973                 : tipc_getNameTable(const tipc_get_name_table_argv * argv)
     974                 : {
     975                 :         tipc_dbg_buf_t db;
     976                 : 
     977                 :         dbg_buf_init(&db, 0, 0, 65408);
     978                 :         nametbl_list(&db, argv->type, argv->depth);
     979                 :         mem_delayed_free(db.buffer, 100);
     980                 :         return db.buffer;
     981                 : }
     982                 : 
     983                 : void
     984                 : nametbl_dump(void)
     985                 : {
     986                 :         nametbl_list(C,0,0);
     987                 : }
     988                 : #endif

Generated by: LTP GCOV extension version 1.1