GlusterFS/코드 분석/기본 자료 구조/사전

From PGWiki

dict_t

libglusterfs/src/dict.h:struct _dict
80 struct _dict {
81         unsigned char   is_static:1;
82         int32_t         hash_size;
83         int32_t         count;
84         int32_t         refcount;
85         data_pair_t   **members;
86         data_pair_t    *members_list;
87         char           *extra_free;
88         char           *extra_stdfree;
89         gf_lock_t       lock;
90         data_pair_t    *members_internal;
91         data_pair_t     free_pair;
92         gf_boolean_t    free_pair_in_use;
93 };
  • is_static
  • hash_size
  • count
  • refcount
  • members
  • members_list
  • extra_free
  • extra_stdfree
  • lock
  • members_internal
  • free_pair
  • free_pair_in_use

data_t

libglusterfs/src/dict.h:struct _data
63 struct _data {
64         unsigned char  is_static:1;
65         unsigned char  is_const:1;
66         int32_t        len;
67         char          *data;
68         int32_t        refcount;
69         gf_lock_t      lock;
70 };
  • is_static
  • is_const
  • len
  • data
  • refcount
  • lock

data_pair_t

libglusterfs/src/dict.h:struct _data_pair
72 struct _data_pair {
73         struct _data_pair *hash_next;
74         struct _data_pair *prev;
75         struct _data_pair *next;
76         data_t            *value;
77         char              *key;
78 };
  • hash_next
  • prev
  • next
  • value
  • key

get_new_dict()

libglusterfs/src/dict.c:get_new_dict()
93 dict_t *
94 get_new_dict (void)
95 {
96         return get_new_dict_full (1);
97 }
  • 96
    매개 변수를 1로 하는 get_new_dict_full() 함수를 호출하여 해시 크기가 1인 사전을 생성한 후에 반환한다.

dict_new()

libglusterfs/src/dict.c:dict_new()
 99 dict_t *
100 dict_new (void)
101 {
102         dict_t *dict = NULL;
103 
104         dict = get_new_dict_full(1);
105 
106         if (dict)
107                 dict_ref (dict);
108 
109         return dict;
110 }
  • 102
    사전 자료형(dict_t)의 dict 변수를 NULL로 선언한다.
  • 104
    매개 변수를 1로 하는 get_new_dict_full() 함수를 호출하여 새로운 사전을 생성한다.
    이 매개 변수는 사전의 해시 크기를 뜻하며, 따라서 해시 크기가 1인 사전을 생성하게 된다.
  • 106-107
    사전이 정상적으로 생성되었다면 dict_ref() 함수를 호출하여 이 사전의 참조 계수를 증가 시킨다.
  • 109
    생성된 사전(dict)를 반환한다.

get_new_data()

libglusterfs/src/dict.c:get_new_data()
36 data_t *
37 get_new_data ()
38 {
39         data_t *data = NULL;
40 
41         data = mem_get0 (THIS->ctx->dict_data_pool);
42         if (!data) {
43                 return NULL;
44         }
45 
46         LOCK_INIT (&data->lock);
47         return data;
48 }
  • 39
    사전 데이터 자료형([#data_t|data_t])의 data 변수를 NULL로 선언한다.
  • 41-44
    mem_get0() 함수를 호출하여 컨텍스트의 사전 데이터 메모리 풀(THIS->ctx->dict_data_pool)로부터 메모리를 가져온다.
    만일 메모리 풀로부터 메모리를 가져오지 못했다면 바로 NULL을 반환한다.
  • 46
    가져온 데이터의 잠금(data->lock)을 잠금 처리한다.
  • 47
    가져온 데이터(data)를 반환한다.

get_new_dict_full()

libglusterfs/src/dict.c:get_new_dict_full()
50 dict_t *
51 get_new_dict_full (int size_hint)
52 {
53         dict_t *dict = mem_get0 (THIS->ctx->dict_pool);
54 
55         if (!dict) {
56                 return NULL;
57         }
58 
59         dict->hash_size = size_hint;
60         if (size_hint == 1) {
61                 /*
62                  * This is the only case we ever see currently.  If we ever
63                  * need to support resizing the hash table, the resize function
64                  * will have to take into account the possibility that
65                  * "members" is not separately allocated (i.e. don't just call
66                  * realloc() blindly.
67                  */
68                 dict->members = &dict->members_internal;
69         }
70         else {
71                 /*
72                  * We actually need to allocate space for size_hint *pointers*
73                  * but we actually allocate space for one *structure*.  Since
74                  * a data_pair_t consists of five pointers, we're wasting four
75                  * pointers' worth for N=1, and will overrun what we allocated
76                  * for N>5.  If anybody ever starts using size_hint, we'll need
77                  * to fix this.
78                  */
79                 GF_ASSERT (size_hint <=
80                            (sizeof(data_pair_t) / sizeof(data_pair_t *)));
81                 dict->members = mem_get0 (THIS->ctx->dict_pair_pool);
82                 if (!dict->members) {
83                         mem_put (dict);
84                         return NULL;
85                 }
86         }
87 
88         LOCK_INIT (&dict->lock);
89 
90         return dict;
91 }
  • 53-57
    mem_get0() 함수를 호출하여 컨텍스트의 사전 메모리 풀(THIS->ctx->dict_pool)로부터 새로운 사전을 위한 메모리를 가져온다.
    가져오지 못했다면 NULL을 반환한다.
  • 59
    사전의 해시 크기(dict->hash_size)를 매개 변수로 넘겨 받은 size_hint로 설정한다.
  • 60-69
    size_hint1이라면 사전의 멤버 정보(dict->members)가 사전의 내부 멤버의 주소(&dict->members_internal)를 가리키도록 한다.
    주석에 따르면, 해시 테이블 크기의 조정을 지원해야 하는 경우 resize 함수에서 "멤버"가 별도로 할당되지 않을 가능성을 고려해야 한다고 한다. 따라서 맹목적으로 realloc()을 호출하는 것을 자제해야 한다고 한다.
  • 70-86
    그렇지 않다면 다음과 같은 조건 분기를 수행한다.
  • 79-80
    GF_ASSERT() 매크로 코드 블록을 호출하여 데이터쌍 자료 구조(data_pair_t)의 크기를 그 포인터의 크기로 나눈 값이 size_hint보다 크지 않다면 예외를 발생시킨다.
  • 81-85
    mem_get0()을 호출하여 컨텍스트의 사전 데이터쌍 메모리 풀(THIS->ctx->dict_pair_pool)로부터 새로운 사전의 데이터쌍을 위한 메모리를 가져와서 멤버 정보(dict->members)에 기록한다.
    이 메모리 풀로부터 데이터를 가져오지 못해서 사전의 멤버 정보(dict->members)가 NULL이라면 mem_put()를 호출하여 사전을 위해서 메모리 풀로부터 가져온 메모리를 반환하고 NULL을 반환한다.
  • 88
    사전의 잠금(dict->lock)을 잠금 처리한다.
  • 90
    새로 만들어진 사전을 반환한다.

dict_set_static_ptr()

libglusterfs/src/dict.c:dict_set_static_ptr()
2029 int
2030 dict_set_static_ptr (dict_t *this, char *key, void *ptr)
2031 {
2032         data_t * data = NULL;
2033         int      ret  = 0;
2034 
2035         data = data_from_ptr_common (ptr, _gf_true);
2036         if (!data) {
2037                 ret = -EINVAL;
2038                 goto err;
2039         }
2040 
2041         ret = dict_set (this, key, data);
2042         if (ret < 0)
2043                 data_destroy (data);
2044 
2045 err:
2046         return ret;
2047 }

ᅟdata_from_ptr_common()

libglusterfs/src/dict.c:data_from_ptr_common()
855 static data_t *
856 data_from_ptr_common (void *value, gf_boolean_t is_static)
857 {
858         /* it is valid to set 0/NULL as a value, no need to check *value */
859 
860         data_t *data = get_new_data ();
861         if (!data) {
862                 return NULL;
863         }
864 
865         data->data = value;
866         data->is_static = is_static;
867 
868         return data;
869 }

get_new_data()

libglusterfs/src/dict.c:get_new_data()
36 data_t *
37 get_new_data ()
38 {
39         data_t *data = NULL;
40 
41         data = mem_get0 (THIS->ctx->dict_data_pool);
42         if (!data) {
43                 return NULL;
44         }
45 
46         LOCK_INIT (&data->lock);
47         return data;
48 }

각주