Protect ubik cache accesses
[openafs.git] / src / ubik / ubik.p.h
index 90e256f..3fe8b15 100644 (file)
 
 #endif
 
-#if defined(UKERNEL)
-#include "ubik_int.h"
-#else /* defined(UKERNEL) */
 #include <ubik_int.h>
-#endif /* defined(UKERNEL) */
 
 /*! \name ubik_trans types */
 #define        UBIK_READTRANS      0
@@ -57,6 +53,7 @@
 
 /*! \name ubik client flags */
 #define UPUBIKONLY         1   /*!< only check servers presumed functional */
+#define UBIK_CALL_NEW      2   /*!< use the semantics of ubik_Call_New */
 /*\}*/
 
 /*! \name RX services types */
@@ -167,7 +164,9 @@ struct ubik_dbase {
     char *pathName;            /*!< root name for dbase */
     struct ubik_trans *activeTrans;    /*!< active transaction list */
     struct ubik_version version;       /*!< version number */
-#if defined(UKERNEL)
+#ifdef AFS_PTHREAD_ENV
+    pthread_mutex_t versionLock;       /*!< lock on version number */
+#elif defined(UKERNEL)
     struct afs_lock versionLock;       /*!< lock on version number */
 #else                          /* defined(UKERNEL) */
     struct Lock versionLock;   /*!< lock on version number */
@@ -191,14 +190,28 @@ struct ubik_dbase {
     int (*getnfiles) (struct ubik_dbase * adbase);     /*!< find out number of files */
     short readers;             /*!< number of current read transactions */
     struct ubik_version cachedVersion; /*!< version of caller's cached data */
+#ifdef UKERNEL
+    struct afs_lock cache_lock;
+#else
+    struct Lock cache_lock; /*!< protects cached application data */
+#endif
 #ifdef AFS_PTHREAD_ENV
     pthread_cond_t version_cond;    /*!< condition variable to manage changes to version */
     pthread_cond_t flags_cond;      /*!< condition variable to manage changes to flags */
-    pthread_mutex_t version_mutex;
-    pthread_mutex_t flags_mutex;
 #endif
 };
 
+/**
+ * ubik_CheckCache callback function.
+ *
+ * @param[in] atrans  ubik transaction
+ * @param[in] rock    rock passed to ubik_CheckCache
+ *
+ * @return operation status
+ *   @retval 0        cache was read properly
+ */
+typedef int (*ubik_updatecache_func) (struct ubik_trans *atrans, void *rock);
+
 /*! \name procedures for automatically authenticating ubik connections */
 extern int (*ubik_CRXSecurityProc) (void *, struct rx_securityClass **,
                                    afs_int32 *);
@@ -235,6 +248,9 @@ extern void *ubik_CheckRXSecurityRock;
 #define TRSETLOCK           8  /*!< SetLock is using trans */
 #define TRSTALE             16 /*!< udisk_end during getLock */
 #endif /* UBIK_PAUSE */
+#define TRCACHELOCKED       32  /*!< this trans has locked dbase->cache_lock
+                                 *   (meaning, this trans has called
+                                 *   ubik_CheckCache at some point */
 /*\}*/
 
 /*! \name ubik_lock flags */
@@ -290,8 +306,13 @@ struct ubik_server {
 };
 
 /*! \name hold and release functions on a database */
-#define        DBHOLD(a)       ObtainWriteLock(&((a)->versionLock))
-#define        DBRELE(a)       ReleaseWriteLock(&((a)->versionLock))
+#ifdef AFS_PTHREAD_ENV
+# define       DBHOLD(a)       assert(pthread_mutex_lock(&((a)->versionLock)) == 0)
+# define       DBRELE(a)       assert(pthread_mutex_unlock(&((a)->versionLock)) == 0)
+#else /* !AFS_PTHREAD_ENV */
+# define       DBHOLD(a)       ObtainWriteLock(&((a)->versionLock))
+# define       DBRELE(a)       ReleaseWriteLock(&((a)->versionLock))
+#endif /* !AFS_PTHREAD_ENV */
 /*\}*/
 
 /* globals */
@@ -394,7 +415,8 @@ extern afs_int32 ContactQuorum_DISK_SetVersion(struct ubik_trans *atrans,
                                               ubik_version *OldVersion,
                                               ubik_version *NewVersion);
                                               
-extern void panic(char *format, ...); 
+extern void panic(char *format, ...)
+    AFS_ATTRIBUTE_FORMAT(__printf__, 1, 2);
 
 extern afs_uint32 ubikGetPrimaryInterfaceAddr(afs_uint32 addr); 
 /*\}*/
@@ -436,10 +458,17 @@ extern void ulock_Debug(struct ubik_debug *aparm);
 extern int uvote_ShouldIRun(void);
 extern afs_int32 uvote_GetSyncSite(void);
 extern int uvote_Init(void);
-extern void ubik_vprint(const char *format, va_list ap);
-extern void ubik_print(const char *format, ...);
-extern void ubik_dprint(const char *format, ...);
-extern void ubik_dprint_25(const char *format, ...);
+extern void ubik_vprint(const char *format, va_list ap)
+    AFS_ATTRIBUTE_FORMAT(__printf__, 1, 0);
+
+extern void ubik_print(const char *format, ...)
+    AFS_ATTRIBUTE_FORMAT(__printf__, 1, 2);
+
+extern void ubik_dprint(const char *format, ...)
+    AFS_ATTRIBUTE_FORMAT(__printf__, 1, 2);
+
+extern void ubik_dprint_25(const char *format, ...)
+    AFS_ATTRIBUTE_FORMAT(__printf__, 1, 2);
 /*\}*/
 
 #endif /* UBIK_INTERNALS */
@@ -454,10 +483,11 @@ extern afs_int32 ubik_nBuffers;
 struct afsconf_cell;
 extern int ubik_ServerInitByInfo(afs_int32 myHost, short myPort,
                                 struct afsconf_cell *info, char clones[],
-                                char *pathName, struct ubik_dbase **dbase);
+                                const char *pathName,
+                                struct ubik_dbase **dbase);
 extern int ubik_ServerInit(afs_int32 myHost, short myPort, 
                           afs_int32 serverList[],
-                          char *pathName, struct ubik_dbase **dbase);
+                          const char *pathName, struct ubik_dbase **dbase);
 extern int ubik_BeginTrans(register struct ubik_dbase *dbase,
                           afs_int32 transMode, struct ubik_trans **transPtr);
 extern int ubik_BeginTransReadAny(register struct ubik_dbase *dbase,
@@ -483,7 +513,9 @@ extern int ubik_WaitVersion(register struct ubik_dbase *adatabase,
                            register struct ubik_version *aversion);
 extern int ubik_GetVersion(register struct ubik_trans *atrans,
                           register struct ubik_version *avers);
-extern int ubik_CacheUpdate(register struct ubik_trans *atrans);
+extern int ubik_CheckCache(struct ubik_trans *atrans,
+                           ubik_updatecache_func check,
+                           void *rock);
 /*\}*/
 
 /*! \name ubikclient.c */
@@ -500,8 +532,12 @@ extern afs_int32 ubik_CallIter(int (*aproc) (), struct ubik_client *aclient,
                               long p3, long p4, long p5, long p6, long p7,
                               long p8, long p9, long p10, long p11, long p12,
                               long p13, long p14, long p15, long p16);
+extern afs_int32 ubik_Call_New(int (*aproc) (), register struct ubik_client
+                              *aclient, afs_int32 aflags, long p1, long p2,
+                              long p3, long p4, long p5, long p6, long p7,
+                              long p8, long p9, long p10, long p11, long p12,
+                              long p13, long p14, long p15, long p16);
 #endif
-
 /*\}*/
 
 /* \name ubikcmd.c */
@@ -512,8 +548,8 @@ extern int ubik_ParseServerList(int argc, char **argv, afs_int32 *ahost,
 /* \name uinit.c */
 
 struct rx_securityClass;
-extern afs_int32 ugen_ClientInit(int noAuthFlag, char *confDir, char *cellName,
-                                afs_int32 sauth, 
+extern afs_int32 ugen_ClientInit(int noAuthFlag, const char *confDir,
+                                char *cellName, afs_int32 sauth,
                                 struct ubik_client **uclientp,
                                 int (*secproc) (struct rx_securityClass *sc,
                                                 afs_int32 scIndex),