gf_timer_t * gf_timer_call_after (glusterfs_ctx_t *ctx, struct timeval delta, gf_timer_cbk_t callbk, void *data) { gf_timer_registry_t *reg = NULL; gf_timer_t *event = NULL; gf_timer_t *trav = NULL; unsigned long long at = 0L; if (ctx == NULL) { gf_log_callingfn ("timer", GF_LOG_ERROR, "invalid argument"); return NULL; } reg = gf_timer_registry_init (ctx); if (!reg) { gf_log_callingfn ("timer", GF_LOG_ERROR, "!reg"); return NULL; } event = GF_CALLOC (1, sizeof (*event), gf_common_mt_gf_timer_t); if (!event) { return NULL; } gettimeofday (&event->at, NULL); event->at.tv_usec = ((event->at.tv_usec + delta.tv_usec) % 1000000); event->at.tv_sec += ((event->at.tv_usec + delta.tv_usec) / 1000000); event->at.tv_sec += delta.tv_sec; at = TS (event->at); event->callbk = callbk; event->data = data; event->xl = THIS; pthread_mutex_lock (®->lock); { trav = reg->active.prev; while (trav != ®->active) { if (TS (trav->at) < at) break; trav = trav->prev; } event->prev = trav; event->next = event->prev->next; event->prev->next = event; event->next->prev = event; } pthread_mutex_unlock (®->lock); return event; }
// 插入一个事件到定时器链表中 gf_timer_t * gf_timer_call_after (glusterfs_ctx_t *ctx, struct timespec delta, gf_timer_cbk_t callbk, void *data) { gf_timer_registry_t *reg = NULL; gf_timer_t *event = NULL; gf_timer_t *trav = NULL; uint64_t at = 0; if (ctx == NULL) { gf_log_callingfn ("timer", GF_LOG_ERROR, "invalid argument"); return NULL; } reg = gf_timer_registry_init (ctx); if (!reg) { gf_log_callingfn ("timer", GF_LOG_ERROR, "!reg"); return NULL; } event = GF_CALLOC (1, sizeof (*event), gf_common_mt_gf_timer_t); if (!event) { return NULL; } timespec_now (&event->at); timespec_adjust_delta (&event->at, delta); at = TS (event->at); event->callbk = callbk; event->data = data; event->xl = THIS; pthread_mutex_lock (®->lock); { //列表最后一个 trav = reg->active.prev; //找最后一个时间比我早的(链表是按时间排序的) while (trav != ®->active) { if (TS (trav->at) < at) break; trav = trav->prev; } event->prev = trav; event->next = event->prev->next; event->prev->next = event; event->next->prev = event; } pthread_mutex_unlock (®->lock); return event; }
struct iobuf * quotad_serialize_reply (rpcsvc_request_t *req, void *arg, struct iovec *outmsg, xdrproc_t xdrproc) { struct iobuf *iob = NULL; ssize_t retlen = 0; ssize_t xdr_size = 0; GF_VALIDATE_OR_GOTO ("server", req, ret); /* First, get the io buffer into which the reply in arg will * be serialized. */ if (arg && xdrproc) { xdr_size = xdr_sizeof (xdrproc, arg); iob = iobuf_get2 (req->svc->ctx->iobuf_pool, xdr_size); if (!iob) { gf_log_callingfn (THIS->name, GF_LOG_ERROR, "Failed to get iobuf"); goto ret; }; iobuf_to_iovec (iob, outmsg); /* Use the given serializer to translate the give C structure in arg * to XDR format which will be written into the buffer in outmsg. */ /* retlen is used to received the error since size_t is unsigned and we * need -1 for error notification during encoding. */ retlen = xdr_serialize_generic (*outmsg, arg, xdrproc); if (retlen == -1) { /* Failed to Encode 'GlusterFS' msg in RPC is not exactly failure of RPC return values.. client should get notified about this, so there are no missing frames */ gf_log_callingfn ("", GF_LOG_ERROR, "Failed to encode message"); req->rpc_err = GARBAGE_ARGS; retlen = 0; } } outmsg->iov_len = retlen; ret: if (retlen == -1) { iobuf_unref (iob); iob = NULL; } return iob; }
void gf_client_clienttable_destroy (clienttable_t *clienttable) { client_t *client = NULL; cliententry_t *cliententries = NULL; uint32_t client_count = 0; int32_t i = 0; if (!clienttable) { gf_log_callingfn ("client_t", GF_LOG_WARNING, "!clienttable"); return; } LOCK (&clienttable->lock); { client_count = clienttable->max_clients; clienttable->max_clients = 0; cliententries = clienttable->cliententries; clienttable->cliententries = NULL; } UNLOCK (&clienttable->lock); if (cliententries != NULL) { for (i = 0; i < client_count; i++) { client = cliententries[i].client; if (client != NULL) { gf_client_unref (client); } } GF_FREE (cliententries); LOCK_DESTROY (&clienttable->lock); GF_FREE (clienttable); } }
void runner_log (runner_t *runner, const char *dom, gf_loglevel_t lvl, const char *msg) { char *buf = NULL; size_t len = 0; int i = 0; if (runner->runerr) return; for (i = 0;; i++) { if (runner->argv[i] == NULL) break; len += (strlen (runner->argv[i]) + 1); } buf = GF_CALLOC (1, len + 1, gf_common_mt_run_logbuf); if (!buf) { runner->runerr = errno; return; } for (i = 0;; i++) { if (runner->argv[i] == NULL) break; strcat (buf, runner->argv[i]); strcat (buf, " "); } if (len > 0) buf[len - 1] = '\0'; gf_log_callingfn (dom, lvl, "%s: %s", msg, buf); GF_FREE (buf); }
gf_timer_registry_t * gf_timer_registry_init (glusterfs_ctx_t *ctx) { if (ctx == NULL) { gf_log_callingfn ("timer", GF_LOG_ERROR, "invalid argument"); return NULL; } if (!ctx->timer) { gf_timer_registry_t *reg = NULL; reg = GF_CALLOC (1, sizeof (*reg), gf_common_mt_gf_timer_registry_t); if (!reg) goto out; pthread_mutex_init (®->lock, NULL); reg->active.next = ®->active; reg->active.prev = ®->active; reg->stale.next = ®->stale; reg->stale.prev = ®->stale; ctx->timer = reg; pthread_create (®->th, NULL, gf_timer_proc, ctx); } out: return ctx->timer; }
int32_t gf_timer_call_cancel (glusterfs_ctx_t *ctx, gf_timer_t *event) { gf_timer_registry_t *reg = NULL; if (ctx == NULL || event == NULL) { gf_log_callingfn ("timer", GF_LOG_ERROR, "invalid argument"); return 0; } reg = gf_timer_registry_init (ctx); if (!reg) { gf_log ("timer", GF_LOG_ERROR, "!reg"); GF_FREE (event); return 0; } pthread_mutex_lock (®->lock); { event->next->prev = event->prev; event->prev->next = event->next; } pthread_mutex_unlock (®->lock); GF_FREE (event); return 0; }
static int _gf_string2longlong (const char *str, long long *n, int base) { long long value = 0; char *tail = NULL; int old_errno = 0; if (str == NULL || n == NULL) { gf_log_callingfn (THIS->name, GF_LOG_WARNING, "argument invalid"); errno = EINVAL; return -1; } old_errno = errno; errno = 0; value = strtoll (str, &tail, base); if (errno == ERANGE || errno == EINVAL) return -1; if (errno == 0) errno = old_errno; if (tail[0] != '\0') return -1; *n = value; return 0; }
static int _gf_string2double (const char *str, double *n) { double value = 0.0; char *tail = NULL; int old_errno = 0; if (str == NULL || n == NULL) { gf_log_callingfn (THIS->name, GF_LOG_WARNING, "argument invalid"); errno = EINVAL; return -1; } old_errno = errno; errno = 0; value = strtod (str, &tail); if (errno == ERANGE || errno == EINVAL) return -1; if (errno == 0) errno = old_errno; if (tail[0] != '\0') return -1; *n = value; return 0; }
int gf_string2boolean (const char *str, gf_boolean_t *b) { if (str == NULL) { gf_log_callingfn (THIS->name, GF_LOG_WARNING, "argument invalid"); return -1; } if ((strcasecmp (str, "1") == 0) || (strcasecmp (str, "on") == 0) || (strcasecmp (str, "yes") == 0) || (strcasecmp (str, "true") == 0) || (strcasecmp (str, "enable") == 0)) { *b = _gf_true; return 0; } if ((strcasecmp (str, "0") == 0) || (strcasecmp (str, "off") == 0) || (strcasecmp (str, "no") == 0) || (strcasecmp (str, "false") == 0) || (strcasecmp (str, "disable") == 0)) { *b = _gf_false; return 0; } return -1; }
int32_t quota_conf_read_gfid (int fd, void *buf, char *type, float version) { int ret = 0; ret = gf_nread (fd, buf, 16); if (ret <= 0) goto out; if (ret != 16) { ret = -1; goto out; } if (version >= 1.2f) { ret = gf_nread (fd, type, 1); if (ret != 1) { ret = -1; goto out; } ret = 17; } else { *type = GF_QUOTA_CONF_TYPE_USAGE; } out: if (ret < 0) gf_log_callingfn ("quota", GF_LOG_ERROR, "failed to read " "gfid from a quota conf"); return ret; }
int32_t quota_conf_write_gfid (int fd, void *buf, char type) { int ret = 0; ret = gf_nwrite (fd, buf, 16); if (ret != 16) { ret = -1; goto out; } ret = gf_nwrite (fd, &type, 1); if (ret != 1) { ret = -1; goto out; } ret = 0; out: if (ret < 0) gf_log_callingfn ("quota", GF_LOG_ERROR, "failed to write " "gfid %s to a quota conf", uuid_utoa (buf)); return ret; }
int32_t quota_conf_read_header (int fd, char *buf) { int header_len = 0; int ret = 0; header_len = strlen (QUOTA_CONF_HEADER); ret = gf_nread (fd, buf, header_len); if (ret <= 0) { goto out; } else if (ret > 0 && ret != header_len) { ret = -1; goto out; } buf[header_len-1] = 0; out: if (ret < 0) gf_log_callingfn ("quota", GF_LOG_ERROR, "failed to read " "header from a quota conf"); return ret; }
void mem_put (struct mem_pool *pool, void *ptr) { struct list_head *list = NULL; int *in_use = NULL; void *head = NULL; if (!pool || !ptr) { gf_log ("mem-pool", GF_LOG_ERROR, "invalid argument"); return; } LOCK (&pool->lock); { switch (__is_member (pool, ptr)) { case 1: list = head = mem_pool_ptr2chunkhead (ptr); in_use = (head + GF_MEM_POOL_LIST_BOUNDARY); if (!is_mem_chunk_in_use(in_use)) { gf_log_callingfn ("mem-pool", GF_LOG_CRITICAL, "mem_put called on freed ptr %p of mem " "pool %p", ptr, pool); break; } pool->hot_count--; pool->cold_count++; *in_use = 0; list_add (list, &pool->list); break; case -1: /* For some reason, the address given is within * the address range of the mem-pool but does not align * with the expected start of a chunk that includes * the list headers also. Sounds like a problem in * layers of clouds up above us. ;) */ abort (); break; case 0: /* The address is outside the range of the mem-pool. We * assume here that this address was allocated at a * point when the mem-pool was out of chunks in mem_get * or the programmer has made a mistake by calling the * wrong de-allocation interface. We do * not have enough info to distinguish between the two * situations. */ FREE (ptr); break; default: /* log error */ break; } } UNLOCK (&pool->lock); }
int gf_string2percent_or_bytesize (const char *str, uint64_t *n, gf_boolean_t *is_percent) { uint64_t value = 0ULL; char *tail = NULL; int old_errno = 0; const char *s = NULL; if (str == NULL || n == NULL) { gf_log_callingfn (THIS->name, GF_LOG_WARNING, "argument invalid"); errno = EINVAL; return -1; } for (s = str; *s != '\0'; s++) { if (isspace (*s)) continue; if (*s == '-') return -1; break; } old_errno = errno; errno = 0; value = strtoull (str, &tail, 10); if (errno == ERANGE || errno == EINVAL) return -1; if (errno == 0) errno = old_errno; if (tail[0] != '\0') { if (strcasecmp (tail, GF_UNIT_KB_STRING) == 0) value *= GF_UNIT_KB; else if (strcasecmp (tail, GF_UNIT_MB_STRING) == 0) value *= GF_UNIT_MB; else if (strcasecmp (tail, GF_UNIT_GB_STRING) == 0) value *= GF_UNIT_GB; else if (strcasecmp (tail, GF_UNIT_TB_STRING) == 0) value *= GF_UNIT_TB; else if (strcasecmp (tail, GF_UNIT_PB_STRING) == 0) value *= GF_UNIT_PB; else if (strcasecmp (tail, GF_UNIT_PERCENT_STRING) == 0) *is_percent = _gf_true; else return -1; } *n = value; return 0; }
int32_t quota_dict_set_meta (dict_t *dict, char *key, const quota_meta_t *meta, ia_type_t ia_type) { int32_t ret = -1; quota_meta_t *value = NULL; value = GF_CALLOC (1, sizeof (quota_meta_t), gf_common_quota_meta_t); if (value == NULL) { gf_log_callingfn ("quota", GF_LOG_ERROR, "Memory allocation failed"); goto out; } value->size = hton64 (meta->size); value->file_count = hton64 (meta->file_count); value->dir_count = hton64 (meta->dir_count); if (ia_type == IA_IFDIR) { ret = dict_set_bin (dict, key, value, sizeof (*value)); } else { /* For a file we don't need to store dir_count in the * quota size xattr, so we set the len of the data in the dict * as 128bits, so when the posix xattrop reads the dict, it only * performs operations on size and file_count */ ret = dict_set_bin (dict, key, value, sizeof (*value) - sizeof (int64_t)); } if (ret < 0) { gf_log_callingfn ("quota", GF_LOG_ERROR, "dict set failed"); GF_FREE (value); } out: return ret; }
int32_t quota_conf_read_version (int fd, float *version) { int ret = 0; char buf[PATH_MAX] = ""; char *tail = NULL; float value = 0.0f; ret = quota_conf_read_header (fd, buf); if (ret == 0) { /* quota.conf is empty */ value = GF_QUOTA_CONF_VERSION; goto out; } else if (ret < 0) { goto out; } value = strtof ((buf + strlen(buf) - 3), &tail); if (tail[0] != '\0') { ret = -1; gf_log_callingfn ("quota", GF_LOG_ERROR, "invalid quota conf " "version"); goto out; } ret = 0; out: if (ret >= 0) *version = value; else gf_log_callingfn ("quota", GF_LOG_ERROR, "failed to read " "version from a quota conf header"); return ret; }
/* hold lock while calling this function */ int __cb_add_entry_buffer (buffer_t *buffer, void *item) { circular_buffer_t *ptr = NULL; int ret = -1; //DO we really need the assert here? GF_ASSERT (buffer->used_len <= buffer->size_buffer); if (buffer->use_once == _gf_true && buffer->used_len == buffer->size_buffer) { gf_log ("", GF_LOG_WARNING, "buffer %p is use once buffer", buffer); return -1; } else { if (buffer->used_len == buffer->size_buffer) { if (buffer->cb[buffer->w_index]) { ptr = buffer->cb[buffer->w_index]; if (ptr->data) { GF_FREE (ptr->data); ptr->data = NULL; GF_FREE (ptr); } buffer->cb[buffer->w_index] = NULL; ptr = NULL; } } buffer->cb[buffer->w_index] = GF_CALLOC (1, sizeof (circular_buffer_t), gf_common_mt_circular_buffer_t); if (!buffer->cb[buffer->w_index]) return -1; buffer->cb[buffer->w_index]->data = item; ret = gettimeofday (&buffer->cb[buffer->w_index]->tv, NULL); if (ret == -1) gf_log_callingfn ("", GF_LOG_WARNING, "getting time of" "the day failed"); buffer->w_index++; buffer->w_index %= buffer->size_buffer - 1; //used_buffer size cannot be greater than the total buffer size if (buffer->used_len < buffer->size_buffer) buffer->used_len++; return buffer->w_index; } }
/*当我们使用完一个内存池中的内存结构以后就需要还给内存池以便被以后的程序使用, 达到循环使用的目的。但是在归还以前我们首先需要判断是不是内存池对象的一个成员, 判断的结果有三种,分别是:是,不是和错误情况(就是它在内存池的内存范围以内, 但是不符合内存池对象的大小),实现如下*/ static int __is_member (struct mem_pool *pool, void *ptr) //判断ptr指向的内存是否是pool的成员 { if (!pool || !ptr) { gf_log_callingfn ("mem-pool", GF_LOG_ERROR, "invalid argument"); return -1; } if (ptr < pool->pool || ptr >= pool->pool_end) //ptr如果不再pool开始到结束的范围内就不是 return 0; if ((mem_pool_ptr2chunkhead (ptr) - pool->pool) % pool->padded_sizeof_type)//判断是否是一个符合内存块大小的内存对象 return -1; return 1; }
static int __is_member (struct mem_pool *pool, void *ptr) { if (!pool || !ptr) { gf_log_callingfn ("mem-pool", GF_LOG_ERROR, "invalid argument"); return -1; } if (ptr < pool->pool || ptr >= pool->pool_end) return 0; if ((mem_pool_ptr2chunkhead (ptr) - pool->pool) % pool->padded_sizeof_type) return -1; return 1; }
void* mem_get0 (struct mem_pool *mem_pool) { void *ptr = NULL; if (!mem_pool) { gf_log_callingfn ("mem-pool", GF_LOG_ERROR, "invalid argument"); return NULL; } ptr = mem_get(mem_pool); if (ptr) memset(ptr, 0, mem_pool->real_sizeof_type); return ptr; }
static int gf_client_clienttable_expand (clienttable_t *clienttable, uint32_t nr) { cliententry_t *oldclients = NULL; uint32_t oldmax_clients = -1; int ret = -1; if (clienttable == NULL || nr <= clienttable->max_clients) { gf_log_callingfn ("client_t", GF_LOG_ERROR, "invalid argument"); ret = EINVAL; goto out; } oldclients = clienttable->cliententries; oldmax_clients = clienttable->max_clients; clienttable->cliententries = GF_CALLOC (nr, sizeof (cliententry_t), gf_common_mt_cliententry_t); if (!clienttable->cliententries) { clienttable->cliententries = oldclients; ret = 0; goto out; } clienttable->max_clients = nr; if (oldclients) { uint32_t cpy = oldmax_clients * sizeof (cliententry_t); memcpy (clienttable->cliententries, oldclients, cpy); } gf_client_chain_client_entries (clienttable->cliententries, oldmax_clients, clienttable->max_clients); /* Now that expansion is done, we must update the client list * head pointer so that the client allocation functions can continue * using the expanded table. */ clienttable->first_free = oldmax_clients; GF_FREE (oldclients); ret = 0; out: return ret; }
int32_t gf_timer_call_stale (gf_timer_registry_t *reg, gf_timer_t *event) { if (reg == NULL || event == NULL) { gf_log_callingfn ("timer", GF_LOG_ERROR, "invalid argument"); return 0; } event->next->prev = event->prev; event->prev->next = event->next; event->next = ®->stale; event->prev = event->next->prev; event->next->prev = event; event->prev->next = event; return 0; }
int32_t quota_dict_get_meta (dict_t *dict, char *key, quota_meta_t *meta) { int32_t ret = -1; data_t *data = NULL; quota_meta_t *value = NULL; int64_t *size = NULL; if (!dict || !key || !meta) goto out; data = dict_get (dict, key); if (!data || !data->data) goto out; if (data->len > sizeof (int64_t)) { value = (quota_meta_t *) data->data; meta->size = ntoh64 (value->size); meta->file_count = ntoh64 (value->file_count); if (data->len > (sizeof (int64_t)) * 2) meta->dir_count = ntoh64 (value->dir_count); else meta->dir_count = 0; } else { size = (int64_t *) data->data; meta->size = ntoh64 (*size); meta->file_count = 0; meta->dir_count = 0; /* This can happen during software upgrade. * Older version of glusterfs will not have inode count. * Return failure, this will be healed as part of lookup */ gf_log_callingfn ("quota", GF_LOG_DEBUG, "Object quota xattrs " "missing: len = %d", data->len); ret = -2; goto out; } ret = 0; out: return ret; }
int gf_string2time (const char *str, uint32_t *n) { unsigned long value = 0; char *tail = NULL; int old_errno = 0; const char *s = NULL; if (str == NULL || n == NULL) { gf_log_callingfn (THIS->name, GF_LOG_WARNING, "argument invalid"); errno = EINVAL; return -1; } for (s = str; *s != '\0'; s++) { if (isspace (*s)) continue; if (*s == '-') return -1; break; } old_errno = errno; errno = 0; value = strtol (str, &tail, 0); if (errno == ERANGE || errno == EINVAL) return -1; if (errno == 0) errno = old_errno; if (!((tail[0] == '\0') || ((tail[0] == 's') && (tail[1] == '\0')) || ((tail[0] == 's') && (tail[1] == 'e') && (tail[2] == 'c') && (tail[3] == '\0')))) return -1; *n = value; return 0; }
int gf_volume_name_validate (const char *volume_name) { const char *vname = NULL; if (volume_name == NULL) { gf_log_callingfn (THIS->name, GF_LOG_WARNING, "argument invalid"); return -1; } if (!isalpha (volume_name[0])) return 1; for (vname = &volume_name[1]; *vname != '\0'; vname++) { if (!(isalnum (*vname) || *vname == '_')) return 1; } return 0; }
int glusterfs_ctx_init () { int ret = 0; if (glusterfs_ctx) { gf_log_callingfn ("", GF_LOG_WARNING, "init called again"); goto out; } glusterfs_ctx = CALLOC (1, sizeof (*glusterfs_ctx)); if (!glusterfs_ctx) { ret = -1; goto out; } INIT_LIST_HEAD (&glusterfs_ctx->graphs); ret = pthread_mutex_init (&glusterfs_ctx->lock, NULL); out: return ret; }
static int _gf_string2ulonglong (const char *str, unsigned long long *n, int base) { unsigned long long value = 0; char *tail = NULL; int old_errno = 0; const char *s = NULL; if (str == NULL || n == NULL) { gf_log_callingfn (THIS->name, GF_LOG_WARNING, "argument invalid"); errno = EINVAL; return -1; } for (s = str; *s != '\0'; s++) { if (isspace (*s)) continue; if (*s == '-') return -1; break; } old_errno = errno; errno = 0; value = strtoull (str, &tail, base); if (errno == ERANGE || errno == EINVAL) return -1; if (errno == 0) errno = old_errno; if (tail[0] != '\0') return -1; *n = value; return 0; }
static int gf_client_chain_client_entries (cliententry_t *entries, uint32_t startidx, uint32_t endcount) { uint32_t i = 0; if (!entries) { gf_log_callingfn ("client_t", GF_LOG_WARNING, "!entries"); return -1; } /* Chain only till the second to last entry because we want to * ensure that the last entry has GF_CLIENTTABLE_END. */ for (i = startidx; i < (endcount - 1); i++) entries[i].next_free = i + 1; /* i has already been incremented up to the last entry. */ entries[i].next_free = GF_CLIENTTABLE_END; return 0; }
char valid_internet_address (char *address, gf_boolean_t wildcard_acc) { char ret = 0; int length = 0; if (address == NULL) { gf_log_callingfn (THIS->name, GF_LOG_WARNING, "argument invalid"); goto out; } length = strlen (address); if (length == 0) goto out; if (valid_ipv4_address (address, length, wildcard_acc) || valid_ipv6_address (address, length, wildcard_acc) || valid_host_name (address, length)) ret = 1; out: return ret; }