aboutsummaryrefslogtreecommitdiff
path: root/src/fs
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2010-07-09 12:20:38 +0000
committerChristian Grothoff <christian@grothoff.org>2010-07-09 12:20:38 +0000
commit0469252aa72449600e92cea94c16f9fb44eab059 (patch)
tree05c5cca9124052fbebc1ea4683ea558afd0d148d /src/fs
parent1a452b2adb7c2dd78bd758e0cc1bad6c62875b2f (diff)
downloadgnunet-0469252aa72449600e92cea94c16f9fb44eab059.tar.gz
gnunet-0469252aa72449600e92cea94c16f9fb44eab059.zip
perform reservation
Diffstat (limited to 'src/fs')
-rw-r--r--src/fs/fs.h16
-rw-r--r--src/fs/fs_publish.c150
2 files changed, 151 insertions, 15 deletions
diff --git a/src/fs/fs.h b/src/fs/fs.h
index 5e55220fd..3a0b54d6f 100644
--- a/src/fs/fs.h
+++ b/src/fs/fs.h
@@ -1307,12 +1307,28 @@ struct GNUNET_FS_PublishContext
1307 struct GNUNET_DATASTORE_Handle *dsh; 1307 struct GNUNET_DATASTORE_Handle *dsh;
1308 1308
1309 /** 1309 /**
1310 * Queue entry for reservation/unreservation.
1311 */
1312 struct GNUNET_DATASTORE_QueueEntry *qre;
1313
1314 /**
1310 * ID of the task performing the upload. NO_TASK if the upload has 1315 * ID of the task performing the upload. NO_TASK if the upload has
1311 * completed. 1316 * completed.
1312 */ 1317 */
1313 GNUNET_SCHEDULER_TaskIdentifier upload_task; 1318 GNUNET_SCHEDULER_TaskIdentifier upload_task;
1314 1319
1315 /** 1320 /**
1321 * Storage space to reserve for the operation.
1322 */
1323 uint64_t reserve_space;
1324
1325 /**
1326 * Overall number of entries to reserve for the
1327 * publish operation.
1328 */
1329 uint32_t reserve_entries;
1330
1331 /**
1316 * Typically GNUNET_NO. Set to GNUNET_YES if "upload_task" is 1332 * Typically GNUNET_NO. Set to GNUNET_YES if "upload_task" is
1317 * GNUNET_SCHEDULER_NO_TASK and we're waiting for a response from 1333 * GNUNET_SCHEDULER_NO_TASK and we're waiting for a response from
1318 * the datastore service (in which case this struct must not be 1334 * the datastore service (in which case this struct must not be
diff --git a/src/fs/fs_publish.c b/src/fs/fs_publish.c
index 050047e41..e44514ea4 100644
--- a/src/fs/fs_publish.c
+++ b/src/fs/fs_publish.c
@@ -166,7 +166,7 @@ ds_put_cont (void *cls,
166 if (GNUNET_OK != success) 166 if (GNUNET_OK != success)
167 { 167 {
168 GNUNET_asprintf (&pcc->p->emsg, 168 GNUNET_asprintf (&pcc->p->emsg,
169 _("Upload failed: %s"), 169 _("Publishing failed: %s"),
170 msg); 170 msg);
171 pi.status = GNUNET_FS_STATUS_PUBLISH_ERROR; 171 pi.status = GNUNET_FS_STATUS_PUBLISH_ERROR;
172 pi.value.publish.eta = GNUNET_TIME_UNIT_FOREVER_REL; 172 pi.value.publish.eta = GNUNET_TIME_UNIT_FOREVER_REL;
@@ -230,6 +230,27 @@ signal_publish_error (struct GNUNET_FS_FileInformation *p,
230 230
231 231
232/** 232/**
233 * Datastore returns from reservation cancel request.
234 *
235 * @param cls the 'struct GNUNET_FS_PublishContext'
236 * @param success success code (not used)
237 * @param msg error message (typically NULL, not used)
238 */
239static void
240finish_release_reserve (void *cls,
241 int success,
242 const char *msg)
243{
244 struct GNUNET_FS_PublishContext *pc = cls;
245
246 pc->qre = NULL;
247 signal_publish_completion (pc->fi, pc);
248 pc->all_done = GNUNET_YES;
249 GNUNET_FS_publish_sync_ (pc);
250}
251
252
253/**
233 * We've finished publishing the SBlock as part of a larger upload. 254 * We've finished publishing the SBlock as part of a larger upload.
234 * Check the result and complete the larger upload. 255 * Check the result and complete the larger upload.
235 * 256 *
@@ -251,10 +272,22 @@ publish_sblocks_cont (void *cls,
251 GNUNET_FS_publish_sync_ (pc); 272 GNUNET_FS_publish_sync_ (pc);
252 return; 273 return;
253 } 274 }
254 // FIXME: release the datastore reserve here! 275 GNUNET_assert (pc->qre == NULL);
255 signal_publish_completion (pc->fi, pc); 276 if ( (pc->dsh != NULL) &&
256 pc->all_done = GNUNET_YES; 277 (pc->rid != 0) )
257 GNUNET_FS_publish_sync_ (pc); 278 {
279 pc->qre = GNUNET_DATASTORE_release_reserve (pc->dsh,
280 pc->rid,
281 UINT_MAX,
282 UNIT_MAX,
283 GNUNET_TIME_UNIT_FOREVER_REL,
284 &finish_release_reserve,
285 pc);
286 }
287 else
288 {
289 finish_release_reserve (pc, GNUNET_OK, NULL);
290 }
258} 291}
259 292
260 293
@@ -423,7 +456,7 @@ encode_cont (void *cls,
423 emsg); 456 emsg);
424#endif 457#endif
425 GNUNET_asprintf (&p->emsg, 458 GNUNET_asprintf (&p->emsg,
426 _("Upload failed: %s"), 459 _("Publishing failed: %s"),
427 emsg); 460 emsg);
428 GNUNET_free (emsg); 461 GNUNET_free (emsg);
429 pi.status = GNUNET_FS_STATUS_PUBLISH_ERROR; 462 pi.status = GNUNET_FS_STATUS_PUBLISH_ERROR;
@@ -858,7 +891,7 @@ GNUNET_FS_publish_main_ (void *cls,
858 { 891 {
859#if DEBUG_PUBLISH 892#if DEBUG_PUBLISH
860 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, 893 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
861 "Upload complete, now publishing SKS and KSK blocks.\n"); 894 "Publishing complete, now publishing SKS and KSK blocks.\n");
862#endif 895#endif
863 /* upload of entire hierarchy complete, 896 /* upload of entire hierarchy complete,
864 publish namespace entries */ 897 publish namespace entries */
@@ -1009,7 +1042,37 @@ fip_signal_start(void *cls,
1009{ 1042{
1010 struct GNUNET_FS_PublishContext *sc = cls; 1043 struct GNUNET_FS_PublishContext *sc = cls;
1011 struct GNUNET_FS_ProgressInfo pi; 1044 struct GNUNET_FS_ProgressInfo pi;
1045 unsigned int kc;
1046 uint64_t left;
1012 1047
1048 if (*do_index)
1049 {
1050 /* space for on-demand blocks */
1051 sc->reserve_space += ((length + DBLOCK_SIZE - 1) / DBLOCK_SIZE) * sizeof (struct OnDemandBlock);
1052 }
1053 else
1054 {
1055 /* space for DBlocks */
1056 sc->reserve_space += length;
1057 }
1058 /* entries for IBlocks and DBlocks, space for IBlocks */
1059 left = length;
1060 while (1)
1061 {
1062 left = (left + DBLOCK_SIZE - 1) / DBLOCK_SIZE;
1063 sc->reserve_entries += left;
1064 if (left == 1)
1065 break;
1066 left = left * sizeof (struct ContentHashKey);
1067 sc->reserve_space += left;
1068 }
1069 /* entries and space for keywords */
1070 if (NULL != *uri)
1071 {
1072 kc = GNUNET_FS_uri_ksk_get_keyword_count (*uri);
1073 sc->reserve_entries += kc;
1074 sc->reserve_space += GNUNET_SERVER_MAX_MESSAGE_SIZE * kc;
1075 }
1013 pi.status = GNUNET_FS_STATUS_PUBLISH_START; 1076 pi.status = GNUNET_FS_STATUS_PUBLISH_START;
1014 *client_info = GNUNET_FS_publish_make_status_ (&pi, sc, fi, 0); 1077 *client_info = GNUNET_FS_publish_make_status_ (&pi, sc, fi, 0);
1015 GNUNET_FS_file_information_sync_ (fi); 1078 GNUNET_FS_file_information_sync_ (fi);
@@ -1089,6 +1152,43 @@ GNUNET_FS_publish_signal_suspend_ (void *cls)
1089 1152
1090 1153
1091/** 1154/**
1155 * We have gotten a reply for our space reservation request.
1156 * Either fail (insufficient space) or start publishing for good.
1157 *
1158 * @param cls the 'struct GNUNET_FS_PublishContext*'
1159 * @param success positive reservation ID on success
1160 * @param msg error message on error, otherwise NULL
1161 */
1162static void
1163finish_reserve (void *cls,
1164 int success,
1165 const char *msg)
1166{
1167 struct GNUNET_FS_PublishContext *pc = cls;
1168 struct GNUNET_FS_ProgressInfo pi;
1169
1170 pc->qre = NULL;
1171 if ( (msg != NULL) ||
1172 (success <= 0) )
1173 {
1174 GNUNET_asprintf (&pc->fi->emsg,
1175 _("Insufficient space for publishing: %s"),
1176 msg);
1177 signal_publish_error (pc->fi,
1178 pc,
1179 pc->fi->emsg);
1180 return;
1181 }
1182 pc->rid = success;
1183 ret->upload_task
1184 = GNUNET_SCHEDULER_add_with_priority (h->sched,
1185 GNUNET_SCHEDULER_PRIORITY_BACKGROUND,
1186 &GNUNET_FS_publish_main_,
1187 ret);
1188}
1189
1190
1191/**
1092 * Publish a file or directory. 1192 * Publish a file or directory.
1093 * 1193 *
1094 * @param h handle to the file sharing subsystem 1194 * @param h handle to the file sharing subsystem
@@ -1143,14 +1243,29 @@ GNUNET_FS_publish_start (struct GNUNET_FS_Handle *h,
1143 ret->fi_pos = ret->fi; 1243 ret->fi_pos = ret->fi;
1144 ret->top = GNUNET_FS_make_top (h, &GNUNET_FS_publish_signal_suspend_, ret); 1244 ret->top = GNUNET_FS_make_top (h, &GNUNET_FS_publish_signal_suspend_, ret);
1145 GNUNET_FS_publish_sync_ (ret); 1245 GNUNET_FS_publish_sync_ (ret);
1146 // FIXME: calculate space needed for "fi" 1246 if (NULL != ret->dsh)
1147 // and reserve as first task (then trigger 1247 {
1148 // "publish_main" from that continuation)! 1248 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1149 ret->upload_task 1249 _("Reserving space for %u entries and %llu bytes for publication\n"),
1150 = GNUNET_SCHEDULER_add_with_priority (h->sched, 1250 (unsigned int) ret->reserve_entries,
1151 GNUNET_SCHEDULER_PRIORITY_BACKGROUND, 1251 (unsigned long long) ret->reserve_space);
1152 &GNUNET_FS_publish_main_, 1252 ret->qre = GNUNET_DATASTORE_reserve (ret->dsh,
1153 ret); 1253 ret->reserve_space,
1254 ret->reserve_entries,
1255 UINT_MAX,
1256 UINT_MAX,
1257 GNUNET_TIME_UNIT_FOREVER_REL,
1258 &finish_reserve,
1259 ret);
1260 }
1261 else
1262 {
1263 ret->upload_task
1264 = GNUNET_SCHEDULER_add_with_priority (h->sched,
1265 GNUNET_SCHEDULER_PRIORITY_BACKGROUND,
1266 &GNUNET_FS_publish_main_,
1267 ret);
1268 }
1154 return ret; 1269 return ret;
1155} 1270}
1156 1271
@@ -1215,6 +1330,11 @@ void
1215GNUNET_FS_publish_stop (struct GNUNET_FS_PublishContext *pc) 1330GNUNET_FS_publish_stop (struct GNUNET_FS_PublishContext *pc)
1216{ 1331{
1217 GNUNET_FS_end_top (pc->h, pc->top); 1332 GNUNET_FS_end_top (pc->h, pc->top);
1333 if (NULL != pc->qre)
1334 {
1335 GNUNET_DATASTORE_cancel (pc->qre);
1336 pc->qre = NULL;
1337 }
1218 if (NULL != pc->dsh) 1338 if (NULL != pc->dsh)
1219 { 1339 {
1220 GNUNET_DATASTORE_disconnect (pc->dsh, GNUNET_NO); 1340 GNUNET_DATASTORE_disconnect (pc->dsh, GNUNET_NO);