File release_string.c¶
File List > base > release_string.c
Go to the documentation of this file
/*
* Copyright 2008 Search Solution Corporation
* Copyright 2016 CUBRID Corporation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
/*
* release_string.c - release related information (at client and server)
*
* Note: This file contains some very simple functions related to version and
* releases of CUBRID. Among these functions are copyright information
* of CUBRID products, name of CUBRID engine, and version.
*/
#ident "$Id$"
#include <stdlib.h>
#include <string.h>
#include "config.h"
#include "porting.h"
#include "release_string.h"
#include "message_catalog.h"
#include "chartype.h"
#include "language_support.h"
#include "environment_variable.h"
#include "log_comm.h"
// XXX: SHOULD BE THE LAST INCLUDE HEADER
#include "memory_wrapper.hpp"
/*
* COMPATIBILITY_RULE - Structure that encapsulates compatibility rules.
* For two revision levels, both a compatibility type
* and optional fixup function list is defined.
*/
typedef struct version
{
unsigned char major;
unsigned char minor;
unsigned short patch;
} REL_VERSION;
typedef struct compatibility_rule
{
REL_VERSION base;
REL_VERSION apply;
REL_COMPATIBILITY compatibility;
REL_FIXUP_FUNCTION *fix_function;
} COMPATIBILITY_RULE;
typedef enum
{
CHECK_LOG_COMPATIBILITY,
CHECK_NET_PROTOCOL_COMPATIBILITY
} COMPATIBILITY_CHECK_MODE;
/*
* Copyright Information
*/
static const char *copyright_header = "\
Copyright (C) 2008 Search Solution Corporation.\nCopyright (C) 2016 CUBRID Corporation.\n\
";
static const char *copyright_body = "\
Copyright Information\n\
";
/*
* CURRENT VERSIONS
*/
#define makestring1(x) #x
#define makestring(x) makestring1(x)
static const char *release_string = makestring (RELEASE_STRING);
static const char *major_release_string = makestring (MAJOR_RELEASE_STRING);
static const char *build_number = makestring (BUILD_NUMBER);
static const char *package_string = PACKAGE_STRING;
static const char *build_os = makestring (BUILD_OS);
static const char *build_type = makestring (BUILD_TYPE);
#if defined (VERSION_STRING)
static const char *version_string = VERSION_STRING;
#endif /* VERSION_STRING */
static const int bit_platform = __WORDSIZE;
static REL_COMPATIBILITY rel_get_compatible_internal (const char *base_rel_str, const char *apply_rel_str,
COMPATIBILITY_CHECK_MODE check, const REL_VERSION rules[]);
/*
* Disk (database image) Version Compatibility
*/
static float disk_compatibility_level = 11.5f;
/*
* rel_copy_version_string - version string of the product
* return: void
*/
void
rel_copy_version_string (char *buf, size_t len)
{
#if defined (CUBRID_OWFS)
snprintf (buf, len, "%s (%s) (%dbit owfs %s build for %s) (%s %s)", rel_name (), rel_build_number (),
rel_bit_platform (), rel_build_type (), rel_build_os (), __DATE__, __TIME__);
#else /* CUBRID_OWFS */
#if defined (VERSION_STRING)
snprintf (buf, len, "%s (%s) (%dbit %s build for %s) (%s %s)", rel_name (), rel_version_string (),
rel_bit_platform (), rel_build_type (), rel_build_os (), __DATE__, __TIME__);
#else /* VERSION_STRING */
snprintf (buf, len, "%s (%s) (%dbit %s build for %s) (%s %s)", rel_name (), rel_build_number (),
rel_bit_platform (), rel_build_type (), rel_build_os (), __DATE__, __TIME__);
#endif /* VERSION_STRING */
#endif /* CUBRID_OWFS */
}
/*
* rel_name - Name of the product from the message catalog
* return: static character string
*/
const char *
rel_name (void)
{
return package_string;
}
/*
* rel_release_string - Release number of the product
* return: static char string
*/
const char *
rel_release_string (void)
{
return release_string;
}
/*
* rel_major_release_string - Major release portion of the release string
* return: static char string
*/
const char *
rel_major_release_string (void)
{
return major_release_string;
}
/*
* rel_build_number - Build bumber portion of the release string
* return: static char string
*/
const char *
rel_build_number (void)
{
return build_number;
}
/*
* rel_build_os - Build OS portion of the release string
* return: static char string
*/
const char *
rel_build_os (void)
{
return build_os;
}
/*
* rel_build_type - Build type portion of the release string
* build, release, coverage, profile
* return: static char string
*/
const char *
rel_build_type (void)
{
return build_type;
}
#if defined (VERSION_STRING)
/*
* rel_version_string - Full version string of the product
* return: static char string
*/
const char *
rel_version_string (void)
{
return version_string;
}
#endif /* VERSION_STRING */
#if defined (ENABLE_UNUSED_FUNCTION)
/*
* rel_copyright_header - Copyright header from the message catalog
* return: static char string
*/
const char *
rel_copyright_header (void)
{
const char *name;
lang_init ();
name = msgcat_message (MSGCAT_CATALOG_CUBRID, MSGCAT_SET_GENERAL, MSGCAT_GENERAL_COPYRIGHT_HEADER);
return (name) ? name : copyright_header;
}
/*
* rel_copyright_body - Copyright body fromt he message catalog
* return: static char string
*/
const char *
rel_copyright_body (void)
{
const char *name;
lang_init ();
name = msgcat_message (MSGCAT_CATALOG_CUBRID, MSGCAT_SET_GENERAL, MSGCAT_GENERAL_COPYRIGHT_BODY);
return (name) ? name : copyright_body;
}
#endif /* ENABLE_UNUSED_FUNCTION */
/*
* rel_disk_compatible - Disk compatibility level
* return:
*/
float
rel_disk_compatible (void)
{
return disk_compatibility_level;
}
/*
* rel_set_disk_compatible - Change disk compatibility level
* return: none
* level(in):
*/
void
rel_set_disk_compatible (float level)
{
disk_compatibility_level = level;
}
/*
* rel_platform - built platform
* return: none
* level(in):
*/
int
rel_bit_platform (void)
{
return bit_platform;
}
/*
* compatibility_rules - Static table of compatibility rules.
* Each time a change is made to the disk_compatibility_level
* a rule needs to be added to this table.
* If pair of numbers is absent from this table, the two are considered
* to be incompatible.
* {base_level (of database), apply_level (of system), compatibility, fix_func}
*/
static const COMPATIBILITY_RULE disk_compatibility_rules[] = {
/* a zero indicates the end of the table */
{{0, 0, 0}, {0, 0, 0}, REL_NOT_COMPATIBLE, NULL}
};
/*
* rel_get_disk_compatible - Test compatibility of disk (database image)
* Check a disk compatibility number stored in
* a database with the disk compatibility number
* for the system being run
* return: One of the three compatibility constants (REL_FULLY_COMPATIBLE,
* REL_FORWARD_COMPATIBLE, and REL_BACKWARD_COMPATIBLE) or
* REL_NOT_COMPATIBLE if they are not compatible
* db_level(in):
* REL_FIXUP_FUNCTION(in): function pointer table
*
* Note: The rules for compatibility are stored in the compatibility_rules
* table. Whenever the disk_compatibility_level variable is changed
* an entry had better be made in the table.
*/
REL_COMPATIBILITY
rel_get_disk_compatible (float db_level, REL_FIXUP_FUNCTION ** fixups)
{
const COMPATIBILITY_RULE *rule;
REL_COMPATIBILITY compat;
REL_FIXUP_FUNCTION *func;
func = NULL;
if (disk_compatibility_level == db_level)
{
compat = REL_FULLY_COMPATIBLE;
}
else
{
compat = REL_NOT_COMPATIBLE;
for (rule = &disk_compatibility_rules[0]; rule->base.major != 0 && compat == REL_NOT_COMPATIBLE; rule++)
{
float base_level, apply_level;
base_level = (float) (rule->base.major + (rule->base.minor / 10.0));
apply_level = (float) (rule->apply.major + (rule->apply.minor / 10.0));
if (base_level == db_level && apply_level == disk_compatibility_level)
{
compat = rule->compatibility;
func = rule->fix_function;
}
}
}
if (fixups != NULL)
{
*fixups = func;
}
return compat;
}
/* Compare release strings.
*
* Returns: < 0, if rel_a is earlier than rel_b
* == 0, if rel_a is the same as rel_b
* > 0, if rel_a is later than rel_b
*/
/*
* rel_compare - Compare release strings, A and B
* return: < 0, if rel_a is earlier than rel_b
* == 0, if rel_a is the same as rel_b
* > 0, if rel_a is later than rel_b
* rel_a(in): release string A
* rel_b(in): release string B
*
* Note:
*/
int
rel_compare (const char *rel_a, const char *rel_b)
{
int a, b, retval = 0;
char *a_temp, *b_temp, *end_p;
/*
* If we get a NULL for one of the values (and we shouldn't), guess that
* the versions are the same.
*/
if (!rel_a || !rel_b)
{
retval = 0;
}
else
{
/*
* Compare strings
*/
a_temp = (char *) rel_a;
b_temp = (char *) rel_b;
/*
* The following loop terminates if we determine that one string
* is greater than the other, or we reach the end of one of the
* strings.
*/
while (!retval && *a_temp && *b_temp)
{
str_to_int32 (&a, &end_p, a_temp, 10);
a_temp = end_p;
str_to_int32 (&b, &end_p, b_temp, 10);
b_temp = end_p;
if (a < b)
{
retval = -1;
}
else if (a > b)
{
retval = 1;
}
/*
* This skips over the '.'.
* This means that "?..?" will parse out to "?.?".
*/
while (*a_temp && *a_temp == '.')
{
a_temp++;
}
while (*b_temp && *b_temp == '.')
{
b_temp++;
}
if (*a_temp && *b_temp && char_isalpha (*a_temp) && char_isalpha (*b_temp))
{
if (*a_temp != *b_temp)
retval = -1;
a_temp++;
b_temp++;
}
}
if (!retval)
{
/*
* Both strings are the same up to this point. If the rest is zeros,
* they're still equal.
*/
while (*a_temp)
{
if (*a_temp != '.' && *a_temp != '0')
{
retval = 1;
break;
}
a_temp++;
}
while (*b_temp)
{
if (*b_temp != '.' && *b_temp != '0')
{
retval = -1;
break;
}
b_temp++;
}
}
}
return retval;
}
/*
* log compatibility matrix
*/
static const REL_VERSION log_incompatible_versions[] = {
{10, 0, 0},
/* PLEASE APPEND HERE versions that are incompatible with existing ones. */
/* NOTE that versions are kept as ascending order. */
/* zero indicates the end of the table */
{0, 0, 0}
};
/*
* rel_is_log_compatible - Test compatiblility of log file format
* return: true if compatible
* writer_rel_str(in): release string of the log writer (log file)
* reader_rel_str(in): release string of the log reader (system being run)
*/
bool
rel_is_log_compatible (const char *writer_rel_str, const char *reader_rel_str)
{
REL_COMPATIBILITY compat;
compat =
rel_get_compatible_internal (writer_rel_str, reader_rel_str, CHECK_LOG_COMPATIBILITY, log_incompatible_versions);
if (compat == REL_NOT_COMPATIBLE)
{
return false;
}
return true;
}
/*
* network compatibility matrix
*/
static const REL_VERSION net_incompatible_versions[] = {
{10, 0, 0},
/* PLEASE APPEND HERE versions that are incompatible with existing ones. */
/* NOTE that versions are kept as ascending order. */
/* zero indicates the end of the table */
{0, 0, 0}
};
/*
* rel_get_net_compatible - Compare the release strings from
* the server and client to determine compatibility.
* return: REL_COMPATIBILITY
* REL_NOT_COMPATIBLE if the client and the server are not compatible
* REL_FULLY_COMPATIBLE if the client and the server are compatible
* REL_FORWARD_COMPATIBLE if the client is forward compatible with the server
* if the server is backward compatible with the client
* the client is older than the server
* REL_BACKWARD_COMPATIBLE if the client is backward compatible with the server
* if the server is forward compatible with the client
* the client is newer than the server
*
* client_rel_str(in): client's release string
* server_rel_str(in): server's release string
*/
REL_COMPATIBILITY
rel_get_net_compatible (const char *client_rel_str, const char *server_rel_str)
{
return rel_get_compatible_internal (server_rel_str, client_rel_str, CHECK_NET_PROTOCOL_COMPATIBILITY,
net_incompatible_versions);
}
/*
* rel_get_compatible_internal - Compare the release to determine compatibility.
* return: REL_COMPATIBILITY
*
* base_rel_str(in): base release string (of database)
* apply_rel_str(in): applier's release string (of system)
* rules(in): rules to determine forward/backward compatibility
*/
static REL_COMPATIBILITY
rel_get_compatible_internal (const char *base_rel_str, const char *apply_rel_str, COMPATIBILITY_CHECK_MODE check,
const REL_VERSION versions[])
{
const REL_VERSION *version, *base_version, *apply_version;
char *base, *apply, *str_a, *str_b;
int val;
unsigned char base_major, base_minor, apply_major, apply_minor;
unsigned short base_patch, apply_patch;
if (apply_rel_str == NULL || base_rel_str == NULL)
{
return REL_NOT_COMPATIBLE;
}
/* release string should be in the form of <major>.<minor>[.<patch>] */
/* check major number */
str_to_int32 (&val, &str_a, apply_rel_str, 10);
apply_major = (unsigned char) val;
str_to_int32 (&val, &str_b, base_rel_str, 10);
base_major = (unsigned char) val;
if (apply_major == 0 || base_major == 0)
{
return REL_NOT_COMPATIBLE;
}
/* skip '.' */
while (*str_a && *str_a == '.')
{
str_a++;
}
while (*str_b && *str_b == '.')
{
str_b++;
}
/* check minor number */
apply = str_a;
base = str_b;
str_to_int32 (&val, &str_a, apply, 10);
apply_minor = (unsigned char) val;
str_to_int32 (&val, &str_b, base, 10);
base_minor = (unsigned char) val;
/* skip '.' */
while (*str_a && *str_a == '.')
{
str_a++;
}
while (*str_b && *str_b == '.')
{
str_b++;
}
if (check == CHECK_NET_PROTOCOL_COMPATIBILITY)
{
if (apply_major != base_major)
{
return REL_NOT_COMPATIBLE;
}
if (apply_minor != base_minor)
{
return REL_NOT_COMPATIBLE;
}
}
/* check patch number */
apply = str_a;
base = str_b;
str_to_int32 (&val, &str_a, apply, 10);
apply_patch = (unsigned short) val;
str_to_int32 (&val, &str_b, base, 10);
base_patch = (unsigned short) val;
if (apply_major == base_major && apply_minor == base_minor && apply_patch == base_patch)
{
return REL_FULLY_COMPATIBLE;
}
base_version = NULL;
apply_version = NULL;
for (version = &versions[0]; version->major != 0; version++)
{
if (base_major >= version->major && base_minor >= version->minor && base_patch >= version->patch)
{
base_version = version;
}
if (apply_major >= version->major && apply_minor >= version->minor && apply_patch >= version->patch)
{
apply_version = version;
}
}
if (base_version == NULL || apply_version == NULL || base_version != apply_version)
{
return REL_NOT_COMPATIBLE;
}
else
{
return REL_FULLY_COMPATIBLE;
}
}