nfs-ganesha 1.4

cache_content_add_entry.c

Go to the documentation of this file.
00001 /*
00002  * vim:expandtab:shiftwidth=8:tabstop=8:
00003  *
00004  * Copyright CEA/DAM/DIF  (2008)
00005  * contributeur : Philippe DENIEL   philippe.deniel@cea.fr
00006  *                Thomas LEIBOVICI  thomas.leibovici@cea.fr
00007  *
00008  *
00009  * This program is free software; you can redistribute it and/or
00010  * modify it under the terms of the GNU Lesser General Public
00011  * License as published by the Free Software Foundation; either
00012  * version 3 of the License, or (at your option) any later version.
00013  * 
00014  * This program is distributed in the hope that it will be useful,
00015  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00016  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00017  * Lesser General Public License for more details.
00018  * 
00019  * You should have received a copy of the GNU Lesser General Public
00020  * License along with this library; if not, write to the Free Software
00021  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
00022  * 
00023  * ---------------------------------------
00024  */
00025 
00037 #ifdef HAVE_CONFIG_H
00038 #include "config.h"
00039 #endif
00040 
00041 #ifdef _SOLARIS
00042 #include "solaris_port.h"
00043 #endif                          /* _SOLARIS */
00044 
00045 #include "LRU_List.h"
00046 #include "log.h"
00047 #include "HashData.h"
00048 #include "HashTable.h"
00049 #include "fsal.h"
00050 #include "cache_inode.h"
00051 #include "cache_content.h"
00052 
00053 #include <unistd.h>
00054 #include <sys/types.h>
00055 #include <sys/param.h>
00056 #include <time.h>
00057 #include <pthread.h>
00058 #include <errno.h>
00059 #include <fcntl.h>
00060 #include <string.h>
00061 
00080 cache_content_entry_t *cache_content_new_entry(cache_entry_t * pentry_inode,
00081                                                cache_content_spec_data_t * pspecdata,
00082                                                cache_content_client_t * pclient,
00083                                                cache_content_add_behaviour_t how,
00084                                                fsal_op_context_t * pcontext,
00085                                                cache_content_status_t * pstatus)
00086 {
00087   cache_content_status_t status;
00088   cache_content_entry_t *pfc_pentry = NULL;
00089   int tmpfd;
00090 
00091   /* Set the return default to CACHE_CONTENT_SUCCESS */
00092   *pstatus = CACHE_CONTENT_SUCCESS;
00093 
00094   /* stat */
00095   pclient->stat.func_stats.nb_call[CACHE_CONTENT_NEW_ENTRY] += 1;
00096 
00097   if(pentry_inode == NULL)
00098     {
00099       *pstatus = CACHE_CONTENT_INVALID_ARGUMENT;
00100 
00101       /* stat */
00102       pclient->stat.func_stats.nb_err_unrecover[CACHE_CONTENT_NEW_ENTRY] += 1;
00103 
00104       return NULL;
00105     }
00106 
00107   if(how != RENEW_ENTRY)
00108     {
00109       /* Get the entry from the preallocated pool */
00110       pfc_pentry = pool_alloc(pclient->content_pool, NULL);
00111 
00112       if(pfc_pentry == NULL)
00113         {
00114           *pstatus = CACHE_CONTENT_MALLOC_ERROR;
00115 
00116           LogDebug(COMPONENT_CACHE_CONTENT,
00117                             "cache_content_new_entry: can't allocate a new fc_entry from cache pool");
00118 
00119           /* stat */
00120           pclient->stat.func_stats.nb_err_unrecover[CACHE_CONTENT_NEW_ENTRY] += 1;
00121 
00122           return NULL;
00123         }
00124     }                           /* if( how != RENEW_ENTRY ) */
00125 
00126   /* Set the path to the local files */
00127   if((status = cache_content_create_name(pfc_pentry->local_fs_entry.cache_path_index,
00128                                          CACHE_CONTENT_INDEX_FILE,
00129                                          pcontext,
00130                                          pentry_inode, pclient)) != CACHE_CONTENT_SUCCESS)
00131     {
00132       pool_free(pclient->content_pool, pfc_pentry);
00133 
00134       *pstatus = CACHE_CONTENT_ENTRY_EXISTS;
00135 
00136       /* stat */
00137       pclient->stat.func_stats.nb_err_retryable[CACHE_CONTENT_NEW_ENTRY] += 1;
00138 
00139       LogEvent(COMPONENT_CACHE_CONTENT,
00140                         "cache_content_new_entry: entry's index pathname could not be created:%u", 
00141                         status );
00142 
00143       return NULL;
00144     }
00145 
00146   if((status = cache_content_create_name(pfc_pentry->local_fs_entry.cache_path_data,
00147                                          CACHE_CONTENT_DATA_FILE,
00148                                          pcontext,
00149                                          pentry_inode, pclient)) != CACHE_CONTENT_SUCCESS)
00150     {
00151       pool_free(pclient->content_pool, pfc_pentry);
00152 
00153       *pstatus = CACHE_CONTENT_ENTRY_EXISTS;
00154 
00155       /* stat */
00156       pclient->stat.func_stats.nb_err_retryable[CACHE_CONTENT_NEW_ENTRY] += 1;
00157 
00158       LogEvent(COMPONENT_CACHE_CONTENT,
00159                         "cache_content_new_entry: entry's data  pathname could not be created");
00160 
00161       return NULL;
00162     }
00163 
00164   LogDebug(COMPONENT_CACHE_CONTENT,
00165                     "added file content cache entry: Data=%s Index=%s",
00166                     pfc_pentry->local_fs_entry.cache_path_data,
00167                     pfc_pentry->local_fs_entry.cache_path_index);
00168 
00169   /* Set the sync state */
00170   pfc_pentry->local_fs_entry.sync_state = JUST_CREATED;
00171 
00172   /* Set the internal_md */
00173   pfc_pentry->internal_md.read_time = 0;
00174   pfc_pentry->internal_md.mod_time = 0;
00175   pfc_pentry->internal_md.refresh_time = 0;
00176   pfc_pentry->internal_md.alloc_time = time(NULL);
00177   pfc_pentry->internal_md.last_flush_time = 0;
00178   pfc_pentry->internal_md.last_refresh_time = 0;
00179   pfc_pentry->internal_md.valid_state = STATE_OK;
00180 
00181   /* Set the local fd info */
00182   pfc_pentry->local_fs_entry.opened_file.local_fd = -1;
00183   pfc_pentry->local_fs_entry.opened_file.last_op = 0;
00184 
00185   /* Create the data file if entry is not recoverd (in this case, it already exists) */
00186   if(how == ADD_ENTRY || how == RENEW_ENTRY)
00187     {
00188       if((tmpfd = creat(pfc_pentry->local_fs_entry.cache_path_data, 0750)) == -1)
00189         {
00190           pool_free(pclient->content_pool, pfc_pentry);
00191 
00192           *pstatus = CACHE_CONTENT_LOCAL_CACHE_ERROR;
00193 
00194           LogEvent(COMPONENT_CACHE_CONTENT,
00195                             "cache_content_new_entry: data cache file could not be created, errno=%d (%s)",
00196                             errno, strerror(errno));
00197 
00198           /* stat */
00199           pclient->stat.func_stats.nb_err_unrecover[CACHE_CONTENT_NEW_ENTRY] += 1;
00200 
00201           return NULL;
00202         }
00203 
00204       /* Close the new fd */
00205       close(tmpfd);
00206 
00207     }
00208 
00209   /* if( how == ADD_ENTRY || how == RENEW_ENTRY ) */
00210   /* Cache the data from FSAL if there are some */
00211   /* Add the entry to the related cache inode entry */
00212   pfc_pentry->pentry_inode = pentry_inode;
00213 
00214   /* Data cache is considered as more pertinent as data below in case of crash recovery */
00215   if(how != RECOVER_ENTRY)
00216     {
00217       /* Get the file content from the FSAL, populate the data cache */
00218       if(pclient->flush_force_fsal == 0)
00219         cache_content_refresh(pfc_pentry, pclient, pcontext, DEFAULT_REFRESH, &status);
00220       else
00221         cache_content_refresh(pfc_pentry, pclient, pcontext, FORCE_FROM_FSAL, &status);
00222 
00223       if(status != CACHE_CONTENT_SUCCESS)
00224         {
00225           pool_free(pclient->content_pool, pfc_pentry);
00226 
00227           *pstatus = status;
00228 
00229           LogEvent(COMPONENT_CACHE_CONTENT,
00230                             "cache_content_new_entry: data cache file could not read from FSAL, status=%u",
00231                             status);
00232 
00233           /* stat */
00234           pclient->stat.func_stats.nb_err_unrecover[CACHE_CONTENT_NEW_ENTRY] += 1;
00235 
00236           return NULL;
00237         }
00238     }
00239   /* if ( how != RECOVER_ENTRY ) */
00240   return pfc_pentry;
00241 }                               /* cache_content_new_entry */