smbd/statcache.c

ソースコードを見る。

関数

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_CONTEXTtdb_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.
覚え書き:
Only the first strlen(orig_translated_path) characters are stored into the cache. This means that full_orig_name will be internally truncated.

statcache.c43 行で定義されています。

参照先 TDB_DATA::dptrTDB_DATA::dsizereset_stat_cache()strdup_upper()tdb_map_size()tdb_stat_cachetdb_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.
戻り値:
True if we translated (and did a scuccessful stat on) the entire name.

statcache.c161 行で定義されています。

参照先 connection_struct::case_sensitiveTDB_DATA::dptrTDB_DATA::dsizestrdup_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.c292 行で定義されています。

参照先 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.c308 行で定義されています。

参照先 strdup_upper()tdb_delete_bystring()tdb_stat_cache.

参照元 smb_stat_cache_delete().

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.c328 行で定義されています。

参照先 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.c342 行で定義されています。

参照先 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.c29 行で定義されています。

参照元 reset_stat_cache()stat_cache_add()stat_cache_delete()stat_cache_lookup().


Sambaに対してSat Aug 29 21:24:29 2009に生成されました。  doxygen 1.4.7