関数 | |
void | stat_cache_add (const char *full_orig_name, const char *orig_translated_path, BOOL case_sensitive) |
Add an entry into the stat cache. | |
BOOL | stat_cache_lookup (connection_struct *conn, pstring name, pstring dirpath, char **start, SMB_STRUCT_STAT *pst) |
Look through the stat cache for an entry | |
void | send_stat_cache_delete_message (const char *name) |
void | stat_cache_delete (const char *name) |
unsigned int | fast_string_hash (TDB_DATA *key) |
BOOL | reset_stat_cache (void) |
変数 | |
static TDB_CONTEXT * | tdb_stat_cache |
void stat_cache_add | ( | const char * | full_orig_name, | |
const char * | orig_translated_path, | |||
BOOL | case_sensitive | |||
) |
Add an entry into the stat cache.
full_orig_name | The original name as specified by the client | |
orig_translated_path | The name on our filesystem. |
statcache.c の 43 行で定義されています。
参照先 TDB_DATA::dptr・TDB_DATA::dsize・reset_stat_cache()・strdup_upper()・tdb_map_size()・tdb_stat_cache・tdb_store_bystring().
参照元 unix_convert().
00044 { 00045 char *translated_path; 00046 size_t translated_path_length; 00047 TDB_DATA data_val; 00048 char *original_path; 00049 size_t original_path_length; 00050 size_t sc_size = lp_max_stat_cache_size(); 00051 00052 if (!lp_stat_cache()) 00053 return; 00054 00055 if (sc_size && (tdb_map_size(tdb_stat_cache) > sc_size*1024)) { 00056 reset_stat_cache(); 00057 } 00058 00059 ZERO_STRUCT(data_val); 00060 00061 /* 00062 * Don't cache trivial valid directory entries such as . and .. 00063 */ 00064 00065 if((*full_orig_name == '\0') || (full_orig_name[0] == '.' && 00066 ((full_orig_name[1] == '\0') || 00067 (full_orig_name[1] == '.' && full_orig_name[2] == '\0')))) 00068 return; 00069 00070 /* 00071 * If we are in case insentive mode, we don't need to 00072 * store names that need no translation - else, it 00073 * would be a waste. 00074 */ 00075 00076 if(case_sensitive && (strcmp(full_orig_name, orig_translated_path) == 0)) 00077 return; 00078 00079 /* 00080 * Remove any trailing '/' characters from the 00081 * translated path. 00082 */ 00083 00084 translated_path = SMB_STRDUP(orig_translated_path); 00085 if (!translated_path) 00086 return; 00087 00088 translated_path_length = strlen(translated_path); 00089 00090 if(translated_path[translated_path_length-1] == '/') { 00091 translated_path[translated_path_length-1] = '\0'; 00092 translated_path_length--; 00093 } 00094 00095 if(case_sensitive) { 00096 original_path = SMB_STRDUP(full_orig_name); 00097 } else { 00098 original_path = strdup_upper(full_orig_name); 00099 } 00100 00101 if (!original_path) { 00102 SAFE_FREE(translated_path); 00103 return; 00104 } 00105 00106 original_path_length = strlen(original_path); 00107 00108 if(original_path[original_path_length-1] == '/') { 00109 original_path[original_path_length-1] = '\0'; 00110 original_path_length--; 00111 } 00112 00113 if (original_path_length != translated_path_length) { 00114 if (original_path_length < translated_path_length) { 00115 DEBUG(0, ("OOPS - tried to store stat cache entry for weird length paths [%s] %lu and [%s] %lu)!\n", 00116 original_path, (unsigned long)original_path_length, translated_path, (unsigned long)translated_path_length)); 00117 SAFE_FREE(original_path); 00118 SAFE_FREE(translated_path); 00119 return; 00120 } 00121 00122 /* we only want to index by the first part of original_path, 00123 up to the length of translated_path */ 00124 00125 original_path[translated_path_length] = '\0'; 00126 original_path_length = translated_path_length; 00127 } 00128 00129 /* 00130 * New entry or replace old entry. 00131 */ 00132 00133 data_val.dsize = translated_path_length + 1; 00134 data_val.dptr = translated_path; 00135 00136 if (tdb_store_bystring(tdb_stat_cache, original_path, data_val, TDB_REPLACE) != 0) { 00137 DEBUG(0,("stat_cache_add: Error storing entry %s -> %s\n", original_path, translated_path)); 00138 } else { 00139 DEBUG(5,("stat_cache_add: Added entry (%lx:size%x) %s -> %s\n", 00140 (unsigned long)data_val.dptr, (unsigned int)data_val.dsize, original_path, translated_path)); 00141 } 00142 00143 SAFE_FREE(original_path); 00144 SAFE_FREE(translated_path); 00145 }
BOOL stat_cache_lookup | ( | connection_struct * | conn, | |
pstring | name, | |||
pstring | dirpath, | |||
char ** | start, | |||
SMB_STRUCT_STAT * | pst | |||
) |
Look through the stat cache for an entry
conn | A connection struct to do the stat() with. | |
name | The path we are attempting to cache, modified by this routine to be correct as far as the cache can tell us | |
dirpath | The path as far as the stat cache told us. | |
start | A pointer into name, for where to 'start' in fixing the rest of the name up. | |
psd | A stat buffer, NOT from the cache, but just a side-effect. |
statcache.c の 161 行で定義されています。
参照先 connection_struct::case_sensitive・TDB_DATA::dptr・TDB_DATA::dsize・strdup_upper()・strnrchr_m()・strrchr_m()・tdb_delete_bystring()・tdb_fetch_bystring()・tdb_stat_cache.
参照元 unix_convert().
00163 { 00164 char *chk_name; 00165 size_t namelen; 00166 BOOL sizechanged = False; 00167 unsigned int num_components = 0; 00168 00169 if (!lp_stat_cache()) 00170 return False; 00171 00172 namelen = strlen(name); 00173 00174 *start = name; 00175 00176 DO_PROFILE_INC(statcache_lookups); 00177 00178 /* 00179 * Don't lookup trivial valid directory entries. 00180 */ 00181 if((*name == '\0') || (name[0] == '.' && 00182 ((name[1] == '\0') || 00183 (name[1] == '.' && name[1] == '\0')))) 00184 return False; 00185 00186 if (conn->case_sensitive) { 00187 chk_name = SMB_STRDUP(name); 00188 if (!chk_name) { 00189 DEBUG(0, ("stat_cache_lookup: strdup failed!\n")); 00190 return False; 00191 } 00192 00193 } else { 00194 chk_name = strdup_upper(name); 00195 if (!chk_name) { 00196 DEBUG(0, ("stat_cache_lookup: strdup_upper failed!\n")); 00197 return False; 00198 } 00199 00200 /* 00201 * In some language encodings the length changes 00202 * if we uppercase. We need to treat this differently 00203 * below. 00204 */ 00205 if (strlen(chk_name) != namelen) 00206 sizechanged = True; 00207 } 00208 00209 while (1) { 00210 TDB_DATA data_val; 00211 char *sp; 00212 00213 data_val = tdb_fetch_bystring(tdb_stat_cache, chk_name); 00214 if(data_val.dptr == NULL || data_val.dsize == 0) { 00215 DEBUG(10,("stat_cache_lookup: lookup failed for name [%s]\n", chk_name )); 00216 /* 00217 * Didn't find it - remove last component for next try. 00218 */ 00219 sp = strrchr_m(chk_name, '/'); 00220 if (sp) { 00221 *sp = '\0'; 00222 /* 00223 * Count the number of times we have done this, 00224 * we'll need it when reconstructing the string. 00225 */ 00226 if (sizechanged) 00227 num_components++; 00228 00229 } else { 00230 /* 00231 * We reached the end of the name - no match. 00232 */ 00233 DO_PROFILE_INC(statcache_misses); 00234 SAFE_FREE(chk_name); 00235 return False; 00236 } 00237 if((*chk_name == '\0') || (strcmp(chk_name, ".") == 0) 00238 || (strcmp(chk_name, "..") == 0)) { 00239 DO_PROFILE_INC(statcache_misses); 00240 SAFE_FREE(chk_name); 00241 return False; 00242 } 00243 } else { 00244 BOOL retval; 00245 char *translated_path = data_val.dptr; 00246 size_t translated_path_length = data_val.dsize - 1; 00247 00248 DEBUG(10,("stat_cache_lookup: lookup succeeded for name [%s] -> [%s]\n", chk_name, translated_path )); 00249 DO_PROFILE_INC(statcache_hits); 00250 if(SMB_VFS_STAT(conn,translated_path, pst) != 0) { 00251 /* Discard this entry - it doesn't exist in the filesystem. */ 00252 tdb_delete_bystring(tdb_stat_cache, chk_name); 00253 SAFE_FREE(chk_name); 00254 SAFE_FREE(data_val.dptr); 00255 return False; 00256 } 00257 00258 if (!sizechanged) { 00259 memcpy(name, translated_path, MIN(sizeof(pstring)-1, translated_path_length)); 00260 } else if (num_components == 0) { 00261 pstrcpy(name, translated_path); 00262 } else { 00263 sp = strnrchr_m(name, '/', num_components); 00264 if (sp) { 00265 pstring last_component; 00266 pstrcpy(last_component, sp); 00267 pstrcpy(name, translated_path); 00268 pstrcat(name, last_component); 00269 } else { 00270 pstrcpy(name, translated_path); 00271 } 00272 } 00273 00274 /* set pointer for 'where to start' on fixing the rest of the name */ 00275 *start = &name[translated_path_length]; 00276 if(**start == '/') 00277 ++*start; 00278 00279 pstrcpy(dirpath, translated_path); 00280 retval = (namelen == translated_path_length) ? True : False; 00281 SAFE_FREE(chk_name); 00282 SAFE_FREE(data_val.dptr); 00283 return retval; 00284 } 00285 } 00286 }
void send_stat_cache_delete_message | ( | const char * | name | ) |
statcache.c の 292 行で定義されています。
参照先 conn_tdb_ctx()・message_send_all().
00293 { 00294 #ifdef DEVELOPER 00295 message_send_all(conn_tdb_ctx(), 00296 MSG_SMB_STAT_CACHE_DELETE, 00297 name, 00298 strlen(name)+1, 00299 True, 00300 NULL); 00301 #endif 00302 }
void stat_cache_delete | ( | const char * | name | ) |
statcache.c の 308 行で定義されています。
参照先 strdup_upper()・tdb_delete_bystring()・tdb_stat_cache.
00309 { 00310 char *lname = strdup_upper(name); 00311 00312 if (!lname) { 00313 return; 00314 } 00315 DEBUG(10,("stat_cache_delete: deleting name [%s] -> %s\n", 00316 lname, name )); 00317 00318 tdb_delete_bystring(tdb_stat_cache, lname); 00319 SAFE_FREE(lname); 00320 }
unsigned int fast_string_hash | ( | TDB_DATA * | key | ) |
statcache.c の 328 行で定義されています。
参照先 TDB_DATA::dptr.
参照元 mangle_hash_init()・reset_stat_cache().
00329 { 00330 unsigned int n = 0; 00331 const char *p; 00332 for (p = key->dptr; *p != '\0'; p++) { 00333 n = ((n << 5) + n) ^ (unsigned int)(*p); 00334 } 00335 return n; 00336 }
BOOL reset_stat_cache | ( | void | ) |
statcache.c の 342 行で定義されています。
参照先 fast_string_hash()・tdb_close()・tdb_open_ex()・tdb_stat_cache.
参照元 reload_services()・stat_cache_add().
00343 { 00344 if (!lp_stat_cache()) 00345 return True; 00346 00347 if (tdb_stat_cache) { 00348 tdb_close(tdb_stat_cache); 00349 } 00350 00351 /* Create the in-memory tdb using our custom hash function. */ 00352 tdb_stat_cache = tdb_open_ex("statcache", 1031, TDB_INTERNAL, 00353 (O_RDWR|O_CREAT), 0644, NULL, fast_string_hash); 00354 00355 if (!tdb_stat_cache) 00356 return False; 00357 return True; 00358 }
TDB_CONTEXT* tdb_stat_cache [static] |
statcache.c の 29 行で定義されています。
参照元 reset_stat_cache()・stat_cache_add()・stat_cache_delete()・stat_cache_lookup().