Example #1
0
int mdb_init ( size_t size )
{
    enum hashfunc_type hash_type = JENKINS_HASH;
    bool preallocate = false;
    bool start_lru_crawler = true;
    process_started = time (0);

    settings_init (size);
    init_lru_crawler ();
    init_lru_maintainer ();
    setbuf (stderr, NULL);
    if ( hash_init (hash_type) != 0 )
    {
        fprintf (stderr, "Failed to initialize hash_algorithm!\n");
        return - 1;
    }
    assoc_init (settings.hashpower_init);
    if ( enable_large_pages () == 0 )
    {
        preallocate = true;
    }
    slabs_init (settings.maxbytes, settings.factor, preallocate);

    memcached_thread_init ();

    if ( start_assoc_maintenance_thread () == - 1 )
    {
        return - 1;
    }
    
    if ( start_lru_crawler && start_lru_maintainer_thread () != 0 )
    {
        fprintf (stderr, "Failed to enable LRU maintainer thread\n");
        return - 1;
    }
    
    if ( settings.slab_reassign && start_slab_maintenance_thread () == - 1 )
    {
        return - 1;
    }

    return 0;
}
Example #2
0
int main(int argc, char *argv[])
{
	int c;
	int do_daemonize= 0;
	int maxcore	= 0;
	struct rlimit rlim;
	char unit	= '\0';
	int size_max	= 0;

	int protocol_specified	= 0;
	int tcp_specified	= 0;
	int udp_specified	= 0;

	char *subopts;
	char *subopts_value;

	enum {
		MAXCONNS_FAST = 0,
		HASHPOWER_INIT,
		SLAB_REASSIGN,
		SLAB_AUTOMOVE
	};
	char *const subopts_tokens[] = {
		[MAXCONNS_FAST]	= "maxconns_fast",
		[HASHPOWER_INIT]= "hashpower",
		[SLAB_REASSIGN] = "slab_reassign",
		[SLAB_AUTOMOVE] = "slab_automove",
		NULL
	};

	/* init settings */
	settings_init();
	
	/* set stderr non-buffering (for running under, say, daemontools) */
	setbuf(stderr, NULL);

	/* process arguments */
	while (-1 != (c = getopt(argc, argv,
		"a:"	/* access mask for unix socket */
		"A"	/* enable admin shutdown commannd */
		"p:"	/* TCP port number to listen on */
		"s:"	/* unix socket path to listen on */
		"U:"	/* UDP port number to listen on */
		"m:"	/* max memory to use for items in megabytes */
		"M"	/* return error on memory exhausted */
		"c:"	/* max simultaneous connections */
		"hi"	/* help, licence info */
		"r"	/* maximize core file limit */
		"v"	/* verbose */
		"d"	/* daemon mode */
		"l:"	/* interface to listen on */
		"f:"	/* factor? */
		"n:"	/* minimum space allocated for key+value+flags */
		"D:"	/* prefix delimiter? */
		"L"	/* Large memory pages */
		"R:"	/* max requests per event */
		"C"	/* Disable use of CAS */
		"b:"	/* backlog queue limit */
		"B:"	/* Binding protocol */
		"I:"	/* Max item size */
		"S"	/* Sasl ON */
		"o:"	/* Extended generic options */
	))) {
		switch (c) {
		case 'A':
			/* enables "shutdown" command */
			settings.shutdown_command = 1;
			break;

		case 'a':
			/* access for unix domain socket, as octal mask (like chmod)*/
			settings.access= strtol(optarg,NULL,8);
			break;

		case 'U':
			settings.udpport = atoi(optarg);
			udp_specified = 1;
			break;
		case 'p':
			settings.port = atoi(optarg);
			tcp_specified = 1;
			break;
		case 's':
			settings.socketpath = optarg;
			break;
		case 'm':
			settings.maxbytes = ((size_t)atoi(optarg)) * 1024 * 1024;
			break;
		case 'M':
			settings.evict_to_free = 0;
			break;
		case 'c':
			settings.maxconns = atoi(optarg);
			break;
		case 'h':
			usage();
			exit(EXIT_SUCCESS);
		case 'i':
			usage_license();
			exit(EXIT_SUCCESS);
		case 'v':
			settings.verbose++;
			break;
		case 'l':
			if (settings.inter != NULL) {
				size_t len = strlen(settings.inter) + strlen(optarg) + 2;
				char *p = malloc(len);
				if (p == NULL) {
				fprintf(stderr, "Failed to allocate memory\n");
				return 1;
				}
				snprintf(p, len, "%s,%s", settings.inter, optarg);
				free(settings.inter);
				settings.inter = p;
			} else {
				settings.inter= strdup(optarg);
			}
			break;
		case 'd':
			do_daemonize = 1;
			break;
		case 'r':
			maxcore = 1;
			break;
		case 'R':
			settings.reqs_per_event = atoi(optarg);
			if (settings.reqs_per_event == 0) {
				fprintf(stderr, "Number of requests per event must be greater than 0\n");
				return 1;
			}
			break;
		case 'f':
			if (atof(optarg) <= 1.0) {
				fprintf(stderr, "Factor must be greater than 1\n");
				return 1;
			}
			double_int(optarg, &settings.factor_numerator, &settings.factor_denominator);
			break;
		case 'n':
			settings.chunk_size = atoi(optarg);
			if (settings.chunk_size == 0) {
				fprintf(stderr, "Chunk size must be greater than 0\n");
				return 1;
			}
			break;
		case 'D':
			if (! optarg || ! optarg[0]) {
				fprintf(stderr, "No delimiter specified\n");
				return 1;
			}
			settings.prefix_delimiter = optarg[0];
			settings.detail_enabled = 1;
			break;
		case 'L' :
			if (enable_large_pages() == 0) {
				settings.preallocate = 1;
			} else {
				fprintf(stderr, "Cannot enable large pages on this system\n"
				"(There is no Linux support as of this version)\n");
				return 1;
			}
			break;
		case 'C' :
			settings.use_cas = 0;
			break;
		case 'b' :
			settings.backlog = atoi(optarg);
			break;
		case 'B':
			protocol_specified = 1;
			if (strcmp(optarg, "auto") == 0) {
				settings.binding_protocol = negotiating_prot;
			} else if (strcmp(optarg, "binary") == 0) {
				settings.binding_protocol = binary_prot;
			} else if (strcmp(optarg, "ascii") == 0) {
				settings.binding_protocol = ascii_prot;
			} else {
				fprintf(stderr, "Invalid value for binding protocol: %s\n"
					" -- should be one of auto, binary, or ascii\n", optarg);
				exit(EX_USAGE);
			}
			break;
		case 'I':
			unit = optarg[strlen(optarg)-1];
			if (unit == 'k' || unit == 'm' ||
				unit == 'K' || unit == 'M') {
				optarg[strlen(optarg)-1] = '\0';
				size_max = atoi(optarg);
				if (unit == 'k' || unit == 'K')
				size_max *= 1024;
				if (unit == 'm' || unit == 'M')
				size_max *= 1024 * 1024;
				settings.item_size_max = size_max;
			} else {
				settings.item_size_max = atoi(optarg);
			}
			if (settings.item_size_max < 1024) {
				fprintf(stderr, "Item max size cannot be less than 1024 bytes.\n");
				return 1;
			}
			if (settings.item_size_max > 1024 * 1024 * 128) {
				fprintf(stderr, "Cannot set item size limit higher than 128 mb.\n");
				return 1;
			}
			if (settings.item_size_max > 1024 * 1024) {
				fprintf(stderr, "WARNING: Setting item max size above 1MB is not"
				" recommended!\n"
				" Raising this limit increases the minimum memory requirements\n"
				" and will decrease your memory efficiency.\n"
				);
			}
			break;
		case 'S': /* set Sasl authentication to 1. Default is 0 */
#ifndef ENABLE_SASL
			fprintf(stderr, "This server is not built with SASL support.\n");
			exit(EX_USAGE);
#endif
			settings.sasl = 1;
			break;
		case 'o': /* It's sub-opts time! */
			subopts = optarg;

			while (*subopts != '\0') {

				switch (getsubopt(&subopts, subopts_tokens, &subopts_value)) {
				case MAXCONNS_FAST:
					settings.maxconns_fast = 1;
					break;
				case HASHPOWER_INIT:
					if (subopts_value == NULL) {
						fprintf(stderr, "Missing numeric argument for hashpower\n");
						return 1;
					}
					settings.hashpower_init = atoi(subopts_value);
					if (settings.hashpower_init < 12) {
						fprintf(stderr, "Initial hashtable multiplier of %d is too low\n",
							settings.hashpower_init);
						return 1;
					} else if (settings.hashpower_init > 64) {
						fprintf(stderr, "Initial hashtable multiplier of %d is too high\n"
							"Choose a value based on \"STAT hash_power_level\" from a running instance\n",
							settings.hashpower_init);
						return 1;
					}
					break;
				case SLAB_REASSIGN:
					settings.slab_reassign = 1;
					break;
				case SLAB_AUTOMOVE:
					if (subopts_value == NULL) {
						settings.slab_automove = 1;
						break;
					}
					settings.slab_automove = atoi(subopts_value);
					if (settings.slab_automove < 0 || settings.slab_automove > 2) {
						fprintf(stderr, "slab_automove must be between 0 and 2\n");
						return 1;
					}
					break;
				default:
					printf("Illegal suboption \"%s\"\n", subopts_value);
					return 1;
				}

			}
			break;
		default:
			fprintf(stderr, "Illegal argument \"%c\"\n", c);
			return 1;
		}
	}

	/*
	 * Use one workerthread to serve each UDP port if the user specified
	 * multiple ports
	 */
	if (settings.inter != NULL && strchr(settings.inter, ',')) {
		settings.num_threads_per_udp = 1;
	} else {
		settings.num_threads_per_udp = 0x7fffffff;
	}

	if (settings.sasl) {
		if (!protocol_specified) {
			settings.binding_protocol = binary_prot;
		} else {
			if (settings.binding_protocol != binary_prot) {
				fprintf(stderr, "ERROR: You cannot allow the ASCII protocol while using SASL.\n");
				exit(EX_USAGE);
			}
		}
	}

	if (tcp_specified && !udp_specified) {
		settings.udpport = settings.port;
	} else if (udp_specified && !tcp_specified) {
		settings.port = settings.udpport;
	}

	if (maxcore != 0) {
		struct rlimit rlim_new;

		/*
		* First try raising to infinity; if that fails, try bringing
		* the soft limit to the hard.
		*/
		if (getrlimit(RLIMIT_CORE, &rlim) == 0) {
			rlim_new.rlim_cur = rlim_new.rlim_max = RLIM_INFINITY;
			if (setrlimit(RLIMIT_CORE, &rlim_new)!= 0) {
				/* failed. try raising just to the old max */
				rlim_new.rlim_cur = rlim_new.rlim_max = rlim.rlim_max;
				(void)setrlimit(RLIMIT_CORE, &rlim_new);
			}
		}

		/*
		* getrlimit again to see what we ended up with. Only fail if
		* the soft limit ends up 0, because then no core files will be
		* created at all.
		*/
		if ((getrlimit(RLIMIT_CORE, &rlim) != 0) || rlim.rlim_cur == 0) {
			fprintf(stderr, "failed to ensure corefile creation\n");
			exit(EX_OSERR);
		}
	}

	/*
	* If needed, increase rlimits to allow as many connections
	* as needed.
	*/
	if (getrlimit(RLIMIT_NOFILE, &rlim) != 0) {
		fprintf(stderr, "failed to getrlimit number of files\n");
		exit(EX_OSERR);
	} else {
		rlim.rlim_cur = settings.maxconns;
		rlim.rlim_max = settings.maxconns;
		if (setrlimit(RLIMIT_NOFILE, &rlim) != 0) {
			fprintf(stderr, "failed to set rlimit for open files. Try starting as root or requesting smaller maxconns value.\n");
			exit(EX_OSERR);
		}
	}

	/* lose root privileges if we have them */
	if (getuid() != 0 || geteuid() != 0) {
		fprintf(stderr, "run as root\n");
		exit(EX_USAGE);
	}

	/* Initialize Sasl if -S was specified */
	if (settings.sasl) {
	//	init_sasl();
	}

	/* daemonize if requested */
	/* if we want to ensure our ability to dump core, don't chdir to / */
	if (do_daemonize) {
		if (sigignore(SIGHUP) == -1) {
			perror("Failed to ignore SIGHUP");
		}
		if (daemonize(maxcore, settings.verbose) == -1) {
			fprintf(stderr, "failed to daemon() in order to daemonize\n");
			exit(EXIT_FAILURE);
		}
	}

	main_loop();

	return 0;
}