Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 21 Nov 2006 16:19:03 GMT
From:      Michael Bushkov <bushman@FreeBSD.org>
To:        Perforce Change Reviews <perforce@freebsd.org>
Subject:   PERFORCE change 110291 for review
Message-ID:  <200611211619.kALGJ3c8045878@repoman.freebsd.org>

next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=110291

Change 110291 by bushman@bushman_nss_ldap_cached on 2006/11/20 11:09:09

	+ Now, before writing something to cache, we check for such element existence.
	  With this check we now avoid some race-condition situations, when 2 program
	  write similar data to the same cache entry.

Affected files ...

.. //depot/projects/soc2006/nss_ldap_cached/src/usr.sbin/cached/query.c#10 edit

Differences ...

==== //depot/projects/soc2006/nss_ldap_cached/src/usr.sbin/cached/query.c#10 (text) ====

@@ -339,6 +339,7 @@
 	struct cache_write_request	*write_request;
 	struct cache_write_response	*write_response;
 	cache_entry c_entry;
+	size_t tdata_size;
 
 	TRACE_IN(on_write_request_process);
 	init_comm_element(&qstate->response, CET_WRITE_RESPONSE);
@@ -386,19 +387,35 @@
 	if (c_entry != NULL) {
 		configuration_lock_entry(qstate->config_entry, CELT_POSITIVE);
 		qstate->config_entry->positive_cache_entry = c_entry;
-		write_response->error_code = cache_write(c_entry,
+		
+		/* checking if there is already a record in the cache */
+		write_response->error_code = cache_read(c_entry,
 			write_request->cache_key,
-	    		write_request->cache_key_size,
-	    		write_request->data,
-			write_request->data_size);
-		configuration_unlock_entry(qstate->config_entry, CELT_POSITIVE);
+			write_request->cache_key_size, NULL,
+			&tdata_size);
+		
+		if (write_response->error_code == -1) {
+		    write_response->error_code = cache_write(c_entry,
+			write_request->cache_key, write_request->cache_key_size,
+	    		write_request->data, write_request->data_size);
 
-		if ((qstate->config_entry->common_query_timeout.tv_sec != 0) ||
-		    (qstate->config_entry->common_query_timeout.tv_usec != 0))
+		    if ((qstate->config_entry->common_query_timeout.tv_sec 
+			!= 0) ||
+			(qstate->config_entry->common_query_timeout.tv_usec
+		        != 0))
 			memcpy(&qstate->timeout,
-				&qstate->config_entry->common_query_timeout,
-				sizeof(struct timeval));
-
+			    &qstate->config_entry->common_query_timeout,
+			    sizeof(struct timeval));
+		} else {
+			LOG_ERR_2("write_request",
+				"trying to write to entry '%s', despite that "
+				"there is already an element with specified "
+				"key in the cache", write_request->entry);
+			
+			write_response->error_code = -1;
+		}
+		
+		configuration_unlock_entry(qstate->config_entry, CELT_POSITIVE);
 	} else
 		write_response->error_code = -1;
 
@@ -417,6 +434,7 @@
 	struct cache_write_request	*write_request;
 	struct cache_write_response	*write_response;
 	cache_entry c_entry;
+	size_t tdata_size;
 
 	TRACE_IN(on_negative_write_request_process);
 	init_comm_element(&qstate->response, CET_WRITE_RESPONSE);
@@ -468,20 +486,37 @@
 	if (c_entry != NULL) {
 		configuration_lock_entry(qstate->config_entry, CELT_NEGATIVE);
 		qstate->config_entry->negative_cache_entry = c_entry;
-		write_response->error_code = cache_write(c_entry,
+
+		write_response->error_code = cache_read(c_entry,
 			write_request->cache_key,
-	    		write_request->cache_key_size,
-	    		negative_data,
-			sizeof(negative_data));
+			write_request->cache_key_size,
+			NULL,
+			&tdata_size);
+		if (write_response->error_code == -1) {
+		    write_response->error_code = cache_write(c_entry,
+			write_request->cache_key, write_request->cache_key_size,
+	    		negative_data, sizeof(negative_data));
+
+			if ((qstate->config_entry->common_query_timeout.tv_sec
+			    != 0) ||
+			    (qstate->config_entry->common_query_timeout.tv_usec
+			    != 0))
+				memcpy(&qstate->timeout,
+				    &qstate->config_entry->common_query_timeout,
+				    sizeof(struct timeval));
+		} else
+			write_response->error_code = -1;
+		
 		configuration_unlock_entry(qstate->config_entry, CELT_NEGATIVE);
-
-		if ((qstate->config_entry->common_query_timeout.tv_sec != 0) ||
-		    (qstate->config_entry->common_query_timeout.tv_usec != 0))
-			memcpy(&qstate->timeout,
-				&qstate->config_entry->common_query_timeout,
-				sizeof(struct timeval));
-	} else
+	} else {
+		LOG_ERR_2("write_request",
+			"trying to write negative request to entry "
+			"'%s', despite that "
+			"there is already an element with specified "
+			"key in the cache", write_request->entry);
+		
 		write_response->error_code = -1;
+	}
 
 fin:
 	qstate->kevent_filter = EVFILT_WRITE;
@@ -697,9 +732,11 @@
 		}
 		configuration_unlock_entry(qstate->config_entry, CELT_POSITIVE);
 
-		configuration_lock_entry(qstate->config_entry, CELT_NEGATIVE);
-		qstate->config_entry->negative_cache_entry = neg_c_entry;
 		if (read_response->error_code == -1) {
+			configuration_lock_entry(qstate->config_entry,
+				CELT_NEGATIVE);
+			qstate->config_entry->negative_cache_entry =
+				neg_c_entry;
 			read_response->error_code = cache_read(neg_c_entry,
 				read_request->cache_key,
 				read_request->cache_key_size, NULL,
@@ -710,8 +747,9 @@
 				read_response->data = NULL;
 				read_response->data_size = 0;
 			}
-		}
-		configuration_unlock_entry(qstate->config_entry, CELT_NEGATIVE);
+			configuration_unlock_entry(qstate->config_entry, 
+				CELT_NEGATIVE);
+		}		
 
 		if ((read_response->error_code == -1) &&
 		    (qstate->config_entry->flags &



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200611211619.kALGJ3c8045878>