static void log_cfg_set_default(void *module_config) { log_config_t *conf = (log_config_t *) module_config; conf->debug_level = LVL_EVENT; rh_strncpy(conf->log_file, "/var/log/robinhood.log", RBH_PATH_MAX); rh_strncpy(conf->report_file, "/var/log/robinhood_actions.log", RBH_PATH_MAX); rh_strncpy(conf->alert_file, "/var/log/robinhood_alerts.log", 1024); conf->alert_mail[0] = '\0'; #ifdef HAVE_CHANGELOGS conf->changelogs_file[0] = '\0'; #endif conf->syslog_facility = LOG_LOCAL1; conf->syslog_priority = LOG_INFO; conf->batch_alert_max = 1; /* no batching */ conf->alert_show_attrs = false; conf->stats_interval = 900; /* 15min */ conf->log_process = 0; conf->log_host = 0; }
static int log_cfg_set(void *cfg, bool reload) { log_config_t *config = (log_config_t *) cfg; char old_log_file[RBH_PATH_MAX] = ""; int old_level = -1; if (reload) return log_cfg_reload(config); /* keep previous values in case log level is forced */ if (log_config.force_debug_level) old_level = log_config.debug_level; if (log_config.force_log_file) rh_strncpy(old_log_file, log_config.log_file, sizeof(old_log_file)); log_config = *config; /* restore previous values */ if (old_level != -1) { log_config.force_debug_level = true; log_config.debug_level = old_level; } if (!EMPTY_STRING(old_log_file)) { log_config.force_log_file = true; rh_strncpy(log_config.log_file, old_log_file, sizeof(log_config.log_file)); } return 0; }
int InitializeLogs(const char *program_name) { struct utsname uts; char *tmp; int rc; /* get node name */ if (uname(&uts) == -1) strcpy(machine_name, "???"); else rh_strncpy(machine_name, uts.nodename, RBH_PATH_MAX); /* if the name is the full machine name (node.subnet.domain.ext), * only kief the brief name */ if ((tmp = strchr(machine_name, '.')) != NULL) *tmp = '\0'; if (program_name == NULL) strcpy(prog_name, "???"); else rh_strncpy(prog_name, program_name, RBH_PATH_MAX); /* open log files */ rc = init_log_descr(log_config.log_file, &log); if (rc) return rc; rc = init_log_descr(log_config.report_file, &report); if (rc) return rc; if (!EMPTY_STRING(log_config.alert_file)) { rc = init_log_descr(log_config.alert_file, &alert); if (rc) return rc; } #ifdef HAVE_CHANGELOGS if (!EMPTY_STRING(log_config.changelogs_file)) { rc = init_log_descr(log_config.changelogs_file, &chglogs); if (rc) return rc; } #endif /* Update log level for external components we get logs from (LLAPI...) */ rbh_adjust_log_level_external(); last_time_test = time(NULL); log_initialized = true; return 0; } /* InitializeLogs */
static int parse_bk_id(attr_set_t *attrs, const char *str, entry_id_t *id, bool *id_set) { char attr[128]; char *val; int rc; val = strchr(str, '='); if (!val) { fprintf(stderr, "Invalid attr format '%s': expected <attr>=<value>\n", str); return -EINVAL; } rh_strncpy(attr, str, MIN2(val - str + 1, sizeof(attr))); val++; if (!strcasecmp(attr, "id") || !strcasecmp(attr, "fid")) { rc = read_fid(val, id); if (rc == 0 && id_set) *id_set = true; return rc; } rc = set_attr_value_from_strings(attr, val, attrs, smi); return rc; }
/* This code is an adaptation of llapi_mds_getfileinfo() in liblustreapi. * It is unused for now, but could be useful when SOM will be implemented. */ int lustre_mds_stat(char *fullpath, int parentfd, struct stat *inode) { /* this buffer must be large enough for handling filename */ char buffer[1024]; struct lov_user_mds_data *lmd = ( struct lov_user_mds_data * ) buffer; char *filename; int rc; /* sanity checks */ if ((fullpath == NULL) || (inode == NULL)) return EINVAL; filename = basename( fullpath ); if ( filename == NULL ) filename = fullpath; memset(lmd, 0, sizeof(buffer)); rh_strncpy(buffer, filename, strlen(filename) + 1); rc = ioctl(parentfd, IOC_MDC_GETFILEINFO, (void *)lmd); if ( rc ) { if ( errno == ENOTTY ) { /* ioctl is not supported, it is not a lustre fs. * Do the regular lstat(2) instead. */ rc = lstat( fullpath, inode ); if ( rc ) { DisplayLog( LVL_CRIT, TAG_MDSSTAT, "Error: %s: lstat failed for %s", __FUNCTION__, fullpath ); return rc; } } else if ( ( errno == ENOENT ) || ( errno == ESTALE ) ) { DisplayLog( LVL_MAJOR, TAG_MDSSTAT, "Warning: %s: %s does not exist", __FUNCTION__, fullpath ); return ENOENT; } else { DisplayLog(LVL_CRIT, TAG_MDSSTAT, "Error: %s: IOC_MDC_GETFILEINFO failed for %s: rc=%d, errno=%d", __FUNCTION__, fullpath, rc, errno); return rc; } } else *inode = lmd->lmd_st; return 0; }
int SetDefaultGlobalConfig( void *module_config, char *msg_out ) { global_config_t *conf = ( global_config_t * ) module_config; msg_out[0] = '\0'; rh_strncpy(conf->fs_path, "", RBH_PATH_MAX); #ifdef _HAVE_FID rh_strncpy(conf->fs_type, "lustre", FILENAME_MAX); #else rh_strncpy(conf->fs_type, "", FILENAME_MAX); #endif rh_strncpy(conf->lock_file, "/var/locks/robinhood.lock", RBH_PATH_MAX); conf->stay_in_fs = TRUE; conf->check_mounted = TRUE; conf->fs_key = FSKEY_FSNAME; #if defined( _LUSTRE ) && defined( _MDS_STAT_SUPPORT ) conf->direct_mds_stat = FALSE; #endif return 0; }
/* retrieve error message */ char *db_errmsg( db_conn_t * conn, char *errmsg, unsigned int buflen ) { if ( *conn == NULL ) { strcpy( errmsg, "Connection not initialized" ); return errmsg; } if ( strlen( sqlite3_errmsg( *conn ) ) + 1 > buflen ) rh_strncpy(errmsg, sqlite3_errmsg(*conn), buflen); else strcpy( errmsg, sqlite3_errmsg( *conn ) ); return errmsg; }
static void no_name_warning(PK_PARG_T pk, attr_set_t *p_attrs, unsigned int count) { DEF_PK(ppk); char msg[256]; entry_id2pk(&ATTR(p_attrs, parent_id), PTR_PK(ppk)); if (count > 1) snprintf(msg, sizeof(msg), "%u entries", count); else rh_strncpy(msg, "entry", sizeof(msg)); DisplayLog(LVL_MAJOR, LISTMGR_TAG, "WARNING: %s created without" " name or parent information: pk="DPK", name='%s', parent='%s'", msg, pk, ATTR_MASK_TEST(p_attrs, name) ? ATTR(p_attrs, name) : "", ATTR_MASK_TEST(p_attrs, parent_id) ? ppk : ""); }
/* check syslog facility name. * keep p_level unchanged if not specified. */ static int check_syslog_facility(const char *descriptor, int *p_fac, int *p_level) { char descr_cp[256]; char *curr; int i; bool match; rh_strncpy(descr_cp, descriptor, 256); curr = strchr(descr_cp, '.'); if (curr != NULL) { curr[0] = '\0'; curr++; /* location of syslog level */ } match = false; for (i = 0; facilitynames[i].c_name != NULL; i++) { if (!strcasecmp(facilitynames[i].c_name, descr_cp)) { if (p_fac) *p_fac = facilitynames[i].c_val; match = true; break; } } if (!match) return ENOENT; if (curr != NULL) { /* now doing the same for priority */ match = false; for (i = 0; prioritynames[i].c_name != NULL; i++) { if (!strcasecmp(prioritynames[i].c_name, curr)) { if (p_level) *p_level = prioritynames[i].c_val; match = true; break; } } if (!match) return ENOENT; } return 0; }
/* Helper function to parse int escape codes (\NNN octal or \xHH hex) * return the number of bytes read in str, or -1 if need a go-again for 0 */ static int parse_escaped_int(const char *str, struct fchunk *chunk, int base) { long int print_val; char value_string[4], *endptr; int numread; if (base == 8) { numread = 3; } else if (base == 16) { numread = 2; } else { RBH_BUG("Error: invalid base"); } /* copy next few chars and try to read as int */ rh_strncpy(value_string, str, numread+1); /* +1 for final '\0' */ print_val = strtol(value_string, &endptr, base); if (endptr == value_string) { /* invalid hex */ return 0; } /* printf will copy any byte we put in format string unchanged, * except for '\0' and '%'. * '\0' is handled as a directive since printf will stop on a 0-byte * even with a length specifier */ if (print_val == 0) { /* if chunk->directive is already set, request a new chunk and * parse this again */ if (chunk->directive) return -1; g_string_append(chunk->format, "%c"); chunk->directive = 'z'; } else if ((char)print_val == '%') { g_string_append(chunk->format, "%%"); } else { /* printf-agnostic character */ g_string_append_c(chunk->format, (char)print_val); } return endptr - value_string; }
int update_stripe_info(lmgr_t *p_mgr, PK_ARG_T pk, int validator, const stripe_info_t *p_stripe, const stripe_items_t *p_items, bool insert_if_absent) { attr_set_t fake_attr; attr_set_t *p_attr = &fake_attr; pktype list[1]; rh_strncpy(list[0], pk, sizeof(*list)); ATTR_MASK_INIT(&fake_attr); if (p_stripe) { ATTR_MASK_SET(&fake_attr, stripe_info); ATTR(&fake_attr, stripe_info) = *p_stripe; } if (p_items) { ATTR_MASK_SET(&fake_attr, stripe_items); ATTR(&fake_attr, stripe_items) = *p_items; } return batch_insert_stripe_info(p_mgr, list, &validator, &p_attr, 1, true); }
char *FormatStripeList(char *buff, size_t sz, const stripe_items_t *p_stripe_items, bool brief) { unsigned int i; size_t written = 0; const char * format; if ( !p_stripe_items || ( p_stripe_items->count == 0 ) ) { rh_strncpy(buff, "(none)", sz); return buff; } buff[0] = '\0'; for ( i = 0; i < p_stripe_items->count; i++ ) { if ( i != p_stripe_items->count - 1 ) { if (brief) format = "ost#%u:%u, "; else format = "ost#%u: %u, "; } else { if (brief) format = "ost#%u:%u"; else format = "ost#%u: %u"; } written += snprintf( ( char * ) ( buff + written ), sz - written, format, p_stripe_items->stripe[i].ost_idx, p_stripe_items->stripe[i].obj_id ); } buff[sz-1] = '\0'; return buff; }
/** * Main daemon routine */ int main( int argc, char **argv ) { int c, option_index = 0; char *bin = basename( argv[0] ); char config_file[MAX_OPT_LEN] = ""; int force_log_level = FALSE; int log_level = 0; int rc; int chgd = 0; char err_msg[4096]; int neg = 0; char badcfg[RBH_PATH_MAX]; /* parse command line options */ while ((c = getopt_long_only(argc, argv, SHORT_OPT_STRING, option_tab, &option_index )) != -1) { switch ( c ) { case '!': neg = 1; break; case 'u': toggle_option(match_user, "user"); prog_options.user = optarg; prog_options.userneg = neg; neg = 0; break; case 'g': toggle_option(match_group, "group"); prog_options.group = optarg; prog_options.groupneg = neg; neg = 0; break; case 'U': /* match numerical (non resolved) users */ toggle_option(match_user, "user"); prog_options.user = "******"; prog_options.userneg = neg; neg = 0; break; case 'G': /* match numerical (non resolved) groups */ toggle_option(match_group, "group"); prog_options.group = "[0-9]*"; prog_options.groupneg = neg; neg = 0; break; case 'n': toggle_option(match_name, "name"); prog_options.name = optarg; prog_options.nameneg = neg; neg = 0; break; #ifdef _LUSTRE case 'o': toggle_option(match_ost, "ost"); prog_options.ost_idx = str2int(optarg); if (prog_options.ost_idx == (unsigned int)-1) { fprintf(stderr, "invalid ost index '%s': unsigned integer expected\n", optarg); exit(1); } if (neg) { fprintf(stderr, "! () is not supported for ost criteria\n"); exit(1); } break; case 'P': toggle_option(match_pool, "pool"); prog_options.pool = optarg; break; case 'O': prog_options.lsost = 1; prog_options.print = 0; disp_mask |= LSOST_DISPLAY_MASK; if (neg) { fprintf(stderr, "! (-not) unexpected before -lsost option\n"); exit(1); } break; #endif case 't': toggle_option(match_type, "type"); prog_options.type = opt2type(optarg); if (prog_options.type == NULL) { fprintf(stderr, "invalid type '%s': expected types: "TYPE_HELP".\n", optarg); exit(1); } if (neg) { fprintf(stderr, "! (-not) is not supported for type criteria\n"); exit(1); } break; case 's': toggle_option(match_size, "size"); if (set_size_filter(optarg)) exit(1); if (neg) { fprintf(stderr, "! (-not) is not supported for size criteria\n"); exit(1); } break; case 'A': toggle_option(match_atime, "atime/amin"); if (set_time_filter(optarg, 0, TRUE, atime)) exit(1); if (neg) { fprintf(stderr, "! (-not) is not supported for time criteria\n"); exit(1); } break; case 'a': toggle_option(match_atime, "atime/amin"); if (set_time_filter(optarg, 60, TRUE, atime)) exit(1); if (neg) { fprintf(stderr, "! (-not) is not supported for time criteria\n"); exit(1); } break; case 'C': toggle_option(match_crtime, "crtime"); if (set_time_filter(optarg, 0, TRUE, rh_crtime)) exit(1); if (neg) { fprintf(stderr, "! (-not) is not supported for time criteria\n"); exit(1); } break; case 'M': toggle_option(match_mtime, "mtime/mmin/msec"); if (set_time_filter(optarg, 0, TRUE, mtime)) exit(1); if (neg) { fprintf(stderr, "! (-not) is not supported for time criteria\n"); exit(1); } break; case 'm': toggle_option(match_mtime, "mtime/mmin/msec"); if (set_time_filter(optarg, 60, FALSE, mtime)) /* don't allow suffix (multiplier is 1min) */ exit(1); if (neg) { fprintf(stderr, "! (-not) is not supported for time criteria\n"); exit(1); } break; case 'z': toggle_option(match_mtime, "mtime/mmin/msec"); if (set_time_filter(optarg, 1, FALSE, mtime)) /* don't allow suffix (multiplier is 1sec) */ exit(1); if (neg) { fprintf(stderr, "! (-not) is not supported for time criteria\n"); exit(1); } break; #ifdef ATTR_INDEX_status case 'S': toggle_option(match_status, "status"); prog_options.status = status2dbval(optarg); if ( prog_options.status == (file_status_t)-1 ) { fprintf(stderr, "Unknown status '%s'. Allowed status: %s.\n", optarg, allowed_status()); exit(1); } prog_options.statusneg = neg; neg = 0; break; #endif case 'l': prog_options.ls = 1; prog_options.print = 0; disp_mask |= LS_DISPLAY_MASK; if (neg) { fprintf(stderr, "! (-not) unexpected before -ls option\n"); exit(1); } break; case 'p': prog_options.print = 1; disp_mask |= LS_DISPLAY_MASK; if (neg) { fprintf(stderr, "! (-not) unexpected before -ls option\n"); exit(1); } break; case 'E': toggle_option(exec, "exec"); prog_options.exec_cmd = optarg; prog_options.print = 0; break; case 'f': rh_strncpy(config_file, optarg, MAX_OPT_LEN); if (neg) { fprintf(stderr, "! (-not) unexpected before -f option\n"); exit(1); } break; case 'd': force_log_level = TRUE; log_level = str2debuglevel( optarg ); if ( log_level == -1 ) { fprintf(stderr, "Unsupported log level '%s'. CRIT, MAJOR, EVENT, VERB, DEBUG or FULL expected.\n", optarg); exit(1); } if (neg) { fprintf(stderr, "! (-not) unexpected before -d option\n"); exit(1); } break; case 'b': prog_options.bulk = force_nobulk; break; case 'h': display_help( bin ); exit( 0 ); break; case 'V': display_version( bin ); exit( 0 ); break; case ':': case '?': default: display_help( bin ); exit( 1 ); break; } } /* get default config file, if not specified */ if (SearchConfig(config_file, config_file, &chgd, badcfg, MAX_OPT_LEN) != 0) { fprintf(stderr, "No config file (or too many) found matching %s\n", badcfg); exit(2); } else if (chgd) { fprintf(stderr, "Using config file '%s'.\n", config_file ); } /* only read ListMgr config */ if ( ReadRobinhoodConfig( 0, config_file, err_msg, &config, FALSE ) ) { fprintf( stderr, "Error reading configuration file '%s': %s\n", config_file, err_msg ); exit( 1 ); } process_config_file = config_file; /* set global configuration */ global_config = config.global_config; /* set policies info */ policies = config.policies; if ( force_log_level ) config.log_config.debug_level = log_level; else config.log_config.debug_level = LVL_MAJOR; /* no event message */ /* Set logging to stderr */ strcpy( config.log_config.log_file, "stderr" ); strcpy( config.log_config.report_file, "stderr" ); strcpy( config.log_config.alert_file, "stderr" ); /* Initialize logging */ rc = InitializeLogs( bin, &config.log_config ); if ( rc ) { fprintf( stderr, "Error opening log files: rc=%d, errno=%d: %s\n", rc, errno, strerror( errno ) ); exit( rc ); } /* Initialize filesystem access */ rc = InitFS(); if (rc) exit(rc); /* Initialize list manager */ rc = ListMgr_Init( &config.lmgr_config, TRUE ); if ( rc ) { DisplayLog( LVL_CRIT, FIND_TAG, "Error %d initializing list manager", rc ); exit( rc ); } else DisplayLog( LVL_DEBUG, FIND_TAG, "ListManager successfully initialized" ); if (CheckLastFS( ) != 0) exit(1); /* Create database access */ rc = ListMgr_InitAccess(&lmgr); if (rc) { DisplayLog( LVL_CRIT, FIND_TAG, "Error %d: cannot connect to database", rc ); exit(rc); } if (argc == optind) { /* no argument: default is root * => switch to bulk mode (unless nobulk is specified) */ if (prog_options.bulk != force_nobulk) { DisplayLog(LVL_DEBUG, FIND_TAG, "Optimization: switching to bulk DB request mode"); mkfilters(FALSE); /* keep dirs */ return list_bulk(); } else { char *id = config.global_config.fs_path; mkfilters(TRUE); /* exclude dirs */ /* no path specified, list all entries */ rc = list_contents(&id, 1); } } else { mkfilters(TRUE); /* exclude dirs */ rc = list_contents(argv+optind, argc-optind); } ListMgr_CloseAccess( &lmgr ); return rc; }
/** * Main daemon routine */ int main(int argc, char **argv) { int c, option_index = 0; const char *bin; char config_file[MAX_OPT_LEN] = ""; bool do_start = false; bool do_reset = false; bool do_resume = false; bool do_complete = false; bool do_status = false; int list_state = -1; int local_flags = 0; int rc; char err_msg[4096]; robinhood_config_t config; struct sigaction act_sigterm; int chgd = 0; char badcfg[RBH_PATH_MAX]; bin = rh_basename(argv[0]); /* supports NULL argument */ /* parse command line options */ while ((c = getopt_long(argc, argv, SHORT_OPT_STRING, option_tab, &option_index)) != -1) { switch (c) { case 'S': do_start = true; break; case 's': do_status = true; break; case 'Z': do_reset = true; break; case 'c': do_complete = true; break; case 'r': do_resume = true; break; case 'L': if (!strcasecmp(optarg, "all")) list_state = RT_ALL; else if (!strcasecmp(optarg, "done")) list_state = RT_DONE; else if (!strcasecmp(optarg, "failed")) list_state = RT_FAILED; else if (!strcasecmp(optarg, "todo")) list_state = RT_TODO; else { fprintf(stderr, "Invalid parameter for option --list: all, done, failed or todo expected.\n"); exit(1); } break; case 'e': local_flags |= RETRY_ERRORS; break; case 'y': local_flags |= NO_CONFIRM; break; case 'f': rh_strncpy(config_file, optarg, MAX_OPT_LEN); break; case 'D': if (!optarg) { fprintf(stderr, "Missing mandatory argument <path> for --dir\n"); exit(1); } else { rh_strncpy(path_buff, optarg, MAX_OPT_LEN); path_filter = path_buff; } break; case 'o': if (!optarg) { fprintf(stderr, "Missing mandatory argument <ost_index> for --ost\n"); exit(1); } /* parse it as a set */ if (lmgr_range2list(optarg, DB_UINT, &ost_list)) { fprintf(stderr, "Invalid value '%s' for --ost option: integer or set expected (e.g. 2 or 3,5-8,10-12).\n", optarg); exit(1); } /* copy arg to display it */ rh_strncpy(ost_range_str, optarg, sizeof(ost_range_str)); break; case 'b': if (!optarg) { fprintf(stderr, "Missing mandatory argument <date_time> for --since\n"); exit(1); } since_time = str2date(optarg); if (since_time == (time_t)-1) { fprintf(stderr, "Invalid date format: yyyymmdd[HH[MM[SS]]] expected\n"); exit(1); } break; case 'l': { int log_level = str2debuglevel(optarg); if (log_level == -1) { fprintf(stderr, "Unsupported log level '%s'. CRIT, MAJOR, EVENT, VERB, DEBUG or FULL expected.\n", optarg); exit(1); } force_debug_level(log_level); break; } case 'h': display_help(bin); exit(0); break; case 'V': display_version(bin); exit(0); break; case ':': case '?': default: display_help(bin); exit(1); break; } } /* check there is no extra arguments */ if (optind != argc) { fprintf(stderr, "Error: unexpected argument on command line: %s\n", argv[optind]); exit(1); } rc = rbh_init_internals(); if (rc != 0) exit(rc); /* get default config file, if not specified */ if (SearchConfig(config_file, config_file, &chgd, badcfg, MAX_OPT_LEN) != 0) { fprintf(stderr, "No config file (or too many) found matching %s\n", badcfg); exit(2); } else if (chgd) { fprintf(stderr, "Using config file '%s'.\n", config_file); } /* only read ListMgr config */ if (ReadRobinhoodConfig(0, config_file, err_msg, &config, false)) { fprintf(stderr, "Error reading configuration file '%s': %s\n", config_file, err_msg); exit(1); } /* XXX HOOK: Set logging to stderr */ strcpy(config.log_config.log_file, "stderr"); strcpy(config.log_config.report_file, "stderr"); strcpy(config.log_config.alert_file, "stderr"); /* Initialize logging */ rc = InitializeLogs(bin, &config.log_config); if (rc) { fprintf(stderr, "Error opening log files: rc=%d, errno=%d: %s\n", rc, errno, strerror(errno)); exit(rc); } /* Initialize filesystem access */ rc = InitFS(); if (rc) exit(rc); /* Initialize status managers (XXX all or just the one used for * recovery?) */ rc = smi_init_all(options.flags); if (rc) exit(rc); /* Initialize list manager */ rc = ListMgr_Init(0); if (rc) { DisplayLog(LVL_CRIT, RECOV_TAG, "Error initializing list manager: %s (%d)", lmgr_err2str(rc), rc); exit(rc); } else DisplayLog(LVL_DEBUG, RECOV_TAG, "ListManager successfully initialized"); if (CheckLastFS() != 0) exit(1); /* Create database access */ rc = ListMgr_InitAccess(&lmgr); if (rc) { DisplayLog(LVL_CRIT, RECOV_TAG, "Error %d: cannot connect to database", rc); exit(rc); } #ifdef _HSM_LITE rc = Backend_Start(&config.backend_config, 0); if (rc) { DisplayLog(LVL_CRIT, RECOV_TAG, "Error initializing backend"); exit(1); } #endif /* create signal handlers */ memset(&act_sigterm, 0, sizeof(act_sigterm)); act_sigterm.sa_flags = 0; act_sigterm.sa_handler = terminate_handler; if (sigaction(SIGTERM, &act_sigterm, NULL) == -1 || sigaction(SIGINT, &act_sigterm, NULL) == -1) { DisplayLog(LVL_CRIT, RECOV_TAG, "Error while setting signal handlers for SIGTERM and SIGINT: %s", strerror(errno)); exit(1); } else DisplayLog(LVL_VERB, RECOV_TAG, "Signals SIGTERM and SIGINT (abort command) are ready to be used"); if (do_status) rc = recov_status(); else if (list_state != -1) rc = recov_list(list_state); else if (do_start) rc = recov_start(); else if (do_reset) rc = recov_reset(local_flags & NO_CONFIRM); else if (do_resume) rc = recov_resume(local_flags & RETRY_ERRORS); else if (do_complete) rc = recov_complete(); else { display_help(bin); rc = 1; } ListMgr_CloseAccess(&lmgr); return rc; }
/** * Main daemon routine */ int main(int argc, char **argv) { int c, option_index = 0; const char *bin; char config_file[MAX_OPT_LEN] = ""; int rc; char err_msg[4096]; robinhood_config_t config; int chgd = 0; char badcfg[RBH_PATH_MAX]; bin = rh_basename(argv[0]); /* parse command line options */ while ((c = getopt_long(argc, argv, SHORT_OPT_STRING, option_tab, &option_index)) != -1) { switch (c) { case 'f': rh_strncpy(config_file, optarg, MAX_OPT_LEN); break; case 'l': { int log_level = str2debuglevel(optarg); if (log_level == -1) { fprintf(stderr, "Unsupported log level '%s'. CRIT, MAJOR, EVENT, VERB, DEBUG or FULL expected.\n", optarg); exit(1); } force_debug_level(log_level); break; } case 'h': display_help(bin); exit(0); break; case 'V': display_version(bin); exit(0); break; case ':': case '?': default: display_help(bin); exit(1); break; } } /* 2 expected argument: old backend path, new path is FS */ if (optind > argc - 2) { fprintf(stderr, "Error: missing arguments on command line.\n"); display_help(bin); exit(1); } else if (optind < argc - 3) { fprintf(stderr, "Error: too many arguments on command line.\n"); display_help(bin); exit(1); } /* get default config file, if not specified */ if (SearchConfig(config_file, config_file, &chgd, badcfg, MAX_OPT_LEN) != 0) { fprintf(stderr, "No config file (or too many) found matching %s\n", badcfg); exit(2); } else if (chgd) { fprintf(stderr, "Using config file '%s'.\n", config_file); } rc = rbh_init_internals(); if (rc != 0) exit(rc); /* only read ListMgr config */ if (ReadRobinhoodConfig(0, config_file, err_msg, &config, false)) { fprintf(stderr, "Error reading configuration file '%s': %s\n", config_file, err_msg); exit(1); } /* XXX HOOK: Set logging to stderr */ strcpy(config.log_config.log_file, "stderr"); strcpy(config.log_config.report_file, "stderr"); strcpy(config.log_config.alert_file, "stderr"); /* Initialize logging */ rc = InitializeLogs(bin, &config.log_config); if (rc) { fprintf(stderr, "Error opening log files: rc=%d, errno=%d: %s\n", rc, errno, strerror(errno)); exit(rc); } /* Initialize Filesystem access */ rc = InitFS(); if (rc) exit(rc); /* Initialize status managers (XXX all or just the one used for rebind?) */ rc = smi_init_all(options.flags); if (rc) exit(rc); #ifdef _HSM_LITE rc = Backend_Start(&config.backend_config, 0); if (rc) { DisplayLog(LVL_CRIT, LOGTAG, "Error initializing backend"); exit(1); } #endif if (optind == argc - 2) rc = rebind_helper(argv[optind], argv[optind + 1], NULL); else if (optind == argc - 3) rc = rebind_helper(argv[optind], argv[optind + 1], argv[optind + 2]); return rc; }
int ReadLmgrConfig( config_file_t config, void *module_config, char *msg_out, int for_reload ) { int rc; lmgr_config_t *conf = ( lmgr_config_t * ) module_config; char **options = NULL; unsigned int nb_options = 0; char tmpstr[1024]; config_item_t db_block; static const char *lmgr_allowed[] = { "commit_behavior", "connect_retry_interval_min", "connect_retry_interval_max", "user_acct", "group_acct", MYSQL_CONFIG_BLOCK, SQLITE_CONFIG_BLOCK, NULL }; #ifdef _MYSQL static const char *db_allowed[] = { "server", "db", "user", "password", "password_file", "port", "socket", "innodb", NULL }; #elif defined (_SQLITE) static const char *db_allowed[] = { "db_file", "retry_delay_microsec", NULL }; #endif /* get ListManager block */ config_item_t lmgr_block = rh_config_FindItemByName( config, LMGR_CONFIG_BLOCK ); if ( lmgr_block == NULL ) { strcpy( msg_out, "Missing configuration block '" LMGR_CONFIG_BLOCK "'" ); return ENOENT; } if ( rh_config_ItemType( lmgr_block ) != CONFIG_ITEM_BLOCK ) { strcpy( msg_out, "A block is expected for '" LMGR_CONFIG_BLOCK "' item" ); return EINVAL; } /* retrieve parameters */ /* 1) commit_behavior */ rc = GetStringParam( lmgr_block, LMGR_CONFIG_BLOCK, "commit_behavior", STR_PARAM_NO_WILDCARDS, tmpstr, 1024, &options, &nb_options, msg_out ); if ( ( rc != 0 ) && ( rc != ENOENT ) ) return rc; else if ( rc != ENOENT ) { if ( !strcasecmp( tmpstr, "autocommit" ) ) conf->commit_behavior = 0; else if ( !strcasecmp( tmpstr, "transaction" ) ) conf->commit_behavior = 1; else if ( !strcasecmp( tmpstr, "periodical" ) /* for backward compatibility */ || !strcasecmp( tmpstr, "periodic" ) ) { if ( ( nb_options != 1 ) || !options || !options[0] ) { strcpy( msg_out, "A single argument is expected for periodic commit behavior. Eg: commit_behavior = periodic(1000)" ); return EINVAL; } conf->commit_behavior = atoi( options[0] ); if ( conf->commit_behavior == 0 ) { strcpy( msg_out, "The argument for \"" LMGR_CONFIG_BLOCK "::commit_behavior = periodical\" must be a positive integer. Eg: commit_behavior = periodic(1000)" ); return EINVAL; } } else { sprintf( msg_out, "Invalid commit behavior '%s' (expected: autocommit, " "transaction, periodic(<count>))", tmpstr ); return EINVAL; } } /* 2) connect_retry_interval_min and connect_retry_interval_max */ rc = GetDurationParam( lmgr_block, LMGR_CONFIG_BLOCK, "connect_retry_interval_min", INT_PARAM_POSITIVE | INT_PARAM_NOT_NULL, ( int * ) &conf->connect_retry_min, NULL, NULL, msg_out ); if ( ( rc != 0 ) && ( rc != ENOENT ) ) return rc; rc = GetDurationParam( lmgr_block, LMGR_CONFIG_BLOCK, "connect_retry_interval_max", INT_PARAM_POSITIVE | INT_PARAM_NOT_NULL, ( int * ) &conf->connect_retry_max, NULL, NULL, msg_out ); if ( ( rc != 0 ) && ( rc != ENOENT ) ) return rc; /* 3) ACCT configuration*/ rc = GetBoolParam( lmgr_block, LMGR_CONFIG_BLOCK, "user_acct", 0, &conf->user_acct, NULL, NULL, msg_out); if ( ( rc != 0 ) && ( rc != ENOENT ) ) return rc; rc = GetBoolParam( lmgr_block, LMGR_CONFIG_BLOCK, "group_acct", 0, &conf->group_acct, NULL, NULL, msg_out); if ( ( rc != 0 ) && ( rc != ENOENT ) ) return rc; CheckUnknownParameters( lmgr_block, LMGR_CONFIG_BLOCK, lmgr_allowed ); /* Database specific parameters */ #ifdef _MYSQL /* get MySQL block */ db_block = rh_config_GetItemByName( lmgr_block, MYSQL_CONFIG_BLOCK ); if ( db_block == NULL ) { strcpy( msg_out, "Missing configuration block '" LMGR_CONFIG_BLOCK "::" MYSQL_CONFIG_BLOCK "'" ); return ENOENT; } if ( rh_config_ItemType( db_block ) != CONFIG_ITEM_BLOCK ) { sprintf( msg_out, "A block is expected for '" LMGR_CONFIG_BLOCK "::" MYSQL_CONFIG_BLOCK "' item, line %d", rh_config_GetItemLine( db_block ) ); return EINVAL; } rc = GetStringParam( db_block, MYSQL_CONFIG_BLOCK, "server", STR_PARAM_NO_WILDCARDS, conf->db_config.server, 256, NULL, NULL, msg_out ); if ( ( rc != 0 ) && ( rc != ENOENT ) ) return rc; rc = GetStringParam( db_block, MYSQL_CONFIG_BLOCK, "db", PARAM_MANDATORY | STR_PARAM_NO_WILDCARDS, conf->db_config.db, 256, NULL, NULL, msg_out ); if ( rc ) return rc; rc = GetStringParam( db_block, MYSQL_CONFIG_BLOCK, "user", STR_PARAM_NO_WILDCARDS, conf->db_config.user, 256, NULL, NULL, msg_out ); if ( ( rc != 0 ) && ( rc != ENOENT ) ) return rc; rc = GetStringParam( db_block, MYSQL_CONFIG_BLOCK, "password", 0, conf->db_config.password, 256, NULL, NULL, msg_out ); if ( ( rc != 0 ) && ( rc != ENOENT ) ) return rc; else if ( rc == ENOENT ) { FILE *passfile; char errstr[1024]; rc = GetStringParam( db_block, MYSQL_CONFIG_BLOCK, "password_file", STR_PARAM_ABSOLUTE_PATH | STR_PARAM_NO_WILDCARDS, tmpstr, 1024, NULL, NULL, msg_out ); if ( ( rc != 0 ) && ( rc != ENOENT ) ) return rc; else if ( rc == ENOENT ) { strcpy( msg_out, MYSQL_CONFIG_BLOCK "::password or " MYSQL_CONFIG_BLOCK "::password_file must be provided" ); return ENOENT; } /* read password file and @TODO check its rights */ passfile = fopen( tmpstr, "r" ); if ( !passfile ) { rc = errno; sprintf( msg_out, "Error opening password file %s : %s", tmpstr, strerror(errno) ); return rc; } fscanf( passfile, "%1024s", tmpstr ); if ( ferror( passfile ) ) { rc = errno; strerror_r( rc, errstr, 1024 ); sprintf( msg_out, "Error reading password file %s : %s", tmpstr, errstr ); return rc; } fclose( passfile ); rh_strncpy(conf->db_config.password, tmpstr, 256); } rc = GetIntParam( db_block, MYSQL_CONFIG_BLOCK, "port", INT_PARAM_POSITIVE | INT_PARAM_NOT_NULL, (int*)&conf->db_config.port, NULL, NULL, msg_out ); if ( ( rc != 0 ) && ( rc != ENOENT ) ) return rc; rc = GetStringParam( db_block, MYSQL_CONFIG_BLOCK, "socket", STR_PARAM_NO_WILDCARDS | STR_PARAM_ABSOLUTE_PATH, conf->db_config.socket, RBH_PATH_MAX, NULL, NULL, msg_out ); if ( ( rc != 0 ) && ( rc != ENOENT ) ) return rc; rc = GetBoolParam( db_block, MYSQL_CONFIG_BLOCK, "innodb", 0, &conf->db_config.innodb, NULL, NULL, msg_out ); if ( ( rc != 0 ) && ( rc != ENOENT ) ) return rc; CheckUnknownParameters( db_block, MYSQL_CONFIG_BLOCK, db_allowed ); #elif defined (_SQLITE) /* get SQLite block */ db_block = rh_config_GetItemByName( lmgr_block, SQLITE_CONFIG_BLOCK ); if ( db_block == NULL ) { strcpy( msg_out, "Missing configuration block '" LMGR_CONFIG_BLOCK "::" SQLITE_CONFIG_BLOCK "'" ); return ENOENT; } if ( rh_config_ItemType( db_block ) != CONFIG_ITEM_BLOCK ) { sprintf( msg_out, "A block is expected for '" LMGR_CONFIG_BLOCK "::" SQLITE_CONFIG_BLOCK "' item, line %d", rh_config_GetItemLine( db_block ) ); return EINVAL; } rc = GetStringParam( db_block, SQLITE_CONFIG_BLOCK, "db_file", STR_PARAM_ABSOLUTE_PATH | STR_PARAM_NO_WILDCARDS, conf->db_config.filepath, RBH_PATH_MAX, NULL, NULL, msg_out ); if ( ( rc != 0 ) && ( rc != ENOENT ) ) return rc; rc = GetIntParam( db_block, SQLITE_CONFIG_BLOCK, "retry_delay_microsec", INT_PARAM_POSITIVE | INT_PARAM_NOT_NULL, (int*)&conf->db_config.retry_delay_microsec, NULL, NULL, msg_out ); if ( ( rc != 0 ) && ( rc != ENOENT ) ) return rc; CheckUnknownParameters( db_block, SQLITE_CONFIG_BLOCK, db_allowed ); #endif return 0; }
static void display_line_log(log_stream_t *p_log, const char *tag, const char *format, va_list arglist) { char line_log[MAX_LINE_LEN]; int written; time_t now = time(NULL); unsigned int th = GetThreadIndex(); struct tm date; int would_print; if (log_initialized) { /* periodically check if log files have been renamed */ if (now - last_time_test > TIME_TEST_FILE) { test_file_names(); last_time_test = now; } } pthread_rwlock_rdlock(&p_log->f_lock); /* if logs are not initalized or the log is a NULL FILE*, * default logging to stderr */ if ((!log_initialized) || ((p_log->log_type != RBH_LOG_SYSLOG) && (p_log->f_log == NULL))) { localtime_r(&now, &date); written = snprintf(line_log, MAX_LINE_LEN, "%.4d/%.2d/%.2d %.2d:%.2d:%.2d %s[%lu/%u] %s%s", 1900 + date.tm_year, date.tm_mon + 1, date.tm_mday, date.tm_hour, date.tm_min, date.tm_sec, log_config.log_process ? "robinhood" : "", (unsigned long)getpid(), th, tag ? tag : "", tag ? " | " : ""); would_print = vsnprintf(line_log + written, MAX_LINE_LEN - written, format, arglist); clean_str(line_log); if (would_print >= MAX_LINE_LEN - written) fprintf(stderr, "%s... <Line truncated. Original size=%u>\n", line_log, would_print); else fprintf(stderr, "%s\n", line_log); } else if (p_log->log_type == RBH_LOG_SYSLOG) { /* add tag to syslog line */ char new_format[MAX_LINE_LEN]; if (tag) snprintf(new_format, MAX_LINE_LEN, "%s | %s", tag, format); else rh_strncpy(new_format, format, MAX_LINE_LEN); vsyslog(log_config.syslog_priority, new_format, arglist); } else { /* log to a file */ localtime_r(&now, &date); written = snprintf(line_log, MAX_LINE_LEN, "%.4d/%.2d/%.2d %.2d:%.2d:%.2d %s%s%s[%lu/%u] %s%s", 1900 + date.tm_year, date.tm_mon + 1, date.tm_mday, date.tm_hour, date.tm_min, date.tm_sec, log_config.log_process ? prog_name : "", log_config.log_host ? "@" : "", log_config.log_host ? machine_name : "", (unsigned long)getpid(), th, tag ? tag : "", tag ? " | " : ""); would_print = vsnprintf(line_log + written, MAX_LINE_LEN - written, format, arglist); clean_str(line_log); if (p_log->f_log != NULL) { if (would_print >= MAX_LINE_LEN - written) fprintf(p_log->f_log, "%s... <Line truncated. Original size=%u>\n", line_log, would_print); else fprintf(p_log->f_log, "%s\n", line_log); } } pthread_rwlock_unlock(&p_log->f_lock); }
/** * Main daemon routine */ int main(int argc, char **argv) { int c, option_index = 0; const char *bin; char config_file[MAX_OPT_LEN] = ""; int rc; char err_msg[4096]; bool chgd = false; char badcfg[RBH_PATH_MAX]; char sm_name[SM_NAME_MAX + 1] = ""; bin = rh_basename(argv[0]); /* parse command line options */ while ((c = getopt_long(argc, argv, SHORT_OPT_STRING, option_tab, &option_index)) != -1) { switch (c) { case 'f': rh_strncpy(config_file, optarg, MAX_OPT_LEN); break; case 'l': { int log_level = str2debuglevel(optarg); if (log_level == -1) { fprintf(stderr, "Unsupported log level '%s'. CRIT, MAJOR, EVENT, VERB, DEBUG or FULL expected.\n", optarg); exit(1); } force_debug_level(log_level); break; } case 's': if (!EMPTY_STRING(sm_name)) fprintf(stderr, "WARNING: only a single status manager is expected " "on command line. '%s' ignored.\n", optarg); else rh_strncpy(sm_name, optarg, sizeof(sm_name)); break; case 'h': display_help(bin); exit(EXIT_SUCCESS); break; case 'V': display_version(bin); exit(EXIT_SUCCESS); break; case ':': case '?': default: display_help(bin); exit(1); break; } } /* 2 expected argument: old backend path, new path is FS */ if (optind > argc - 3) { fprintf(stderr, "Error: missing arguments on command line.\n"); display_help(bin); exit(1); } else if (optind < argc - 4) { fprintf(stderr, "Error: too many arguments on command line.\n"); display_help(bin); exit(1); } rc = rbh_init_internals(); if (rc != 0) exit(EXIT_FAILURE); /* get default config file, if not specified */ if (SearchConfig(config_file, config_file, &chgd, badcfg, MAX_OPT_LEN) != 0) { fprintf(stderr, "No config file (or too many) found matching %s\n", badcfg); exit(2); } else if (chgd) { fprintf(stderr, "Using config file '%s'.\n", config_file); } /* only read common config (listmgr, ...) (mask=0) */ if (rbh_cfg_load(0, config_file, err_msg)) { fprintf(stderr, "Error reading configuration file '%s': %s\n", config_file, err_msg); exit(1); } if (!log_config.force_debug_level) log_config.debug_level = LVL_MAJOR; /* no event message */ /* Set logging to stderr */ strcpy(log_config.log_file, "stderr"); strcpy(log_config.report_file, "stderr"); strcpy(log_config.alert_file, "stderr"); /* Initialize logging */ rc = InitializeLogs(bin); if (rc) { fprintf(stderr, "Error opening log files: rc=%d, errno=%d: %s\n", rc, errno, strerror(errno)); exit(EXIT_FAILURE); } /* Initialize Filesystem access */ rc = InitFS(); if (rc) exit(EXIT_FAILURE); /* Initialize status managers (XXX all or just the one used for undelete?) */ rc = smi_init_all(0); if (rc) exit(EXIT_FAILURE); /* load the status manager */ if (!EMPTY_STRING(sm_name)) { rc = load_smi(sm_name, &smi); if (rc) exit(EXIT_FAILURE); } else { /* if there is a single smi that allows undelete, use it */ rc = load_single_smi(&smi); if (rc) exit(EXIT_FAILURE); } if (optind == argc - 3) rc = rebind_helper(argv[optind], argv[optind + 1], argv[optind + 2], NULL); else if (optind == argc - 4) rc = rebind_helper(argv[optind], argv[optind + 1], argv[optind + 2], argv[optind + 3]); exit(rc ? EXIT_FAILURE: EXIT_SUCCESS); }
int get_stripe_info(lmgr_t *p_mgr, PK_ARG_T pk, stripe_info_t *p_stripe_info, stripe_items_t *p_items) { /* stripe_count, stripe_size, pool_name, validator => 4 */ #define STRIPE_INFO_COUNT 4 char *res[STRIPE_INFO_COUNT]; result_handle_t result; int i; int rc = DB_SUCCESS; GString *req; /* retrieve basic stripe info */ req = g_string_new ("SELECT stripe_count, stripe_size, pool_name,validator FROM " STRIPE_INFO_TABLE " WHERE id="); g_string_append_printf(req, DPK, pk); rc = db_exec_sql(&p_mgr->conn, req->str, &result); if (rc) goto out; rc = db_next_record(&p_mgr->conn, &result, res, STRIPE_INFO_COUNT); if (rc == DB_END_OF_LIST) rc = DB_NOT_EXISTS; if (rc) goto res_free; for (i = 0; i < STRIPE_INFO_COUNT; i++) { DisplayLog(LVL_FULL, LISTMGR_TAG, "stripe_res[%u] = %s", i, res[i] ? res[i] : "<null>"); if (res[i] == NULL) { rc = DB_ATTR_MISSING; goto res_free; } } p_stripe_info->stripe_count = atoi(res[0]); p_stripe_info->stripe_size = atoi(res[1]); rh_strncpy(p_stripe_info->pool_name, res[2], MAX_POOL_LEN); #ifdef HAVE_LLAPI_FSWAP_LAYOUTS p_stripe_info->validator = atoi(res[3]); #endif db_result_free(&p_mgr->conn, &result); if (p_items) { /* retrieve stripe list */ g_string_printf(req, "SELECT stripe_index,ostidx,details FROM " STRIPE_ITEMS_TABLE " WHERE id=" DPK " ORDER BY stripe_index ASC", pk); rc = db_exec_sql(&p_mgr->conn, req->str, &result); if (rc) goto out; #ifndef _LUSTRE_HSM /* this is abnormal if LUSTRE/HSM feature is not present */ if (p_stripe_info->stripe_count != db_result_nb_records(&p_mgr->conn, &result)) { DisplayLog(LVL_MAJOR, LISTMGR_TAG, "Warning: the number of stripe items (%d) doesn't match stripe count (%u)! (Pk=" DPK ")", db_result_nb_records(&p_mgr->conn, &result), p_stripe_info->stripe_count, pk); } #endif p_items->count = db_result_nb_records(&p_mgr->conn, &result); if (p_items->count > 0) { /* allocate stripe array */ p_items->stripe = MemCalloc(p_items->count, sizeof(stripe_item_t)); if (!p_items->stripe) { rc = DB_NO_MEMORY; goto res_free; } /* fill stripe units */ for (i = 0; i < p_items->count; i++) { rc = db_next_record(&p_mgr->conn, &result, res, STRIPE_INFO_COUNT); if (rc) goto stripe_free; if (res[0] == NULL) { rc = DB_ATTR_MISSING; goto stripe_free; } if (i != atoi(res[0])) { DisplayLog(LVL_MAJOR, LISTMGR_TAG, "Warning: inconsistent stripe order: stripe %s returned in position %u", res[0], i); } p_items->stripe[i].ost_idx = atoi(res[1]); /* raw copy of binary buffer (last 3 fields of stripe_item_t * = address of ost_gen field) */ memcpy(&p_items->stripe[i].ost_gen, res[2], STRIPE_DETAIL_SZ); } } else p_items->stripe = NULL; /* last query result must be freed */ rc = DB_SUCCESS; goto res_free; } rc = DB_SUCCESS; /* result is already freed */ goto out; stripe_free: free_stripe_items(p_items); res_free: db_result_free(&p_mgr->conn, &result); out: g_string_free(req, TRUE); return rc; }
static int lmgr_cfg_read(config_file_t config, void *module_config, char *msg_out) { int rc; bool bval; lmgr_config_t *conf = (lmgr_config_t *) module_config; char **options = NULL; unsigned int nb_options = 0; char tmpstr[1024]; config_item_t lmgr_block; config_item_t db_block; static const char *lmgr_allowed[] = { "commit_behavior", "connect_retry_interval_min", "connect_retry_interval_max", "accounting", MYSQL_CONFIG_BLOCK, SQLITE_CONFIG_BLOCK, "user_acct", "group_acct", /* deprecated => accounting */ NULL }; const cfg_param_t cfg_params[] = { {"connect_retry_interval_min", PT_DURATION, PFLG_POSITIVE | PFLG_NOT_NULL, &conf->connect_retry_min, 0}, {"connect_retry_interval_max", PT_DURATION, PFLG_POSITIVE | PFLG_NOT_NULL, &conf->connect_retry_max, 0}, {"accounting", PT_BOOL, 0, &conf->acct, 0}, END_OF_PARAMS }; #ifdef _MYSQL static const char *db_allowed[] = { "server", "db", "user", "password", "password_file", "port", "socket", "engine", "tokudb_compression", NULL }; const cfg_param_t db_params[] = { {"server", PT_STRING, PFLG_NO_WILDCARDS, conf->db_config.server, sizeof(conf->db_config.server)} , {"db", PT_STRING, PFLG_MANDATORY | PFLG_NO_WILDCARDS, conf->db_config.db, sizeof(conf->db_config.db)} , {"user", PT_STRING, PFLG_NO_WILDCARDS, conf->db_config.user, sizeof(conf->db_config.user)} , {"port", PT_INT, PFLG_POSITIVE | PFLG_NOT_NULL, (int *)&conf->db_config.port, 0}, {"socket", PT_STRING, PFLG_NO_WILDCARDS | PFLG_ABSOLUTE_PATH, conf->db_config.socket, sizeof(conf->db_config.socket)} , {"engine", PT_STRING, PFLG_NO_WILDCARDS | PFLG_NOT_EMPTY, conf->db_config.engine, sizeof(conf->db_config.engine)} , {"tokudb_compression", PT_STRING, PFLG_NO_WILDCARDS, conf->db_config.tokudb_compression, sizeof(conf->db_config.tokudb_compression)} , END_OF_PARAMS }; #elif defined(_SQLITE) static const char *db_allowed[] = { "db_file", "retry_delay_microsec", NULL }; const cfg_param_t db_params[] = { {"db_file", PT_STRING, PFLG_ABSOLUTE_PATH | PFLG_NO_WILDCARDS, conf->db_config.filepath, sizeof(conf->db_config.filepath)} , {"retry_delay_microsec", PT_INT, PFLG_POSITIVE | PFLG_NOT_NULL, (int *)&conf->db_config.retry_delay_microsec, 0}, END_OF_PARAMS }; #endif /* get ListManager block */ rc = get_cfg_block(config, LMGR_CONFIG_BLOCK, &lmgr_block, msg_out); if (rc) return rc; /* retrieve std parameters */ rc = read_scalar_params(lmgr_block, LMGR_CONFIG_BLOCK, cfg_params, msg_out); if (rc) return rc; /* commit_behavior */ rc = GetStringParam(lmgr_block, LMGR_CONFIG_BLOCK, "commit_behavior", PFLG_NO_WILDCARDS, tmpstr, sizeof(tmpstr), &options, &nb_options, msg_out); if ((rc != 0) && (rc != ENOENT)) return rc; else if (rc != ENOENT) { if (!strcasecmp(tmpstr, "autocommit")) conf->commit_behavior = 0; else if (!strcasecmp(tmpstr, "transaction")) conf->commit_behavior = 1; else if (!strcasecmp(tmpstr, "periodic")) { if ((nb_options != 1) || !options || !options[0]) { strcpy(msg_out, "A single argument is expected for periodic commit behavior. Eg: commit_behavior = periodic(1000)"); return EINVAL; } conf->commit_behavior = atoi(options[0]); if (conf->commit_behavior == 0) { strcpy(msg_out, "The argument for \"" LMGR_CONFIG_BLOCK "::commit_behavior = periodic\" must be a positive integer. Eg: commit_behavior = periodic(1000)"); return EINVAL; } } else { sprintf(msg_out, "Invalid commit behavior '%s' (expected: autocommit, " "transaction, periodic(<count>))", tmpstr); return EINVAL; } } /* manage deprecated parameters */ rc = GetBoolParam(lmgr_block, LMGR_CONFIG_BLOCK, "user_acct", 0, &bval, NULL, NULL, msg_out); if (rc == 0) { DisplayLog(LVL_CRIT, TAG, "WARNING: parameter %s::%s' is deprecated. Specify 'accounting = yes/no' instead.", LMGR_CONFIG_BLOCK, "user_acct"); DisplayLog(LVL_MAJOR, TAG, "Setting 'accounting = %s' for compatibility.", bool2str(bval)); conf->acct = bval; } rc = GetBoolParam(lmgr_block, LMGR_CONFIG_BLOCK, "group_acct", 0, &bval, NULL, NULL, msg_out); if (rc == 0) { DisplayLog(LVL_CRIT, TAG, "WARNING: parameter %s::%s' is deprecated. Specify 'accounting = yes/no' instead.", LMGR_CONFIG_BLOCK, "group_acct"); DisplayLog(LVL_MAJOR, TAG, "Setting 'accounting = %s' for compatibility.", bool2str(bval)); conf->acct = bval; } CheckUnknownParameters(lmgr_block, LMGR_CONFIG_BLOCK, lmgr_allowed); /* Database parameters */ #ifdef _MYSQL /* get MySQL block */ rc = get_cfg_block(config, LMGR_CONFIG_BLOCK "::" MYSQL_CONFIG_BLOCK, &db_block, msg_out); if (rc) return rc; /* DB std params */ rc = read_scalar_params(db_block, MYSQL_CONFIG_BLOCK, db_params, msg_out); if (rc) return rc; /* DB params with specific type */ rc = GetStringParam(db_block, MYSQL_CONFIG_BLOCK, "password", 0, conf->db_config.password, 256, NULL, NULL, msg_out); if ((rc != 0) && (rc != ENOENT)) return rc; else if (rc == ENOENT) { FILE *passfile; char errstr[1024]; rc = GetStringParam(db_block, MYSQL_CONFIG_BLOCK, "password_file", PFLG_ABSOLUTE_PATH | PFLG_NO_WILDCARDS, tmpstr, sizeof(tmpstr), NULL, NULL, msg_out); if ((rc != 0) && (rc != ENOENT)) return rc; else if (rc == ENOENT) { strcpy(msg_out, MYSQL_CONFIG_BLOCK "::password or " MYSQL_CONFIG_BLOCK "::password_file must be provided"); return ENOENT; } /* read password file and @TODO check its rights */ passfile = fopen(tmpstr, "r"); if (!passfile) { rc = errno; sprintf(msg_out, "Error opening password file %s : %s", tmpstr, strerror(errno)); return rc; } rc = fscanf(passfile, "%1023s", tmpstr); if (ferror(passfile) || rc < 1) { rc = errno; if (strerror_r(rc, errstr, sizeof(errstr))) { snprintf(errstr, sizeof(errstr), "%d", rc); } sprintf(msg_out, "Error reading password file %s : %s", tmpstr, errstr); return rc; } fclose(passfile); rh_strncpy(conf->db_config.password, tmpstr, 256); } CheckUnknownParameters(db_block, MYSQL_CONFIG_BLOCK, db_allowed); #elif defined(_SQLITE) /* get SQLite block */ rc = get_cfg_block(config, LMGR_CONFIG_BLOCK "::" SQLITE_CONFIG_BLOCK, &db_block, msg_out); if (rc) return rc; rc = read_scalar_params(db_block, SQLITE_CONFIG_BLOCK, db_params, msg_out); if (rc) return rc; CheckUnknownParameters(db_block, SQLITE_CONFIG_BLOCK, db_allowed); #endif return 0; }
/** * build LOVEA buffer from stripe information * @return size of significant information in buffer. */ ssize_t BuildLovEA(const entry_id_t * p_id, const attr_set_t * p_attrs, void * buff, size_t buf_sz) { int i; size_t len = 0; if (!ATTR_MASK_TEST(p_attrs, stripe_info)) /* no stripe info */ return 0; /* check inconsistent values */ if (!ATTR_MASK_TEST(p_attrs, stripe_items) || (ATTR(p_attrs, stripe_items).count != ATTR(p_attrs, stripe_info).stripe_count)) { DisplayLog(LVL_MAJOR, "BuildLovEA", "ERROR: inconsistent stripe info for "DFID, PFID(p_id)); return -1; } /* is there a pool? */ if (EMPTY_STRING(ATTR(p_attrs, stripe_info).pool_name)) { /* no => build lov_user_md_v1 */ struct lov_user_md_v1 * p_lum = (struct lov_user_md_v1 *) buff; len = sizeof(struct lov_user_md_v1) + ATTR(p_attrs, stripe_info).stripe_count * sizeof(struct lov_user_ost_data_v1); /* check buffer size */ if (buf_sz < len) return -1; p_lum->lmm_magic = LOV_USER_MAGIC_V1; p_lum->lmm_pattern = LOV_PATTERN_RAID0; /* the only supported for now */ #ifdef _HAVE_FID p_lum->lmm_object_id = p_id->f_oid; p_lum->lmm_object_seq = p_id->f_seq; #else /* lmm_object_gr for Lustre 1.x */ p_lum->lmm_object_id = p_id->inode; p_lum->lmm_object_gr = 0; #endif p_lum->lmm_stripe_size = ATTR(p_attrs, stripe_info).stripe_size; p_lum->lmm_stripe_count = ATTR(p_attrs, stripe_info).stripe_count; p_lum->lmm_stripe_offset = 0; /* set stripe items */ for ( i = 0; i < ATTR(p_attrs, stripe_items).count; i++ ) { p_lum->lmm_objects[i].l_ost_idx = ATTR(p_attrs, stripe_items).stripe[i].ost_idx; p_lum->lmm_objects[i].l_ost_gen = ATTR(p_attrs, stripe_items).stripe[i].ost_gen; #ifdef HAVE_OBJ_ID p_lum->lmm_objects[i].l_object_id = ATTR(p_attrs, stripe_items).stripe[i].obj_id; #ifdef HAVE_OBJ_SEQ p_lum->lmm_objects[i].l_object_seq = ATTR(p_attrs, stripe_items).stripe[i].obj_seq; #else p_lum->lmm_objects[i].l_object_gr = ATTR(p_attrs, stripe_items).stripe[i].obj_seq; #endif #else /* new structure (union of fid and id/seq) */ p_lum->lmm_objects[i].l_ost_oi.oi.oi_id = ATTR(p_attrs, stripe_items).obj_id; p_lum->lmm_objects[i].l_ost_oi.oi.oi_seq = ATTR(p_attrs, stripe_items).stripe[i].obj_seq; #endif } return len; } else { /* yes => build lov_user_md_v3 */ struct lov_user_md_v3 * p_lum = (struct lov_user_md_v3 *) buff; len = sizeof(struct lov_user_md_v3) + ATTR(p_attrs, stripe_info).stripe_count * sizeof(struct lov_user_ost_data_v1); /* check buffer size */ if (buf_sz < len) return (size_t)-1; p_lum->lmm_magic = LOV_USER_MAGIC_V3; p_lum->lmm_pattern = LOV_PATTERN_RAID0; /* the only supported for now */ #ifdef _HAVE_FID p_lum->lmm_object_id = p_id->f_oid; p_lum->lmm_object_seq = p_id->f_seq; #else /* lmm_object_gr for Lustre 1.x */ p_lum->lmm_object_id = p_id->inode; p_lum->lmm_object_gr = 0; #endif p_lum->lmm_stripe_size = ATTR(p_attrs, stripe_info).stripe_size; p_lum->lmm_stripe_count = ATTR(p_attrs, stripe_info).stripe_count; p_lum->lmm_stripe_offset = 0; /* pool name */ rh_strncpy(p_lum->lmm_pool_name, ATTR(p_attrs, stripe_info).pool_name, LOV_MAXPOOLNAME); /* set stripe items */ for ( i = 0; i < ATTR(p_attrs, stripe_items).count; i++ ) { p_lum->lmm_objects[i].l_ost_idx = ATTR(p_attrs, stripe_items).stripe[i].ost_idx; p_lum->lmm_objects[i].l_ost_gen = ATTR(p_attrs, stripe_items).stripe[i].ost_gen; #ifdef HAVE_OBJ_ID p_lum->lmm_objects[i].l_object_id = ATTR(p_attrs, stripe_items).stripe[i].obj_id; #ifdef HAVE_OBJ_SEQ p_lum->lmm_objects[i].l_object_seq = ATTR(p_attrs, stripe_items).stripe[i].obj_seq; #else p_lum->lmm_objects[i].l_object_gr = ATTR(p_attrs, stripe_items).stripe[i].obj_seq; #endif #else /* new structure (union of fid and id/seq) */ p_lum->lmm_objects[i].l_ost_oi.oi.oi_id = ATTR(p_attrs, stripe_items).obj_id; p_lum->lmm_objects[i].l_ost_oi.oi.oi_seq = ATTR(p_attrs, stripe_items).stripe[i].obj_seq; #endif } return len; } }
int lustre_mds_stat_by_fid( const entry_id_t * p_id, struct stat *inode ) { char filename[MAXNAMLEN]; char buffer[1024]; struct lov_user_mds_data *lmd = ( struct lov_user_mds_data * ) buffer; int rc; /* ensure fid directory is opened */ if ( fid_dir_fd == NULL ) { P( dir_lock ); if ( fid_dir_fd == NULL ) { char path[RBH_PATH_MAX]; char *curr = path; unsigned int mlen; /* filesystem root */ strcpy( path, get_mount_point(&mlen) ); curr += mlen; /* fid directory */ strcpy( curr, "/" FIDDIR ); /* open fir directory */ fid_dir_fd = opendir( path ); } V( dir_lock ); if ( fid_dir_fd == NULL ) return errno; } sprintf( filename, DFID, PFID(p_id) ); memset( lmd, 0, sizeof( buffer ) ); rh_strncpy(buffer, filename, strlen(filename) + 1); rc = ioctl( dirfd( fid_dir_fd ), IOC_MDC_GETFILEINFO, ( void * ) lmd ); if ( rc ) { if ( errno == ENOTTY ) { return ENOTSUP; } else if ( ( errno == ENOENT ) || ( errno == ESTALE ) ) { DisplayLog( LVL_MAJOR, TAG_MDSSTAT, "Warning: %s: %s does not exist", __FUNCTION__, filename ); return ENOENT; } else { DisplayLog( LVL_CRIT, TAG_MDSSTAT, "Error: %s: IOC_MDC_GETFILEINFO failed for %s", __FUNCTION__, filename ); return errno; } } *inode = lmd->lmd_st; return 0; }
/** * Main daemon routine */ int main( int argc, char **argv ) { int c, i, option_index = 0; char *bin = basename( argv[0] ); int rc; char err_msg[4096]; robinhood_config_t rh_config; int chgd = 0; char badcfg[RBH_PATH_MAX]; char tag_name[256] = ""; start_time = time( NULL ); zero_options( &options ); /* parse command line options */ while ( ( c = getopt_long( argc, argv, SHORT_OPT_STRING, option_tab, &option_index ) ) != -1 ) { switch ( c ) { case 's': options.partial_scan = TRUE; rh_strncpy(options.partial_scan_path, optarg, RBH_PATH_MAX); /* clean final slash */ if (FINAL_SLASH(options.partial_scan_path)) REMOVE_FINAL_SLASH(options.partial_scan_path); break; case 'd': if (parse_diff_mask(optarg, &options.diff_mask, err_msg)) { fprintf(stderr, "Invalid argument for --diff: %s\n", err_msg); exit( 1 ); } break; case 'a': if (optarg) { if (!strcasecmp(optarg,"fs")) options.diff_arg.apply = APPLY_FS; else if (!strcasecmp(optarg,"db")) options.diff_arg.apply = APPLY_DB; else { fprintf(stderr, "Invalid argument for --apply: '%s' (fs or db expected)\n", optarg); exit( 1 ); } } else options.diff_arg.apply = APPLY_DB; break; case 'D': options.flags |= FLAG_DRY_RUN; break; case 'f': rh_strncpy(options.config_file, optarg, MAX_OPT_LEN); break; #ifdef _HSM_LITE case 'b': options.diff_arg.recov_from_backend = 1; break; #endif #ifdef _HAVE_FID /* only for lustre 2.x */ case 'o': rh_strncpy(options.output_dir, optarg, MAX_OPT_LEN); break; #endif case 'l': options.force_log_level = TRUE; options.log_level = str2debuglevel( optarg ); if ( options.log_level == -1 ) { fprintf( stderr, "Unsupported log level '%s'. CRIT, MAJOR, EVENT, VERB, DEBUG or FULL expected.\n", optarg ); exit( 1 ); } break; case 'h': display_help( bin ); exit( 0 ); break; case 'V': display_version( bin ); exit( 0 ); break; case ':': case '?': default: fprintf(stderr,"Run '%s --help' for more details.\n", bin); exit( 1 ); break; } } /* check there is no extra arguments */ if ( optind != argc ) { fprintf( stderr, "Error: unexpected argument on command line: %s\n", argv[optind] ); exit( 1 ); } /* Initialize global tools */ #ifdef _LUSTRE if ( ( rc = Lustre_Init( ) ) ) { fprintf( stderr, "Error %d initializing liblustreapi\n", rc ); exit( 1 ); } #endif /* Initilize uidgid cache */ if ( InitUidGid_Cache( ) ) { fprintf( stderr, "Error initializing uid/gid cache\n" ); exit( 1 ); } /* get default config file, if not specified */ if (SearchConfig(options.config_file, options.config_file, &chgd, badcfg, MAX_OPT_LEN) != 0) { fprintf(stderr, "No config file (or too many) found matching %s\n", badcfg); exit(2); } else if (chgd) { fprintf(stderr, "Using config file '%s'.\n", options.config_file ); } if ( ReadRobinhoodConfig( MODULE_MASK_FS_SCAN | MODULE_MASK_ENTRY_PROCESSOR, options.config_file, err_msg, &rh_config, FALSE ) ) { fprintf( stderr, "Error reading configuration file '%s': %s\n", options.config_file, err_msg ); exit( 1 ); } process_config_file = options.config_file; /* set global configuration */ global_config = rh_config.global_config; /* set policies info */ policies = rh_config.policies; if (options.force_log_level) rh_config.log_config.debug_level = options.log_level; else rh_config.log_config.debug_level = LVL_CRIT; /* no event message */ /* Set logging to stderr */ strcpy( rh_config.log_config.log_file, "stderr" ); strcpy( rh_config.log_config.report_file, "stderr" ); strcpy( rh_config.log_config.alert_file, "stderr" ); /* Initialize logging */ rc = InitializeLogs( bin, &rh_config.log_config ); if ( rc ) { fprintf( stderr, "Error opening log files: rc=%d, errno=%d: %s\n", rc, errno, strerror( errno ) ); exit( rc ); } /* Initialize filesystem access */ rc = InitFS(); if (rc) exit(rc); #ifdef _HSM_LITE rc = Backend_Start( &rh_config.backend_config, options.flags ); if ( rc ) { DisplayLog( LVL_CRIT, DIFF_TAG, "Error initializing backend" ); exit( 1 ); } #endif /* Initialize list manager */ rc = ListMgr_Init( &rh_config.lmgr_config, FALSE ); if ( rc ) { DisplayLog( LVL_CRIT, DIFF_TAG, "Error %d initializing list manager", rc ); exit( rc ); } else DisplayLog( LVL_VERB, DIFF_TAG, "ListManager successfully initialized" ); if ( CheckLastFS( ) != 0 ) exit( 1 ); if (options.diff_mask) rh_config.entry_proc_config.diff_mask = options.diff_mask; else { /* parse "all" */ char tmpstr[] = "all"; if (parse_diff_mask(tmpstr, &rh_config.entry_proc_config.diff_mask, err_msg)) { DisplayLog(LVL_CRIT, DIFF_TAG, "unexpected error parsing diff mask: %s", err_msg); exit(1); } } #ifdef LUSTRE_DUMP_FILES if (options.diff_arg.apply == APPLY_FS && !(options.flags & FLAG_DRY_RUN)) { /* open the file to write LOV EA and FID remapping */ if (!EMPTY_STRING(options.output_dir)) { char fname[RBH_PATH_MAX]; if (mkdir(options.output_dir, 0700) && (errno != EEXIST)) { DisplayLog(LVL_CRIT, DIFF_TAG, "Failed to create directory %s: %s", options.output_dir, strerror(errno)); exit(1); } snprintf(fname, RBH_PATH_MAX-1, "%s/"LOVEA_FNAME, options.output_dir); options.diff_arg.lovea_file = fopen(fname, "w"); if (options.diff_arg.lovea_file == NULL) { DisplayLog(LVL_CRIT, DIFF_TAG, "Failed to open %s for writting: %s", fname, strerror(errno)); exit(1); } snprintf(fname, RBH_PATH_MAX-1, "%s/"FIDREMAP_FNAME, options.output_dir); options.diff_arg.fid_remap_file = fopen(fname, "w"); if (options.diff_arg.fid_remap_file == NULL) { DisplayLog(LVL_CRIT, DIFF_TAG, "Failed to open %s for writting: %s", fname, strerror(errno)); exit(1); } } } #endif /* if no DB apply action is specified, can't use md_update field for checking * removed entries. So, create a special tag for that. */ if ((options.diff_arg.apply != APPLY_DB) || (options.flags & FLAG_DRY_RUN)) { fprintf(stderr, "Preparing diff table...\n"); /* create a connexion to the DB. this is safe to use the global lmgr var * as statistics thread is not running */ if (!ensure_db_access()) exit(1); /* create a tag to clear entries after the scan */ /* There could be several diff running in parallel, * so set a suffix to avoid conflicts */ sprintf(tag_name, "DIFF_%u", (unsigned int) getpid()); options.diff_arg.db_tag = tag_name; /* add filter for partial scan */ if (options.partial_scan) { lmgr_filter_t filter; filter_value_t val; lmgr_simple_filter_init( &filter ); char tmp[RBH_PATH_MAX]; strcpy(tmp, options.partial_scan_path); strcat(tmp, "/*"); val.value.val_str = tmp; lmgr_simple_filter_add(&filter, ATTR_INDEX_fullpath, LIKE, val, 0); rc = ListMgr_CreateTag(&lmgr, tag_name, &filter, FALSE); lmgr_simple_filter_free(&filter); } else rc = ListMgr_CreateTag(&lmgr, tag_name, NULL, FALSE); if (rc) exit(rc); } /* Initialise Pipeline */ rc = EntryProcessor_Init(&rh_config.entry_proc_config, DIFF_PIPELINE, options.flags, &options.diff_arg); if ( rc ) { DisplayLog( LVL_CRIT, DIFF_TAG, "Error %d initializing EntryProcessor pipeline", rc ); goto clean_tag; } else DisplayLog( LVL_VERB, DIFF_TAG, "EntryProcessor successfully initialized" ); fprintf(stderr, "Starting scan\n"); /* print header to indicate the content of diff * #<diff cmd> * ---fs[=/subdir] * +++db */ for (i = 0; i < argc; i++) printf("%s%s", i==0?"# ":" ", argv[i]); printf("\n"); if (options.diff_arg.apply == APPLY_FS) { if (options.partial_scan) printf("---fs=%s\n",options.partial_scan_path); else printf("---fs\n"); printf("+++db\n"); } else { printf("---db\n"); if (options.partial_scan) printf("+++fs=%s\n",options.partial_scan_path); else printf("+++fs\n"); } /* Start FS scan */ if (options.partial_scan) rc = FSScan_Start(&rh_config.fs_scan_config, options.flags, options.partial_scan_path); else rc = FSScan_Start(&rh_config.fs_scan_config, options.flags, NULL); if ( rc ) { DisplayLog( LVL_CRIT, DIFF_TAG, "Error %d initializing FS Scan module", rc ); goto clean_tag; } else DisplayLog( LVL_VERB, DIFF_TAG, "FS Scan module successfully initialized" ); /* Flush logs now, to have a trace in the logs */ FlushLogs( ); /* both pipeline and scan are now running, can now trap events and display stats */ /* create signal handling thread */ rc = pthread_create( &sig_thr, NULL, signal_handler_thr, NULL ); if ( rc ) { DisplayLog( LVL_CRIT, DIFF_TAG, "Error starting signal handler thread: %s", strerror( errno ) ); goto clean_tag; } else DisplayLog( LVL_VERB, DIFF_TAG, "Signal handler thread started successfully" ); pthread_create(&stat_thread, NULL, stats_thr, NULL); /* wait for FS scan to end */ FSScan_Wait( ); DisplayLog( LVL_MAJOR, DIFF_TAG, "FS Scan finished" ); /* Pipeline must be flushed */ EntryProcessor_Terminate( TRUE ); #ifdef LUSTRE_DUMP_FILES /* flush the lovea file */ if (options.diff_arg.lovea_file) { fprintf(stderr, " > LOV EA information written to %s/"LOVEA_FNAME"\n", options.output_dir); fclose(options.diff_arg.lovea_file); } if (options.diff_arg.fid_remap_file) { fprintf(stderr, " > FID remapping written to %s/"FIDREMAP_FNAME"\n", options.output_dir); fclose(options.diff_arg.fid_remap_file); } #endif fprintf(stderr, "End of scan\n"); DisplayLog( LVL_MAJOR, DIFF_TAG, "All tasks done! Exiting." ); rc = 0; clean_tag: /* destroy the tag before exit */ if (options.diff_arg.db_tag != NULL && ensure_db_access()) { fprintf(stderr, "Cleaning diff table...\n"); ListMgr_DestroyTag(&lmgr, options.diff_arg.db_tag); } exit(rc); return rc; /* for compiler */ }
/** * Force log file. * Won't be overridden by configuration. */ void force_log_file(const char *file) { rh_strncpy(log_config.log_file, file, sizeof(log_config.log_file)); log_config.force_log_file = true; }
/** * Main daemon routine */ int main( int argc, char **argv ) { int c = 0; char *bin = basename( argv[0] ); int rc; char err_msg[4096]; robinhood_config_t config; int chgd = 0; /* options */ char config_file[MAX_OPT_LEN] = ""; char badcfg[RBH_PATH_MAX]; int force_log_level = FALSE; int log_level = 0; int margin = 0; char output_file[MAX_OPT_LEN] = "/tmp/lov_objid"; lmgr_t lmgr; FILE * out; /* parse command line options */ while ((c = getopt(argc, argv, OPT_STRING)) != -1) { switch (c) { case 'l': force_log_level = TRUE; log_level = str2debuglevel(optarg); if (log_level == -1) { fprintf( stderr, "Unsupported log level '%s'. CRIT, MAJOR, EVENT, VERB, DEBUG or FULL expected.\n", optarg ); exit(1); } break; case 'f': rh_strncpy(config_file, optarg, MAX_OPT_LEN); break; case 'o': rh_strncpy(output_file, optarg, MAX_OPT_LEN); break; case 'm': margin = str2int(optarg); if (margin < 0) { fprintf( stderr, "Invalid parameter '%s' for '-m' option: positive integer expected\n", optarg ); exit(1); } break; case ':': case '?': default: display_help(bin); exit( 1 ); break; } } /* get default config file, if not specified */ if (SearchConfig(config_file, config_file, &chgd, badcfg, MAX_OPT_LEN) != 0) { fprintf(stderr, "No config file (or too many) found matching %s\n", badcfg); exit(2); } else if (chgd) { fprintf(stderr, "Using config file '%s'.\n", config_file ); } /* only read ListMgr config */ if ( ReadRobinhoodConfig( 0, config_file, err_msg, &config, FALSE ) ) { fprintf( stderr, "Error reading configuration file '%s': %s\n", config_file, err_msg ); exit( 1 ); } process_config_file = config_file; /* set global configuration */ global_config = config.global_config; if ( force_log_level ) config.log_config.debug_level = log_level; else config.log_config.debug_level = LVL_MAJOR; /* no event message */ /* set logging to stderr for this tool */ strcpy( config.log_config.log_file, "stderr" ); strcpy( config.log_config.report_file, "stderr" ); strcpy( config.log_config.alert_file, "stderr" ); /* Initialize logging */ rc = InitializeLogs( bin, &config.log_config ); if ( rc ) { fprintf( stderr, "Error opening log files: rc=%d, errno=%d: %s\n", rc, errno, strerror( errno ) ); exit( rc ); } /* Initialize list manager */ rc = ListMgr_Init( &config.lmgr_config, TRUE ); if ( rc ) { DisplayLog( LVL_CRIT, TAG, "Error %d initializing list manager", rc ); exit( rc ); } else DisplayLog( LVL_DEBUG, TAG, "ListManager successfully initialized" ); if ( CheckLastFS( ) != 0 ) exit( 1 ); /* Create database access */ rc = ListMgr_InitAccess( &lmgr ); if ( rc ) { DisplayLog( LVL_CRIT, TAG, "Error %d: cannot connect to database", rc ); exit( rc ); } out = fopen(output_file, "w"); if (!out) { DisplayLog(LVL_CRIT, TAG, "Failed to open '%s' for writting: %s", output_file, strerror(errno)); return errno; } /* direct SQL request to retrieve the max object index from DB */ result_handle_t res; /* FIXME max on the low weight 32bits of the 'objid' 64bits value */ rc = db_exec_sql(&lmgr.conn, "SELECT ostidx, max(hex(cast(reverse(cast(details as binary(8))) as binary(4)))) " "FROM "STRIPE_ITEMS_TABLE" GROUP BY ostidx ORDER BY ostidx", &res); if (rc) goto db_error; int index = -1; do { char *resstr[2]; unsigned int ostidx; unsigned int objid; unsigned long long objid_long; resstr[0] = resstr[1] = NULL; rc = db_next_record( &lmgr.conn, &res, resstr, 2 ); if (rc == DB_END_OF_LIST) break; else if (rc != DB_SUCCESS) goto db_error; index ++; if (resstr[0] == NULL || resstr[1] == NULL) { DisplayLog(LVL_MAJOR, TAG, "ERROR: got NULL record from DB at index %u", index); rc = EINVAL; goto out; } /* resstr[0] is ost_idx */ if (sscanf(resstr[0], "%u", &ostidx) != 1) { DisplayLog(LVL_MAJOR, TAG, "ERROR: cannot parse OST index '%s' at index %u", resstr[0], index); rc = EINVAL; goto out; } else if (ostidx != index) { DisplayLog(LVL_MAJOR, TAG, "Warning: OST index %u not found in database, assuming current objid=1", index); objid_long = 1 + margin; printf("ostidx=%u, max objid=%016LX\n", ostidx, objid_long); fwrite(&objid_long, sizeof(objid_long), 1, out); continue; } /* resstr[1] is objid (hexa) */ if (sscanf(resstr[1], "%X", &objid) != 1) { DisplayLog(LVL_MAJOR, TAG, "ERROR: cannot parse objid '%s' at index %u", resstr[1], index); rc = EINVAL; goto out; } objid_long = objid + margin; printf("ostidx=%u, objid=%016LX\n", ostidx, objid_long); fwrite(&objid_long, sizeof(objid_long), 1, out); } while(rc == 0); fclose(out); ListMgr_CloseAccess( &lmgr ); return 0; db_error: DisplayLog( LVL_CRIT, TAG, "Database error %d\n", rc); out: ListMgr_CloseAccess( &lmgr ); return rc; }
/** * Main daemon routine */ int main( int argc, char **argv ) { int c, option_index = 0; char *bin = basename( argv[0] ); char config_file[MAX_OPT_LEN] = ""; enum { ACTION_NONE, ACTION_LIST, ACTION_RESTORE } action = ACTION_NONE; int force_log_level = FALSE; int log_level = 0; int rc; char err_msg[4096]; robinhood_config_t config; int chgd = 0; char badcfg[RBH_PATH_MAX]; /* parse command line options */ while ( ( c = getopt_long( argc, argv, SHORT_OPT_STRING, option_tab, &option_index ) ) != -1 ) { switch ( c ) { case 'L': if ( (action != ACTION_NONE) && (action != ACTION_LIST) ) fprintf( stderr, "WARNING: only a single action (--list or --restore) is expected\n" "on command line. '--restore' will be ignored.\n" ); action = ACTION_LIST; break; case 'R': if ( (action != ACTION_NONE) && (action != ACTION_RESTORE) ) fprintf( stderr, "WARNING: only a single action (--list or --restore) is expected\n" "on command line. '--list' will be ignored.\n" ); action = ACTION_RESTORE; break; case 'f': rh_strncpy(config_file, optarg, MAX_OPT_LEN); break; case 'l': force_log_level = TRUE; log_level = str2debuglevel( optarg ); if ( log_level == -1 ) { fprintf( stderr, "Unsupported log level '%s'. CRIT, MAJOR, EVENT, VERB, DEBUG or FULL expected.\n", optarg ); exit( 1 ); } break; case 'h': display_help( bin ); exit( 0 ); break; case 'V': display_version( bin ); exit( 0 ); break; case ':': case '?': default: display_help( bin ); exit( 1 ); break; } } /* 1 expected argument: path */ if ( optind != argc - 1 ) { fprintf( stderr, "Error: missing mandatory argument on command line: <path|fid>\n" ); exit( 1 ); } rh_strncpy(path_filter, argv[optind], RBH_PATH_MAX); /* get default config file, if not specified */ if (SearchConfig(config_file, config_file, &chgd, badcfg, MAX_OPT_LEN) != 0) { fprintf(stderr, "No config file (or too many) found matching %s\n", badcfg); exit(2); } else if (chgd) { fprintf(stderr, "Using config file '%s'.\n", config_file ); } /* only read ListMgr config */ if ( ReadRobinhoodConfig( 0, config_file, err_msg, &config, FALSE ) ) { fprintf( stderr, "Error reading configuration file '%s': %s\n", config_file, err_msg ); exit( 1 ); } process_config_file = config_file; /* set global configuration */ global_config = config.global_config; /* set policies info */ policies = config.policies; if ( force_log_level ) config.log_config.debug_level = log_level; /* XXX HOOK: Set logging to stderr */ strcpy( config.log_config.log_file, "stderr" ); strcpy( config.log_config.report_file, "stderr" ); strcpy( config.log_config.alert_file, "stderr" ); /* Initialize logging */ rc = InitializeLogs( bin, &config.log_config ); if ( rc ) { fprintf( stderr, "Error opening log files: rc=%d, errno=%d: %s\n", rc, errno, strerror( errno ) ); exit( rc ); } /* Initialize Filesystem access */ rc = InitFS(); if (rc) exit(rc); /* Initialize list manager */ rc = ListMgr_Init( &config.lmgr_config, FALSE ); if ( rc ) { DisplayLog( LVL_CRIT, LOGTAG, "Error %d initializing list manager", rc ); exit( rc ); } else DisplayLog( LVL_DEBUG, LOGTAG, "ListManager successfully initialized" ); if ( CheckLastFS( ) != 0 ) exit( 1 ); /* Create database access */ rc = ListMgr_InitAccess( &lmgr ); if ( rc ) { DisplayLog( LVL_CRIT, LOGTAG, "Error %d: cannot connect to database", rc ); exit( rc ); } #ifdef _HSM_LITE rc = Backend_Start( &config.backend_config, 0 ); if ( rc ) { DisplayLog( LVL_CRIT, LOGTAG, "Error initializing backend" ); exit( 1 ); } #endif /* perform the action */ switch( action ) { case ACTION_LIST: rc= list_rm(); break; case ACTION_RESTORE: rc = undo_rm(); break; case ACTION_NONE: display_help( bin ); rc = 1; break; default: fprintf(stderr, "Unexpected action (action code=%#x)\n", action ); display_help( bin ); rc = EINVAL; break; } ListMgr_CloseAccess( &lmgr ); return rc; }