struct conn_target *calculate_key_target (const char *key, int key_len) { int i = 0; unsigned hash; struct conn_target *S; static char key_buffer[MAX_KEY_LEN+4]; if (!CC->tot_buckets || key_len <= 0 || key_len > MAX_KEY_LEN) { return 0; } if (key_len >= 3 && key[key_len - 1] == '$' && key[key_len - 2] == '#' && key[key_len - 3] == '@') { char *tmp; for (tmp = (char *)(key + key_len - 4); tmp >= (char *)key; --tmp) { if (*tmp == '#') { break; } } if (tmp >= (char *)key) { char *ttt; unsigned r = strtoul (tmp + 1, &ttt, 10); if (ttt > tmp + 1 && ttt == key + key_len - 3) { S = CC->buckets[r % CC->tot_buckets]; return S; } } } if ((CC->cluster_mode & 255) == CLUSTER_MODE_RANDOM) { for (i = 0; i < 10; i++) { S = CC->buckets[lrand48 () % CC->tot_buckets]; if (S && S->active_outbound_connections) { return S; } } return 0; } if ((CC->cluster_mode & 255) == CLUSTER_MODE_FIRSTINT) { unsigned long long longhash = extract_num (key, key_len, 0); if (verbosity > 1) { fprintf (stderr, "extract_num(%.*s) = %llu\n", key_len, key, longhash); } if ((long long) longhash == -1) { return 0; } if (CC->step > 0) { longhash /= CC->step; } S = CC->buckets[longhash % CC->tot_buckets]; return S->active_outbound_connections ? S : 0; } if ((CC->cluster_mode & 255) > CLUSTER_MODE_FIRSTINT && (CC->cluster_mode & 255) <= CLUSTER_MODE_FIFTHINT) { int k = (CC->cluster_mode & 255) - (CLUSTER_MODE_FIRSTINT - 1); char *p1 = (char *) key, *p2; int clen = key_len; unsigned long long longhash = 0; for (i = 0; i < k; i++) { longhash = extract_num (p1, clen, &p2); if ((long long) longhash == -1) { return 0; } assert (p2 >= p1 && p2 <= p1 + clen); clen -= p2 - p1; p1 = p2; } if (CC->step > 0) { longhash /= CC->step; } S = CC->buckets[longhash % CC->tot_buckets]; return S->active_outbound_connections ? S : 0; } if (DOT_EXTENSION) { char *dot_pos = memchr (key, '.', key_len); if (dot_pos) { key_len = dot_pos - key; } } if (CC->points) { unsigned long long x = crc64 (key, key_len); int a = -1, b = CC->tot_buckets * CC->points_num, c; while (b - a > 1) { c = (a + b) >> 1; if (x < CC->points[c].x) { b = c; } else { a = c; } } assert (CC->points_num > 0); for (i = 0; i < MAX_RETRIES; i++) { if (a < 0) { a += CC->points_num; } S = CC->points[a].target; if (S->active_outbound_connections) { return S; } a--; } return 0; }
static int cache_record_deserialize (struct cache_record *rec, const char *serialized, size_t size, int skip_tags) { const char *p = serialized; size_t bytes_left = size; size_t str_len; assert (rec != NULL); assert (serialized != NULL); if (!skip_tags) rec->tags = tags_new (); else rec->tags = NULL; #define extract_num(var) \ do { \ if (bytes_left < sizeof(var)) \ goto err; \ memcpy (&var, p, sizeof(var)); \ bytes_left -= sizeof(var); \ p += sizeof(var); \ } while (0) #define extract_str(var) \ do { \ if (bytes_left < sizeof(str_len)) \ goto err; \ memcpy (&str_len, p, sizeof(str_len)); \ p += sizeof(str_len); \ if (bytes_left < str_len) \ goto err; \ var = xmalloc (str_len + 1); \ memcpy (var, p, str_len); \ var[str_len] = '\0'; \ p += str_len; \ } while (0) extract_num (rec->mod_time); extract_num (rec->atime); if (!skip_tags) { extract_str (rec->tags->artist); extract_str (rec->tags->album); extract_str (rec->tags->title); extract_num (rec->tags->track); extract_num (rec->tags->time); if (rec->tags->title) rec->tags->filled |= TAGS_COMMENTS; else { if (rec->tags->artist) free (rec->tags->artist); rec->tags->artist = NULL; if (rec->tags->album) free (rec->tags->album); rec->tags->album = NULL; } if (rec->tags->time >= 0) rec->tags->filled |= TAGS_TIME; } return 1; err: logit ("Cache record deserialization error at %tdB", p - serialized); tags_free (rec->tags); rec->tags = NULL; return 0; }
int firstint_fits (const char *const key, int key_len) { unsigned long long id = extract_num (key, key_len, NULL); return id % copy_mod == copy_rem; }
static uri_template_expr *build_expr(char *tpl, int len) { uri_template_expr *expr; uri_template_var *var = uri_template_var_create(); char *name = tpl, *start = tpl, *prefix; if (IS_OPERATOR(*tpl)) { expr = uri_template_expr_create(*tpl++); name = tpl; } else { expr = uri_template_expr_create(0); } while (tpl - start <= len) { switch(*tpl) { case '%': if (name + len - tpl > 2) { if (isxdigit(*(tpl + 1))) { if (isxdigit(*(++tpl + 1))) { tpl++; } else { expr->error = URI_TEMPLATE_ERROR; } } else { expr->error = URI_TEMPLATE_ERROR; } } else { expr->error = URI_TEMPLATE_ERROR; } break; case ':': prefix = ++tpl; if (*tpl >= '1' && *tpl++ <= '9') { while (isdigit(*tpl)) { tpl++; } if (*tpl == ',' || *tpl == '}') { if (tpl - prefix < 5) { var->length = extract_num(tpl - (tpl - prefix), tpl - prefix); } else { expr->error = URI_TEMPLATE_ERROR; } tpl--; } else { expr->error = URI_TEMPLATE_ERROR; } } else { expr->error = URI_TEMPLATE_ERROR; } break; case '*': if (*(tpl + 1) == '}' || *(tpl + 1) == ',') { var->explode = 1; } else { expr->error = URI_TEMPLATE_ERROR; } break; case ',': case '}': var->name = estrndup(name, tpl - name - SHIFT_BACK(var)); uri_template_expr_add_var(expr, var); if (*tpl == ',') { var = uri_template_var_create(); name = tpl + 1; } break; default: expr->error |= !(isalnum(*tpl) || *tpl == '_' || *tpl == '.'); break; } tpl++; } return expr; }