CUBRID Engine  latest
release_string.c
Go to the documentation of this file.
1 /*
2  * Copyright 2008 Search Solution Corporation
3  * Copyright 2016 CUBRID Corporation
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  */
18 
19 /*
20  * release_string.c - release related information (at client and server)
21  *
22  * Note: This file contains some very simple functions related to version and
23  * releases of CUBRID. Among these functions are copyright information
24  * of CUBRID products, name of CUBRID engine, and version.
25  */
26 
27 #ident "$Id$"
28 
29 #include <stdlib.h>
30 #include <string.h>
31 
32 #include "config.h"
33 #include "porting.h"
34 #include "release_string.h"
35 #include "message_catalog.h"
36 #include "chartype.h"
37 #include "language_support.h"
38 #include "environment_variable.h"
39 #include "log_comm.h"
40 
41 /*
42  * COMPATIBILITY_RULE - Structure that encapsulates compatibility rules.
43  * For two revision levels, both a compatibility type
44  * and optional fixup function list is defined.
45  */
46 
47 typedef struct version
48 {
49  unsigned char major;
50  unsigned char minor;
51  unsigned short patch;
52 } REL_VERSION;
53 
54 typedef struct compatibility_rule
55 {
61 
62 typedef enum
63 {
67 
68 /*
69  * Copyright Information
70  */
71 static const char *copyright_header = "\
72 Copyright (C) 2008 Search Solution Corporation.\nCopyright (C) 2016 CUBRID Corporation.\n\
73 ";
74 
75 static const char *copyright_body = "\
76 Copyright Information\n\
77 ";
78 
79 /*
80  * CURRENT VERSIONS
81  */
82 #define makestring1(x) #x
83 #define makestring(x) makestring1(x)
84 
85 static const char *release_string = makestring (RELEASE_STRING);
86 static const char *major_release_string = makestring (MAJOR_RELEASE_STRING);
87 static const char *build_number = makestring (BUILD_NUMBER);
88 static const char *package_string = PACKAGE_STRING;
89 static const char *build_os = makestring (BUILD_OS);
90 static const char *build_type = makestring (BUILD_TYPE);
91 
92 #if defined (VERSION_STRING)
93 static const char *version_string = VERSION_STRING;
94 #endif /* VERSION_STRING */
95 static int bit_platform = __WORDSIZE;
96 
97 static REL_COMPATIBILITY rel_get_compatible_internal (const char *base_rel_str, const char *apply_rel_str,
98  COMPATIBILITY_CHECK_MODE check, REL_VERSION rules[]);
99 
100 /*
101  * Disk (database image) Version Compatibility
102  */
103 static float disk_compatibility_level = 11.0f;
104 
105 /*
106  * rel_copy_version_string - version string of the product
107  * return: void
108  */
109 void
110 rel_copy_version_string (char *buf, size_t len)
111 {
112 #if defined (CUBRID_OWFS)
113  snprintf (buf, len, "%s (%s) (%dbit owfs %s build for %s) (%s %s)", rel_name (), rel_build_number (),
114  rel_bit_platform (), rel_build_type (), rel_build_os (), __DATE__, __TIME__);
115 #else /* CUBRID_OWFS */
116 #if defined (VERSION_STRING)
117  snprintf (buf, len, "%s (%s) (%dbit %s build for %s) (%s %s)", rel_name (), rel_version_string (),
118  rel_bit_platform (), rel_build_type (), rel_build_os (), __DATE__, __TIME__);
119 #else /* VERSION_STRING */
120  snprintf (buf, len, "%s (%s) (%dbit %s build for %s) (%s %s)", rel_name (), rel_build_number (),
121  rel_bit_platform (), rel_build_type (), rel_build_os (), __DATE__, __TIME__);
122 #endif /* VERSION_STRING */
123 #endif /* CUBRID_OWFS */
124 }
125 
126 /*
127  * rel_name - Name of the product from the message catalog
128  * return: static character string
129  */
130 const char *
131 rel_name (void)
132 {
133  return package_string;
134 }
135 
136 /*
137  * rel_release_string - Release number of the product
138  * return: static char string
139  */
140 const char *
142 {
143  return release_string;
144 }
145 
146 /*
147  * rel_major_release_string - Major release portion of the release string
148  * return: static char string
149  */
150 const char *
152 {
153  return major_release_string;
154 }
155 
156 /*
157  * rel_build_number - Build bumber portion of the release string
158  * return: static char string
159  */
160 const char *
162 {
163  return build_number;
164 }
165 
166 /*
167  * rel_build_os - Build OS portion of the release string
168  * return: static char string
169  */
170 const char *
172 {
173  return build_os;
174 }
175 
176 /*
177  * rel_build_type - Build type portion of the release string
178  * build, release, coverage, profile
179  * return: static char string
180  */
181 const char *
183 {
184  return build_type;
185 }
186 
187 #if defined (VERSION_STRING)
188 /*
189  * rel_version_string - Full version string of the product
190  * return: static char string
191  */
192 const char *
193 rel_version_string (void)
194 {
195  return version_string;
196 }
197 #endif /* VERSION_STRING */
198 
199 #if defined (ENABLE_UNUSED_FUNCTION)
200 /*
201  * rel_copyright_header - Copyright header from the message catalog
202  * return: static char string
203  */
204 const char *
205 rel_copyright_header (void)
206 {
207  const char *name;
208 
209  lang_init ();
211  return (name) ? name : copyright_header;
212 }
213 
214 /*
215  * rel_copyright_body - Copyright body fromt he message catalog
216  * return: static char string
217  */
218 const char *
219 rel_copyright_body (void)
220 {
221  const char *name;
222 
223  lang_init ();
225  return (name) ? name : copyright_body;
226 }
227 #endif /* ENABLE_UNUSED_FUNCTION */
228 
229 /*
230  * rel_disk_compatible - Disk compatibility level
231  * return:
232  */
233 float
235 {
237 }
238 
239 
240 /*
241  * rel_set_disk_compatible - Change disk compatibility level
242  * return: none
243  * level(in):
244  */
245 void
247 {
248  disk_compatibility_level = level;
249 }
250 
251 /*
252  * rel_platform - built platform
253  * return: none
254  * level(in):
255  */
256 int
258 {
259  return bit_platform;
260 }
261 
262 /*
263  * compatibility_rules - Static table of compatibility rules.
264  * Each time a change is made to the disk_compatibility_level
265  * a rule needs to be added to this table.
266  * If pair of numbers is absent from this table, the two are considered
267  * to be incompatible.
268  * {base_level (of database), apply_level (of system), compatibility, fix_func}
269  */
271  /* a zero indicates the end of the table */
272  {{0, 0, 0}, {0, 0, 0}, REL_NOT_COMPATIBLE, NULL}
273 };
274 
275 /*
276  * rel_get_disk_compatible - Test compatibility of disk (database image)
277  * Check a disk compatibility number stored in
278  * a database with the disk compatibility number
279  * for the system being run
280  * return: One of the three compatibility constants (REL_FULLY_COMPATIBLE,
281  * REL_FORWARD_COMPATIBLE, and REL_BACKWARD_COMPATIBLE) or
282  * REL_NOT_COMPATIBLE if they are not compatible
283  * db_level(in):
284  * REL_FIXUP_FUNCTION(in): function pointer table
285  *
286  * Note: The rules for compatibility are stored in the compatibility_rules
287  * table. Whenever the disk_compatibility_level variable is changed
288  * an entry had better be made in the table.
289  */
291 rel_get_disk_compatible (float db_level, REL_FIXUP_FUNCTION ** fixups)
292 {
293  COMPATIBILITY_RULE *rule;
294  REL_COMPATIBILITY compat;
295  REL_FIXUP_FUNCTION *func;
296 
297  func = NULL;
298 
299  if (disk_compatibility_level == db_level)
300  {
301  compat = REL_FULLY_COMPATIBLE;
302  }
303  else
304  {
305  compat = REL_NOT_COMPATIBLE;
306  for (rule = &disk_compatibility_rules[0]; rule->base.major != 0 && compat == REL_NOT_COMPATIBLE; rule++)
307  {
308  float base_level, apply_level;
309 
310  base_level = (float) (rule->base.major + (rule->base.minor / 10.0));
311  apply_level = (float) (rule->apply.major + (rule->apply.minor / 10.0));
312 
313  if (base_level == db_level && apply_level == disk_compatibility_level)
314  {
315  compat = rule->compatibility;
316  func = rule->fix_function;
317  }
318  }
319  }
320 
321  if (fixups != NULL)
322  {
323  *fixups = func;
324  }
325 
326  return compat;
327 }
328 
329 
330 /* Compare release strings.
331  *
332  * Returns: < 0, if rel_a is earlier than rel_b
333  * == 0, if rel_a is the same as rel_b
334  * > 0, if rel_a is later than rel_b
335  */
336 /*
337  * rel_compare - Compare release strings, A and B
338  * return: < 0, if rel_a is earlier than rel_b
339  * == 0, if rel_a is the same as rel_b
340  * > 0, if rel_a is later than rel_b
341  * rel_a(in): release string A
342  * rel_b(in): release string B
343  *
344  * Note:
345  */
346 int
347 rel_compare (const char *rel_a, const char *rel_b)
348 {
349  int a, b, retval = 0;
350  char *a_temp, *b_temp, *end_p;
351 
352  /*
353  * If we get a NULL for one of the values (and we shouldn't), guess that
354  * the versions are the same.
355  */
356  if (!rel_a || !rel_b)
357  {
358  retval = 0;
359  }
360  else
361  {
362  /*
363  * Compare strings
364  */
365  a_temp = (char *) rel_a;
366  b_temp = (char *) rel_b;
367  /*
368  * The following loop terminates if we determine that one string
369  * is greater than the other, or we reach the end of one of the
370  * strings.
371  */
372  while (!retval && *a_temp && *b_temp)
373  {
374  str_to_int32 (&a, &end_p, a_temp, 10);
375  a_temp = end_p;
376  str_to_int32 (&b, &end_p, b_temp, 10);
377  b_temp = end_p;
378  if (a < b)
379  {
380  retval = -1;
381  }
382  else if (a > b)
383  {
384  retval = 1;
385  }
386  /*
387  * This skips over the '.'.
388  * This means that "?..?" will parse out to "?.?".
389  */
390  while (*a_temp && *a_temp == '.')
391  {
392  a_temp++;
393  }
394  while (*b_temp && *b_temp == '.')
395  {
396  b_temp++;
397  }
398  if (*a_temp && *b_temp && char_isalpha (*a_temp) && char_isalpha (*b_temp))
399  {
400  if (*a_temp != *b_temp)
401  retval = -1;
402  a_temp++;
403  b_temp++;
404  }
405  }
406 
407  if (!retval)
408  {
409  /*
410  * Both strings are the same up to this point. If the rest is zeros,
411  * they're still equal.
412  */
413  while (*a_temp)
414  {
415  if (*a_temp != '.' && *a_temp != '0')
416  {
417  retval = 1;
418  break;
419  }
420  a_temp++;
421  }
422  while (*b_temp)
423  {
424  if (*b_temp != '.' && *b_temp != '0')
425  {
426  retval = -1;
427  break;
428  }
429  b_temp++;
430  }
431  }
432  }
433  return retval;
434 }
435 
436 /*
437  * log compatibility matrix
438  */
440  {10, 0, 0},
441 
442  /* PLEASE APPEND HERE versions that are incompatible with existing ones. */
443  /* NOTE that versions are kept as ascending order. */
444 
445  /* zero indicates the end of the table */
446  {0, 0, 0}
447 };
448 
449 /*
450  * rel_is_log_compatible - Test compatiblility of log file format
451  * return: true if compatible
452  * writer_rel_str(in): release string of the log writer (log file)
453  * reader_rel_str(in): release string of the log reader (system being run)
454  */
455 bool
456 rel_is_log_compatible (const char *writer_rel_str, const char *reader_rel_str)
457 {
458  REL_COMPATIBILITY compat;
459 
460  compat =
461  rel_get_compatible_internal (writer_rel_str, reader_rel_str, CHECK_LOG_COMPATIBILITY, log_incompatible_versions);
462  if (compat == REL_NOT_COMPATIBLE)
463  {
464  return false;
465  }
466 
467  return true;
468 }
469 
470 /*
471  * network compatibility matrix
472  */
474  {10, 0, 0},
475 
476  /* PLEASE APPEND HERE versions that are incompatible with existing ones. */
477  /* NOTE that versions are kept as ascending order. */
478 
479  /* zero indicates the end of the table */
480  {0, 0, 0}
481 };
482 
483 /*
484  * rel_get_net_compatible - Compare the release strings from
485  * the server and client to determine compatibility.
486  * return: REL_COMPATIBILITY
487  * REL_NOT_COMPATIBLE if the client and the server are not compatible
488  * REL_FULLY_COMPATIBLE if the client and the server are compatible
489  * REL_FORWARD_COMPATIBLE if the client is forward compatible with the server
490  * if the server is backward compatible with the client
491  * the client is older than the server
492  * REL_BACKWARD_COMPATIBLE if the client is backward compatible with the server
493  * if the server is forward compatible with the client
494  * the client is newer than the server
495  *
496  * client_rel_str(in): client's release string
497  * server_rel_str(in): server's release string
498  */
500 rel_get_net_compatible (const char *client_rel_str, const char *server_rel_str)
501 {
502  return rel_get_compatible_internal (server_rel_str, client_rel_str, CHECK_NET_PROTOCOL_COMPATIBILITY,
503  net_incompatible_versions);
504 }
505 
506 /*
507  * rel_get_compatible_internal - Compare the release to determine compatibility.
508  * return: REL_COMPATIBILITY
509  *
510  * base_rel_str(in): base release string (of database)
511  * apply_rel_str(in): applier's release string (of system)
512  * rules(in): rules to determine forward/backward compatibility
513  */
514 static REL_COMPATIBILITY
515 rel_get_compatible_internal (const char *base_rel_str, const char *apply_rel_str, COMPATIBILITY_CHECK_MODE check,
516  REL_VERSION versions[])
517 {
518  REL_VERSION *version, *base_version, *apply_version;
519  char *base, *apply, *str_a, *str_b;
520  int val;
521 
522  unsigned char base_major, base_minor, apply_major, apply_minor;
523  unsigned short base_patch, apply_patch;
524 
525  if (apply_rel_str == NULL || base_rel_str == NULL)
526  {
527  return REL_NOT_COMPATIBLE;
528  }
529 
530  /* release string should be in the form of <major>.<minor>[.<patch>] */
531 
532  /* check major number */
533  str_to_int32 (&val, &str_a, apply_rel_str, 10);
534  apply_major = (unsigned char) val;
535  str_to_int32 (&val, &str_b, base_rel_str, 10);
536  base_major = (unsigned char) val;
537  if (apply_major == 0 || base_major == 0)
538  {
539  return REL_NOT_COMPATIBLE;
540  }
541 
542  /* skip '.' */
543  while (*str_a && *str_a == '.')
544  {
545  str_a++;
546  }
547  while (*str_b && *str_b == '.')
548  {
549  str_b++;
550  }
551 
552  /* check minor number */
553  apply = str_a;
554  base = str_b;
555  str_to_int32 (&val, &str_a, apply, 10);
556  apply_minor = (unsigned char) val;
557  str_to_int32 (&val, &str_b, base, 10);
558  base_minor = (unsigned char) val;
559 
560  /* skip '.' */
561  while (*str_a && *str_a == '.')
562  {
563  str_a++;
564  }
565  while (*str_b && *str_b == '.')
566  {
567  str_b++;
568  }
569 
571  {
572  if (apply_major != base_major)
573  {
574  return REL_NOT_COMPATIBLE;
575  }
576  if (apply_minor != base_minor)
577  {
578  return REL_NOT_COMPATIBLE;
579  }
580  }
581 
582  /* check patch number */
583  apply = str_a;
584  base = str_b;
585  str_to_int32 (&val, &str_a, apply, 10);
586  apply_patch = (unsigned short) val;
587  str_to_int32 (&val, &str_b, base, 10);
588  base_patch = (unsigned short) val;
589  if (apply_major == base_major && apply_minor == base_minor && apply_patch == base_patch)
590  {
591  return REL_FULLY_COMPATIBLE;
592  }
593 
594  base_version = NULL;
595  apply_version = NULL;
596  for (version = &versions[0]; version->major != 0; version++)
597  {
598  if (base_major >= version->major && base_minor >= version->minor && base_patch >= version->patch)
599  {
600  base_version = version;
601  }
602  if (apply_major >= version->major && apply_minor >= version->minor && apply_patch >= version->patch)
603  {
604  apply_version = version;
605  }
606  }
607 
608  if (base_version == NULL || apply_version == NULL || base_version != apply_version)
609  {
610  return REL_NOT_COMPATIBLE;
611  }
612  else
613  {
614  return REL_FULLY_COMPATIBLE;
615  }
616 }
static const char * release_string
int lang_init(void)
float rel_disk_compatible(void)
int rel_compare(const char *rel_a, const char *rel_b)
int rel_bit_platform(void)
void rel_copy_version_string(char *buf, size_t len)
static REL_COMPATIBILITY rel_get_compatible_internal(const char *base_rel_str, const char *apply_rel_str, COMPATIBILITY_CHECK_MODE check, REL_VERSION rules[])
const char * rel_build_os(void)
void(* REL_FIXUP_FUNCTION)(void)
static float disk_compatibility_level
COMPATIBILITY_CHECK_MODE
struct version REL_VERSION
const char * rel_build_number(void)
unsigned char major
REL_COMPATIBILITY
const char * rel_build_type(void)
#define MSGCAT_GENERAL_COPYRIGHT_BODY
static const char * copyright_body
struct compatibility_rule COMPATIBILITY_RULE
unsigned short patch
REL_COMPATIBILITY rel_get_net_compatible(const char *client_rel_str, const char *server_rel_str)
void rel_set_disk_compatible(float level)
static REL_VERSION net_incompatible_versions[]
bool rel_is_log_compatible(const char *writer_rel_str, const char *reader_rel_str)
const char * rel_name(void)
#define NULL
Definition: freelistheap.h:34
int str_to_int32(int *ret_p, char **end_p, const char *str_p, int base)
Definition: porting.c:2346
static const char * build_type
static REL_VERSION log_incompatible_versions[]
static COMPATIBILITY_RULE disk_compatibility_rules[]
unsigned char minor
REL_COMPATIBILITY compatibility
#define MSGCAT_SET_GENERAL
#define MSGCAT_GENERAL_COPYRIGHT_HEADER
#define MSGCAT_CATALOG_CUBRID
static const char * package_string
REL_COMPATIBILITY rel_get_disk_compatible(float db_level, REL_FIXUP_FUNCTION **fixups)
static const char * build_number
char * msgcat_message(int cat_id, int set_id, int msg_id)
static int bit_platform
REL_FIXUP_FUNCTION * fix_function
const char * rel_release_string(void)
#define makestring(x)
static const char * copyright_header
static const char * build_os
static const char * major_release_string
const char * rel_major_release_string(void)
int char_isalpha(int c)
Definition: chartype.c:61