L4Re/departure

Annotated tests/dstest_file_client.cc

360:92c5f6aa8c36
2022-06-12 Paul Boddie Reintroduced PagerObject code generation required to initiate servers. mmap-region-flags
paul@141 1
/*
paul@141 2
 * Test file operations.
paul@141 3
 *
paul@237 4
 * Copyright (C) 2020, 2021, 2022 Paul Boddie <paul@boddie.org.uk>
paul@141 5
 *
paul@141 6
 * This program is free software; you can redistribute it and/or
paul@141 7
 * modify it under the terms of the GNU General Public License as
paul@141 8
 * published by the Free Software Foundation; either version 2 of
paul@141 9
 * the License, or (at your option) any later version.
paul@141 10
 *
paul@141 11
 * This program is distributed in the hope that it will be useful,
paul@141 12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
paul@141 13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
paul@141 14
 * GNU General Public License for more details.
paul@141 15
 *
paul@141 16
 * You should have received a copy of the GNU General Public License
paul@141 17
 * along with this program; if not, write to the Free Software
paul@141 18
 * Foundation, Inc., 51 Franklin Street, Fifth Floor,
paul@141 19
 * Boston, MA  02110-1301, USA
paul@141 20
 */
paul@141 21
paul@141 22
#include <l4/re/env.h>
paul@141 23
#include <l4/sys/err.h>
paul@141 24
paul@141 25
#include <thread>
paul@141 26
paul@141 27
#include <stdio.h>
paul@141 28
#include <string.h>
paul@141 29
#include <stdlib.h>
paul@141 30
paul@141 31
#include <fsclient/client.h>
paul@141 32
#include <systypes/fcntl.h>
paul@141 33
paul@141 34
paul@141 35
paul@141 36
/* Write data to the file. */
paul@141 37
paul@141 38
static void write_data(file_t *file, int region)
paul@141 39
{
paul@141 40
  offset_t size = 600;
paul@141 41
  char buffer[size];
paul@141 42
paul@141 43
  memset(buffer, (int) 'a' + region, size);
paul@141 44
paul@141 45
  offset_t nwritten = client_write(file, buffer, size);
paul@141 46
paul@141 47
  printf("Written %ld/%ld in #%d to file with first %c, last %c...\n", nwritten, size, region, *buffer, *(buffer + nwritten - 1));
paul@141 48
paul@141 49
  /* Flush to make the output available. */
paul@141 50
paul@141 51
  client_flush(file);
paul@141 52
}
paul@141 53
paul@141 54
/* Read and write data to the file. */
paul@141 55
paul@141 56
static void read_and_write(file_t *file, bool creator)
paul@141 57
{
paul@141 58
  offset_t size = 600, total = 0;
paul@141 59
  long err;
paul@141 60
  int region = 0;
paul@141 61
paul@141 62
  /* Register for notifications. */
paul@141 63
paul@180 64
  if ((err = client_subscribe(file, NOTIFY_CONTENT_AVAILABLE | NOTIFY_PEER_CLOSED, client_notifier_task())))
paul@141 65
  {
paul@141 66
    printf("Could not subscribe to notifications: %s\n", l4sys_errtostr(err));
paul@141 67
    return;
paul@141 68
  }
paul@141 69
paul@141 70
  /* Seek to the end of the file, if this is not actually a new file. */
paul@141 71
paul@141 72
  client_seek(file, 0, SEEK_END);
paul@141 73
paul@141 74
  printf("File %s at position %ld...\n", creator ? "creator" : "follower", client_tell(file));
paul@141 75
paul@141 76
  /* Write initial data as the file's creator. */
paul@141 77
paul@141 78
  if (creator)
paul@141 79
    write_data(file, region++);
paul@141 80
paul@141 81
  while (region < 26)
paul@141 82
  {
paul@141 83
    char buffer[size];
paul@141 84
    offset_t nread;
paul@141 85
paul@141 86
    /* Wait for notification of content. */
paul@141 87
paul@180 88
    err = client_wait_file(file, client_notifier_task());
paul@141 89
paul@141 90
    if (err)
paul@141 91
    {
paul@141 92
      printf("Error waiting for notifications: %s\n", l4sys_errtostr(err));
paul@141 93
      return;
paul@141 94
    }
paul@141 95
paul@141 96
    printf("File %s notified with conditions:%s%s\n", creator ? "creator" : "follower",
paul@141 97
                                                      file->notifications & NOTIFY_PEER_CLOSED ? " closed" : "",
paul@141 98
                                                      file->notifications & NOTIFY_CONTENT_AVAILABLE ? " content" : "");
paul@141 99
paul@141 100
    /* Attempt to read. */
paul@141 101
paul@141 102
    nread = client_read(file, buffer, size);
paul@141 103
paul@141 104
    while (nread)
paul@141 105
    {
paul@141 106
      total += nread;
paul@141 107
paul@141 108
      printf("Read as %s %ld/%ld, total %ld, first %c, last %c, from file...\n", creator ? "creator" : "follower",
paul@141 109
             nread, size, total, *buffer, *(buffer + nread - 1));
paul@141 110
paul@141 111
      if (!(*(buffer + nread - 1)))
paul@141 112
        printf("Warning: length before zero region is %ld\n", strlen(buffer));
paul@141 113
paul@141 114
#if 0
paul@141 115
      for (offset_t i = 0; i < nread; i += 60)
paul@141 116
      {
paul@141 117
        fwrite(buffer + i, sizeof(char), nread - i > 60 ? 60 : nread - i, stdout);
paul@141 118
        fputs("\n", stdout);
paul@141 119
      }
paul@141 120
#endif
paul@141 121
      nread = client_read(file, buffer, size);
paul@141 122
    }
paul@141 123
paul@141 124
    /* Without any more content, a peer closed event should terminate reading
paul@141 125
       from the pipe. */
paul@141 126
paul@141 127
    if (file->notifications & NOTIFY_PEER_CLOSED)
paul@141 128
      break;
paul@141 129
paul@141 130
    write_data(file, region++);
paul@141 131
  }
paul@141 132
paul@141 133
  printf("Data shown.\n");
paul@141 134
}
paul@141 135
paul@141 136
int main(int argc, char *argv[])
paul@141 137
{
paul@141 138
  if (argc < 2)
paul@141 139
  {
paul@237 140
    printf("Need a filename.\n");
paul@141 141
    return 1;
paul@141 142
  }
paul@141 143
paul@141 144
  char *filename = argv[1];
paul@147 145
  file_t *file1, *file2;
paul@141 146
paul@237 147
  file1 = client_open(filename, O_RDWR | O_CREAT);
paul@237 148
  file2 = client_open(filename, O_RDWR);
paul@141 149
paul@141 150
  if ((file1 == NULL) || (file2 == NULL))
paul@141 151
  {
paul@141 152
    printf("Could not obtain files.\n");
paul@141 153
    return 1;
paul@141 154
  }
paul@141 155
paul@141 156
  /* Schedule threads. */
paul@141 157
paul@141 158
  std::thread *activities[2];
paul@141 159
paul@141 160
  activities[0] = new std::thread(read_and_write, file1, true);
paul@141 161
  activities[1] = new std::thread(read_and_write, file2, false);
paul@141 162
paul@141 163
  for (int i = 0; i < 2; i++)
paul@141 164
    activities[i]->join();
paul@141 165
}
paul@141 166
paul@141 167
// vim: tabstop=2 expandtab shiftwidth=2