Redis Source Code Analysis (35) --- implementation analysis of redis. c server (2)

Source: Internet
Author: User
Tags redis version redis server

The amount of code on the Redis server is really large. If you learn how to implement one API, it is undoubtedly very inefficient. So today I am studying the implementation code on the server, he focuses on his execution process, and I have analyzed his Module design in the previous article. If you do not understand it, you can continue to read the previous article. So I learned to analyze the implementation of the redis server mainly from the main function. Before analyzing the main execution process, the author of Redis declares several variables here, which we need to know.

/* Our shared "common" objects * // * shared object */struct sharedObjectsStruct shared;/* Global vars that are actually used as constants. the following double * values are used for double on-disk serialization, and are initialized * at runtime to avoid strange compiler optimizations. * // * global double type constant */double R_Zero, R_PosInf, R_NegInf, R_Nan; /* = =============================== * // * Global vars * // * Global */struct RedisServer server; /* server global state * // * Our command table. ** Every entry is composed of the following fields: ** name: a string representing the command name. * function: pointer to the C function implementing the command. * arity: number of arguments, it is possible to use-N to say> = N * sflags: command flags as string. see below for a table of flags. * flags: flags as bitmask. computed by Redis using the 'sflags 'field. * get_keys_proc: an optional function to get key arguments from a command. * This is only used when the following three fields are not * enough to specify what arguments are keys. * first_key_index: first argument that is a key * last_key_index: last argument that is a key * key_step: step to get all the keys from first to last argument. for instance * in MSET the step is two since arguments are key, val, key, val ,... * microseconds: microseconds of total execution time for this command. * cballs: total number of cballs of this command. ** The flags, microseconds and callfields are computed by Redis and shoshould * always be set to zero. ** Command flags are expressed using strings where every character represents * a flag. later the populateCommandTable () function will take care of * populating the real 'flags' field using this characters. ** This is the meaning of the flags: ** w: write command (may modify the key space ). * r: read command (will never modify the key space ). * m: may increase memory usage once called. don't allow if out of memory. * a: admin command, like SAVE or SHUTDOWN. * p: Pub/Sub related command. * f: force replication of this command, regardless of server. dirty. * s: command not allowed in scripts. * R: random command. command is not deterministic, that is, the same command * with the same arguments, with the same key space, may have different * results. for instance SPOP and RANDOMKEY are two random commands. * S: Sort command output array if called from script, so that the output * is deterministic. * l: Allow command while loading the database. * t: Allow command while a slave has stale data but is not allowed to * server this data. normally no command is accepted in this condition * but just a few. * M: Do not automatically propagate the command on MONITOR. * F: Fast command: O (1) or O (log (N) command that shoshould never delay * its execution as long as the kernel scheduler is giving us time. * Note that commands that may trigger a DEL as a side effect (like SET) * are not fast commands. * // * redis command table ing */struct redisCommand redisCommandTable [] = {"get", getCommand, 2, "rF", 0, NULL, 0 },{ "set", setCommand,-3, "wm", 0, NULL, 0 },{ "setnx", setnxCommand, 3, "wmF", 0, NULL, 0}, {"setex", setexCommand, 4, "wm", 0, NULL, 0 },.....
This command table is quite large and omitted. It basically includes all possible commands. After all, the server is implementing the response of these commands. The following describes how to execute the main program on the server. A process diagram is provided:


The code is as follows:

Int main (int argc, char ** argv) {struct timeval TV;/* We need to initialize our libraries, and the server configuration. */# ifdef INIT_SETPROCTITLE_REPLACEMENT spt_init (argc, argv); # endif setlocale (LC_COLLATE, ""); // enable thread security mode zmalloc_enable_thread_safeness (); // enable the handler method zmalloc_set_oom_handler (redisOutOfMemoryHandler) when memory overflow occurs; srand (time (NULL) ^ getpid (); // get the current time gettimeofday (& TV, NULL); dictSet HashFunctionSeed (TV. TV _sec ^ TV. TV _usec ^ getpid (); server. sentinel_mode = checkForSentinelMode (argc, argv); // initialize the server configuration initServerConfig (); /* We need to init sentinel right now as parsing the configuration file * in sentinel mode will have the effect of populating the sentinel * data structures with master nodes to monitor. * /// initialize the server mode if (server. sentinel_mode) {initSentinelConfig (); initSentine L ();} if (argc> = 2) {int j = 1;/* First option to parse in argv [] */sds options = sdsempty (); char * configfile = NULL;/* Handle special options -- help and -- version */if (strcmp (argv [1], "-v ") = 0 | strcmp (argv [1], "-- version") = 0) version (); if (strcmp (argv [1], "-- help ") = 0 | strcmp (argv [1], "-h") = 0) usage (); if (strcmp (argv [1], "-- test-memory") = 0) {if (argc = 3) {memtest ( Toi (argv [2]), 50); exit (0);} else {fprintf (stderr, "Please specify the amount of memory to test in megabytes. \ n "); fprintf (stderr," Example :. /redis-server -- test-memory 4096 \ n "); exit (1) ;}/ * First argument is the config file name? */If (argv [j] [0]! = '-' | Argv [j] [1]! = '-') Configfile = argv [j ++];/* All the other options are parsed and conceptually appended to the * configuration file. for instance -- port 6380 will generate the * string "port 6380 \ n" to be parsed after the actual file name * is parsed, if any. */while (j! = Argc) {if (argv [j] [0] = '-' & argv [j] [1] = '-') {/* Option name */if (sdslen (options) options = sdscat (options, "\ n"); options = sdscat (options, argv [j] + 2 ); options = sdscat (options, "");} else {/* Option argument */options = sdscatrepr (options, argv [j], strlen (argv [j]); options = sdscat (options, "");} j ++;} if (server. sentinel_mode & configfile & * configfile = '-') {redisLog (REDIS_W ARNING, "Sentinel config from STDIN not allowed. "); redisLog (REDIS_WARNING," Sentinel needs config file on disk to save state. exiting... "); exit (1);} if (configfile) server. configfile = getAbsolutePath (configfile); resetServerSaveParams (); // load server configurations, load loadServerConfig (configfile, options) according to the config configuration file; sdsfree (options );} else {redisLog (REDIS_WARNING, "Warning: no config file specified, using The default config. In order to specify a config file use % s/path/to/% s. conf ", argv [0], server. sentinel_mode? "Sentinel": "redis") ;}// whether to enable the daemon if (server. daemonize) daemonize (); initServer (); if (server. daemonize) createPidFile (); redisSetProcTitle (argv [0]); redisAsciiArt (); if (! Server. sentinel_mode) {/* Things not needed when running in Sentinel mode. */redisLog (REDIS_WARNING, "Server started, Redis version" REDIS_VERSION); # ifdef _ linux _ linuxOvercommitMemoryWarning (); # endif loadDataFromDisk (); if (server. ipfd_count> 0) redisLog (REDIS_NOTICE, "The server is now ready to accept connections on port % d", server. port); if (server. sofd> 0) redisLog (REDIS_NOTICE, "The ser Ver is now ready to accept connections at % s ", server. unixsocket);} else {sentinelIsRunning ();}/* Warning the user about suspicious maxmemory setting. */if (server. maxmemory> 0 & server. maxmemory <1024*1024) {redisLog (REDIS_WARNING, "WARNING: You specified a maxmemory value that is less than 1 MB (current value is % llu bytes ). are you sure this is what you really want? ", Server. maxmemory);} // The beforeSleep method aeSetBeforeSleepProc (server. el, beforeSleep); // enable the event-driven cycle aeMain (server. el); aeDeleteEventLoop (server. el); return 0 ;}
The method is very simple. Some people may wonder why there is no connection operation. The Client and Server do not need to have a connection operation. Why is there no connection operation here, because the operations are actively performed by the client, the main operations on the server are much simpler.

Redis Source Code Analysis (35) --- implementation analysis of redis. c server (2)

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.