00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00039 #ifndef _LOG_INTERNAL_H
00040 #define _LOG_INTERNAL_H
00041
00042 #include <stdio.h>
00043 #include <pthread.h>
00044 #include <stdint.h>
00045 #include <result.h>
00046 #include <list.h>
00047 #include "hrtime.h"
00048 #include "../hal/pcm_i.h"
00049
00050 #ifdef __cplusplus
00051 extern "C" {
00052 #endif
00053
00054
00055
00056
00057
00058
00059 #define PHYSICAL_LOG_NUM_ENTRIES_LOG2 20
00060 #define PHYSICAL_LOG_NUM_ENTRIES (1 << PHYSICAL_LOG_NUM_ENTRIES_LOG2)
00061 #define PHYSICAL_LOG_SIZE (PHYSICAL_LOG_NUM_ENTRIES * sizeof(pcm_word_t))
00062
00063
00064
00065
00066 #define LF_FLAGS_MASK 0xFFFFFFFFFFFF0000LLU
00067 #define LF_TYPE_MASK 0x000000000000FFFFLLU
00068
00069
00070 #define LF_DIRTY 0x8000000000000000
00071
00072
00073 #define INV_LOG_ORDER 0xFFFFFFFFFFFFFFFF
00074
00075
00076 #define LF_ASYNC_TRUNCATION 0x0000000000000001
00077
00078
00079 enum {
00080 LF_TYPE_FREE = 0,
00081 LF_TYPE_VALIDVALUES
00082 };
00083
00084
00085 typedef struct m_logmgr_s m_logmgr_t;
00086 typedef struct m_log_s m_log_t;
00087 typedef struct m_log_ops_s m_log_ops_t;
00088 typedef struct m_log_dsc_s m_log_dsc_t;
00089 typedef struct m_log_nvmd_s m_log_nvmd_t;
00090
00091
00092 struct m_log_ops_s {
00093 m_result_t (*alloc)(m_log_dsc_t *log_dsc);
00094 m_result_t (*init)(pcm_storeset_t *set, m_log_t *log, m_log_dsc_t *log_dsc);
00095 m_result_t (*truncation_init)(pcm_storeset_t *set, m_log_dsc_t *log_dsc);
00096 m_result_t (*truncation_prepare_next)(pcm_storeset_t *set, m_log_dsc_t *log_dsc);
00097 m_result_t (*truncation_do)(pcm_storeset_t *set, m_log_dsc_t *log_dsc);
00098 m_result_t (*recovery_init)(pcm_storeset_t *set, m_log_dsc_t *log_dsc);
00099 m_result_t (*recovery_prepare_next)(pcm_storeset_t *set, m_log_dsc_t *log_dsc);
00100 m_result_t (*recovery_do)(pcm_storeset_t *set, m_log_dsc_t *log_dsc);
00101 m_result_t (*report_stats)(m_log_dsc_t *log_dsc);
00102 };
00103
00104
00109 struct m_log_nvmd_s {
00110 pcm_word_t generic_flags;
00111 pcm_word_t reserved2;
00112 pcm_word_t reserved3;
00113 pcm_word_t reserved4;
00114 };
00115
00116 struct m_log_dsc_s {
00117 m_log_ops_t *ops;
00118 m_log_t *log;
00119 m_log_nvmd_t *nvmd;
00120 pcm_word_t *nvphlog;
00121 uint64_t flags;
00122 uint64_t logorder;
00123 struct list_head list;
00124 };
00125
00126 extern m_log_ops_t *m_log_ops[];
00127
00128 struct m_logmgr_s {
00129 pthread_mutex_t mutex;
00130 struct list_head free_logs_list;
00131 struct list_head pending_logs_list;
00132 struct list_head active_logs_list;
00133 struct list_head known_logtypes_list;
00134
00135 pthread_cond_t logtrunc_cond;
00136 pthread_t logtrunc_thread;
00137 uint64_t trunc_time;
00138 uint64_t trunc_count;
00139 };
00140
00141
00142 m_result_t m_logmgr_init(pcm_storeset_t *set);
00143 m_result_t m_logmgr_fini(void);
00144 m_result_t m_logmgr_register_logtype(pcm_storeset_t *set, int type, m_log_ops_t *ops);
00145 m_result_t m_logmgr_alloc_log(pcm_storeset_t *set, int type, uint64_t flags, m_log_dsc_t **log_dscp);
00146 m_result_t m_logmgr_free_log(m_log_dsc_t *log_dsc);
00147 m_result_t m_logmgr_do_recovery(pcm_storeset_t *set);
00148 m_result_t m_logtrunc_truncate(pcm_storeset_t *set);
00149 void m_logmgr_stat_print();
00150
00151
00152
00153 #define PHLOG_WRITE(logtype, set, phlog, val) \
00154 do { \
00155 int retries = 0; \
00156 while (m_phlog_##logtype##_write(set, (phlog), (val)) != M_R_SUCCESS) { \
00157 if (retries++ > 1) { \
00158 M_INTERNALERROR("Cannot complete log write successfully.\n"); \
00159 } \
00160 (phlog)->stat_wait_for_trunc++; \
00161 m_logtrunc_truncate(set); \
00162 } \
00163 } while (0);
00164
00165
00166 #define PHLOG_FLUSH(logtype, set, phlog) \
00167 do { \
00168 int retries = 0; \
00169 while (m_phlog_##logtype##_flush(set, (phlog)) != M_R_SUCCESS) { \
00170 if (retries++ > 1) { \
00171 M_INTERNALERROR("Cannot complete log write successfully.\n"); \
00172 } \
00173 (phlog)->stat_wait_for_trunc++; \
00174 m_logtrunc_truncate(set); \
00175 } \
00176 } while (0);
00177
00178
00179 #define PHLOG_WRITE_ASYNCTRUNC(logtype, set, phlog, val) \
00180 do { \
00181 hrtime_t __start; \
00182 hrtime_t __end; \
00183 if (m_phlog_##logtype##_write(set, (phlog), (val)) != M_R_SUCCESS) { \
00184 (phlog)->stat_wait_for_trunc++; \
00185 __start = hrtime_cycles(); \
00186 while (m_phlog_##logtype##_write(set, (phlog), (val)) != M_R_SUCCESS); \
00187 __end = hrtime_cycles(); \
00188 phlog->stat_wait_time_for_trunc += (HRTIME_CYCLE2NS(__end - __start)); \
00189 } \
00190 } while (0);
00191
00192
00193 #define PHLOG_FLUSH_ASYNCTRUNC(logtype, set, phlog) \
00194 do { \
00195 hrtime_t __start; \
00196 hrtime_t __end; \
00197 if (m_phlog_##logtype##_flush(set, (phlog)) != M_R_SUCCESS) { \
00198 (phlog)->stat_wait_for_trunc++; \
00199 __start = hrtime_cycles(); \
00200 while (m_phlog_##logtype##_flush(set, (phlog)) != M_R_SUCCESS); \
00201 __end = hrtime_cycles(); \
00202 phlog->stat_wait_time_for_trunc += (HRTIME_CYCLE2NS(__end - __start)); \
00203 } \
00204 } while (0);
00205
00206
00207 #ifdef __cplusplus
00208 }
00209 #endif
00210
00211 #endif